summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1995-12-02 17:30:23 +0000
committerPeter Wemm <peter@FreeBSD.org>1995-12-02 17:30:23 +0000
commit58162a7314f7e4552e9585026529da1640363549 (patch)
tree8d6be8896a925b2043a5656b818313e358ae04d7
Notes
-rw-r--r--usr.sbin/sendmail/FAQ731
-rw-r--r--usr.sbin/sendmail/KNOWNBUGS119
-rw-r--r--usr.sbin/sendmail/Makefile45
-rw-r--r--usr.sbin/sendmail/READ_ME288
-rw-r--r--usr.sbin/sendmail/RELEASE_NOTES4003
-rw-r--r--usr.sbin/sendmail/cf/README1740
-rw-r--r--usr.sbin/sendmail/cf/cf/Makefile111
-rw-r--r--usr.sbin/sendmail/cf/cf/chez.cs.mc54
-rw-r--r--usr.sbin/sendmail/cf/cf/clientproto.mc54
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-hpux10.mc51
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-hpux9.mc51
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-osf1.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-solaris2.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/cs-ultrix4.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/cyrusproto.mc40
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc48
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-hpux10.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-hpux9.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-osf1.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-solaris2.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/generic-ultrix4.mc47
-rw-r--r--usr.sbin/sendmail/cf/cf/huginn.cs.mc63
-rw-r--r--usr.sbin/sendmail/cf/cf/mail.cs.mc64
-rw-r--r--usr.sbin/sendmail/cf/cf/mail.eecs.mc64
-rw-r--r--usr.sbin/sendmail/cf/cf/mailspool.cs.mc57
-rw-r--r--usr.sbin/sendmail/cf/cf/python.cs.mc62
-rw-r--r--usr.sbin/sendmail/cf/cf/s2k-osf1.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/tcpproto.mc53
-rw-r--r--usr.sbin/sendmail/cf/cf/ucbarpa.mc50
-rw-r--r--usr.sbin/sendmail/cf/cf/ucbvax.mc111
-rw-r--r--usr.sbin/sendmail/cf/cf/uucpproto.mc53
-rw-r--r--usr.sbin/sendmail/cf/cf/vangogh.cs.mc53
-rw-r--r--usr.sbin/sendmail/cf/domain/Berkeley.EDU.m445
-rw-r--r--usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m440
-rw-r--r--usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m438
-rw-r--r--usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m438
-rw-r--r--usr.sbin/sendmail/cf/domain/berkeley-only.m440
-rw-r--r--usr.sbin/sendmail/cf/domain/generic.m448
-rw-r--r--usr.sbin/sendmail/cf/feature/bestmx_is_local.m458
-rw-r--r--usr.sbin/sendmail/cf/feature/local_procmail.m444
-rw-r--r--usr.sbin/sendmail/cf/feature/masquerade_envelope.m440
-rw-r--r--usr.sbin/sendmail/cf/feature/notsticky.m442
-rw-r--r--usr.sbin/sendmail/cf/feature/nullclient.m471
-rw-r--r--usr.sbin/sendmail/cf/feature/redirect.m450
-rw-r--r--usr.sbin/sendmail/cf/feature/smrsh.m442
-rw-r--r--usr.sbin/sendmail/cf/feature/stickyhost.m440
-rw-r--r--usr.sbin/sendmail/cf/feature/use_ct_file.m446
-rw-r--r--usr.sbin/sendmail/cf/m4/cf.m450
-rw-r--r--usr.sbin/sendmail/cf/m4/cfhead.m4147
-rw-r--r--usr.sbin/sendmail/cf/m4/nullrelay.m4129
-rw-r--r--usr.sbin/sendmail/cf/m4/proto.m4818
-rw-r--r--usr.sbin/sendmail/cf/m4/version.m439
-rw-r--r--usr.sbin/sendmail/cf/mailer/cyrus.m444
-rw-r--r--usr.sbin/sendmail/cf/mailer/fax.m453
-rw-r--r--usr.sbin/sendmail/cf/mailer/local.m494
-rw-r--r--usr.sbin/sendmail/cf/mailer/mail11.m450
-rw-r--r--usr.sbin/sendmail/cf/mailer/phquery.m451
-rw-r--r--usr.sbin/sendmail/cf/mailer/pop.m453
-rw-r--r--usr.sbin/sendmail/cf/mailer/procmail.m452
-rw-r--r--usr.sbin/sendmail/cf/mailer/smtp.m4135
-rw-r--r--usr.sbin/sendmail/cf/mailer/usenet.m448
-rw-r--r--usr.sbin/sendmail/cf/mailer/uucp.m4174
-rw-r--r--usr.sbin/sendmail/cf/ostype/aix3.m441
-rw-r--r--usr.sbin/sendmail/cf/ostype/amdahl-uts.m444
-rw-r--r--usr.sbin/sendmail/cf/ostype/aux.m443
-rw-r--r--usr.sbin/sendmail/cf/ostype/bsd4.3.m439
-rw-r--r--usr.sbin/sendmail/cf/ostype/bsd4.4.m442
-rw-r--r--usr.sbin/sendmail/cf/ostype/bsdi1.0.m438
-rw-r--r--usr.sbin/sendmail/cf/ostype/bsdi2.0.m438
-rw-r--r--usr.sbin/sendmail/cf/ostype/dgux.m439
-rw-r--r--usr.sbin/sendmail/cf/ostype/domainos.m442
-rw-r--r--usr.sbin/sendmail/cf/ostype/dynix3.2.m439
-rw-r--r--usr.sbin/sendmail/cf/ostype/hpux10.m451
-rw-r--r--usr.sbin/sendmail/cf/ostype/hpux9.m449
-rw-r--r--usr.sbin/sendmail/cf/ostype/irix4.m441
-rw-r--r--usr.sbin/sendmail/cf/ostype/irix5.m461
-rw-r--r--usr.sbin/sendmail/cf/ostype/isc4.1.m448
-rw-r--r--usr.sbin/sendmail/cf/ostype/nextstep.m444
-rw-r--r--usr.sbin/sendmail/cf/ostype/osf1.m440
-rw-r--r--usr.sbin/sendmail/cf/ostype/ptx2.m445
-rw-r--r--usr.sbin/sendmail/cf/ostype/riscos4.5.m442
-rw-r--r--usr.sbin/sendmail/cf/ostype/sco3.2.m445
-rw-r--r--usr.sbin/sendmail/cf/ostype/solaris2.m445
-rw-r--r--usr.sbin/sendmail/cf/ostype/svr4.m445
-rw-r--r--usr.sbin/sendmail/cf/ostype/ultrix4.m437
-rw-r--r--usr.sbin/sendmail/cf/ostype/unknown.m441
-rw-r--r--usr.sbin/sendmail/cf/sh/makeinfo.sh79
-rw-r--r--usr.sbin/sendmail/contrib/bitdomain.c409
-rw-r--r--usr.sbin/sendmail/contrib/bsdi.mc191
-rwxr-xr-xusr.sbin/sendmail/contrib/expn.pl1367
-rw-r--r--usr.sbin/sendmail/contrib/mailprio297
-rw-r--r--usr.sbin/sendmail/contrib/rmail.oldsys.patch108
-rw-r--r--usr.sbin/sendmail/doc/changes/changes.me997
-rw-r--r--usr.sbin/sendmail/doc/changes/changes.ps1092
-rw-r--r--usr.sbin/sendmail/doc/op/op.me7593
-rw-r--r--usr.sbin/sendmail/doc/op/op.ps5944
-rw-r--r--usr.sbin/sendmail/mail.local/Makefile9
-rw-r--r--usr.sbin/sendmail/mail.local/mail.local.8105
-rw-r--r--usr.sbin/sendmail/mail.local/mail.local.c868
-rw-r--r--usr.sbin/sendmail/mail.local/pathnames.h37
-rw-r--r--usr.sbin/sendmail/mailstats/mailstats.c227
-rw-r--r--usr.sbin/sendmail/makemap/makemap.8134
-rw-r--r--usr.sbin/sendmail/makemap/makemap.c496
-rw-r--r--usr.sbin/sendmail/rmail/Makefile6
-rw-r--r--usr.sbin/sendmail/rmail/rmail.871
-rw-r--r--usr.sbin/sendmail/rmail/rmail.c373
-rw-r--r--usr.sbin/sendmail/smrsh/Makefile8
-rw-r--r--usr.sbin/sendmail/smrsh/README144
-rw-r--r--usr.sbin/sendmail/smrsh/smrsh.8105
-rw-r--r--usr.sbin/sendmail/smrsh/smrsh.c233
-rw-r--r--usr.sbin/sendmail/src/Makefile47
-rw-r--r--usr.sbin/sendmail/src/READ_ME1183
-rw-r--r--usr.sbin/sendmail/src/TRACEFLAGS71
-rw-r--r--usr.sbin/sendmail/src/alias.c835
-rw-r--r--usr.sbin/sendmail/src/arpadate.c219
-rw-r--r--usr.sbin/sendmail/src/clock.c278
-rw-r--r--usr.sbin/sendmail/src/collect.c743
-rw-r--r--usr.sbin/sendmail/src/conf.c3755
-rw-r--r--usr.sbin/sendmail/src/conf.h1807
-rw-r--r--usr.sbin/sendmail/src/convtime.c203
-rw-r--r--usr.sbin/sendmail/src/daemon.c1736
-rw-r--r--usr.sbin/sendmail/src/deliver.c3016
-rw-r--r--usr.sbin/sendmail/src/domain.c871
-rw-r--r--usr.sbin/sendmail/src/envelope.c924
-rw-r--r--usr.sbin/sendmail/src/err.c695
-rw-r--r--usr.sbin/sendmail/src/headers.c1477
-rw-r--r--usr.sbin/sendmail/src/macro.c441
-rw-r--r--usr.sbin/sendmail/src/main.c2113
-rw-r--r--usr.sbin/sendmail/src/makesendmail282
-rw-r--r--usr.sbin/sendmail/src/map.c3330
-rw-r--r--usr.sbin/sendmail/src/mci.c425
-rw-r--r--usr.sbin/sendmail/src/mime.c866
-rw-r--r--usr.sbin/sendmail/src/parseaddr.c2157
-rw-r--r--usr.sbin/sendmail/src/pathnames.h54
-rw-r--r--usr.sbin/sendmail/src/queue.c2071
-rw-r--r--usr.sbin/sendmail/src/readcf.c2554
-rw-r--r--usr.sbin/sendmail/src/recipient.c1349
-rw-r--r--usr.sbin/sendmail/src/savemail.c1388
-rw-r--r--usr.sbin/sendmail/src/sendmail.8514
-rw-r--r--usr.sbin/sendmail/src/sendmail.h1237
-rw-r--r--usr.sbin/sendmail/src/sendmail.hf78
-rw-r--r--usr.sbin/sendmail/src/srvrsmtp.c1285
-rw-r--r--usr.sbin/sendmail/src/stab.c173
-rw-r--r--usr.sbin/sendmail/src/stats.c132
-rw-r--r--usr.sbin/sendmail/src/sysexits.c184
-rw-r--r--usr.sbin/sendmail/src/sysexits.h118
-rw-r--r--usr.sbin/sendmail/src/trace.c133
-rw-r--r--usr.sbin/sendmail/src/udb.c1103
-rw-r--r--usr.sbin/sendmail/src/useful.h78
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c1055
-rw-r--r--usr.sbin/sendmail/src/util.c2008
-rw-r--r--usr.sbin/sendmail/src/version.c39
-rw-r--r--usr.sbin/sendmail/test/Results65
-rw-r--r--usr.sbin/sendmail/test/t_seteuid.c120
-rw-r--r--usr.sbin/sendmail/test/t_setreuid.c132
158 files changed, 76442 insertions, 0 deletions
diff --git a/usr.sbin/sendmail/FAQ b/usr.sbin/sendmail/FAQ
new file mode 100644
index 000000000000..cc27e50805fd
--- /dev/null
+++ b/usr.sbin/sendmail/FAQ
@@ -0,0 +1,731 @@
+Newsgroups: comp.mail.sendmail,comp.mail.misc,comp.mail.smail,comp.answers,news.answers
+Subject: comp.mail.sendmail Frequently Asked Questions (FAQ)
+From: brad@birch.ims.disa.mil (Brad Knowles)
+Followup-to: comp.mail.sendmail
+Summary: This posting contains a list of Frequently Asked Questions
+ (and their answers) about the program "sendmail", distributed
+ with many versions of Unix (and available for some other
+ operating systems). This FAQ is shared between
+ comp.mail.sendmail and the Sendmail V8 distribution. It should
+ be read by anyone who wishes to post to comp.mail.sendmail, or
+ anyone having questions about the newsgroup itself.
+
+Archive-name: mail/sendmail-faq
+Posting-Frequency: monthly (first Monday)
+
+
+[The most recent copy of this document can be obtained via anonymous
+FTP from rtfm.mit.edu in /pub/usenet/news.answers/mail/sendmail-faq.
+If you do not have access to anonymous FTP, you can retrieve it by
+sending email to mail-server@rtfm.mit.edu with the command "send
+usenet/news.answers/mail/sendmail-faq" in the message.]
+
+
+
+ Sendmail Version 8
+ Frequently Asked Questions
+ Last updated 9/17/95
+
+
+This FAQ is specific to Version 8.6.10 of sendmail. Other questions,
+particularly regarding compilation and configuration, are answered in
+src/READ_ME and cf/README (found in the V8 sendmail distribution).
+
+This is also the official FAQ for the Usenet newsgroup
+comp.mail.sendmail.
+
+======================================================================
+BEFORE YOU GO ANY FURTHER
+======================================================================
+
+ * What do you wish everyone would do before sending you mail or
+ posting to comp.mail.sendmail?
+
+ Read this FAQ completely. Read src/READ_ME and cf/README
+ completely. Read the books written to help with common
+ problems such as compilation and installation, configuration,
+ security issues, etc.... Ask themselves if their question
+ hasn't already been answered.
+----------------------------------------------------------------------
+ * How can I be sure if this is the right place to look for answers
+ to my questions?
+
+ 1. Do you know, for a fact, that the question is related to
+ sendmail V8?
+
+ 2. Do you know, for a fact, that the question is related to an
+ older version of sendmail?
+
+ 3. Is the question about a sendmail-like program (e.g., Smail,
+ Zmailer, MMDF, etc...)?
+
+ 4. Is the question about an SMTP Gateway product for a LAN
+ mail package (e.g., cc:Mail, MS-Mail, WordPerfect
+ Office/GroupWise, etc...)?
+
+ If you answered "yes" to the question #1, then this is the
+ right place.
+
+ If you answered "yes" to questions #2 or #3, then you should
+ seriously consider upgrading to the most recent version of
+ sendmail V8.
+
+ For question #2, If you're going to continue using an older
+ version of sendmail, you may not find much help and will
+ probably get some responses that amount to "Get V8".
+ Otherwise, this is probably the best place to look for
+ answers.
+
+ If you answered "yes" to question #3 and are not going to
+ upgrade to sendmail V8, then this is probably not the right
+ place to look.
+
+ If you answered "yes" to question #4, then this is almost
+ certainly not the right place to look.
+
+ For questions #3 and #4, try looking around elsewhere in the
+ "comp.mail.*" hierarchy for a more appropriate newsgroup.
+ For example, you might want to try posting to comp.mail.misc
+ or comp.mail.smail.
+
+ If you couldn't answer "yes" to any of the above questions,
+ then you're DEFINITELY in the wrong place. For the sake of
+ your sanity and ego, not to mention avoiding the waste of
+ your time and ours, try asking your System or E-Mail
+ Administrator(s) before you post any questions publicly.
+----------------------------------------------------------------------
+ * Where can I find the latest version of this FAQ?
+
+ It is included in the most recent Version 8 distribution of
+ sendmail (described below), as well as via anonymous FTP from
+ rtfm.mit.edu in /pub/usenet/news.answers/mail/sendmail-faq.
+ If you do not have access to anonymous FTP, you can retrieve
+ it by sending email to mail-server@rtfm.mit.edu with the
+ command "send usenet/news.answers/mail/sendmail-faq" in the
+ message.
+----------------------------------------------------------------------
+ * I don't have access to Usenet news. Can I still get access to
+ comp.mail.sendmail?
+
+ Yes. Send email to mxt@dl.ac.uk with the command "sub
+ comp-news.comp.mail.sendmail <full-US-ordered-email-address>"
+ in the message.
+
+ E-mail you want posted on comp.mail.sendmail should be sent
+ to comp-mail-sendmail@dl.ac.uk
+----------------------------------------------------------------------
+ * I have sendmail-related DNS questions. Where should I ask them?
+
+ Depending on how deeply they get into the DNS, they can be
+ asked here. However, you'll probably be told that you should
+ send them to the Info-BIND mailing list (if the question is
+ specific to that program) or to the Usenet newsgroup
+ comp.protocols.tcp-ip.domains (DNS in general).
+----------------------------------------------------------------------
+ * How do I subscribe to either of these?
+
+ For comp.protocols.tcp-ip.domains, you have to be on Usenet.
+ They don't have a news-to-mail gateway yet.
+
+ For the Info-BIND mailing list, send email to
+ bind-request@uunet.uu.net with the command "subscribe" in the
+ message. Submissions should be sent to bind@uunet.uu.net
+
+======================================================================
+GENERAL QUESTIONS
+======================================================================
+
+ * Where can I get Version 8?
+
+ Via anonymous FTP from FTP.CS.Berkeley.EDU in /ucb/sendmail.
+----------------------------------------------------------------------
+ * What are the differences between Version 8 and other versions?
+
+ See doc/changes/changes.me in the sendmail distribution.
+----------------------------------------------------------------------
+ * What happened to sendmail 6.x and 7.x?
+
+ When a new (Alpha/Beta) version of sendmail was released, it
+ was changed to Release 6. Development continued in that tree
+ until 4.4BSD was released, when everything on the 4.4 tape
+ was set to be version 8.1. Version 7.x never existed.
+----------------------------------------------------------------------
+ * What books are available describing sendmail?
+
+ There is one book available devoted to sendmail:
+
+ Costales, Allman, and Rickert, _Sendmail_. O'Reilly &
+ Associates.
+
+ Several books have sendmail chapters, for example:
+
+ Nemeth, Snyder, and Seebass, _Unix System Administration
+ Handbook_. Prentice-Hall.
+ Carl-Mitchell and Quarterman, _Practical Internetworking with
+ TCP/IP and UNIX_. Addison-Wesley.
+ Hunt, _TCP/IP Network Administration_. O'Reilly & Associates.
+
+ Another book about sendmail is due out "soon":
+
+ Avolio & Vixie, _Sendmail Theory and Practice_. Digital
+ Press (release date unknown).
+
+ For details on sendmail-related DNS issues, consult:
+
+ Liu and Albitz, _DNS and BIND_. O'Reilly & Associates.
+
+ For details on UUCP, see:
+
+ O'Reilly and Todino, _Managing UUCP and Usenet_.
+ O'Reilly & Associates.
+
+======================================================================
+COMPILING AND INSTALLING SENDMAIL 8
+======================================================================
+
+ * Version 8 requires a new version of "make". Where can I get this?
+
+ Actually, Version 8 does not require a new version of "make".
+ It includes a collection of Makefiles for different architectures,
+ only one or two of which require the new "make". For a supported
+ architecture, use ``sh makesendmail''. If you are porting to a
+ new architecture, start with Makefile.dist.
+
+ If you really do want the new make, it is available on any of
+ the BSD Net2 or 4.4-Lite distribution sites. These include:
+
+ ftp.uu.net /systems/unix/bsd-sources
+ gatekeeper.dec.com /.0/BSD/net2
+ ucquais.cba.uc.edu /pub/net2
+ ftp.luth.se /pub/unix/4.3bsd/net2
+
+ Diffs and instructions for building this version of make
+ under SunOS 4.1.x are available on ftp.css.itd.umich.edu in
+ /pub/systems/sun/Net2-make.sun4.diff.Z. A patchkit for
+ Ultrix is on ftp.vix.com in /pub/patches/pmake-for-ultrix.Z.
+ Patches for AIX 3.2.4 are available on ftp.uni-stuttgart.de
+ in /sw/src/patches/bsd-make-rus-patches.
+
+ There is also a Linux version available on the main Linux
+ distribution sites as pmake; this version is included as
+ standard with the current Slackware distributions.
+----------------------------------------------------------------------
+ * What macro package do I use to format the V8 man pages?
+
+ The BSD group switched over the the ``mandoc'' macros for the
+ 4.4 release. These include more hooks designed for hypertext
+ handling. However, new man pages won't format under the old
+ man macros. Fortunately, old man pages will format under the
+ new mandoc macros.
+
+ Get the new macros with the BSD Net2 or 4.4-Lite release (see
+ above for locations; for example, on FTP.UU.NET the files
+ /system/unix/bsd-sources/share/tmac/me/strip/sed and
+ /system/unix/bsd-sources/share/tmac/* are what you need).
+
+ This macro set is also included with newer versions of groff.
+----------------------------------------------------------------------
+ * What modes should be used when installing sendmail?
+
+ The sendmail binary should be owned by root, mode 4755.
+ The queue directory should be owned by root, with a mode
+ between 700 and 755. Under no circumstances should
+ it be group or other writable!
+ The sendmail config file should be owned by root, mode 644.
+ The aliases file should generally be owned by one trusted
+ user and writable only by that user, although it is
+ not unreasonable to have it group writable by a
+ "sysadmin" group. It should not be world writable.
+ The aliases database files (aliases.db or aliases.{pag,dir}
+ depending on what database format you compile with)
+ should be owned by root, mode 644.
+
+======================================================================
+CONFIGURATION QUESTIONS
+======================================================================
+
+ * How do I make all my addresses appear to be from a single host?
+
+ Using the V8 configuration macros, use:
+
+ MASQUERADE_AS(my.dom.ain)
+
+ This will cause all addresses to be sent out as being from
+ the indicated domain.
+----------------------------------------------------------------------
+ * How do I rewrite my From: lines to read ``First_Last@My.Domain''?
+
+ There are a couple of ways of doing this. This describes
+ using the "user database" code. This is still experimental,
+ and was intended for a different purpose -- however, it does
+ work with a bit of care. It does require that you have the
+ Berkeley "db" package installed (it won't work with DBM).
+
+ First, create your input file. This should have lines like:
+
+ loginname:mailname First_Last
+ First_Last:maildrop loginname
+
+ Install it in (say) /etc/userdb. Create the database:
+
+ makemap btree /etc/userdb.db < /etc/userdb
+
+ You can then create a config file that uses this. You will
+ have to include the following in your .mc file:
+
+ define(confUSERDB_SPEC, /etc/userdb.db)
+ FEATURE(notsticky)
+----------------------------------------------------------------------
+ * So what was the user database feature intended for?
+
+ The intent was to have all information for a given user
+ (where the user is the unique login name, not an inherently
+ non-unique full name) in one place. This would include phone
+ numbers, addresses, and so forth. The "maildrop" feature is
+ because Berkeley does not use a centralized mail server
+ (there are a number of reasons for this that are mostly
+ historic), and so we need to know where each user gets his or
+ her mail delivered -- i.e., the mail drop.
+
+ We are in the process of setting up our environment so that
+ mail sent to an unqualified "name" goes to that person's
+ preferred maildrop; mail sent to "name@host" goes to that
+ host. The purpose of "FEATURE(notsticky)" is to cause
+ "name@host" to be looked up in the user database for delivery
+ to the maildrop.
+----------------------------------------------------------------------
+ * Why are you so hostile to using full names for e-mail addresses?
+
+ Because full names are not unique. For example, the computer
+ community has two Andy Tannenbaums and two Peter Deutsches.
+ At one time, Bell Labs had two Stephen R. Bournes with
+ offices a few doors apart. You can create alternative
+ addresses (e.g., Stephen_R_Bourne_2), but that's even worse
+ -- which one of them has to have their name desecrated in
+ this way? And you can bet that one of them will get most of
+ the other person's e-mail.
+
+ So called "full names" are just an attempt to create longer
+ versions of unique names. Rather that lulling people into a
+ sense of security, I'd rather that it be clear that these
+ handles are arbitrary. People should use good user agents
+ that have alias mappings so that they can attach arbitrary
+ names for their personal use to those with whom they
+ correspond (such as the MH alias file).
+
+ Even worse is fuzzy matching in e-mail -- this can make good
+ addresses turn bad. For example, Eric Allman is currently
+ (to the best of our knowledge) the only ``Allman'' at
+ Berkeley, so mail sent to "Allman@Berkeley.EDU" should get to
+ him. But if another Allman ever appears, this address could
+ suddenly become ambiguous. He's been the only Allman at
+ Berkeley for over fifteen years -- to suddenly have this
+ "good address" bounce mail because it is ambiguous would be a
+ heinous wrong.
+
+ Finger services should be as fuzzy as possible (within
+ reason, of course). Mail services should be unique.
+----------------------------------------------------------------------
+ * Should I use a wildcard MX for my domain?
+
+ If at all possible, no.
+
+ Wildcard MX records have lots of semantic "gotcha"s. For
+ example, they will match a host "unknown.your.domain" -- if
+ you don't explicitly test for unknown hosts in your domain,
+ you will get "config error: mail loops back to myself"
+ errors.
+
+ See RFCs 1535-1537 for more detail and other related (or
+ common) problems.
+----------------------------------------------------------------------
+ * How can I get sendmail to process messages sent to an account and
+ send the results back to the originator?
+
+ This is a local mailer issue, not a sendmail issue.
+ Depending on what you're doing, look at procmail (mentioned
+ again below), ftpmail, or Majordomo.
+
+ Check your local archie server to see what machine(s) nearest
+ you have the most recent versions of these programs.
+----------------------------------------------------------------------
+ * How can I get sendmail to deliver local mail to $HOME/.mail
+ instead of into /usr/spool/mail (or /usr/mail)?
+
+ Again, this is a local mailer issue, not a sendmail issue.
+ Either modify your local mailer (source code will be
+ required) or change the program called in the "local" mailer
+ configuration description to be a new program that does this
+ local delivery. One program that is capable of doing this is
+ "procmail", although there are probably many others as well.
+
+ You might be interested in reading the paper ``HLFSD:
+ Delivering Email to your $HOME'' available in the Proceedings
+ of the USENIX System Administration (LISA VII) Conference
+ (November 1993). This is also available via public FTP from
+ ftp.cs.columbia.edu in /pub/hlfsd/{README.hlfsd,hlfsd.ps}.
+----------------------------------------------------------------------
+ * I'm trying to to get my mail to go into queue only mode, and it
+ delivers the mail interactively anyway. (Or, I'm trying to use
+ the "don't deliver to expensive mailer" flag, and it delivers the
+ mail interactively anyway.) I can see it does it: here's the
+ output of "sendmail -v foo@somehost" (or Mail -v or equivalent).
+
+ The -v flag to sendmail (which is implied by the -v flag to
+ Mail and other programs in that family) tells sendmail to
+ watch the transaction. Since you have explicitly asked to
+ see what's going on, it assumes that you do not want to to
+ auto-queue, and turns that feature off. Remove the -v flag
+ and use a "tail -f" of the log instead to see what's going
+ on.
+
+ If you are trying to use the "don't deliver to expensive
+ mailer" flag (mailer flag "e"), be sure you also turn on
+ global option "c" -- otherwise it ignores the mailer flag.
+----------------------------------------------------------------------
+ * There are four UUCP mailers listed in the configuration files.
+ Which one should I use?
+
+ The choice is partly a matter of local preferences and what
+ is running at the other end of your UUCP connection. Unlike
+ good protocols that define what will go over the wire, UUCP
+ uses the policy that you should do what is right for the
+ other end; if they change, you have to change. This makes it
+ hard to do the right thing, and discourages people from
+ updating their software. In general, if you can avoid UUCP,
+ please do.
+
+ If you can't avoid it, you'll have to find the version that
+ is closest to what the other end accepts. Following is a
+ summary of the UUCP mailers available.
+
+ uucp-old (obsolete name: "uucp")
+ This is the oldest, the worst (but the closest to UUCP) way
+ of sending messages across UUCP connections. It does
+ bangify everything and prepends $U (your UUCP name) to the
+ sender's address (which can already be a bang path
+ itself). It can only send to one address at a time, so it
+ spends a lot of time copying duplicates of messages. Avoid
+ this if at all possible.
+
+ uucp-new (obsolete name: "suucp")
+ The same as above, except that it assumes that in one rmail
+ command you can specify several recipients. It still has a
+ lot of other problems.
+
+ uucp-dom
+ This UUCP mailer keeps everything as domain addresses.
+ Basically, it uses the SMTP mailer rewriting rules.
+
+ Unfortunately, a lot of UUCP mailer transport agents
+ require bangified addresses in the envelope, although you
+ can use domain-based addresses in the message header. (The
+ envelope shows up as the From_ line on UNIX mail.) So....
+
+ uucp-uudom
+ This is a cross between uucp-new (for the envelope
+ addresses) and uucp-dom (for the header addresses). It
+ bangifies the envelope sender (From_ line in messages)
+ without adding the local hostname, unless there is no host
+ name on the address at all (e.g., "wolf") or the host
+ component is a UUCP host name instead of a domain name
+ ("somehost!wolf" instead of "some.dom.ain!wolf").
+
+ Examples:
+
+ We are on host grasp.insa-lyon.fr (UUCP host name "grasp").
+ The following summarizes the sender rewriting for various
+ mailers.
+
+ Mailer sender rewriting in the envelope
+ ------ ------ -------------------------
+ uucp-{old,new} wolf grasp!wolf
+ uucp-dom wolf wolf@grasp.insa-lyon.fr
+ uucp-uudom wolf grasp.insa-lyon.fr!wolf
+
+ uucp-{old,new} wolf@fr.net grasp!fr.net!wolf
+ uucp-dom wolf@fr.net wolf@fr.net
+ uucp-uudom wolf@fr.net fr.net!wolf
+
+ uucp-{old,new} somehost!wolf grasp!somehost!wolf
+ uucp-dom somehost!wolf somehost!wolf@grasp.insa-lyon.fr
+ uucp-uudom somehost!wolf grasp.insa-lyon.fr!somehost!wolf
+
+======================================================================
+RESOLVING PROBLEMS
+======================================================================
+
+ * When I compile, I get "undefined symbol inet_aton" messages.
+
+ You've probably replaced your resolver with the version from
+ BIND 4.9.3. You need to compile with -l44bsd in order to get
+ the additional routines.
+----------------------------------------------------------------------
+ * I'm getting "Local configuration error" messages, such as:
+
+ 553 relay.domain.net config error: mail loops back to myself
+ 554 <user@domain.net>... Local configuration error
+
+ How can I solve this problem?
+
+ You have asked mail to the domain (e.g., domain.net) to be
+ forwarded to a specific host (in this case, relay.domain.net)
+ by using an MX record, but the relay machine doesn't
+ recognize itself as domain.net. Add domain.net to
+ /etc/sendmail.cw (if you are using FEATURE(use_cw_file)) or
+ add "Cw domain.net" to your configuration file.
+
+ IMPORTANT: Be sure you kill and restart the sendmail daemon
+ after you change the configuration file (for ANY change in
+ the configuration, not just this one):
+
+ kill `head -1 /etc/sendmail.pid`
+ sh -c "`tail -1 /etc/sendmail.pid`"
+
+ NOTA BENE: kill -1 does not work!
+----------------------------------------------------------------------
+ * When I use sendmail V8 with a Sun config file I get lines like:
+
+ /etc/sendmail.cf: line 273: replacement $3 out of bounds
+
+ the line in question reads:
+
+ R$*<@$%y>$* $1<@$2.LOCAL>$3 user@ether
+
+ what does this mean? How do I fix it?
+
+ V8 doesn't recognize the Sun "$%y" syntax, so as far as it is
+ concerned, there is only a $1 and a $2 (but no $3) in this
+ line. Read Rick McCarty's paper on "Converting Standard Sun
+ Config Files to Sendmail Version 8", in the contrib directory
+ (file "converting.sun.configs") on the sendmail distribution
+ for a full discussion of how to do this.
+----------------------------------------------------------------------
+ * When I use sendmail V8 on a Sun, I sometimes get lines like:
+
+ /etc/sendmail.cf: line 445: bad ruleset 96 (50 max)
+
+ what does this mean? How do I fix it?
+
+ You're somehow trying to start up the old Sun sendmail (or
+ sendmail.mx) with a sendmail V8 config file, which Sun's
+ sendmail doesn't like. Check your /etc/rc.local, any
+ procedures that have been created to stop and re-start the
+ sendmail processes, etc.... Make sure that you've switched
+ everything over to using the new sendmail. To keep this
+ problem from ever happening again, try the following:
+
+ mv /usr/lib/sendmail /usr/lib/sendmail.old
+ ln -s /usr/local/lib/sendmail.v8 /usr/lib/sendmail
+ mv /usr/lib/sendmail.mx /usr/lib/sendmail.mx.old
+ ln -s /usr/local/lib/sendmail.v8 /usr/lib/sendmail.mx
+ chmod 0000 /usr/lib/sendmail.old
+ chmod 0000 /usr/lib/sendmail.mx.old
+
+ Assuming you have installed sendmail V8 in /usr/local/lib.
+----------------------------------------------------------------------
+ * When I use sendmail V8 on an IBM RS/6000 running AIX, the system
+ resource controller always reports sendmail as "inoperative" even
+ though it is running. What's wrong?
+
+ IBM's system resource controller is one of their "value
+ added" features to AIX -- it's not a Unix standard. You'll
+ need to either redefine the subsystem to use signals (see
+ chssys(1)) or dump the entire subsystem and invoke sendmail
+ in /etc/rc.tcpip or some other boot script.
+----------------------------------------------------------------------
+ * When I use sendmail V8 on an Intel x86 machine running Linux, I
+ have some problems. Specifically, I have....
+
+ The current versions of Linux are generally considered to be
+ great for hobbyists and anyone else who wants to learn Unix
+ inside and out, or wants to always have something to do, or
+ wants a machine for light-duty mostly personal use and not
+ high-volume multi-user purposes.
+
+ However, for those who want a system that will just sit in
+ the background and work without a fuss handling thousands of
+ mail messages a day for lots of different users, it's not
+ (yet) stable enough to fit the bill.
+
+ Unfortunately, there are no known shareware/freeware
+ implementations of any operating system that provides the
+ level of stability necessary to handle that kind of load
+ (i.e., there are no free lunches).
+
+ If you're wedded to the Intel x86 platform and want to run
+ sendmail, we suggest you look at commercial implementations
+ of Unix such as Interactive, UnixWare, Solaris, or BSD/386
+ (just a sample of the dozens of different versions of Unix
+ for Intel x86).
+
+ Of all known vendor supported versions of Unix for Intel x86,
+ BSDI's BSD/386 is least expensive and the only one known to
+ currently ship with sendmail V8 pre-installed. Since sendmail
+ V8 is continuing to be developed at UC Berkeley, and BSD/386
+ is a full BSD 4.4 implementation, this is obviously be the most
+ "native" sendmail V8 environment.
+----------------------------------------------------------------------
+ * When I use sendmail on an Intel x86 machine running OS/2, I have
+ some problems. Specifically, I have....
+
+ The OS/2 port of sendmail is known to have left out huge
+ chunks of the code and functionality of even much older
+ versions of sendmail, in large part because the underlying OS
+ just doesn't have the necessary hooks to make it happen.
+ This port is so broken that we make no attempt to provide any
+ kind of support for it. Try BSDI's BSD/386 instead.
+----------------------------------------------------------------------
+ * I'm connected to the network via a SLIP/PPP link. Sometimes my
+ sendmail process hangs (although it looks like part of the
+ message has been transfered). Everything else works. What's
+ wrong?
+
+ Most likely, the problem isn't sendmail at all, but the low
+ level network connection. It's important that the MTU
+ (Maximum Transfer Unit) for the SLIP connection be set
+ properly at both ends. If they disagree, large packets will
+ be trashed and the connection will hang.
+----------------------------------------------------------------------
+ * I just upgraded to 8.x and suddenly I'm getting messages in my
+ syslog of the form "collect: I/O error on connection". What is
+ going wrong?
+
+ Nothing. This is just a diagnosis of a condition that had
+ not been diagnosed before. If you are getting a lot of these
+ from a single host, there is probably some incompatibility
+ between 8.x and that host. If you get a lot of them in
+ general, you may have network problems that are causing
+ connections to get reset.
+----------------------------------------------------------------------
+ * I just upgraded to 8.x and now when my users try to forward their
+ mail to a program they get an "illegal shell" message and their
+ mail is not delivered. What's wrong?
+
+ In order for people to be able to run a program from their
+ .forward file, 8.x insists that their shell (that is, the
+ shell listed for that user in the passwd entry) be a "valid"
+ shell, meaning a shell listed in /etc/shells. If /etc/shells
+ does not exist, a default list is used, typically consisting
+ of /bin/sh and /bin/csh.
+
+ This is to support environments that may have NFS-shared
+ directories mounted on machines on which users do not have
+ login permission. For example, many people make their
+ file server inaccessible for performance or security
+ reasons; although users have directories, their shell on
+ the server is /usr/local/etc/nologin or some such. If you
+ allowed them to run programs anyway you might as well let
+ them log in.
+
+ If you are willing to let users run programs from their
+ .forward file even though they cannot telnet or rsh in (as
+ might be reasonable if you run smrsh to control the list of
+ programs they can run) then add the line
+
+ /SENDMAIL/ANY/SHELL/
+
+ to /etc/shells. This must be typed exactly as indicated,
+ in caps, with the trailing slash. NOTA BENE: DO NOT
+ list /usr/local/etc/nologin in /etc/shells -- this will
+ open up other security problems.
+----------------------------------------------------------------------
+ * I just upgraded to 8.x and suddenly connections to the SMTP port
+ take a long time. What is going wrong?
+
+ It's probably something weird in your TCP implementation that
+ makes the IDENT code act oddly. On most systems V8 tries to
+ do a ``callback'' to the connecting host to get a validated
+ user name (see RFC 1413 for detail). If the connecting host
+ does not support such a service it will normally fail quickly
+ with "Connection refused", but certain kinds of packet
+ filters and certain TCP implementations just time out.
+
+ To test this, set the IDENT timeout to zero using
+ ``OrIdent=0'' in the configuration file. This will
+ completely disable all use of the IDENT protocol.
+
+ Another possible problem is that you have your name server
+ and/or resolver configured improperly. Make sure that all
+ "nameserver" entries in /etc/resolv.conf point to functional
+ servers. If you are running your own server make certain
+ that all the servers listed in your root cache (usually
+ called something like "/var/namedb/root.cache"; see your
+ /etc/named.boot file to get your value) are up to date.
+ Either of these can cause long delays.
+----------------------------------------------------------------------
+ * I just upgraded to 8.x and suddenly I get errors such as ``unknown
+ mailer error 5 -- mail: options MUST PRECEDE recipients.'' What is
+ going wrong?
+
+ You need OSTYPE(systype) in your .mc file -- otherwise the
+ configurations use a default that probably disagrees with
+ your local mail system. See cf/README for details.
+----------------------------------------------------------------------
+ * Under V8, the "From " header gets mysteriously munged when I send
+ to an alias.
+
+ ``It's not a bug, it's a feature.'' This happens when you
+ have a "owner-list" alias and you send to "list". V8
+ propagates the owner information into the envelope sender
+ field (which appears as the "From " header on UNIX mail or as
+ the Return-Path: header) so that downstream errors are
+ properly returned to the mailing list owner instead of to the
+ sender. In order to make this appear as sensible as possible
+ to end users, I recommend making the owner point to a
+ "request" address -- for example:
+
+ list: :include:/path/name/list.list
+ owner-list: list-request
+ list-request: eric
+
+ This will make message sent to "list" come out as being "From
+ list-request" instead of "From eric".
+----------------------------------------------------------------------
+ * I am trying to use MASQUERADE_AS (or the user database) to
+ rewrite from addresses, and although it works in the From: header
+ line, it doesn't work in the envelope (e.g., the "From " line).
+
+ Believe it or not, this is intentional. The interpretation
+ of the standards by the V8 development group was that this
+ was an inappropriate rewriting, and that if the rewriting
+ were incorrect at least the envelope would contain a valid
+ return address. Other people have since described scenarios
+ where the envelope cannot be correct without this rewriting,
+ so 8.7 will have an option to rewrite both header and
+ envelope.
+----------------------------------------------------------------------
+ * I want to run Sendmail version 8 on my DEC system, but you don't
+ have MAIL11V3 support in sendmail. How do I handle this?
+
+ Get Paul Vixie's reimplementation of the mail11 protocol from
+ gatekeeper.dec.com in /pub/DEC/gwtools.
+
+ Rumour has it that he will be fully integrating into sendmail
+ V8 what little is left of IDA sendmail that is not handled
+ (or handled as well) by V8. No additional information on
+ this project is currently available.
+----------------------------------------------------------------------
+ * Messages seem to disappear from my queue unsent. When I look in
+ the queue directory I see that they have been renamed from qf* to
+ Qf*, and sendmail doesn't see these.
+
+ If you look closely you should find that the Qf files are
+ owned by users other than root. Since sendmail runs as root
+ it refuses to believe information in non-root-owned qf files,
+ and it renames them to Qf to get them out of the way and make
+ it easy for you to find. The usual cause of this is
+ twofold: first, you have the queue directory world writable
+ (which is probably a mistake -- this opens up other security
+ problems) and someone is calling sendmail with an "unsafe"
+ flag, usually a -o flag that sets an option that could
+ compromise security. When sendmail sees this it gives up
+ setuid root permissions.
+
+ The usual solution is to not use the problematic flags. If
+ you must use them, you have to write a special queue
+ directory and have them processed by the same uid that
+ submitted the job in the first place.
+----------------------------------------------------------------------
+@(#)FAQ 8.16 (Berkeley) 9/17/95
+Send updates to sendmail@sendmail.ORG.
diff --git a/usr.sbin/sendmail/KNOWNBUGS b/usr.sbin/sendmail/KNOWNBUGS
new file mode 100644
index 000000000000..f9020e7fb75e
--- /dev/null
+++ b/usr.sbin/sendmail/KNOWNBUGS
@@ -0,0 +1,119 @@
+
+
+ K N O W N B U G S I N S E N D M A I L
+ (for 8.7)
+
+
+The following are bugs or deficiencies in sendmail that I am aware of
+but which have not been fixed in the current release. You probably
+want to get the most up to date version of this from FTP.CS.Berkeley.EDU
+in /ucb/sendmail/KNOWNBUGS. For descriptions of bugs that have been
+fixed, see the file RELEASE_NOTES (in the root directory of the sendmail
+distribution).
+
+This list is not guaranteed to be complete.
+
+
+* Null bytes are not handled properly in headers.
+
+ Sendmail should handle full binary data. As it stands, it handles
+ all values in the body, but only 0x01-0x80 and 0xA0-0xFF in
+ the header. Notably missing is 0x00, which would require a major
+ restructuring of the code -- for example, almost no C library support
+ could be used to handle strings.
+
+* Duplicate error messages.
+
+ Sometimes identical, duplicate error messages can be generated. As
+ near as I can tell, this is rare and relatively innocuous.
+
+* $c (hop count) macro improperly set.
+
+ The $c macro is supposed to contain the current hop count, for use
+ when calling a mailer. This macro is initialized too early, and
+ is always zero (or the value of the -c command line flag, if any).
+ This macro will probably be removed entirely in a future release;
+ I don't believe there are any mailers left that require it.
+
+* If you EXPN a list or user that has a program mailer, the output of
+ EXPN will include ``@local.host.name''. You can't actually mail to
+ this address. It's not clear what the right behaviour is in this
+ circumstance.
+
+* MX records that point at non-existent hosts work strangly.
+
+ Consider the DNS records:
+
+ hostH MX 1 hostA
+ MX 2 hostB
+ hostA A 128.32.8.9
+
+ (note that there is no A record for hostB). If hostA is down,
+ an attempt to send to hostH gives "host unknown" -- that is, it
+ reflects out the status on the last host it tries, which in this
+ case is hostB, which is unknown. It probably ought to eliminate
+ hostB early in processing.
+
+* \231 considered harmful.
+
+ Header addresses that have the \231 character (and possibly others
+ in the range \201 - \237) behave in odd and usually unexpected ways.
+
+* accept() problem on SVR4.
+
+ Apparently, the sendmail daemon loop (doing accept()s on the network)
+ can get into a wierd state on SVR4; it starts logging ``SYSERR:
+ getrequests: accept: Protocol Error''. The workaround is to kill
+ and restart the sendmail daemon. We don't have an SVR4 system at
+ Berkeley that carries more than token mail load, so I can't validate
+ this. It is likely to be a glitch in the sockets emulation, since
+ "Protocol Error" is not possible error code with Berkeley TCP/IP.
+
+ I've also had someone report the message ``sendmail: accept:
+ SIOCGPGRP failed errno 22'' on an SVR4 system. This message is
+ not in the sendmail source code, so I assume it is also a bug
+ in the sockets emulation. (Errno 22 is EINVAL "Invalid Argument"
+ on all the systems I have available, including Solaris 2.x.)
+
+* Sending user deletion not done properly in :include: lists.
+
+ If you don't have the "m" (me too) option set, then a person
+ sending to a list that contains themselves should not get a copy
+ of the message. However, if that list points to a :include: file
+ that has one address per line, this will break, and the sender
+ will always get a copy of their own message, just as though the
+ "m" option were set.
+
+ You can eliminate this by adding commas at the end of each line
+ of the :include: file.
+
+* Excessive mailing list nesting can run out of file descriptors.
+
+ If you have a mailing list that includes lots of other mailing
+ lists, each of which has a separate owner, you can run out of
+ file descriptors. Each mailing list with a separate owner uses
+ one open file descriptor (prior to 8.6.6 it was three open
+ file descriptors per list). This is particularly egregious if
+ you have your connection cache set to be large.
+
+* Connection caching breaks if you pass the port number as an argument.
+
+ If you have a definition such as:
+
+ Mport, P=[IPC], F=kmDFMuX, S=11/31, R=21,
+ M=2100000, T=DNS/RFC822/SMTP,
+ A=IPC [127.0.0.1] $h
+
+ (i.e., where $h is the port number instead of the host name) the
+ connection caching code will break because it won't notice that
+ two messages addressed to different ports should use different
+ connections.
+
+* ESMTP SIZE underestimates the size of a message
+
+ Sendmail makes no allowance for headers that it adds, nor does it
+ account for the SMTP on-the-wire \r\n expansion. It probably doesn't
+ allow for 8->7 bit MIME conversions either.
+
+
+(Version 8.21, last updated 8/27/95)
diff --git a/usr.sbin/sendmail/Makefile b/usr.sbin/sendmail/Makefile
new file mode 100644
index 000000000000..2dc0b0fd7b50
--- /dev/null
+++ b/usr.sbin/sendmail/Makefile
@@ -0,0 +1,45 @@
+# @(#)Makefile 8.12 (Berkeley) 5/29/95
+
+VER= XX
+SUBDIR= src mailstats makemap praliases cf/cf
+FTPDIR= mastodon:/disks/barad-dur/ftp/sendmail/.
+DISTFILES=sendmail.${VER}.tar.Z sendmail.${VER}.tar.gz \
+ RELEASE_NOTES FAQ KNOWNBUGS
+FILES= Files.base Files.cf Files.misc Files.xdoc
+
+tar: sccs-check compile-world run-pax
+
+sccs-check:
+ sccs check
+ (cd src; sccs check)
+ (cd doc/op; sccs check)
+ (cd doc/intro; sccs check)
+ (cd doc/usenix; sccs check)
+ (cd cf; sccs check)
+ (cd cf/m4; sccs check)
+ (cd cf/mailer; sccs check)
+ (cd cf/feature; sccs check)
+ (cd cf/cf; sccs check)
+ (cd cf/ostype; sccs check)
+ (cd cf/domain; sccs check)
+
+compile-world:
+ (cd src; ${MAKE})
+ (cd doc; PRINTER=ps ${MAKE})
+ (cd doc; chmod 444 op/op.ps intro/intro.ps usenix/usenix.ps)
+ (cd cf/cf; ${MAKE})
+
+run-pax: Files.base Files.cf Files.misc Files.xdoc
+ chmod +x src/makesendmail
+ pax -w -x tar -L \
+ -s ",cf/domain/unspecified-domain,sendmail-${VER}/cf/domain/berkeley-only,p" \
+ -s ",^,sendmail-${VER}/," \
+ -f sendmail.${VER}.tar \
+ `cat ${FILES} | grep -v ^#`
+ gzip -c sendmail.${VER}.tar > sendmail.${VER}.tar.gz
+ compress sendmail.${VER}.tar
+
+ftp: sendmail.${VER}.tar.Z
+ rcp ${DISTFILES} ${FTPDIR}
+
+.include <bsd.subdir.mk>
diff --git a/usr.sbin/sendmail/READ_ME b/usr.sbin/sendmail/READ_ME
new file mode 100644
index 000000000000..2e50d085ecad
--- /dev/null
+++ b/usr.sbin/sendmail/READ_ME
@@ -0,0 +1,288 @@
+/*-
+ * @(#)READ_ME 8.25 (Berkeley) 11/19/95
+ */
+
+ SENDMAIL RELEASE 8
+
+This directory has the latest sendmail software from Berkeley. See
+doc/changes/changes.me for a summary of changes since 5.67.
+
+Report any bugs to sendmail-bugs@sendmail.ORG
+
+******************************************************************
+** DO NOT USE MAKE to compile sendmail. Instead, cd src and **
+** use the "makesendmail" shell script. On many environments **
+** this will do everything for you, no fuss, no muss. See **
+** src/READ_ME for more details of compilation. See cf/README **
+** for details about building a runtime configuration file. **
+******************************************************************
+
+
++--------------+
+| MANUAL PAGES |
++--------------+
+
+The sendmail manual pages use contemporary Berkeley troff macros. If
+your system does not process these manual pages, you can pick up the
+new macros in a BSD Net/2 FTP site (e.g. on FTP.UU.NET, the files
+/systems/unix/bsd-sources/share/tmac/me/strip.sed and
+/systems/unix/bsd-sources/share/tmac/*).
+
+The strip.sed file is only used in installation.
+
+After installation, edit tmac.doc and tmac.andoc to reflect the
+installation path of the tmac files. Those files contain pointers to
+/usr/share/tmac/, and those pointers are not changed by the `make
+install` process. There's also a bug in those files -- make the
+following patch:
+
+*** tmac.an~ Tue Jul 12 14:29:09 1994
+--- tmac.an Fri Jul 15 13:17:54 1994
+***************
+*** 50,55 ****
+ .de TH
+ .rn TH xX
+ .so /usr/share/lib/tmac/tmac.an.old
+! .TH \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+ .rm xX
+ ..
+--- 50,55 ----
+ .de TH
+ .rn TH xX
+ .so /usr/share/lib/tmac/tmac.an.old
+! .TH "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" "\\$7" "\\$8"
+ .rm xX
+ ..
+
+Rename the existing tmac.an to be tmac.an.old, and rename tmac.andoc
+to be tmac.an.
+
+tmac.an will choose between tmac.an.old, your old macros, or tmac.doc,
+which are the new macros, so that both the new man pages and the
+existing man pages will be translated properly.
+
+I'm also told that the groff distribution from MIT has a tmac.doc
+macro set that is compatible with these macros.
+
+
++-----------------------+
+| RELATED DOCUMENTATION |
++-----------------------+
+
+There are other files you should read. Rooted in this directory are:
+
+ CHANGES-R5-R8
+ Describes changes between Release 5 and Release 8 of sendmail.
+ There are some things that may behave somewhat differently.
+ For example, the rules governing when :include: files will
+ be read have been tightened up for security reasons.
+ FAQ
+ Answers to Frequently Asked Questions.
+ KNOWNBUGS
+ Known bugs in the current release. I try to keep this up
+ to date -- get the latest version from FTP.CS.Berkeley.EDU
+ in /ucb/sendmail/KNOWNBUGS.
+ RELEASE_NOTES
+ A detailed description of the changes in each version. This
+ is quite long, but informative.
+ src/READ_ME
+ Details on compiling and installing sendmail.
+ cf/README
+ Details on configuring sendmail.
+ doc/op/op.me
+ The sendmail Installation & Operations Guide. Be warned: if
+ you are running this off on SunOS or some other system with an
+ old version of -me, you need to add the following macro to the
+ macros:
+
+ .de sm
+ \s-1\\$1\\s0\\$2
+ ..
+
+ This sets a word in a smaller pointsize.
+
+
++--------------+
+| RELATED RFCS |
++--------------+
+
+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
+ RFC1425 SMTP Service Extensions (ESMTP spec)
+ RFC1426 SMTP Service Extension for 8bit-MIMEtransport
+ RFC1427 SMTP Service Extension for Message Size Declaration
+ RFC1521 MIME: Multipurpose Internet Mail Extensions
+ RFC1344 Implications of MIME for Internet Mail Gateways
+ RFC1428 Transition of Internet Mail from Just-Send-8 to
+ 8-bit SMTP/MIME
+
+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)
+
+Warning to AIX users: this version of sendmail does not implement
+MB, MR, or MG DNS resource records, as defined (as experiments) in
+RFC1035.
+
+
++-------------------+
+| DATABASE ROUTINES |
++-------------------+
+
+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.
+
+Be sure you remove ndbm.h and ndbm.o from the db distribution. These
+will cause problems with sendmail because sendmail already understands
+about NEWDB and NDBM coexisting.
+
+
++--------------------+
+| HOST NAME SERVICES |
++--------------------+
+
+If you are using NIS or /etc/hosts, it is critical that you
+list the long (fully qualified) name somewhere (preferably first) in
+the /etc/hosts file used to build the NIS database. For example, the
+line should read
+
+ 128.32.149.68 mastodon.CS.Berkeley.EDU mastodon
+
+**** NOT ****
+
+ 128.32.149.68 mastodon
+
+If you do not include the long name, sendmail will complain loudly
+about ``unable to qualify my own domain name (mastodon) -- using
+short name'' and conclude that your canonical name is the short
+version and use that in messages. The name "mastodon" doesn't mean
+much outside of Berkeley, and so this creates incorrect and unreplyable
+messages.
+
+
++-------------+
+| USE WITH MH |
++-------------+
+
+This version of sendmail notices and reports certain kinds of SMTP
+protocol violations that were ignored by older versions. If you
+are running MH you may wish to install the patch in contrib/mh.patch
+that will prevent these warning reports. This patch also works
+with the old version of sendmail, so it's safe to go ahead and
+install it.
+
+
++----------------+
+| USE WITH IDENT |
++----------------+
+
+Sendmail 8 supports the IDENT protocol, as defined by RFC 1413.
+No ident server is included with this distribution. I have found
+copies available on:
+
+ ftp.lysator.liu.se /pub/ident/servers
+ romulus.ucs.uoknor.edu /networking/ident/servers
+ ftp.cyf-kr.edu.pl /agh/uciagh/network/ident
+
+If you want to run an IDENT server, I suggest getting a copy from
+one of those sites. Versions are available for several different
+systems, including Apollo, BSD, NeXT, AIX, TOPS20, and VMS.
+
+
++-----------+
+| MAKEFILES |
++-----------+
+
+The Makefiles in this release use the new Berkeley "make" that is
+available in BSD Net/2 and 4.4BSD. If you are using this version
+of make, you may notice one or two places where the Makefile includes
+"../../Makefile.inc". This file is not included with the sendmail
+distribution because it's not part of sendmail. However, it is,
+in toto:
+
+ # @(#)Makefile.inc 8.1 (Berkeley) 6/6/93
+
+ BINDIR?= /usr/sbin
+
+The other directories should all have Makefile.dist files that work
+on the old make, albeit without all the niceties included.
+
+You can also get a new Berkeley make from the Net2 release (available
+on many public FTP archives). This version should also interpret old
+Makefiles, so you could drop it in as your default make.
+
+For more details, see src/READ_ME.
+
+
++---------------------+
+| DIRECTORY STRUCTURE |
++---------------------+
+
+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.
+mail.local The source for the local delivery agent used for 4.4BSD.
+ THIS IS NOT PART OF SENDMAIL! and may not compile
+ everywhere, since it depends on some 4.4-isms. Warning:
+ it does mailbox locking differently than other systems.
+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 or NEWDB version of the
+ aliases file.
+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. RMAIL IS NOT PART OF
+ SENDMAIL!!! The 4.4BSD source is included for you to
+ look at or try to port to your system. I know it doesn't
+ compile on {SunOS, HP-UX, OSF/1, other} (pick one).
+smrsh The "sendmail restricted shell", which can be used as
+ a replacement for /bin/sh in the prog mailer to provide
+ increased security control. NOT PART OF SENDMAIL!
+src Source for the sendmail program itself.
+test Some test scripts (currently only for compilation aids).
diff --git a/usr.sbin/sendmail/RELEASE_NOTES b/usr.sbin/sendmail/RELEASE_NOTES
new file mode 100644
index 000000000000..42931dad88d3
--- /dev/null
+++ b/usr.sbin/sendmail/RELEASE_NOTES
@@ -0,0 +1,4003 @@
+ SENDMAIL RELEASE NOTES
+ @(#)RELEASE_NOTES 8.7.2.1 (Berkeley) 11/19/95
+
+
+This listing shows the version of the sendmail binary, the version
+of the sendmail configuration files, the date of release, and a
+summary of the changes in that release.
+
+8.7.2/8.7.2 95/11/19
+ REALLY fix the backslash escapes in SmtpGreetingMessage,
+ OperatorChars, and UnixFromLine options. They were not
+ properly repaired in 8.7.1.
+ Completely delete the Bcc: header if and only if there are other
+ valid recipient headers (To:, Cc: or Apparently-To:, the
+ last being a historic botch, of course). If Bcc: is the
+ only recipient header in the message, it's value is tossed,
+ but the header name is kept. The old behaviour (always keep
+ the header name and toss the value) allowed primary recipients
+ to see that a Bcc: went to _someone_.
+ Include queue id on ``Authentication-Warning: <host>: <user> set
+ sender to <addresss> using -f'' syslog messages. Suggested
+ by Kari Hurtta.
+ If a sequence or switch map lookup entry gets a tempfail but then
+ continues on to another map type, but the name is not found,
+ return a temporary failure from the sequence or switch map.
+ For example, if hosts search ``dns files'' and DNS fails
+ with a tempfail, the hosts map will go on and search files,
+ but if it fails the whole thing should be a tempfail, not
+ a permanent (host unknown) failure, even though that is the
+ failure in the hosts.files map. This error caused hard
+ bounces when it should have requeued.
+ Aliases to files such as /users/bar/foo/inbox, with /users/bar/foo
+ owned by bar mode 700 and inbox being setuid bar stopped
+ working properly due to excessive paranoia. Pointed out by
+ John Hawkinson of Panix.
+ An SMTP RCPT command referencing a host that gave a nameserver
+ timeout would return a 451 command (8.6 accepted it and
+ queued it locally). Revert to the 8.6 behaviour in order
+ to simplify queue management for clustered systems. Suggested
+ by Gregory Neil Shapiro of WPI. The same problem could break
+ MH, which assumes that the SMTP session will succeed (tsk, tsk
+ -- mail gets lost!); this was pointe dout by Stuart Pook of
+ Infobiogen.
+ Fix possible buffer overflow in munchstring(). This was not a security
+ problem because you couldn't specify any argument to this
+ without first giving up root privileges, but it is still a
+ good idea to avoid future problems. Problem noted by John
+ Hawkinson and Sam Hartman of MIT.
+ ``452 Out of disk space for temp file'' messages weren't being
+ printed. Fix from David Perlin of Nanosoft.
+ Don't advertise the ESMTP DSN extension if the SendMIMEErrors option
+ is not set, since this is required to get the actual DSNs
+ created. Problem pointed out by John Gardiner Myers of CMU.
+ Log permission problems that cause .forward and :include: files to
+ be untrusted or ignored on log level 12 and higher. Suggestted
+ by Randy Martin of Clemson University.
+ Allow user ids in U= clauses of M lines to have hyphens and
+ underscores.
+ Fix overcounting of recipients -- only happened when sending to an
+ alias. Pointed out by Mark Andrews of SGI and Jack Woolley
+ of Systems and Computer Technology Corporation.
+ If a message is sent to an address that fails, the error message that
+ is returned could show some extraneous "success" information
+ included even if the user did not request success notification,
+ which was confusing. Pointed out by Allan Johannesen of WPI.
+ Config files that had no AliasFile definition were defaulting to
+ using /etc/aliases; this caused problems with nullclient
+ configurations. Change it back to the 8.6 semantics of
+ having no local alias file unless it is declared. Problem
+ noted by Charles Karney of Princeton University.
+ Fix compile problem if NOTUNIX is defined. Pointed out by Bryan
+ Costales of ICSI.
+ Map lookups of class "userdb" maps were always case sensitive; they
+ should be controlled by the -f flag like other maps. Pointed
+ out by Bjart Kvarme <bjart.kvarme@usit.uio.no>.
+ Fix problem that caused some addresses to be passed through ruleset 5
+ even when they were tagged as "sticky" by prefixing the
+ address with an "@". Patch from Thomas Dwyer III of Michigan
+ Technological University.
+ When converting a message to Quoted-Printable, prevent any lines with
+ dots alone on a line by themselves. This is because of the
+ preponderence of broken mailers that still get this wrong.
+ Code contributed by Per Hedeland of Ericsson.
+ Fix F{macro}/file construct -- it previously did nothing. Pointed
+ out by Bjart Kvarme of USIT/UiO (Norway).
+ Announce whether a cached connection is SMTP or ESMTP (in -v mode).
+ Requested by Allan Johannesen.
+ Delete check for text format of alias files -- it should be legal
+ to have the database format of the alias files without the
+ text version. Problem pointed out by Joe Rhett of Navigist,
+ Inc.
+ If "Ot" was specified with no value, the TZ variable was not properly
+ imported from the environment. Pointed out by Frank Crawford
+ <frank@ansto.gov.au>.
+ Some architectures core dumped on "program" maps that didn't have
+ extra arguments. Patch from Booker C. Bense of Stanford
+ University.
+ Queue run processes would re-spawn daemons when given a SIGHUP; only
+ the parent should do this. Fix from Brian Coan of the
+ Association for Progressive Communications.
+ If MinQueueAge was set and a message was considered but not run
+ during a queue run and the Timeout.queuereturn interval was
+ reached, a "timed out" error message would be returned that
+ didn't include the failed address (and claimed to be a warning
+ even though it was fatal). The fix is to not return such
+ messages until they are actually tried, i.e., in the next
+ MinQueueAge interval. Problem noted by Rein Tollevik of
+ SINTEF RUNIT, Oslo.
+ Add HES_GETMAILHOST compile flag to support MIT Hesiod distributions
+ that have the hes_getmailhost() routine. DEC Hesiod
+ distributions do not have this routine. Based on a patch
+ from Betty Lee of Stanford University.
+ PORTABILITY FIXES:
+ Solaris: Change location of newaliases and mailq from
+ /usr/ucb to /usr/bin to match Sun settings. From
+ James B. Davis of TCI.
+ DomainOS: Makefile.DomainOS doesn't require -ldbm. From
+ Don Lewis of Silicon Systems.
+ HP-UX 10: rename Makefile.HP-UX.10 => Makefile.HP-UX.10.x
+ so that the makesendmail script will find it. Pointed
+ out by Richard Allen of the University of Iceland.
+ Also, use -Aa -D_HPUX_SOURCE instead of -Ae, which
+ isn't supported on all compilers.
+ UXPDS: compilation fixes from Diego R. Lopez.
+ CONFIG: FAX mailer wasn't setting .FAX as a pseudo-domain unless
+ you also had a FAX_RELAY. From Thomas.Tornblom@Hax.SE.
+ CONFIG: Minor glitch in S21 -- attachment of local domain name
+ didn't have trailing dot. From Jim Hickstein of Teradyne.
+ CONFIG: Fix best_mx_is_local feature to allow nested addresses such as
+ user%host@thishost. From Claude Scarpelli of Infobiogen
+ (France).
+ CONFIG: OSTYPE(hpux10) failed to define the location of the help file.
+ Pointed out by Hannu Martikka of Nokia Telecommunications.
+ CONFIG: Diagnose some inappropriate ordering in configuration files,
+ such as FEATURE(smrsh) listed after MAILER(local). Based on
+ a bug report submitted by Paul Hoffman of Proper Publishing.
+ CONFIG: Make OSTYPE files consistently not override settings that
+ have already been set. Previously it worked differently
+ for different files.
+ CONFIG: Change relay mailer to do masquerading like 8.6 did. My take
+ is that this is wrong, but the change was causing problems
+ for some people. From Per Hedeland of Ericsson.
+ CONTRIB: bitdomain.c patch from John Gardiner Myers <jgm+@CMU.EDU>;
+ portability changes for Posix environments (no functional
+ changes).
+
+8.7.1/8.7.1 95/10/01
+ Old macros that have become options (SmtpGreetingMessage,
+ OperatorChars, and UnixFromLine) didn't allow backslash
+ escapes in the options, where they previously had. Bug
+ pointed out by John Hawkinson of MIT.
+ Fix strange case of an executable called by a program map that
+ returns a value but also a non-zero exit status; this
+ would give contradictory results in the higher level; in
+ particular, the default clause in the map lookup would be
+ ignored. Change to ignore the value if the program returns
+ non-zero exit status. From Tom Moore of AT&T GIS.
+ Shorten parameters passed to syslog() in some contexts to avoid a
+ bug in many vendors' implementations of that routine. Although
+ this isn't really a bug in sendmail per se, and my solution
+ has to assume that syslog() has at least a 1K buffer size
+ internally (I know some vendors have shortened this
+ dramatically -- they're on their own), sendmail is a popular
+ target. Also, limit the size of %s arguments in sprintf.
+ These both have possible security implications. Solutions
+ suggested by Casper Dik of Sun's Network Security Group
+ (Holland), Mark Seiden, and others.
+ Fix a problem that might cause a non-standard -B (body type)
+ parameter to be passed to the next server with undefined
+ results. This could have security implications.
+ If a filesystem was at > 100% utilization, the freediskspace()
+ routine incorrectly returned an error rather than zero.
+ Problem noted by G. Paul Ziemba of Alantec.
+ Change MX sort order so that local hostnames (those in $=w) always
+ sort first within a given preference. This forces the bestmx
+ map to always return the local host first, if it is included
+ in the list of highest priority MX records. From K. Robert
+ Elz.
+ Avoid some possible null pointer dereferences. Fixes from Randy
+ Martin <WOLF@CLEMSON.EDU>
+ When sendmail starts up on systems that have no fully qualified
+ domain name (FQDN) anywhere in the first matching host map
+ (e.g., /etc/hosts if the hosts service searches "files dns"),
+ sendmail would sleep to try to find a FQDN, which it really
+ really needs. This has been changed to fall through to the
+ next map type if it can't find a FQDN -- i.e., if the hosts
+ file doesn't have a FQDN, it will try dns even though the
+ short name was found in /etc/hosts. This is probably a crock,
+ but many people have hosts files without FQDNs. Remember:
+ domain names are your friends.
+ Log a high-priority message if you can't find your FQDN during startup.
+ Suggested by Simon Barnes of Schlumberger Limited.
+ When using Hesiod, initialize it early to improve error reporting.
+ Patch from Don Lewis of Silicon Systems, Inc.
+ Apparently at least some versions of Linux have a 90 !minute! TCP
+ connection timeout in the kernel. Add a new "connect" timeout
+ to limit this time. Defaults to zero (use whatever the
+ kernel provides). Based on code contributed by J.R. Oldroyd
+ of TerraNet.
+ Under some circumstances, a failed message would not be properly
+ removed from the queue, causing tons of bogus error messages.
+ (This fix eliminates the problematic EF_KEEPQUEUE flag.)
+ Problem noted by Allan E Johannesen and Gregory Neil Shapiro
+ of WPI.
+ PORTABILITY FIXES:
+ On IRIX 5.x, there was an inconsistency in the setting
+ of sendmail.st location. Change the Makefile to
+ install it in /var/sendmail.st to match the OSTYPE
+ file and SGI standards. From Andre
+ <andre@curry.zfe.siemens.de>.
+ Support for Fujitsu/ICL UXP/DS (For the DS/90 Series)
+ from Diego R. Lopez <drlopez@cica.es>.
+ Linux compilation patches from J.R. Oldroyd of TerraNet, Inc.
+ LUNA 2 Mach patches from Motonori Nakamura.
+ SunOS Makefile was including -ldbm, which is for the old
+ dbm library. The ndbm library is part of libc.
+ CONFIG: avoid bouncing ``user@host.'' (note trailing dot) with
+ ``local configuration error'' in nullclient configuration.
+ Patch from Gregory Neil Shapiro of WPI.
+ CONFIG: don't allow an alias file in nullclient configurations --
+ since all addresses are relayed, they give errors during
+ rebuild. Suggested by Per Hedeland of Ericsson.
+ CONFIG: local mailer on Solaris 2 should always get a -f flag because
+ otherwise the F=S causes the From_ line to imply that root is
+ the sender. Problem pointed out by Claude Scarpelli of
+ Infobiogen (France).
+ NEW FILES:
+ cf/feature/use_ct_file.m4 (omitted from 8.7 by mistake)
+ src/Makefiles/Makefile.KSR (omitted from 8.7 by mistake)
+ src/Makefiles/Makefile.UXPDS
+
+8.7/8.7 95/09/16
+ Fix a problem that could cause sendmail to run out of file
+ descriptors due to a trashed data structure after a
+ vfork. Fix from Brian Coan of the Institute for
+ Global Communications.
+ Change the VRFY response if you have disabled VRFY -- some
+ people seemed to think that it was too rude.
+ Avoid reference to uninitialized file descriptor if HASFLOCK
+ was not defined. This was used "safely" in the sense
+ that it only did a stat, but it would have set the
+ map modification time improperly. Problem pointed out
+ by Roy Mongiovi of Georgia Tech.
+ Clean up the Subject: line on warning messages and return
+ receipts so that they don't say "Returned mail:"; this
+ can be confusing.
+ Move ruleset entry/exit debugging from 21.2 to 21.1 -- this is
+ useful enough to make it worthwhile printing on "-d".
+ Avoid logging alias statistics every time you read the alias
+ file on systems with no database method compiled in.
+ If you have a name with a trailing dot, and you try looking it
+ up using gethostbyname without the dot (for /etc/hosts
+ compatibility), be sure to turn off RES_DEFNAMES and
+ RES_DNSRCH to avoid finding the wrong name accidently.
+ Problem noted by Charles Amos of the University of
+ Maryland.
+ Don't do timeouts in collect if you are not running SMTP.
+ There is nothing that says you can't have a long
+ running program piped into sendmail (possibly via
+ /bin/mail, which just execs sendmail). Problem reported
+ by Don "Truck" Lewis of Silicon Systems.
+ Try gethostbyname() even if the DNS lookup fails iff option I
+ is not set. This allows you to have hosts listed in
+ NIS or /etc/hosts that are not known to DNS. It's normally
+ a bad idea, but can be useful on firewall machines. This
+ should really be broken out on a separate flag, I suppose.
+ Avoid compile warnings against BIND 4.9.3, which uses function
+ prototypes. From Don Lewis of Silicon Systems.
+ Avoid possible incorrect diagnosis of DNS-related errors caused
+ by things like attempts to resolve uucp names using
+ $[ ... $] -- the fix is to clear h_errno at appropriate
+ times. From Kyle Jones of UUNET.
+ SECURITY: avoid denial-of-service attacks possible by destroying
+ the alias database file by setting resource limits low.
+ This involves adding two new compile-time options:
+ HASSETRLIMIT (indicating that setrlimit(2) support is
+ available) and HASULIMIT (indicating that ulimit(2) support
+ is available -- the Release 3 form is used). The former
+ is assumed on BSD-based systems, the latter on System
+ V-based systems. Attack noted by Phil Brandenberger of
+ Swarthmore University.
+ New syntaxes in test (-bt) mode:
+ ``.Dmvalue'' will define macro "m" to "value".
+ ``.Ccvalue'' will add "value" to class "c".
+ ``=Sruleset'' will dump the contents of the indicated
+ ruleset.
+ ``=M'' will display the known mailers.
+ ``-ddebug-spec'' is equivalent to the command-line
+ -d debug flag.
+ ``$m'' will print the value of macro $m.
+ ``$=c'' will print the contents of class $=c.
+ ``/mx host'' returns the MX records for ``host''.
+ ``/parse address'' will parse address, returning the value of
+ crackaddr (essentially, the comment information)
+ and the parsed address (the same as -bv).
+ ``/try mailer address'' will rewrite address into the form
+ it will have when presented to the indicated mailer.
+ ``/tryflags flags'' will set flags used by parsing. The
+ flags can be `H' for header or `E' for envelope,
+ and `S' for sender or `R' for recipient. These
+ can be combined, so `HR' sets flags for header
+ recipients.
+ ``/canon hostname'' will try to canonify hostname and
+ return the result.
+ ``/map mapname key'' will look up `key' in the indicated
+ `mapname' and return the result.
+ Somewhat better handling of UNIX-domain socket addresses -- it
+ should show the pathname rather than hex bytes.
+ Restore ``-ba'' mode -- this reads a file from stdin and parses
+ the header for envelope sender information and uses
+ CR-LF as message terminators. It was thought to be
+ obsolete (used only for Arpanet NCP protocols), but it
+ turns out that the UK ``Grey Book'' protocols require
+ that functionality.
+ Fix a fix in previous release -- if gethostname and gethostbyname
+ return a name without dots, and if an attempt to canonify
+ that name fails, wait one minute and try again. This can
+ result in an extra 60 second delay on startup if your system
+ hostname (as returned by hostname(1)) has no dot and no names
+ listed in /etc/hosts or your NIS map have a dot.
+ Check for proper domain name on HELO and EHLO commands per
+ RFC 1123 section 5.2.5. Problem noted by Thomas Dwyer III
+ of Michigan Technological University.
+ Relax chownsafe rules slightly -- old version said that if you
+ can't tell if _POSIX_CHOWN_RESTRICTED is set (that is,
+ if fpathconf returned EINVAL or ENOSYS), assume that
+ chown is not safe. The new version falls back to whether
+ you are on a BSD system or not. This is important for
+ SunOS, which apparently always returns one of those
+ error codes. This impacts whether you can mail to files
+ or not.
+ Syntax errors such as unbalanced parentheses in the configuration
+ file could be omitted if you had "Oem" prior to the
+ syntax error in the config file. Change to always print
+ the error message. It was especially wierd because it
+ would cause a "warning" message to be sent to the Postmaster
+ for every message sent (but with no transcript). Problem
+ noted by Gregory Paris of Motorola.
+ Rewrite collect and putbody to handle full 8-bit data, including
+ zero bytes. These changes are internally extensive, but
+ should have minimal impact on external function.
+ Allow full words for option names -- if the option letter is
+ (apparently) a space, then take the word following -- e.g.,
+ O MatchGECOS=TRUE
+ The full list of old and new names is as follows:
+ 7 SevenBitInput
+ 8 EightBitMode
+ A AliasFile
+ a AliasWait
+ B BlankSub
+ b MinFreeBlocks/MaxMessageSize
+ C CheckpointInterval
+ c HoldExpensive
+ D AutoRebuildAliases
+ d DeliveryMode
+ E ErrorHeader
+ e ErrorMode
+ f SaveFromLine
+ F TempFileMode
+ G MatchGECOS
+ H HelpFile
+ h MaxHopCount
+ i IgnoreDots
+ I ResolverOptions
+ J ForwardPath
+ j SendMimeErrors
+ k ConnectionCacheSize
+ K ConnectionCacheTimeout
+ L LogLevel
+ l UseErrorsTo
+ m MeToo
+ n CheckAliases
+ O DaemonPortOptions
+ o OldStyleHeaders
+ P PostmasterCopy
+ p PrivacyOptions
+ Q QueueDirectory
+ q QueueFactor
+ R DontPruneRoutes
+ r, T Timeout
+ S StatusFile
+ s SuperSafe
+ t TimeZoneSpec
+ u DefaultUser
+ U UserDatabaseSpec
+ V FallbackMXhost
+ v Verbose
+ w TryNullMXList
+ x QueueLA
+ X RefuseLA
+ Y ForkEachJob
+ y RecipientFactor
+ z ClassFactor
+ Z RetryFactor
+ The old macros that passed information into sendmail have
+ been changed to options; those correspondences are:
+ $e SmtpGreetingMessage
+ $l UnixFromLine
+ $o OperatorChars
+ $q (deleted -- not necessary)
+ To avoid possible problems with an older sendmail,
+ configuration level 6 is accepted by this version of
+ sendmail; any config file using the new names should
+ specify "V6" in the configuration.
+ Change address parsing to properly note that a phrase before a
+ colon and a trailing semicolon are essentially the same
+ as text outside of angle brackets (i.e., sendmail should
+ treat them as comments). This is to handle the
+ ``group name: addr1, addr2, ..., addrN;'' syntax (it will
+ assume that ``group name:'' is a comment on the first
+ address and the ``;'' is a comment on the last address).
+ This requires config file support to get right. It does
+ understand that :: is NOT this syntax, and can be turned
+ off completely by setting the ColonOkInAddresses option.
+ Level 6 config files added with new mailer flags:
+ A Addresses are aliasable.
+ i Do udb rewriting on envelope as well as header
+ sender lines. Applies to the from address mailer
+ flags rather than the recipient mailer flags.
+ j Do udb rewriting on header recipient addresses.
+ Applies to the sender mailer flags rather than the
+ recipient mailer flags.
+ k Disable check for loops when doing HELO command.
+ o Always run as the mail recipient, even on local
+ delivery.
+ w Check for an /etc/passwd entry for this user.
+ 5 Pass addresses through ruleset 5.
+ : Check for :include: on this address.
+ | Check for |program on this address.
+ / Check for /file on this address.
+ @ Look up sender header addresses in the user
+ database. Applies to the mailer flags for the
+ mailer corresponding to the envelope sender
+ address, rather than to recipient mailer flags.
+ Pre-level 6 configuration files set A, w, 5, :, |, /, and @
+ on the "local" mailer, the o flag on the "prog" and "*file*"
+ mailers, and the ColonOkInAddresses option.
+ Eight-to-seven bit MIME conversions. This borrows ideas from
+ John Beck of Hewlett-Packard, who generously contributed
+ their implementation to me, which I then didn't use (see
+ mime.c for an explanation of why). This adds the
+ EightBitMode option (a.k.a. `8') and an F=8 mailer flag
+ to control handling of 8-bit data. These have to cope with
+ two types of 8-bit data: unlabelled 8-bit data (that is,
+ 8-bit data that is entered without declaring it as 8-bit
+ MIME -- technically this is illegal according to the
+ specs) and labelled 8-bit data (that is, it was declared
+ as 8BITMIME in the ESMTP session or by using the
+ -B8BITMIME command line flag). If the F=8 mailer flag is
+ set then 8-bit data is sent to non-8BITMIME machines
+ instead of converting to 7 bit (essentially using
+ just-send-8 semantics). The values for EightBitMode are:
+ m convert unlabelled 8-bit input to 8BITMIME, and do
+ any necessary conversion of 8BITMIME to 7BIT
+ (essentially, the full MIME option).
+ p pass unlabelled 8-bit input, but convert labelled
+ 8BITMIME input to 7BIT as required (default).
+ s strict adherence: reject unlabelled 8-bit input,
+ convert 8BITMIME to 7BIT as required. The F=8
+ flag is ignored.
+ Unlabelled 8-bit data is rejected in mode `s' regardless of
+ the setting of F=8.
+ Add new internal class 'n', which is the set of MIME Content-Types
+ which can not be 8 to 7 bit encoded because of other
+ considerations. Types "multipart/*" and "message/*" are
+ never directly encoded (although their components can be).
+ Add new internal class 's', which is the set of subtypes of the
+ MIME message/* content type that can be treated as though
+ they are an RFC822 message. It is predefined to have
+ "rfc822". Suggested By Kari Hurtta.
+ Add new internal class 'e'. This is the set of MIME
+ Content-Transfer-Encodings that can be converted to
+ a seven bit format (Quoted-Printable or Base64). It is
+ preinitialized to contain "7bit", "8bit", and "binary".
+ Add C=charset mailer parameter and the the DefaultCharSet option (no
+ short name) to set the default character set to use in the
+ Content-Type: header when doing encoding of an 8-bit message
+ which isn't marked as MIME into MIME format. If the C=
+ parameter is set on the Envelope From address, use that as
+ the default encoding; else use the DefaultCharSet option.
+ If neither is set, it defaults to "unknown-8bit" as
+ suggested by RFC 1428 section 3.
+ Allow ``U=user:group'' field in mailer definition to set a default
+ user and group that a mailer will be executed as. This
+ overrides the 'u' and 'g' options, and if the `F=S' flag is
+ also set, it is the uid/gid that will always be used (that
+ is, the controlling address is ignored). The values may be
+ numeric or symbolic; if only a symbolic user is given (no
+ group) that user's default group in the passwd file is used
+ as the group. Based on code donated by Chip Rosenthal of
+ Unicom.
+ Allow `u' option to also accept user:group as a value, in the same
+ fashion as the U= mailer option.
+ Add the symbolic time zone name in the Arpanet format dates (as
+ a comment). This adds a new compile-time configuration
+ flag: TZ_TYPE can be set to TZ_TM_NAME (use the value
+ of (struct tm *)->tm_name), TZ_TM_ZONE (use the value
+ of (struct tm *)->tm_zone), TZ_TZNAME (use extern char
+ *tzname[(struct tm *)->tm_isdst]), TZ_TIMEZONE (use
+ timezone()), or TZ_NONE (don't include the comment). Code
+ from Chip Rosenthal.
+ The "Timeout" option (formerly "r") is extended to allow suboptions.
+ For example,
+ O Timeout.helo = 2m
+ There are also two new suboptions "queuereturn" and
+ "queuewarn"; these subsume the old T option. Thus, to
+ set them both the preferred new syntax is
+ O Timeout.queuereturn = 5d
+ O Timeout.queuewarn = 4h
+ Sort queue by host name instead of by message priority if the
+ QueueSortOrder option (no short name) is set is set to
+ ``host''. This makes better use of the connection cache,
+ but may delay more ``interactive'' messages behind large
+ backlogs under some circumstances. This is probably a
+ good option if you have high speed links or don't do lots
+ of ``batch'' messages, but less good if you are using
+ something like PPP on a 14.4 modem. Based on code
+ contributed by Roy Mongiovi of Georgia Tech (my main
+ contribution was to make it configurable).
+ Save i-number of df file in qf file to simplify rebuilding of queue
+ after disasterous disk crash. Suggested by Kyle Jones of
+ UUNET; closely based on code from KJS DECWRL code written
+ by Paul Vixie. NOTA BENE: The qf files produced by 8.7
+ are NOT back compatible with 8.6 -- that is, you can convert
+ from 8.6 to 8.7, but not the other direction.
+ Add ``F=d'' mailer flag to disable all use of angle brackets in
+ route-addrs in envelopes; this is because in some cases
+ they can be sent to the shell, which interprets them as
+ I/O redirection.
+ Don't include error file (option E) with return-receipts; this
+ can be confusing.
+ Don't send "Warning: cannot send" messages to owner-* or
+ *-request addresses. Suggested by Christophe Wolfhugel
+ of the Institut Pasteur, Paris.
+ Allow -O command line flag to set long form options.
+ Add "MinQueueAge" option to set the minimum time between attempts
+ to run the queue. For example, if the queue interval
+ (-q value) is five minutes, but the minimum queue age
+ is fifteen minutes, jobs won't be tried more often than
+ once every fifteen minutes. This can be used to give
+ you more responsiveness if your delivery mode is set to
+ queue-only.
+ Allow "fileopen" timeout (default: 60 seconds) for opening
+ :include: and .forward files.
+ Add "-k", "-v", and "-z" flags to map definitions; these set the
+ key field name, the value field name, and the field
+ delimiter. The field delimiter can be a single character
+ or the sequence "\t" or "\n" for tab or newline.
+ These are for use by NIS+ and similar access methods.
+ Change maps to always strip quotes before lookups; the -q flag
+ turns off this behaviour. Suggested by Motonori Nakamura.
+ Add "nisplus" map class. Takes -k and -v flags to choose the
+ key and value field names respectively. Code donated by
+ Sun Microsystems.
+ Add "hesiod" map class. The "file name" is used as the
+ "HesiodNameType" parameter to hes_resolve(3). Returns the
+ first value found for the match. Code donated by Scott
+ Hutton of Indiana University.
+ Add "netinfo" (NeXT NetInfo) map class. Maps can have a -k flag to
+ specify the name of the property that is searched as the
+ key and a -v flag to specify the name of the property that
+ is returned as the value (defaults to "members"). The
+ default map is "/aliases". Some code based on code
+ contributed by Robert La Ferla of Hot Software.
+ Add "text" map class. This does slow, linear searches through
+ text files. The -z flag specifies a column delimiter
+ (defaults to any sequence of white space), the -k flag
+ sets the key column number, and the -v flag sets the
+ value column number. Lines beginning with `#' are treated
+ as comments.
+ Add "program" map class to execute arbitrary programs. The search
+ key is presented as the last argument; the output is one
+ line read from the programs standard output. Exit statuses
+ are from sysexits.h.
+ Add "sequence" map class -- searches maps in sequence until it
+ finds a match. For example, the declarations:
+ Kmap1 ...
+ Kmap2 ...
+ Kmapseq sequence map1 map2
+ defines a map "mapseq" that first searches map1; if the
+ value is found it is returned immediately, otherwise
+ map2 is searched and the value returned.
+ Add "switch" map class. This is much like "sequence" except that
+ the ordering is fetched from an external file, usually
+ the system service switch. The parameter is the name of
+ the service to switch on, and the maps that it will use
+ are the name of the switch map followed by ".service_type".
+ For example, if the declaration of the map is
+ Ksample switch hosts
+ and the system service switch specifies that hosts are
+ looked up using dns and nis in that order, then this is
+ equivalent to
+ Ksample sequence sample.dns sample.nis
+ The subordinate maps (sample.*) must already be defined.
+ Add "user" map class -- looks up users using getpwnam. Takes a
+ "-v field" flag on the definition that tells what passwd
+ entry to return -- legal values are name, passwd, uid, gid,
+ gecos, dir, and shell. Generally expected to be used with
+ the -m (matchonly) flag.
+ Add "bestmx" map class -- returns the best MX value for the host
+ listed as the value. If there are several "best" MX records
+ for this host, one will be chosen at random.
+ Add "userdb" map class -- looks up entries in the user database.
+ The "file name" is actually the tag that will be used,
+ typically "mailname". If there are multiple entries
+ matching the name, the one chosen is undefined.
+ Add multiple queue timeouts (both return and warning). These are
+ set by the Precedence: or Priority: header fields to one of
+ three values. If a Priority: is set and has value "normal",
+ "urgent", or "non-urgent" the corresponding timeouts are
+ used. If no priority is set, the Precedence: is consulted;
+ if negative, non-urgent timeouts are used; if greater than
+ zero, urgent timeouts are used. Otherwise, normal timeouts
+ are used. The timeouts are set by setting the six timeouts
+ queue{warn,return}.{urgent,normal,non-urgent}.
+ Fix problem when a mail address is resolved to a $#error mailer
+ with a temporary failure indication; it works in SMTP,
+ but when delivering locally the mail is silently discarded.
+ This patch, from Kyle Jones of UUNET, bounces it instead
+ of queueing it (queueing is very hard).
+ When using /etc/hosts or NIS-style lookups, don't assume that
+ the first name in the list is the best one -- instead,
+ search for the first one with a dot. For example, if
+ an /etc/hosts entry reads
+ 128.32.149.68 mammoth mammoth.CS.Berkeley.EDU
+ this change will use the second name as the canonical
+ machine name instead of the initial, unqualified name.
+ Change dequote map to replace spaces in quoted text with a value
+ indicated by the -s flag on the dequote map definition.
+ For example, ``Mdequote dequote -s_'' will change
+ "Foo Bar" into an unquoted Foo_Bar instead of leaving it
+ quoted (because of the space character). Suggested by Dan
+ Oscarsson for use in X.400 addresses.
+ Implement long macro names as ${name}; long class names can
+ be similarly referenced as $={name} and $~{name}.
+ Definitions are (e.g.) ``D{name}value''. Names that have
+ a leading lower case letter or punctuation characters are
+ reserved for internal use by sendmail; i.e., config files
+ should use names that begin with a capital letter. Based
+ on code contributed by Dan Oscarsson.
+ Fix core dump if getgrgid returns a null group list (as opposed
+ to an empty group list, that is, a pointer to a list
+ with no members). Fix from Andrew Chang of Sun Microsystems.
+ Fix possible core dump if malloc fails -- if the malloc in xalloc
+ failed, it called syserr which called newstr which called
+ xalloc.... The newstr is now avoided for "panic" messages.
+ Reported by Stuart Kemp of James Cook University.
+ Improve connection cache timeouts; previously, they were not even
+ checked if you were delivering to anything other than an
+ IPC-connected host, so a series of (say) local mail
+ deliveries could cause cached connections to be open
+ much longer than the specified timeout.
+ If an incoming message exceeds the maximum message size, stop
+ writing the incoming bytes to the queue data file, since
+ this can fill your mqueue partition -- this is a possible
+ denial-of-service attack.
+ Don't reject all numeric local user names unless HESIOD is
+ defined. It turns out that Posix allows all-numeric
+ user names. Fix from Tony Sanders of BSDI.
+ Add service switch support. If the local OS has a service
+ switch (e.g., /etc/nsswitch.conf on Solaris or /etc/svc.conf
+ on DEC systems) that will be used; otherwise, it falls back
+ to using a local mechanism based on the ServiceSwitchFile
+ option (default: /etc/service.switch). For example, if the
+ service switch lists "files" and "nis" for the aliases
+ service, that will be the default lookup order. the "files"
+ ("local" on DEC) service type expands to any alias files
+ you listed in the configuration file, even if they aren't
+ actually file lookups.
+ Option I (NameServerOptions) no longer sets the "UseNameServer"
+ variable which tells whether or not DNS should be considered
+ canonical. This is now determined based on whether or not
+ "dns" is in the service list for "hosts".
+ Add preliminary support for the ESMTP "DSN" extension (Delivery
+ Status Notifications). DSN notifications override
+ Return-Receipt-To: headers, which are bogus anyhow.
+ Add T=mts-name-type/address-type/diagnostic-type keyletter to mailer
+ definitions to define the types used in DSN returns for
+ MTA names, addresses, and diagnostics respectively.
+ Extend heuristic to force running in ESMTP mode to look for the
+ five-character string "ESMTP" anywhere in the 220 greeting
+ message (not just the second line). This is to provide
+ better compatibility with other ESMTP servers.
+ Print sequence number of job when running the queue so you can
+ easily see how much progress you have made. Suggested
+ by Peter Wemm of DIALix.
+ Map newlines to spaces in logged message-ids; some versions of
+ syslog truncate the rest of the line after newlines.
+ Suggested by Fletcher Mattox of U. Texas.
+ Move up forking for job runs so that if a message is split into
+ multiple envelopes you don't get "fork storms" -- this
+ also improves the connection cache utilization.
+ Accept "<<>>", "<<<>>>", and so forth as equivalent to "<>" for
+ the purposes of refusing to send error returns. Suggested
+ by Motonori Nakamura of Ritsumeikan University.
+ Relax rules on when a file can be written when referenced from
+ the aliases file: use the default uid/gid instead of the
+ real uid/gid. This allows you to create a file owned by
+ and writable only by the default uid/gid that will work
+ all the time (without having the setuid bit set). Change
+ suggested by Shau-Ping Lo and Andrew Cheng of Sun
+ Microsystems.
+ Add "DialDelay" option (no short name) to provide an "extra"
+ delay for dial on demand systems. If this is non-zero
+ and a connect fails, sendmail will wait this long and
+ then try again. If it takes longer than the kernel
+ timeout interval to establish the connection, this
+ option can give the network software time to establish
+ the link. The default units are seconds.
+ Move logging of sender information to be as early as possible;
+ previously, it could be delayed a while for SMTP mail
+ sent to aliases. Suggested by Brad Knowles of the
+ Defense Information Systems Agency.
+ Call res_init() before setting RES_DEBUG; this is required by
+ BIND 4.9.3, or so I'm told. From Douglas Anderson of
+ the National Computer Security Center.
+ Add xdelay= field in logs -- this is a transaction delay, telling
+ you how long it took to deliver to this address on the
+ last try. It is intended to be used for sorting mailing
+ lists to favor "quick" addresses. Provided for use by
+ the mailprio scripts (see below).
+ If a map cannot be opened, and that map is non-optional, and
+ an address requires that map for resolution, queue the
+ map instead of bouncing it. This involves creating a
+ pseudo-class of maps called "bogus-map" -- if a required
+ map cannot be opened, the class is changed to bogus-map;
+ all queries against bogus-map return "tempfail". The
+ bogus-map class is not directly accessible. A sample
+ implementation was donated by Jem Taylor of Glasgow
+ University Computing Service.
+ Fix a possible core dump when mailing to a program that talks
+ SMTP on its standard input. Fix from Keith Moore of
+ the University of Kentucky.
+ Make it possible to resolve filenames to $#local $: @ /filename;
+ previously, the "@" would cause it to not be recognized
+ as a file. Problem noted by Brian Hill of U.C. Davis.
+ Accept a -1 signal to re-exec the daemon. This only works if
+ argv[0] is a full path to sendmail.
+ Fix bug in "addr=..." field in O option on little-endian machines
+ -- the network number wasn't being converted to network
+ byte order. Patch from Kurt Lidl of Pix Technologies
+ Corporation.
+ Pre-initialize the resolver early on; this is to avoid a bug with
+ BIND 4.9.3 that can cause the _res.retry field to get
+ reset to zero, causing all name server lookups to time
+ out. Fix from Matt Day of Artisoft.
+ Restore T line (trusted users) in config file -- but instead of
+ locking out the -f flag, they just tell whether or not
+ an X-Authentication-Warning: will be added. This really
+ just creates new entries in class 't', so "Ft/file/name"
+ can be used to read trusted user names from a file.
+ Trusted users are also allowed to execute programs even
+ if they have a shell that isn't in /etc/shells.
+ Improve NEWDB alias file rebuilding so it will create them
+ properly if they do not already exist. This had been
+ a MAYBENEXTRELEASE feature in 8.6.9.
+ Check for @:@ entry in NIS maps before starting up to avoid
+ (but not prevent, sigh) race conditions. This ought to
+ be handled properly in ypserv, but isn't. Suggested by
+ Michael Beirne of Motorola.
+ Refuse connections if there isn't enough space on the filesystem
+ holding the queue. Contributed by Robert Dana of Wolf
+ Communications.
+ Skip checking for directory permissions in the path to a file
+ when checking for file permissions iff setreuid()
+ succeeded -- it is unnecessary in that case. This avoids
+ significant performance problems when looking for .forward
+ files. Based on a suggestion by Win Bent of USC.
+ Allow symbolic ruleset names. Syntax can be "Sname" to get an
+ arbitrary ruleset number assigned or "Sname = integer"
+ to assign a specific ruleset number. Reference is
+ $>name_or_number. Names can be composed of alphas, digits,
+ underscore, or hyphen (first character must be non-numeric).
+ Allow -o flag on AliasFile lines to make the alias file optional.
+ From Bryan Costales of ICSI.
+ Add NoRecipientAction option to handle the case where there is
+ no legal recipient header in the message. It can take
+ on values:
+ None Leave the message as is. The
+ message will be passed on even
+ though it is in technically
+ illegal syntax.
+ Add-To Add a To: header with any
+ recipients that it can find from
+ the envelope. This risks exposing
+ Bcc: recipients.
+ Add-Apparently-To Add an Apparently-To: header. This
+ has almost no redeeming social value,
+ and is provided only for back
+ compatibility.
+ Add-To-Undisclosed Add a header reading
+ To: undisclosed-recipients:;
+ which will have the effect of
+ making the message legal without
+ exposing Bcc: recipients.
+ Add-Bcc To add an empty Bcc: header.
+ There is a chance that mailers down
+ the line will delete this header,
+ which could cause exposure of Bcc:
+ recipients.
+ The default is NoRecipientAction=None.
+ Truncate (rather than delete) Bcc: lines in the header. This
+ should prevent later sendmails (at least, those that don't
+ themselves delete Bcc:) from considering this message to
+ be non-conforming -- although it does imply that non-blind
+ recipients can see that a Bcc: was sent, albeit not to whom.
+ Add SafeFileEnvironment option. If declared, files named as delivery
+ targets must be regular files in addition to the regular
+ checks. Also, if the option is non-null then it is used as
+ the name of a directory that is used as a chroot(2)
+ environment for the delivery; the file names listed in an
+ alias or forward should include the name of this root.
+ For example, if you run with
+ O SafeFileEnvironment=/arch
+ then aliases should reference "/arch/rest/of/path". If a
+ value is given, sendmail also won't try to save to
+ /usr/tmp/dead.letter (instead it just leaves the job in the
+ queue as Qfxxxxxx). Inspired by *Hobbit*'s sendmail patch kit.
+ Support -A flag for alias files; this will comma concatenate like
+ entries. For example, given the aliases:
+ list: member1
+ list: member2
+ and an alias file declared as:
+ OAhash:-A /etc/aliases
+ the final alias inserted will be "list: member1,member2";
+ without -A you will get an error on the second and subsequent
+ alias for "list". Contributed by Bryan Costales of ICSI.
+ Line-buffer transcript file. Suggested by Liudvikas Bukys.
+ Fix a problem that could cause very long addresses to core dump in
+ some special circumstances. Problem pointed out by Allan
+ Johannesen.
+ (Internal change.) Change interface to expand() (macro expansion)
+ to be simpler and more consistent.
+ Delete check for funny qf file names. This didn't really give
+ any extra security and caused some people some problems.
+ (If you -really- want this, define PICKY_QF_NAME_CHECK
+ at compile time.) Suggested by Kyle Jones of UUNET.
+ (Internal change.) Change EF_NORETURN to EF_NO_BODY_RETN and
+ merge with DSN code; this is simpler and more consistent.
+ This may affect some people who have written their own
+ checkcompat() routine.
+ (Internal change.) Eliminate `D' line in qf file. The df file
+ is now assumed to be the same name as the qf file (with
+ the `q' changed to a `d', of course).
+ Avoid forking for delivery if all recipient mailers are marked as
+ "expensive" -- this can be a major cost on some systems.
+ Essentially, this forces sendmail into "queue only" mode
+ if all it is going to do is queue anyway.
+ Avoid sending a null message in some rather unusual circumstances
+ (specifically, the RCPT command returns a temporary
+ failure but the connection is lost before the DATA
+ command). Fix from Scott Hammond of Secure Computing
+ Corporation.
+ Change makesendmail to use a somewhat more rational naming scheme:
+ Makefiles and obj directories are named $os.$rel.$arch,
+ where $os is the operating system (e.g., SunOS), $rel is
+ the release number (e.g., 5.3), and $arch is the machine
+ architecture (e.g., sun4). Any of these can be omitted,
+ and anything after the first dot in a release number can
+ be replaced with "x" (e.g., SunOS.4.x.sun4). The previous
+ version used $os.$arch.$rel and was rather less general.
+ Change makesendmail to do a "make depend" in the target directory
+ when it is being created. This involves adding an empty
+ "depend:" entry in most Makefiles.
+ Ignore IDENT return value if the OSTYPE field returns "OTHER",
+ as indicated by RFC 1413. Pointed out by Kari Hurtta
+ of the Finnish Meteorological Institute.
+ Fix problem that could cause multiple responses to DATA command
+ on header syntax errors (e.g., lines beginning with colons).
+ Problem noted by Jens Thomassen of the University of Oslo.
+ Don't let null bytes in headers cause truncation of the rest of
+ the header.
+ Log Authentication-Warning:s. Suggested by Motonori Nakamura.
+ Increase timeouts on message data puts to allow time for receivers
+ to canonify addresses in headers on the fly. This is still
+ a rather ugly heuristic. From Motonori Nakamura.
+ Add "HasWildcardMX" suboption to ResolverOptions; if set, MX
+ records are not used when canonifying names, and when MX
+ lookups are done for addressing they must be fully
+ qualified. This is useful if you have a wildcard MX record,
+ although it may cause other problems. In general, don't use
+ wildcard MX records. Patch from Motonori Nakamura.
+ Eliminate default two-line SMTP greeting message. Instead of
+ adding an extra "ESMTP spoken here" line, the word "ESMTP"
+ is added between the first and second word of the first
+ line of the greeting message (i.e., immediately after the
+ host name). This eliminates the need for the BROKEN_SMTP_PEERS
+ compile flag. Old sendmails won't see the ESMTP, but that's
+ acceptable because SIZE was the only useful extension that
+ old sendmails understand.
+ Avoid gethostbyname calls on UNIX domain sockets during SIGUSR1
+ invoked state dumps. From Masaharu Onishi.
+ Allow on-line comments in .forward and :include: files; they are
+ introduced by the string "<LWSP>#@#<LWSP>", where <LWSP>
+ is a space or a tab. This is intended for native
+ representation of non-ASCII sets such as Japanese, where
+ existing encodings would be unreadable or would lose
+ data -- for example,
+ <motonori@cs.ritsumei.ac.jp> NAKAMURA Motonori
+ (romanized/less information)
+ <motonori@cs.ritsumei.ac.jp> =?ISO-2022-JP?B?GyRCQ2ZCPBsoQg==?=
+ =?ISO-2022-JP?B?GyRCQUdFNRsoQg==?=
+ (with MIME encoding, not human readable)
+ <motonori@cs.ritsumei.ac.jp> #@# ^[$BCfB<^[(B ^[$BAGE5^[(B
+ (native encoding with ISO-2022-JP)
+ The last form is human readable in the Japanese environment.
+ Based on a fix from (surprise!) Motonori Nakamura.
+ Don't make SMTP error returns on MAIL FROM: line be "sticky" for all
+ messages to that host; these are most frequently associated
+ with addresses rather than the host, with the exception of
+ 421 (service shutting down). The effect was to cause queues
+ to sometimes take an excessive time to flush. Reported by
+ Robert Sargent of Southern Geographics Technologies and
+ Eric Prestemon of American University.
+ Add Nice=N mailer option to set the niceness at which a mailer will
+ run. This is actually a relative niceness (that is, an
+ increment on the background value).
+ Log queue runs that are skipped due to high loads. They are logged
+ at LOG_INFO priority iff the log level is > 8. Contributed
+ by Bruce Nagel of Data General.
+ Allow the error mailer to accept a DSN-style error status code
+ instead of an sysexits status code in the host part.
+ Anything with a dot will be interpreted as a DSN-style code.
+ Add new mailer flag: F=3 will tell translations to Quoted-Printable
+ to encode characters that might be munged by an EBCDIC system
+ in addition to the set required by RFC 1521. The additional
+ characters are !, ", #, $, @, [, \, ], ^, `, {, |, }, and ~.
+ (Think of "IBM 360" as the mnemonic for this flag.)
+ Change check for mailing to files to look for a pathname of [FILE]
+ rather than looking for the mailer named *file*. The mapping
+ of leading slashes still goes to the *file* mailer. This
+ allows you to implement the *file* mailer as a separate
+ program, for example, to insert a Content-Length: header
+ or do special security policy. However, note that the usual
+ initial checking for the file permissions is still done, and
+ the program in question needs to be very careful about how
+ it does the file write to avoid security problems.
+ Be able to read ~root/.forward even if the path isn't accessible to
+ regular users. This is disrecommended because sendmail
+ sometimes does not run as root (e.g., when an unsafe option
+ is specified on the command line), but should otherwise be
+ safe because .forward files must be owned by the user for
+ whom mail is being forwarded, and cannot be a symbolic link.
+ Suggested by Forrest Aldrich of Wang Laboratories.
+ Add new "HostsFile" option that is the pathname to the /etc/hosts
+ file. This is used for canonifying hostnames when the
+ service type is "files".
+ Implement programs on F (read class from file) line. The syntax is
+ Fc|/path/to/program to read the output from the program
+ into class "c".
+ Probe the network interfaces to find alternate names for this
+ host. Requires the SIOCGIFCONF ioctl call. Code
+ contributed by SunSoft.
+ Add "E" configuration line to set or propogate environment
+ variables into children. "E<envar>" will propogate
+ the named variable from the environment when sendmail
+ was invoked into any children it calls; "E<envar>=<value>"
+ sets the named variable to the indicated value. Any
+ variables not explicitly named will not be in the child
+ environment. However, sendmail still forces an
+ "AGENT=sendmail" environment variable, in part to enforce
+ at least one environment variable, since many programs and
+ libraries die horribly if this is not guaranteed.
+ Change heuristic for rebuilding both NEWDB and NDBM versions of
+ alias databases -- new algorithm looks for the substring
+ "/yp/" in the file name. This is more portable and involves
+ less overhead. Suggested by Motonori Nakamura.
+ Dynamically allocate the queue work list so that you don't lose
+ jobs in large queue runs. The old QUEUESIZE compile parameter
+ is replaced by QUEUESEGSIZE (the unit of allocation, which
+ should not need to be changed) and the MaxQueueRunSize option,
+ which is the absolute maximum number of jobs that will ever
+ be handled in a single queue run. Based on code contributed
+ by Brian Coan of the Institute for Global Communications.
+ Log message when a message is dropped because it exceeds the maximum
+ message size. Suggested by Leo Bicknell of Virginia Tech.
+ Allow trusted users (those on a T line or in $=t) to use -bs without
+ an X-Authentication-Warning: added. Suggested by Mark Thomas
+ of Mark G. Thomas Consulting.
+ Announce state of compile flags on -d0.1 (-d0.10 throws in the
+ OS-dependent defines). The old semantic of -d0.1 to not
+ run the daemon in background has been moved to -d99.100,
+ and the old 52.5 flag (to avoid disconnect() from closing
+ all output files) has been moved to 52.100. This makes
+ things more consistent (flags below .100 don't change
+ semantics) and separates out the backgrounding so that
+ it doesn't happen automatically on other unrelated debugging
+ flags.
+ If -t is used but no addresses are found in the header, give an
+ error message rather than just doing nothing. Fix from
+ Motonori Nakamura.
+ On systems (like SunOS) where the effective gid is not necessarily
+ included in the group list returned by getgroups(), the
+ `restrictmailq' option could sometimes cause an authorized
+ user to not be able to use `mailq'. Fix from Charles Hannum
+ of MIT.
+ Allow symbolic service names for [IPC] mailers. Suggested by
+ Gerry Magennis of Logica International.
+ Add DontExpandCnames option to prevent $[ ... $] from expanding CNAMEs
+ when running DNS. For example, if the name FTP.Foo.ORG is
+ a CNAME for Cruft.Foo.ORG, then when sitting on a machine in
+ the Foo.ORG domain a lookup of "FTP" returns "Cruft.Foo.ORG"
+ if this option is not set, or "FTP.Foo.ORG" if it is set.
+ This is technically illegal under RFC 822 and 1123, but the
+ IETF is moving toward legalizing it. Note that turning on
+ this option is not sufficient to guarantee that a downstream
+ neighbor won't rewrite the address for you.
+ Add "-m" flag to makesendmail script -- this tells you what object
+ directory and Makefile it will use, but doesn't actually do
+ the make.
+ Do some additional checking on the contents of the qf file to try
+ to detect attacks against the qf file. In particular,
+ abort on any line beginning "From ", and add an "end of
+ file" line -- any data after that line is prohibited.
+ Always use /etc/sendmail.cf, regardless of the arbitrary vendor
+ choices. This can be overridden in the Makefile by using
+ either -DUSE_VENDOR_CF_PATH to get the vendor location
+ (to the extent that we know it) or by defining
+ _PATH_SENDMAILCF (which is a "hard override"). This allows
+ sendmail 8 to have more consistent installation instructions.
+ Allow macros on `K' line in config file. Suggested by Andrew Chang
+ of Sun Microsystems.
+ Improved symbol table hash function from Eric Wassenaar. This one
+ is at least 50% faster.
+ Fix problem that didn't notice that timeout on file open was a
+ transient error. Fix from Larry Parmelee of Cornell
+ University.
+ Allow comments (lines beginning with a `#') in files read for
+ classes. Suggested by Motonori Nakamura.
+ Make SIGINT (usually ^C) in test mode return to the prompt instead
+ of dropping out entirely. This makes testing some of the
+ name server lookups easier to deal with when there are
+ hung servers. From Motonori Nakamura.
+ Add new ${opMode} macro that is set to the current operation mode
+ (e.g., `s' for -bs, `t' for -bt, etc.). Suggested by
+ Claude Marinier <MARINIER@emp.ewd.dreo.dnd.ca>.
+ Add new delivery mode (Odd) that defers all map lookups to queue runs.
+ Kind of like queue-only mode (Odq) except it tries to avoid
+ any external service requests; for dial-on-demand hosts that
+ want to minimize DNS lookups when mail is being queued. For
+ this to work you will also have to make sure that gethostbyname
+ of your local host name does not do a DNS lookup.
+ Improved handling of "out of space" conditions from John Myers of
+ Carnegie Mellon.
+ Improved security for mailing to files on systems that have fchmod(2)
+ support.
+ Improve "cannot send message for N days" message -- now says "could
+ not send for past N days". Suggested by Tom Moore of AT&T
+ Global Information Solutions.
+ Less misleading Subject: line on messages sent to postmaster only.
+ From Motonori Nakamura.
+ Avoid duplicate error messages on bad command line flags. From
+ Motonori Nakamura.
+ Better error message for case where ruleset 0 falls off the end
+ or otherwise does not resolve to a canonical triple.
+ Fix a problem that could cause multiple bounce messages if a bad
+ address was sent along with a good address to an SMTP
+ site where that SMTP site returned a 4yz code in response
+ to the final dot of the data. Problem reported by David
+ James of British Telecom.
+ Add "volatile" declarations so that gcc -O2 will work. Patches
+ from Alexander Dupuy of System Management ARTS.
+ Delete duplicates in MX lists -- believe it or not, there are sites
+ that list the same host twice in an MX list. This deletion
+ only works on adjacent preferences, so an MX list that
+ had A=5, B=10, A=15 would leave both As, but one that had
+ A=5, A=10, B=15 would reduce to A, B. This is intentional,
+ just in case there is something wierd I haven't thought of.
+ Suggested by Barry Shein of Software Tool & Die.
+ SECURITY: .forward files cannot be symbolic links. If they are,
+ a bad guy can read your private files.
+ PORTABILITY FIXES:
+ Solaris 2 from Rob McMahon <cudcv@csv.warwick.ac.uk>.
+ System V Release 4 from Motonori Nakamura of Ritsumeikan
+ University. This expands the disk size
+ checking to include all (?) SVR4 configurations.
+ System V Release 4 from Kimmo Suominen -- initgroups(3)
+ and setrlimit(2) are both available.
+ System V Release 4 from sob@sculley.ffg.com -- some versions
+ apparently "have EX_OK defined in other headerfiles."
+ Linux Makefile typo.
+ Linux getusershell(3) is broken in Slackware 2.0 --
+ from Andrew Pam of Xanadu Australia.
+ More Linux tweaking from John Kennedy of California State
+ University, Chico.
+ Cray changes from Eric Wassenaar: ``On Cray, shorts,
+ ints, and longs are all 64 bits, and all structs
+ are multiples of 64 bits. This means that the
+ sizeof operator returns only multiples of 8.
+ This requires adaptation of code that really
+ deals with 32 bit or 16 bit fields, such as IP
+ addresses or nameserver fields.''
+ DG/UX 5.4.3 from Mark T. Robinson <mtr@ornl.gov>. To
+ get the old behaviour, use -DDGUX_5_4_2.
+ DG/UX hack: add _FORCE_MAIL_LOCAL_=yes environment
+ variable to fix bogus /bin/mail behaviour.
+ Tandem NonStop-UX from Rick McCarty <mccarty@mpd.tandem.com>.
+ This also cleans up some System V Release 4 compile
+ problems.
+ Solaris 2: sendmail.cw file should be in /etc/mail to
+ match all the other configuration files. Fix
+ from Glenn Barry of Emory University.
+ Solaris 2.3: compile problem in conf.c. Fix from Alain
+ Nissen of the University of Liege, Belgium.
+ Ultrix: freespace calculation was incorrect. Fix from
+ Takashi Kizu of Osaka University.
+ SVR4: running in background gets a SIGTTOU because the
+ emulation code doesn't realize that "getpeername"
+ doesn't require reading the file. Fix from Peter
+ Wemm of DIALix.
+ Solaris 2.3: due to an apparent bug in the socket emulation
+ library, sockets can get into a "wedged" state where
+ they just return EPROTO; closing and re-opening the
+ socket clears the problem. Fix from Bob Manson
+ of Ohio State University.
+ Hitachi 3050R & 3050RX running HI-UX/WE2: portability
+ fixes from Akihiro Hashimoto ("Hash") of Chiba
+ University.
+ AIX changes to allow setproctitle to work from Rainer Schöpf
+ of Zentrum für Datenverarbeitung der Universität
+ Mainz.
+ AIX changes for load average from Ed Ravin of NASA/Goddard.
+ SCO Unix from Chip Rosenthal of Unicom (code was using the
+ wrong statfs call).
+ ANSI C fixes from Adam Glass (NetBSD project).
+ Stardent Titan/ANSI C fixes from Kate Hedstrom of Rutgers
+ University.
+ DG-UX fixes from Bruce Nagel of Data General.
+ IRIX64 updates from Mark Levinson of the University of
+ Rochester Medical Center.
+ Altos System V (``the first UNIX/XENIX merge the Altos
+ did for their Series 1000 & Series 2000 line;
+ their merged code was licenced back to AT&T and
+ Microsoft and became System V release 3.2'') from
+ Tim Rice <timr@crl.com>.
+ OSF/1 running on Intel Paragon from Jeff A. Earickson
+ <jeff@ssd.intel.com> of Intel Scalable Systems
+ Divison.
+ Amdahl UTS System V 2.1.5 (SVr3-based) from Janet Jackson
+ <janet@dialix.oz.au>.
+ System V Release 4 (statvfs semantic fix) from Alain
+ Durand of I.M.A.G.
+ HP-UX 10.x multiprocessor load average changes from
+ Scott Hutton and Jeff Sumler of Indiana University.
+ Cray CSOS from Scott Bolte of Cray Computer Corporation.
+ Unicos 8.0 from Douglas K. Rand of the University of North
+ Dakota, Scientific Computing Center.
+ Solaris 2.4 fixes from Sanjay Dani of Dani Communications.
+ ConvexOS 11.0 from Christophe Wolfhugel.
+ IRIX 4.0.5 from David Ashton-Reader of CADcentre.
+ ISC UNIX from J. J. Bailey.
+ HP-UX 9.xx on the 8xx series machines from Remy Giraud
+ of Meteo France.
+ HP-UX configuration from Tom Lane <tgl@sss.pgh.pa.us>.
+ IRIX 5.2 and 5.3 from Kari E. Hurtta.
+ FreeBSD 2.0 from Mike Hickey of Federal Data Corporation.
+ Sony NEWS-OS 4.2.1R and 6.0.3 from Motonori Nakamura.
+ Omron LUNA unios-b, mach from Motonori Nakamura.
+ NEC EWS-UX/V 4.2 from Motonori Nakamura.
+ NeXT 2.1 from Bryan Costales.
+ AUX patch thanks to Mike Erwin of Apple Computer.
+ HP-UX 10.0 from John Beck of Hewlett-Packard.
+ Ultrix: allow -DBROKEN_RES_SEARCH=0 if you are using a
+ non-DEC resolver. Suggested by Allan Johannesen.
+ UnixWare 2.0 fixes from Petr Lampa of the Technical
+ University of Brno (Czech Republic).
+ KSR OS 1.2.2 support from Todd Miller of the University
+ of Colorado.
+ UX4800 support from Kazuhisa Shimizu of NEC.
+ MAKEMAP: allow -d flag to allow insertion of duplicate aliases
+ in type ``btree'' maps. The semantics of this are undefined
+ for regular maps, but it can be useful for the user database.
+ MAKEMAP: lock database file while rebuilding to avoid sendmail
+ lookups while the rebuild is going on. There is a race
+ condition between the open(... O_TRUNC ...) and the lock
+ on the file, but it should be quite small.
+ SMRSH: sendmail restricted shell added to the release. This can
+ be used as an alternative to /bin/sh for the "prog" mailer,
+ giving the local administrator more control over what
+ programs can be run from sendmail.
+ MAIL.LOCAL: add this local mailer to the tape. It is not really
+ part of the release proper, and isn't fully supported; in
+ particular, it does not run on System V based systems and
+ never will.
+ CONTRIB: a patch to rmail.c from Bill Gianopoulos of Raytheon
+ to allow rmail to compile on systems that don't have
+ function prototypes and systems that don't have snprintf.
+ CONTRIB: add the "mailprio" scripts that will help you sort mailing
+ lists by transaction delay times so that addresses that
+ respond quickly get sent first. This is to prevent very
+ sluggish servers from delaying other peoples' mail.
+ Contributed by Tony Sanders of BSDI.
+ CONTRIB: add the "bsdi.mc" file as contributed by Tony Sanders
+ of BSDI. This has a lot of comments to help people out.
+ CONFIG: Don't have .mc files include(../m4/cf.m4) -- instead,
+ put this on the m4 command line. On GNU m4 (which
+ supports the __file__ primitive) you can run m4 in an
+ arbitrary directory -- use either:
+ m4 ${CFDIR}/m4/cf.m4 config.mc > config.cf
+ or
+ m4 -I${CFDIR} m4/cf.m4 config.mc > config.cf
+ On other versions of m4 that don't support __file__, you
+ can use:
+ m4 -D_CF_DIR_=${CFDIR}/ ${CFDIR}/m4/cf.m4 ...
+ (Note the trailing slash on the _CF_DIR_ definition.)
+ Old versions of m4 will default to _CF_DIR_=.. for back
+ compatibility.
+ CONFIG: fix mail from <> so it will properly convert to
+ MAILER-DAEMON on local addresses.
+ CONFIG: fix code that was supposed to catch colons in host
+ names. Problem noted by John Gardiner Myers of CMU.
+ CONFIG: allow use of SMTP_MAILER_MAX in nullclient configuration.
+ From Paul Riddle of the University of Maryland, Baltimore
+ County.
+ CONFIG: Catch and reject "." as a host address.
+ CONFIG: Generalize domaintable to look up all domains, not
+ just unqualified ones.
+ CONFIG: Delete OLD_SENDMAIL support -- as near as I can tell, it
+ was never used and didn't work anyway.
+ CONFIG: Set flags A, w, 5, :, /, |, and @ on the "local" mailer
+ and d on all mailers in the UUCP class.
+ CONFIG: Allow "user+detail" to be aliased specially: it will first
+ look for an alias for "user+detail", then for "user+*", and
+ finally for "user". This is intended for forwarding mail
+ for system aliases such as root and postmaster to a
+ centralized hub.
+ CONFIG: add confEIGHT_BIT_HANDLING to set option 8 (see above).
+ CONFIG: add smtp8 mailer; this has the F=8 (just-send-8) flag set.
+ The F=8 flag is also set on the "relay" mailer, since
+ this is expected to be another sendmail.
+ CONFIG: avoid qualifying all UUCP addresses sent via SMTP with
+ the name of the UUCP_RELAY -- in some cases, this is the
+ wrong value (e.g., when we have local UUCP connections),
+ and this can create unreplyable addresses. From Chip
+ Rosenthal of Unicom.
+ CONFIG: add confRECEIVED_HEADER to change the format of the
+ Received: header inserted into all messages. Suggested by
+ Gary Mills of the University of Manitoba.
+ CONFIG: Make "notsticky" the default; use FEATURE(stickyhost)
+ to get the old behaviour. I did this upon observing
+ that almost everyone needed this feature, and that the
+ concept I was trying to make happen didn't work with
+ some user agents anyway. FEATURE(notsticky) still works,
+ but it is a no-op.
+ CONFIG: Add LUSER_RELAY -- the host to which unrecognized user
+ names are sent, rather than immediately diagnosing them
+ as User Unknown.
+ CONFIG: Add SMTP_MAILER_ARGS, ESMTP_MAILER_ARGS, SMTP8_MAILER_ARGS,
+ and RELAY_MAILER_ARGS to set the arguments for the
+ indicated mailers. All default to "IPC $h". Patch from
+ Larry Parmelee of Cornell University.
+ CONFIG: pop mailer needs F=n flag to avoid "annoying side effects
+ on the client side" and F=P to get an appropriate
+ return-path. From Kimmo Suominen.
+ CONFIG: add FEATURE(local_procmail) to use the procmail program
+ as the local mailer. For addresses of the form "user+detail"
+ the "detail" part is passed to procmail via the -a flag.
+ Contributed by Kimmo Suominen.
+ CONFIG: add MAILER(procmail) to add an interface to procmail for
+ use from mailertables. This lets you execute arbitrary
+ procmail scripts. Contributed by Kimmo Suominen.
+ CONFIG: add T= fields (MTS type) to local, smtp, and uucp mailers.
+ CONFIG: add OSTYPE(ptx2) for DYNIX/ptx 2.x from Sequent. From
+ Paul Southworth of CICNet Systems Support.
+ CONFIG: use -a$g as default to UUCP mailers, instead of -a$f.
+ This causes the null return path to be rewritten as
+ MAILER-DAEMON; otherwise UUCP gets horribly confused.
+ From Michael Hohmuth of Technische Universitat Dresden.
+ CONFIG: Add FEATURE(bestmx_is_local) to cause any hosts that
+ list us as the best possible MX record to be treated as
+ though they were local (essentially, assume that they
+ are included in $=w). This can cause additional DNS
+ traffic, but is easier to administer if this fits your
+ local model. It does not work reliably if there are
+ multiple hosts that share the best MX preference.
+ Code contributed by John Oleynick of Rutgers.
+ CONFIG: Add FEATURE(smrsh) to use smrsh (the SendMail Restricted
+ SHell) instead of /bin/sh as the program used for delivery
+ to programs. If an argument is included, it is used as
+ the path to smrsh; otherwise, /usr/local/etc/smrsh is
+ assumed.
+ CONFIG: Add LOCAL_MAILER_MAX and PROCMAILER_MAILER_MAX to limit the
+ size of messages to the local and procmail mailers
+ respectively. Contributed by Brad Knowles of the Defense
+ Information Systems Agency.
+ CONFIG: Handle leading ``phrase:'' and trailing ``;'' as comments
+ (just like text outside of angle brackets) in order to
+ properly deal with ``group: addr1, ... addrN;'' syntax.
+ CONFIG: Require OSTYPE macro (the defaults really don't apply to
+ any real systems any more) and tweak the DOMAIN macro
+ so that it is less likely that users will accidently use
+ the Berkeley defaults. Also, create some generic files
+ that really can be used in the real world.
+ CONFIG: Add new configuration macros to set character sets for
+ messages _arriving from_ various mailers: LOCAL_MAILER_CHARSET,
+ SMTP_MAILER_CHARSET, and UUCP_MAILER_CHARSET.
+ CONFIG: Change UUCP_MAX_SIZE to UUCP_MAILER_MAX for consistency.
+ The old name will still be accepted for a while at least.
+ CONFIG: Implement DECNET_RELAY as spec for host to which DECNET
+ mail (.DECNET pseudo-domain or node::user) will be sent.
+ As with all relays, it can be ``mailer:hostname''. Suggested
+ by Scott Hutton.
+ CONFIG: Add MAILER(mail11) to get DECnet support. Code contributed
+ by Barb Dijker of Labyrinth Computer Services.
+ CONFIG: change confCHECK_ALIASES to default to False -- it has poor
+ performance for large alias files, and this confused many
+ people.
+ CONFIG: Add confCF_VERSION to append local information to the
+ configuration version number displayed during SMTP startup.
+ CONFIG: fix some.newsgroup.usenet@local.host syntax (previously it
+ would only work when locally addressed. Fix from
+ Edvard Tuinder of Cistron Internet Services.
+ CONFIG: use ${opMode} to avoid error on .REDIRECT addresses if option
+ "n" (CheckAlaises) is set when rebuilding alias database.
+ Based on code contributed by Claude Marinier.
+ CONFIG: Allow mailertable to have values of the form
+ ``error:code message''. The ``code'' is a status code
+ derived from the sysexits codes -- e.g., NOHOST or UNAVAILABLE.
+ Contributed by David James <dwj@agw.bt.co.uk>.
+ CONFIG: add MASQUERADE_DOMAIN(domain list) to extend the list of
+ sender domains that will be replaced with the masquerade name.
+ These domains will not be treated as local, but if mail passes
+ through with sender addresses in those domains they will be
+ replaced by the masquerade name. These can also be specified
+ in a file using MASQUERADE_DOMAIN_FILE(filename).
+ CONFIG: add FEATURE(masquerade_envelope) to masquerade the envelope
+ as well as the header. Substantial improvements to this
+ code were contributed by Per Hedeland.
+ CONFIG: add MAILER(phquery) to define a new "ph" mailer; this can be
+ accessed from a mailertable to do CCSO ph lookups. Contributed
+ by Kimmo Suominen.
+ CONFIG: add MAILER(cyrus) to define a new Cyrus mailer; this can be
+ used to define cyrus and cyrusbb mailers (for IMAP support).
+ Contributed by John Gardiner Myers of Carnegie Mellon.
+ CONFIG: add confUUCP_MAILER to select default mailer to use for
+ UUCP addressing. Suggested by Tom Moore of AT&T GIS.
+ NEW FILES:
+ cf/cf/cs-hpux10.mc
+ cf/cf/cs-solaris2.mc
+ cf/cf/cyrusproto.mc
+ cf/cf/generic-bsd4.4.mc
+ cf/cf/generic-hpux10.mc
+ cf/cf/generic-hpux9.mc
+ cf/cf/generic-osf1.mc
+ cf/cf/generic-solaris2.mc
+ cf/cf/generic-sunos4.1.mc
+ cf/cf/generic-ultrix4.mc
+ cf/cf/huginn.cs.mc
+ cf/domain/berkeley-only.m4
+ cf/domain/generic.m4
+ cf/feature/bestmx_is_local.m4
+ cf/feature/local_procmail.m4
+ cf/feature/masquerade_envelope.m4
+ cf/feature/smrsh.m4
+ cf/feature/stickyhost.m4
+ cf/feature/use_ct_file.m4
+ cf/m4/cfhead.m4
+ cf/mailer/cyrus.m4
+ cf/mailer/mail11.m4
+ cf/mailer/phquery.m4
+ cf/mailer/procmail.m4
+ cf/ostype/amdahl-uts.m4
+ cf/ostype/bsdi2.0.m4
+ cf/ostype/hpux10.m4
+ cf/ostype/irix5.m4
+ cf/ostype/isc4.1.m4
+ cf/ostype/ptx2.m4
+ cf/ostype/unknown.m4
+ contrib/bsdi.mc
+ contrib/mailprio
+ contrib/rmail.oldsys.patch
+ mail.local/mail.local.0
+ makemap/makemap.0
+ smrsh/README
+ smrsh/smrsh.0
+ smrsh/smrsh.8
+ smrsh/smrsh.c
+ src/Makefiles/Makefile.CSOS
+ src/Makefiles/Makefile.EWS-UX_V
+ src/Makefiles/Makefile.HP-UX.10
+ src/Makefiles/Makefile.IRIX.5.x
+ src/Makefiles/Makefile.IRIX64
+ src/Makefiles/Makefile.ISC
+ src/Makefiles/Makefile.KSR
+ src/Makefiles/Makefile.NEWS-OS.4.x
+ src/Makefiles/Makefile.NEWS-OS.6.x
+ src/Makefiles/Makefile.NEXTSTEP
+ src/Makefiles/Makefile.NonStop-UX
+ src/Makefiles/Makefile.Paragon
+ src/Makefiles/Makefile.SCO.3.2v4.2
+ src/Makefiles/Makefile.SunOS.5.3
+ src/Makefiles/Makefile.SunOS.5.4
+ src/Makefiles/Makefile.SunOS.5.5
+ src/Makefiles/Makefile.UNIX_SV.4.x.i386
+ src/Makefiles/Makefile.uts.systemV
+ src/Makefiles/Makefile.UX4800
+ src/aliases.0
+ src/mailq.0
+ src/mime.c
+ src/newaliases.0
+ src/sendmail.0
+ test/t_seteuid.c
+ RENAMED FILES:
+ cf/cf/alpha.mc => cf/cf/s2k-osf1.mc
+ cf/cf/chez.mc => cf/cf/chez.cs.mc
+ cf/cf/hpux-cs-exposed.mc => cf/cf/cs-hpux9.mc
+ cf/cf/osf1-cs-exposed.mc => cf/cf/cs-osf1.mc
+ cf/cf/s2k.mc => cf/cf/s2k-ultrix4.mc
+ cf/cf/sunos4.1-cs-exposed.mc => cf/cf/cs-sunos4.1.mc
+ cf/cf/ultrix4.1-cs-exposed.mc => cf/cf/cs-ultrix4.mc
+ cf/cf/vangogh.mc => cf/cf/vangogh.cs.mc
+ cf/domain/Berkeley.m4 => cf/domain/Berkeley.EDU.m4
+ cf/domain/cs-exposed.m4 => cf/domain/CS.Berkeley.EDU.m4
+ cf/domain/eecs-hidden.m4 => cf/domain/EECS.Berkeley.EDU.m4
+ cf/domain/s2k.m4 => cf/domain/S2K.Berkeley.EDU.m4
+ cf/ostype/hpux.m4 => cf/ostype/hpux9.m4
+ cf/ostype/irix.m4 => cf/ostype/irix4.m4
+ cf/ostype/ultrix4.1.m4 => cf/ostype/ultrix4.m4
+ src/Makefile.* => src/Makefiles/Makefile.*
+ src/Makefile.AUX => src/Makefiles/Makefile.A-UX
+ src/Makefile.BSDI => src/Makefiles/Makefile.BSD-OS
+ src/Makefile.DGUX => src/Makefiles/Makefile.dgux
+ src/Makefile.RISCos => src/Makefiles/Makefile.UMIPS
+ src/Makefile.SunOS.4.0.3 => src/Makefiles/Makefile.SunOS.4.0
+ OBSOLETED FILES:
+ cf/cf/cogsci.mc
+ cf/cf/cs-exposed.mc
+ cf/cf/cs-hidden.mc
+ cf/cf/hpux-cs-hidden.mc
+ cf/cf/knecht.mc
+ cf/cf/osf1-cs-hidden.mc
+ cf/cf/sunos3.5-cs-exposed.mc
+ cf/cf/sunos3.5-cs-hidden.mc
+ cf/cf/sunos4.1-cs-hidden.mc
+ cf/cf/ultrix4.1-cs-hidden.mc
+ cf/domain/cs-hidden.m4
+ contrib/rcpt-streaming
+ src/Makefiles/Makefile.SunOS.5.x
+
+8.6.12/8.6.12 95/03/28
+ Fix to IDENT code (it was getting the size of the reply buffer
+ too small, so nothing was ever accepted). Fix from several
+ people, including Allan Johannesen, Shane Castle of the
+ Boulder County Information Services, and Jeff Smith of
+ Warwick University (all arrived within a few hours of
+ each other!).
+ Fix a problem that could cause large jobs to run out of
+ file descriptors on systems that use vfork() rather
+ than fork().
+
+8.6.11/8.6.11 95/03/08
+ The ``possible attack'' message would be logged more often
+ than necessary if you are using Pine as a user agent.
+ The wrong host would be reported in the ``possible attack''
+ message when attempted from IDENT.
+ In some cases the syslog buffer could be overflowed when
+ reporting the ``possible attack'' message. This can
+ cause denial of service attacks. Truncate the message
+ to 80 characters to prevent this problem.
+ When reading the IDENT response a loop is needed around the
+ read from the network to ensure that you don't get
+ partial lines.
+ Password entries without any shell listed (that is, a null
+ shell) wouldn't match as "ok". Problem noted by
+ Rob McMahon.
+ When running BIND 4.9.x a problem could occur because the
+ _res.options field is initialized differently than it
+ was historically -- this requires that sendmail call
+ res_init before it tweaks any bits.
+ Fix an incompatibility in openxscript() between the file open mode
+ and the stdio mode passed to fdopen. This caused UnixWare
+ 2.0 to have conniptions. Fix from Martin Sohnius of
+ Novell Labs Europe.
+ Fix problem with static linking of local getopt routine when
+ using GNU's ld command. Fix from John Kennedy of
+ Cal State Chico.
+ It was possible to turn off privacy flags. Problem noted by
+ *Hobbit*.
+ Be more paranoid about writing files. Suggestions by *Hobbit*
+ and Liudvikas Bukys.
+ MAKEMAP: fixes for 64 bit machines (DEC Alphas in particular)
+ from Spider Boardman.
+ CONFIG: No changes (version number only, to keep it in sync
+ with the binaries).
+
+8.6.10/8.6.10 95/02/10
+ SECURITY: Diagnose bogus values to some command line flags that
+ could allow trash to get into headers and qf files.
+ Validate the name of the user returned by the IDENT protocol.
+ Some systems that really dislike IDENT send intentionally
+ bogus information. Problem pointed out by Michael Bushnell
+ of the Free Software Foundation. Has some security
+ implications.
+ Fix a problem causing error messages about DNS problems when
+ the host name contained a percent sign to act oddly
+ because it was passed as a printf-style format string.
+ In some cases this could cause core dumps.
+ Avoid possible buffer overrun in returntosender() if error
+ message is quite ling. From Fletcher Mattox of the
+ University of Texas.
+ Fix a problem that would silently drop "too many hops" error
+ messages if and only if you were sending to an alias.
+ From Jon Giltner of the University of Colorado and
+ Dan Harton of Oak Ridge National Laboratory.
+ Fix a bug that caused core dumps on some systems if -d11.2 was
+ set and e->e_message was null. Fix from Bruce Nagel of
+ Data General.
+ Fix problem that can still cause df files to be left around
+ after "hop count exceeded" messages. Fix from Andrew
+ Chang and Shau-Ping Lo of SunSoft.
+ Fix a problem that can cause buffer overflows on very long
+ user names (as might occur if you piped to a program
+ with a lot of arguments).
+ Avoid returning an error and re-queueing if the host signature
+ is null; this can occur on addresses like ``user@.''.
+ Problem noted by Wesley Craig and the University of
+ Michigan.
+ Avoid possible calls to malloc(0) if MCI caching is turned
+ off. Bug fix from Pierre David of the Laboratoire
+ Parallelisme, Reseaux, Systemes et Modelisation (PRiSM),
+ Universite de Versailles - St Quentin, and Jacky
+ Thibault.
+ Make a local copy of the line being sent via senttolist() -- in
+ some cases, buffers could get trashed by map lookups
+ causing it to do unexpected things. This also simplifies
+ some of the map code.
+ CONFIG: No changes (version number only, to keep it in sync
+ with the binaries).
+
+8.6.9/8.6.9 94/04/19
+ Do all mail delivery completely disconnected from any terminal.
+ This provides consistency with daemon delivery and
+ may have some security implications.
+ Make sure that malloc doesn't get called with zero size,
+ since that fails on some systems. Reported by Ed
+ Hill of the University of Iowa.
+ Fix multi-line values for $e (SMTP greeting message). Reported
+ by Mike O'Connor of Ford Motor Company.
+ Avoid syserr if no NIS domain name is defined, but the map it
+ is trying to open is optional. From Win Bent of USC.
+ Changes for picky compilers from Ed Gould of Digital Equipment.
+ Hesiod support for UDB from Todd Miller of the University of
+ Colorado. Use "hesiod" as the service name in the U
+ option.
+ Fix a problem that failed to set the "authentic" host name (that
+ is, the one derived from the socket info) if you called
+ sendmail -bs from inetd. Based on code contributed by
+ Todd Miller (this problem was also reported by Guy Helmer
+ of Dakota State University). This also fixes a related
+ problem reported by Liudvikas Bukys of the University of
+ Rochester.
+ Parameterize "nroff -h" in all the Makefiles so people with
+ variant versions can use them easily. Suggested by
+ Peter Collinson of Hillside Systems.
+ SMTP "MAIL" commands with multiple ESMTP parameters required two
+ spaces between parameters instead of one. Reported by
+ Valdis Kletnieks of Virginia Tech.
+ Reduce the number of system calls during message collection by
+ using global timeouts around the collect() loop. This
+ code was contributed by Eric Wassenaar.
+ If the initial hostname name gathering results in a name
+ without a dot (usually caused by NIS misconfiguration)
+ and BIND is compiled in, directly access DNS to get
+ the canonical name. This should make life easier for
+ Solaris systems. If it still can't be resolved, and
+ if the name server is listed as "required", try again
+ in 30 seconds. If that also fails, exit immediately to
+ avoid bogus "config error: mail loops back to myself"
+ messages.
+ Improve the "MAIL DELETED BECAUSE OF LACK OF DISK SPACE" error
+ message to explain how much space was available and
+ sound a bit less threatening. Suggested by Stan Janet
+ of the National Institute of Standards and Technology.
+ If mail is delivered to an alias that has an owner, deliver any
+ requested return-receipt immediately, and strip the
+ Return-Receipt-To: header from the subsequent message.
+ This prevents a certain class of denial of service
+ attack, arguably gives more reasonable semantics, and
+ moves things more towards what will probably become a
+ network standard. Suggested by Christopher Davis of
+ Kapor Enterprises.
+ Add a "noreceipts" privacy flag to turn off all return receipts
+ without recompiling.
+ Avoid printing ESMTP parameters as part of the error message
+ if there are errors during parsing. This change is
+ purely cosmetic.
+ Avoid sending out error messages during the collect phase of
+ SMTP; there is an MVS mailer from UCLA that gets
+ confused by this. Of course, I think it's their bug....
+ Check for the $j macro getting undefined, losing a dot, or getting
+ lost from $=w in the daemon before accepting a connection;
+ if it is, it dumps state, prints a LOG_ALERT message,
+ and drops core for debugging. This is an attempt to
+ track down a bug that I thought was long since gone.
+ If you see this, please forward the log fragment to
+ sendmail@sendmail.ORG.
+ Change OLD_NEWDB from a #ifdef to a #if so it can be turned off
+ with -DOLD_NEWDB=0 on the command line. From Christophe
+ Wolfhugel.
+ Instead of trying to truncate the listen queue for the server
+ SMTP port when the load average is too high, just close
+ the port completely and reopen it later as needed.
+ This ensures that the other end gets a quick "connection
+ refused" response, and that the connection can be
+ recovered later. In particular, some socket emulations
+ seem to get confused if you tweak the listen queue
+ size around and can never start listening to connections
+ again. The down side is that someone could start up
+ another daemon process in the interim, so you could
+ have multiple daemons all not listening to connections;
+ this could in turn cause the sendmail.pid file to be
+ incorrect. A better approach might be to accept the
+ connection and give a 421 code, but that could break
+ other mailers in mysterious ways and have paging behaviour
+ implications.
+ Fix a glitch in TCP-level debugging that caused flag 16.101 to
+ set debugging on the wrong socket. From Eric Wassenaar.
+ When creating a df* temporary file, be sure you truncate any
+ existing data in the file -- otherwise system crashes
+ and the like could result in extra data being sent.
+ DOC: Replace the CHANGES-R5-R8 readme file with a paper in the
+ doc directory. This includes some additional
+ information.
+ CONFIG: change UUCP rules to never add $U! or $k! on the front
+ of recipient envelope addresses. This should have been
+ handled by the $&h trick, but broke if people were
+ mixing domainized and UUCP addresses. They should
+ probably have converted all the way over to uucp-uudom
+ instead of uucp-{new,old}, but the failure mode was to
+ loop the mail, which was bad news.
+ Portability fixes:
+ Newer BSDI systems (several people).
+ Older BSDI systems from Christophe Wolfhugel.
+ Intergraph CLIX, from Paul Southworth of CICNet.
+ UnixWare, from Evan Champion.
+ NetBSD from Adam Glass.
+ Solaris from Quentin Campbell of the University of
+ Newcastle upon Tyne.
+ IRIX from Dean Cookson and Bill Driscoll of Mitre
+ Corporation.
+ NCR 3000 from Kevin Darcy of Chrysler Financial Corporation.
+ SunOS (it has setsid() and setvbuf() calls) from
+ Jonathan Kamens of OpenVision Technologies.
+ HP-UX from Tor Lillqvist.
+ New Files:
+ src/Makefile.CLIX
+ src/Makefile.NCR3000
+ doc/changes/Makefile
+ doc/changes/changes.me
+ doc/changes/changes.ps
+
+8.6.8/8.6.6 94/03/21
+ SECURITY: it was possible to read any file as root using the
+ E (error message) option. Reported by Richard Jones;
+ fixed by Michael Corrigan and Christophe Wolfhugel.
+
+8.6.7/8.6.6 94/03/14
+ SECURITY: it was possible to get root access by using wierd
+ values to the -d flag. Thanks to Alain Durand of
+ INRIA for forwarding me the notice from the bugtraq
+ list.
+
+8.6.6/8.6.6 94/03/13
+ SECURITY: the ability to give files away on System V-based
+ systems proved dangerous -- don't run as the owner
+ of a :include: file on a system that allows giveaways.
+ Unfortunately, this also applies to determining a
+ valid shell.
+ IMPORTANT: Previous versions weren't expiring old connections
+ in the connection cache for a long time under some
+ circumstances. This could result in resource exhaustion,
+ both at your end and at the other end. This checks the
+ connections for timeouts much more frequently. From
+ Doug Anderson of NCSC.
+ Fix a glitch that snuck in that caused programs to be run as
+ the sender instead of the recipient if the mail was
+ from a local user to another local user. From
+ Motonori Nakamura of Kyoto University.
+ Fix "wildcard" on /etc/shells matching -- instead of looking
+ for "*", look for "/SENDMAIL/ANY/SHELL/". From
+ Bryan Costales of ICSI.
+ Change the method used to declare the "statfs" availability;
+ instead of HASSTATFS and/or HASUSTAT with a ton of
+ tweaking in conf.c, there is a single #define called
+ SFS_TYPE which takes on one of six values (SFS_NONE
+ for no statfs availability, SFS_USTAT for the ustat(2)
+ syscall, SFS_4ARGS for a four argument statfs(2) call,
+ and SFS_VFS, SFS_MOUNT, or SFS_STATFS for a two argument
+ statfs(2) call with the declarations in <sys/vfs.h>,
+ <sys/mount.h>, or <sys/statfs.h> respectively).
+ Fix glitch in NetInfo support that could return garbage if
+ there was no "/locations/sendmail" property. From
+ David Meyer of the University of Virginia.
+ Change HASFLOCK from defined/not-defined to a 0/1 definition
+ to allow Linux to turn it off even though it is a
+ BSD-like system.
+ Allow setting of "ident" timeout to zero to turn off the ident
+ protocol entirely.
+ Make 7-bit stripping local to a connection (instead of to a
+ mailer); this allows you to specify that SMTP is a
+ 7-bit channel, but revert to 8-bit should it advertise
+ that it supports 8BITMIME. You still have to specify
+ mailer flag 7 to get this stripping at all.
+ Improve makesendmail script so it handles more cases automatically.
+ Tighten up restrictions on taking ownership of :include: files
+ to avoid problems on systems that allow you to give away
+ files.
+ Fix a problem that made it impossible to rebuild the alias
+ file if it was on a read-only file system. From
+ Harry Edmon of the University of Washington.
+ Improve MX randomization function. From John Gardiner Myers
+ of CMU.
+ Fix a minor glitch causing a bogus message to be printed (used
+ %s instead of %d in a printf string for the line number)
+ when a bad queue file was read. From Harry Edmon.
+ Allow $s to remain NULL on locally generated mail. I'm not
+ sure this is necessary, but a lot of people have complained
+ about it, and there is a legitimate question as to whether
+ "localhost" is legal as an 822-style domain.
+ Fix a problem with very short line lengths (mailer L= flag) in
+ headers. This causes a leading space to be added onto
+ continuation lines (including in the body!), and also
+ tries to wrap headers containing addresses (From:, To:,
+ etc) intelligently at the shorter line lengths. Problem
+ Reported by Lars-Johan Liman of SUNET Operations Center.
+ Log the real user name when logging syserrs, since these can have
+ security implications. Suggested by several people.
+ Fix address logging of cached connections -- it used to always
+ log the numeric address as zero. This is a somewhat
+ bogus implementation in that it does an extra system
+ call, but it should be an inexpensive one. Fix from
+ Motonori Nakamura.
+ Tighten up handling of short syslog buffers even more -- there
+ were cases where the outgoing relay= name was too long
+ to share a line with delay= and mailer= logging.
+ Limit the overhead on split envelopes to one open file descriptor
+ per envelope -- previously the overhead was three
+ descriptors. This was in response to a problem reported
+ by P{r (Pell) Emanuelsson.
+ Fixes to better handle the case of unexpected connection closes;
+ this redirects the output to the transcript so the info
+ is not lost. From Eric Wassenaar.
+ Fix potential string overrun if you macro evaluate a string that
+ has a naked $ at the end. Problem noted by James Matheson
+ <jmrm@eng.cam.ac.uk>.
+ Make default error number on $#error messages 553 (``Requested
+ action not taken: mailbox name not allowed'') instead of
+ 501 (``Syntax error in parameters or arguments'') to
+ avoid bogus "protocol error" messages.
+ Strip off any existing trailing dot on names during $[ ... $]
+ lookup. This prevents it from ending up with two dots
+ on the end of dot terminated names. From Wesley Craig
+ of the University of Michigan and Bryan Costales of ICSI.
+ Clean up file class reading so that the debugging information is
+ more informative. It hadn't been using setclass, so you
+ didn't see the class items being added.
+ Avoid core dump if you are running a version of sendmail where
+ NIS is compiled in, and you specify an NIS map, but
+ NIS is not running. Fix from John Oleynick of
+ Rutgers.
+ Diagnose bizarre case where res_search returns a failure value,
+ but sets h_errno to a success value.
+ Make sure that "too many hops" messages are considered important
+ enough to send an error to the Postmaster (that is, the
+ address specified in the P option). This fix should
+ help problems that cause the df file to be left around
+ sometimes -- unfortunately, I can't seem to reproduce
+ the problem myself.
+ Avoid core dump (null pointer reference) on EXPN command; this
+ only occurred if your log level was set to 10 or higher
+ and the target account was an alias or had a .forward file.
+ Problem noted by Janne Himanka.
+ Avoid "denial of service" attacks by someone who is flooding your
+ SMTP port with bad commands by shutting the connection
+ after 25 bad commands are issued. From Kyle Jones of
+ UUNET.
+ Fix core dump on error messages with very long "to" buffers;
+ fmtmsg overflows the message buffer. Fixed by trimming
+ the to address to 203 characters. Problem reported by
+ John Oleynick.
+ Fix configuration for HASFLOCK -- there were some spots where
+ a #ifndef was incorrectly #ifdef. Pointed out by
+ George Baltz of the University of Maryland.
+ Fix a typo in savemail() that could cause the error message To:
+ lists to be incorrect in some places. From Motonori
+ Nakamura.
+ Fix a glitch that can cause duplicate error messages on split
+ envelopes where an address on one of the lists has a
+ name server failure. Fix from Voradesh Yenbut of the
+ University of Washington.
+ Fix possible bogus pointer reference on ESMTP parameters that
+ don't have an ``=value'' part.
+ CNAME loops caused an error message to be generated, but also
+ re-queued the message. Changed to just re-queue the
+ message (it's really hard to just bounce it because
+ of the wierd way the name server works in the presence
+ of CNAME loops). Problem noted by James M.R.Matheson
+ of Cambridge University.
+ Avoid giving ``warning: foo owned process doing -bs'' messages
+ if they use ``MAIL FROM:<foo>'' where foo is their true
+ user name. Suggested by Andreas Stolcke of ICSI.
+ Change the NAMED_BIND compile flag to be a 0/1 flag so you can
+ override it easily in the Makefile -- that is, you can
+ turn it off using -DNAMED_BIND=0.
+ If a gethostbyname(...) of an address with a trailing dot fails,
+ try it without the trailing dot. This is because if
+ you have a version of gethostbyname() that falls back
+ to NIS or the /etc/hosts file it will fail to find
+ perfectly reasonable names that just don't happen to
+ be dot terminated in the hosts file. You don't want to
+ strip the dot first though because we're trying to ensure
+ that country names that match one of your subdomains get
+ a chance.
+ PRALIASES: fix bogus output on non-null-terminated strings.
+ From Bill Gianopoulos of Raytheon.
+ CONFIG: Avoid rewriting anything that matches $w to be $j.
+ This was in code intended to only catch the self-literal
+ address (that is, [1.2.3.4], where 1.2.3.4 is your
+ IP address), but the code was broken. However, it will
+ still do this if $M is defined; this is necessary to
+ get client configurations to work (sigh). Note that this
+ means that $M overrides :mailname entries in the user
+ database! Problem noted by Paul Southworth.
+ CONFIG: Fix definition of Solaris help file location. From
+ Steve Cliffe <steve@gorgon.cs.uow.edu.au>.
+ CONFIG: Fix bug that broke news.group.USENET mappings.
+ CONFIG: Allow declaration of SMTP_MAILER_MAX, FAX_MAILER_MAX,
+ and USENET_MAILER_MAX to tweak the maximum message
+ size for various mailers.
+ CONFIG: Change definition of USENET_MAILER_ARGS to include argv[0]
+ instead of assuming that it is "inews" for consistency
+ with other mailers. From Michael Corrigan of UC San Diego.
+ CONFIG: When mail is forwarded to a LOCAL_RELAY or a MAIL_HUB,
+ qualify the address in the SMTP envelope as user@{relay|hub}
+ instead of user@$j. From Bill Wisner of The Well.
+ CONFIG: Fix route-addr syntax in nullrelay configuration set.
+ CONFIG: Don't turn off case mapping of user names in the local
+ mailer for IRIX. This was different than most every other
+ system.
+ CONFIG: Avoid infinite loops on certainly list:; syntaxes in
+ envelope. Noted by Thierry Besancon
+ <besancon@excalibur.ens.fr>.
+ CONFIG: Don't include -z by default on uux line -- most systems
+ don't want it set by default. Pointed out by Philippe
+ Michel of Thomson CSF.
+ CONFIG: Fix some bugs with mailertables -- for example, if your
+ host name was foo.bar.ray.com and you matched against
+ ".ray.com", the old implementation bound %1 to "bar"
+ instead of "foo.bar". Also, allow "." in the mailertable
+ to match anything -- essentially, take over SMART_HOST.
+ This also moves matching of explicit local host names
+ before the mailertable so they don't have to be special
+ cased in the mailertable data. Reported by Bill
+ Gianopoulos of Raytheon; the fix for the %1 binding
+ problem was contributed by Nicholas Comanos of the
+ University of Sydney.
+ CONFIG: Don't include "root" in class $=L (users to deliver
+ locally, even if a hub or relay exists) by default.
+ This is because of the known bug where definition of
+ both a LOCAL_RELAY and a MAIL_HUB causes $=L to ignore
+ both and deliver into the local mailbox.
+ CONFIG: Move up bitdomain and uudomain handling so that they
+ are done before .UUCP class matching; uudomain was
+ reported as ineffective before. This also frees up
+ diversion 8 for future use. Problem reported by Kimmo
+ Suominen.
+ CONFIG: Don't try to convert dotted IP address (e.g., [1.2.3.4])
+ into host names. As pointed out by Jonathan Kamens,
+ these are often used because either the forward or reverse
+ mapping is broken; this translation makes it broken again.
+ DOC: Clarify $@ and $: in the Install & Op Guide. From Kimmo
+ Suominen.
+ Portability fixes:
+ Unicos from David L. Kensiski of Sterling Sofware.
+ DomainOS from Don Lewis of Silicon Systems.
+ GNU m4 1.0.3 from Karst Koymans of Utrecht University.
+ Convex from Kimmo Suominen <kim@tac.nyc.ny.us>.
+ NetBSD from Adam Glass <glass@sun-lamp.cs.berkeley.edu>.
+ BSD/386 from Tony Sanders of BSDI.
+ Apollo from Eric Wassenaar.
+ DGUX from Doug Anderson.
+ Sequent DYNIX/ptx 2.0 from Tim Wright of Sequent.
+ NEW FILES:
+ src/Makefile.DomainOS
+ src/Makefile.PTX
+ src/Makefile.SunOS.5.1
+ src/Makefile.SunOS.5.2
+ src/Makefile.SunOS.5.x
+ src/mailq.1
+ cf/ostype/domainos.m4
+ doc/op/Makefile
+ doc/intro/Makefile
+ doc/usenix/Makefile
+
+8.6.5/8.6.5 94/01/13
+ Security fix: /.forward could be owned by anyone (the test
+ to allow root to own any file was backwards). From
+ Bob Campbell at U.C. Berkeley.
+ Security fix: group ids were not completely set when programs
+ were invoked. This caused programs to have group
+ permissions they should not have had (usually group
+ daemon instead of their own group). In particular,
+ Perl scripts would refuse to run.
+ Security: check to make sure files that are written are not
+ symbolic links (at least under some circumstances).
+ Although this does not respond to a specific known
+ attack, it's just a good idea. Suggested by
+ Christian Wettergren.
+ Security fix: if a user had an NFS mounted home directory on
+ a system with a restricted shell listed in their
+ /etc/passwd entry, they could still execute any
+ program by putting that in their .forward file.
+ This fix prevents that by insisting that their shell
+ appear in /etc/shells before allowing a .forward to
+ execute a program or write a file. You can disable
+ this by putting "*" in /etc/shells. It also won't
+ permit world-writable :include: files to reference
+ programs or files (there's no way to disable this).
+ These behaviours are only one level deep -- for
+ example, it is legal for a world-writable :include:
+ file to reference an alias that writes a file, on
+ the assumption that the alias file is well controlled.
+ Security fix: root was not treated suspiciously enough when
+ looking into subdirectories. This would potentially
+ allow a cracker to examine files that were publically
+ readable but in a non-publically searchable directory.
+ Fix a problem that causes an error on QUIT on a cached
+ connection to create problems on the current job.
+ These are typically unrelated, so errors occur in
+ the wrong place.
+ Reset CurrentLA in sendall() -- this makes sendmail queue
+ runs more responsive to load average, and fixes a
+ problem that ignored the load average in locally
+ generated mail. From Eric Wassenaar.
+ Fix possible core dump on aliases with null LHS. From
+ John Orthoefer of BB&N.
+ Revert to using flock() whenever possible -- there are just
+ too many bugs in fcntl() locking, particularly over
+ NFS, that cause sendmail to fail in perverse ways.
+ Fix a bug that causes the connection cache to get confused
+ when sending error messages. This resulted in
+ "unexpected close" messages. It should fix itself
+ on the following queue run. Problem noted by
+ Liudvikas Bukys of the University of Rochester.
+ Include $k in $=k as documented in the Install & Op Guide.
+ This seems odd, but it was documented.... From
+ Michael Corrigan of UCSD.
+ Fix problem that caused :include:s from alias files to be
+ forced to be owned by root instead of daemon
+ (actually DefUid). From Tim Irvin.
+ Diagnose unrecognized I option values -- from Mortin Forssen
+ of the Chalmers University of Technology.
+ Make "error" mailer work consistently when there is no error
+ code associated with it -- previously it returned OK
+ even though there was a real problem. Now it assumes
+ EX_UNAVAILABLE.
+ Fix bug that caused the last header line of messages that had
+ no body and which were terminated with EOF instead of
+ "." to be discarded. Problem noted by Liudvikas Bukys.
+ Fix core dump on SMTP mail to programs that failed -- it tried
+ to go to a "next MX host" when none existed, causing
+ a core dump. From der Mouse at McGill University.
+ Change IDENTPROTO from a defined/not defined to a 0/1 switch;
+ this makes it easier to turn it off (using
+ -DIDENTPROTO=0 in the Makefile). From der Mouse.
+ Fix YP_MASTER_NAME store to use the unupdated result of
+ gethostname() (instead of myhostname(), which tries
+ to fully qualify the name) to be consistent with
+ SunOS. If your hostname is unqualified, this fixes
+ transfers to slave servers. Bug noted by Keith
+ McMillan of Ameritech Services, Inc.
+ Fix Ultrix problem: gethostbyname() can return a very large
+ (> 500) h_length field, which causes the sockaddr
+ to be trashed. Use the size of the sockaddr instead.
+ Fix from Bob Manson of Ohio State.
+ Don't assume "-a." on host lookups if NAMED_BIND is not
+ defined -- this confuses gethostbyname on hosts
+ file lookups, which doesn't understand the trailing
+ dot convention.
+ Log SMTP server subprocesses that die with a signal instead
+ of from a clean exit.
+ If you don't have option "I" set, don't assume that a DNS
+ "host unknown" message is authoritative -- it
+ might still be found in /etc/hosts.
+ Fix a problem that would cause Deferred: messages to be sent
+ as the subject of an error message, even though the
+ actual cause of a message was more severe than that.
+ Problem noted by Chris Seabrook of OSSI.
+ Fix race condition in DBM alias file locking. From Kyle
+ Jones of UUNET.
+ Limit delivery syslog line length to avoid bugs in some
+ versions of syslog(3). This adds a new compile time
+ variable SYSLOG_BUFSIZE. From Jay Plett of Princeton
+ University, which is in turn derived from IDA.
+ Fix quotes inside of comments in addresses -- previously
+ it insisted that they be balanced, but the 822 spec
+ says that they should be ignored.
+ Dump open file state to syslog upon receiving SIGUSR1 (for
+ debugging). This also evaluates ruleset 89, if set
+ (with the null input), and logs the result. This
+ should be used sparingly, since the rewrite process
+ is not reentrant.
+ Change -qI, -qR, and -qS flags to be case-insensitive as
+ documented in the Bat Book.
+ If the mailer returned EX_IOERR or EX_OSERR, sendmail did not
+ return an error message and did not requeue the message.
+ Fix based on code from Roland Dirlewanger of
+ Reseau Regional Aquarel, Bordeaux, France.
+ Fix a problem that caused a seg fault if you got a 421 error
+ code during some parts of connection initialization.
+ I've only seen this when talking to buggy mailers on
+ the other end, but it shouldn't give a seg fault in
+ any case. From Amir Plivatsky.
+ Fix core dump caused by a ruleset call that returns null.
+ Fix from Bryan Costales of ICSI.
+ Full-Name: field was being ignored. Fix from Motonori Nakamura
+ of Kyoto University.
+ Fix a possible problem with very long input lines in setproctitle.
+ From P{r Emanuelsson.
+ Avoid putting "This is a warning message" out on return receipts.
+ Suggested by Douglas Anderson.
+ Detect loops caused by recursive ruleset calls. Suggested by
+ Bryan Costales.
+ Initialize non-alias maps during alias rebuilds -- they may be
+ needed for parsing. Problem noted by Douglas Anderson.
+ Log sender address even if no message was collected in SMTP
+ (e.g., if all RCPTs failed). Suggested by Motonori
+ Nakamura.
+ Don't reflect the owner-list contents into the envelope sender
+ address if the value contains ", :, /, or | (to avoid
+ illegal addresses appearing there).
+ Efficiency hack for toktype macro -- from Craig Partridge of
+ BB&N.
+ Clean up DNS error printing so that a host name is always
+ included.
+ Remember to set $i during queue runs. Reported by Stephen
+ Campbell of Dartmouth University.
+ If the environment variable HOSTALIASES is set, use it during
+ canonification as the name of a file with per-user host
+ translations so that headers are properly mapped. Reported
+ by Anne Bennett of Concordia University.
+ Avoid printing misleading error message if SMTP mailer (not
+ using [IPC]) should die on a core dump.
+ Avoid incorrect diagnosis of "file 1 closed" when it is caused
+ by the other end closing the connection. From
+ Dave Morrison of Oracle.
+ Improve several of the error messages printed by "mailq"
+ to include a host name or other useful information.
+ Add NetInfo preliminary support for NeXT systems. From Vince
+ DeMarco.
+ Fix a glitch that sometimes caused :include:s that pointed to
+ NFS filesystems that were down to give an "aliasing/
+ forwarding loop broken" message instead of queueing
+ the message for retry. Noted by William C Fenner of
+ the NRL Connection Machine Facility.
+ Fix a problem that could cause a core dump if the input sequence
+ had (or somehow acquired) a \231 character.
+ Make sure that route-addrs always have <angle brackets> around
+ them in non-SMTP envelopes (SMTP envelopes already do
+ this properly).
+ Avoid wierd headers on unbalanced punctuation of the form:
+ ``Joe User <user)'' -- this caused reference to the
+ null macro. Fix from Rick McCarty of IO.COM.
+ Fix a problem that caused an alias "user: user@local.host" to
+ not have the QNOTREMOTE bit set; this caused configs
+ to act as if FEATURE(notsticky) was defined even when
+ it was not. The effect of the problem was to make it
+ very hard to to set up satellite sites that had a few
+ local accounts, with everything else forwarded to a
+ corporate hub. Reported by Detlef Drewanz of the
+ University of Rostock and Mark Frost of NCD.
+ Change queuing to not call rulesets 3, {1 or 2}, 4 on header
+ addresses. This is more efficient (fewer name server
+ calls) and fixes certain unusual configurations, such
+ as those that have ruleset 4 do something that is
+ non-idempotent unless a mailer-specific ruleset did
+ something else. Problem reported by Brian J. Coan
+ of the Institute for Global Communications.
+ Fix the "obsolete argument" routine in main to better understand
+ new arguments. For example, if you used ``sendmail
+ -C config -v -q'' it would choke on the -q because
+ the -C would stop looking for old-format arguments.
+ Fix the code that was intended to allow two users to forward their
+ mail to the same program and have them appear unique.
+ Portability fixes for:
+ SCO UNIX from Murray Kucherawy.
+ SCO Open Server 3.2v4 from Philippe Brand.
+ System V Release 4 from Rick Ellis and others.
+ OSF/1 from Steve Campbell.
+ DG/UX from Ben Mesander of the USGS and Bryan Curnutt
+ of Stoner Associates.
+ Motorola SysV88 from Kevin Johnson of Motorola.
+ Solaris 2.3 from Casper H.S. Dik of the University
+ of Amsterdam and John Caruso of University
+ of Maryland.
+ FreeBSD from Ollivier Robert.
+ NetBSD from Adam Glass.
+ TitanOS from Kate Hedstrom of Rutgers University.
+ Irix from Bryan Curnutt.
+ Dynix from Jim Davis of the University of Arizona.
+ RISC/os.
+ Linux from John Kennedy of California State University
+ at Chico.
+ Solaris 2.x from Tony Boner of the U.S. Air Force.
+ NEXTSTEP 3.x from Vince DeMarco.
+ HP-UX from various people. NOTA BENE: the location
+ of the config file has moved to /usr/lib
+ to match the HP-UX version of sendmail.
+ CONFIG: Don't do any recipient rewriting on relay mailer;
+ since this is intended only for internal use, the
+ usual RFC 821/822/1123 rules can be relaxed. The
+ main point of this is to avoid munging (ugh) UUCP
+ addresses when relaying internally.
+ CONFIG: fix typo in mailer/uucp.m4 that mutilates list:;
+ syntax addresses delivered via UUCP. Solution
+ provided by Peter Wemm.
+ CONFIG: fix thumb-fumble in default UUCP relaying in ruleset
+ zero; it caused double @ signs in addresses. From
+ Irving Reid of the University of Toronto.
+ CONFIG: Portability fixes for SCO Unix 3.2 with TCP/IP 1.2.1
+ from Markku Toijala of ICL Personal Systems Oy.
+ CONFIG: Add trailing "." on pseudo-domains for consistency;
+ this fixes a problem (noted by Al Whaley of Sunnyside)
+ that made it hard to recognize your own pseudodomain
+ names.
+ CONFIG: catch "@host" syntax errors (i.e., null local-parts)
+ rather than letting them get "local configuration
+ error"s. Problem noted by John Gardiner Myers.
+ CONFIG: add uucp-uudom mailer variant, based on code posted
+ by Spider Boardman <spider@Orb.Nashua.NH.US>; this
+ has uucp-dom semantics but old UUCP syntax. This
+ also permits "uucp-old" as an alias for "uucp" and
+ "uucp-new" as a synonym for "suucp" for consistency.
+ CONFIG: add POP mailer support (from Kimmo Suominen
+ <kim@grendel.lut.fi>).
+ CONFIG: drop CSNET_RELAY support -- CSNET is long gone.
+ CONFIG: fix bug caused with domain literal addresses (e.g.,
+ ``[128.32.131.12]'') when FEATURE(allmasquerade)
+ was set; it would get an additional @masquerade.host
+ added to the address. Problem noted by Peter Wan
+ of Georgia Tech.
+ CONFIG: make sure that the local UUCP name is in $=w. From
+ Jim Murray of Stratus.
+ CONFIG: changes to UUCP rewriting to simulate IDA-style "V"
+ mailer flag. Briefly, if you are sending to host
+ "foo", then it rewrites "foo!...!baz" to "...!baz",
+ "foo!baz" remains "foo!baz", and anything else has
+ the local name prepended.
+ CONFIG: portability fixes for HP-UX.
+ DOC: several minor problems fixed in the Install & Op Guide.
+ MAKEMAP: fix core dump problem on lines that are too long or
+ which lack newline. From Mark Delany.
+ MAILSTATS: print sums of columns (total messages & kbytes
+ in and out of the system). From Tom Ferrin of UC
+ San Francisco Computer Graphics Lab.
+ SIGNIFICANT USER- OR SYSAD-VISIBLE CHANGES:
+ On HP-UX, /etc/sendmail.cf has been moved to
+ /usr/lib/sendmail.cf to match HP sendmail.
+ Permissions have been tightened up on world-writable
+ :include: files and accounts that have shells
+ that are not listed in /etc/shells. This may
+ cause some .forward files that have worked
+ before to start failing.
+ SIGUSR1 dumps some state to the log.
+ NEW FILES:
+ src/Makefile.DGUX
+ src/Makefile.Dynix
+ src/Makefile.FreeBSD
+ src/Makefile.Mach386
+ src/Makefile.NetBSD
+ src/Makefile.RISCos
+ src/Makefile.SCO
+ src/Makefile.SVR4
+ src/Makefile.Titan
+ cf/mailer/pop.m4
+ cf/ostype/bsdi1.0.m4
+ cf/ostype/dgux.m4
+ cf/ostype/dynix3.2.m4
+ cf/ostype/sco3.2.m4
+ makemap/Makefile.dist
+ praliases/Makefile.dist
+
+8.6.4/8.6.4 93/10/31
+ Repair core-dump problem (write to read-only memory segment)
+ if you fall back to the return-to-Postmaster case in
+ savemail. Problem reported by Richard Liu.
+ Immediately diagnose bogus sender addresses in SMTP. This
+ makes quite certain that crackers can't use this
+ class of attack.
+ Reliability Fix: check return value from fclose() and fsync()
+ in a few critical places.
+ Minor problem in initsys() that reversed a condition for
+ redirecting the output channel on queue runs. It's
+ not clear this code even does anything. From Eric
+ Wassenaar of the Dutch National Institute for Nuclear
+ and High-Energy Physics.
+ Fix some problems that caused queue runs to do "too much work",
+ such as double-reading the Errors-To: header. From
+ Eric Wassenaar.
+ Error messages on writing the temporary file (including the
+ data file) were getting suppressed in SMTP -- this
+ fix causes them to be properly reported. From Eric
+ Wassenaar.
+ Some changes to support AF_UNIX sockets -- this will only
+ really become relevant in the next release, but some
+ people need it for local patches. From Michael
+ Corrigan of UC San Diego.
+ Use dynamically allocated memory (instead of static buffers)
+ for macros defined in initsys() and settime(); since
+ these can have different values depending on which
+ envelope they are in. From Eric Wassenaar.
+ Improve logging to show ctladdr on to= logging; this tells you
+ what uid/gid processes ran as.
+ Fix a problem that caused error messages to be discarded if
+ the sender address was unparseable for some reason;
+ this was supposed to fall back to the "return to
+ postmaster" case.
+ Improve aliaswait backoff algorithm.
+ Portability patches for Linux (8.6.3 required another header
+ file) (from Karl London) and SCO UNIX.
+ CONFIG: patch prog mailer to not strip host name off of envelope
+ addresses (so that it matches local again). From
+ Christopher Davis.
+ CONFIG: change uucp-dom mailer so that "<>" translates to $n;
+ this prevents uux from seeing lines with null names like
+ ``From Sat Oct 30 14:55:31 1993''. From Motonori
+ Nakamura of Kyoto University.
+ CONFIG: handle <list:;> syntax correctly. This isn't legal, but
+ it shouldn't fail miserably. From Motonori Nakamura.
+
+8.6.2/8.6.2 93/10/15
+ Put a "successful delivery" message in the transcript for
+ addresses that get return-receipts.
+ Put a prominent "this is only a warning" message in warning
+ messages -- some people don't read carefully enough
+ and end up sending the message several times.
+ Include reason for temporary failure in the "warning" return
+ message. Currently, it just says "cannot send for
+ four hours".
+ Fix the "Original message received" time generated for
+ returntosender messages. It was previously listed as
+ the current time. Bug reported by Eric Hagberg of
+ Cornell University Medical College.
+ If there is an error when writing the body of a message,
+ don't send the trailing dot and wait for a response
+ in sender SMTP, as this could cause the connection to
+ hang up under some bizarre circumstances. From Eric
+ Wassenaar.
+ Fix some server SMTP synchronization problems caused when
+ connections fail during message collection. From
+ Eric Wassenaar.
+ Fix a problem that can cause srvrsmtp to reject mail if the
+ name server is down -- it accepts the RCPT but rejects
+ the DATA command. Problem reported by Jim Murray of
+ Stratus.
+ Fix a problem that can cause core dumps if the config file
+ incorrectly resolves to a null hostname. Reported by
+ Allan Johannesen of WPI.
+ Non-root use of -C flag, dangerous -f flags, and use of -oQ
+ by non-root users were not put into
+ X-Authentication-Warning:s as intended because the
+ config file hadn't set the PrivacyFlags yet. Fix
+ from Sven-Ove Westberg of the University of Lulea.
+ Under very odd circumstances, the alias file rebuild code
+ could get confused as to whether a database was
+ open or not.
+ Check "vendor code" on the end of V lines -- this is
+ intended to provide a hook for vendor-specific
+ configuration syntax. (This is a "new feature",
+ but I've made an exception to my rule in a belief
+ that this is a highly exceptional case.)
+ Portability fixes for DG/UX (from Douglas Anderson of NCSC),
+ SCO Unix (from Murray Kucherawy), A/UX, and OSF/1
+ (from Jon Forrest of UC Berkeley)
+ CONFIG: fix ``mailer:host'' form of UUCP relay naming.
+
+8.6.1/8.6 93/10/08
+ Portability fixes for A/UX and Encore UMAX V.
+ Fix error message handling -- if you had a name server down
+ causing an error during parsing, that message was never
+ propogated to the queue file.
+
+8.6/8.6 93/10/05
+ Configuration cleanup: make it easier to undo IDENTPROTO in
+ conf.h (other systems have the same bug).
+ If HASGETDTABLESIZE and _SC_OPEN_MAX are both defined, assume
+ getdtablesize() instead of sysconf(); a disturbingly
+ large number of systems defined _SC_OPEN_MAX in the
+ header files but don't have the syscall.
+ Another patch to really truly ignore MX records in getcanonname
+ if trymx == FALSE.
+ Fix problem that caused the "250 IAA25499 Message accepted for
+ delivery" message to be omitted if there was an error
+ in the header of the message (e.g., a bad Errors-To:
+ line). Pointed out by Michael Corrigan of UCSD.
+ Announce name of host we are chatting when we get errors; this
+ is an IDA-ism suggested by Christophe Wolfhugel.
+ Portability fixes for Alpha OSF/1 (from Anthony Baxter of the
+ Australian Artificial Intelligence Institute), SCO Unix
+ (from Murray Kucherawy of Hookup Communication Corp.),
+ NeXT (from Vince DeMarco and myself), Linux (from
+ Karl London <karl@borg.demon.co.uk>), BSDI (from
+ Christophe Wolfhugel, and SVR4 on Dell (from Kimmo
+ Suominen), AUX 3.0 on Macintosh, and ANSI C compilers.
+ Some changes to get around gcc optimizer bugs. From Takahiro
+ Kanbe.
+ Fix error recovery in queueup if another tf file of the same
+ name already exists. Problem stumbled over by Bill
+ Wisner of The Well.
+ Output YP_MASTER_NAME and YP_LAST_MODIFIED without null bytes.
+ Problem noted by Keith McMillan of Ameritech Services.
+ Deal with group permissions properly when opening .forward and
+ :include: files. This relaxes the 8.1C restrictions
+ slightly more. This includes proper setting of groups
+ when reading :include: files, allowing you to read some
+ files that you should be able to read but have previously
+ been denied unless you owned them or they had "other"
+ read permission.
+ Make certain that $j is in $=w (after the .cf is read) so that
+ if the user is forced to override some silly system,
+ MX suppression will still work.
+ Fix a couple of efficiency problems where newstr was double-
+ calling expensive routines. In at least one case, it
+ wasn't guaranteed that they would always return the
+ same result. Problem noted by Christophe Wolfhugel.
+ Fix null pointer dereference in putoutmsg -- only on an error
+ condition from a non-SMTP mailer. From Motonori
+ Nakamura.
+ Macro expand "C" line class definitions before scanning so that
+ "CX $Z" works.
+ Fix problem that caused error message to be sent while still
+ trying to send the original message if the connection
+ is closed during a DATA command after getting an error
+ on an RCPT command (pretty obscure). Problem reported
+ by John Myers of CMU.
+ Fix reply to NOOP to be 250 instead of 200 -- this is a long
+ term bug.
+ Fix a nasty bug causing core dumps when returning the "warning:
+ cannot deliver for N hours -- will keep trying" message;
+ it only occurred if you had PostMasterCopy set and
+ only on some architectures. Although sendmail would
+ keep trying, it would send error messages on each
+ queue interval. This is an important fix.
+ Allow u and g options to take user and group names respectively.
+ Don't do a chdir into the queue directory in -bt mode to make
+ ruleset testing a bit easier.
+ Don't allow users to turn off logging (using -oL) on the command
+ line -- command line can only raise, not lower, logging
+ level.
+ Set $u to the original recipient on the SMTP transaction or on
+ the command line. This is only done if there is exactly
+ one recipient. Technically, this does not meet the
+ specs, because it does not guarantee a domain on the
+ address.
+ Fix a problem that dumped error messages on bad addresses if
+ you used the -t flag. Problem noted by Josh Smith of
+ Harvey Mudd College.
+ Given an address such as ``<foo> <bar>'', auto-quote the first
+ ``<foo>'' part, giving ``"<foo>" <bar>''. This is to
+ avoid the problem of people who use angle brackets in
+ their full name information.
+ Fix a null pointer dereference if you set option "l", have
+ an Errors-To: header in the message, and have Errors-To:
+ defined in the config file H lines. From J.R. Oldroyd.
+ Put YPCOMPAT on #ifdef NIS instead -- it's one less thing to get
+ wrong when compiling. Suggested by Rick McCarty of TI.
+ Fix a problem that could pass negative SIZE parameter if the
+ df file got lost; this would cause servers to always
+ give a temporary failure, making the problem even worse.
+ Problem noted by Allan Johannesen of WPI.
+ Add "ident" timeout (one of the "r" option selectors) for IDENT
+ protocol timeouts (30s default). Requested by Murray
+ Kucherawy of HookUp Communication Corp. to handle bogus
+ PC TCP/IP implementations.
+ Change $w default definition to be just the first component of
+ the domain name on config level 5. The $j macro defaults
+ to the FQDN; $m remains as before. This lets well-behaved
+ config files use any of the short, long, or subdomain
+ names.
+ Add makesendmail script in src to try to automate multi-architecture
+ builds. I know, this is sub-optimal, but it is still
+ helpful.
+ Fix very obscure race condition that can cause a queue run to
+ get a queue file for an already completed job. This
+ problem has existed for years. Problem noted by the
+ long suffering Allan Johannesen of WPI.
+ Fix a problem that caused the raw sender name to be passed to
+ udbsender instead of the canonified name -- this caused
+ it to sometimes miss records that it should have found.
+ Relax check of name on HELO packet so that a program using -bs
+ that claims to be itself works properly.
+ Restore rewriting of $: part of address through 2, R, 4 in
+ buildaddr -- this requires passing a lot of flags to get
+ it right. Unlike old versions, this ONLY rewrites
+ recipient addresses, not sender addresses.
+ Fix a bug that caused core dumps in config files that cannot
+ resolve /file/name style addresses. Fix from Jonathan
+ Kamens of OpenVision Technologies.
+ Fix problem with fcntl locking that can cause error returns to
+ be lost if the lock is lost; this required fully
+ queueing everything, dropping the envelope (so errors
+ would get returned), and then re-reading the queue from
+ scratch.
+ Fix a problem that caused aliases that redefine an otherwise
+ true address to still send to the original address
+ if and only if the alias failed in certain bizarre
+ ways (e.g, if they pointed at a list:; syntax address).
+ Problem pointed out by Jonathan Kamens.
+ Remove support for frozen configuration files. They caused
+ more trouble than it was worth.
+ Fix problem that can cause error messages to get ignored when
+ using both -odb and -t flags. Problem noted by Rob
+ McNicholas at U.C. Berkeley.
+ Include all "normal" variations on hostname in $=w. For example,
+ if the host name is vangogh.cs.berkeley.edu, $=w will
+ contain vangogh, vangogh.cs, and vangogh.cs.berkeley.edu.
+ Add "restrictqrun" privacy flag -- without this, anyone can run
+ the queue.
+ Reset SmtpPhase global on initial connection creation so that
+ messages don't come out with stale information.
+ Pass an "ext" argument to lockfile so that error/log messages
+ will properly reflect the true filename being locked.
+ Put all [...] address forms into $=w -- this eliminates the need
+ for MAXIPADDR in conf.h. Suggested by John Gardiner
+ Myers of CMU.
+ Fix a bug that can cause qf files to be left around even after
+ an SMTP RSET command. Problem and fix from Michael
+ Corrigan.
+ Don't send a PostMasterCopy to errors when the Precedence: is
+ negative. Error reports still go to the envelope
+ sender address.
+ Add LA_SHORT for load averages.
+ Lock sendmail.st file when posting statistics.
+ Add "SendBufSize" and "RcvBufSize" suboptions to "O" option to
+ set the size of the TCP send and receive buffers; if you
+ run over a slow slip line you may need to set these down
+ (although it would be better to fix the SLIP implementation
+ so that it's not necessary to recompile every program
+ that does bulk data transfer).
+ Allow null defaults on $( ... $) lookups. Problem reported by
+ Amir Plivatsky.
+ Diagnose crufty S and V config lines. This resulted from an
+ observation that some people were using the SITE macro
+ without the SITECONFIG macro first, which was causing
+ bogus config files that were not caught.
+ Fix makemap -f flag to turn off case folding (it was turning it
+ on instead). THIS IS A USER VISIBLE CHANGE!!!
+ Fix a problem that caused multiple error messages to be sent if
+ you used "sendmail -t -oem -odb", your system uses fcntl
+ locking, and one of the recipient addresses is unknown.
+ Reset uid earlier in include() so that recursive .forwards or
+ :include:s don't use the wrong uid.
+ If file descriptor 0, 1, or 2 was closed when sendmail was
+ called, the code to recover the descriptor was broken.
+ This sometimes (only sometimes) caused problems with the
+ alias file. Fix from Motonori Nakamura.
+ Fix a problem that caused aliaswait to go into infinite recursion
+ if the @:@ metasymbol wasn't found in the alias file.
+ Improve error message on newaliases if database files cannot be
+ opened or if running with no database format defined.
+ Do a better estimation of the size of error messages when NoReturn
+ is set. Problem noted by P{r (Pell) Emanuelsson.
+ Fix a problem causing the "c" option (don't connect to expensive
+ mailers) to be ignored in SMTP. Problem noted and the
+ solution suggested by Robert Elz of Munnari University.
+ Improve connection caching algorithm by passing "[host]" to
+ hostsignature, which strips the square brackets and
+ returns the real name. This allows mailertable entries
+ to match regular entries.
+ Re-enable Return-Receipt-To: -- people seem to want this stupid
+ feature, even if it doesn't work right.
+ Catch and log attempts to try the "wiz" command in server SMTP.
+ This also ups the log level from LOG_NOTICE to LOG_CRIT.
+ Be more generous at assigning $z to the home directory -- do this
+ for programs that are specified through a .forward file.
+ Fix from Andrew Chang of Sun Microsystems.
+ Always save a fatal error message in preference to a non-fatal
+ error message so that the "subject" line of return
+ messages is the best possible.
+ CONFIG: reduce the number of quotes needed to quote configuration
+ parameters with commas: two quotes should work now, e.g.,
+ define(ALIAS_FILE, ``/etc/aliases,/etc/aliases.local'').
+ CONFIG: class $=Z is a set of UUCP hosts that use uucp-dom
+ connections (domain-ized UUCP).
+ CONFIG: fix bug in default maps (-o must be before database file
+ name). Pointed out by Christophe Wolfhugel.
+ CONFIG: add FEATURE(nodns) to state that we are not relying on
+ DNS. This would presumably be used in UUCP islands.
+ CONFIG: add OSTYPE(nextstep) and OSTYPE(linux).
+ CONFIG: log $u in Received: line. This is in technical violation
+ of the standards, since it doesn't guarantee a domain
+ on the address.
+ CONFIG: don't assume "m" in local mailer flags -- this means that
+ if you redefine LOCAL_MAILER_FLAGS you will have to include
+ the "m" flag should you want it. Apparently some Solaris 2.2
+ installations can't handle multiple local recipients.
+ Problem noted by Josh Smith.
+ CONFIG: add confDOMAIN_NAME to set $j (if undefined, $j defaults).
+ CONFIG: change default version level from 4 to 5.
+ CONFIG: add FEATURE(nullclient) to create a config file that
+ forwards all mail to a hub without ever looking at the
+ addresses in any detail.
+ CONFIG: properly strip mailer: information off of relays when
+ used to change .BITNET form into %-hack form.
+ CONFIG: fix a problem that caused infinite loops if presented
+ with an address such as "!foo".
+ CONFIG: check for self literal (e.g., [128.32.131.12]) even if
+ the reverse "PTR" mapping is broken. There's a better
+ way to do this, but the change is fairly major and I
+ want to hold it for another release. Problem noted by
+ Bret Marquis.
+
+8.5/8.5 93/07/23
+ Serious bug: if you used a command line recipient that was unknown
+ sendmail would not send a return message (it was treating
+ everything as though it had an SMTP-style client that
+ would do the return itself). Problem noted by Josh Smith.
+ Change "trymx" option in getcanonname() to ignore all MX data,
+ even during a T_ANY query. This actually didn't break
+ anything, because the only time you called getcanonname
+ with !trymx was if you already knew there were no MX
+ records, but it is somewhat cleaner. From Motonori
+ Nakamura.
+ Don't call getcanonname from getmxrr if you already know there
+ are no DNS records matching the name.
+ Fix a problem causing error messages to always include "The
+ original message was received ... from localhost".
+ The correct original host information is now included.
+ Previous change to cf/sh/makeinfo.sh doesn't port to Ultrix (their
+ version of "test" doesn't have the -x flag). Change it
+ to use -f instead. From John Myers.
+ CONFIG: 8.4 mistakenly set the default SMTP-style mailer to
+ esmtp -- it should be smtp.
+ CONFIG: send all relayed mail using confRELAY_MAILER (defaults
+ to "relay" (a variant of "smtp") if MAILER(smtp) is used,
+ else "suucp" if MAILER(uucp) is used, else "unknown");
+ this cleans up the configs somewhat. This fixes a serious
+ problem that caused route-addrs to get mistaken as relays,
+ pointed out by John Myers. WARNING: this also causes
+ the default on SMART_HOST to change from "suucp" to
+ "relay" if you have MAILER(smtp) specified.
+
+8.4/8.4 93/07/22
+ Add option `w'. If you receive a message that comes to you because
+ you are the best (lowest preference) target of an MX, and
+ you haven't explicitly recognized the source MX host in
+ your .cf file, this option will cause you to try the target
+ host directly (as if there were no MX for it at all). If
+ `w' is not set, this case is a configuration error.
+ Beware: if `w' is set, senders may get bogus errors like
+ "message timed out" or "host unknown" for problems that
+ are really configuration errors. This option is
+ disrecommended, provided only for compatibility with
+ UIUC sendmail.
+ Fix a problem that caused the incoming socket to be left open
+ when sendmail forks after the DATA command. This caused
+ calling systems to wait in FIN_WAIT_2 state until the
+ entire list was processed and the child closed -- a
+ potentially prodigious amount of time. Problem noted
+ by Neil Rickert.
+ Fix problem (created in 6.64) that caused mail sent to multiple
+ addresses, one of which was a bad address, to completely
+ suppress the sending of the message. This changes
+ handling of EF_FATALERRS somewhat, and adds an
+ EF_GLOBALERRS flag. This also fixes a potential problem
+ with duplicate error messages if there is a syntax error
+ in the header of a message that isn't noticed until late
+ in processing. Original problem pointed out by Josh Smith
+ of Harvey Mudd College. This release includes quite a bit
+ of dickering with error handling (see below).
+ Back out SMTP transaction if MAIL gets nested 501 error. This
+ will only hurt already-broken software and should help
+ humans.
+ Fix a problem that broke aliases when neither NDBM nor NEWDB were
+ compiled in. It would never read the alias file.
+ Repair unbalanced `)' and `>' (the "open" versions are already
+ repaired).
+ Logging of "done" in dropenvelope() was incorrect: it would
+ log this even when the queue file still existed. Change
+ this to only log "done" (at log level 11) when the
+ queue file is actually removed. From John Myers.
+ Log "lost connection" in server SMTP at log level 20 if there
+ is no pending transaction. Some senders just close the
+ connection rather than sending QUIT.
+ Fix a bug causing getmxrr to add a dot to the end of unqualified
+ domains that do not have MX records -- this would cause
+ the subsequent host name lookup to fail. The problem
+ only occurred if you had FEATURE(nocanonify) set.
+ Problem noted by Rick McCarty of Texas Instruments.
+ Fix invocation of setvbuf when passed a -X flag -- I had
+ unwittingly used an ANSI C extension, and this caused
+ core dumps on some machines.
+ Diagnose self-destructive alias loops on RCPT as well as EXPN.
+ Previously it just gave an empty send queue, which
+ then gave either "Need RCPT (recipient)" at the DATA
+ (confusing, since you had given an RCPT command which
+ returned 250) or just dropped the email, depending on
+ whether you were running VERBose mode. Now it usually
+ diagnoses this case as "aliasing/forwarding loop broken".
+ Unfortunately, it still doesn't adequately diagnose
+ some true error conditions.
+ Add internal concept of "warning messages" using 6xx codes.
+ These are not reported only to Postmaster. Unbalanced
+ parens, brackets, and quotes are printed as 653 codes.
+ They are always mapped to 5xx codes before use in SMTP.
+ Clean up error messages to tell both the actual address that
+ failed and the alias they arose from. This makes it
+ somewhat easier to diagnose problems. Difficulty noted
+ by Motonori Nakamura.
+ Fix a problem that inappropriately added a ctladdr to addresses
+ that shouldn't have had one during a queue run. This
+ caused error messages to be handled differently during
+ a queue run than a direct run.
+ Don't print the qf name and line number if you get errors during
+ the direct run of the queue from srvrsmtp -- this was
+ just extra stuff for users to crawl through.
+ Put command line flags on second line of pid file so you can
+ auto-restart the daemon with all appropriate arguments.
+ Use "kill `head -1 /etc/sendmail.pid`" to stop the
+ daemon, and "eval `tail -1 /etc/sendmail.pid`" to
+ restart it.
+ Remove the ``setuid(getuid())'' in main -- this caused the
+ IDENT daemon to screw up. This required that I change
+ HASSETEUID to HASSETREUID and complicate the mode
+ changing somewhat because both Ultrix and SunOS seem
+ to have a bug causing seteuid() to set the saved uid
+ as well as the effective. The program test/t_setreuid.c
+ will test to see if your implementation of setreuid(2)
+ is appropriately functional.
+ The FallBackMX (option V) handling failed to properly identify
+ fallback to yourself -- most of the code was there,
+ but it wasn't being enabled. Problem noted by Murray
+ Kucherawy of the University of Waterloo.
+ Change :include: open timeout from ETIMEDOUT to an internal
+ code EOPENTIMEOUT; this avoids adding "during SmtpPhase
+ with CurHostName" in error messages, which can be
+ confusing. Reported by Jonathan Kamens of OpenVision
+ Technologies.
+ Back out setpgrp (setpgid on POSIX systems) call to reset the
+ process group id. The original fix was to get around
+ some problems with recalcitrant MUAs, but it breaks
+ any call from a shell that creates a process group id
+ different from the process id. I could try to fix
+ this by diddling the tty owner (using tcsetpgrp or
+ equivalent) but this is too likely to break other
+ things.
+ Portability changes:
+ Support -M as equivalent to -oM on Ultrix -- apparently
+ DECnet calls sendmail with -MrDECnet -Ms<HOST> -bs
+ instead of using standard flags. Oh joy. This
+ behaviour reported by Jon Giltner of University
+ of Colorado.
+ SGI IRIX -- this includes several changes that should
+ help other strict ANSI compilers.
+ SCO Unix -- from Murray Kucherawy of HookUp Communication
+ Corporation.
+ Solaris running the Sun C compiler (which despite the
+ documentation apparently doesn't define
+ __STDC__ by default).
+ ConvexOS from Eric Schnoebelen of Convex.
+ Sony NEWS workstations and Omron LUNA workstations from
+ Motonori Nakamura.
+ CONFIG: add confTRY_NULL_MX_LIST to set option `w'.
+ CONFIG: delete `C' and `e' from default SMTP mailers flags;
+ several people have made a good argument that this
+ creates more problems than it solves (although this
+ may prove painful in the short run).
+ CONFIG: generalize all the relays to accept a "mailer:host"
+ format.
+ CONFIG: move local processing in ruleset 0 into a new ruleset
+ 98 (8 on old sendmail). Domain literal [a.b.c.d]
+ addresses are also passed through this ruleset.
+ CONFIG: if neither SMART_HOST nor MAILER(smtp) were defined,
+ internet-style addresses would "fall off the end" of
+ ruleset zero and be interpreted as local -- however,
+ the angle brackets confused the recursive call.
+ These are now diagnosed as "Unrecognized host name".
+ CONFIG: USENET rules weren't included in S0 because of a mistaken
+ ifdef(`_MAILER_USENET_') instead of
+ ifdef(`_MAILER_usenet_'). Problem found by Rein Tollevik
+ of SINTEF RUNIT, Oslo.
+ CONFIG: move up LOCAL_RULE_0 processing so that it happens very
+ early in ruleset 0; this allows .mc authors to bypass
+ things like the "short circuit" code for local addresses.
+ Prompted by a comment by Bill Wisner of The Well.
+ CONFIG: add confSMTP_MAILER to define the mailer used (smtp or
+ esmtp) to send SMTP mail. This allows you to default
+ to esmtp but use a mailertable or other override to
+ deal with broken servers. This logic was pointed out
+ to me by Bill Wisner. Ditto for confLOCAL_MAILER.
+ Changes to cf/sh/makeinfo.sh to make it portable to SVR4
+ environments. Ugly as sin.
+
+8.3/8.3 93/07/13
+ Fix setuid problems introduced in 8.2 that caused messages
+ like "Cannot create qfXXXXXX: Invalid argument"
+ or "Cannot reopen dfXXXXXX: Permission denied". This
+ involved a new compile flag "HASSETEUID" that takes
+ the place of the old _POSIX_SAVED_IDS -- it turns out
+ that the POSIX interface is broken enough to break
+ some systems badly. This includes some fixes for
+ HP-UX. Also fixes problems where the real uid is
+ not reset properly on startup (from Neil Rickert).
+ Fix a problem that caused timed out messages to not report the
+ addresses that timed out. Error messages are also more
+ "user friendly".
+ Drop required bandwidth on connections from 64 bytes/sec to
+ 16 bytes/sec.
+ Further Solaris portability changes -- doesn't require the BSD
+ compatibility library. This also adds a new
+ "HASGETDTABLESIZE" compile flag which can be used if
+ you want to use getdtablesize(2) instead of sysconf(2).
+ These are loosely based on changes from David Meyer at
+ University of Oregon. This now seems to work, at least
+ for quick test cases.
+ Fix a problem that can cause duplicate error messages to be
+ sent if you are in SMTP, you send to multiple addresses,
+ and at least one of those addresses is good and points
+ to an account that has a .forward file (whew!).
+ Fix a problem causing messages to be discarded if checkcompat()
+ returned EX_TEMPFAIL (because it didn't properly mark
+ the "to" address). Problem noted by John Myers.
+ Fix dfopen to return NULL if the open failed; I was depending
+ on fdopen(-1) returning NULL, which isn't the case. This
+ isn't serious, but does result in wierd error diagnoses.
+ From Michael Corrigan.
+ CONFIG: add UUCP_MAX_SIZE M4 macro to set the maximum size of
+ messages sent through UUCP-family mailers. Suggested
+ by Bill Wisner of The Well.
+ CONFIG: if both MAILER(uucp) and MAILER(smtp) are specified,
+ include a "uucp-dom" mailer that uses domain-style
+ addressing. Suggested by Bill Wisner.
+ CONFIG: Add LOCAL_SHELL_FLAGS and LOCAL_SHELL_ARGS to match
+ LOCAL_MAILER_FLAGS and LOCAL_MAILER_ARGS. Suggested by
+ Christophe Wolfhugel.
+ CONFIG: Add OSTYPE(aix3). From Christophe Wolfhugel.
+
+8.2/8.2 93/07/11
+ Don't drop out on config file parse errors in -bt mode.
+ On older configuration files, assume option "l" (use Errors-To
+ header) for back compatibility. NOTE: this DOES NOT
+ imply an endorsement of the Errors-To: header in any way.
+ Accept -x flag on AIX-3 as well as OSF/1. Why, why, why???
+ Don't log errors on EHLO -- it isn't a "real" error for an old
+ SMTP server to give an error on this command, and
+ logging it in the transcript can be confusing. Fix
+ from Bill Wisner.
+ IRIX compatibility changes provided by Dan Rich
+ <drich@sandman.lerc.nasa.gov>.
+ Solaris 2 compatibility changes. Provided by Bob Cunningham
+ <bob@kahala.soest.hawaii.edu>, John Oleynick
+ <juo@klinzhai.rutgers.edu>
+ Debugging: -d17 was overloaded (hostsignature and usersmtp.c);
+ move usersmtp (smtpinit and smtpmailfrom) to -d18 to
+ match the other flags in that file.
+ Flush transcript before fork in mailfile(). From Eric Wassenaar.
+ Save h_errno in mci struct and improve error message display.
+ Changes from Eric Wassenaar.
+ Open /dev/null for the transcript if the create of the xf file
+ failed; this avoids at least one possible null pointer
+ reference in very wierd cases. From Eric Wassenaar.
+ Clean up statistics gathering; it was over-reporting because of
+ forks. From Eric Wassenaar.
+ Fix problem that causes old Return-Path: line to override new
+ Return-Path: line (conf.c needs H_FORCE to avoid
+ re-using old value). From Motonori Nakamura.
+ Fix broken -m flag in K definition -- even if -m (match only)
+ was specified, it would still replace the key with the
+ value. Noted by Rick McCarty of Texas Instruments.
+ If the name server timed out over several days, no "timed out"
+ message would ever be sent back. The timeout code
+ has been moved from markfailure() to dropenvelope()
+ so that all such failures should be diagnosted. Pointed
+ out by Christophe Wolfhugel and others.
+ Relax safefile() constraints: directories in an include or
+ forward path must be readable by self if the controlling
+ user owns the entry, readable by all otherwise (e.g.,
+ when reading your .forward file, you have to own and
+ have X permssion in it; everyone needs X permission in
+ the root and directories leading up to your home);
+ include files must be readable by anyone, but need not
+ be owned by you.
+ If _POSIX_SAVED_IDS is defined, setuid to the owner before
+ reading a .forward file; this gets around some problems
+ on NFS mounts if root permission is not exported and
+ the user's home directory isn't x'able.
+ Additional NeXT portability enhancements from Axel Zinser.
+ Additional HP-UX portability enhancements from Brian Bullen.
+ Add a timeout around SMTP message writes; this assumes you can
+ get throughput of at least 64 bytes/second. Note that
+ this does not impact the "datafinal" default, which
+ is separate; this is just intended to work around
+ network clogs that will occur before the final dot
+ is sent. From Eric Wassenaar.
+ Change map code to set the "include null" flag adaptively --
+ it initially tries both, but if it finds anything
+ matching without a null it never tries again with a
+ null and vice versa. If -N is specified, it never
+ tries without the null and creates new maps with a
+ null byte. If -O is specified, it never tries with
+ the null (for efficiency). If -N and -O are specified,
+ you get -NO (get it?) lookup at all, so this would
+ be a bad idea. If you don't specify either -N or -O,
+ it adapts.
+ Fix recognition of "same from address" so that MH submissions
+ will insert the appropriate full name information;
+ this used to work and got broken somewhere along the
+ way.
+ Some changes to eliminate some unnecessary SYSERRs in the
+ log. For example, if you lost a connection, don't
+ bother reporting that fact on the connection you lost.
+ Add some "extended debugging" flags to try to track down
+ why we get occassional problems with file descriptor
+ one being closed when execing a mailer; it seems to
+ only happen when there has been another error in the
+ same transaction. This requires XDEBUG, defined
+ by default in conf.h.
+ Add "-X filename" command line flag, which logs both sides of
+ all SMTP transactions. This is intended ONLY for
+ debugging bad implementations of other mailers; start
+ it up, send a message from a mailer that is failing,
+ and then kill it off and examine the indicated log.
+ This output is not intended to be particularly human
+ readable. This also adds the HASSETVBUF compile
+ flag, defaulted on if your compiler defines __STDC__.
+ CONFIG: change SMART_HOST to override an SMTP mailer. If you
+ have a local net that should get direct connects, you
+ will need to use LOCAL_NET_CONFIG to catch these hosts.
+ See cf/README for an example.
+ CONFIG: add LOCAL_MAILER_ARGS (default: `mail -d $u') to handle
+ sites that don't use the -d flag.
+ CONFIG: hide recipient addresses as well as sender addresses
+ behind $M if FEATURE(allmasquerade) is specified; this
+ has been requested by several people, but can break
+ local aliases. For example, if you mail to "localalias"
+ this will be rewritten as "localalias@masqueradehost";
+ although initial delivery will work, replies will be
+ broken. Use it sparingly.
+ CONFIG: add FEATURE(domaintable). This maps unqualified domains
+ to qualified domains in headers. I believe this is
+ largely equivalent to the IDA feature of the same name.
+ CONFIG: use $U as UUCP name instead of $k. This permits you
+ to override the "system name" as your UUCP name --
+ in particular, to use domain-ized UUCP names. From
+ Bill Wisner of The Well.
+ CONFIG: create new mailer "esmtp" that always tries EHLO
+ first. This is currently unused in the config files,
+ but could be used in a mailertable entry.
+
+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 Motonori Nakamura 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 Motonori Nakamura 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
+ Motonori Nakamura of Kyoto University.
+ Fix a problem that can cause failure to return errors to Postmaster
+ in certain cases. From Motonori Nakamura.
+ 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 Motonori Nakamura.
+ 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 Motonori Nakamura 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 Motonori Nakamura 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 Motonori Nakamura
+ 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 Motonori Nakamura.
+ 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 Motonori Nakamura.
+ Improvements to MX piggybacking code, from Motonori Nakamura.
+ Fix case where CurHostName points to an auto variable that has
+ been deallocated (from Motonori Nakamura).
+ 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 Motonori Nakamura:
+ 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 Motonori Nakamura 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 Motonori Nakamura).
+
+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.
diff --git a/usr.sbin/sendmail/cf/README b/usr.sbin/sendmail/cf/README
new file mode 100644
index 000000000000..c0fb9106b8af
--- /dev/null
+++ b/usr.sbin/sendmail/cf/README
@@ -0,0 +1,1740 @@
+
+
+ NEW SENDMAIL CONFIGURATION FILES
+
+ Eric Allman <eric@CS.Berkeley.EDU>
+
+ @(#)README 8.80 (Berkeley) 11/19/95
+
+
+This document describes the sendmail configuration files being used
+at Berkeley. These use features in the new (R8) sendmail; they will
+not work on other versions.
+
+These configuration files are probably not as general as previous
+versions, and don't handle as many of the weird 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 weird
+world, things are going to get weirder 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 version 1.1
+also works. Unfortunately, I'm told that the M4 on BSDI 1.0 doesn't
+work -- you'll have to use a Net/2 or GNU version.
+
+IF YOU DON'T HAVE A BERKELEY MAKE, don't despair! Just run
+"m4 ../m4/cf.m4 foo.mc > foo.cf" -- that should be all you need.
+There is also a fairly crude (but functional) Makefile.dist that works
+on the old version of make.
+
+To get started, you may want to look at tcpproto.mc (for TCP-only
+sites), uucpproto.mc (for UUCP-only sites), and clientproto.mc (for
+clusters of clients using a single mail host). 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.
+
+*******************************************************************
+*** BE SURE YOU CUSTOMIZE THESE FILES! They have some ***
+*** Berkeley-specific assumptions built in, such as the name ***
+*** of our UUCP-relay. You'll want to create your own domain ***
+*** description, and use that in place of domain/Berkeley.m4. ***
+*******************************************************************
+
+
++--------------------------+
+| 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.
+You must pre-load "cf.m4":
+
+ m4 ${CFDIR}/m4/cf.m4 config.mc > config.cf
+
+where ${CFDIR} is the root of the cf directory and config.mc is the
+name of your configuration file. If you are running a version of M4
+that understands the __file__ builtin (versions of GNU m4 >= 0.75 do
+this, but the versions distributed with 4.4BSD and derivatives do not)
+or the -I flag (ditto), then ${CFDIR} can be in an arbitrary directory.
+For "traditional" versions, ${CFDIR} ***MUST*** be "..", or you MUST
+use -D_CF_DIR_=/path/to/cf/dir/ -- note the trailing slash! For example:
+
+ m4 -D_CF_DIR_=${CFDIR}/ ${CFDIR}/m4/cf.m4 config.mc > config.cf
+
+Let's examine a typical .mc file:
+
+ 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.
+ #
+
+ #
+ # This is a Berkeley-specific configuration file for HP-UX 9.x.
+ # It applies only the the Computer Science Division at Berkeley,
+ # and should not be used elsewhere. It is provided on the sendmail
+ # distribution as a sample only. To create your own configuration
+ # file, create an appropriate domain file in ../domain, change the
+ # `DOMAIN' macro below to reference that file, and copy the result
+ # to a name of your own choosing.
+ #
+ divert(0)
+
+The divert(-1) will delete the crud in the resulting output file.
+The copyright notice can be replace by whatever your lawyers require;
+our lawyers require the one that I've included in my files. A copyleft
+is a copyright by another name. The divert(0) restores regular output.
+
+ 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.
+
+ OSTYPE(hpux9)dnl
+
+You must specify an OSTYPE to properly configure things such as the
+pathname of the help and status files, the flags needed for the local
+mailer, and other important things. If you omit it, you will get an
+error when you try to build the configuration. Look at the ostype
+directory for the list of known operating system types.
+
+ DOMAIN(CS.Berkeley.EDU)dnl
+
+This example is specific to the Computer Science Division at Berkeley.
+You can use "DOMAIN(generic)" to get a sufficiently bland definition
+that may well work for you, or you can create a customized domain
+definition appropriate for your environment.
+
+ MAILER(local)
+ MAILER(smtp)
+
+These describe the mailers used at the default CS site site. The
+local mailer is always included automatically. Beware MAILER
+declarations should always be last in the configuration file, and
+MAILER(smtp) should always precede MAILER(uucp).
+
+One word of warning: M4 macros are expanded even in lines that appear
+to be comments. For example, if you have
+
+ # See FEATURE(foo) above
+
+it will not do what you expect, because the FEATURE(foo) will be
+expanded. This also applies to
+
+ # And then define the $X macro to be the return address
+
+because ``define'' is an M4 keyword. If you want to use them, surround
+them with directed quotes, `like this'.
+
+
++--------+
+| OSTYPE |
++--------+
+
+You MUST define an operating system environment, or the configuration
+file build will puke. There are several environments available; look
+at the "ostype" directory for the current list. This macro changes
+things like the location of the alias file and queue directory. Some
+of these files are identical to one another.
+
+It is IMPERATIVE that the OSTYPE occur before any MAILER definitions.
+In general, the OSTYPE macro should go immediately after any version
+information, and MAILER definitions should always go last.
+
+Operating system definitions are usually easy to write. They may define
+the following variables (everything defaults, so an ostype file may be
+empty). Unfortunately, the list of configuration-supported systems is
+not as broad as the list of source-supported systems, since many of
+the source contributors do not include corresponding ostype files.
+
+ALIAS_FILE [/etc/aliases] The location of the text version
+ of the alias file(s). It can be a comma-separated
+ list of names (but be sure you quote values with
+ commas in them -- for example, use
+ define(`ALIAS_FILE', `a,b')
+ to get "a" and "b" both listed as alias files;
+ otherwise the define() primitive only sees "a").
+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 [rmn] The flags used by the local mailer. The
+ flags lsDFM are always included.
+LOCAL_MAILER_ARGS [mail -d $u] The arguments passed to deliver local
+ mail.
+LOCAL_MAILER_MAX [undefined] If defined, the maximum size of local
+ mail that you are willing to accept.
+LOCAL_MAILER_CHARSET [undefined] If defined, messages containing 8-bit data
+ that ARRIVE from an address that resolves to the
+ local mailer and which are converted to MIME will be
+ labelled with this character set.
+LOCAL_SHELL_PATH [/bin/sh] The shell used to deliver piped email.
+LOCAL_SHELL_FLAGS [eu] The flags used by the shell mailer. The
+ flags lsDFM are always included.
+LOCAL_SHELL_ARGS [sh -c $u] The arguments passed to deliver "prog"
+ mail.
+LOCAL_SHELL_DIR [$z:/] The directory search path in which the
+ shell should run.
+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.
+USENET_MAILER_MAX [100000] The maximum size of messages that will
+ be accepted by the usenet mailer.
+SMTP_MAILER_FLAGS [undefined] Flags added to SMTP mailer. Default
+ flags are `mDFMUX' for all SMTP-based mailers; the
+ "esmtp" mailer adds `a' and "smtp8" adds `8'.
+SMTP_MAILER_MAX [undefined] The maximum size of messages that will
+ be transported using the smtp, smtp8, or esmtp
+ mailers.
+SMTP_MAILER_ARGS [IPC $h] The arguments passed to the smtp mailer.
+ About the only reason you would want to change this
+ would be to change the default port.
+ESMTP_MAILER_ARGS [IPC $h] The arguments passed to the esmtp mailer.
+SMTP8_MAILER_ARGS [IPC $h] The arguments passed to the smtp8 mailer.
+RELAY_MAILER_ARGS [IPC $h] The arguments passed to the relay mailer.
+SMTP_MAILER_CHARSET [undefined] If defined, messages containing 8-bit data
+ that ARRIVE from an address that resolves to one of
+ the SMTP mailers and which are converted to MIME will
+ be labelled with this character set.
+UUCP_MAILER_FLAGS [undefined] Flags added to UUCP mailer. Default
+ flags are `DFMhuU' (and `m' for uucp-new mailer,
+ minus `U' for uucp-dom mailer).
+UUCP_MAILER_ARGS [uux - -r -z -a$g -gC $h!rmail ($u)] The arguments
+ passed to the UUCP mailer.
+UUCP_MAILER_MAX [100000] The maximum size message accepted for
+ transmission by the UUCP mailers.
+UUCP_MAILER_CHARSET [undefined] If defined, messages containing 8-bit data
+ that ARRIVE from an address that resolves to one of
+ the UUCP mailers and which are converted to MIME will
+ be labelled with this character set.
+FAX_MAILER_PATH [/usr/local/lib/fax/mailfax] The program used to
+ submit FAX messages.
+FAX_MAILER_MAX [100000] The maximum size message accepted for
+ transmission by FAX.
+POP_MAILER_PATH [/usr/lib/mh/spop] The pathname of the POP mailer.
+POP_MAILER_FLAGS [Penu] Flags added to POP mailer. Flags "lsDFM"
+ are always added.
+POP_MAILER_ARGS [pop $u] The arguments passed to the POP mailer.
+PROCMAIL_MAILER_FLAGS [Shu] Flags added to Procmail mailer. Flags
+ ``DFMmn'' are always set.
+PROCMAIL_MAILER_ARGS [procmail -m $h $f $u] The arguments passed to
+ the Procmail mailer.
+PROCMAIL_MAILER_MAX [undefined] If set, the maximum size message that
+ will be accepted by the procmail mailer.
+MAIL11_MAILER_PATH [/usr/etc/mail11] The path to the mail11 mailer.
+MAIL11_MAILER_FLAGS [nsFx] Flags for the mail11 mailer.
+MAIL11_MAILER_ARGS [mail11 $g $x $h $u] Arguments passed to the mail11
+ mailer.
+PH_MAILER_PATH [/usr/local/etc/phquery] The path to the phquery
+ program.
+PH_MAILER_FLAGS [ehmu] Flags for the phquery mailer.
+PH_MAILER_ARGS [phquery -- $u] -- arguments to the phquery mailer.
+CYRUS_MAILER_FLAGS [A5@] The flags used by the cyrus mailer. The
+ flags lsDFMnP are always included.
+CYRUS_MAILER_PATH [/usr/cyrus/bin/deliver] The progam used to deliver
+ cyrus mail.
+CYRUS_MAILER_ARGS [deliver -e -m $h -- $u] The arguments passed
+ to deliver cyrus mail.
+CYRUS_BB_MAILER_FLAGS [undefined] The flags used by the cyrusbb
+ mailer. The flags lsDFMnP are always included.
+CYRUS_BB_MAILER_ARGS [deliver -e -m $u] The arguments passed
+ to deliver cyrusbb mail.
+
+
+
++---------+
+| 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 accept UUCP-addressed email.
+ If not defined, all UUCP sites must be directly
+ connected.
+BITNET_RELAY The host that will accept BITNET-addressed email.
+ If not defined, the .BITNET pseudo-domain won't work.
+DECNET_RELAY The host that will accept DECNET-addressed email.
+ If not defined, the .DECNET pseudo-domain and addresses
+ of the form node::user will not work.
+FAX_RELAY The host that will accept mail to the .FAX pseudo-domain.
+ The "fax" mailer overrides this value.
+LOCAL_RELAY DEPRECATED. 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 only with some user
+ agents.
+LUSER_RELAY The site that will handle lusers -- that is, apparently
+ local names that aren't local accounts or aliases.
+
+Any of these can be either ``mailer:hostname'' (in which case the
+mailer is the internal mailer name, such as ``uucp-new'' and the hostname
+is the name of the host as appropriate for that mailer) or just a
+``hostname'', in which case a default mailer type (usually ``relay'',
+a variant on SMTP) is used. WARNING: if you have a wildcard MX
+record matching your domain, you probably want to define these to
+have a trailing dot so that you won't get the mail diverted back
+to yourself.
+
+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. As a general rule, put the
+MAILER definitions last in your .mc file, and always put MAILER(smtp)
+before MAILER(uucp) -- several features and definitions will modify
+the definition of mailers, and the smtp mailer modifies the UUCP
+mailer.
+
+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. This file actually defines
+ four mailers: "smtp" for regular (old-style) SMTP to
+ other servers, "esmtp" for extended SMTP to other
+ servers, "smtp8" to do SMTP to other servers without
+ converting 8-bit data to MIME (essentially, this is
+ your statement that you know the other end is 8-bit
+ clean even if it doesn't say so), and "relay" for
+ transmission to our RELAY_HOST, LUSER_RELAY, or
+ MAILER_HUB.
+
+uucp The Unix-to-Unix Copy Program mailer. Actually, this
+ defines two mailers, "uucp-old" (a.k.a. "uucp") and
+ "uucp-new" (a.k.a. "suucp"). The latter is for when you
+ know that the UUCP mailer at the other end can handle
+ multiple recipients in one transfer. If the smtp mailer
+ is also included in your configuration, two other mailers
+ ("uucp-dom" and "uucp-uudom") are also defined [warning:
+ you MUST specify MAILER(smtp) before MAILER(uucp)]. When you
+ include the uucp mailer, sendmail looks for all names in
+ the $=U class and sends them to the uucp-old mailer; all
+ names in the $=Y class are sent to uucp-new; and all
+ names in the $=Z class are sent to uucp-uudom. Note that
+ this is a function of what version of rmail runs on
+ the receiving end, and hence may be out of your control.
+ See the section below describing UUCP mailers in more
+ detail.
+
+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.
+
+pop Post Office Protocol.
+
+procmail An interface to procmail (does not come with sendmail).
+ This is designed to be used in mailertables. For example,
+ a common question is "how do I forward all mail for a given
+ domain to a single person?". If you have this mailer
+ defined, you could set up a mailertable reading:
+
+ host.com procmail:/etc/procmailrcs/host.com
+
+ with the file /etc/procmailrcs/host.com reading:
+
+ :0 # forward mail for host.com
+ ! -oi -f $1 person@other.host
+
+ This would arrange for (anything)@host.com to be sent
+ to person@other.host. Within the procmail script, $1 is
+ the name of the sender and $2 is the name of the recipient.
+ If you use this with FEATURE(local_procmail), the FEATURE
+ should be listed first.
+
+mail11 The DECnet mail11 mailer, useful only if you have the mail11
+ program from gatekeeper.dec.com:/pub/DEC/gwtools (and
+ DECnet, of course). This is for Phase IV DECnet support;
+ if you have Phase V at your site you may have additional
+ problems.
+
+phquery The phquery program. This is somewhat counterintuitively
+ referenced as the "ph" mailer internally. It can be used
+ to do CCSO name server lookups. The phquery program, which
+ this mailer uses, is distributed with the ph client.
+
+cyrus The cyrus and cyrusbb mailers. The cyrus mailer delivers to
+ a local cyrus user. this mailer can make use of the
+ "user+detail@local.host" syntax; it will deliver the mail to
+ the user's "detail" mailbox if the mailbox's ACL permits.
+ The cyrusbb mailer delivers to a system-wide cyrus mailbox
+ if the mailbox's ACL permits.
+
+
+The local mailer accepts addresses of the form "user+detail", where
+the "+detail" is not used for mailbox matching but is available
+to certain local mail programs (in particular, see FEATURE(local_procmail)).
+For example, "eric", "eric+sendmail", and "eric+sww" all indicate
+the same user, but additional arguments <null>, "sendmail", and "sww"
+may be provided for use in sorting mail.
+
+
++----------+
+| 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.
+
+use_ct_file Read the file /etc/sendmail.ct file to get the names
+ of users that will be ``trusted'', that is, able to
+ set their envelope from address using -f without
+ generating a warning message.
+ The actual filename can be overridden by redefining
+ confCT_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. You may also want to
+ use "define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')" to
+ turn off the usual resolver options that do a similar
+ thing.
+
+stickyhost If set, 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 is used if you want a set up where "user" is
+ not necessarily the same as "user@local.host", e.g.,
+ to make a distinct domain-wide namespace. Prior to
+ 8.7 this was the default, and notsticky was used to
+ turn this off.
+
+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 -o /etc/mailertable
+ Keys in this database are fully qualified domain names
+ or partial domains preceded by a dot -- for example,
+ "vangogh.CS.Berkeley.EDU" or ".CS.Berkeley.EDU".
+ Values must be of the form:
+ mailer:domain
+ where "mailer" is the internal mailer name, and "domain"
+ is where to send the message. These maps are not
+ reflected into the message header.
+
+domaintable Include a "domain table" which can be used to provide
+ domain name mapping. Use of this should really be
+ limited to your own domains. It may be useful if you
+ change names (e.g., your company changes names from
+ oldname.com to newname.com). The argument of the
+ FEATURE may be the key definition. If none is specified,
+ the definition used is:
+ hash -o /etc/domaintable
+ The key in this table is the domain name; the value is
+ the new (fully qualified) domain. Anything in the
+ domaintable is reflected into headers; that is, this
+ is done in ruleset 3.
+
+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 Myers.
+ The argument of the FEATURE may be the key definition; if
+ none is specified, the definition used is:
+ hash -o /etc/bitdomain.db
+ Keys are the bitnet hostname; values are the corresponding
+ internet hostname.
+
+uucpdomain Similar feature for UUCP hosts. The default map definition
+ is:
+ hash -o /etc/uudomain.db
+ 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.
+
+allmasquerade If masquerading is enabled (using MASQUERADE_AS), this
+ feature will cause recipient addresses to also masquerade
+ as being from the masquerade host. Normally they get
+ the local hostname. Although this may be right for
+ ordinary users, it can break local aliases. For example,
+ if you send to "localalias", the originating sendmail will
+ find that alias and send to all members, but send the
+ message with "To: localalias@masqueradehost". Since that
+ alias likely does not exist, replies will fail. Use this
+ feature ONLY if you can guarantee that the ENTIRE
+ namespace on your masquerade host supersets all the
+ local entries.
+
+nodns We aren't running DNS at our site (for example,
+ we are UUCP-only connected). It's hard to consider
+ this a "feature", but hey, it had to go somewhere.
+
+nullclient This is a special case -- it creates a stripped down
+ configuration file containing nothing but support for
+ forwarding all mail to a central hub via a local
+ SMTP-based network. The argument is the name of that
+ hub.
+
+ The only other feature that should be used in conjunction
+ with this one is "nocanonify" (this causes addresses to
+ be sent unqualified via the SMTP connection; normally
+ they are qualifed with the masquerade name, which
+ defaults to the name of the hub machine). No mailers
+ should be defined. No aliasing or forwarding is done.
+
+local_procmail Use procmail as the local mailer. This mailer can
+ make use of the "user+indicator@local.host" syntax;
+ normally the +indicator is just tossed, but by default
+ it is passed as the -a argument to procmail. The
+ argument to this feature is the pathname of procmail,
+ which defaults to /usr/local/bin/procmail.
+
+bestmx_is_local Accept mail as though locally addressed for any host that
+ lists us as the best possible MX record. This generates
+ additional DNS traffic, but should be OK for low to
+ medium traffic hosts. THIS FEATURE IS FUNDAMENTALLY
+ INCOMPATIBLE WITH WILDCARD MX RECORDS!!! If you have
+ a wildcard MX record that matches your domain, you
+ cannot use this feature.
+
+smrsh Use the SendMail Restricted SHell (smrsh) provided
+ with the distribution instead of /bin/sh for mailing
+ to programs. This improves the ability of the local
+ system administrator to control what gets run via
+ e-mail. If an argument is provided it is used as the
+ pathname to smrsh; otherwise, /usr/local/etc/smrsh is
+ assumed.
+
+
++-------+
+| 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 |
++--------------------+
+
+ *****************************************************
+ * This section is really obsolete, and is preserved *
+ * only for back compatibility. You should plan on *
+ * using mailertables for new installations. In *
+ * particular, it doesn't work for the newer forms *
+ * of UUCP mailers, such as uucp-uudom. *
+ *****************************************************
+
+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.
+
+If your host is known by several different names, you need to augment
+the $=w class. This is a list of names by which you are known, and
+anything sent to an address using a host name in this list will be
+treated as local mail. You can do this in two ways: either create
+the file /etc/sendmail.cw containing a list of your aliases (one per
+line), and use ``FEATURE(use_cw_file)'' in the .mc file, or add the
+line:
+
+ Cw alias.host.name
+
+at the end of that file. See the ``vangogh.mc'' file for an example.
+Be sure you use the fully-qualified name of the host, rather than a
+short name.
+
+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). The third
+parameter is the name of both a macro to store the local name (in
+this case, $U) and the name of the class (e.g., $=U) in which to store
+the host information read from the file. 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, and $W is defined to be ucbarpa.Berkeley.EDU, that
+is, the name of the relay to which the hosts listed in uucp.ucbarpa
+are connected. [The machine ucbarpa is gone now, but I've left
+this out-of-date configuration file around to demonstrate how you
+might do this.]
+
+Note that the case of SITECONFIG with a third parameter of ``U'' is
+special; the second parameter is assumed to be the UUCP name of the
+local site, rather than the name of a remote site, and the UUCP name
+is entered into $=w (the list of local hostnames) as $U.UUCP.
+
+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).
+
+
++--------------------+
+| USING UUCP MAILERS |
++--------------------+
+
+It's hard to get UUCP mailers right because of the extremely ad hoc
+nature of UUCP addressing. These config files are really designed
+for domain-based addressing, even for UUCP sites.
+
+There are four UUCP mailers available. The choice of which one to
+use is partly a matter of local preferences and what is running at
+the other end of your UUCP connection. Unlike good protocols that
+define what will go over the wire, UUCP uses the policy that you
+should do what is right for the other end; if they change, you have
+to change. This makes it hard to do the right thing, and discourages
+people from updating their software. In general, if you can avoid
+UUCP, please do.
+
+The major choice is whether to go for a domainized scheme or a
+non-domainized scheme. This depends entirely on what the other
+end will recognize. If at all possible, you should encourage the
+other end to go to a domain-based system -- non-domainized addresses
+don't work entirely properly.
+
+The four mailers are:
+
+ uucp-old (obsolete name: "uucp")
+ This is the oldest, the worst (but the closest to UUCP) way of
+ sending messages accros UUCP connections. It does bangify
+ everything and prepends $U (your UUCP name) to the sender's
+ address (which can already be a bang path itself). It can
+ only send to one address at a time, so it spends a lot of
+ time copying duplicates of messages. Avoid this if at all
+ possible.
+
+ uucp-new (obsolete name: "suucp")
+ The same as above, except that it assumes that in one rmail
+ command you can specify several recipients. It still has a
+ lot of other problems.
+
+ uucp-dom
+ This UUCP mailer keeps everything as domain addresses.
+ Basically, it uses the SMTP mailer rewriting rules. This mailer
+ is only included if MAILER(smtp) is also specified.
+
+ Unfortunately, a lot of UUCP mailer transport agents require
+ bangified addresses in the envelope, although you can use
+ domain-based addresses in the message header. (The envelope
+ shows up as the From_ line on UNIX mail.) So....
+
+ uucp-uudom
+ This is a cross between uucp-new (for the envelope addresses)
+ and uucp-dom (for the header addresses). It bangifies the
+ envelope sender (From_ line in messages) without adding the
+ local hostname, unless there is no host name on the address
+ at all (e.g., "wolf") or the host component is a UUCP host name
+ instead of a domain name ("somehost!wolf" instead of
+ "some.dom.ain!wolf"). This is also included only if MAILER(smtp)
+ is also specified.
+
+Examples:
+
+We are on host grasp.insa-lyon.fr (UUCP host name "grasp"). The
+following summarizes the sender rewriting for various mailers.
+
+Mailer sender rewriting in the envelope
+------ ------ -------------------------
+uucp-{old,new} wolf grasp!wolf
+uucp-dom wolf wolf@grasp.insa-lyon.fr
+uucp-uudom wolf grasp.insa-lyon.fr!wolf
+
+uucp-{old,new} wolf@fr.net grasp!fr.net!wolf
+uucp-dom wolf@fr.net wolf@fr.net
+uucp-uudom wolf@fr.net fr.net!wolf
+
+uucp-{old,new} somehost!wolf grasp!somehost!wolf
+uucp-dom somehost!wolf somehost!wolf@grasp.insa-lyon.fr
+uucp-uudom somehost!wolf grasp.insa-lyon.fr!somehost!wolf
+
+If you are using one of the domainized UUCP mailers, you really want
+to convert all UUCP addresses to domain format -- otherwise, it will
+do it for you (and probably not the way you expected). For example,
+if you have the address foo!bar!baz (and you are not sending to foo),
+the heuristics will add the @uucp.relay.name or @local.host.name to
+this address. However, if you map foo to foo.host.name first, it
+will not add the local hostname. You can do this using the uucpdomain
+feature.
+
+
++-------------------+
+| TWEAKING RULESETS |
++-------------------+
+
+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.
+
+A common use is to convert old UUCP addreses to SMTP addresses using
+the UUCPSMTP macro. For example:
+
+ LOCAL_RULE_3
+ UUCPSMTP(decvax, decvax.dec.com)
+ UUCPSMTP(research, research.att.com)
+
+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.
+
+This could also be used to look up hosts in a database map:
+
+ LOCAL_RULE_3
+ R$* < @ $+ > $* $: $1 < @ $(hostmap $2 $) > $3
+
+This map would be defined in the LOCAL_CONFIG portion, as shown below.
+
+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$+ <@ host.dom.ain.> $#uucp $@ cnmat $: $1 < @ host.dom.ain.>
+
+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.
+
+You can also tweak rulesets 1 and 2 using LOCAL_RULE_1 and LOCAL_RULE_2.
+These rulesets are normally empty.
+
+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:
+
+ LOCAL_CONFIG
+ Khostmap hash /etc/hostmap.db
+ Kyplocal nis -m hosts.byname
+
+
++---------------------------+
+| MASQUERADING AND RELAYING |
++---------------------------+
+
+You can have your host masquerade as another using
+
+ MASQUERADE_AS(host.domain)
+
+This causes outgoing SMTP mail to be labeled as coming from the
+indicated domain, rather than $j. One normally masquerades as one
+of one's own subdomains (for example, it's unlikely that I would
+choose to masquerade as an MIT site).
+
+The masquerade name is not normally canonified, so it is important
+that it be your One True Name, that is, fully qualified and not a
+CNAME.
+
+Normally the only addresses that are masqueraded are those that come
+from this host (that is, are either unqualified or in $=w, the list
+of local domain names). You can augment this list using
+
+ MASQUERADE_DOMAIN(otherhost.domain)
+
+The effect of this is that although mail to user@otherhost.domain
+will not be delivered locally, any mail including any user@otherhost.domain
+will, when relayed, be rewritten to have the MASQUERADE_AS address.
+This can be a space-separated list of names.
+
+If these names are in a file, you can use
+
+ MASQUERADE_DOMAIN_FILE(filename)
+
+to read the list of names from the indicated file.
+
+Normally only header addresses are masqueraded. If you want to
+masquerade the envelope as well, use
+
+ FEATURE(masquerade_envelope)
+
+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
+
+ EXPOSED_USER(usernames)
+
+This adds users to class E; you could also use something like
+
+ FE/etc/sendmail.cE
+
+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
+
+ define(`LOCAL_RELAY', mailer:hostname)
+
+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
+
+ LOCAL_USER(usernames)
+
+This adds users to class L; you could also use something like
+
+ FL/etc/sendmail.cL
+
+If you want all incoming mail sent to a centralized hub, as for a
+shared /var/spool/mail scheme, use
+
+ define(`MAIL_HUB', mailer:hostname)
+
+Again, ``mailer:'' defaults to "smtp". If you define both LOCAL_RELAY
+and MAIL_HUB _AND_ you have FEATURE(stickyhost), unqualified names will
+be sent to the LOCAL_RELAY and other local names will be sent to MAIL_HUB.
+Names in $=L will be delivered locally, so you MUST have aliases or
+.forward files for them.
+
+For example, if are on machine mastodon.CS.Berkeley.EDU and you have
+FEATURE(stickyhost), the following combinations of settings will have the
+indicated effects:
+
+email sent to.... eric eric@mastodon.CS.Berkeley.EDU
+
+LOCAL_RELAY set to mail.CS.Berkeley.EDU (delivered locally)
+mail.CS.Berkeley.EDU (no local aliasing) (aliasing done)
+
+MAIL_HUB set to mammoth.CS.Berkeley.EDU mammoth.CS.Berkeley.EDU
+mammoth.CS.Berkeley.EDU (aliasing done) (aliasing done)
+
+Both LOCAL_RELAY and mail.CS.Berkeley.EDU mammoth.CS.Berkeley.EDU
+MAIL_HUB set as above (no local aliasing) (aliasing done)
+
+If you do not have FEATURE(stickyhost) set, then LOCAL_RELAY and
+MAIL_HUB act identically, with MAIL_HUB taking precedence.
+
+If you want all outgoing mail to go to a central relay site, define
+SMART_HOST as well. Briefly:
+
+ LOCAL_RELAY applies to unqualifed names (e.g., "eric").
+ MAIL_HUB applies to names qualified with the name of the
+ local host (e.g., "eric@mastodon.CS.Berkeley.EDU").
+ SMART_HOST applies to names qualified with other hosts.
+
+However, beware that other relays (e.g., UUCP_RELAY, BITNET_RELAY,
+DECNET_RELAY, and FAX_RELAY) take precedence over SMART_HOST, so if you
+really want absolutely everything to go to a single central site you will
+need to unset all the other relays -- or better yet, find or build a
+minimal config file that does this.
+
+
++-------------------------------+
+| NON-SMTP BASED CONFIGURATIONS |
++-------------------------------+
+
+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.
+
+You can define a ``smart host'' that understands a richer address syntax
+using:
+
+ define(`SMART_HOST', mailer:hostname)
+
+In this case, the ``mailer:'' defaults to "relay". Any messages that
+can't be handled using the usual UUCP rules are passed to this host.
+
+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:
+
+ define(`SMART_HOST', suucp:uunet)
+ LOCAL_NET_CONFIG
+ R$* < @ $* .$m. > $* $#smtp $@ $2.$m. $: $1 < @ $2.$m. > $3
+
+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.
+If you have FEATURE(nocanonify), you may need to omit the dots after
+the $m. If you are running a local DNS inside your domain which is
+not otherwise connected to the outside world, you probably want to
+use:
+
+ define(`SMART_HOST', smtp:fire.wall.com)
+ LOCAL_NET_CONFIG
+ R$* < @ $* . > $* $#smtp $@ $2. $: $1 < @ $2. > $3
+
+That is, send directly only to things you found in your DNS lookup;
+anything else goes through SMART_HOST.
+
+If you are not running DNS at all, it is important to use
+FEATURE(nodns) to avoid having sendmail queue everything waiting
+for the name server to come up.
+
+
++-----------+
+| WHO AM I? |
++-----------+
+
+Normally, the $j macro is automatically defined to be your fully
+qualified domain name (FQDN). Sendmail does this by getting your
+host name using gethostname and then calling gethostbyname on the
+result. For example, in some environments gethostname returns
+only the root of the host name (such as "foo"); gethostbyname is
+supposed to return the FQDN ("foo.bar.com"). In some (fairly rare)
+cases, gethostbyname may fail to return the FQDN. In this case
+you MUST define confDOMAIN_NAME to be your fully qualified domain
+name. This is usually done using:
+
+ Dmbar.com
+ define(`confDOMAIN_NAME', `$w.$m')dnl
+
+
++--------------------+
+| USING MAILERTABLES |
++--------------------+
+
+To use FEATURE(mailertable), you will have to create an external
+database containing the routing information for various domains.
+For example, a mailertable file in text format might be:
+
+ .my.domain xnet:%1.my.domain
+ uuhost1.my.domain suucp:uuhost1
+ .bitnet smtp:relay.bit.net
+
+This should normally be stored in /etc/mailertable. The actual
+database version of the mailertable is built using:
+
+ makemap hash /etc/mailertable.db < /etc/mailertable
+
+The semantics are simple. Any LHS entry that does not begin with
+a dot matches the full host name indicated. LHS entries beginning
+with a dot match anything ending with that domain name -- that is,
+they can be thought of as having a leading "*" wildcard. Matching
+is done in order of most-to-least qualified -- for example, even
+though ".my.domain" is listed first in the above example, an entry
+of "uuhost1.my.domain" will match the second entry since it is
+more explicit.
+
+The RHS should always be a "mailer:host" pair. The mailer is the
+configuration name of a mailer (that is, an `M' line in the
+sendmail.cf file). The "host" will be the hostname passed to
+that mailer. In domain-based matches (that is, those with leading
+dots) the "%1" may be used to interpolate the wildcarded part of
+the host name. For example, the first line above sends everything
+addressed to "anything.my.domain" to that same host name, but using
+the (presumably experimental) xnet mailer.
+
+In some cases you may want to temporarily turn off MX records,
+particularly on gateways. For example, you may want to MX
+everything in a domain to one machine that then forwards it
+directly. To do this, you might use the DNS configuration:
+
+ *.domain. IN MX 0 relay.machine
+
+and on relay.machine use the mailertable:
+
+ .domain smtp:[gateway.domain]
+
+The [square brackets] turn off MX records for this host only.
+If you didn't do this, the mailertable would use the MX record
+again, which would give you an MX loop.
+
+
++--------------------------------+
+| USING USERDB TO MAP FULL NAMES |
++--------------------------------+
+
+The user database was not originally intended for mapping full names
+to login names (e.g., Eric.Allman => eric), but some people are using
+it that way. (I would recommend that you set up aliases for this
+purpose instead -- since you can specify multiple alias files, this
+is fairly easy.) The intent was to locate the default maildrop at
+a site, but allow you to override this by sending to a specific host.
+
+If you decide to set up the user database in this fashion, it is
+imperative that you not use FEATURE(stickyhost) -- otherwise,
+e-mail sent to Full.Name@local.host.name will be rejected.
+
+To build the internal form of the user database, use:
+
+ makemap btree /usr/data/base.db < /usr/data/base.txt
+
+As a general rule, I am adamantly opposed to using full names as
+e-mail addresses, since they are not in any sense unique. For example,
+the Unix software-development community has two Andy Tannenbaums,
+at least two well-known Peter Deutsches, and at one time Bell Labs
+had two Stephen R. Bournes with offices along the same hallway.
+Which one will be forced to suffer the indignity of being
+Stephen_R_Bourne_2? The less famous of the two, or the one that
+was hired later?
+
+Finger should handle full names (and be fuzzy). Mail should use
+handles, and not be fuzzy. [Not that I expect anyone to pay any
+attention to my opinions.]
+
+
++--------------------------------+
+| MISCELLANEOUS SPECIAL FEATURES |
++--------------------------------+
+
+Plussed users
+ Sometimes it is convenient to merge configuration on a
+ centralized mail machine, for example, to forward all
+ root mail to a mail server. In this case it might be
+ useful to be able to treat the root addresses as a class
+ of addresses with subtle differences. You can do this
+ using plussed users. For example, a client might include
+ the alias:
+
+ root: root+client1@server
+
+ On the server, this will match an alias for "root+client1".
+ If that is not found, the alias "root+*" will be tried,
+ then "root".
+
+
++----------------+
+| SECURITY NOTES |
++----------------+
+
+A lot of sendmail security comes down to you. Sendmail 8 is much
+more careful about checking for security problems than previous
+versions, but there are some things that you still need to watch
+for. In particular:
+
+* Make sure the aliases file isn't writable except by trusted
+ system personnel. This includes both the text and database
+ version.
+
+* Make sure that other files that sendmail reads, such as the
+ mailertable, is only writable by trusted system personnel.
+
+* The queue directory should not be world writable PARTICULARLY
+ if your system allows "file giveaways" (that is, if a non-root
+ user can chown any file they own to any other user).
+
+* If your system allows file giveaways, DO NOT create a publically
+ writable directory for forward files. This will allow anyone
+ to steal anyone else's e-mail. Instead, create a script that
+ copies the .forward file from users' home directories once a
+ night (if you want the non-NFS-mounted forward directory).
+
+* If your system allows file giveaways, you'll find that
+ sendmail is much less trusting of :include: files -- in
+ particular, you'll have to have /SENDMAIL/ANY/SHELL/ in
+ /etc/shells before they will be trusted (that is, before
+ files and programs listed in them will be honored).
+
+In general, file giveaways are a mistake -- if you can turn them
+off I recommend you do so.
+
+
++------------------+
+| FlexFAX SOFTWARE |
++------------------+
+
+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:
+
+ $Header: /usr/people/sam/fax/RCS/HOWTO,v 1.14 93/05/24 11:42:16 sam Exp $
+
+ How To Obtain This Software (in case all you get is this file)
+ --------------------------------------------------------------
+ The source code is available for public ftp on
+ sgi.com sgi/fax/v2.1.src.tar.Z
+ (192.48.153.1)
+
+ You can also obtain inst'able images for Silicon Graphics machines from
+ sgi.com sgi/fax/v2.1.inst.tar
+ (192.48.153.1)
+
+ For example,
+ % ftp -n sgi.com
+ ....
+ ftp> user anonymous
+ ... <type in password>
+ ftp> cd sgi/fax
+ ftp> binary
+ ftp> get v2.1.src.tar.Z
+
+ In general, the latest version of the 2.1 release of the software is
+ always available as "v2.1.src.tar.Z" or "v2.1.inst.tar" in the ftp
+ directory. This file is a link to the appropriate released version (so
+ don't waste your time retrieving the linked file as well!) Any files of
+ the form v2.1.*.patch are shell scripts that can be used to patch older
+ versions of the source code. For example, the file v2.1.0.patch would
+ contain patches to update v2.1.0.tar.Z. (Note to beta testers: this is
+ different than the naming conventions used during beta testing.) Patch
+ files only work to go between consecutive versions, so if you are
+ multiple versions behind the latest release, you will need to apply
+ each patch file between your current version and the latest.
+
+
+ Obtaining the Software by Electronic Mail
+ -----------------------------------------
+ Do not send me requests for the software; they will be ignored (without
+ response). If you cannot use FTP at all, there is a service called
+ "ftpmail" available from gatekeeper.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".
+
+
+ Obtaining the Software Within Silicon Graphics
+ ----------------------------------------------
+ Internal to Silicon Graphics there are inst'able images on the host
+ flake.asd in the directory /usr/dist. Thus you can do something like:
+
+ % inst -f flake.asd.sgi.com:/usr/dist/flexfax
+
+ to install the latest version of the software on your machine.
+
+
+ What to do Once You've Retrieved Stuff
+ --------------------------------------
+ The external distributions come in a compressed or uncompressed tar
+ file. To extract the source distribution:
+
+ % zcat v2.1.src.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.1.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 are also
+ included in the inst'able images as flexfax.server.*. They are not
+ installed by default, so to get them also you need to do:
+
+ % inst -f flexfax
+ ...
+ inst> install flexfax.server.*
+ inst> go
+
+ The SGI binaries were built for Version 4.0.5H 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, the subsystem flexfax.man.readme contains the README file and
+ other useful pieces of information--the installed files are placed in
+ the directory /usr/local/doc/flexfax). Basically you will need to run
+ the faxaddmodem script to setup and configure your fax modem. Consult
+ the README file and the manual page for faxaddmodem for information.
+
+
+ FlexFAX Mail List
+ -----------------
+ 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
+
+ majordomo@whizzer.wpd.sgi.com
+
+ For example, to subscribe, send the line "subscribe flexfax" in
+ the body of your message. The line "help" will return a list of
+ the commands understood by the mailing list management software.
+
+ Submissions (including bug reports) should be directed to:
+
+ flexfax@sgi.com
+
+ When corresponding about this software please always specify what
+ version you have, what system you're running on, and, if the problem is
+ specific to your modem, identify the modem and firmware revision.
+
+
++--------------------------------+
+| 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 "*".
+
+Remember that these options are M4 variables, and hence may need to
+be quoted. In particular, arguments with commas will usually have to
+be ``double quoted, like this phrase'' to avoid having the comma
+confuse things. This is common for alias file definitions and for
+the read timeout.
+
+M4 Variable Name Configuration Description & [Default]
+================ ============= =======================
+confMAILER_NAME $n macro [MAILER-DAEMON] The sender name used
+ for internally generated outgoing
+ messages.
+confDOMAIN_NAME $j macro If defined, sets $j. This should
+ only be done if your system cannot
+ determine your local domain name,
+ and then it should be set to
+ $w.Foo.COM, where Foo.COM is your
+ domain name.
+confCF_VERSION $Z macro If defined, this is appended to the
+ configuration version name.
+confFROM_HEADER From: [$?x$x <$g>$|$g$.] The format of an
+ internally generated From: address.
+confRECEIVED_HEADER Received:
+ [.$?_($?s$|from $.$_) $.by $j ($v/$Z)$?r with $r$. id $i$?u for $u$.; $b]
+ The format of the Received: header
+ in messages passed through this host.
+ It is unwise to try to change this.
+confCW_FILE Fw class [/etc/sendmail.cw] Name of file used
+ to get the local additions to the $=w
+ (local host names) class.
+confCT_FILE Ft class [/etc/sendmail.ct] Name of file used
+ to get the local additions to the $=t
+ (trusted users) class.
+confTRUSTED_USERS Ct class [no default] Names of users to add to
+ the list of trusted users. This list
+ always includes root, uucp, and daemon.
+ See also FEATURE(use_ct_file).
+confSMTP_MAILER - [smtp] The mailer name used when
+ SMTP connectivity is required.
+ One of "smtp", "smtp8", or "esmtp".
+confUUCP_MAILER - [uucp-old] The mailer to be used by
+ default for bang-format recipient
+ addresses. See also discussion of
+ $=U, $=Y, and $=Z in the MAILER(uucp)
+ section.
+confLOCAL_MAILER - [local] The mailer name used when
+ local connectivity is required.
+ Almost always "local".
+confRELAY_MAILER - [relay] The default mailer name used
+ for relaying any mail (e.g., to a
+ BITNET_RELAY, a SMART_HOST, or
+ whatever). This can reasonably be
+ "uucp-new" if you are on a
+ UUCP-connected site.
+confSEVEN_BIT_INPUT SevenBitInput [False] Force input to seven bits?
+confEIGHT_BIT_HANDLING EightBitMode [pass8] 8-bit data handling
+confALIAS_WAIT AliasWait [10m] Time to wait for alias file
+ rebuild until you get bored and
+ decide that the apparently pending
+ rebuild failed.
+confMIN_FREE_BLOCKS MinFreeBlocks [100] Minimum number of free blocks on
+ queue filesystem to accept SMTP mail.
+ (Prior to 8.7 this was minfree/maxsize,
+ where minfree was the number of free
+ blocks and maxsize was the maximum
+ message size. Use confMAX_MESSAGE_SIZE
+ for the second value now.)
+confMAX_MESSAGE_SIZE MaxMessageSize The maximum size of messages that will
+ be accepted (in bytes).
+confBLANK_SUB BlankSub [.] Blank (space) substitution
+ character.
+confCON_EXPENSIVE HoldExpensive [False] Avoid connecting immediately
+ to mailers marked expensive?
+confCHECKPOINT_INTERVAL CheckpointInterval
+ Checkpoint queue files every N
+ recipients.
+confDELIVERY_MODE DeliveryMode [background] Default delivery mode.
+confAUTO_REBUILD AutoRebuildAliases
+ Automatically rebuild alias
+ file if needed.
+confERROR_MODE ErrorMode Error message mode.
+confERROR_MESSAGE ErrorHeader Error message header/file.
+confSAVE_FROM_LINES SafeFromLine Save extra leading From_ lines.
+confTEMP_FILE_MODE TempFileMode [0600] Temporary file mode.
+confMATCH_GECOS MatchGECOS Match GECOS field.
+confMAX_HOP MaxHopCount Maximum hop count.
+confIGNORE_DOTS* IgnoreDots Ignore dot as terminator for incoming
+ messages?
+confBIND_OPTS ResolverOptions Default options for DNS resolver.
+confMIME_FORMAT_ERRORS* SendMimeErrors [True] Send error messages as MIME-
+ encapsulated messages per RFC 1344.
+confFORWARD_PATH ForwardPath [$z/.forward.$w:$z/.forward]
+ The colon-separated list of places to
+ search for .forward files. N.B.: see
+ the Security Notes section.
+confMCI_CACHE_SIZE ConnectionCacheSize
+ [2] Size of open connection cache.
+confMCI_CACHE_TIMEOUT ConnectionCacheTimeout
+ [5m] Open connection cache timeout.
+confUSE_ERRORS_TO* UserErrorsTo [False] 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 LogLevel [9] Log level.
+confME_TOO MeToo Include sender in group expansions.
+confCHECK_ALIASES CheckAliases [False] Check RHS of aliases when
+ running newaliases. Since this does
+ DNS lookups on every address, it can
+ slow down the alias rebuild process
+ considerably on large alias files.
+confOLD_STYLE_HEADERS* OldStyleHeaders [True] Assume that headers without
+ special chars are old style.
+confDAEMON_OPTIONS DaemonPortOptions
+ SMTP daemon options.
+confPRIVACY_FLAGS PrivacyOptions [authwarnings] Privacy flags.
+confCOPY_ERRORS_TO PostmasterCopy Address for additional copies of all
+ error messages.
+confQUEUE_FACTOR QueueFactor Slope of queue-only function.
+confDONT_PRUNE_ROUTES DontPruneRoutes Don't prune down route-addr syntax
+ addresses to the minimum possible.
+confSAFE_QUEUE* SuperSafe [True] Commit all messages to disk
+ before forking.
+confTO_INITIAL Timeout.initial [5m] The timeout waiting for a response
+ on the initial connect.
+confTO_HELO Timeout.helo [5m] The timeout waiting for a response
+ to a HELO or EHLO command.
+confTO_MAIL Timeout.mail [10m] The timeout waiting for a
+ response to the MAIL command.
+confTO_RCPT Timeout.rcpt [1h] The timeout waiting for a response
+ to the RCPT command.
+confTO_DATAINIT Timeout.datainit
+ [5m] The timeout waiting for a 354
+ response from the DATA command.
+confTO_DATABLOCK Timeout.datablock
+ [1h] The timeout waiting for a block
+ during DATA phase.
+confTO_DATAFINAL Timeout.datafinal
+ [1h] The timeout waiting for a response
+ to the final "." that terminates a
+ message.
+confTO_RSET Timeout.rset [5m] The timeout waiting for a response
+ to the RSET command.
+confTO_QUIT Timeout.quit [2m] The timeout waiting for a response
+ to the QUIT command.
+confTO_MISC Timeout.misc [2m] The timeout waiting for a response
+ to other SMTP commands.
+confTO_COMMAND Timeout.command [1h] In server SMTP, the timeout waiting
+ for a command to be issued.
+confTO_IDENT Timeout.ident [30s] The timeout waiting for a response
+ to an IDENT query.
+confTO_FILEOPEN Timeout.fileopen
+ [60s] The timeout waiting for a file
+ (e.g., :include: file) to be opened.
+confTO_QUEUERETURN Timeout.queuereturn
+ [5d] The timeout before a message is
+ returned as undeliverable.
+confTO_QUEUERETURN_NORMAL
+ Timeout.queuereturn.normal
+ [undefined] As above, for normal
+ priority messages.
+confTO_QUEUERETURN_URGENT
+ Timeout.queuereturn.urgent
+ [undefined] As above, for urgent
+ priority messages.
+confTO_QUEUERETURN_NONURGENT
+ Timeout.queuereturn.non-urgent
+ [undefined] As above, for non-urgent
+ (low) priority messages.
+confTO_QUEUEWARN Timeout.queuewarn
+ [4h] The timeout before a warning
+ message is sent to the sender telling
+ them that the message has been deferred.
+confTO_QUEUEWARN_NORMAL Timeout.queuewarn.normal
+ [undefined] As above, for normal
+ priority messages.
+confTO_QUEUEWARN_URGENT Timeout.queuewarn.urgent
+ [undefined] As above, for urgent
+ priority messages.
+confTO_QUEUEWARN_NONURGENT
+ Timeout.queuewarn.non-urgent
+ [undefined] As above, for non-urgent
+ (low) priority messages.
+confTIME_ZONE TimeZoneSpec [USE_SYSTEM] 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 DefaultUser [1:1] Default user id.
+confUSERDB_SPEC UserDatabaseSpec
+ User database specification.
+confFALLBACK_MX FallbackMXhost Fallback MX host.
+confTRY_NULL_MX_LIST TryNullMXList If we are the best MX for a host and
+ haven't made other arrangements, try
+ connecting to the host directly;
+ normally this would be a config error.
+confQUEUE_LA QueueLA Load average at which queue-only
+ function kicks in.
+confREFUSE_LA RefuseLA Load average at which incoming
+ SMTP connections are refused.
+confWORK_RECIPIENT_FACTOR
+ RecipientFactor Cost of each recipient.
+confSEPARATE_PROC ForkEachJob Run all deliveries in a separate
+ process.
+confWORK_CLASS_FACTOR ClassFactor Priority multiplier for class.
+confWORK_TIME_FACTOR RetryFactor Cost of each delivery attempt.
+confQUEUE_SORT_ORDER QueueSortOrder Queue sort algorithm: Priority or Host.
+confMIN_QUEUE_AGE MinQueueAge The minimum amount of time a job
+ must sit in the queue between queue
+ runs. This allows you to set the
+ queue run interval low for better
+ resposiveness without trying all
+ jobs in each run.
+confDEF_CHAR_SET DefaultCharSet When converting unlabelled 8 bit
+ input to MIME, the character set to
+ use by default.
+confSERVICE_SWITCH_FILE ServiceSwitchFile
+ The file to use for the service switch
+ on systems that do not have a system-
+ defined switch.
+confDIAL_DELAY DialDelay If a connection fails, wait this long
+ and try again. This is to allow
+ "dial on demand" connections to have
+ enough time to complete a connection.
+confNO_RCPT_ACTION NoRecipientAction
+ What to do if there are no legal
+ recipient fields (To:, Cc: or Bcc:)
+ in the message. Legal values can
+ be "none" to just leave the
+ nonconforming message as is, "add-to"
+ to add a To: header with all the
+ known recipients (which may expose
+ blind recipients), "add-apparently-to"
+ to do the same but use Apparently-To:
+ instead of To:, "add-bcc" to add an
+ empty Bcc: header, or
+ "add-to-undisclosed" to add the header
+ ``To: undisclosed-recipients:;''.
+ Default is "none".
+confSAFE_FILE_ENV SafeFileEnvironment
+ If set, sendmail will do a chroot()
+ into this directory before writing
+ files.
+confCOLON_OK_IN_ADDR ColonOkInAddr If set, colons are treated as a regular
+ character in addresses. If not set,
+ they are treated as the introducer to
+ the RFC 822 "group" syntax. Colons are
+ handled properly in route-addrs. This
+ option defaults on for V5 and lower
+ configuration files.
+confMAX_QUEUE_RUN_SIZE MaxQueueRunSize If set, limit the maximum size of any
+ given queue run to this number of
+ entries. Essentially, this will stop
+ reading the queue directory after this
+ number of entries are reached; it does
+ _not_ pick the highest priority jobs,
+ so this should be as large as your
+ system can tolerate. If not set, there
+ is no limit.
+confDONT_EXPAND_CNAMES DontExpandCnames
+ If set, $[ ... $] lookups that do DNS
+ based lookups do not expand CNAME
+ records. This currently violates the
+ published standards, but the IETF
+ seems to be moving toward legalizing
+ this. For example, if "FTP.Foo.ORG"
+ is a CNAME for "Cruft.Foo.ORG", then
+ with this option set a lookup of
+ "FTP" will return "FTP.Foo.ORG"; if
+ clear it returns "Cruft.FOO.ORG". N.B.
+ you may not see any effect until your
+ downstream neighbors stop doing CNAME
+ lookups as well.
+confFROM_LINE UnixFromLine [From $g $d] The From_ line used
+ when sending to files or programs.
+confOPERATORS OperatorChars [.:%@!^/[]+] Address operator
+ characters.
+confSMTP_LOGIN_MSG SmtpGreetingMessage
+ [$j Sendmail $v/$Z; $b]
+ The initial (spontaneous) SMTP
+ greeting message. The word "ESMTP"
+ will be inserted between the first and
+ second words to convince other
+ sendmails to try to speak ESMTP.
+confDONT_INIT_GROUPS DontInitGroups If set, the initgroups(3) routine will
+ never be invoked. You might want to
+ do this if you are running NIS and you
+ have a large group map, since this
+ call does a sequential scan of the map;
+ in a large site this can cause your
+ ypserv to run essentially full time.
+ If you set this, agents run on behalf
+ of users will only have their primary
+ (/etc/passwd) group permissions.
+
+See also the description of OSTYPE for some parameters that can be
+tweaked (generally pathnames to mailers).
+
+
++-----------+
+| 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, "CS.Berkeley.EDU.m4"
+ describes hosts in the CS.Berkeley.EDU 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 peccadillos.
+
+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)
+ 3x mailer rules (sender header qualification)
+ 4x mailer rules (recipient header qualification)
+ 5x mailer subroutines (general)
+ 6x mailer subroutines (general)
+ 7x mailer subroutines (general)
+ 8x reserved
+ 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)
+ 98 Local part of ruleset 0 (ruleset 8 in old sendmail)
+ 99 Guaranteed null (for debugging)
+
+
+MAILERS
+
+ 0 local, prog local and program mailers
+ 1 [e]smtp, relay SMTP channel
+ 2 uucp-* UNIX-to-UNIX Copy Program
+ 3 netnews Network News delivery
+ 4 fax Sam Leffler's FlexFAX software
+ 5 mail11 DECnet mailer
+
+
+MACROS
+
+ A
+ B Bitnet Relay
+ C DECnet Relay
+ D The local domain -- usually not needed
+ E reserved for X.400 Relay
+ F FAX Relay
+ G
+ H mail Hub (for mail clusters)
+ I
+ J
+ K
+ L Luser Relay
+ 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 domains that should be mapped to $M
+ N
+ O operators that indicate network operations (cannot be in local names)
+ P top level pseudo-domains: BITNET, DECNET, 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 locally connected domain-ized UUCP hosts
+ . 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
+ 9 special local rulesets (1 and 2)
diff --git a/usr.sbin/sendmail/cf/cf/Makefile b/usr.sbin/sendmail/cf/cf/Makefile
new file mode 100644
index 000000000000..33f594377a04
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/Makefile
@@ -0,0 +1,111 @@
+# @(#)Makefile 8.17 (Berkeley) 9/12/95
+
+#
+# This Makefile uses the new Berkeley "make" program. See Makefile.dist
+# for a more vanilla version.
+#
+# Configuration files are created using "m4 file.mc > file.cf";
+# this may be easier than tweaking the Makefile. You do need to
+# have a fairly modern M4 available (GNU m4 works). On SunOS, use
+# /usr/5bin/m4.
+#
+
+M4= m4
+#M4= /usr/src/usr.bin/m4/obj/m4
+CFDIR= ..
+CHMOD= chmod
+ROMODE= 444
+RM= rm -f
+
+.SUFFIXES: .mc .cf
+
+.mc.cf:
+ $(RM) $@
+ (cd ${.CURDIR} && $(M4) ${CFDIR}/m4/cf.m4 ${@:R}.mc > obj/$@)
+ $(CHMOD) $(ROMODE) $@
+
+ALL= generic-bsd4.4.cf generic-hpux9.cf generic-hpux10.cf \
+ generic-osf1.cf generic-solaris2.cf \
+ generic-sunos4.1.cf generic-ultrix4.cf \
+ cs-hpux9.cf cs-osf1.cf cs-solaris2.cf \
+ cs-sunos4.1.cf cs-ultrix4.cf \
+ s2k-osf1.cf s2k-ultrix4.cf \
+ chez.cs.cf huginn.cs.cf mail.cs.cf mail.eecs.cf mailspool.cs.cf \
+ python.cs.cf ucbarpa.cf ucbvax.cf vangogh.cs.cf
+
+all: $(ALL)
+
+clean cleandir:
+ $(RM) $(ALL) core
+
+depend install:
+
+# this is overkill, but....
+M4FILES=\
+ ${CFDIR}/domain/Berkeley.EDU.m4 \
+ ${CFDIR}/domain/CS.Berkeley.EDU.m4 \
+ ${CFDIR}/domain/EECS.Berkeley.EDU.m4 \
+ ${CFDIR}/domain/S2K.Berkeley.EDU.m4 \
+ ${CFDIR}/feature/allmasquerade.m4 \
+ ${CFDIR}/feature/always_add_domain.m4 \
+ ${CFDIR}/feature/bestmx_is_local.m4 \
+ ${CFDIR}/feature/bitdomain.m4 \
+ ${CFDIR}/feature/domaintable.m4 \
+ ${CFDIR}/feature/local_procmail.m4 \
+ ${CFDIR}/feature/mailertable.m4 \
+ ${CFDIR}/feature/nocanonify.m4 \
+ ${CFDIR}/feature/nodns.m4 \
+ ${CFDIR}/feature/notsticky.m4 \
+ ${CFDIR}/feature/nouucp.m4 \
+ ${CFDIR}/feature/nullclient.m4 \
+ ${CFDIR}/feature/redirect.m4 \
+ ${CFDIR}/feature/smrsh.m4 \
+ ${CFDIR}/feature/stickyhost.m4 \
+ ${CFDIR}/feature/use_cw_file.m4 \
+ ${CFDIR}/feature/uucpdomain.m4 \
+ ${CFDIR}/hack/cssubdomain.m4 \
+ ${CFDIR}/m4/cf.m4 \
+ ${CFDIR}/m4/cfhead.m4 \
+ ${CFDIR}/m4/nullrelay.m4 \
+ ${CFDIR}/m4/proto.m4 \
+ ${CFDIR}/m4/version.m4 \
+ ${CFDIR}/mailer/cyrus.m4 \
+ ${CFDIR}/mailer/fax.m4 \
+ ${CFDIR}/mailer/local.m4 \
+ ${CFDIR}/mailer/mail11.m4 \
+ ${CFDIR}/mailer/pop.m4 \
+ ${CFDIR}/mailer/procmail.m4 \
+ ${CFDIR}/mailer/smtp.m4 \
+ ${CFDIR}/mailer/usenet.m4 \
+ ${CFDIR}/mailer/uucp.m4 \
+ ${CFDIR}/ostype/aix3.m4 \
+ ${CFDIR}/ostype/amdahl-uts.m4 \
+ ${CFDIR}/ostype/aux.m4 \
+ ${CFDIR}/ostype/bsd4.3.m4 \
+ ${CFDIR}/ostype/bsd4.4.m4 \
+ ${CFDIR}/ostype/bsdi1.0.m4 \
+ ${CFDIR}/ostype/dgux.m4 \
+ ${CFDIR}/ostype/domainos.m4 \
+ ${CFDIR}/ostype/dynix3.2.m4 \
+ ${CFDIR}/ostype/hpux9.m4 \
+ ${CFDIR}/ostype/irix4.m4 \
+ ${CFDIR}/ostype/irix5.m4 \
+ ${CFDIR}/ostype/linux.m4 \
+ ${CFDIR}/ostype/nextstep.m4 \
+ ${CFDIR}/ostype/osf1.m4 \
+ ${CFDIR}/ostype/ptx2.m4 \
+ ${CFDIR}/ostype/riscos4.5.m4 \
+ ${CFDIR}/ostype/sco3.2.m4 \
+ ${CFDIR}/ostype/solaris2.m4 \
+ ${CFDIR}/ostype/sunos3.5.m4 \
+ ${CFDIR}/ostype/sunos4.1.m4 \
+ ${CFDIR}/ostype/svr4.m4 \
+ ${CFDIR}/ostype/ultrix4.m4 \
+ ${CFDIR}/siteconfig/uucp.cogsci.m4 \
+ ${CFDIR}/siteconfig/uucp.old.arpa.m4 \
+ ${CFDIR}/siteconfig/uucp.ucbarpa.m4 \
+ ${CFDIR}/siteconfig/uucp.ucbvax.m4 \
+
+$(ALL): $(M4FILES)
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/cf/cf/chez.cs.mc b/usr.sbin/sendmail/cf/cf/chez.cs.mc
new file mode 100644
index 000000000000..b30fe9ce22da
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/chez.cs.mc
@@ -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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for a home machine that wants to masquerade as an
+# on-campus machine. Additionally, all addresses without a hostname
+# will be forwarded to that machine.
+#
+
+VERSIONID(`@(#)chez.cs.mc 8.5 (Berkeley) 8/6/95')
+OSTYPE(bsd4.4)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+MASQUERADE_AS(vangogh.CS.Berkeley.EDU)dnl
+FEATURE(use_cw_file)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/clientproto.mc b/usr.sbin/sendmail/cf/cf/clientproto.mc
new file mode 100644
index 000000000000..a59ac037e192
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/clientproto.mc
@@ -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.
+#
+
+#
+# This the prototype for a "null client" -- that is, a client that
+# does nothing except forward all mail to a mail hub. IT IS NOT
+# USABLE AS IS!!!
+#
+# To use this, you MUST use the nullclient feature with the name of
+# the mail hub as its argument. You MUST also define an `OSTYPE' to
+# define the location of the queue directories and the like.
+# In addition, you MAY select the nocanonify feature. This causes
+# addresses to be sent unqualified via the SMTP connection; normally
+# they are qualifed with the masquerade name, which defaults to the
+# name of the hub machine.
+# Other than these, it should never contain any other lines.
+#
+
+VERSIONID(`@(#)clientproto.mc 8.6 (Berkeley) 8/16/95')
+
+OSTYPE(unknown)
+FEATURE(nullclient, mailhost.$m)
diff --git a/usr.sbin/sendmail/cf/cf/cs-hpux10.mc b/usr.sbin/sendmail/cf/cf/cs-hpux10.mc
new file mode 100644
index 000000000000..1d39ccfa413a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-hpux10.mc
@@ -0,0 +1,51 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for HP-UX 9.x.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-hpux10.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(hpux10)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+define(`MAIL_HUB', mailspool.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-hpux9.mc b/usr.sbin/sendmail/cf/cf/cs-hpux9.mc
new file mode 100644
index 000000000000..a27febeaedac
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-hpux9.mc
@@ -0,0 +1,51 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for HP-UX 9.x.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-hpux9.mc 8.4 (Berkeley) 8/6/95')
+OSTYPE(hpux9)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+define(`MAIL_HUB', mailspool.CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-osf1.mc b/usr.sbin/sendmail/cf/cf/cs-osf1.mc
new file mode 100644
index 000000000000..b5beca80c0f2
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-osf1.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for OSF/1.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-osf1.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(osf1)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-solaris2.mc b/usr.sbin/sendmail/cf/cf/cs-solaris2.mc
new file mode 100644
index 000000000000..aad526b6a51c
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-solaris2.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for Solaris 2.x.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-solaris2.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(solaris2)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc b/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc
new file mode 100644
index 000000000000..024fc375d743
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for SunOS 4.1.x.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-sunos4.1.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(sunos4.1)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc b/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc
new file mode 100644
index 000000000000..1f90d00e0151
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for Ultrix 4.x.
+# It applies only the the Computer Science Division at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)cs-ultrix4.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(ultrix4)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/cyrusproto.mc b/usr.sbin/sendmail/cf/cf/cyrusproto.mc
new file mode 100644
index 000000000000..125b931704c0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/cyrusproto.mc
@@ -0,0 +1,40 @@
+divert(-1)
+#
+# (C) Copyright 1995 by Carnegie Mellon University
+#
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of CMU not be
+# used in advertising or publicity pertaining to distribution of the
+# software without specific, written prior permission.
+#
+# CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+# CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+#
+# Contributed to Berkeley by John Gardiner Myers <jgm+@CMU.EDU>.
+#
+# This sample mc file is for a site that uses the Cyrus IMAP server
+# exclusively for local mail.
+#
+
+VERSIONID(`@(#)cyrusproto.mc 8.2 (Carnegie Mellon) @(#)cyrusproto.mc 8.2')
+define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')
+FEATURE(nouucp)
+FEATURE(nocanonify)
+FEATURE(always_add_domain)
+MAILER(smtp)
+MAILER(cyrus)
+
+define(`confLOCAL_MAILER',`cyrus')
+
+LOCAL_RULE_0
+Rbb + $+ < @ $=w . > $#cyrusbb $: $1
diff --git a/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc b/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc
new file mode 100644
index 000000000000..482f671d0a5f
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc
@@ -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.
+#
+
+#
+# This is a generic configuration file for 4.4 BSD-based systems,
+# including 4.4-Lite, BSDi, NetBSD, and FreeBSD.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-bsd4.4.mc 8.1 (Berkeley) 9/12/95')
+OSTYPE(bsd4.4)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-hpux10.mc b/usr.sbin/sendmail/cf/cf/generic-hpux10.mc
new file mode 100644
index 000000000000..9c59c64bed69
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-hpux10.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for HP-UX 9.x.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-hpux10.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(hpux10)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-hpux9.mc b/usr.sbin/sendmail/cf/cf/generic-hpux9.mc
new file mode 100644
index 000000000000..d56e05ec9ec6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-hpux9.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for HP-UX 9.x.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-hpux9.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(hpux9)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-osf1.mc b/usr.sbin/sendmail/cf/cf/generic-osf1.mc
new file mode 100644
index 000000000000..3134f6138f5e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-osf1.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for OSF/1.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-osf1.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(osf1)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-solaris2.mc b/usr.sbin/sendmail/cf/cf/generic-solaris2.mc
new file mode 100644
index 000000000000..7e6b84ec9046
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-solaris2.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for SunOS 5.x (a.k.a. Solaris 2.x)
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-solaris2.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(solaris2)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc b/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc
new file mode 100644
index 000000000000..1e3b3c83bfb2
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for SunOS 4.1.x.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-sunos4.1.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(sunos4.1)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc b/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc
new file mode 100644
index 000000000000..a12b3d107ffe
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc
@@ -0,0 +1,47 @@
+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.
+#
+
+#
+# This is a generic configuration file for Ultrix 4.x.
+# It has support for local and SMTP mail only. If you want to
+# customize it, copy it to a name appropriate for your environment
+# and do the modifications there.
+#
+
+VERSIONID(`@(#)generic-ultrix4.mc 8.2 (Berkeley) 8/6/95')
+OSTYPE(ultrix4)dnl
+DOMAIN(generic)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/huginn.cs.mc b/usr.sbin/sendmail/cf/cf/huginn.cs.mc
new file mode 100644
index 000000000000..4914f32e3137
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/huginn.cs.mc
@@ -0,0 +1,63 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for the backup CS Division mail server.
+#
+
+VERSIONID(`@(#)huginn.cs.mc 8.6 (Berkeley) 8/25/95')
+OSTYPE(hpux9)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MASQUERADE_AS(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+
+LOCAL_CONFIG
+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.cs.mc b/usr.sbin/sendmail/cf/cf/mail.cs.mc
new file mode 100644
index 000000000000..50daad7e68c0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/mail.cs.mc
@@ -0,0 +1,64 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for the primary CS Division mail server.
+#
+
+VERSIONID(`@(#)mail.cs.mc 8.9 (Berkeley) 8/25/95')
+OSTYPE(ultrix4)dnl
+DOMAIN(Berkeley.EDU)dnl
+MASQUERADE_AS(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`confUSERDB_SPEC', ``/usr/local/lib/users.cs.db,/usr/local/lib/users.eecs.db'')dnl
+
+LOCAL_CONFIG
+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
index 000000000000..f6d2bdcde106
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/mail.eecs.mc
@@ -0,0 +1,64 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in Electrical Engineering and Computer Sciences at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only.
+#
+# This file is for the primary EECS mail server.
+#
+
+VERSIONID(`@(#)mail.eecs.mc 8.9 (Berkeley) 8/25/95')
+OSTYPE(ultrix4)dnl
+DOMAIN(EECS.Berkeley.EDU)dnl
+MASQUERADE_AS(EECS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`confUSERDB_SPEC', `/usr/local/lib/users.eecs.db,/usr/local/lib/users.cs.db,/usr/local/lib/users.coe.db')dnl
+
+LOCAL_CONFIG
+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/mailspool.cs.mc b/usr.sbin/sendmail/cf/cf/mailspool.cs.mc
new file mode 100644
index 000000000000..0493b2dffcf0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/mailspool.cs.mc
@@ -0,0 +1,57 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for our mail spool machine. For a while we were using
+# "root.machinename" instead of "root+machinename", so this is included
+# for back compatibility.
+#
+
+VERSIONID(`@(#)mailspool.cs.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(sunos4.1)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+
+LOCAL_CONFIG
+CDroot sys-custodian
+
+LOCAL_RULE_3
+R$=D . $+ $1 + $2
diff --git a/usr.sbin/sendmail/cf/cf/python.cs.mc b/usr.sbin/sendmail/cf/cf/python.cs.mc
new file mode 100644
index 000000000000..3dff97d15300
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/python.cs.mc
@@ -0,0 +1,62 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for a home machine that wants to masquerade as an
+# on-campus machine. Additionally, all addresses without a hostname
+# will be forwarded to that machine.
+#
+
+VERSIONID(`@(#)python.cs.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(bsd4.4)dnl
+DOMAIN(CS.Berkeley.EDU)dnl
+define(`LOCAL_RELAY', vangogh.CS.Berkeley.EDU)dnl
+MASQUERADE_AS(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-osf1.mc b/usr.sbin/sendmail/cf/cf/s2k-osf1.mc
new file mode 100644
index 000000000000..db324ae51561
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/s2k-osf1.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for OSF/1.
+# It applies only the the Sequoia 2000 Project at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)s2k-osf1.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(osf1)dnl
+DOMAIN(S2K.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc b/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc
new file mode 100644
index 000000000000..1404b86393b9
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for Ultrix 4.x.
+# It applies only the the Sequoia 2000 Project at Berkeley,
+# and should not be used elsewhere. It is provided on the sendmail
+# distribution as a sample only. To create your own configuration
+# file, create an appropriate domain file in ../domain, change the
+# `DOMAIN' macro below to reference that file, and copy the result
+# to a name of your own choosing.
+#
+
+VERSIONID(`@(#)s2k-ultrix4.mc 8.3 (Berkeley) 8/6/95')
+OSTYPE(ultrix4)dnl
+DOMAIN(S2K.Berkeley.EDU)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/tcpproto.mc b/usr.sbin/sendmail/cf/cf/tcpproto.mc
new file mode 100644
index 000000000000..7f43558ca97d
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/tcpproto.mc
@@ -0,0 +1,53 @@
+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.
+#
+
+#
+# This is the prototype file for a configuration that supports nothing
+# but basic SMTP connections via TCP.
+#
+# You MUST change the `OSTYPE' macro to specify the operating system
+# on which this will run; this will set the location of various
+# support files for your operating system environment. You MAY
+# create a domain file in ../domain and reference it by adding a
+# `DOMAIN' macro after the `OSTYPE' macro. I recommend that you
+# first copy this to another file name so that new sendmail releases
+# will not trash your changes.
+#
+
+VERSIONID(`@(#)tcpproto.mc 8.4 (Berkeley) 8/6/95')
+OSTYPE(unknown)
+FEATURE(nouucp)
+MAILER(local)
+MAILER(smtp)
diff --git a/usr.sbin/sendmail/cf/cf/ucbarpa.mc b/usr.sbin/sendmail/cf/cf/ucbarpa.mc
new file mode 100644
index 000000000000..39d73908cad6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/ucbarpa.mc
@@ -0,0 +1,50 @@
+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.
+#
+
+#
+# This machine has been decommissioned at Berkeley, and hence should
+# not be considered to be tested. This file is provided as an example
+# only, of how you might set up a joint SMTP/UUCP configuration. At
+# this point I recommend using `FEATURE(mailertable)' instead of
+# `SITECONFIG'. See also ucbvax.mc.
+#
+
+VERSIONID(`@(#)ucbarpa.mc 8.3 (Berkeley) 8/6/95')
+DOMAIN(CS.Berkeley.EDU)dnl
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+MAILER(uucp)dnl
+SITECONFIG(uucp.ucbarpa, ucbarpa, U)
diff --git a/usr.sbin/sendmail/cf/cf/ucbvax.mc b/usr.sbin/sendmail/cf/cf/ucbvax.mc
new file mode 100644
index 000000000000..cc8cd2ce66de
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/ucbvax.mc
@@ -0,0 +1,111 @@
+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.
+#
+
+#
+# This machine has been decommissioned at Berkeley, and hence should
+# not be considered to be tested. This file is provided as an example
+# only, of how you might set up a fairly complex configuration.
+# Ucbvax was our main relay (both SMTP and UUCP) for many years.
+# At this point I recommend using `FEATURE(mailertable)' instead of
+# `SITECONFIG' for routing of UUCP within your domain.
+#
+
+VERSIONID(`@(#)ucbvax.mc 8.5 (Berkeley) 8/25/95')
+OSTYPE(bsd4.3)
+DOMAIN(CS.Berkeley.EDU)
+MASQUERADE_AS(CS.Berkeley.EDU)
+MAILER(local)
+MAILER(smtp)
+MAILER(uucp)
+undefine(`UUCP_RELAY')dnl
+
+LOCAL_CONFIG
+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/uucpproto.mc b/usr.sbin/sendmail/cf/cf/uucpproto.mc
new file mode 100644
index 000000000000..49c4a0de6562
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/uucpproto.mc
@@ -0,0 +1,53 @@
+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.
+#
+
+#
+# This is the prototype for a configuration that only supports UUCP
+# and does not have DNS support at all.
+#
+# You MUST change the `OSTYPE' macro to specify the operating system
+# on which this will run; this will set the location of various
+# support files for your operating system environment. You MAY
+# create a domain file in ../domain and reference it by adding a
+# `DOMAIN' macro after the `OSTYPE' macro. I recommend that you
+# first copy this to another file name so that new sendmail releases
+# will not trash your changes.
+#
+
+VERSIONID(`@(#)uucpproto.mc 8.5 (Berkeley) 8/6/95')
+OSTYPE(unknown)
+FEATURE(nodns)dnl
+MAILER(local)dnl
+MAILER(uucp)dnl
diff --git a/usr.sbin/sendmail/cf/cf/vangogh.cs.mc b/usr.sbin/sendmail/cf/cf/vangogh.cs.mc
new file mode 100644
index 000000000000..2be3179ea9bf
--- /dev/null
+++ b/usr.sbin/sendmail/cf/cf/vangogh.cs.mc
@@ -0,0 +1,53 @@
+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.
+#
+
+#
+# This is a Berkeley-specific configuration file for a specific
+# machine in the Computer Science Division at Berkeley, and should
+# not be used elsewhere. It is provided on the sendmail distribution
+# as a sample only.
+#
+# This file is for the BSD development machine; it has some parameters
+# set up (to stress sendmail) and accepts mail for some other machines.
+#
+
+VERSIONID(`@(#)vangogh.cs.mc 8.4 (Berkeley) 8/6/95')
+DOMAIN(CS.Berkeley.EDU)dnl
+OSTYPE(bsd4.4)dnl
+MAILER(local)dnl
+MAILER(smtp)dnl
+define(`MCI_CACHE_SIZE', 5)
+Cw okeeffe.CS.Berkeley.EDU
+Cw python.CS.Berkeley.EDU
diff --git a/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4 b/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4
new file mode 100644
index 000000000000..2bad42bc3063
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4
@@ -0,0 +1,45 @@
+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.EDU.m4 8.9 (Berkeley) 10/5/95')
+DOMAIN(berkeley-only)dnl
+define(`BITNET_RELAY', `bitnet-relay.Berkeley.EDU')dnl
+define(`UUCP_RELAY', `uucp-relay.Berkeley.EDU')dnl
+define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward')dnl
+define(`confCW_FILE', `-o /etc/sendmail.cw')dnl
+define(`confDONT_INIT_GROUPS', True)dnl
+FEATURE(redirect)dnl
+FEATURE(use_cw_file)dnl
+FEATURE(stickyhost)dnl
diff --git a/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4 b/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4
new file mode 100644
index 000000000000..97ccfb208992
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4
@@ -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.Berkeley.EDU.m4 8.2 (Berkeley) 4/21/95')
+DOMAIN(Berkeley.EDU)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/EECS.Berkeley.EDU.m4 b/usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m4
new file mode 100644
index 000000000000..a41fc7ed823a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m4
@@ -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.Berkeley.EDU.m4 8.2 (Berkeley) 4/21/95')
+DOMAIN(Berkeley.EDU)dnl
+MASQUERADE_AS(EECS.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4 b/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4
new file mode 100644
index 000000000000..4aed130b7ba2
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4
@@ -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.Berkeley.EDU.m4 8.2 (Berkeley) 4/21/95')
+DOMAIN(CS.Berkeley.EDU)dnl
+MASQUERADE_AS(postgres.Berkeley.EDU)dnl
diff --git a/usr.sbin/sendmail/cf/domain/berkeley-only.m4 b/usr.sbin/sendmail/cf/domain/berkeley-only.m4
new file mode 100644
index 000000000000..ef710714ea9e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/berkeley-only.m4
@@ -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(`@(#)unspecified-domain.m4 8.2 (Berkeley) 4/21/95')
+errprint(`*** ERROR: You are trying to use the Berkeley sample configuration')
+errprint(` files outside of the Computer Science Division at Berkeley.')
+errprint(` The configuration (.mc) files must be customized to reference')
+errprint(` domain files appropriate for your environment.')
diff --git a/usr.sbin/sendmail/cf/domain/generic.m4 b/usr.sbin/sendmail/cf/domain/generic.m4
new file mode 100644
index 000000000000..6799ff895227
--- /dev/null
+++ b/usr.sbin/sendmail/cf/domain/generic.m4
@@ -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.
+#
+
+#
+# The following is a generic domain file. You should be able to
+# use it anywhere. If you want to customize it, copy it to a file
+# named with your domain and make the edits; then, copy the appropriate
+# .mc files and change `DOMAIN(generic)' to reference your updated domain
+# files.
+#
+divert(0)
+VERSIONID(`@(#)generic.m4 8.2 (Berkeley) 4/21/95')
+define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward')dnl
+define(`confCW_FILE', `-o /etc/sendmail.cw')dnl
+FEATURE(redirect)dnl
+FEATURE(use_cw_file)dnl
diff --git a/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4 b/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4
new file mode 100644
index 000000000000..23dff8c93eef
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4
@@ -0,0 +1,58 @@
+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(`@(#)bestmx_is_local.m4 8.2 (Berkeley) 10/29/95')
+divert(-1)
+
+LOCAL_CONFIG
+Kbestmx bestmx
+
+LOCAL_NET_CONFIG
+
+# If we are the best MX for a site, then we want to accept
+# its mail as local. We assume we've already weeded out mail to
+# UUCP sites which are connected to us, which should also have
+# listed us as their best MX.
+#
+# Warning: this may generate a lot of extra DNS traffic -- a
+# lower cost method is to list all the expected best MX hosts
+# in $=w. This should be fine (and easier to administer) for
+# low to medium traffic hosts.
+
+R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3
+R$* $=O $* < @ $* @@ $=w . > $* $@ $>97 $1 $2 $3
+R$* < @ $* @@ $=w . > $* $#local $: $1
+R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4
diff --git a/usr.sbin/sendmail/cf/feature/local_procmail.m4 b/usr.sbin/sendmail/cf/feature/local_procmail.m4
new file mode 100644
index 000000000000..9087a690d082
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/local_procmail.m4
@@ -0,0 +1,44 @@
+divert(-1)
+#
+# Copyright (c) 1994 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(`@(#)local_procmail.m4 8.3 (Berkeley) 10/29/95')
+divert(-1)
+
+define(`PROCMAIL_PATH',
+ ifelse(_ARG_, `', `/usr/local/bin/procmail', `_ARG_'))
+define(`LOCAL_MAILER_FLAGS', `SPfhn')
+define(`LOCAL_MAILER_PATH', PROCMAIL_PATH)
+define(`LOCAL_MAILER_ARGS', `procmail -Y -a $h -d $u')
diff --git a/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4 b/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4
new file mode 100644
index 000000000000..1e6010856ea6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4
@@ -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(`@(#)masquerade_envelope.m4 8.1 (Berkeley) 7/9/95')
+divert(-1)
+
+define(`_MASQUERADE_ENVELOPE_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/notsticky.m4 b/usr.sbin/sendmail/cf/feature/notsticky.m4
new file mode 100644
index 000000000000..027b8e3a51c0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/notsticky.m4
@@ -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.
+#
+
+divert(0)
+VERSIONID(`@(#)notsticky.m4 8.3 (Berkeley) 5/29/95')
+#
+# This is now the default. Use ``FEATURE(stickyhost)'' if you want
+# the old default behaviour.
+#
+divert(-1)
diff --git a/usr.sbin/sendmail/cf/feature/nullclient.m4 b/usr.sbin/sendmail/cf/feature/nullclient.m4
new file mode 100644
index 000000000000..7543070f77f7
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/nullclient.m4
@@ -0,0 +1,71 @@
+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', `')')
+define(_NULL_CLIENT_ONLY_, `1')
+ifelse(_ARG_, `', `errprint(`Feature "nullclient" requires argument')',
+ `define(`MAIL_HUB', _ARG_)')
+POPDIVERT
+
+#
+# This is used only for relaying mail from a client to a hub when
+# that client does absolutely nothing else -- i.e., it is a "null
+# mailer". In this sense, it acts like the "R" option in Sun
+# sendmail.
+#
+
+VERSIONID(`@(#)nullclient.m4 8.6 (Berkeley) 6/29/95')
+
+PUSHDIVERT(6)
+# hub host (to which all mail is sent)
+DH`'ifdef(`MAIL_HUB', MAIL_HUB,
+ `errprint(`MAIL_HUB not defined for nullclient feature')')
+ifdef(`MASQUERADE_NAME',, `define(`MASQUERADE_NAME', MAIL_HUB)')dnl
+
+# route-addr separators
+C: : ,
+POPDIVERT
+PUSHDIVERT(7)
+############################################
+### Null Client Mailer specification ###
+############################################
+
+ifdef(`confRELAY_MAILER',,
+ `define(`confRELAY_MAILER', `nullclient')')dnl
+ifdef(`confFROM_HEADER',,
+ `define(`confFROM_HEADER', <$g>)')dnl
+
+Mnullclient, P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS),ifdef(`SMTP_MAILER_MAX', ` M=SMTP_MAILER_MAX,')
+ A=IPC $h
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/feature/redirect.m4 b/usr.sbin/sendmail/cf/feature/redirect.m4
new file mode 100644
index 000000000000..081db113ae01
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/redirect.m4
@@ -0,0 +1,50 @@
+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.4 (Berkeley) 6/25/95')
+divert(-1)
+
+
+PUSHDIVERT(3)
+# addresses sent to foo@host.REDIRECT will give a 551 error code
+R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} >
+R$* < @ $+ .REDIRECT. > <i> $: $1 < @ $2 . REDIRECT. >
+R$* < @ $+ .REDIRECT. > < $- > $# error $@ 5.1.1 $: "551 User not local; please try " <$1@$2>
+POPDIVERT
+
+PUSHDIVERT(6)
+CPREDIRECT
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/feature/smrsh.m4 b/usr.sbin/sendmail/cf/feature/smrsh.m4
new file mode 100644
index 000000000000..6b4faab25261
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/smrsh.m4
@@ -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.
+#
+
+divert(0)
+VERSIONID(`@(#)smrsh.m4 8.2 (Berkeley) 11/11/95')
+divert(-1)
+
+ifdef(`_MAILER_local_',
+ `errprint(`*** FEATURE(smrsh) must occur before MAILER(local)')')dnl
+define(`LOCAL_SHELL_PATH', ifelse(_ARG_, `', `/usr/local/etc/smrsh', _ARG_))
diff --git a/usr.sbin/sendmail/cf/feature/stickyhost.m4 b/usr.sbin/sendmail/cf/feature/stickyhost.m4
new file mode 100644
index 000000000000..bdd9c9a729f0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/stickyhost.m4
@@ -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(`@(#)stickyhost.m4 8.1 (Berkeley) 11/12/94')
+divert(-1)
+
+define(`_STICKY_LOCAL_DOMAIN_', 1)
diff --git a/usr.sbin/sendmail/cf/feature/use_ct_file.m4 b/usr.sbin/sendmail/cf/feature/use_ct_file.m4
new file mode 100644
index 000000000000..c33bbfd7833e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/feature/use_ct_file.m4
@@ -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_ct_file.m4 8.1 (Berkeley) 9/17/95')
+divert(-1)
+
+# if defined, the sendmail.cf will read the /etc/sendmail.ct file
+# to find the names of trusted users. There should only be a few
+# of these, and normally this is done directly in the .cf file.
+
+define(`_USE_CT_FILE_', `')
+
+divert(0)
diff --git a/usr.sbin/sendmail/cf/m4/cf.m4 b/usr.sbin/sendmail/cf/m4/cf.m4
new file mode 100644
index 000000000000..4e54f4142898
--- /dev/null
+++ b/usr.sbin/sendmail/cf/m4/cf.m4
@@ -0,0 +1,50 @@
+divert(-1)
+#
+# Copyright (c) 1983, 1995 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.
+#
+
+#
+# This file is included so that multiple includes of cf.m4 will work
+#
+
+# figure out where the CF files live
+ifdef(`_CF_DIR_', `',
+ `ifelse(__file__, `__file__',
+ `define(`_CF_DIR_', `../')',
+ `define(`_CF_DIR_',
+ substr(__file__, 0, eval(len(__file__) - 8)))')')
+
+divert(0)dnl
+ifdef(`OSTYPE', `dnl',
+`include(_CF_DIR_`'m4/cfhead.m4)dnl
+VERSIONID(`@(#)cf.m4 8.24 (Berkeley) 8/16/95')')
diff --git a/usr.sbin/sendmail/cf/m4/cfhead.m4 b/usr.sbin/sendmail/cf/m4/cfhead.m4
new file mode 100644
index 000000000000..46605e7e34c0
--- /dev/null
+++ b/usr.sbin/sendmail/cf/m4/cfhead.m4
@@ -0,0 +1,147 @@
+#
+# Copyright (c) 1983, 1995 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 _CF_DIR_`'sh/makeinfo.sh _CF_DIR_ > TEMPFILE)dnl
+include(TEMPFILE)dnl
+syscmd(rm -f TEMPFILE)dnl
+#####
+######################################################################
+######################################################################
+
+divert(-1)
+
+changecom()
+undefine(`format')
+undefine(`hpux')
+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)
+ ifdef(`__OSTYPE__', `errprint(`duplicate OSTYPE'($1))')
+ define(`__OSTYPE__', $1)
+ define(`_ARG_', $2)
+ include(_CF_DIR_`'ostype/$1.m4)POPDIVERT`'')
+define(`MAILER',
+`ifdef(`_MAILER_$1_', `dnl`'',
+`define(`_MAILER_$1_', `')PUSHDIVERT(7)include(_CF_DIR_`'mailer/$1.m4)POPDIVERT`'')')
+define(`DOMAIN', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'domain/$1.m4)POPDIVERT`'')
+define(`FEATURE', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'feature/$1.m4)POPDIVERT`'')
+define(`HACK', `PUSHDIVERT(-1)define(`_ARG_', $2)include(_CF_DIR_`'hack/$1.m4)POPDIVERT`'')
+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 $2.UUCP, `dnl')
+define(`SITE', `ifelse(CONCAT($'2`, $3), SU,
+ CONCAT(CY, $'1`),
+ CONCAT(C, $3, $'1`))')
+sinclude(_CF_DIR_`'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)')
+define(`MASQUERADE_DOMAIN', `PUSHDIVERT(5)CM$1
+POPDIVERT`'dnl')
+define(`MASQUERADE_DOMAIN_FILE', `PUSHDIVERT(5)FM$1
+POPDIVERT`'dnl')
+define(`_OPTINS', `ifdef(`$1', `$2$1$3')')
+
+m4wrap(`include(_CF_DIR_`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; $b')
+define(`confRECEIVED_HEADER', `$?sfrom $s $.$?_($?s$|from $.$_) $.by $j ($v/$Z)$?r with $r$. id $i$?u for $u$.; $b')
+define(`confSEVEN_BIT_INPUT', `False')
+define(`confEIGHT_BIT_HANDLING', `pass8')
+define(`confALIAS_WAIT', `10')
+define(`confMIN_FREE_BLOCKS', `100')
+define(`confBLANK_SUB', `.')
+define(`confCON_EXPENSIVE', `False')
+define(`confDELIVERY_MODE', `background')
+define(`confTEMP_FILE_MODE', `0600')
+define(`confMCI_CACHE_SIZE', `2')
+define(`confMCI_CACHE_TIMEOUT', `5m')
+define(`confUSE_ERRORS_TO', `False')
+define(`confLOG_LEVEL', `9')
+define(`confCHECK_ALIASES', `False')
+define(`confOLD_STYLE_HEADERS', `True')
+define(`confPRIVACY_FLAGS', `authwarnings')
+define(`confSAFE_QUEUE', `True')
+define(`confTO_QUEUERETURN', `5d')
+define(`confTO_QUEUEWARN', `4h')
+define(`confTIME_ZONE', `USE_SYSTEM')
+define(`confDEF_USER_ID', `1:1')
+define(`confCW_FILE', `/etc/sendmail.cw')
+define(`confMIME_FORMAT_ERRORS', `True')
+define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward')
+
+divert(0)dnl
+VERSIONID(`@(#)cfhead.m4 8.3 (Berkeley) 9/15/95')
diff --git a/usr.sbin/sendmail/cf/m4/nullrelay.m4 b/usr.sbin/sendmail/cf/m4/nullrelay.m4
new file mode 100644
index 000000000000..799f3ab79198
--- /dev/null
+++ b/usr.sbin/sendmail/cf/m4/nullrelay.m4
@@ -0,0 +1,129 @@
+divert(-1)
+#
+# Copyright (c) 1983, 1995 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(`@(#)nullrelay.m4 8.10 (Berkeley) 9/29/95')
+
+#
+# This configuration applies only to relay-only hosts. They send
+# all mail to a hub without consideration of the address syntax
+# or semantics, except for adding the hub qualification to the
+# addresses.
+#
+# This is based on a prototype done by Bryan Costales of ICSI.
+#
+
+######################################################################
+######################################################################
+#####
+##### REWRITING RULES
+#####
+######################################################################
+######################################################################
+
+###########################################
+### Rulset 3 -- Name Canonicalization ###
+###########################################
+S3
+
+# handle null input
+R$@ $@ <@>
+
+# strip group: syntax (not inside angle brackets!) and trailing semicolon
+R$* $: $1 <@> mark addresses
+R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr>
+R$* :: $* <@> $: $1 :: $2 unmark node::addr
+R:`include': $* <@> $: :`include': $1 unmark :`include':...
+R$* : $* <@> $: $2 strip colon if marked
+R$* <@> $: $1 unmark
+R$* ; $: $1 strip trailing semi
+
+# null input now results from list:; syntax
+R$@ $@ :; <@>
+
+# 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
+
+ifdef(`_NO_CANONIFY_', `dnl',
+`# eliminate local host if present
+R@ $=w $=: $+ $@ @ $M $2 $3 @thishost ...
+R@ $+ $@ @ $1 @somewhere ...
+
+R$+ @ $=w $@ $1 @ $M ...@thishost
+R$+ @ $+ $@ $1 @ $2 ...@somewhere
+
+R$=w ! $+ $@ $2 @ $M thishost!...
+R$+ ! $+ $@ $1 ! $2 @ $M somewhere ! ...
+
+R$+ % $=w $@ $1 @ $M ...%thishost
+R$+ % $+ $@ $1 @ $2 ...%somewhere
+
+R$+ $@ $1 @ $M unadorned user')
+
+
+######################################
+### Ruleset 0 -- Parse Address ###
+######################################
+
+S0
+
+R$*:;<@> $#error $@ USAGE $: "list:; syntax illegal for recipient addresses"
+
+# pass everything else to a relay host
+R$* $#_RELAY_ $@ $H $: $1
+
+
+##################################################
+### Ruleset 4 -- Final Output Post-rewriting ###
+##################################################
+S4
+
+R$* <@> $@ handle <> and list:;
+
+# strip trailing dot off before passing to nullclient relay
+R$* @ $+ . $1 @ $2
+
+#
+######################################################################
+######################################################################
+#####
+`##### MAILER DEFINITIONS'
+#####
+######################################################################
+######################################################################
+undivert(7)dnl
diff --git a/usr.sbin/sendmail/cf/m4/proto.m4 b/usr.sbin/sendmail/cf/m4/proto.m4
new file mode 100644
index 000000000000..2397c4a7f6f1
--- /dev/null
+++ b/usr.sbin/sendmail/cf/m4/proto.m4
@@ -0,0 +1,818 @@
+divert(-1)
+#
+# Copyright (c) 1983, 1995 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.99 (Berkeley) 11/18/95')
+
+MAILER(local)dnl
+
+# level 6 config file format
+V6/Berkeley
+divert(-1)
+
+# do some sanity checking
+ifdef(`__OSTYPE__',,
+ `errprint(`*** ERROR: No system type defined (use OSTYPE macro)')')
+
+# pick our default mailers
+ifdef(`confSMTP_MAILER',, `define(`confSMTP_MAILER', `smtp')')
+ifdef(`confLOCAL_MAILER',, `define(`confLOCAL_MAILER', `local')')
+ifdef(`confRELAY_MAILER',,
+ `define(`confRELAY_MAILER',
+ `ifdef(`_MAILER_smtp_', `relay',
+ `ifdef(`_MAILER_uucp', `uucp-new', `unknown')')')')
+ifdef(`confUUCP_MAILER',, `define(`confUUCP_MAILER', `uucp-old')')
+define(`_SMTP_', `confSMTP_MAILER')dnl for readability only
+define(`_LOCAL_', `confLOCAL_MAILER')dnl for readability only
+define(`_RELAY_', `confRELAY_MAILER')dnl for readability only
+define(`_UUCP_', `confUUCP_MAILER')dnl for readability only
+
+# back compatibility with old config files
+ifdef(`confDEF_GROUP_ID',
+ `errprint(`*** confDEF_GROUP_ID is obsolete.')
+ errprint(` Use confDEF_USER_ID with a colon in the value instead.')')
+ifdef(`confREAD_TIMEOUT',
+ `errprint(`*** confREAD_TIMEOUT is obsolete.')
+ errprint(` Use individual confTO_<timeout> parameters instead.')')
+ifdef(`confMESSAGE_TIMEOUT',
+ `define(`_ARG_', index(confMESSAGE_TIMEOUT, /))
+ ifelse(_ARG_, -1,
+ `define(`confTO_QUEUERETURN', confMESSAGE_TIMEOUT)',
+ `define(`confTO_QUEUERETURN',
+ substr(confMESSAGE_TIMEOUT, 0, _ARG_))
+ define(`confTO_QUEUEWARN',
+ substr(confMESSAGE_TIMEOUT, eval(_ARG_+1)))')')
+ifdef(`confMIN_FREE_BLOCKS', `ifelse(index(confMIN_FREE_BLOCKS, /), -1,,
+ `errprint(`*** compound confMIN_FREE_BLOCKS is obsolete.')
+ errprint(` Use confMAX_MESSAGE_SIZE for the second part of the value.')')')
+
+# clean option definitions below....
+define(`_OPTION', `ifdef(`$2', `O $1=$2', `#O $1`'ifelse($3, `',, `=$3')')')dnl
+
+divert(0)dnl
+
+##################
+# local info #
+##################
+
+Cwlocalhost
+ifdef(`USE_CW_FILE',
+`# file containing names of hosts for which we receive email
+Fw`'confCW_FILE',
+ `dnl')
+
+# my official domain name
+# ... define this only if sendmail cannot automatically determine your domain
+ifdef(`confDOMAIN_NAME', `Dj`'confDOMAIN_NAME', `#Dj$w.Foo.COM')
+
+ifdef(`_NULL_CLIENT_ONLY_', `divert(-1)')dnl
+
+CP.
+
+ifdef(`UUCP_RELAY',
+`# UUCP relay host
+DY`'UUCP_RELAY
+CPUUCP
+
+')dnl
+ifdef(`BITNET_RELAY',
+`# BITNET relay host
+DB`'BITNET_RELAY
+CPBITNET
+
+')dnl
+ifdef(`DECNET_RELAY',
+`define(`_USE_DECNET_SYNTAX_', 1)dnl
+# DECnet relay host
+DC`'DECNET_RELAY
+CPDECNET
+
+')dnl
+ifdef(`FAX_RELAY',
+`# FAX relay host
+DF`'FAX_RELAY
+CPFAX
+
+')dnl
+# "Smart" relay host (may be null)
+DS`'ifdef(`SMART_HOST', SMART_HOST)
+
+# place to which unknown users should be forwarded
+ifdef(`LUSER_RELAY', `', `#')dnl
+Kuser user -m -a<>
+ifdef(`LUSER_RELAY',
+ `DL`'LUSER_RELAY',
+ `#DLname_of_luser_relay')
+
+# 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..
+
+# Mailer table (overriding domains)
+ifdef(`MAILER_TABLE',
+ `Kmailertable MAILER_TABLE',
+ `#Kmailertable dbm /etc/mailertable')
+
+# Domain table (adding domains)
+ifdef(`DOMAIN_TABLE',
+ `Kdomaintable DOMAIN_TABLE',
+ `#Kdomaintable dbm /etc/domaintable')
+
+# who I send unqualified names to (null means deliver locally)
+DR`'ifdef(`LOCAL_RELAY', LOCAL_RELAY)
+
+# who gets all local email traffic ($R has precedence for unqualified names)
+DH`'ifdef(`MAIL_HUB', MAIL_HUB)
+
+# 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
+# class M: domains that should be converted to $M
+#CL root
+CE root
+undivert(5)dnl
+
+# dequoting map
+Kdequote dequote
+
+divert(0)dnl # end of nullclient diversion
+# who I masquerade as (null for no masquerading) (see also $=M)
+DM`'ifdef(`MASQUERADE_NAME', MASQUERADE_NAME)
+
+# my name for error messages
+ifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON')
+
+undivert(6)dnl
+include(_CF_DIR_`m4/version.m4')
+
+###############
+# Options #
+###############
+
+# strip message body to 7 bits on input?
+_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT')
+
+# 8-bit data handling
+_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', adaptive)
+
+ifdef(`_NULL_CLIENT_ONLY_', `dnl', `
+# wait for alias file rebuild (default units: minutes)
+_OPTION(AliasWait, `confALIAS_WAIT', 5m)
+
+# location of alias file
+O AliasFile=ifdef(`ALIAS_FILE', `ALIAS_FILE', /etc/aliases)
+')
+# minimum number of free blocks on filesystem
+_OPTION(MinFreeBlocks, `confMIN_FREE_BLOCKS', 100)
+
+# maximum message size
+_OPTION(MaxMessageSize, `confMAX_MESSAGE_SIZE', 1000000)
+
+# substitution for space (blank) characters
+_OPTION(BlankSub, `confBLANK_SUB', _)
+
+# avoid connecting to "expensive" mailers on initial submission?
+_OPTION(HoldExpensive, `confCON_EXPENSIVE')
+
+# checkpoint queue runs after every N successful deliveries
+_OPTION(CheckpointInterval, `confCHECKPOINT_INTERVAL', 10)
+
+# default delivery mode
+_OPTION(DeliveryMode, `confDELIVERY_MODE', background)
+
+# automatically rebuild the alias database?
+_OPTION(AutoRebuildAliases, `confAUTO_REBUILD')
+
+# error message header/file
+_OPTION(ErrorHeader, `confERROR_MESSAGE', /etc/sendmail.oE)
+
+# error mode
+_OPTION(ErrorMode, `confERROR_MODE', print)
+
+# save Unix-style "From_" lines at top of header?
+_OPTION(SaveFromLine, `confSAVE_FROM_LINES')
+
+# temporary file mode
+_OPTION(TempFileMode, `confTEMP_FILE_MODE', 0600)
+
+# match recipients against GECOS field?
+_OPTION(MatchGECOS, `confMATCH_GECOS')
+
+# maximum hop count
+_OPTION(MaxHopCount, `confMAX_HOP', 17)
+
+# location of help file
+O HelpFile=ifdef(`HELP_FILE', HELP_FILE, /usr/lib/sendmail.hf)
+
+# ignore dots as terminators in incoming messages?
+_OPTION(IgnoreDots, `confIGNORE_DOTS')
+
+# name resolver options
+_OPTION(ResolverOptions, `confBIND_OPTS', +AAONLY)
+
+# deliver MIME-encapsulated error messages?
+_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS')
+
+# Forward file search path
+_OPTION(ForwardPath, `confFORWARD_PATH', /var/forward/$u:$z/.forward.$w:$z/.forward)
+
+# open connection cache size
+_OPTION(ConnectionCacheSize, `confMCI_CACHE_SIZE', 2)
+
+# open connection cache timeout
+_OPTION(ConnectionCacheTimeout, `confMCI_CACHE_TIMEOUT', 5m)
+
+# use Errors-To: header?
+_OPTION(UseErrorsTo, `confUSE_ERRORS_TO')
+
+# log level
+_OPTION(LogLevel, `confLOG_LEVEL', 10)
+
+# send to me too, even in an alias expansion?
+_OPTION(MeToo, `confME_TOO')
+
+# verify RHS in newaliases?
+_OPTION(CheckAliases, `confCHECK_ALIASES')
+
+# default messages to old style headers if no special punctuation?
+_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS')
+
+# SMTP daemon options
+_OPTION(DaemonPortOptions, `confDAEMON_OPTIONS', Port=esmtp)
+
+# privacy flags
+_OPTION(PrivacyOptions, `confPRIVACY_FLAGS', authwarnings)
+
+# who (if anyone) should get extra copies of error messages
+_OPTION(PostMasterCopy, `confCOPY_ERRORS_TO', Postmaster)
+
+# slope of queue-only function
+_OPTION(QueueFactor, `confQUEUE_FACTOR', 600000)
+
+# queue directory
+O QueueDirectory=ifdef(`QUEUE_DIR', QUEUE_DIR, /var/spool/mqueue)
+
+# timeouts (many of these)
+_OPTION(Timeout.initial, `confTO_INITIAL', 5m)
+_OPTION(Timeout.helo, `confTO_HELO', 5m)
+_OPTION(Timeout.mail, `confTO_MAIL', 10m)
+_OPTION(Timeout.rcpt, `confTO_RCPT', 1h)
+_OPTION(Timeout.datainit, `confTO_DATAINIT', 5m)
+_OPTION(Timeout.datablock, `confTO_DATABLOCK', 1h)
+_OPTION(Timeout.datafinal, `confTO_DATAFINAL', 1h)
+_OPTION(Timeout.rset, `confTO_RSET', 5m)
+_OPTION(Timeout.quit, `confTO_QUIT', 2m)
+_OPTION(Timeout.misc, `confTO_MISC', 2m)
+_OPTION(Timeout.command, `confTO_COMMAND', 1h)
+_OPTION(Timeout.ident, `confTO_IDENT', 30s)
+_OPTION(Timeout.fileopen, `confTO_FILEOPEN', 60s)
+_OPTION(Timeout.queuereturn, `confTO_QUEUERETURN', 5d)
+_OPTION(Timeout.queuereturn.normal, `confTO_QUEUERETURN_NORMAL', 5d)
+_OPTION(Timeout.queuereturn.urgent, `confTO_QUEUERETURN_URGENT', 2d)
+_OPTION(Timeout.queuereturn.non-urgent, `confTO_QUEUERETURN_NONURGENT', 7d)
+_OPTION(Timeout.queuewarn, `confTO_QUEUEWARN', 4h)
+_OPTION(Timeout.queuewarn.normal, `confTO_QUEUEWARN_NORMAL', 4h)
+_OPTION(Timeout.queuewarn.urgent, `confTO_QUEUEWARN_URGENT', 1h)
+_OPTION(Timeout.queuewarn.non-urgent, `confTO_QUEUEWARN_NONURGENT', 12h)
+
+# should we not prune routes in route-addr syntax addresses?
+_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES')
+
+# queue up everything before forking?
+_OPTION(SuperSafe, `confSAFE_QUEUE')
+
+# status file
+O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', /etc/sendmail.st)
+
+# 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', `#O TimeZoneSpec=',
+ confTIME_ZONE, `USE_TZ', `O TimeZoneSpec=',
+ `O TimeZoneSpec=confTIME_ZONE')
+
+# default UID (can be username or userid:groupid)
+_OPTION(DefaultUser, `confDEF_USER_ID', nobody)
+
+# list of locations of user database file (null means no lookup)
+_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', /etc/userdb)
+
+# fallback MX host
+_OPTION(FallbackMXhost, `confFALLBACK_MX', fall.back.host.net)
+
+# if we are the best MX host for a site, try it directly instead of config err
+_OPTION(TryNullMXList, `confTRY_NULL_MX_LIST')
+
+# load average at which we just queue messages
+_OPTION(QueueLA, `confQUEUE_LA', 8)
+
+# load average at which we refuse connections
+_OPTION(RefuseLA, `confREFUSE_LA', 12)
+
+# work recipient factor
+_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', 30000)
+
+# deliver each queued job in a separate process?
+_OPTION(ForkEachJob, `confSEPARATE_PROC')
+
+# work class factor
+_OPTION(ClassFactor, `confWORK_CLASS_FACTOR', 1800)
+
+# work time factor
+_OPTION(RetryFactor, `confWORK_TIME_FACTOR', 90000)
+
+# shall we sort the queue by hostname first?
+_OPTION(QueueSortOrder, `confQUEUE_SORT_ORDER', priority)
+
+# minimum time in queue before retry
+_OPTION(MinQueueAge, `confMIN_QUEUE_AGE', 30m)
+
+# default character set
+_OPTION(DefaultCharSet, `confDEF_CHAR_SET', iso-8859-1)
+
+# service switch file (ignored on Solaris, Ultrix, OSF/1, others)
+_OPTION(ServiceSwitchFile, `confSERVICE_SWITCH_FILE', /etc/service.switch)
+
+# dialup line delay on connection failure
+_OPTION(DialDelay, `confDIAL_DELAY', 10s)
+
+# action to take if there are no recipients in the message
+_OPTION(NoRecipientAction, `confNO_RCPT_ACTION', add-to-undisclosed)
+
+# chrooted environment for writing to files
+_OPTION(SafeFileEnvironment, `confSAFE_FILE_ENV', /arch)
+
+# are colons OK in addresses?
+_OPTION(ColonOkInAddr, `confCOLON_OK_IN_ADDR')
+
+# how many jobs can you process in the queue?
+_OPTION(MaxQueueRunSize, `confMAX_QUEUE_RUN_SIZE', 10000)
+
+# shall I avoid expanding CNAMEs (violates protocols)?
+_OPTION(DontExpandCnames, `confDONT_EXPAND_CNAMES')
+
+# SMTP initial login message (old $e macro)
+_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG')
+
+# UNIX initial From header format (old $l macro)
+_OPTION(UnixFromLine, `confFROM_LINE')
+
+# delimiter (operator) characters (old $o macro)
+_OPTION(OperatorChars, `confOPERATORS')
+
+# shall I avoid calling initgroups(3) because of high NIS costs?
+_OPTION(DontInitGroups, `confDONT_INIT_GROUPS')
+
+###########################
+# Message precedences #
+###########################
+
+Pfirst-class=0
+Pspecial-delivery=100
+Plist=-30
+Pbulk=-60
+Pjunk=-100
+
+#####################
+# Trusted users #
+#####################
+
+# this is equivalent to setting class "t"
+ifdef(`_USE_CT_FILE_', `', `#')Ft`'ifdef(`confCT_FILE', confCT_FILE, `/etc/sendmail.ct')
+Troot
+Tdaemon
+Tuucp
+ifdef(`confTRUSTED_USERS', `T`'confTRUSTED_USERS', `dnl')
+
+#########################
+# Format of headers #
+#########################
+
+ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `$?x$x <$g>$|$g$.')')dnl
+H?P?Return-Path: $g
+HReceived: confRECEIVED_HEADER
+H?D?Resent-Date: $a
+H?D?Date: $a
+H?F?Resent-From: confFROM_HEADER
+H?F?From: confFROM_HEADER
+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>
+ifdef(`_NULL_CLIENT_ONLY_',
+ `include(_CF_DIR_`'m4/nullrelay.m4)m4exit',
+ `dnl')
+#
+######################################################################
+######################################################################
+#####
+##### REWRITING RULES
+#####
+######################################################################
+######################################################################
+
+undivert(9)dnl
+
+###########################################
+### Rulset 3 -- Name Canonicalization ###
+###########################################
+S3
+
+# handle null input (translate to <@> special case)
+R$@ $@ <@>
+
+# strip group: syntax (not inside angle brackets!) and trailing semicolon
+R$* $: $1 <@> mark addresses
+R$* < $* > $* <@> $: $1 < $2 > $3 unmark <addr>
+R$* :: $* <@> $: $1 :: $2 unmark node::addr
+R:`include': $* <@> $: :`include': $1 unmark :`include':...
+R$* : $* <@> $: $2 strip colon if marked
+R$* <@> $: $1 unmark
+R$* ; $: $1 strip trailing semi
+
+# null input now results from list:; syntax
+R$@ $@ :; <@>
+
+# strip angle brackets -- note RFC733 heuristic to get innermost item
+R$* $: < $1 > housekeeping <>
+R$+ < $* > < $2 > strip excess on left
+R< $* > $+ < $1 > strip excess on right
+R<> $@ < @ > MAIL FROM:<> case
+R< $+ > $: $1 remove housekeeping <>
+
+# 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@ $+ : $+ $@ $>96 < @$1 > : $2 handle <route-addr>
+
+# find focus for list syntax
+R $+ : $* ; @ $+ $@ $>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$+ < @ $+ > $@ $>96 $1 < @ $2 > already canonical
+
+# do some sanity checking
+R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs
+
+ifdef(`_NO_UUCP_', `dnl',
+`# convert old-style addresses to a domain-based address
+R$- ! $+ $@ $>96 $2 < @ $1 .UUCP > resolve uucp names
+R$+ . $- ! $+ $@ $>96 $3 < @ $1 . $2 > domain uucps
+R$+ ! $+ $@ $>96 $2 < @ $1 .UUCP > uucp subdomains
+')
+ifdef(`_USE_DECNET_SYNTAX_',
+`# convert node::user addresses into a domain-based address
+R$- :: $+ $@ $>96 $2 < @ $1 .DECNET > resolve DECnet names
+R$- . $- :: $+ $@ $>96 $3 < @ $1.$2 .DECNET > numeric DECnet addr
+',
+ `dnl')
+# 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$* @ $* $@ $>96 $1 < @ $2 > Insert < > and finish
+
+# else we must be a local name
+R$* $@ $>96 $1
+
+
+################################################
+### Ruleset 96 -- bottom half of ruleset 3 ###
+################################################
+
+S96
+
+# 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')
+R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d]
+R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal
+R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr
+
+# look up domains in the domain table
+ifdef(`DOMAIN_TABLE', `', `#')dnl
+R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3
+
+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
+R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3')
+')
+ifdef(`_NO_CANONIFY_', `dnl',
+`# pass to name server to make hostname canonical
+R$* < @ $* $~P > $* $: $1 < @ $[ $2 $3 $] > $4')
+
+# local host aliases and pseudo-domains are always canonical
+R$* < @ $=w > $* $: $1 < @ $2 . > $3
+R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4
+R$* < @ $* . . > $* $1 < @ $2 . > $3
+
+# 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$* <@> $@ handle <> and list:;
+
+# strip trailing dot off possibly canonical name
+R$* < @ $+ . > $* $1 < @ $2 > $3
+
+# eliminate internal code -- should never get this far!
+R$* < @ *LOCAL* > $* $1 < @ $j > $2
+
+# 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')
+
+ifdef(`_USE_DECNET_SYNTAX_',
+`# put DECnet back in :: form
+R$+ @ $+ . DECNET $2 :: $1 u@h.DECNET => h::u',
+ `dnl')
+# delete duplicate local names
+R$+ % $=w @ $=w $1 @ $j u%host@host => u@host
+
+
+
+##############################################################
+### Ruleset 97 -- recanonicalize and call ruleset zero ###
+### (used for recursive calls) ###
+##############################################################
+
+S`'97
+R$* $: $>3 $1
+R$* $@ $>0 $1
+
+
+######################################
+### Ruleset 0 -- Parse Address ###
+######################################
+
+S0
+
+R<@> $#_LOCAL_ $: <@> special case error msgs
+R$* : $* ; <@> $#error $@ 5.1.3 $: "list:; syntax illegal for recipient addresses"
+R<@ $+> $#error $@ 5.1.1 $: "user address required"
+R$* <$* : $* > $* $#error $@ 5.1.1 $: "colon illegal in host name part"
+R$* < @ . > $* $#error $@ 5.1.2 $: "invalid host name"
+
+ifdef(`_MAILER_smtp_',
+`# handle numeric address spec
+R$* < @ [ $+ ] > $* $: $>98 $1 < @ [ $2 ] > $3 numeric internet spec
+R$* < @ [ $+ ] > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 still numeric: send',
+ `dnl')
+
+# now delete the local info -- note $=O to find characters that cause forwarding
+R$* < @ > $* $@ $>97 $1 user@ => user
+R< @ $=w . > : $* $@ $>97 $2 @here:... -> ...
+R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here
+R$* $=O $* < @ $=w . > $@ $>97 $1 $2 $3 ...@here -> ...
+
+# handle local hacks
+R$* $: $>98 $1
+
+# short circuit local delivery so forwarded email works
+ifdef(`_MAILER_usenet_',
+`R$+ . USENET < @ $=w . > $#usenet $: $1 handle usenet specially',
+ `dnl')
+ifdef(`_STICKY_LOCAL_DOMAIN_',
+`R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub
+R< $+ > $+ < $+ > $>95 < $1 > $2 < $3 > yep ....
+R< > $+ + $* < $+ > $#_LOCAL_ $: $1 + $2 plussed name?
+R< > $+ < $+ > $#_LOCAL_ $: @ $1 nope, local address',
+`R$=L < @ $=w . > $#_LOCAL_ $: @ $1 special local names
+R$+ < @ $=w . > $#_LOCAL_ $: $1 regular local name')
+
+define(`X', ifdef(`MAILER_TABLE', `', `#'))dnl
+# not local -- try mailer table lookup
+X`'R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name
+X`'R< $+ . > $* $: < $1 > $2 strip trailing dot
+X`'R< $+ > $* $: < $(mailertable $1 $) > $2 lookup
+X`'R< error : $- $+ > $* $#error $@ $1 $: $2 check -- error?
+X`'R< $- : $+ > $* $# $1 $@ $2 $: $3 check -- resolved?
+X`'R< $+ > $* $: $>90 <$1> $2 try domain
+undefine(`X')dnl
+undivert(4)dnl
+
+ifdef(`_NO_UUCP_', `dnl',
+`# resolve remotely connected UUCP links (if any)
+ifdef(`_CLASS_V_',
+`R$* < @ $=V . UUCP . > $* $: $>95 < $V > $1 <@$2.UUCP.> $3',
+ `dnl')
+ifdef(`_CLASS_W_',
+`R$* < @ $=W . UUCP . > $* $: $>95 < $W > $1 <@$2.UUCP.> $3',
+ `dnl')
+ifdef(`_CLASS_X_',
+`R$* < @ $=X . UUCP . > $* $: $>95 < $X > $1 <@$2.UUCP.> $3',
+ `dnl')')
+
+# resolve fake top level domains by forwarding to other hosts
+ifdef(`BITNET_RELAY',
+`R$*<@$+.BITNET.>$* $: $>95 < $B > $1 <@$2.BITNET.> $3 user@host.BITNET',
+ `dnl')
+ifdef(`DECNET_RELAY',
+`R$*<@$+.DECNET.>$* $: $>95 < $C > $1 <@$2.DECNET.> $3 user@host.DECNET',
+ `dnl')
+ifdef(`_MAILER_pop_',
+`R$+ < @ POP. > $#pop $: $1 user@POP',
+ `dnl')
+ifdef(`_MAILER_fax_',
+`R$+ < @ $+ .FAX. > $#fax $@ $2 $: $1 user@host.FAX',
+`ifdef(`FAX_RELAY',
+`R$*<@$+.FAX.>$* $: $>95 < $F > $1 <@$2.FAX.> $3 user@host.FAX',
+ `dnl')')
+
+ifdef(`UUCP_RELAY',
+`# forward non-local UUCP traffic to our UUCP relay
+R$*<@$*.UUCP.>$* $: $>95 < $Y > $1 <@$2.UUCP.> $3 uucp mail',
+`ifdef(`_MAILER_uucp_',
+`# forward other UUCP traffic straight to UUCP
+R$* < @ $+ .UUCP. > $* $#_UUCP_ $@ $2 $: $1 < @ $2 .UUCP. > $3 user@host.UUCP',
+ `dnl')')
+ifdef(`_MAILER_usenet_', `
+# addresses sent to net.group.USENET will get forwarded to a newsgroup
+R$+ . USENET $#usenet $: $1',
+ `dnl')
+
+ifdef(`_LOCAL_RULES_',
+`# figure out what should stay in our local mail system
+undivert(1)', `dnl')
+
+# pass names that still have a host to a smarthost (if defined)
+R$* < @ $* > $* $: $>95 < $S > $1 < @ $2 > $3 glue on smarthost name
+
+# deal with other remote names
+ifdef(`_MAILER_smtp_',
+`R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain',
+`R$* < @$* > $* $#error $@ 5.1.2 $: Unrecognized host name $2')
+
+# if this is quoted, strip the quotes and try again
+R$+ $: $(dequote $1 $) strip quotes
+R$+ $=O $+ $@ $>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 ###
+###########################################################################
+
+S5
+
+# deal with plussed users so aliases work nicely
+R$+ + * $#_LOCAL_ $@ $&h $: $1
+R$+ + $* $#_LOCAL_ $@ $2 $: $1 + *
+
+# prepend an empty "forward host" on the front
+R$+ $: <> $1
+
+define(`X', ifdef(`LUSER_RELAY', `', `#'))dnl
+# send unrecognized local users to a relay host
+X`'R< > $+ + $* $: < $L . > $( user $1 $) + $2
+X`'R< > $+ $: < $L . > $( user $1 $) look up user
+X`'R< $* > $+ <> $* $: < > $2 $3 found; strip $L
+X`'R< $* . > $+ $: < $1 > $2 strip extra dot
+undefine(`X')dnl
+
+# handle plussed local names
+R< > $+ + $* $#_LOCAL_ $@ $2 $: $1
+
+# see if we have a relay or a hub
+R< > $+ $: < $H > $1 try hub
+R< > $+ $: < $R > $1 try relay
+R< > $+ $@ $1 nope, give up
+R< $- : $+ > $+ $: $>95 < $1 : $2 > $3 < @ $2 >
+R< $+ > $+ $@ $>95 < $1 > $2 < @ $1 >
+
+###################################################################
+### Ruleset 90 -- try domain part of mailertable entry ###
+###################################################################
+
+define(`X', ifdef(`MAILER_TABLE', `', `#'))dnl
+X`'S90
+X`'R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
+X`'R$* <$- : $+ > $* $# $2 $@ $3 $: $4 check -- resolved?
+X`'R$* < . $+ > $* $@ $>90 $1 . <$2> $3 no -- strip & try again
+X`'R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "."
+X`'R<$- : $+ > $* $# $1 $@ $2 $: $3 "." found?
+X`'R< $* > $* $@ $2 no mailertable match
+undefine(`X')dnl
+
+###################################################################
+### Ruleset 95 -- canonify mailer:host syntax to triple ###
+###################################################################
+
+S95
+R< > $* $@ $1 strip off null relay
+R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer
+R< $=w > $* $@ $2 delete local host
+R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer
+
+###################################################################
+### Ruleset 93 -- convert header names to masqueraded form ###
+###################################################################
+
+S93
+R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed
+R$=E < @ $=M . > $@ $1 < @ $2 . >
+ifdef(`_LIMITED_MASQUERADE_', `#')dnl
+R$=E < @ $=w . > $@ $1 < @ $2 . >
+R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms
+ifdef(`_LIMITED_MASQUERADE_', `#')dnl
+R$* < @ $=w . > $* $: $1 < @ $2 . @ $M > $3
+R$* < @ *LOCAL* > $* $: $1 < @ $j . @ $M > $2
+R$* < @ $+ @ > $* $@ $1 < @ $2 > $3 $M is null
+R$* < @ $+ @ $+ > $* $@ $1 < @ $3 . > $4 $M is not null
+
+###################################################################
+### Ruleset 94 -- convert envelope names to masqueraded form ###
+###################################################################
+
+S94
+ifdef(`_MASQUERADE_ENVELOPE_', `', `#')dnl
+R$+ $@ $>93 $1
+ifdef(`_MASQUERADE_ENVELOPE_', `#', `')dnl
+R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2
+
+###################################################################
+### Ruleset 98 -- local part of ruleset zero (can be null) ###
+###################################################################
+
+S98
+undivert(3)dnl
+#
+######################################################################
+######################################################################
+#####
+`##### MAILER DEFINITIONS'
+#####
+######################################################################
+######################################################################
+undivert(7)dnl
diff --git a/usr.sbin/sendmail/cf/m4/version.m4 b/usr.sbin/sendmail/cf/m4/version.m4
new file mode 100644
index 000000000000..d057c1a56899
--- /dev/null
+++ b/usr.sbin/sendmail/cf/m4/version.m4
@@ -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.
+#
+VERSIONID(`@(#)version.m4 8.7.2.2 (Berkeley) 11/20/95')
+#
+divert(0)
+# Configuration version number
+DZ8.7.2`'ifdef(`confCF_VERSION', `/confCF_VERSION')
diff --git a/usr.sbin/sendmail/cf/mailer/cyrus.m4 b/usr.sbin/sendmail/cf/mailer/cyrus.m4
new file mode 100644
index 000000000000..f5311371b536
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/cyrus.m4
@@ -0,0 +1,44 @@
+PUSHDIVERT(-1)
+#
+# (C) Copyright 1995 by Carnegie Mellon University
+#
+# All Rights Reserved
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of CMU not be
+# used in advertising or publicity pertaining to distribution of the
+# software without specific, written prior permission.
+#
+# CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+# CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+# SOFTWARE.
+#
+# Contributed to Berkeley by John Gardiner Myers <jgm+@CMU.EDU>.
+#
+
+ifdef(`CYRUS_MAILER_FLAGS',, `define(`CYRUS_MAILER_FLAGS', `A5@')')
+ifdef(`CYRUS_MAILER_PATH',, `define(`CYRUS_MAILER_PATH', /usr/cyrus/bin/deliver)')
+ifdef(`CYRUS_MAILER_ARGS',, `define(`CYRUS_MAILER_ARGS', `deliver -e -m $h -- $u')')
+ifdef(`CYRUS_BB_MAILER_FLAGS',, `define(`CYRUS_BB_MAILER_FLAGS', `')')
+ifdef(`CYRUS_BB_MAILER_ARGS',, `define(`CYRUS_BB_MAILER_ARGS', `deliver -e -m $u')')
+
+POPDIVERT
+
+##################################################
+### Cyrus Mailer specification ###
+##################################################
+
+VERSIONID(`@(#)cyrus.m4 8.2 (Carnegie Mellon) 9/12/95')
+
+Mcyrus, P=CYRUS_MAILER_PATH, F=CONCAT(`lsDFMnP', CYRUS_MAILER_FLAGS), S=10, R=20/40, T=X-Unix,
+ ifdef(`CYRUS_MAILER_MAX', `M=CYRUS_MAILER_MAX, ')A=CYRUS_MAILER_ARGS
+
+Mcyrusbb, P=CYRUS_MAILER_PATH, F=CONCAT(`lsDFMnP', CYRUS_MAILER_FLAGS), S=10, R=20/40, T=X-Unix,
+ ifdef(`CYRUS_MAILER_MAX', `M=CYRUS_MAILER_MAX, ')A=CYRUS_BB_MAILER_ARGS
diff --git a/usr.sbin/sendmail/cf/mailer/fax.m4 b/usr.sbin/sendmail/cf/mailer/fax.m4
new file mode 100644
index 000000000000..777fe01cf36a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/fax.m4
@@ -0,0 +1,53 @@
+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)')
+ifdef(`FAX_MAILER_MAX',,
+ `define(`FAX_MAILER_MAX', 100000)')
+POPDIVERT
+####################################
+### FAX Mailer specification ###
+####################################
+
+VERSIONID(`@(#)fax.m4 8.4 (Berkeley) 10/10/95')
+
+Mfax, P=FAX_MAILER_PATH, F=DFMhu, S=14, R=24, M=FAX_MAILER_MAX, T=X-Phone/X-FAX/X-Unix,
+ A=mailfax $u $h $f
+
+LOCAL_CONFIG
+CPFAX
diff --git a/usr.sbin/sendmail/cf/mailer/local.m4 b/usr.sbin/sendmail/cf/mailer/local.m4
new file mode 100644
index 000000000000..124cbba75282
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/local.m4
@@ -0,0 +1,94 @@
+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', `rmn')')
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/mail)')
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -d $u')')
+ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', `eu')')
+ifdef(`LOCAL_SHELL_PATH',, `define(`LOCAL_SHELL_PATH', /bin/sh)')
+ifdef(`LOCAL_SHELL_ARGS',, `define(`LOCAL_SHELL_ARGS', `sh -c $u')')
+ifdef(`LOCAL_SHELL_DIR',, `define(`LOCAL_SHELL_DIR', `$z:/')')
+POPDIVERT
+
+##################################################
+### Local and Program Mailer specification ###
+##################################################
+
+VERSIONID(`@(#)local.m4 8.21 (Berkeley) 11/6/95')
+
+Mlocal, P=LOCAL_MAILER_PATH, F=CONCAT(`lsDFMAw5:/|@', LOCAL_MAILER_FLAGS), S=10/30, R=20/40,
+ _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')_OPTINS(`LOCAL_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/X-Unix,
+ A=LOCAL_MAILER_ARGS
+Mprog, P=LOCAL_SHELL_PATH, F=CONCAT(`lsDFMo', LOCAL_SHELL_FLAGS), S=10/30, R=20/40, D=LOCAL_SHELL_DIR,
+ _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')T=X-Unix,
+ A=LOCAL_SHELL_ARGS
+
+#
+# Envelope sender rewriting
+#
+S10
+R<@> $n errors to mailer-daemon
+R$+ $: $>50 $1 add local domain if needed
+R$* $: $>94 $1 do masquerading
+
+#
+# Envelope recipient rewriting
+#
+S20
+R$+ < @ $* > $: $1 strip host part
+
+#
+# Header sender rewriting
+#
+S30
+R<@> $n errors to mailer-daemon
+R$+ $: $>50 $1 add local domain if needed
+R$* $: $>93 $1 do masquerading
+
+#
+# Header recipient rewriting
+#
+S40
+R$+ $: $>50 $1 add local domain if needed
+ifdef(`_ALL_MASQUERADE_', `', `#')dnl
+R$* $: $>93 $1 do all-masquerading
+
+#
+# Common code to add local domain name (only if always-add-domain)
+#
+S50
+ifdef(`_ALWAYS_ADD_DOMAIN_', `', `#')dnl
+R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified
+ifdef(`_ALWAYS_ADD_DOMAIN_', `', `#')dnl
+R$+ $@ $1 < @ *LOCAL* > add local qualification
diff --git a/usr.sbin/sendmail/cf/mailer/mail11.m4 b/usr.sbin/sendmail/cf/mailer/mail11.m4
new file mode 100644
index 000000000000..21e05dd19fd8
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/mail11.m4
@@ -0,0 +1,50 @@
+PUSHDIVERT(-1)
+#
+# Not exciting enough to bother with copyrights and most of the
+# rulesets are based from those provided by DEC.
+# Barb Dijker, Labyrinth Computer Services, barb@labyrinth.com
+#
+# This mailer is only useful if you have DECNET and the
+# mail11 program - gatekeeper.dec.com:/pub/DEC/gwtools.
+#
+# For local delivery of DECNET style addresses to the local
+# DECNET node, you will need feature(use_cw_file) and put
+# your DECNET nodename in in the cw file.
+#
+ifdef(`MAIL11_MAILER_PATH',, `define(`MAIL11_MAILER_PATH', /usr/etc/mail11)')
+ifdef(`MAIL11_MAILER_FLAGS',, `define(`MAIL11_MAILER_FLAGS', nsFx)')
+ifdef(`MAIL11_MAILER_ARGS',, `define(`MAIL11_MAILER_ARGS', mail11 $g $x $h $u)')
+define(`_USE_DECNET_SYNTAX_')
+
+POPDIVERT
+
+PUSHDIVERT(3)
+# DECNET delivery
+R$* < @ $=w .DECNET. > $#local $: $1 local DECnet
+R$+ < @ $+ .DECNET. > $#mail11 $@ $2 $: $1 DECnet user
+POPDIVERT
+
+PUSHDIVERT(6)
+CPDECNET
+POPDIVERT
+
+###########################################
+### UTK-MAIL11 Mailer specification ###
+###########################################
+
+VERSIONID(`@(#)mail11.m4 8.1 (Berkeley) 5/23/95')
+
+Mmail11, P=MAIL11_MAILER_PATH, F=MAIL11_MAILER_FLAGS, S=15, R=25,
+ A=MAIL11_MAILER_ARGS
+
+S15
+R$+ $: $>25 $1 preprocess
+R$w :: $+ $@ $w :: $1 ready to go
+
+S25
+R$+ < @ $- .UUCP > $: $2 ! $1 back to old style
+R$+ < @ $- .DECNET > $: $2 :: $1 convert to DECnet style
+R$+ < @ $- .LOCAL > $: $2 :: $1 convert to DECnet style
+R$+ < @ $=w. > $: $2 :: $1 convert to DECnet style
+R$=w :: $+ $2 strip local names
+R$+ :: $+ $@ $1 :: $2 already qualified
diff --git a/usr.sbin/sendmail/cf/mailer/phquery.m4 b/usr.sbin/sendmail/cf/mailer/phquery.m4
new file mode 100644
index 000000000000..ee359e09e532
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/phquery.m4
@@ -0,0 +1,51 @@
+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.
+#
+# Contributed by Kimmo Suominen <kim@tac.nyc.ny.us>.
+#
+
+ifdef(`PH_MAILER_PATH',, `define(`PH_MAILER_PATH', /usr/local/etc/phquery)')
+ifdef(`PH_MAILER_FLAGS',, `define(`PH_MAILER_FLAGS', `ehmu')')
+ifdef(`PH_MAILER_ARGS',, `define(`PH_MAILER_ARGS', `phquery -- $u')')
+
+POPDIVERT
+
+####################################
+### PH Mailer specification ###
+####################################
+
+VERSIONID(`@(#)phquery.m4 8.1 (Berkeley) 8/1/95')
+
+Mph, P=PH_MAILER_PATH, F=CONCAT(`nrDFM', PH_MAILER_FLAGS), S=10, R=20/40,
+ A=PH_MAILER_ARGS
diff --git a/usr.sbin/sendmail/cf/mailer/pop.m4 b/usr.sbin/sendmail/cf/mailer/pop.m4
new file mode 100644
index 000000000000..210a3c83a6fc
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/pop.m4
@@ -0,0 +1,53 @@
+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(`POP_MAILER_PATH',, `define(`POP_MAILER_PATH', /usr/lib/mh/spop)')
+ifdef(`POP_MAILER_FLAGS',, `define(`POP_MAILER_FLAGS', `Penu')')
+ifdef(`POP_MAILER_ARGS',, `define(`POP_MAILER_ARGS', `pop $u')')
+
+POPDIVERT
+
+####################################
+### POP Mailer specification ###
+####################################
+
+VERSIONID(`@(#)pop.m4 8.5 (Berkeley) 4/23/95')
+
+Mpop, P=POP_MAILER_PATH, F=CONCAT(`lsDFM', POP_MAILER_FLAGS), S=10, R=20/40, T=DNS/RFC822/X-Unix,
+ A=POP_MAILER_ARGS
+
+LOCAL_CONFIG
+# POP mailer is a pseudo-domain
+CPPOP
diff --git a/usr.sbin/sendmail/cf/mailer/procmail.m4 b/usr.sbin/sendmail/cf/mailer/procmail.m4
new file mode 100644
index 000000000000..d1293b9ceff6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/procmail.m4
@@ -0,0 +1,52 @@
+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(`PROCMAIL_PATH',,
+ `define(`PROCMAIL_PATH', /usr/local/bin/procmail)')
+ifdef(`PROCMAIL_MAILER_FLAGS',,
+ `define(`PROCMAIL_MAILER_FLAGS', `Shu')')
+ifdef(`PROCMAIL_MAILER_ARGS',,
+ `define(`PROCMAIL_MAILER_ARGS', `procmail -m $h $f $u')')
+
+POPDIVERT
+
+######################*****##############
+### PROCMAIL Mailer specification ###
+##################*****##################
+
+VERSIONID(`@(#)procmail.m4 8.4 (Berkeley) 4/23/95')
+
+Mprocmail, P=PROCMAIL_PATH, F=CONCAT(`DFMm', PROCMAIL_MAILER_FLAGS), S=11/31, R=21/31, T=DNS/RFC822/X-Unix,
+ ifdef(`PROCMAIL_MAILER_MAX', `M=PROCMAIL_MAILER_MAX, ')A=PROCMAIL_MAILER_ARGS
diff --git a/usr.sbin/sendmail/cf/mailer/smtp.m4 b/usr.sbin/sendmail/cf/mailer/smtp.m4
new file mode 100644
index 000000000000..6b59574e61e4
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/smtp.m4
@@ -0,0 +1,135 @@
+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(`SMTP_MAILER_ARGS',, `define(`SMTP_MAILER_ARGS', `IPC $h')')
+ifdef(`ESMTP_MAILER_ARGS',, `define(`ESMTP_MAILER_ARGS', `IPC $h')')
+ifdef(`SMTP8_MAILER_ARGS',, `define(`SMTP8_MAILER_ARGS', `IPC $h')')
+ifdef(`RELAY_MAILER_ARGS',, `define(`RELAY_MAILER_ARGS', `IPC $h')')
+ifdef(`_MAILER_uucp_',
+ `errprint(`*** MAILER(smtp) must appear before MAILER(uucp)')')dnl
+POPDIVERT
+#####################################
+### SMTP Mailer specification ###
+#####################################
+
+VERSIONID(`@(#)smtp.m4 8.32 (Berkeley) 11/20/95')
+
+Msmtp, P=[IPC], F=CONCAT(mDFMuX, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), E=\r\n, L=990,
+ _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,
+ A=SMTP_MAILER_ARGS
+Mesmtp, P=[IPC], F=CONCAT(mDFMuXa, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), E=\r\n, L=990,
+ _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,
+ A=ESMTP_MAILER_ARGS
+Msmtp8, P=[IPC], F=CONCAT(mDFMuX8, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), E=\r\n, L=990,
+ _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,
+ A=SMTP8_MAILER_ARGS
+Mrelay, P=[IPC], F=CONCAT(mDFMuXa8, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `61/71', `61'), E=\r\n, L=2040,
+ _OPTINS(`RELAY_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,
+ A=RELAY_MAILER_ARGS
+
+#
+# envelope sender rewriting
+#
+S11
+R$+ $: $>51 $1 sender/recipient common
+R$* :; <@> $@ list:; special case
+R$* $: $>61 $1 qualify unqual'ed names
+R$+ $: $>94 $1 do masquerading
+
+
+#
+# envelope recipient rewriting --
+# also header recipient if not masquerading recipients
+#
+S21
+R$+ $: $>51 $1 sender/recipient common
+R$+ $: $>61 $1 qualify unqual'ed names
+
+
+#
+# header sender and masquerading header recipient rewriting
+#
+S31
+R$+ $: $>51 $1 sender/recipient common
+R:; <@> $@ list:; special case
+
+# do special header rewriting
+R$* <@> $* $@ $1 <@> $2 pass null host through
+R< @ $* > $* $@ < @ $1 > $2 pass route-addr through
+R$* $: $>61 $1 qualify unqual'ed names
+R$+ $: $>93 $1 do masquerading
+
+
+#
+# convert pseudo-domain addresses to real domain addresses
+#
+S51
+
+# 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
+R$+.BITNET <@ $+:$+ > $: $1 .BITNET < @ $3 > strip mailer: part',
+ `dnl')
+ifdef(`_NO_UUCP_', `dnl', `
+# do UUCP heuristics; note that these are shared with UUCP mailers
+R$+ < @ $+ .UUCP. > $: < $2 ! > $1 convert to UUCP form
+R$+ < @ $* > $* $@ $1 < @ $2 > $3 not UUCP form
+
+# leave these in .UUCP form to avoid further tampering
+R< $&h ! > $- ! $+ $@ $2 < @ $1 .UUCP. >
+R< $&h ! > $-.$+ ! $+ $@ $3 < @ $1.$2 >
+R< $&h ! > $+ $@ $1 < @ $&h .UUCP. >
+R< $+ ! > $+ $: $1 ! $2 < @ *LOCAL* >')
+
+
+#
+# common sender and masquerading recipient rewriting
+#
+S61
+
+R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified
+R$+ $@ $1 < @ *LOCAL* > add local qualification
+
+
+#
+# relay mailer header masquerading recipient rewriting
+#
+S71
+
+R$+ $: $>61 $1
+R$+ $: $>93 $1
diff --git a/usr.sbin/sendmail/cf/mailer/usenet.m4 b/usr.sbin/sendmail/cf/mailer/usenet.m4
new file mode 100644
index 000000000000..2abf3b072dba
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/usenet.m4
@@ -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.
+#
+# 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', `inews -m -h -n')')
+POPDIVERT
+####################################
+### USENET Mailer specification ###
+####################################
+
+VERSIONID(`@(#)usenet.m4 8.5 (Berkeley) 4/26/95')
+
+Musenet, P=USENET_MAILER_PATH, F=USENET_MAILER_FLAGS, S=10, R=20,
+ _OPTINS(`USENET_MAILER_MAX', `M=', `, ')T=X-Usenet/X-Usenet/X-Unix,
+ A=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
index 000000000000..0b6594971d03
--- /dev/null
+++ b/usr.sbin/sendmail/cf/mailer/uucp.m4
@@ -0,0 +1,174 @@
+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_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gC $h!rmail ($u)')')
+ifdef(`UUCP_MAILER_FLAGS',, `define(`UUCP_MAILER_FLAGS', `')')
+ifdef(`UUCP_MAILER_MAX',,
+ `define(`UUCP_MAILER_MAX',
+ `ifdef(`UUCP_MAX_SIZE', `UUCP_MAX_SIZE', 100000)')')
+POPDIVERT
+#####################################
+### UUCP Mailer specification ###
+#####################################
+
+VERSIONID(`@(#)uucp.m4 8.24 (Berkeley) 9/5/95')
+
+#
+# There are innumerable variations on the UUCP mailer. It really
+# is rather absurd.
+#
+
+# old UUCP mailer (two names)
+Muucp, P=UUCP_MAILER_PATH, F=CONCAT(DFMhuUd, UUCP_MAILER_FLAGS), S=12, R=22/42, M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS
+Muucp-old, P=UUCP_MAILER_PATH, F=CONCAT(DFMhuUd, UUCP_MAILER_FLAGS), S=12, R=22/42, M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS
+
+# smart UUCP mailer (handles multiple addresses) (two names)
+Msuucp, P=UUCP_MAILER_PATH, F=CONCAT(mDFMhuUd, UUCP_MAILER_FLAGS), S=12, R=22/42, M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS
+Muucp-new, P=UUCP_MAILER_PATH, F=CONCAT(mDFMhuUd, UUCP_MAILER_FLAGS), S=12, R=22/42, M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS
+
+ifdef(`_MAILER_smtp_',
+`# domain-ized UUCP mailer
+Muucp-dom, P=UUCP_MAILER_PATH, F=CONCAT(mDFMhud, UUCP_MAILER_FLAGS), S=52/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS
+
+# domain-ized UUCP mailer with UUCP-style sender envelope
+Muucp-uudom, P=UUCP_MAILER_PATH, F=CONCAT(mDFMhud, UUCP_MAILER_FLAGS), S=72/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), M=UUCP_MAILER_MAX,
+ _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix,
+ A=UUCP_MAILER_ARGS')
+
+
+#
+# envelope and header sender rewriting
+#
+S12
+
+# handle error address as a special case
+R<@> $n errors to mailer-daemon
+
+# list:; syntax should disappear
+R:; <@> $@
+
+R$* < @ $* . > $* $1 < @ $2 > $3 strip trailing dots
+R$* < @ $=w > $1 strip local name
+R<@ $- . UUCP > : $+ $1 ! $2 convert to UUCP format
+R<@ $+ > : $+ $1 ! $2 convert to UUCP format
+R$* < @ $- . UUCP > $2 ! $1 convert to UUCP format
+R$* < @ $+ > $2 ! $1 convert to UUCP format
+R$&h ! $+ ! $+ $@ $1 ! $2 $h!...!user => ...!user
+R$&h ! $+ $@ $&h ! $1 $h!user => $h!user
+R$+ $: $U ! $1 prepend our name
+R! $+ $: $k ! $1 in case $U undefined
+
+#
+# envelope recipient rewriting
+#
+S22
+
+# list:; should disappear
+R:; <@> $@
+
+R$* < @ $* . > $* $1 < @ $2 > $3 strip trailing dots
+R$* < @ $j > $1 strip local name
+R<@ $- . UUCP > : $+ $1 ! $2 convert to UUCP format
+R<@ $+ > : $+ $1 ! $2 convert to UUCP format
+R$* < @ $- . UUCP > $2 ! $1 convert to UUCP format
+R$* < @ $+ > $2 ! $1 convert to UUCP format
+
+#
+# header recipient rewriting
+#
+S42
+
+# list:; syntax should disappear
+R:; <@> $@
+
+R$* < @ $* . > $* $1 < @ $2 > $3 strip trailing dots
+R$* < @ $j > $1 strip local name
+R<@ $- . UUCP > : $+ $1 ! $2 convert to UUCP format
+R<@ $+ > : $+ $1 ! $2 convert to UUCP format
+R$* < @ $- . UUCP > $2 ! $1 convert to UUCP format
+R$* < @ $+ > $2 ! $1 convert to UUCP format
+R$&h ! $+ ! $+ $@ $1 ! $2 $h!...!user => ...!user
+R$&h ! $+ $@ $&h ! $1 $h!user => $h!user
+R$+ $: $U ! $1 prepend our name
+R! $+ $: $k ! $1 in case $U undefined
+
+
+ifdef(`_MAILER_smtp_',
+`#
+# envelope sender rewriting for uucp-dom mailer
+#
+S52
+
+# handle error address as a special case
+R<@> $n errors to mailer-daemon
+
+# pass everything to standard SMTP mailer rewriting
+R$* $@ $>11 $1
+
+#
+# envelope sender rewriting for uucp-uudom mailer
+#
+S72
+
+# handle error address as a special case
+R<@> $n errors to mailer-daemon
+
+# do standard SMTP mailer rewriting
+R$* $: $>11 $1
+
+R$* < @ $* . > $* $1 < @ $2 > $3 strip trailing dots
+R<@ $- . UUCP > : $+ $@ $1 ! $2 convert to UUCP format
+R<@ $+ > : $+ $@ $1 ! $2 convert to UUCP format
+R$* < @ $- . UUCP > $@ $2 ! $1 convert to UUCP format
+R$* < @ $+ > $@ $2 ! $1 convert to UUCP format')
+
+
+PUSHDIVERT(4)
+# resolve locally connected UUCP links
+R$* < @ $=Z . UUCP. > $* $#uucp-uudom $@ $2 $: $1 < @ $2 .UUCP. > $3
+R$* < @ $=Y . UUCP. > $* $#uucp-new $@ $2 $: $1 < @ $2 .UUCP. > $3
+R$* < @ $=U . UUCP. > $* $#uucp-old $@ $2 $: $1 < @ $2 .UUCP. > $3
+POPDIVERT
diff --git a/usr.sbin/sendmail/cf/ostype/aix3.m4 b/usr.sbin/sendmail/cf/ostype/aix3.m4
new file mode 100644
index 000000000000..19763422fe3c
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/aix3.m4
@@ -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(`@(#)aix3.m4 8.5 (Berkeley) 11/13/95')
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/bellmail)')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', mail $u)')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `mn')')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4 b/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4
new file mode 100644
index 000000000000..34b352104145
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4
@@ -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(`@(#)amdahl-uts.m4 8.2 (Berkeley) 11/13/95')
+divert(-1)
+
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /etc/mail/aliases)')
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /etc/mail/sendmail.hf)')
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `fSn')')
+define(`confCW_FILE', /etc/mail/sendmail.cw)
diff --git a/usr.sbin/sendmail/cf/ostype/aux.m4 b/usr.sbin/sendmail/cf/ostype/aux.m4
new file mode 100644
index 000000000000..3c60eb13a62a
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/aux.m4
@@ -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.
+#
+
+divert(0)
+VERSIONID(`@(#)aux.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
+ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', mn)')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -d -r $f $u')')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/bsd4.3.m4 b/usr.sbin/sendmail/cf/ostype/bsd4.3.m4
new file mode 100644
index 000000000000..546fd376c93c
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/bsd4.3.m4
@@ -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(`@(#)bsd4.3.m4 8.4 (Berkeley) 11/13/95')
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')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
index 000000000000..835e4d89c6c1
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/bsd4.4.m4
@@ -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.
+#
+#
+
+divert(0)
+VERSIONID(`@(#)bsd4.4.m4 8.4 (Berkeley) 11/13/95')
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /usr/share/misc/sendmail.hf)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /var/log/sendmail.st)')dnl
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)')dnl
+ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4 b/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4
new file mode 100644
index 000000000000..8bc3c218b41e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4
@@ -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(`@(#)bsdi1.0.m4 8.2 (Berkeley) 8/16/95')dnl
+include(_CF_DIR_`'ostype/bsd4.4.m4)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4 b/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4
new file mode 100644
index 000000000000..a98ddc0d45c6
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4
@@ -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(`@(#)bsdi2.0.m4 8.1 (Berkeley) 8/16/95')dnl
+include(_CF_DIR_`'ostype/bsd4.4.m4)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/dgux.m4 b/usr.sbin/sendmail/cf/ostype/dgux.m4
new file mode 100644
index 000000000000..e78ce3bca5aa
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/dgux.m4
@@ -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(`@(#)dgux.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', m)')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/domainos.m4 b/usr.sbin/sendmail/cf/ostype/domainos.m4
new file mode 100644
index 000000000000..65329f3e1728
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/domainos.m4
@@ -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.
+#
+
+divert(0)
+VERSIONID(`@(#)domainos.m4 8.2 (Berkeley) 11/13/95')
+divert(-1)
+
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')
diff --git a/usr.sbin/sendmail/cf/ostype/dynix3.2.m4 b/usr.sbin/sendmail/cf/ostype/dynix3.2.m4
new file mode 100644
index 000000000000..149f6ad3a6fc
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/dynix3.2.m4
@@ -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(`@(#)dynix3.2.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/hpux10.m4 b/usr.sbin/sendmail/cf/ostype/hpux10.m4
new file mode 100644
index 000000000000..7c8ba4090dce
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/hpux10.m4
@@ -0,0 +1,51 @@
+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(`@(#)hpux10.m4 8.6 (Berkeley) 11/13/95')
+
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /var/spool/mqueue)')dnl
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /etc/mail/aliases)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /etc/mail/sendmail.st)')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /usr/share/lib/sendmail.hf)')dnl
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/bin/rmail)')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `m')')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `rmail -d $u')')dnl
+ifdef(`LOCAL_SHELL_PATH',, `define(`LOCAL_SHELL_PATH', /usr/bin/sh)')dnl
+ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gC $h!rmail ($u)')')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
+dnl
+dnl For maximum compability with HP-UX, use:
+dnl define(`confME_TOO', True)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/hpux9.m4 b/usr.sbin/sendmail/cf/ostype/hpux9.m4
new file mode 100644
index 000000000000..7a120052e424
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/hpux9.m4
@@ -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(`@(#)hpux9.m4 8.10 (Berkeley) 11/13/95')
+
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', `/bin/rmail')')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `m')')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `rmail -d $u')')dnl
+ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gC $h!rmail ($u)')')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
+dnl
+dnl For maximum compability with HP-UX, use:
+dnl define(`confME_TOO', True)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/irix4.m4 b/usr.sbin/sendmail/cf/ostype/irix4.m4
new file mode 100644
index 000000000000..e24b008823e4
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/irix4.m4
@@ -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(`@(#)irix4.m4 8.5 (Berkeley) 11/13/95')
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', Ehm)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/irix5.m4 b/usr.sbin/sendmail/cf/ostype/irix5.m4
new file mode 100644
index 000000000000..79843da6dbeb
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/irix5.m4
@@ -0,0 +1,61 @@
+divert(-1)
+#
+# Copyright (c) 1995 Eric P. Allman
+# Copyright (c) 1988, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Contributed by Kari E. Hurtta <Kari.Hurtta@dionysos.fmi.fi>
+#
+# 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.
+#
+
+#
+# Notes:
+# - SGI's /etc/sendmail.cf defines also 'u' for local mailer flags -- you
+# perhaps don't want it.
+# - Perhaps is should also add define(`LOCAL_MAILER_CHARSET', iso-8859-1)
+# put some Asian sites may prefer otherwise -- or perhaps not.
+# - SGI's /etc/sendmail.cf seems use: A=mail -s -d $u
+# It seems work without that -s however.
+# - SGI's /etc/sendmail.cf set's default uid and gid to 998 (guest)
+# - In SGI seems that TZ variable is needed that correct time is marked to
+# syslog
+# - helpfile is in /etc/sendmail.hf in SGI's /etc/sendmail.cf
+#
+
+divert(0)
+VERSIONID(`@(#)irix5.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', Ehmu)')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -s -d $u')')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /var/spool/mqueue)')dnl
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /etc/aliases)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /var/sendmail.st)')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /etc/sendmail.hf)')dnl
+define(`confDEF_USER_ID', `998:998')dnl
+define(`confTIME_ZONE', USE_TZ)dnl
diff --git a/usr.sbin/sendmail/cf/ostype/isc4.1.m4 b/usr.sbin/sendmail/cf/ostype/isc4.1.m4
new file mode 100644
index 000000000000..258f5450bb93
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/isc4.1.m4
@@ -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(`@(#)isc4.1.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /usr/lib/sendmail.hf)')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `lmail -s $u')')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `humS')')dnl
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/lmail)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
+ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -gC $h!rmail ($u)')')dnl
+ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl
+define(`confTIME_ZONE', `USE_TZ')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/nextstep.m4 b/usr.sbin/sendmail/cf/ostype/nextstep.m4
new file mode 100644
index 000000000000..515757aaf82b
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/nextstep.m4
@@ -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(`@(#)nextstep.m4 8.5 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /etc/sendmail/aliases)')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /usr/lib/sendmail.hf)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /etc/sendmail/sendmail.st)')dnl
+ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `rmnP')')dnl
+ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', `euP')')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/osf1.m4 b/usr.sbin/sendmail/cf/ostype/osf1.m4
new file mode 100644
index 000000000000..107cd7507171
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/osf1.m4
@@ -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(`@(#)osf1.m4 8.3 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/adm/sendmail/aliases)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/adm/sendmail/sendmail.st)')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /usr/share/lib/sendmail.hf)')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/ptx2.m4 b/usr.sbin/sendmail/cf/ostype/ptx2.m4
new file mode 100644
index 000000000000..365d21a1bbdd
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/ptx2.m4
@@ -0,0 +1,45 @@
+divert(-1)
+#
+# Copyright (c) 1994 Eric P. Allman
+# Copyright (c) 1994
+# 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.
+#
+
+# Support for DYNIX/ptx 2.x.
+
+divert(0)
+VERSIONID(`@(#)ptx2.m4 8.1 (Berkeley) 12/4/94')
+ifdef(`ALIAS_FILE',,`define(`ALIAS_FILE', /usr/lib/aliases)')dnl
+ifdef(`HELP_FILE',,`define(`HELP_FILE', /usr/lib/sendmail.hf)')dnl
+ifdef(`STATUS_FILE',,`define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
+define(`LOCAL_MAILER_PATH', `/bin/mail')dnl
+define(`LOCAL_MAILER_FLAGS', `rmn')dnl
+define(`LOCAL_SHELL_FLAGS', `e')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
index 000000000000..7e8f382d0e0e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/riscos4.5.m4
@@ -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.
+#
+
+divert(0)
+VERSIONID(`@(#)riscos4.5.m4 8.3 (Berkeley) 11/13/95')
+
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `rmail -d $u')')dnl
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', `/usr/lib/aliases')')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', `/usr/spool/mqueue')')dnl
+ifdef(`HELP_FILE',, `define(`HELP_FILE', `/usr/lib/sendmail.hf')')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/sco3.2.m4 b/usr.sbin/sendmail/cf/ostype/sco3.2.m4
new file mode 100644
index 000000000000..06fc050197c3
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/sco3.2.m4
@@ -0,0 +1,45 @@
+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(`@(#)sco3.2.m4 8.2 (Berkeley) 11/13/95')
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /usr/lib/mail/aliases)')dnl
+ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /usr/lib/sendmail.st)')dnl
+ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl
+ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/bin/lmail)')dnl
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', PuhCE)')dnl
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `lmail $u')')dnl
+ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', Peu)')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/solaris2.m4 b/usr.sbin/sendmail/cf/ostype/solaris2.m4
new file mode 100644
index 000000000000..9a7b0703ecbb
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/solaris2.m4
@@ -0,0 +1,45 @@
+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(`@(#)solaris2.m4 8.6 (Berkeley) 11/13/95')
+divert(-1)
+
+ifdef(`ALIAS_FILE',, `define(`ALIAS_FILE', /etc/mail/aliases)')
+ifdef(`HELP_FILE',, `define(`HELP_FILE', /etc/mail/sendmail.hf)')
+ifdef(`STATUS_FILE',, `define(`STATUS_FILE', /etc/mail/sendmail.st)')
+ifdef(`LOCAL_MAILER_FLAGS',, `define(`LOCAL_MAILER_FLAGS', `SnE')')
+ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -f $g -d $u')')
+define(`confCW_FILE', /etc/mail/sendmail.cw)
diff --git a/usr.sbin/sendmail/cf/ostype/svr4.m4 b/usr.sbin/sendmail/cf/ostype/svr4.m4
new file mode 100644
index 000000000000..ae18c1038b7e
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/svr4.m4
@@ -0,0 +1,45 @@
+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(`@(#)svr4.m4 8.2 (Berkeley) 5/26/95')
+
+ifdef(`ALIAS_FILE',,`define(`ALIAS_FILE', /usr/ucblib/aliases)')dnl
+ifdef(`HELP_FILE',,`define(`HELP_FILE', /usr/ucblib/sendmail.hf)')dnl
+ifdef(`STATUS_FILE',,`define(`STATUS_FILE', /usr/ucblib/sendmail.st)')dnl
+define(`LOCAL_MAILER_PATH', `/usr/ucblib/binmail')dnl
+define(`LOCAL_MAILER_FLAGS', `rmn')dnl
+define(`LOCAL_SHELL_FLAGS', `ehuP')dnl
+define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl
diff --git a/usr.sbin/sendmail/cf/ostype/ultrix4.m4 b/usr.sbin/sendmail/cf/ostype/ultrix4.m4
new file mode 100644
index 000000000000..f6998e1c5cab
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/ultrix4.m4
@@ -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(`@(#)ultrix4.m4 8.2 (Berkeley) 7/2/94')
diff --git a/usr.sbin/sendmail/cf/ostype/unknown.m4 b/usr.sbin/sendmail/cf/ostype/unknown.m4
new file mode 100644
index 000000000000..7aadbb505d4b
--- /dev/null
+++ b/usr.sbin/sendmail/cf/ostype/unknown.m4
@@ -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(`@(#)unknown.m4 8.1 (Berkeley) 4/21/95')
+errprint(`*** ERROR: You have not specified a valid operating system type.')
+errprint(` Use the OSTYPE macro to select a valid system type. This')
+errprint(` is necessary in order to get the proper pathnames and flags')
+errprint(` appropriate for your environment.')
diff --git a/usr.sbin/sendmail/cf/sh/makeinfo.sh b/usr.sbin/sendmail/cf/sh/makeinfo.sh
new file mode 100644
index 000000000000..68b85d30c6a2
--- /dev/null
+++ b/usr.sbin/sendmail/cf/sh/makeinfo.sh
@@ -0,0 +1,79 @@
+#!/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.6 (Berkeley) 8/6/95
+#
+
+usewhoami=0
+usehostname=0
+for p in `echo $PATH | sed 's/:/ /g'`
+do
+ if [ "x$p" = "x" ]
+ then
+ p="."
+ fi
+ if [ -f $p/whoami ]
+ then
+ usewhoami=1
+ if [ $usehostname -ne 0 ]
+ then
+ break;
+ fi
+ fi
+ if [ -f $p/hostname ]
+ then
+ usehostname=1
+ if [ $usewhoami -ne 0 ]
+ then
+ break;
+ fi
+ fi
+done
+if [ $usewhoami -ne 0 ]
+then
+ user=`whoami`
+else
+ user=$LOGNAME
+fi
+
+if [ $usehostname -ne 0 ]
+then
+ host=`hostname`
+else
+ host=`uname -n`
+fi
+echo '#####' built by $user@$host on `date`
+echo '#####' in `pwd` | sed 's/\/tmp_mnt//'
+echo '#####' using $1 as configuration include directory | sed 's/\/tmp_mnt//'
+echo "define(\`__HOST__', $host)dnl"
diff --git a/usr.sbin/sendmail/contrib/bitdomain.c b/usr.sbin/sendmail/contrib/bitdomain.c
new file mode 100644
index 000000000000..52d6d2187c3f
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/bitdomain.c
@@ -0,0 +1,409 @@
+/*
+ * By John G. Myers, jgm+@cmu.edu
+ * Version 1.2
+ *
+ * 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 || !strchr(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 || !strchr(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/bsdi.mc b/usr.sbin/sendmail/contrib/bsdi.mc
new file mode 100644
index 000000000000..231a7bc77ac6
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/bsdi.mc
@@ -0,0 +1,191 @@
+Return-Path: sanders@austin.BSDI.COM
+Received: from hofmann.CS.Berkeley.EDU (hofmann.CS.Berkeley.EDU [128.32.34.35]) by orodruin.CS.Berkeley.EDU (8.6.9/8.7.0.Beta0) with ESMTP id KAA28278 for <eric@orodruin.CS.Berkeley.EDU>; Sat, 10 Dec 1994 10:49:08 -0800
+Received: from austin.BSDI.COM (austin.BSDI.COM [137.39.95.2]) by hofmann.CS.Berkeley.EDU (8.6.9/8.6.6.Beta11) with ESMTP id KAA09482 for <eric@cs.berkeley.edu>; Sat, 10 Dec 1994 10:49:03 -0800
+Received: from austin.BSDI.COM (sanders@localhost [127.0.0.1]) by austin.BSDI.COM (8.6.9/8.6.9) with ESMTP id MAA14919 for <eric@cs.berkeley.edu>; Sat, 10 Dec 1994 12:49:01 -0600
+Message-Id: <199412101849.MAA14919@austin.BSDI.COM>
+To: Eric Allman <eric@cs.berkeley.edu>
+Subject: Re: sorting mailings lists with fastest delivery users first
+In-reply-to: Your message of Sat, 10 Dec 1994 08:25:30 PST.
+References: <199412101625.IAA15407@mastodon.CS.Berkeley.EDU>
+From: Tony Sanders <sanders@bsdi.com>
+Organization: Berkeley Software Design, Inc.
+Date: Sat, 10 Dec 1994 12:49:00 -0600
+Sender: sanders@austin.BSDI.COM
+
+(some random text deleted)
+
+I'll send you something else I've hacked up. You are free to use this
+or do with it as you like (I hereby make all my parts public domain).
+It's a sample .mc file that has comments (mostly taken from the README)
+and examples describing most of the common things people need to setup.
+
+#
+# /usr/share/sendmail/cf/sample.mc
+#
+# Do not edit /etc/sendmail.cf directly unless you cannot do what you
+# want in the master config file (/usr/share/sendmail/cf/sample.mc).
+# To create /etc/sendmail.cf from the master:
+# cd /usr/share/sendmail/cf
+# mv /etc/sendmail.cf /etc/sendmail.cf.save
+# m4 < sample.mc > /etc/sendmail.cf
+#
+# Then kill and restart sendmail:
+# sh -c 'set `cat /var/run/sendmail.pid`; kill $1; shift; eval "$@"'
+#
+# See /usr/share/sendmail/README for help in building a configuration file.
+#
+include(`../m4/cf.m4')
+VERSIONID(`@(#)$Id$')
+
+dnl # Specify your OS type below
+OSTYPE(`bsd4.4')
+
+dnl # NOTE: `dnl' is the m4 command for delete-to-newline; these are
+dnl # used to prevent those lines from appearing in the sendmail.cf.
+dnl #
+dnl # UUCP-only sites should configure FEATURE(`nodns') and SMART_HOST.
+dnl # The uucp-dom mailer requires MAILER(smtp). For more info, see
+dnl # `UUCP Config' at the end of this file.
+
+dnl # If you are not running DNS at all, it is important to use
+dnl # FEATURE(nodns) to avoid having sendmail queue everything
+dnl # waiting for the name server to come up.
+dnl # Example:
+dnl FEATURE(`nodns')
+
+dnl # Use FEATURE(`nocanonify') to skip address canonification via $[ ... $].
+dnl # This would generally only be used by sites that only act as mail gateways
+dnl # or which have user agents that do full canonification themselves.
+dnl # You may also want to use:
+dnl # define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')
+dnl # to turn off the usual resolver options that do a similar thing.
+dnl # Examples:
+dnl FEATURE(`nocanonify')
+dnl define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')
+
+dnl # If /bin/hostname is not set to the FQDN (Full Qualified Domain Name;
+dnl # for example, foo.bar.com) *and* you are not running a nameserver
+dnl # (that is, you do not have an /etc/resolv.conf and are not running
+dnl # named) *and* the canonical name for your machine in /etc/hosts
+dnl # (the canonical name is the first name listed for a given IP Address)
+dnl # is not the FQDN version then define NEED_DOMAIN and specify your
+dnl # domain using `DD' (for example, if your hostname is `foo.bar.com'
+dnl # then use DDbar.com). If in doubt, just define it anyway; doesn't hurt.
+dnl # Examples:
+dnl define(`NEED_DOMAIN', `1')
+dnl DDyour.site.domain
+
+dnl # Define SMART_HOST if you want all outgoing mail to go to a central
+dnl # site. SMART_HOST applies to names qualified with non-local names.
+dnl # Example:
+dnl define(`SMART_HOST', `smtp:firewall.bar.com')
+
+dnl # Define MAIL_HUB if you want all incoming mail sent to a
+dnl # centralized hub, as for a shared /var/spool/mail scheme.
+dnl # MAIL_HUB applies to names qualified with the name of the
+dnl # local host (e.g., "eric@foo.bar.com").
+dnl # Example:
+dnl define(`MAIL_HUB', `smtp:mailhub.bar.com')
+
+dnl # LOCAL_RELAY is a site that will handle unqualified names, this is
+dnl # basically for site/company/department wide alias forwarding. By
+dnl # default mail is delivered on the local host.
+dnl # Example:
+dnl define(`LOCAL_RELAY', `smtp:mailgate.bar.com')
+
+dnl # Relay hosts for fake domains: .UUCP .BITNET .CSNET
+dnl # Examples:
+dnl define(`UUCP_RELAY', `mailer:your_relay_host')
+dnl define(`BITNET_RELAY', `mailer:your_relay_host')
+dnl define(`CSNET_RELAY', `mailer:your_relay_host')
+
+dnl # Define `MASQUERADE_AS' is used to hide behind a gateway.
+dnl # add any accounts you wish to be exposed (i.e., not hidden) to the
+dnl # `EXPOSED_USER' list.
+dnl # Example:
+dnl MASQUERADE_AS(`some.other.host')
+
+dnl # If masquerading, EXPOSED_USER defines the list of accounts
+dnl # that retain the local hostname in their address.
+dnl # Example:
+dnl EXPOSED_USER(`postmaster hostmaster webmaster')
+
+dnl # If masquerading is enabled (using MASQUERADE_AS above) then
+dnl # FEATURE(allmasquerade) will cause recipient addresses to
+dnl # masquerade as being from the masquerade host instead of
+dnl # getting the local hostname. Although this may be right for
+dnl # ordinary users, it breaks local aliases that aren't exposed
+dnl # using EXPOSED_USER.
+dnl # Example:
+dnl FEATURE(allmasquerade)
+
+dnl # Include any required mailers
+MAILER(local)
+MAILER(smtp)
+MAILER(uucp)
+
+LOCAL_CONFIG
+# If this machine should be accepting mail as local for other hostnames
+# that are MXed to this hostname then add those hostnames below using
+# a line like:
+# Cw bar.com
+# The most common case where you need this is if this machine is supposed
+# to be accepting mail for the domain. That is, if this machine is
+# foo.bar.com and you have an MX record in the DNS that looks like:
+# bar.com. IN MX 0 foo.bar.com.
+# Then you will need to add `Cw bar.com' to the config file for foo.bar.com.
+# DO NOT add Cw entries for hosts whom you simply store and forward mail
+# for or else it will attempt local delivery. So just because bubba.bar.com
+# is MXed to your machine you should not add a `Cw bubba.bar.com' entry
+# unless you want local delivery and your machine is the highest-priority
+# MX entry (that is is has the lowest preference value in the DNS.
+
+LOCAL_RULE_0
+# `LOCAL_RULE_0' can be used to introduce alternate delivery rules.
+# For example, let's say you accept mail via an MX record for widgets.com
+# (don't forget to add widgets.com to your Cw list, as above).
+#
+# If wigets.com only has an AOL address (widgetsinc) then you could use:
+# R$+ <@ widgets.com.> $#smtp $@aol.com. $:widgetsinc<@aol.com.>
+#
+# Or, if widgets.com was connected to you via UUCP as the UUCP host
+# widgets you might have:
+# R$+ <@ widgets.com.> $#uucp $@widgets $:$1<@widgets.com.>
+
+dnl ###
+dnl ### UUCP Config
+dnl ###
+
+dnl # `SITECONFIG(site_config_file, name_of_site, connection)'
+dnl # site_config_file the name of a file in the cf/siteconfig
+dnl # directory (less the `.m4')
+dnl # name_of_site the actual name of your UUCP site
+dnl # connection one of U, W, X, or Y; where U means the sites listed
+dnl # in the config file are connected locally; W, X, and Y
+dnl # build remote UUCP hub classes ($=W, etc).
+dnl # You will need to create the specific site_config_file in
+dnl # /usr/share/sendmail/siteconfig/site_config_file.m4
+dnl # The site_config_file contains a list of directly connected UUCP hosts,
+dnl # e.g., if you only connect to UUCP site gargoyle then you could just:
+dnl # echo 'SITE(gargoyle)' > /usr/share/sendmail/siteconfig/uucp.foobar.m4
+dnl # Example:
+dnl SITECONFIG(`uucp.foobar', `foobar', U)
+
+dnl # If you are on a local SMTP-based net that connects to the outside
+dnl # world via UUCP, you can use LOCAL_NET_CONFIG to add appropriate rules.
+dnl # For example:
+dnl # define(`SMART_HOST', suucp:uunet)
+dnl # LOCAL_NET_CONFIG
+dnl # R$* < @ $* .$m. > $* $#smtp $@ $2.$m. $: $1 < @ $2.$m. > $3
+dnl # This will cause all names that end in your domain name ($m) to be sent
+dnl # via SMTP; anything else will be sent via suucp (smart UUCP) to uunet.
+dnl # If you have FEATURE(nocanonify), you may need to omit the dots after
+dnl # the $m.
+dnl #
+dnl # If you are running a local DNS inside your domain which is not
+dnl # otherwise connected to the outside world, you probably want to use:
+dnl # define(`SMART_HOST', smtp:fire.wall.com)
+dnl # LOCAL_NET_CONFIG
+dnl # R$* < @ $* . > $* $#smtp $@ $2. $: $1 < @ $2. > $3
+dnl # That is, send directly only to things you found in your DNS lookup;
+dnl # anything else goes through SMART_HOST.
diff --git a/usr.sbin/sendmail/contrib/expn.pl b/usr.sbin/sendmail/contrib/expn.pl
new file mode 100755
index 000000000000..270f483bc6f3
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/expn.pl
@@ -0,0 +1,1367 @@
+#!/usr/bin/perl
+'di ';
+'ds 00 \\"';
+'ig 00 ';
+#
+# THIS PROGRAM IS ITS OWN MANUAL PAGE. INSTALL IN man & bin.
+#
+
+# hardcoded constants, should work fine for BSD-based systems
+require 'sys/socket.ph';
+$sockaddr = 'S n a4 x8';
+
+# system requirements:
+# must have 'nslookup' and 'hostname' programs.
+
+# $Header: /home/muir/bin/RCS/expn,v 3.9 1995/10/02 17:51:35 muir Exp muir $
+
+# TODO:
+# less magic should apply to command-line addresses
+# less magic should apply to local addresses
+# add magic to deal with cross-domain cnames
+
+# Checklist: (hard addresses)
+# 250 Kimmo Suominen <"|/usr/local/mh/lib/slocal -user kim"@grendel.tac.nyc.ny.us>
+# harry@hofmann.cs.Berkeley.EDU -> harry@tenet (.berkeley.edu) [dead]
+# bks@cs.berkeley.edu -> shiva.CS (.berkeley.edu) [dead]
+# 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 accounting 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;
+$ENV{'PATH'} .= ":/usr/etc" unless $ENV{'PATH'} =~ m,/usr/etc,;
+$ENV{'PATH'} .= ":/usr/ucb" unless $ENV{'PATH'} =~ m,/usr/ucb,;
+select(STDERR);
+
+$0 = "$av0 - running hostname";
+chop($name = `hostname || uname -n`);
+
+$0 = "$av0 - lookup host FQDN and IP addr";
+($hostname,$aliases,$type,$len,$thisaddr) = gethostbyname($name);
+
+$0 = "$av0 - parsing args";
+$usage = "Usage: $av0 [-1avwd] user[\@host] [user2[host2] ...]";
+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));
+}
+$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+/;
+$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";
+ &alarm("greeting with $server",'');
+ while(<S>) {
+ alarm(0);
+ print if $watch;
+ if (/^(\d+)([- ])/) {
+ if ($1 != 220) {
+ $0 = "$av0 - bad numeric response from $server";
+ &alarm("giving up after bad response from $server",'');
+ &read_response($2,$watch);
+ alarm(0);
+ 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 response 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;
+ }
+ &alarm("greeting with $server",'');
+ }
+ alarm(0);
+
+ # if this causes problems, remove it
+ $0 = "$av0 - sending helo to $server";
+ &alarm("sending helo to $server","");
+ &ps("helo $hostname");
+ while(<S>) {
+ print if $watch;
+ last if /^\d+ /;
+ }
+ alarm(0);
+
+ # 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 = ();
+ }
+
+# ($ecode,@expansion) = &expn_vrfy($u,$server);
+ (@foo) = &expn_vrfy($u,$server);
+ ($ecode,@expansion) = @foo;
+ if ($ecode) {
+ &giveup('',$ecode,$u);
+ last USER;
+ }
+
+ for $s (@expansion) {
+ $s =~ s/[\n\r]//g;
+ $0 = "$av0 - parsing $server: $s";
+
+ $skipwatch = $watch;
+
+ if ($s =~ /^[25]51([- ]).*<(.+)>/) {
+ print "$s" if $watch;
+ print "(pretending 250$1<$2>)" if ($debug && $watch);
+ print "\n" if $watch;
+ $s = "250$1<$2>";
+ $skipwatch = 0;
+ }
+
+ if ($s =~ /^250([- ])(.+)/) {
+ print "$s\n" if $skipwatch;
+ ($done,$addr) = ($1,$2);
+ ($newhost, $newaddr, $newname) = &parse($addr,$server,$oldname, $#expansion == 0);
+ 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 responses
+ # 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;
+ }
+ # 553 is a known code...
+ if ($s =~ /^(553)([- ])/) {
+ if ($valid) {
+ print STDERR "\@$server:$u ($oldname) USER AMBIGUOUS\n";
+ } else {
+ &verbose(&final($u,$server,$oldname,"USER AMBIGUOUS"));
+ }
+ last if ($2 eq " ");
+ next;
+ }
+ # 252 is a known code...
+ if ($s =~ /^(252)([- ])/) {
+ if ($valid) {
+ print STDERR "\@$server:$u ($oldname) REFUSED TO VRFY\n";
+ } else {
+ &verbose(&final($u,$server,$oldname,"REFUSED TO VRFY"));
+ }
+ last if ($2 eq " ");
+ next;
+ }
+ &giveup('',"$server: did not grok '$s'",$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));
+ }
+ }
+ }
+
+ &alarm("sending 'quit' to $server",'');
+ $0 = "$av0 - sending 'quit' to $server";
+ &ps("quit");
+ while(<S>) {
+ print if $watch;
+ last if /^\d+ /;
+ }
+ close(S);
+ alarm(0);
+}
+
+$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);
+ local($pk,$file,$line);
+ ($pk, $file, $line) = caller;
+
+ $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 at $file:$line!!! 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
+ # Nested 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;
+}
+# Some systems use expn and vrfy interchangeably. Some only
+# implement one or the other. Some check expn against mailing
+# lists and vrfy against users. It doesn't appear to be
+# consistent.
+#
+# So, what do we do? We try everything!
+#
+#
+# Ranking of result codes: good: 250, 251/551, 252, 550, anything else
+#
+# Ranking of inputs: best: user@host.domain, okay: user
+#
+# Return value: $error_string, @responses_from_server
+sub expn_vrfy
+{
+ local($u,$server) = @_;
+ local(@c) = ('expn', 'vrfy');
+ local(@try_u) = $u;
+ local(@ret,$code);
+
+ if (($u =~ /(.+)@(.+)/) && (&trhost($2) eq &trhost($server))) {
+ push(@try_u,$1);
+ }
+
+ TRY:
+ for $c (@c) {
+ for $try_u (@try_u) {
+ &alarm("${c}'ing $try_u on $server",'',$u);
+ &ps("$c $try_u");
+ alarm(0);
+ $s = <S>;
+ if ($s eq '') {
+ return "$server: lost connection";
+ }
+ if ($s !~ /^(\d+)([- ])/) {
+ return "$server: garbled reply to '$c $try_u'";
+ }
+ if ($1 == 250) {
+ $code = 250;
+ @ret = ("",$s);
+ push(@ret,&read_response($2,$debug));
+ return (@ret);
+ }
+ if ($1 == 551 || $1 == 251) {
+ $code = $1;
+ @ret = ("",$s);
+ push(@ret,&read_response($2,$debug));
+ next;
+ }
+ if ($1 == 252 && ($code == 0 || $code == 550)) {
+ $code = 252;
+ @ret = ("",$s);
+ push(@ret,&read_response($2,$watch));
+ next;
+ }
+ if ($1 == 550 && $code == 0) {
+ $code = 550;
+ @ret = ("",$s);
+ push(@ret,&read_response($2,$watch));
+ next;
+ }
+ &read_response($2,$watch);
+ }
+ }
+ return "$server: expn/vrfy not implemented" unless @ret;
+ return @ret;
+}
+# sometimes the old parse routine (now parse2) didn't
+# reject funky addresses.
+sub parse
+{
+ local($oldaddr,$server,$oldname,$one_to_one) = @_;
+ local($newhost, $newaddr, $newname, $um) = &parse2($oldaddr,$server,$oldname,$one_to_one);
+ if ($newaddr =~ m,^["/],) {
+ return (undef, $oldaddr, $newname) if $valid;
+ return (undef, $um, $newname);
+ }
+ return ($newhost, $newaddr, $newname);
+}
+
+# returns ($new_smtp_server,$new_address,$new_name)
+# given a response 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 parse2
+{
+ local($newaddr,$context_host,$old_name,$parsing_args) = @_;
+ local(@names) = $old_name;
+ local($urx) = "[-A-Za-z_.0-9+]+";
+ local($unmangle);
+
+ #
+ # 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
+ #
+ $unmangle = $newaddr;
+ 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),$unmangle);
+ }
+ if ($newaddr =~ /^(.+)\@($urx)$/) {
+ print "(\@)" if $debug;
+ return (&domainify($2,$context_host,$newaddr),$newaddr,&firstname(@names),$unmangle);
+ }
+ if ($parsing_args) {
+ if ($newaddr =~ /^($urx)\!(.+)$/) {
+ return (&domainify($1,$context_host,$newaddr),$newaddr,&firstname(@names),$unmangle);
+ }
+ if ($newaddr =~ /^($urx)$/) {
+ return ($context_host,$newaddr,&firstname(@names),$unmangle);
+ }
+ print STDERR "Could not parse $newaddr\n";
+ }
+ print "(?)" if $debug;
+ return(undef,$newaddr,&firstname(@names),$unmangle);
+}
+# 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 fails, 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}) {
+ $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";
+}
+
+sub alarm
+{
+ local($alarm_action,$alarm_redirect,$alarm_user) = @_;
+ alarm(3600);
+ $SIG{ALRM} = 'handle_alarm';
+}
+# this involves one great big ugly hack.
+# the "next HOST" unwinds the stack!
+sub handle_alarm
+{
+ &giveup($alarm_redirect,"Timed out during $alarm_action",$alarm_user);
+ next HOST;
+}
+
+# read the rest of the current smtp daemon's response (and toss it away)
+sub read_response
+{
+ local($done,$watch) = @_;
+ local(@resp);
+ print $s if $watch;
+ while(($done eq "-") && ($s = <S>) && ($s =~ /^\d+([- ])/)) {
+ print $s if $watch;
+ $done = $1;
+ push(@resp,$s);
+ }
+ return @resp;
+}
+# 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;
+&handle_alarm;
+################### BEGIN PERL/TROFF TRANSITION
+.00 ;
+
+'di
+.nr nl 0-1
+.nr % 0
+.\\"'; __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 ]
+.RI [ -1 ]
+.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 at
+.IR ftp://ftp.idiom.com/pub/muir-programs/expn .
+.SH AUTHOR
+.I David Muir Sharnoff\ \ \ \ <muir@idiom.com>
diff --git a/usr.sbin/sendmail/contrib/mailprio b/usr.sbin/sendmail/contrib/mailprio
new file mode 100644
index 000000000000..cdbc3b06c264
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/mailprio
@@ -0,0 +1,297 @@
+Message-Id: <199412081919.NAA23234@austin.BSDI.COM>
+To: Eric Allman <eric@cs.berkeley.edu>
+Subject: Re: sorting mailings lists with fastest delivery users first
+In-reply-to: Your message of Thu, 08 Dec 1994 06:08:33 PST.
+References: <199412081408.GAA06210@mastodon.CS.Berkeley.EDU>
+From: Tony Sanders <sanders@bsdi.com>
+Organization: Berkeley Software Design, Inc.
+Date: Thu, 08 Dec 1994 13:19:39 -0600
+Sender: sanders@austin.BSDI.COM
+
+Eric Allman writes:
+> Nope, that's a new one, so far as I know. Any interest in
+> contributing it? For small lists it seems overkill, but for
+> large lists it could be a major win.
+
+Sure, I will contribute it; after I sent you mail last night I went ahead
+and finished up what I thought needed to be done. I would like to get
+some feedback from you on a few items, if you have time.
+
+There are two programs, mailprio_mkdb and mailprio (source below).
+
+mailprio_mkdb reads maillog files and creates a DB file of address vs.
+delay. I'm not too happy with how it does the averages right now but this
+is just a quick hack. However, it should at least order sites that take
+days vs. those that deliver on the first pass through. One thing that
+would make this information a lot more accurate is if sendmail could log
+a "transaction delay" (on failures also), as well as total delivery delay.
+Perhaps, as an option, it could maintain the DB file itself?
+
+mailprio then simply reads a list of addresses from stdin (the mailing
+list), and tries to prioritize them according to the info the database.
+It collects comment lines and other junk at the top of the file; all
+mailprio does is reorder lines, the actual text of the file should
+be unchanged to the extent that you can verify it with:
+ sort sorted_list > checkit; sort mailing-list | diff - checkit
+Users with no delay information are put next. The prioritized list is last.
+Of course, this function could also be built-into sendmail (eventually).
+
+Putting "new account" info at the top with the current averaging function
+probably adversly affects the prioritized list (at least in the short
+term), but putting it at the bottom would not really give the new accounts
+a fair chance. I suspect this isn't that big of a problem. I'm running
+this here on a list with 461 accounts and about 10 messages per day so
+I'll see how it goes. I'll keep some stats on delay times and see what
+happens.
+
+Another thing that would help this situation, is if sendmail had the queue
+ordered by site (but you already know this). If you ever get to do per
+site queuing you should consider "blocking" a queue for some short period
+of time if a connection fails to that site [sendmail does this inside a
+single process on a per account basis now right?]; this would allow multiple
+sendmails to quickly skip over those sites for people like me that run:
+
+ for i in 1 2 3 4 5 6 7 8 ; do daemon sendmail -q; done
+
+to flush a queue that has gotten behind. You could also do this inside
+sendmail with a parallelism option (when it is time to run the queue, how
+many processes to start).
+
+#! /bin/sh
+# This is a shell archive. Remove anything before this line, then unpack
+# it by saving it into a file and typing "sh file". To overwrite existing
+# files, type "sh file -c". You can also feed this as standard input via
+# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
+# will see the following message at the end:
+# "End of shell archive."
+# Contents: mailprio mailprio_mkdb
+# Wrapped by sanders@austin.BSDI.COM on Fri Dec 9 18:07:02 1994
+PATH=/bin:/usr/bin:/usr/ucb ; export PATH
+if test -f 'mailprio' -a "${1}" != "-c" ; then
+ echo shar: Will not clobber existing file \"'mailprio'\"
+else
+echo shar: Extracting \"'mailprio'\" \(3093 characters\)
+sed "s/^X//" >'mailprio' <<'END_OF_FILE'
+X#!/usr/bin/perl
+X#
+X# mailprio -- setup mail priorities for a mailing list
+X#
+X# Sort mailing list by mailprio database:
+X# mailprio < mailing-list > sorted_list
+X# Double check against orig:
+X# sort sorted_list > checkit; sort mailing-list | diff - checkit
+X# If it checks out, install it.
+X#
+X# TODO:
+X# option to process mqueue files so we can reorder files in the queue!
+X$usage = "Usage: mailprio [-p priodb]\n";
+X$home = "/home/sanders/lists";
+X$priodb = "$home/mailprio";
+X
+Xif ($main'ARGV[0] =~ /^-/) {
+X $args = shift;
+X if ($args =~ m/\?/) { print $usage; exit 0; }
+X if ($args =~ m/p/) {
+X $priodb = shift || die $usage, "-p requires argument\n"; }
+X}
+X
+X# In shell script, it goes something like this:
+X# old_mailprio > /tmp/a
+X# fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b
+X# ; /tmp/b contains list of known users, faster delivery first
+X# fgrep -v -f /tmp/b lists/inet-access > /tmp/c
+X# ; put all unknown stuff at the top of new list for now
+X# echo '# -----' >> /tmp/c
+X# cat /tmp/b >> /tmp/c
+X
+X# Setup %list and @list
+Xlocal($addr, $canon);
+Xwhile ($addr = <STDIN>) {
+X chop $addr;
+X next if $addr =~ /^# ----- /; # that's our line
+X push(@list, $addr), next if $addr =~ /^\s*#/; # save comments
+X $canon = &canonicalize((&simplify_address($addr))[0]);
+X unless (defined $canon) {
+X warn "no address found: $addr\n";
+X push(@list, $addr); # save it anyway
+X next;
+X }
+X if (defined $list{$canon}) {
+X warn "duplicate: ``$addr -> $canon''\n";
+X push(@list, $addr); # save it anyway
+X next;
+X }
+X $list{$canon} = $addr;
+X}
+X
+Xlocal(*prio);
+Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
+Xforeach $to (keys %list) {
+X if (defined $prio{$to}) {
+X # add to list of found users (%userprio) and remove from %list
+X # so that we know what users were not yet prioritized
+X $userprio{$to} = $prio{$to}; # priority
+X $useracct{$to} = $list{$to}; # string
+X delete $list{$to};
+X }
+X}
+Xdbmclose(%prio);
+X
+X# Put all the junk we found at the very top
+X# (this might not always be a feature)
+Xprint join("\n", @list), "\n";
+X
+X# unprioritized users go next, slow accounts will get moved down quickly
+Xprint '# ----- unprioritized users', "\n";
+Xforeach $to (keys %list) { print $list{$to}, "\n"; }
+X
+X# finally, our prioritized list of users
+Xprint '# ----- prioritized users', "\n";
+Xforeach $to (sort { $userprio{$a} <=> $userprio{$b}; } keys %userprio) {
+X die "Opps! Something is seriously wrong with useracct: $to\n"
+X unless defined $useracct{$to};
+X print $useracct{$to}, "\n";
+X}
+X
+Xexit(0);
+X
+X# REPL-LIB ---------------------------------------------------------------
+X
+Xsub canonicalize {
+X local($addr) = @_;
+X # lowercase, strip leading/trailing whitespace
+X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
+X}
+X
+X# @addrs = simplify_address($addr);
+Xsub simplify_address {
+X local($_) = shift;
+X 1 while s/\([^\(\)]*\)//g; # strip comments
+X 1 while s/"[^"]*"//g; # strip comments
+X split(/,/); # split into parts
+X foreach (@_) {
+X 1 while s/.*<(.*)>.*/\1/;
+X s/^\s+//;
+X s/\s+$//;
+X }
+X @_;
+X}
+END_OF_FILE
+if test 3093 -ne `wc -c <'mailprio'`; then
+ echo shar: \"'mailprio'\" unpacked with wrong size!
+fi
+chmod +x 'mailprio'
+# end of 'mailprio'
+fi
+if test -f 'mailprio_mkdb' -a "${1}" != "-c" ; then
+ echo shar: Will not clobber existing file \"'mailprio_mkdb'\"
+else
+echo shar: Extracting \"'mailprio_mkdb'\" \(3504 characters\)
+sed "s/^X//" >'mailprio_mkdb' <<'END_OF_FILE'
+X#!/usr/bin/perl
+X#
+X# mailprio_mkdb -- make mail priority database based on delay times
+X#
+X$usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n";
+X$home = "/home/sanders/lists";
+X$maillog = "/var/log/maillog";
+X$priodb = "$home/mailprio";
+X
+Xif ($main'ARGV[0] =~ /^-/) {
+X $args = shift;
+X if ($args =~ m/\?/) { print $usage; exit 0; }
+X if ($args =~ m/l/) {
+X $maillog = shift || die $usage, "-l requires argument\n"; }
+X if ($args =~ m/p/) {
+X $priodb = shift || die $usage, "-p requires argument\n"; }
+X}
+X
+Xlocal(*prio);
+X# We'll merge with existing information if it's already there.
+Xdbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n";
+X&getlog_stats($maillog, *prio);
+X# foreach $addr (sort { $prio{$a} <=> $prio{$b}; } keys %prio) {
+X# printf("%06d %s\n", $prio{$addr}, $addr); }
+Xdbmclose(%prio);
+Xexit(0);
+X
+Xsub getlog_stats {
+X local($maillog, *stats) = @_;
+X local($to, $delay);
+X local($h, $m, $s);
+X open(MAILLOG, "< $maillog") || die "$maillog: $!\n";
+X while (<MAILLOG>) {
+X ($delay) = (m/, delay=([^,]*), /);
+X $delay || next;
+X ($h, $m, $s) = split(/:/, $delay);
+X $delay = ($h * 60 * 60) + ($m * 60) + $s;
+X
+X # deleting everything after ", " seems safe enough, though
+X # it is possible that it was inside "..."'s and that we will
+X # miss some addresses because of it. However, I'm not willing
+X # to do full parsing just for that case. If this bothers you
+X # you could do something like: s/, (delay|ctladdr)=.*//;
+X # but you have to make sure you catch all the possible names.
+X $to = $_; $to =~ s/^.* to=//; $to =~ s/, .*//;
+X foreach $addr (&simplify_address($to)) {
+X next unless $addr;
+X $addr = &canonicalize($addr);
+X # print $delay, " ", $addr, "\n";
+X $stats{$addr} = $delay unless defined $stats{$addr}; # init
+X
+X # This average function moves the value around quite rapidly
+X # which may or may not be a feature.
+X #
+X # This has at least one odd behavior because we currently only
+X # use the delay information from maillog which is only logged
+X # on actual delivery. This works backwards from what we really
+X # want to happen when a fast host goes down for a while and then
+X # comes back up.
+X #
+X # I spoke with Eric and he suggested adding an xdelay statistic
+X # for a per transaction delay which would help that situation
+X # a lot. What I believe you want in that cases something like:
+X # delay fast, xdelay fast: smokin', these hosts go first
+X # delay slow, xdelay fast: put host high on the list (back up?)
+X # delay fast, xdelay slow: host is down/having problems/slow
+X # delay slow, xdelay slow: poorly connected sites, very last
+X # Of course, you have to reorder the distribution list fairly
+X # often for that to help. Come to think of it, you should
+X # also reorder /var/spool/mqueue files also (if they aren't
+X # locked of course). Hmmm....
+X $stats{$addr} = int(($stats{$addr} + $delay) / 2);
+X }
+X }
+X close(MAILLOG);
+X}
+X
+X# REPL-LIB ---------------------------------------------------------------
+X
+Xsub canonicalize {
+X local($addr) = @_;
+X # lowercase, strip leading/trailing whitespace
+X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr;
+X}
+X
+X# @addrs = simplify_address($addr);
+Xsub simplify_address {
+X local($_) = shift;
+X 1 while s/\([^\(\)]*\)//g; # strip comments
+X 1 while s/"[^"]*"//g; # strip comments
+X split(/,/); # split into parts
+X foreach (@_) {
+X 1 while s/.*<(.*)>.*/\1/;
+X s/^\s+//;
+X s/\s+$//;
+X }
+X @_;
+X}
+END_OF_FILE
+if test 3504 -ne `wc -c <'mailprio_mkdb'`; then
+ echo shar: \"'mailprio_mkdb'\" unpacked with wrong size!
+fi
+chmod +x 'mailprio_mkdb'
+# end of 'mailprio_mkdb'
+fi
+echo shar: End of shell archive.
+exit 0
diff --git a/usr.sbin/sendmail/contrib/rmail.oldsys.patch b/usr.sbin/sendmail/contrib/rmail.oldsys.patch
new file mode 100644
index 000000000000..856fcf1f93eb
--- /dev/null
+++ b/usr.sbin/sendmail/contrib/rmail.oldsys.patch
@@ -0,0 +1,108 @@
+From: Bill Gianopoulos <wag@sccux1.msd.ray.com>
+Message-Id: <199405191527.LAA03463@sccux1.msd.ray.com>
+Subject: Patch to rmail to elliminate need for snprintf
+To: sendmail@CS.Berkeley.EDU
+Date: Thu, 19 May 1994 11:27:16 -0400 (EDT)
+
+I have written the following patch to rmail which removes the requirement
+for snprintf while maintaining the protection from buffer overruns. It also
+fixes it to compile with compilers which don't understand ANSI function
+prototypes. Perhaps this should be included in the next version?
+
+*** rmail/rmail.c.orig Mon May 31 18:10:44 1993
+--- rmail/rmail.c Thu May 19 11:04:50 1994
+***************
+*** 78,86 ****
+--- 78,109 ----
+ #include <sysexits.h>
+ #include <unistd.h>
+
++ #ifdef __STDC__
+ void err __P((int, const char *, ...));
+ void usage __P((void));
++ #else
++ void err ();
++ void usage ();
++ #endif
+
++ #define strdup(s) strcpy(xalloc(strlen(s) + 1), s)
++
++ char *
++ xalloc(sz)
++ register int sz;
++ {
++ register char *p;
++
++ /* some systems can't handle size zero mallocs */
++ if (sz <= 0)
++ sz = 1;
++
++ p = malloc((unsigned) sz);
++ if (p == NULL)
++ err(EX_UNAVAILABLE, "Out of memory!!");
++ return (p);
++ }
++
+ int
+ main(argc, argv)
+ int argc;
+***************
+*** 230,250 ****
+ 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);
+--- 253,285 ----
+ args[i++] = "-oi"; /* Ignore '.' on a line by itself. */
+
+ if (from_sys != NULL) { /* Set sender's host name. */
+! if (strchr(from_sys, '.') == NULL) {
+! if ((strlen(from_sys) + strlen(domain) + 6)
+! > sizeof(buf))
+! err(EX_DATAERR, "sender hostname too long");
+! (void)sprintf(buf,
+ "-oMs%s.%s", from_sys, domain);
+! }
+! else {
+! if ((strlen(from_sys) + 5) > sizeof(buf))
+! err(EX_DATAERR ,"sender hostname too long");
+! (void)sprintf(buf, "-oMs%s", from_sys);
+! }
+ if ((args[i++] = strdup(buf)) == NULL)
+ err(EX_TEMPFAIL, NULL);
+ }
+ /* Set protocol used. */
+! if ((strlen(domain) + 5) > sizeof(buf))
+! err(EX_DATAERR, "protocol name too long");
+! (void)sprintf(buf, "-oMr%s", domain);
+ if ((args[i++] = strdup(buf)) == NULL)
+ err(EX_TEMPFAIL, NULL);
+
+ /* Set name of ``from'' person. */
+! if (((from_path ? strlen(from_path) : 0) + strlen(from_user) + 3)
+! > sizeof(buf))
+! err(EX_DATAERR, "from address too long");
+! (void)sprintf(buf, "-f%s%s",
+ from_path ? from_path : "", from_user);
+ if ((args[i++] = strdup(buf)) == NULL)
+ err(EX_TEMPFAIL, NULL);
+--
+William A. Gianopoulos; Raytheon Missile Systems Division
+wag@sccux1.msd.ray.com
diff --git a/usr.sbin/sendmail/doc/changes/changes.me b/usr.sbin/sendmail/doc/changes/changes.me
new file mode 100644
index 000000000000..ee838bd40d78
--- /dev/null
+++ b/usr.sbin/sendmail/doc/changes/changes.me
@@ -0,0 +1,997 @@
+.\" Copyright (c) 1994 Eric P. Allman
+.\" Copyright (c) 1988, 1994
+.\" 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.
+.\"
+.\" @(#)changes.me 8.2 (Berkeley) 5/3/95
+.\"
+.\" ditroff -me -Pxx changes.me
+.eh '%''Changes in Sendmail Version 8'
+.oh 'Changes in Sendmail Version 8''%'
+.nr si 3n
+.if n .ls 2
+.+c
+.(l C
+.sz 14
+Changes in Sendmail Version 8*
+.sz
+.sp
+Eric Allman
+.sp 0.5
+.i
+University of California, Berkeley
+Mammoth Project
+.)l
+.(f
+*An earlier version of this paper was printed in the
+Proceedings of the 1994 AUUG Queensland Summer Technical Conference,
+Gateway Hotel, Brisbane, March 1994.
+.)f
+.sp
+.(l F
+.ce
+ABSTRACT
+.sp \n(psu
+Version 8 of
+.i sendmail
+includes a number of major changes from previous versions.
+This paper gives a very short history of
+.i sendmail ,
+a summary of the major differences between version 5
+(the last publically available version)
+and version 8,
+and some discussion of future directions.
+.)l
+.sp 2
+.pp
+In 1987, the author stopped major work on
+.i sendmail
+due to other time committments,
+only to return to active work in 1991.
+This paper explores why work resumed
+and what changes have been made.
+.pp
+Section 1 gives a short history of
+.i sendmail
+through version 5 and the motivation behind working on version 8.
+Section 2 has
+a rather detailed description of what has changed
+between version 5 and version 8.
+The paper finishes off with some thoughts
+about what still needs to be done.
+.sh 1 "HISTORY"
+.pp
+As discussed elsewhere,
+[Allman83a, Allman83b, Allman&Amos85]
+sendmail has existed in various forms since 1980.
+It was released under the name
+.i delivermail
+in 4BSD and 4.1BSD, and as
+.i sendmail
+in 4.2BSD.
+.\"4.0BSD delivermail 1.10
+.\"4.1BSD delivermail 1.10
+.\"4.2BSD sendmail 4.12
+.\"4.3BSD sendmail 5.52
+It quickly became the dominant mail system for networked UNIX systems.
+.pp
+Prior the release of 4.3BSD in November 1986,
+the author had left the University for private industry,
+but continued to do some work on
+.i sendmail
+with activity slowly trailing off
+until effectively stopping after February 1987.
+There was minimal support done by many people for several years,
+until July of 1991 when the original author,
+who had returned the University,
+started active work on it again.
+.pp
+There were several reasons for renewed work on
+.i sendmail .
+There was a desire at Berkeley to convert to a subdomained structure
+so that individuals were identified by their subdomain
+rather than by their individual workstation;
+although possible in the old code, there were some problems,
+and the author was the obvious person to address them.
+The Computer Systems Research Group (CSRG),
+the group that produced the Berkeley Software Distributions,
+was working on 4.4BSD,
+and wanted an update to the mail system.
+Bryan Costales was working on a book on
+.i sendmail
+that was being reviewed by the author,
+which encouraged him to make some revisions.
+And the author wanted to try to unify some of the disparate versions of
+.i sendmail
+that had been permitted to proliferate.
+.pp
+During the 1987\-91 fallow period,
+many vendors and outside volunteers
+had produced variants of
+.i sendmail .
+Perhaps the best known is the IDA version
+[IDA87].
+Originally intended to be a new set of configuration files,
+IDA expanded into a fairly large set of patches for the code.
+Originally produced in Sweden,
+IDA development passed to the University of Illinois,
+and was widely used by the fairly large set of people
+who prefer to get and compile their own source code
+rather than use vendor-supplied binaries.
+.pp
+In about the same time frame,
+attempts were made to clean up and extend the Simple Mail Transport Protocol
+(SMTP)
+[RFC821].
+This involved clarifications of some ambiguities in the protocol,
+and correction of some problem areas
+[RFC1123],
+as well as extensions for additional functionality
+(dubbed Extended Simple Mail Transport Protocol, or ESMTP)
+[RFC1425, RFC1426, RFC1427]
+and a richer set of semantics in the body of messages
+(the Multipurpose Internet Mail Extensions, a.k.a. MIME)
+[RFC1521, RFC1344].
+Neither the IDA group nor most vendors
+were modifying
+.i sendmail
+to conform to these new standards.
+It seemed clear that these were ``good things''
+that should be encouraged.
+However, since no one was working on a publically available version of
+.i sendmail
+with these updates,
+they were unlikely to be widely deployed any time in the near future.
+.pp
+There are, of course, other mail transport agents available,
+such as
+.i MMDF
+.\"[ref],
+.i zmailer
+.\"[ref],
+.i smail
+.\"[ref],
+and
+.i PP
+.\"[ref].
+However, none of these seemed to be gaining the prominence of
+.i sendmail ;
+it appeared that most companies would not convert to another
+mail transport agent any time in the forseeable future.
+However, they might be persuaded to convert to a newer version of
+.i sendmail .
+.pp
+All of these convinced the author
+to work on a updated version of
+.i sendmail
+for public distribution.
+.pp
+The new version of
+.i sendmail
+is referred to as version eight (V8).
+Versions six and seven were skipped
+because of an agreement
+that all files in 4.4BSD would be numbered as
+.q 8.1 .
+Rather than have an external version number
+that differed from the file version numbers,
+.i sendmail
+just jumped directly to V8.
+.sh 1 "CHANGES IN VERSION EIGHT"
+.pp
+The following is a summary of the changes between the last commonly
+available version of sendmail from Berkeley (5.67) and the latest
+version (8.6.6).
+.pp
+Many of these are ideas that had been tried in IDA,
+but many of them were generalized in V8.
+.sh 2 "Performance Enhancements"
+.pp
+Instead of closing SMTP connections immediately, open connections are
+cached for possible future use. There is a limit to the number of
+simultaneous open connections and the idle time of any individual
+connection.
+.pp
+This is of best help during queue processing (since there is the
+potential of many different messages going to one site), although
+it can also help when processing MX records which aren't handled
+by MX Piggybacking.
+.pp
+If two hosts with different names in a single message happen to
+have the same set of MX hosts, they can be sent in the same
+transaction. Version 8 notices this and tries to batch the messages.
+.pp
+For example, if two sites ``foo.com'' and ``bar.com'' are both
+served by UUNET, they will have the same set of MX hosts and will
+be sent in one transaction. UUNET will then split the message
+and send it to the two individual hosts.
+.sh 2 "RFC 1123 Changes"
+.pp
+A number of changes have been made to make sendmail ``conditionally
+compliant'' (that is, it satisfies all of the MUST clauses and most
+but not all of the SHOULD clauses in RFC 1123).
+.pp
+The major areas of change are (numbers are RFC 1123 section numbers):
+.nr ii 0.75i
+.ip \(sc5.2.7
+Response to RCPT command is fast. Previously, sendmail
+expanded all aliases as far as it could \*- this could
+take a very long time, particularly if there were
+name server delays. Version 8 only checks for the
+existence of an alias and does the expansion later.
+It does still do a DNS lookup if there is an explicit host name
+in the RCPT command,
+but this time is bounded.
+.ip \(sc5.2.8
+Numeric IP addresses are logged in Received: lines.
+This helps tracing spoofed messages.
+.ip \(sc5.2.17
+Self domain literal is properly handled. Previously,
+if someone sent to user@[1.2.3.4], where 1.2.3.4 is
+your IP address, the mail would probably be rejected
+with a ``configuration error''.
+Version 8 can handle these addresses.
+.ip \(sc5.3.2
+Better control over individual timeouts. RFC 821 specified
+no timeouts. Older versions of sendmail had a single
+timeout, typically set to two hours. Version 8 allows
+the configuration file to set timeouts for various
+SMTP commands individually.
+.ip \(sc5.3.3
+Error messages are sent as From:<>. This was urged by
+RFC 821 and reiterated by RFC 1123, but older versions
+of sendmail never really did it properly. Version 8
+does. However, some systems cannot handle this
+perfectly legal address; if necessary, you can create
+a special mailer that uses the `g' flag to disable this.
+.ip \(sc5.3.3
+Error messages are never sent to <>. Previously,
+sendmail was happy to send responses-to-responses which
+sometimes resulted in responses-to-responses-to-responses
+which resulted in .... you get the idea.
+.ip \(sc5.3.3
+Route-addrs (the ugly ``<@hosta,@hostb:user@hostc>''
+syntax) are pruned. RFC 821 urged the use of this
+bletcherous syntax. RFC 1123 has seen the light and
+officially deprecates them, further urging that you
+eliminate all but ``user@hostc'' should you receive
+one of these things. Version 8 is slightly more generous
+than the standards suggest; instead of stripping off all
+the route addressees, it only strips hosts off up to
+the one before the last one known to DNS, thus allowing
+you to have pseudo-hosts such as foo.BITNET. The `R'
+option will turn this off.
+.lp
+The areas in which sendmail is not ``unconditionally compliant'' are:
+.ip \(sc5.2.6
+Sendmail does do header munging.
+.ip \(sc5.2.10
+Sendmail doesn't always use the exact SMTP message
+text from RFC 821. This is a rather silly requirement.
+.ip \(sc5.3.1.1
+Sendmail doesn't guarantee only one connect for each
+host on queue runs. Connection caching gives you most
+of this, but it does not provide a guarantee.
+.ip \(sc5.3.1.1
+Sendmail doesn't always provide an adequate limit
+on concurrency. That is, there can be several
+independent sendmails running at once. My feeling
+is that doing an absolute limit would be a mistake
+(it might result in lost mail). However, if you use
+the XLA contributed software, most of this will be
+guaranteed (but I don't guarantee the guarantee).
+.sh 2 "Extended SMTP Support
+.pp
+Version 8 includes both sending and receiving support for Extended
+SMTP support as defined by RFC 1425 (basic) and RFC 1427 (SIZE);
+and limited support for RFC 1426 (BODY).
+The body support is minimal because the
+.q 8BITMIME
+body type is not currently advertised.
+Although such a body type will be accepted,
+it will not be correctly converted to 7 bits
+if speaking to a non-8-bit-MIME aware SMTP server.
+.pp
+.i Sendmail
+tries to speak ESMTP if you have the `a' flag set
+in the flags for the mailer descriptor,
+or if the other end advertises the fact that it speaks ESMTP.
+This is a non-standard advertisement:
+.i sendmail
+announces
+.q "ESMTP spoken here"
+during the initial connection message,
+and client sendmails search for this message.
+This creates some problems for some PC-based mailers,
+which do not understand two-line greeting messages
+as required by RFC 821.
+.sh 2 "Eight-Bit Clean
+.pp
+Previous versions of sendmail used the 0200 bit for quoting. This
+version avoids that use.
+However, you can set option `7' to get seven bit stripping
+for compatibility with RFC 821,
+which is a 7-bit protocol.
+This option says ``strip to 7 bits on input''.
+.pp
+Individual mailers can still produce seven bit out put using the
+`7' mailer flag.
+This flag says ``strip to 7 bits on output''.
+.sh 2 "User Database"
+.pp
+The User Database (UDB) is an as-yet experimental attempt to provide
+unified large-site name support.
+We are installing it at Berkeley;
+future versions may show significant modifications.
+Briefly, UDB contains a database that is intended to contain
+all the per-user information for your workgroup,
+such as people's full names, their .plan information,
+their outgoing mail name, and their mail drop.
+.pp
+The user database allows you to map both incoming and outgoing
+addresses, much like IDA. However, the interface is still
+better with IDA;
+in particular, the alias file with incoming/outgoing marks
+provides better locality of information.
+.sh 2 "Improved BIND Support"
+.pp
+The BIND support, particularly for MX records, had a number of
+annoying ``features'' which have been removed in this release. In
+particular, these more tightly bind (pun intended) the name server
+to sendmail, so that the name server resolution rules are incorporated
+directly into sendmail.
+.pp
+The major change has been that the $[ ... $] operator didn't fully
+qualify names that were in DNS as A or MX records. Version 8 does
+this qualification.
+.pp
+This has proven to be an annoyance in Sun shops,
+who often still run without BIND support.
+However, it is really critical that this be supported,
+since MX records are mandatory.
+In SunOS you can choose either MX support or NIS support,
+but not both.
+This is fixed in Solaris,
+and some
+.i sendmail
+support to allow this in SunOS should be forthcoming in a future release.
+.sh 2 "Keyed Files"
+.pp
+Generalized keyed files is an idea taken directly from IDA sendmail
+(albeit with a completely different implementation).
+They can be useful on large sites.
+.pp
+Version 8 includes the following built-in map classes:
+.ip dbm
+Support for the ndbm(3) library.
+.ip hash
+Support for the ``Hash'' type from the new Berkeley db(3) library.
+this library provides substantially better database support
+than ndbm(3),
+including in-memory caching,
+arbitrarily long keys and values,
+and better disk utilization.
+.ip btree
+Support for the ``B-Tree'' type from the new Berkeley db(3) library.
+B-Trees provide better clustering than Hashed files
+if you are fetching lots of records that have similar keys,
+such as searching a dictionary for words beginning with ``detr''.
+.ip nis
+Support for NIS (a.k.a. YP) maps.
+NIS+ is not supported in this version.
+.ip host
+Support for DNS lookups.
+.ip dequote
+A ``pseudo-map'' (that is, once that does not have any external data)
+that allows a configuration file to break apart a quoted string
+in the address.
+This is necessary primarily for DECnet addresses,
+which often have quoted addresses that need to be unwrapped on gateways.
+.sh 2 "Multi-Word Classes & Macros in Classes"
+.pp
+Classes can now be multiple words. For example,
+.(b
+CShofmann.CS.Berkeley.EDU
+.)b
+allows you to match the entire string ``hofmann.CS.Berkeley.EDU''
+using the single construct ``$=S''.
+.pp
+Class definitions are now allowed to include macros \*- for example:
+.(b
+Cw$k
+.)b
+is legal.
+.sh 2 "IDENT Protocol Support"
+.pp
+The IDENT protocol as defined in RFC 1413 [RFC1413] is supported.
+However, many systems have a TCP/IP bug that renders this useless,
+and the feature must be turned off.
+Roughly, if one of these system receives a
+.q "No route to host"
+message (ICMP message ICMP_UNREACH_HOST) on
+.i any
+connection, all connections to that host are closed.
+Some firewalls return this error if you try to connect
+to the IDENT port,
+so you can't receive email from these hosts on these systems.
+It's possible that if the firewall used a more specific message
+(such as ICMP_UNREACH_PROTOCOL, ICMP_UNREACH_PORT or ICMP_UNREACH_NET_PROHIB)
+it would work, but this hasn't been verified.
+.pp
+IDENT protocol support cannot be used on
+4.3BSD,
+Apollo DomainOS,
+Apple A/UX,
+ConvexOS,
+Data General DG/UX,
+HP-UX,
+Sequent Dynix,
+or
+Ultrix 4.x, x \(<= 3.
+It seems to work on
+4.4BSD,
+IBM AIX 3.x,
+OSF/1,
+SGI IRIX,
+Solaris,
+SunOS,
+and Ultrix 4.4.
+.sh 2 "Separate Envelope/Header Processing
+.pp
+Since the From: line is passed in separately from the envelope
+sender, these have both been made visible; the $g macro is set to
+the envelope sender during processing of mailer argument vectors
+and the header sender during processing of headers.
+.pp
+It is also possible to specify separate per-mailer envelope and
+header processing. The SenderRWSet and RecipientRWset arguments
+for mailers can be specified as ``envelope/header'' to give different
+rewritings for envelope versus header addresses.
+.sh 2 "Owner-List Propagates to Envelope
+.pp
+When an alias has an associated owner-list name, that alias is used
+to change the envelope sender address. This will cause downstream
+errors to be returned to that owner.
+.pp
+Some people find this confusing
+because the envelope sender is what appears in the first
+``From_'' line in UNIX messages
+(that is, the line beginning ``From<space>''
+instead of ``From:'';
+the latter is the header from, which
+.i does
+indicate the sender of the message).
+In previous versions,
+.i sendmail
+has tried to avoid changing the envelope sender
+for back compatibility with UNIX convention;
+at this point that back compatibility is creating too many problems,
+and it is necessary to move forward into the 1980s.
+.sh 2 "Command Line Flags"
+.pp
+The
+.b \-B
+flag has been added to pass in body type information.
+.pp
+The
+.b \-p
+flag has been added to pass in protocol information
+that was previously passed in by defining the
+.b $r
+and
+.b $s
+macros.
+.pp
+The
+.b \-X
+flag has been added to allow logging of all protocol in and
+out of sendmail for debugging.
+You can set
+.q "\-X filename"
+and a complete transcript will be logged in that file.
+This gets big fast: the option is only for debugging.
+.pp
+The
+.b \-q
+flag can limit limit a queue run to specific recipients,
+senders, or queue ids using \-qRsubstring, \-qSsubstring, or
+\-qIsubstring respectively.
+.sh 2 "New Configuration Line Types
+.pp
+The `T' (Trusted users) configuration line has been deleted. It
+will still be accepted but will be ignored.
+.pp
+The `K' line has been added to declare database maps.
+.pp
+The `V' line has been added to declare the configuration version
+level.
+.pp
+The `M' (mailer) line takes a D= field to specify execution
+directory.
+.sh 2 "New and Extended Options"
+.pp
+Several new options have been added, many to support new features,
+others to allow tuning that was previously available only by
+recompiling. Briefly:
+.nr ii 0.5i
+.ip A
+The alias file specification can now be a list of alias files.
+Also, the configuration can specify a class of file.
+For example, to search the NIS aliases, use
+.q OAnis:mail.aliases .
+.ip b
+Insist on a minimum number of disk blocks.
+.ip C
+Delivery checkpoint interval. Checkpoint the queue (to avoid
+duplicate deliveries) every C addresses.
+.ip E
+Default error message. This message (or the contents of the
+indicated file) are prepended to error messages.
+.ip G
+Enable GECOS matching. If you can't find a local user name
+and this option is enabled, do a sequential scan of the passwd
+file to match against full names. Previously a compile option.
+.ip h
+Maximum hop count. Previously this was compiled in.
+.ip I
+This option has been extended to allow setting of resolver parameters.
+.ip j
+Send errors in MIME-encapsulated format.
+.ip J
+Forward file path. Where to search for .forward files \*- defaults
+to $HOME/.forward.
+.ip k
+Connection cache size. The total number of connections that will
+be kept open at any time.
+.ip K
+Connection cache lifetime. The amount of time any connection
+will be permitted to sit idle.
+.ip l
+Enable Errors-To: header. These headers violate RFC 1123;
+this option is included to provide back compatibility with
+old versions of sendmail.
+.ip O
+Incoming daemon options (e.g., use alternate SMTP port).
+.ip p
+Privacy options. These can be used to make your SMTP server
+less friendly.
+.ip r
+This option has been extended to allow finer grained control
+over timeouts.
+For example, you can set the timeout for SMTP commands individually.
+.ip R
+Don't prune route-addrs. Normally, if version 8 sees an address
+like "<@hostA,@hostB:user@hostC>, sendmail will try to strip off
+as much as it can (up to user@hostC) as suggested by RFC 1123.
+This option disables that behaviour.
+.ip T
+The
+.q "Return To Sender"
+timeout has been extended
+to allow specification of a warning message interval,
+typically something on the order of four hours.
+If a message cannot be delivered in that interval,
+a warning message is sent back to the sender
+but the message continues to be tried.
+.ip U
+User database spec. This is still experimental.
+.ip V
+Fallback ``MX'' host. This can be thought of as an MX host
+that applies to all addresses that has a very high preference
+value (that is, use it only if everything else fails).
+.ip w
+If set, assume that if you are the best MX host for a host,
+you should send directly to that host. This is intended
+for compatibility with UIUC sendmail, and may have some
+use on firewalls.
+.ip 7
+Do not run eight bit clean. Technically, you have to assert
+this option to be RFC 821 compatible.
+.sh 2 "New Mailer Definitions"
+.ip L=
+Set the allowable line length. In V5, the L mailer flag implied
+a line length limit of 990 characters; this is now settable to
+an arbitrary value.
+.ip F=a
+Try to use ESMTP. It will fall back to SMTP if the initial
+EHLO packet is rejected.
+.ip F=b
+Ensure a blank line at the end of messages. Useful on the
+*file* mailer.
+.ip F=c
+Strip all comments from addresses; this should only be used as
+a last resort when dealing with cranky mailers.
+.ip F=g
+Never use the null sender as the envelope sender, even when
+running SMTP. This violates RFC 1123.
+.ip F=7
+Strip all output to this mailer to 7 bits.
+.ip F=L
+Used to set the line limit to 990 bytes for SMTP compatibility.
+It now does that only if the L= keyletter is not specified.
+This flag is obsolete and should not be used.
+.sh 2 "New or Changed Pre-Defined Macros"
+.ip $k
+UUCP node name from uname(2).
+.ip $m
+Domain part of our full hostname.
+.ip $_
+RFC 1413-provided sender address.
+.ip $w
+Previously was sometimes the full domain name, sometimes
+just the first word. Now guaranteed to be the first word
+of the domain name (i.e., the host name).
+.ip $j
+Previously had to be defined \*- it is now predefined to be
+the full domain name, if that can be determined. That is,
+it is equivalent to $w.$m.
+.sh 2 "New and Changed Classes"
+.ip $=k
+Initialized to contain $k.
+.ip $=w
+Now includes
+.q [1.2.3.4]
+(where 1.2.3.4 is your IP address)
+to allow the configuration file to recognize your own IP address.
+.sh 2 "New Rewriting Tokens"
+.pp
+The
+.b $&
+construct has been adopted from IDA to defer macro evaluation.
+Normally, macros in rulesets are bound when the rule is first parsed
+during startup.
+Some macros change during processing and are uninteresting during startup.
+However, that macro can be referenced using
+.q $&x
+to defer the evaulation of
+$x
+until the rule is processed.
+.pp
+The tokens
+.b $(
+and
+.b $)
+have been added to allow specification of map rewriting.
+.pp
+Version 8 allows
+.b $@
+on the Left Hand Side of an `R' line to match
+zero tokens.
+This is intended to be used to match the null input.
+.sh 2 "Bigger Defaults
+.pp
+Version 8 allows up to 100 rulesets instead of 30. It is recommended
+that rulesets 0\-9 be reserved for sendmail's dedicated use in future
+releases.
+.pp
+The total number of MX records that can be used has been raised to
+20.
+.pp
+The number of queued messages that can be handled at one time has
+been raised from 600 to 1000.
+.sh 2 "Different Default Tuning Parameters
+.pp
+Version 8 has changed the default parameters for tuning queue costs
+to make the number of recipients more important than the size of
+the message (for small messages). This is reasonable if you are
+connected with reasonably fast links.
+.sh 2 "Auto-Quoting in Addresses
+.pp
+Previously, the ``Full Name <email address>'' syntax would generate
+incorrect protocol output if ``Full Name'' had special characters
+such as dot. This version puts quotes around such names.
+.sh 2 "Symbolic Names On Error Mailer
+.pp
+Several names have been built in to the $@ portion of the $#error
+mailer. For example:
+.(b
+$#error $@NOHOST $: Host unknown
+.)b
+Prints the indicated message
+and sets the exit status of
+.i sendmail
+to
+.sm EX_NOHOST .
+.sh 2 "New Built-In Mailers"
+.pp
+Two new mailers, *file* and *include*, are included to define options
+when mailing to a file or a :include: file respectively. Previously
+these were overloaded on the local mailer.
+.sh 2 "SMTP VRFY Doesn't Expand
+.pp
+Previous versions of sendmail treated VRFY and EXPN the same. In
+this version, VRFY doesn't expand aliases or follow .forward files.
+.pp
+As an optimization, if you run with your default delivery mode
+being queue-only, the RCPT command will also not chase aliases and
+\&.forward files.
+It will chase them when it processes the queue.
+This speeds up RCPT processing.
+.sh 2 "[IPC] Mailers Allow Multiple Hosts
+.pp
+When an address resolves to a mailer that has ``[IPC]'' as its
+``Path'', the $@ part (host name) can be a colon-separated list of
+hosts instead of a single hostname. This asks sendmail to search
+the list for the first entry that is available exactly as though
+it were an MX record. The intent is to route internal traffic
+through internal networks without publishing an MX record to the
+net. MX expansion is still done on the individual items.
+.sh 2 "Aliases Extended"
+.pp
+The implementation has been merged with maps. Among other things,
+this supports multiple alias files and NIS-based aliases. For
+example:
+.(b
+OA/etc/aliases,nis:mail.aliases
+.)b
+will search first the local database
+.q /etc/aliases
+followed by the NIS map
+
+.sh 2 "Portability and Security Enhancements
+.pp
+A number of internal changes have been made to enhance portability.
+.pp
+Several fixes have been made to increase the paranoia factor.
+.pp
+In particular, the permissions required for .forward and :include:
+files have been tightened up considerably. V5 would pretty much
+read any file it could get to as root, which exposed some security
+holes. V8 insists that all directories leading up to the .forward
+or :include: file be searchable ("x" permission) by the controlling
+user" (defined below), that the file itself be readable by the
+controlling user, and that .forward files be owned by the user
+who is being forwarded to or root.
+.pp
+The "controlling user" is the user on whose behalf the mail is
+being delivered. For example, if you mail to "user1" then the
+controlling user for ~user1/.forward and any mailers invoked
+by that .forward file, including :include: files.
+.pp
+Previously, anyone who had a home directory could create a .forward
+could forward to a program. Now, sendmail checks to make sure
+that they have an "approved shell", that is, a shell listed in
+the /etc/shells file.
+.sh 2 "Miscellaneous Fixes and Enhancements"
+.pp
+A number of small bugs having to do with things like backslash-escaped
+quotes inside of comments have been fixed.
+.pp
+The fixed size limit on header lines
+(such as
+.q To:
+and
+.q Cc: )
+has been eliminated;
+those buffers are dynamically allocated now.
+.pp
+Sendmail writes a /etc/sendmail.pid file with the current process id
+and the current invocation flags.
+.pp
+Two people using the same program (e.g., submit) are considered
+"different" so that duplicate elimination doesn't delete one of
+them. For example, two people forwarding their email to
+|submit will be treated as two recipients.
+.pp
+The mailstats program prints mailer names and gets the location of
+the sendmail.st file from /etc/sendmail.cf.
+.pp
+Many minor bugs have been fixed, such as handling of backslashes
+inside of quotes.
+.pp
+A hook has been added to allow rewriting of local addresses after
+aliasing.
+.sh 1 "FUTURE WORK"
+.pp
+The previous section describes
+.i sendmail
+as of version 8.6.6.
+There is still much to be done.
+Some high points are described below.
+This list is by no means exhaustive.
+.sh 2 "Full MIME Support"
+.pp
+Currently
+.i sendmail
+only supports seven bit MIME messages.
+Although it can pass eight bit MIME messages,
+it cannot advertise that fact because the standards say
+that the mail agent must be able to do 8- to 7-bit conversion
+to have full 8-bit support.
+This requires far more extensive modification of the message body
+than is currently supported.
+.pp
+The best way to do this would be to support the general concept
+of an external
+``message filter''
+that could do arbitrary modifications of the message.
+This would allow MIME conversion as well as such things as
+automatic encryption of messages sent over external links.
+This is probably an extremely non-trivial change.
+.sh 2 "Service Switch Abstraction"
+.pp
+Most modern systems include some concept of a
+.q "service switch"
+\*- for example, to look up host names you can try
+DNS, NIS, NIS+, text tables, NetInfo,
+or other services in some arbitrary order.
+This is currently very clumsy in
+.i sendmail ,
+with only limited control of the services provided.
+.sh 2 "More Control of Local Addresses"
+.pp
+Currently some addresses are declared as
+.q local
+and are handled specially \*-
+for example, they may have .forward files,
+may be translated into program calls or file deliveries,
+and so forth.
+These should be broken out into separate flags
+to allow the local system administrator
+to have more fine-grained control over operations.
+.sh 2 "More Run-Time Configuration Options"
+.pp
+There are many options that are configured at compile time,
+such as the method of file locking
+and the use of the IDENT protocol
+[RFC1413].
+These should be transfered to run time
+by adding new options.
+.pp
+Similarly, some options are currently overloaded,
+that is, a single option controls more than one thing.
+These should probably be broken out into separate options.
+.pp
+This implies that options will change from single characters
+to words.
+.sh 2 "More Configuration Control Over Errors"
+.pp
+Currently,
+the configuration file can generate an error message during parsing.
+However,
+it cannot tweak other operations,
+such as issuing a warning message to the system postmaster.
+Similarly,
+some errors should not be triggered if they are in aliases
+during an alias file rebuild,
+but should be triggered if that alias is actually used.
+.sh 2 "Long Term Host State"
+.pp
+Currently,
+.i sendmail
+only remembers host status during a single queue run.
+This should be converted to long term status
+stored on disk
+so it can be shared between instantiations of
+.i sendmail .
+Entries will have to be timestamped
+so they can time out.
+This will allow
+.i sendmail
+to implement exponential backoff on queue runs
+on a per-host basis.
+.sh 2 "Connection Control"
+.pp
+Modern networks have different types of connectivity
+than the past.
+In particular, the rising prominence of dialup IP
+has created certain challenges for automated servers.
+It is not uncommon to try to make a connection to a host
+and have it fail, even though if you tried again it would succeed.
+The connection management could be a bit cleverer
+to try to adapt to such situations.
+.sh 2 "Other Caching"
+.pp
+When you do an MX record lookup,
+the name server automatically returns the IP addresses
+of the associated MX servers.
+This information is currently ignored,
+and another query is done to get this information.
+It should be cached to avoid excess name server traffic.
+.sh 1 "REFERENCES"
+.ip [Allman83a]
+.q "Sendmail \*- An Internetwork Mail Router."
+E. Allman.
+In
+.ul
+Unix Programmers's Manual,
+4.2 Berkeley Software Distribution,
+volume 2C.
+August 1983.
+.ip [Allman83b]
+.q "Mail Systems and Addressing in 4.2BSD."
+E. Allman
+In
+.ul
+UNICOM Conference Proceedings.
+San Diego, California.
+January 1983.
+.ip [Allman&Amos85]
+``Sendmail Revisited.''
+E. Allman and M. Amos.
+In
+.ul
+Usenix Summer 1985 Conference Proceedings.
+Portland, Oregon.
+June 1985.
+.ip [IDA87]
+.ul 3
+Electronic Mail Addressing in Theory and Practice
+with the IDA Sendmail Enhancement Kit
+(or The Postmaster's Last Will and Testament).
+Lennart Lo\*:vstrand.
+Department of Computer and Information Science,
+University of Linko\*:ping,
+Sweden,
+Report no. LiTH-IDA-Ex-8715.
+May 1987.
+.ip [RFC821]
+.ul
+Simple Mail Transport Protocol.
+J. Postel.
+August 1982.
+.ip [RFC1123]
+.ul
+Requirements for Internet Hosts \*- Application and Support.
+Internet Engineering Task Force,
+R. Braden, Editor.
+October 1989.
+.ip [RFC1344]
+.ul
+Implications of MIME for Internet Mail Gateways.
+N. Borenstein.
+June 1992.
+.ip [RFC1413]
+.ul
+Identification Protocol.
+M. St. Johns.
+February 1993.
+.ip [RFC1425]
+.ul
+SMTP Service Extensions.
+J. Klensin, N. Freed, M. Rose, E. Stefferud, and D. Crocker.
+February 1993.
+.ip [RFC1426]
+.ul
+SMTP Service Extension for 8bit-MIMEtransport.
+J. Klensin, N. Freed, M. Rose, E. Stefferud, and D. Crocker.
+February 1993.
+.ip [RFC1427]
+.ul
+SMTP Service Extension for Message Size Declaration.
+J. Klensin, N. Freed, and K. Moore.
+February 1993.
+.ip [RFC1521]
+.ul 3
+MIME (Multipurpose Internet Mail Extensions) Part One:
+Mechanisms for Specifying and Describing
+the Format of Internet Message Bodies.
+N. Borenstein and N. Freed.
+September 1993.
diff --git a/usr.sbin/sendmail/doc/changes/changes.ps b/usr.sbin/sendmail/doc/changes/changes.ps
new file mode 100644
index 000000000000..5ba54a43edec
--- /dev/null
+++ b/usr.sbin/sendmail/doc/changes/changes.ps
@@ -0,0 +1,1092 @@
+%!PS-Adobe-3.0
+%%Creator: groff version 1.08
+%%DocumentNeededResources: font Times-Roman
+%%+ font Times-Italic
+%%+ font Times-Bold
+%%+ font Symbol
+%%DocumentSuppliedResources: procset grops 1.08 0
+%%Pages: 11
+%%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
+%%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-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(Changes in Sendmail V)196.615 141 Q(ersion 8*)-1.554 E
+/F1 10/Times-Roman@0 SF(Eric Allman)263.42 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.11
+(Ve)112 243.6 S 1.709(rsion 8 of)1.11 F F2(sendmail)4.209 E F1 1.709
+(includes a number of major changes from pre)4.209 F 1.71(vious v)-.25 F
+(ersions.)-.15 E .701(This paper gi)112 255.6 R -.15(ve)-.25 G 3.201(sav).15 G
+.701(ery short history of)194.794 255.6 R F2(sendmail)3.201 E F1 3.201(,as)C .7
+(ummary of the major dif)329.82 255.6 R(ferences)-.25 E .953(between v)112
+267.6 R .954(ersion 5 \(the last publically a)-.15 F -.25(va)-.2 G .954
+(ilable v).25 F .954(ersion\) and v)-.15 F .954(ersion 8, and some dis-)-.15 F
+(cussion of future directions.)112 279.6 Q .48
+(In 1987, the author stopped major w)97 324 R .48(ork on)-.1 F F2(sendmail)2.98
+E F1 .48(due to other time committments, only to return)2.98 F(to acti)72 336 Q
+.3 -.15(ve w)-.25 H(ork in 1991.).05 E(This paper e)5 E(xplores wh)-.15 E 2.5
+(yw)-.05 G(ork resumed and what changes ha)277 336 Q .3 -.15(ve b)-.2 H
+(een made.).15 E .58(Section 1 gi)97 352.2 R -.15(ve)-.25 G 3.08(sas).15 G .58
+(hort history of)173.36 352.2 R F2(sendmail)3.08 E F1 .58(through v)3.08 F .58
+(ersion 5 and the moti)-.15 F -.25(va)-.25 G .58(tion behind w).25 F .58
+(orking on)-.1 F -.15(ve)72 364.2 S .126(rsion 8.).15 F .126
+(Section 2 has a rather detailed description of what has changed between v)
+5.126 F .125(ersion 5 and v)-.15 F .125(ersion 8.)-.15 F
+(The paper \214nishes of)72 376.2 Q 2.5(fw)-.25 G
+(ith some thoughts about what still needs to be done.)168.95 376.2 Q/F3 10
+/Times-Bold@0 SF 2.5(1. HIST)72 400.2 R(OR)-.18 E(Y)-.35 E F1 .151
+(As discussed else)112 416.4 R .151
+(where, [Allman83a, Allman83b, Allman&Amos85] sendmail has e)-.25 F .151
+(xisted in v)-.15 F(ar)-.25 E(-)-.2 E .405(ious forms since 1980.)87 428.4 R
+.405(It w)5.405 F .405(as released under the name)-.1 F F2(delivermail)2.905 E
+F1 .404(in 4BSD and 4.1BSD, and as)2.905 F F2(send-)2.904 E(mail)87 440.4 Q F1
+(in 4.2BSD.)2.5 E(It quickly became the dominant mail system for netw)5 E(ork)
+-.1 E(ed UNIX systems.)-.1 E 1.569(Prior the release of 4.3BSD in No)112 456.6
+R -.15(ve)-.15 G 1.569(mber 1986, the author had left the Uni).15 F -.15(ve)
+-.25 G 1.57(rsity for pri).15 F -.25(va)-.25 G(te).25 E(industry)87 468.6 Q
+3.347(,b)-.65 G .847(ut continued to do some w)129.777 468.6 R .847(ork on)-.1
+F F2(sendmail)3.347 E F1 .847(with acti)3.347 F .846(vity slo)-.25 F .846
+(wly trailing of)-.25 F 3.346(fu)-.25 G .846(ntil ef)445.204 468.6 R(fecti)-.25
+E -.15(ve)-.25 G(ly).15 E .255(stopping after February 1987.)87 480.6 R .255
+(There w)5.255 F .255(as minimal support done by man)-.1 F 2.756(yp)-.15 G .256
+(eople for se)389.796 480.6 R -.15(ve)-.25 G .256(ral years, until).15 F
+(July of 1991 when the original author)87 492.6 Q 2.5(,w)-.4 G
+(ho had returned the Uni)249.36 492.6 Q -.15(ve)-.25 G(rsity).15 E 2.5(,s)-.65
+G(tarted acti)379.4 492.6 Q .3 -.15(ve w)-.25 H(ork on it ag).05 E(ain.)-.05 E
+1.271(There were se)112 508.8 R -.15(ve)-.25 G 1.271(ral reasons for rene).15 F
+1.271(wed w)-.25 F 1.271(ork on)-.1 F F2(sendmail)3.771 E F1 6.271(.T)C 1.271
+(here w)369.549 508.8 R 1.27(as a desire at Berk)-.1 F(ele)-.1 E 3.77(yt)-.15 G
+(o)499 508.8 Q(con)87 520.8 Q -.15(ve)-.4 G .097
+(rt to a subdomained structure so that indi).15 F .098
+(viduals were identi\214ed by their subdomain rather than by)-.25 F 1.758
+(their indi)87 532.8 R 1.758(vidual w)-.25 F 1.758(orkstation; although possib\
+le in the old code, there were some problems, and the)-.1 F .66(author w)87
+544.8 R .66(as the ob)-.1 F .66(vious person to address them.)-.15 F .66
+(The Computer Systems Research Group \(CSRG\), the)5.66 F 1.89
+(group that produced the Berk)87 556.8 R(ele)-.1 E 4.39(yS)-.15 G(oftw)238.12
+556.8 Q 1.89(are Distrib)-.1 F 1.89(utions, w)-.2 F 1.89(as w)-.1 F 1.89
+(orking on 4.4BSD, and w)-.1 F 1.89(anted an)-.1 F .053
+(update to the mail system.)87 568.8 R .053(Bryan Costales w)5.053 F .053(as w)
+-.1 F .053(orking on a book on)-.1 F F2(sendmail)2.553 E F1 .053(that w)2.553 F
+.053(as being re)-.1 F(vie)-.25 E(wed)-.25 E .923(by the author)87 580.8 R
+3.423(,w)-.4 G .923(hich encouraged him to mak)154.359 580.8 R 3.422(es)-.1 G
+.922(ome re)283.572 580.8 R 3.422(visions. And)-.25 F .922(the author w)3.422 F
+.922(anted to try to unify)-.1 F(some of the disparate v)87 592.8 Q(ersions of)
+-.15 E F2(sendmail)2.5 E F1(that had been permitted to proliferate.)2.5 E .023
+(During the 1987\25591 f)112 609 R(allo)-.1 E 2.523(wp)-.25 G .023(eriod, man)
+228.482 609 R 2.523(yv)-.15 G .023(endors and outside v)283.498 609 R .023
+(olunteers had produced v)-.2 F .024(ariants of)-.25 F F2(sendmail)87 621 Q F1
+5.518(.P)C .517(erhaps the best kno)136.688 621 R .517(wn is the ID)-.25 F
+3.017(Av)-.4 G .517(ersion [ID)280.317 621 R 3.017(A87]. Originally)-.4 F .517
+(intended to be a ne)3.017 F 3.017(ws)-.25 G .517(et of)485.433 621 R .268
+(con\214guration \214les, ID)87 633 R 2.768(Ae)-.4 G .269(xpanded into a f)
+189.464 633 R .269(airly lar)-.1 F .269(ge set of patches for the code.)-.18 F
+.269(Originally produced in)5.269 F .471(Sweden, ID)87 645 R 2.971(Ad)-.4 G
+-2.15 -.25(ev e)149.472 645 T .471(lopment passed to the Uni).25 F -.15(ve)-.25
+G .471(rsity of Illinois, and w).15 F .47(as widely used by the f)-.1 F .47
+(airly lar)-.1 F(ge)-.18 E .077
+(set of people who prefer to get and compile their o)87 657 R .077
+(wn source code rather than use v)-.25 F(endor)-.15 E .078(-supplied bina-)-.2
+F(ries.)87 669 Q .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/F4 8/Times-Roman@0
+SF .045(*An earlier v)93.6 690.6 R .045(ersion of this paper w)-.12 F .044
+(as printed in the Proceedings of the 1994 A)-.08 F .044
+(UUG Queensland Summer T)-.44 F .044(echnical Conference,)-.56 F(Gate)72 700.2
+Q -.08(wa)-.2 G 2(yH).08 G(otel, Brisbane, March 1994.)107.928 700.2 Q F3
+(Changes in Sendmail V)72 756 Q(ersion 8)-1 E(1)499 756 Q EP
+%%Page: 2 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 294.65(2C)72 60 S(hanges in Sendmail V)378.87 60 Q
+(ersion 8)-1 E/F1 10/Times-Roman@0 SF .151
+(In about the same time frame, attempts were made to clean up and e)112 96 R
+.151(xtend the Simple Mail T)-.15 F(rans-)-.35 E .468
+(port Protocol \(SMTP\) [RFC821].)87 108 R .468(This in)5.468 F -.2(vo)-.4 G
+(lv).2 E .469(ed clari\214cations of some ambiguities in the protocol, and)-.15
+F .085(correction of some problem areas [RFC1123], as well as e)87 120 R .084
+(xtensions for additional functionality \(dubbed)-.15 F 1.052
+(Extended Simple Mail T)87 132 R 1.053
+(ransport Protocol, or ESMTP\) [RFC1425, RFC1426, RFC1427] and a richer)-.35 F
+1.376(set of semantics in the body of messages \(the Multipurpose Internet Mai\
+l Extensions, a.k.a. MIME\))87 144 R .497([RFC1521, RFC1344].)87 156 R .497
+(Neither the ID)5.497 F 2.998(Ag)-.4 G .498(roup nor most v)258.526 156 R .498
+(endors were modifying)-.15 F/F2 10/Times-Italic@0 SF(sendmail)2.998 E F1 .498
+(to conform)2.998 F 1.7(to these ne)87 168 R 4.2(ws)-.25 G 4.2(tandards. It)
+148.23 168 R 1.699(seemed clear that these were `)4.2 F 1.699(`good things')
+-.74 F 4.199('t)-.74 G 1.699(hat should be encouraged.)394.483 168 R(Ho)87 180
+Q(we)-.25 E -.15(ve)-.25 G 1.635 -.4(r, s).15 H .835(ince no one w).4 F .835
+(as w)-.1 F .835(orking on a publically a)-.1 F -.25(va)-.2 G .835(ilable v).25
+F .836(ersion of)-.15 F F2(sendmail)3.336 E F1 .836(with these updates,)3.336 F
+(the)87 192 Q 2.5(yw)-.15 G(ere unlik)113.79 192 Q(ely to be widely deplo)-.1 E
+(yed an)-.1 E 2.5(yt)-.15 G(ime in the near future.)274.25 192 Q .466
+(There are, of course, other mail transport agents a)112 208.2 R -.25(va)-.2 G
+.465(ilable, such as).25 F F2 .465(MMDF zmailer smail)2.965 F F1(and)2.965 E F2
+(PP)2.965 E F1(Ho)87 220.2 Q(we)-.25 E -.15(ve)-.25 G .842 -.4(r, n).15 H .042
+(one of these seemed to be g).4 F .043(aining the prominence of)-.05 F F2
+(sendmail)2.543 E F1 2.543(;i)C 2.543(ta)390.518 220.2 S .043
+(ppeared that most compa-)400.281 220.2 R .238(nies w)87 232.2 R .238
+(ould not con)-.1 F -.15(ve)-.4 G .238(rt to another mail transport agent an)
+.15 F 2.737(yt)-.15 G .237(ime in the forseeable future.)327.438 232.2 R(Ho)
+5.237 E(we)-.25 E -.15(ve)-.25 G 1.037 -.4(r, t).15 H(he).4 E(y)-.15 E
+(might be persuaded to con)87 244.2 Q -.15(ve)-.4 G(rt to a ne).15 E(wer v)-.25
+E(ersion of)-.15 E F2(sendmail)2.5 E F1(.)A .841(All of these con)112 260.4 R
+.841(vinced the author to w)-.4 F .841(ork on a updated v)-.1 F .841(ersion of)
+-.15 F F2(sendmail)3.342 E F1 .842(for public distrib)3.342 F(u-)-.2 E(tion.)87
+272.4 Q 1.024(The ne)112 288.6 R 3.524(wv)-.25 G 1.023(ersion of)155.858 288.6
+R F2(sendmail)3.523 E F1 1.023(is referred to as v)3.523 F 1.023
+(ersion eight \(V8\).)-.15 F -1.11(Ve)6.023 G 1.023(rsions six and se)1.11 F
+-.15(ve)-.25 G 3.523(nw).15 G(ere)491.79 288.6 Q 1.281
+(skipped because of an agreement that all \214les in 4.4BSD w)87 300.6 R 1.281
+(ould be numbered as \2318.1\232.)-.1 F 1.282(Rather than)6.282 F(ha)87 312.6 Q
+2.05 -.15(ve a)-.2 H 4.25(ne).15 G 1.75(xternal v)127.76 312.6 R 1.75
+(ersion number that dif)-.15 F 1.75(fered from the \214le v)-.25 F 1.75
+(ersion numbers,)-.15 F F2(sendmail)4.25 E F1 1.75(just jumped)4.25 F
+(directly to V8.)87 324.6 Q F0 2.5(2. CHANGES)72 348.6 R(IN VERSION EIGHT)2.5 E
+F1 .138(The follo)112 364.8 R .139
+(wing is a summary of the changes between the last commonly a)-.25 F -.25(va)
+-.2 G .139(ilable v).25 F .139(ersion of send-)-.15 F(mail from Berk)87 376.8 Q
+(ele)-.1 E 2.5(y\()-.15 G(5.67\) and the latest v)170.9 376.8 Q
+(ersion \(8.6.6\).)-.15 E(Man)112 393 Q 2.5(yo)-.15 G 2.5(ft)142.68 393 S
+(hese are ideas that had been tried in ID)151.29 393 Q(A, b)-.4 E(ut man)-.2 E
+2.5(yo)-.15 G 2.5(ft)363.27 393 S(hem were generalized in V8.)371.88 393 Q F0
+2.5(2.1. P)87 417 R(erf)-.2 E(ormance Enhancements)-.25 E F1 .549
+(Instead of closing SMTP connections immediately)127 433.2 R 3.049(,o)-.65 G
+.549(pen connections are cached for possible)342.135 433.2 R .029(future use.)
+102 445.2 R .029(There is a limit to the number of simultaneous open connectio\
+ns and the idle time of an)5.029 F(y)-.15 E(indi)102 457.2 Q
+(vidual connection.)-.25 E 1.219(This is of best help during queue processing \
+\(since there is the potential of man)127 473.4 R 3.719(yd)-.15 G(if)474.82
+473.4 Q(ferent)-.25 E 1.113(messages going to one site\), although it can also\
+ help when processing MX records which aren')102 485.4 R(t)-.18 E
+(handled by MX Piggybacking.)102 497.4 Q 1.258(If tw)127 513.6 R 3.757(oh)-.1 G
+1.257(osts with dif)161.075 513.6 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 525.6 R 3.44(yc)-.15 G .94
+(an be sent in the same transaction.)153.45 525.6 R -1.11(Ve)5.94 G .94
+(rsion 8 notices this and tries to batch the mes-)1.11 F(sages.)102 537.6 Q
+-.15(Fo)127 553.8 S 3.638(re).15 G 1.138(xample, if tw)148.668 553.8 R 3.637
+(os)-.1 G 1.137(ites `)216.42 553.8 R(`foo.com')-.74 E 3.637('a)-.74 G 1.137
+(nd `)286.914 553.8 R(`bar)-.74 E(.com')-.55 E 3.637('a)-.74 G 1.137
+(re both serv)352.408 553.8 R 1.137(ed by UUNET)-.15 F 3.637(,t)-.74 G(he)
+470.513 553.8 Q 3.637(yw)-.15 G(ill)495.66 553.8 Q(ha)102 565.8 Q .557 -.15
+(ve t)-.2 H .257(he same set of MX hosts and will be sent in one transaction.)
+.15 F .258(UUNET will then split the mes-)5.258 F(sage and send it to the tw)
+102 577.8 Q 2.5(oi)-.1 G(ndi)213.28 577.8 Q(vidual hosts.)-.25 E F0 2.5
+(2.2. RFC)87 601.8 R(1123 Changes)2.5 E F1 2.607(An)127 618 S .107
+(umber of changes ha)141.827 618 R .407 -.15(ve b)-.2 H .106(een made to mak)
+.15 F 2.606(es)-.1 G .106(endmail `)321.07 618 R .106
+(`conditionally compliant')-.74 F 2.606('\()-.74 G .106(that is, it)469.058 618
+R(satis\214es all of the MUST clauses and most b)102 630 Q
+(ut not all of the SHOULD clauses in RFC 1123\).)-.2 E
+(The major areas of change are \(numbers are RFC 1123 section numbers\):)127
+646.2 Q 26.5(\2475.2.7 Response)102 662.4 R .565(to RCPT command is f)3.065 F
+3.065(ast. Pre)-.1 F(viously)-.25 E 3.065(,s)-.65 G .565(endmail e)362.295
+662.4 R .565(xpanded all aliases as f)-.15 F(ar)-.1 E .686
+(as it could \212 this could tak)156 674.4 R 3.186(eav)-.1 G .685
+(ery long time, particularly if there were name serv)290.118 674.4 R(er)-.15 E
+3.891(delays. V)156 686.4 R 1.391(ersion 8 only checks for the e)-1.11 F 1.392
+(xistence of an alias and does the e)-.15 F(xpansion)-.15 E(later)156 698.4 Q
+5.176(.I)-.55 G 2.676(td)184.226 698.4 S .176
+(oes still do a DNS lookup if there is an e)194.682 698.4 R .175
+(xplicit host name in the RCPT com-)-.15 F(mand, b)156 710.4 Q
+(ut this time is bounded.)-.2 E EP
+%%Page: 3 3
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Changes in Sendmail V)72 60 Q(ersion 8)-1 E(3)499 60 Q
+/F1 10/Times-Roman@0 SF 26.5(\2475.2.8 Numeric)102 96 R .612
+(IP addresses are logged in Recei)3.112 F -.15(ve)-.25 G .613(d: lines.).15 F
+.613(This helps tracing spoofed mes-)5.613 F(sages.)156 108 Q 21.5
+(\2475.2.17 Self)102 124.2 R .127(domain literal is properly handled.)2.627 F
+(Pre)5.126 E(viously)-.25 E 2.626(,i)-.65 G 2.626(fs)368.196 124.2 S .126
+(omeone sent to user@[1.2.3.4],)378.042 124.2 R .12
+(where 1.2.3.4 is your IP address, the mail w)156 136.2 R .12
+(ould probably be rejected with a `)-.1 F(`con\214gu-)-.74 E(ration error')156
+148.2 Q 2.5('. V)-.74 F(ersion 8 can handle these addresses.)-1.11 E 26.5
+(\2475.3.2 Better)102 164.4 R 1.189(control o)3.69 F -.15(ve)-.15 G 3.689(ri)
+.15 G(ndi)240.088 164.4 Q 1.189(vidual timeouts.)-.25 F 1.189
+(RFC 821 speci\214ed no timeouts.)6.189 F 1.189(Older v)6.189 F(er)-.15 E(-)-.2
+E .002(sions of sendmail had a single timeout, typically set to tw)156 176.4 R
+2.502(oh)-.1 G 2.502(ours. V)398.142 176.4 R .002(ersion 8 allo)-1.11 F .002
+(ws the)-.25 F(con\214guration \214le to set timeouts for v)156 188.4 Q
+(arious SMTP commands indi)-.25 E(vidually)-.25 E(.)-.65 E 26.5
+(\2475.3.3 Error)102 204.6 R 1.06(messages are sent as From:<>.)3.56 F 1.059
+(This w)6.059 F 1.059(as ur)-.1 F 1.059(ged by RFC 821 and reiterated by)-.18 F
+.237(RFC 1123, b)156 216.6 R .237(ut older v)-.2 F .237(ersions of sendmail ne)
+-.15 F -.15(ve)-.25 G 2.737(rr).15 G .237(eally did it properly)355.186 216.6 R
+5.237(.V)-.65 G .238(ersion 8 does.)448.254 216.6 R(Ho)156 228.6 Q(we)-.25 E
+-.15(ve)-.25 G 1.934 -.4(r, s).15 H 1.134
+(ome systems cannot handle this perfectly le).4 F -.05(ga)-.15 G 3.633(la).05 G
+1.133(ddress; if necessary)402.941 228.6 R 3.633(,y)-.65 G(ou)494 228.6 Q
+(can create a special mailer that uses the `g' \215ag to disable this.)156
+240.6 Q 26.5(\2475.3.3 Error)102 256.8 R 3.212(messages are ne)5.712 F -.15(ve)
+-.25 G 5.712(rs).15 G 3.212(ent to <>.)275.628 256.8 R(Pre)8.213 E(viously)-.25
+E 5.713(,s)-.65 G 3.213(endmail w)383.028 256.8 R 3.213(as happ)-.1 F 5.713(yt)
+-.1 G 5.713(os)474.957 256.8 S(end)489.56 256.8 Q 6
+(responses-to-responses which sometimes resulted in responses-to-responses-to-)
+156 268.8 R(responses which resulted in ....)156 280.8 Q(you get the idea.)5 E
+26.5(\2475.3.3 Route-addrs)102 297 R .111(\(the ugly `)2.611 F
+(`<@hosta,@hostb:user@hostc>')-.74 E 2.611('s)-.74 G .111(yntax\) are pruned.)
+389.124 297 R .112(RFC 821)5.112 F(ur)156 309 Q 1.001
+(ged the use of this bletcherous syntax.)-.18 F 1
+(RFC 1123 has seen the light and of)6.001 F(\214cially)-.25 E 1.124
+(deprecates them, further ur)156 321 R 1.125(ging that you eliminate all b)-.18
+F 1.125(ut `)-.2 F(`user@hostc')-.74 E 3.625('s)-.74 G 1.125(hould you)462.595
+321 R(recei)156 333 Q 1.698 -.15(ve o)-.25 H 1.398(ne of these things.).15 F
+-1.11(Ve)6.398 G 1.398(rsion 8 is slightly more generous than the standards)
+1.11 F .753(suggest; instead of stripping of)156 345 R 3.253(fa)-.25 G .753
+(ll the route addressees, it only strips hosts of)293.115 345 R 3.254(fu)-.25 G
+3.254(pt)487.966 345 S(o)499 345 Q 1.29(the one before the last one kno)156 357
+R 1.289(wn to DNS, thus allo)-.25 F 1.289(wing you to ha)-.25 F 1.589 -.15
+(ve p)-.2 H(seudo-hosts).15 E(such as foo.BITNET)156 369 Q 5(.T)-.74 G
+(he `R' option will turn this of)251.91 369 Q(f.)-.25 E
+(The areas in which sendmail is not `)102 385.2 Q(`unconditionally compliant')
+-.74 E 2.5('a)-.74 G(re:)367.43 385.2 Q 26.5(\2475.2.6 Sendmail)102 401.4 R
+(does do header munging.)2.5 E 21.5(\2475.2.10 Sendmail)102 417.6 R(doesn')3.2
+E 3.2(ta)-.18 G -.1(lwa)233.88 417.6 S .7(ys use the e).1 F .701
+(xact SMTP message te)-.15 F .701(xt from RFC 821.)-.15 F .701(This is a)5.701
+F(rather silly requirement.)156 429.6 Q 19(\2475.3.1.1 Sendmail)102 445.8 R
+(doesn')3.512 E 3.512(tg)-.18 G 1.012
+(uarantee only one connect for each host on queue runs.)235.064 445.8 R
+(Connec-)6.011 E(tion caching gi)156 457.8 Q -.15(ve)-.25 G 2.5(sy).15 G
+(ou most of this, b)235.87 457.8 Q(ut it does not pro)-.2 E(vide a guarantee.)
+-.15 E 19(\2475.3.1.1 Sendmail)102 474 R(doesn')2.843 E 2.843(ta)-.18 G -.1
+(lwa)233.166 474 S .343(ys pro).1 F .343(vide an adequate limit on concurrenc)
+-.15 F 4.144 -.65(y. T)-.15 H .344(hat is, there can).65 F .757(be se)156 486 R
+-.15(ve)-.25 G .757(ral independent sendmails running at once.).15 F .757
+(My feeling is that doing an abso-)5.757 F 1.047(lute limit w)156 498 R 1.047
+(ould be a mistak)-.1 F 3.547(e\()-.1 G 1.048(it might result in lost mail\).)
+284.302 498 R(Ho)6.048 E(we)-.25 E -.15(ve)-.25 G 1.848 -.4(r, i).15 H 3.548
+(fy).4 G 1.048(ou use the)461.354 498 R .801(XLA contrib)156 510 R .801
+(uted softw)-.2 F .801(are, most of this will be guaranteed \(b)-.1 F .801
+(ut I don')-.2 F 3.3(tg)-.18 G .8(uarantee the)454.61 510 R(guarantee\).)156
+522 Q F0 2.5(2.3. Extended)87 546 R(SMTP Support)2.5 E F1 -1.11(Ve)127 562.2 S
+.154(rsion 8 includes both sending and recei)1.11 F .155
+(ving support for Extended SMTP support as de\214ned)-.25 F .229(by RFC 1425 \
+\(basic\) and RFC 1427 \(SIZE\); and limited support for RFC 1426 \(BOD)102
+574.2 R 2.729(Y\). The)-.55 F(body)2.729 E .275(support is minimal because the\
+ \2318BITMIME\232 body type is not currently adv)102 586.2 R 2.776
+(ertised. Although)-.15 F(such)2.776 E 3.076(ab)102 598.2 S .576
+(ody type will be accepted, it will not be correctly con)114.516 598.2 R -.15
+(ve)-.4 G .576(rted to 7 bits if speaking to a non-8-bit-).15 F(MIME a)102
+610.2 Q -.1(wa)-.15 G(re SMTP serv).1 E(er)-.15 E(.)-.55 E/F2 10/Times-Italic@0
+SF(Sendmail)127 626.4 Q F1 .287(tries to speak ESMTP if you ha)2.787 F .588
+-.15(ve t)-.2 H .288(he `a' \215ag set in the \215ags for the mailer descrip-)
+.15 F(tor)102 638.4 Q 3.322(,o)-.4 G 3.322(ri)123.532 638.4 S 3.322(ft)132.964
+638.4 S .822(he other end adv)142.396 638.4 R .822(ertises the f)-.15 F .822
+(act that it speaks ESMTP)-.1 F 5.822(.T)-1.11 G .821
+(his is a non-standard adv)376.446 638.4 R(ertise-)-.15 E(ment:)102 650.4 Q F2
+(sendmail)2.98 E F1 .48(announces \231ESMTP spok)2.98 F .48
+(en here\232 during the initial connection message, and client)-.1 F .587
+(sendmails search for this message.)102 662.4 R .586
+(This creates some problems for some PC-based mailers, which)5.586 F
+(do not understand tw)102 674.4 Q
+(o-line greeting messages as required by RFC 821.)-.1 E EP
+%%Page: 4 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 294.65(4C)72 60 S(hanges in Sendmail V)378.87 60 Q
+(ersion 8)-1 E 2.5(2.4. Eight-Bit)87 96 R(Clean)2.5 E/F1 10/Times-Roman@0 SF
+(Pre)127 112.2 Q 1.263(vious v)-.25 F 1.263
+(ersions of sendmail used the 0200 bit for quoting.)-.15 F 1.264(This v)6.264 F
+1.264(ersion a)-.15 F -.2(vo)-.2 G 1.264(ids that use.).2 F(Ho)102 124.2 Q(we)
+-.25 E -.15(ve)-.25 G 1.119 -.4(r, y).15 H .318
+(ou can set option `7' to get se).4 F -.15(ve)-.25 G 2.818(nb).15 G .318
+(it stripping for compatibility with RFC 821, which is)290.046 124.2 R 2.5(a7)
+102 136.2 S(-bit protocol.)113.94 136.2 Q(This option says `)5 E
+(`strip to 7 bits on input')-.74 E('.)-.74 E(Indi)127 152.4 Q .375
+(vidual mailers can still produce se)-.25 F -.15(ve)-.25 G 2.875(nb).15 G .376
+(it out put using the `7' mailer \215ag.)303.02 152.4 R .376(This \215ag says)
+5.376 F -.74(``)102 164.4 S(strip to 7 bits on output').74 E('.)-.74 E F0 2.5
+(2.5. User)87 188.4 R(Database)2.5 E F1 1.926
+(The User Database \(UDB\) is an as-yet e)127 204.6 R 1.926
+(xperimental attempt to pro)-.15 F 1.925(vide uni\214ed lar)-.15 F(ge-site)-.18
+E .396(name support.)102 216.6 R 1.996 -.8(We a)5.396 H .396
+(re installing it at Berk).8 F(ele)-.1 E .396(y; future v)-.15 F .396
+(ersions may sho)-.15 F 2.897(ws)-.25 G .397(igni\214cant modi\214cations.)
+406.373 216.6 R(Brie\215y)102 228.6 Q 3.583(,U)-.65 G 1.083
+(DB contains a database that is intended to contain all the per)142.433 228.6 R
+1.082(-user information for your)-.2 F -.1(wo)102 240.6 S .172
+(rkgroup, such as people').1 F 2.673(sf)-.55 G .173
+(ull names, their .plan information, their outgoing mail name, and their)222.29
+240.6 R(mail drop.)102 252.6 Q .438(The user database allo)127 268.8 R .438
+(ws you to map both incoming and outgoing addresses, much lik)-.25 F 2.937(eI)
+-.1 G -.4(DA)487.46 268.8 S(.).4 E(Ho)102 280.8 Q(we)-.25 E -.15(ve)-.25 G
+1.799 -.4(r, t).15 H .999(he interf).4 F .999(ace is still better with ID)-.1 F
+.999(A; in particular)-.4 F 3.499(,t)-.4 G 1
+(he alias \214le with incoming/outgoing)355.55 280.8 R(marks pro)102 292.8 Q
+(vides better locality of information.)-.15 E F0 2.5(2.6. Impr)87 316.8 R -.1
+(ove)-.18 G 2.5(dB).1 G(IND Support)158.01 316.8 Q F1 .262
+(The BIND support, particularly for MX records, had a number of anno)127 333 R
+.261(ying `)-.1 F(`features')-.74 E 2.761('w)-.74 G(hich)486.78 333 Q(ha)102
+345 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 345 S .912(his release.)198.308 345 R .912(In particular)5.912
+F 3.412(,t)-.4 G .912(hese more tightly bind \(pun intended\) the name)307.916
+345 R(serv)102 357 Q(er to sendmail, so that the name serv)-.15 E
+(er resolution rules are incorporated directly into sendmail.)-.15 E .688
+(The major change has been that the $[ ... $] operator didn')127 373.2 R 3.188
+(tf)-.18 G .688(ully qualify names that were in)376.41 373.2 R
+(DNS as A or MX records.)102 385.2 Q -1.11(Ve)5 G
+(rsion 8 does this quali\214cation.)1.11 E .429(This has pro)127 401.4 R -.15
+(ve)-.15 G 2.929(nt).15 G 2.929(ob)197.147 401.4 S 2.929(ea)210.076 401.4 S
+2.929(na)221.885 401.4 S(nno)234.254 401.4 Q .43
+(yance in Sun shops, who often still run without BIND support.)-.1 F(Ho)102
+413.4 Q(we)-.25 E -.15(ve)-.25 G 1.001 -.4(r, i).15 H 2.701(ti).4 G 2.701(sr)
+153.842 413.4 S .201
+(eally critical that this be supported, since MX records are mandatory)163.763
+413.4 R 5.2(.I)-.65 G 2.7(nS)450.26 413.4 S .2(unOS you)463.52 413.4 R .101
+(can choose either MX support or NIS support, b)102 425.4 R .101(ut not both.)
+-.2 F .101(This is \214x)5.101 F .101(ed in Solaris, and some)-.15 F/F2 10
+/Times-Italic@0 SF(send-)2.602 E(mail)102 437.4 Q F1(support to allo)2.5 E 2.5
+(wt)-.25 G(his in SunOS should be forthcoming in a future release.)192.31 437.4
+Q F0 2.5(2.7. K)87 461.4 R(ey)-.25 E(ed Files)-.1 E F1 .242(Generalized k)127
+477.6 R -.15(ey)-.1 G .242(ed \214les is an idea tak).15 F .241
+(en directly from ID)-.1 F 2.741(As)-.4 G .241
+(endmail \(albeit with a completely)368.606 477.6 R(dif)102 489.6 Q
+(ferent implementation\).)-.25 E(The)5 E 2.5(yc)-.15 G(an be useful on lar)
+239.63 489.6 Q(ge sites.)-.18 E -1.11(Ve)127 505.8 S
+(rsion 8 includes the follo)1.11 E(wing b)-.25 E(uilt-in map classes:)-.2 E
+33.72(dbm Support)102 522 R(for the ndbm\(3\) library)2.5 E(.)-.65 E 33.17
+(hash Support)102 538.2 R 1.229(for the `)3.729 F(`Hash')-.74 E 3.729('t)-.74 G
+1.229(ype from the ne)261.636 538.2 R 3.729(wB)-.25 G(erk)345.732 538.2 Q(ele)
+-.1 E 3.729(yd)-.15 G 1.229(b\(3\) library)383.641 538.2 R 6.23(.t)-.65 G 1.23
+(his library pro-)441.55 538.2 R 4.094(vides substantially better database sup\
+port than ndbm\(3\), including in-memory)156 550.2 R
+(caching, arbitrarily long k)156 562.2 Q -.15(ey)-.1 G 2.5(sa).15 G(nd v)279.89
+562.2 Q(alues, and better disk utilization.)-.25 E 31.51(btree Support)102
+578.4 R .547(for the `)3.047 F(`B-T)-.74 E(ree')-.35 E 3.047('t)-.74 G .547
+(ype from the ne)266.328 578.4 R 3.048(wB)-.25 G(erk)347.698 578.4 Q(ele)-.1 E
+3.048(yd)-.15 G .548(b\(3\) library)384.926 578.4 R 5.548(.B)-.65 G(-T)445.362
+578.4 Q .548(rees pro)-.35 F(vide)-.15 E .521(better clustering than Hashed \
+\214les if you are fetching lots of records that ha)156 590.4 R .821 -.15(ve s)
+-.2 H(imilar).15 E -.1(ke)156 602.4 S(ys, such as searching a dictionary for w)
+-.05 E(ords be)-.1 E(ginning with `)-.15 E(`detr')-.74 E('.)-.74 E 39.83
+(nis Support)102 618.6 R(for NIS \(a.k.a. YP\) maps.)2.5 E
+(NIS+ is not supported in this v)5 E(ersion.)-.15 E 34.83(host Support)102
+634.8 R(for DNS lookups.)2.5 E 19.84(dequote A)102 651 R -.74(``)2.642 G
+(pseudo-map').74 E 2.642('\()-.74 G .142(that is, once that does not ha)232.554
+651 R .442 -.15(ve a)-.2 H .442 -.15(ny ex).15 H .142(ternal data\) that allo)
+.15 F .142(ws a con-)-.25 F .099
+(\214guration \214le to break apart a quoted string in the address.)156 663 R
+.098(This is necessary primarily)5.098 F .726
+(for DECnet addresses, which often ha)156 675 R 1.026 -.15(ve q)-.2 H .726
+(uoted addresses that need to be unwrapped).15 F(on g)156 687 Q(ate)-.05 E -.1
+(wa)-.25 G(ys.).1 E EP
+%%Page: 5 5
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Changes in Sendmail V)72 60 Q(ersion 8)-1 E(5)499 60 Q
+2.5(2.8. Multi-W)87 96 R(ord Classes & Macr)-.75 E(os in Classes)-.18 E/F1 10
+/Times-Roman@0 SF(Classes can no)127 112.2 Q 2.5(wb)-.25 G 2.5(em)200.35 112.2
+S(ultiple w)215.07 112.2 Q 2.5(ords. F)-.1 F(or e)-.15 E(xample,)-.15 E
+(CShofmann.CS.Berk)142 128.4 Q(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(allo)102
+144.6 Q 2.395(ws you to match the entire string `)-.25 F(`hofmann.CS.Berk)-.74
+E(ele)-.1 E -.65(y.)-.15 G(EDU').65 E 4.894('u)-.74 G 2.394
+(sing the single construct)399.878 144.6 R -.74(``)102 156.6 S($=S').74 E('.)
+-.74 E(Class de\214nitions are no)127 172.8 Q 2.5(wa)-.25 G(llo)234.52 172.8 Q
+(wed to include macros \212 for e)-.25 E(xample:)-.15 E(Cw$k)142 189 Q(is le)
+102 205.2 Q -.05(ga)-.15 G(l.).05 E F0 2.5(2.9. IDENT)87 229.2 R(Pr)2.5 E
+(otocol Support)-.18 E F1 .633
+(The IDENT protocol as de\214ned in RFC 1413 [RFC1413] is supported.)127 245.4
+R(Ho)5.633 E(we)-.25 E -.15(ve)-.25 G 1.433 -.4(r, m).15 H(an).4 E 3.134(ys)
+-.15 G(ys-)491.78 245.4 Q .909(tems ha)102 257.4 R 1.209 -.15(ve a T)-.2 H .909
+(CP/IP b).15 F .908
+(ug that renders this useless, and the feature must be turned of)-.2 F 3.408
+(f. Roughly)-.25 F 3.408(,i)-.65 G(f)500.67 257.4 Q 8.538
+(one of these system recei)102 269.4 R -.15(ve)-.25 G 11.038(sa\231).15 G 8.539
+(No route to host\232 message \(ICMP message)280.568 269.4 R(ICMP_UNREA)102
+281.4 Q .829(CH_HOST\) on)-.4 F/F2 10/Times-Italic@0 SF(any)3.329 E F1 .828
+(connection, all connections to that host are closed.)3.329 F .828
+(Some \214re-)5.828 F -.1(wa)102 293.4 S .087
+(lls return this error if you try to connect to the IDENT port, so you can').1
+F 2.587(tr)-.18 G(ecei)408.889 293.4 Q .387 -.15(ve e)-.25 H .087
+(mail from these).15 F 1.712(hosts on these systems.)102 305.4 R(It')6.712 E
+4.212(sp)-.55 G 1.712(ossible that if the \214re)228.62 305.4 R -.1(wa)-.25 G
+1.712(ll used a more speci\214c message \(such as).1 F(ICMP_UNREA)102 317.4 Q
+(CH_PR)-.4 E -1.88 -.4(OT O)-.4 H 72.325(COL, ICMP_UNREA).4 F(CH_POR)-.4 E
+74.825(To)-.6 G(r)500.67 317.4 Q(ICMP_UNREA)102 329.4 Q(CH_NET_PR)-.4 E
+(OHIB\) it w)-.4 E(ould w)-.1 E(ork, b)-.1 E(ut this hasn')-.2 E 2.5(tb)-.18 G
+(een v)375.62 329.4 Q(eri\214ed.)-.15 E .678(IDENT protocol support cannot be \
+used on 4.3BSD, Apollo DomainOS, Apple A/UX, Con-)127 345.6 R -.15(vex)102
+357.6 S .949(OS, Data General DG/UX, HP-UX, Sequent Dynix, or Ultrix 4.x, x).15
+F/F3 10/Symbol SF<a3>3.449 E F1 3.449(3. It)3.449 F .949(seems to w)3.449 F
+.949(ork on)-.1 F
+(4.4BSD, IBM AIX 3.x, OSF/1, SGI IRIX, Solaris, SunOS, and Ultrix 4.4.)102
+369.6 Q F0 2.5(2.10. Separate)87 393.6 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 409.8 R -.15(ve)
+-.4 G .854(lope sender).15 F 3.354(,t)-.4 G .854(hese ha)420.978 409.8 R 1.154
+-.15(ve b)-.2 H .854(oth been).15 F .427
+(made visible; the $g macro is set to the en)102 421.8 R -.15(ve)-.4 G .428
+(lope sender during processing of mailer ar).15 F .428(gument v)-.18 F(ec-)-.15
+E(tors and the header sender during processing of headers.)102 433.8 Q .085
+(It is also possible to specify separate per)127 450 R .085(-mailer en)-.2 F
+-.15(ve)-.4 G .084(lope and header processing.).15 F .084(The Sender)5.084 F(-)
+-.2 E -.55(RW)102 462 S 1.085(Set and RecipientR).55 F 1.085(Wset ar)-.55 F
+1.085(guments for mailers can be speci\214ed as `)-.18 F(`en)-.74 E -.15(ve)-.4
+G(lope/header').15 E 3.585('t)-.74 G 3.585(og)478.595 462 S -2.15 -.25(iv e)
+492.18 462 T(dif)102 474 Q(ferent re)-.25 E(writings for en)-.25 E -.15(ve)-.4
+G(lope v).15 E(ersus header addresses.)-.15 E F0 2.5(2.11. Owner)87 498 R
+(-List Pr)-.37 E(opagates to En)-.18 E -.1(ve)-.4 G(lope).1 E F1 1.168
+(When an alias has an associated o)127 514.2 R(wner)-.25 E 1.168
+(-list name, that alias is used to change the en)-.2 F -.15(ve)-.4 G(lope).15 E
+(sender address.)102 526.2 Q(This will cause do)5 E
+(wnstream errors to be returned to that o)-.25 E(wner)-.25 E(.)-.55 E 1.813
+(Some people \214nd this confusing because the en)127 542.4 R -.15(ve)-.4 G
+1.813(lope sender is what appears in the \214rst).15 F -.74(``)102 554.4 S
+(From_').74 E 3.127('l)-.74 G .627(ine in UNIX messages \(that is, the line be)
+146.417 554.4 R .627(ginning `)-.15 F(`From<space>')-.74 E 3.127('i)-.74 G .627
+(nstead of `)424.797 554.4 R(`From:')-.74 E(';)-.74 E .502
+(the latter is the header from, which)102 566.4 R F2(does)3.002 E F1 .503
+(indicate the sender of the message\).)3.002 F .503(In pre)5.503 F .503
+(vious v)-.25 F(ersions,)-.15 E F2(sendmail)102 578.4 Q F1 .057(has tried to a)
+2.557 F -.2(vo)-.2 G .057(id changing the en).2 F -.15(ve)-.4 G .056
+(lope sender for back compatibility with UNIX con).15 F -.15(ve)-.4 G(n-).15 E
+.177(tion; at this point that back compatibility is creating too man)102 590.4
+R 2.678(yp)-.15 G .178(roblems, and it is necessary to mo)357.972 590.4 R -.15
+(ve)-.15 G(forw)102 602.4 Q(ard into the 1980s.)-.1 E F0 2.5(2.12. Command)87
+626.4 R(Line Flags)2.5 E F1(The)127 642.6 Q F0<ad42>2.5 E F1
+(\215ag has been added to pass in body type information.)2.5 E(The)127 658.8 Q
+F0<ad70>3.057 E F1 .557
+(\215ag has been added to pass in protocol information that w)3.057 F .557
+(as pre)-.1 F .556(viously passed in by)-.25 F(de\214ning the)102 670.8 Q F0
+($r)2.5 E F1(and)2.5 E F0($s)2.5 E F1(macros.)2.5 E(The)127 687 Q F0<ad58>2.6 E
+F1 .1(\215ag has been added to allo)2.6 F 2.6(wl)-.25 G .1
+(ogging of all protocol in and out of sendmail for deb)279.89 687 R(ug-)-.2 E
+2.732(ging. Y)102 699 R .232(ou can set \231\255X \214lename\232 and a complet\
+e transcript will be logged in that \214le.)-1.1 F .231(This gets big)5.231 F
+-.1(fa)102 711 S(st: the option is only for deb).1 E(ugging.)-.2 E EP
+%%Page: 6 6
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 294.65(6C)72 60 S(hanges in Sendmail V)378.87 60 Q
+(ersion 8)-1 E/F1 10/Times-Roman@0 SF(The)127 96 Q F0<ad71>4.006 E F1 1.507(\
+\215ag can limit limit a queue run to speci\214c recipients, senders, or queue\
+ ids using)4.006 F
+(\255qRsubstring, \255qSsubstring, or \255qIsubstring respecti)102 108 Q -.15
+(ve)-.25 G(ly).15 E(.)-.65 E F0 2.5(2.13. New)87 132 R(Con\214guration Line T)
+2.5 E(ypes)-.74 E F1 .674(The `T' \(T)127 148.2 R .674
+(rusted users\) con\214guration line has been deleted.)-.35 F .674
+(It will still be accepted b)5.674 F .674(ut will)-.2 F(be ignored.)102 160.2 Q
+(The `K' line has been added to declare database maps.)127 176.4 Q
+(The `V' line has been added to declare the con\214guration v)127 192.6 Q
+(ersion le)-.15 E -.15(ve)-.25 G(l.).15 E(The `M' \(mailer\) line tak)127 208.8
+Q(es a D= \214eld to specify e)-.1 E -.15(xe)-.15 G(cution directory).15 E(.)
+-.65 E F0 2.5(2.14. New)87 232.8 R(and Extended Options)2.5 E F1(Se)127 249 Q
+-.15(ve)-.25 G .9(ral ne).15 F 3.4(wo)-.25 G .9(ptions ha)184.8 249 R 1.2 -.15
+(ve b)-.2 H .9(een added, man).15 F 3.4(yt)-.15 G 3.4(os)314.89 249 S .9
+(upport ne)327.18 249 R 3.4(wf)-.25 G .9(eatures, others to allo)379.83 249 R
+3.4(wt)-.25 G(uning)481.22 249 Q(that w)102 261 Q(as pre)-.1 E(viously a)-.25 E
+-.25(va)-.2 G(ilable only by recompiling.).25 E(Brie\215y:)5 E 28.78(AT)102
+277.2 S .099(he alias \214le speci\214cation can no)144.11 277.2 R 2.599(wb)
+-.25 G 2.599(eal)286.654 277.2 S .099(ist of alias \214les.)303.512 277.2 R
+.098(Also, the con\214guration can spec-)5.099 F(ify a class of \214le.)138
+289.2 Q -.15(Fo)5 G 2.5(re).15 G(xample, to search the NIS aliases, use \231O)
+232.13 289.2 Q(Anis:mail.aliases\232.)-.35 E 31(bI)102 305.4 S
+(nsist on a minimum number of disk blocks.)141.33 305.4 Q 29.33(CD)102 321.6 S
+(eli)145.22 321.6 Q -.15(ve)-.25 G .24(ry checkpoint interv).15 F 2.74
+(al. Checkpoint)-.25 F .24(the queue \(to a)2.74 F -.2(vo)-.2 G .24
+(id duplicate deli).2 F -.15(ve)-.25 G .24(ries\) e).15 F -.15(ve)-.25 G .24
+(ry C).15 F(addresses.)138 333.6 Q 29.89(ED)102 349.8 S(ef)145.22 349.8 Q .712
+(ault error message.)-.1 F .711
+(This message \(or the contents of the indicated \214le\) are prepended)5.712 F
+(to error messages.)138 361.8 Q 28.78(GE)102 378 S .785(nable GECOS matching.)
+144.11 378 R .785(If you can')5.785 F 3.285<748c>-.18 G .786
+(nd a local user name and this option is enabled,)307.51 378 R .59
+(do a sequential scan of the passwd \214le to match ag)138 390 R .589
+(ainst full names.)-.05 F(Pre)5.589 E .589(viously a compile)-.25 F(option.)138
+402 Q 31(hM)102 418.2 S(aximum hop count.)146.89 418.2 Q(Pre)5 E
+(viously this w)-.25 E(as compiled in.)-.1 E 32.67(IT)102 434.4 S
+(his option has been e)144.11 434.4 Q(xtended to allo)-.15 E 2.5(ws)-.25 G
+(etting of resolv)300.64 434.4 Q(er parameters.)-.15 E 33.22(jS)102 450.6 S
+(end errors in MIME-encapsulated format.)143.56 450.6 Q 32.11(JF)102 466.8 S
+(orw)143.41 466.8 Q(ard \214le path.)-.1 E(Where to search for .forw)5 E
+(ard \214les \212 def)-.1 E(aults to $HOME/.forw)-.1 E(ard.)-.1 E 31(kC)102 483
+S .05(onnection cache size.)144.67 483 R .05
+(The total number of connections that will be k)5.05 F .05(ept open at an)-.1 F
+2.55(yt)-.15 G(ime.)486.5 483 Q 28.78(KC)102 499.2 S 1.395
+(onnection cache lifetime.)144.67 499.2 R 1.395(The amount of time an)6.395 F
+3.895(yc)-.15 G 1.394(onnection will be permitted to sit)364.53 499.2 R(idle.)
+138 511.2 Q 33.22(lE)102 527.4 S .333(nable Errors-T)144.11 527.4 R .333
+(o: header)-.8 F 5.334(.T)-.55 G .334
+(hese headers violate RFC 1123; this option is included to pro-)252.89 527.4 R
+(vide back compatibility with old v)138 539.4 Q(ersions of sendmail.)-.15 E
+28.78(OI)102 555.6 S(ncoming daemon options \(e.g., use alternate SMTP port\).)
+141.33 555.6 Q 31(pP)102 571.8 S(ri)143.56 571.8 Q -.25(va)-.25 G .3 -.15(cy o)
+.25 H 2.5(ptions. These).15 F(can be used to mak)2.5 E 2.5(ey)-.1 G
+(our SMTP serv)322.22 571.8 Q(er less friendly)-.15 E(.)-.65 E 32.67(rT)102 588
+S .67(his option has been e)144.11 588 R .67(xtended to allo)-.15 F 3.17<778c>
+-.25 G .67(ner grained control o)307 588 R -.15(ve)-.15 G 3.17(rt).15 G 3.17
+(imeouts. F)411.02 588 R .67(or e)-.15 F(xample,)-.15 E
+(you can set the timeout for SMTP commands indi)138 600 Q(vidually)-.25 E(.)
+-.65 E 29.33(RD)102 616.2 S(on')145.22 616.2 Q 11.797(tp)-.18 G 9.297
+(rune route-addrs.)177.947 616.2 R(Normally)269.851 616.2 Q 11.797(,i)-.65 G
+11.797(fv)324.608 616.2 S 9.297(ersion 8 sees an address lik)344.585 616.2 R(e)
+-.1 E 1.256("<@hostA,@hostB:user@hostC>, sendmail will try to strip of)138
+628.2 R 3.755(fa)-.25 G 3.755(sm)406.48 628.2 S 1.255(uch as it can \(up to)
+421.905 628.2 R(user@hostC\) as suggested by RFC 1123.)138 640.2 Q
+(This option disables that beha)5 E(viour)-.2 E(.)-.55 E 29.89(TT)102 656.4 S
+1.485(he \231Return T)144.11 656.4 R 3.985(oS)-.8 G 1.485
+(ender\232 timeout has been e)213.035 656.4 R 1.485(xtended to allo)-.15 F
+3.986(ws)-.25 G 1.486(peci\214cation of a w)399.942 656.4 R(arning)-.1 E .789
+(message interv)138 668.4 R .789
+(al, typically something on the order of four hours.)-.25 F .788
+(If a message cannot be)5.788 F(deli)138 680.4 Q -.15(ve)-.25 G 1.245
+(red in that interv).15 F 1.245(al, a w)-.25 F 1.245
+(arning message is sent back to the sender b)-.1 F 1.246(ut the message)-.2 F
+(continues to be tried.)138 692.4 Q 28.78(UU)102 708.6 S(ser database spec.)
+145.22 708.6 Q(This is still e)5 E(xperimental.)-.15 E EP
+%%Page: 7 7
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Changes in Sendmail V)72 60 Q(ersion 8)-1 E(7)499 60 Q
+/F1 10/Times-Roman@0 SF 28.78(VF)102 96 S .758(allback `)143.41 96 R(`MX')-.74
+E 3.258('h)-.74 G 3.258(ost. This)211.756 96 R .757
+(can be thought of as an MX host that applies to all addresses)3.258 F
+(that has a v)138 108 Q(ery high preference v)-.15 E
+(alue \(that is, use it only if e)-.25 E -.15(ve)-.25 G(rything else f).15 E
+(ails\).)-.1 E 28.78(wI)102 124.2 S 3.066(fs)141.33 124.2 S .566(et, assume th\
+at if you are the best MX host for a host, you should send directly to that)
+151.616 124.2 R 3.213(host. This)138 136.2 R .713
+(is intended for compatibility with UIUC sendmail, and may ha)3.213 F 1.013
+-.15(ve s)-.2 H .712(ome use on).15 F(\214re)138 148.2 Q -.1(wa)-.25 G(lls.).1
+E 31(7D)102 164.4 S 2.758(on)145.22 164.4 S .258(ot run eight bit clean.)
+157.978 164.4 R -.7(Te)5.258 G(chnically).7 E 2.758(,y)-.65 G .258(ou ha)
+305.656 164.4 R .558 -.15(ve t)-.2 H 2.758(oa).15 G .259
+(ssert this option to be RFC 821 com-)354.68 164.4 R(patible.)138 176.4 Q F0
+2.5(2.15. New)87 200.4 R(Mailer De\214nitions)2.5 E F1 21.75(L= Set)102 216.6 R
+.93(the allo)3.43 F -.1(wa)-.25 G .93(ble line length.).1 F .93
+(In V5, the L mailer \215ag implied a line length limit of 990)5.93 F
+(characters; this is no)138 228.6 Q 2.5(ws)-.25 G(ettable to an arbitrary v)
+233.29 228.6 Q(alue.)-.25 E 17.86(F=a T)102 244.8 R(ry to use ESMTP)-.35 E 5
+(.I)-1.11 G 2.5(tw)222.65 244.8 S(ill f)235.15 244.8 Q
+(all back to SMTP if the initial EHLO pack)-.1 E(et is rejected.)-.1 E 17.3
+(F=b Ensure)102 261 R 2.5(ab)2.5 G(lank line at the end of messages.)180.21 261
+Q(Useful on the *\214le* mailer)5 E(.)-.55 E 17.86(F=c Strip)102 277.2 R .68(a\
+ll comments from addresses; this should only be used as a last resort when dea\
+ling)3.18 F(with crank)138 289.2 Q 2.5(ym)-.15 G(ailers.)195.62 289.2 Q 17.3
+(F=g Ne)102 305.4 R -.15(ve)-.25 G 2.88(ru).15 G .38
+(se the null sender as the en)169.91 305.4 R -.15(ve)-.4 G .379(lope sender).15
+F 2.879(,e)-.4 G -.15(ve)343.645 305.4 S 2.879(nw).15 G .379(hen running SMTP)
+368.034 305.4 R 5.379(.T)-1.11 G .379(his violates)458.341 305.4 R(RFC 1123.)
+138 317.4 Q 17.3(F=7 Strip)102 333.6 R(all output to this mailer to 7 bits.)2.5
+E 16.19(F=L Used)102 349.8 R .198
+(to set the line limit to 990 bytes for SMTP compatibility)2.697 F 5.198(.I)
+-.65 G 2.698(tn)398.622 349.8 S .698 -.25(ow d)409.1 349.8 T .198
+(oes that only if the).25 F(L= k)138 361.8 Q -.15(ey)-.1 G
+(letter is not speci\214ed.).15 E
+(This \215ag is obsolete and should not be used.)5 E F0 2.5(2.16. New)87 385.8
+R(or Changed Pr)2.5 E(e-De\214ned Macr)-.18 E(os)-.18 E F1 23.5($k UUCP)102 402
+R(node name from uname\(2\).)2.5 E 20.72($m Domain)102 418.2 R
+(part of our full hostname.)2.5 E 23.5($_ RFC)102 434.4 R(1413-pro)2.5 E
+(vided sender address.)-.15 E 21.28($w Pre)102 450.6 R .148(viously w)-.25 F
+.148(as sometimes the full domain name, sometimes just the \214rst w)-.1 F
+2.647(ord. No)-.1 F 2.647(wg)-.25 G(uar)488.1 450.6 Q(-)-.2 E
+(anteed to be the \214rst w)138 462.6 Q
+(ord of the domain name \(i.e., the host name\).)-.1 E 25.72($j Pre)102 478.8 R
+.193(viously had to be de\214ned \212 it is no)-.25 F 2.693(wp)-.25 G .194
+(rede\214ned to be the full domain name, if that can)310.067 478.8 R
+(be determined.)138 490.8 Q(That is, it is equi)5 E -.25(va)-.25 G(lent to $w)
+.25 E(.$m.)-.65 E F0 2.5(2.17. New)87 514.8 R(and Changed Classes)2.5 E F1
+17.86($=k Initialized)102 531 R(to contain $k.)2.5 E 15.64($=w No)102 547.2 R
+3.069(wi)-.25 G .569
+(ncludes \231[1.2.3.4]\232 \(where 1.2.3.4 is your IP address\) to allo)163.039
+547.2 R 3.068(wt)-.25 G .568(he con\214guration \214le)422.314 547.2 R
+(to recognize your o)138 559.2 Q(wn IP address.)-.25 E F0 2.5(2.18. New)87
+583.2 R(Rewriting T)2.5 E(ok)-.92 E(ens)-.1 E F1(The)127 599.4 Q F0($&)3.25 E
+F1 .75(construct has been adopted from ID)3.25 F 3.25(At)-.4 G 3.25(od)322
+599.4 S .75(efer macro e)335.25 599.4 R -.25(va)-.25 G 3.25(luation. Normally)
+.25 F 3.25(,m)-.65 G(acros)482.9 599.4 Q .476
+(in rulesets are bound when the rule is \214rst parsed during startup.)102
+611.4 R .476(Some macros change during pro-)5.476 F .046
+(cessing and are uninteresting during startup.)102 623.4 R(Ho)5.046 E(we)-.25 E
+-.15(ve)-.25 G .846 -.4(r, t).15 H .047
+(hat macro can be referenced using \231$&x\232 to).4 F(defer the e)102 635.4 Q
+-.25(va)-.25 G(ulation of $x until the rule is processed.).25 E(The tok)127
+651.6 Q(ens)-.1 E F0($\()2.5 E F1(and)2.5 E F0($\))2.5 E F1(ha)2.5 E .3 -.15
+(ve b)-.2 H(een added to allo).15 E 2.5(ws)-.25 G(peci\214cation of map re)
+319.59 651.6 Q(writing.)-.25 E -1.11(Ve)127 667.8 S 1.499(rsion 8 allo)1.11 F
+(ws)-.25 E F0($@)3.999 E F1 1.499
+(on the Left Hand Side of an `R' line to match zero tok)3.999 F 3.998
+(ens. This)-.1 F(is)3.998 E(intended to be used to match the null input.)102
+679.8 Q EP
+%%Page: 8 8
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 294.65(8C)72 60 S(hanges in Sendmail V)378.87 60 Q
+(ersion 8)-1 E 2.5(2.19. Bigger)87 96 R(Defaults)2.5 E/F1 10/Times-Roman@0 SF
+-1.11(Ve)127 112.2 S 1.283(rsion 8 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 124.2 Q
+(ed for sendmail')-.15 E 2.5(sd)-.55 G(edicated use in future releases.)202.66
+124.2 Q(The total number of MX records that can be used has been raised to 20.)
+127 140.4 Q .335(The number of queued messages that can be handled at one time\
+ has been raised from 600 to)127 156.6 R(1000.)102 168.6 Q F0 2.5(2.20. Differ)
+87 192.6 R(ent Default T)-.18 E(uning P)-.92 E(arameters)-.1 E F1 -1.11(Ve)127
+208.8 S .8(rsion 8 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 208.8 R .712(recipients more important than the size of t\
+he message \(for small messages\).)102 220.8 R .712(This is reasonable if)5.712
+F(you are connected with reasonably f)102 232.8 Q(ast links.)-.1 E F0 2.5
+(2.21. A)87 256.8 R(uto-Quoting in Addr)-.5 E(esses)-.18 E F1(Pre)127 273 Q
+(viously)-.25 E 3.2(,t)-.65 G .701(he `)177.36 273 R .701
+(`Full Name <email address>')-.74 F 3.201('s)-.74 G .701(yntax w)322.025 273 R
+.701(ould generate incorrect protocol out-)-.1 F .006(put if `)102 285 R .006
+(`Full Name')-.74 F 2.506('h)-.74 G .006(ad special characters such as dot.)
+187.754 285 R .005(This v)5.006 F .005(ersion puts quotes around such names.)
+-.15 F F0 2.5(2.22. Symbolic)87 309 R(Names On Err)2.5 E(or Mailer)-.18 E F1
+(Se)127 325.2 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 5(.F)-.55 G(or e)428.96
+325.2 Q(xample:)-.15 E($#error $@NOHOST $: Host unkno)142 341.4 Q(wn)-.25 E
+(Prints the indicated message and sets the e)102 357.6 Q(xit status of)-.15 E
+/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1(to)2.5 E/F3 9/Times-Roman@0 SF
+(EX_NOHOST)2.5 E F1(.)A F0 2.5(2.23. New)87 381.6 R(Built-In Mailers)2.5 E F1
+-1 -.8(Tw o)127 397.8 T(ne)3.901 E 3.101(wm)-.25 G .601(ailers, *\214le* and *\
+include*, are included to de\214ne options when mailing to a \214le)174.822
+397.8 R(or a :include: \214le respecti)102 409.8 Q -.15(ve)-.25 G(ly).15 E 5
+(.P)-.65 G(re)232.88 409.8 Q(viously these were o)-.25 E -.15(ve)-.15 G
+(rloaded on the local mailer).15 E(.)-.55 E F0 2.5(2.24. SMTP)87 433.8 R
+(VRFY Doesn't Expand)2.5 E F1(Pre)127 450 Q 1.438(vious v)-.25 F 1.438
+(ersions of sendmail treated VRFY and EXPN the same.)-.15 F 1.437(In this v)
+6.437 F 1.437(ersion, VRFY)-.15 F(doesn')102 462 Q 2.5(te)-.18 G
+(xpand aliases or follo)138.05 462 Q 2.5(w.)-.25 G(forw)235.84 462 Q
+(ard \214les.)-.1 E .663(As an optimization, if you run with your def)127 478.2
+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 478.2 R 1.09
+(command will also not chase aliases and .forw)102 490.2 R 1.09(ard \214les.)
+-.1 F 1.09(It will chase them when it processes the)6.09 F 2.5(queue. This)102
+502.2 R(speeds up RCPT processing.)2.5 E F0 2.5(2.25. [IPC])87 526.2 R
+(Mailers Allo)2.5 E 2.5(wM)-.1 G(ultiple Hosts)210.49 526.2 Q F1 .099
+(When an address resolv)127 542.4 R .099(es to a mailer that has `)-.15 F
+(`[IPC]')-.74 E 2.599('a)-.74 G 2.6(si)353.52 542.4 S .1(ts `)362.79 542.4 R
+(`P)-.74 E(ath')-.15 E .1(', the $@ part \(host name\))-.74 F .138
+(can be a colon-separated list of hosts instead of a single hostname.)102 554.4
+R .137(This asks sendmail to search the)5.137 F .16
+(list for the \214rst entry that is a)102 566.4 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 578.4 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 590.4 Q(vidual items.)-.25 E
+F0 2.5(2.26. Aliases)87 614.4 R(Extended)2.5 E F1 .298
+(The implementation has been mer)127 630.6 R .298(ged with maps.)-.18 F .299
+(Among other things, this supports multiple)5.298 F
+(alias \214les and NIS-based aliases.)102 642.6 Q -.15(Fo)5 G 2.5(re).15 G
+(xample:)258.34 642.6 Q -.35(OA)142 658.8 S(/etc/aliases,nis:mail.aliases).35 E
+(will search \214rst the local database \231/etc/aliases\232 follo)102 675 Q
+(wed by the NIS map)-.25 E EP
+%%Page: 9 9
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Changes in Sendmail V)72 60 Q(ersion 8)-1 E(9)499 60 Q
+2.5(2.27. P)87 96 R(ortability and Security Enhancements)-.2 E/F1 10
+/Times-Roman@0 SF 2.5(An)127 112.2 S(umber of internal changes ha)141.72 112.2
+Q .3 -.15(ve b)-.2 H(een made to enhance portability).15 E(.)-.65 E(Se)127
+128.4 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 .46
+(In particular)127 144.6 R 2.96(,t)-.4 G .46(he permissions required for .forw)
+184.45 144.6 R .46(ard and :include: \214les ha)-.1 F .76 -.15(ve b)-.2 H .46
+(een tightened up).15 F(considerably)102 156.6 Q 5.182(.V)-.65 G 2.683(5w)
+167.352 156.6 S .183(ould pretty much read an)182.155 156.6 R 2.683<798c>-.15 G
+.183(le it could get to as root, which e)295.96 156.6 R .183(xposed some secu-)
+-.15 F 1.02(rity holes.)102 168.6 R 1.02
+(V8 insists that all directories leading up to the .forw)6.02 F 1.02
+(ard or :include: \214le be searchable)-.1 F .334
+(\("x" permission\) by the controlling user" \(de\214ned belo)102 180.6 R .335
+(w\), that the \214le itself be readable by the con-)-.25 F(trolling user)102
+192.6 Q 2.5(,a)-.4 G(nd that .forw)159.65 192.6 Q(ard \214les be o)-.1 E
+(wned by the user who is being forw)-.25 E(arded to or root.)-.1 E .565
+(The "controlling user" is the user on whose behalf the mail is being deli)127
+208.8 R -.15(ve)-.25 G 3.065(red. F).15 F .565(or e)-.15 F(xample,)-.15 E .459
+(if you mail to "user1" then the controlling user for ~user1/.forw)102 220.8 R
+.46(ard and an)-.1 F 2.96(ym)-.15 G .46(ailers in)416.94 220.8 R -.2(vo)-.4 G
+-.1(ke).2 G 2.96(db).1 G 2.96(yt)481.04 220.8 S(hat)491.78 220.8 Q(.forw)102
+232.8 Q(ard \214le, including :include: \214les.)-.1 E(Pre)127 249 Q(viously)
+-.25 E 2.816(,a)-.65 G -.15(ny)178.636 249 S .316
+(one who had a home directory could create a .forw).15 F .316(ard could forw)
+-.1 F .316(ard to a pro-)-.1 F 2.965(gram. No)102 261 R 1.765 -.65(w, s)-.25 H
+.466(endmail checks to mak).65 F 2.966(es)-.1 G .466(ure that the)262.934 261 R
+2.966(yh)-.15 G -2.25 -.2(av e)321.672 261 T .466(an "appro)3.166 F -.15(ve)
+-.15 G 2.966(ds).15 G .466(hell", that is, a shell listed)398.42 261 R
+(in the /etc/shells \214le.)102 273 Q F0 2.5(2.28. Miscellaneous)87 297 R
+(Fixes and Enhancements)2.5 E F1 4.03(An)127 313.2 S 1.53(umber of small b)
+143.25 313.2 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 313.2 R(comments ha)102
+325.2 Q .3 -.15(ve b)-.2 H(een \214x).15 E(ed.)-.15 E 1.552(The \214x)127 341.4
+R 1.552(ed size limit on header lines \(such as \231T)-.15 F 1.553
+(o:\232 and \231Cc:\232\) has been eliminated; those)-.8 F -.2(bu)102 353.4 S
+-.25(ff).2 G(ers are dynamically allocated no).25 E -.65(w.)-.25 G .289(Sendma\
+il writes a /etc/sendmail.pid \214le with the current process id and the curre\
+nt in)127 369.6 R -.2(vo)-.4 G(cation).2 E(\215ags.)102 381.6 Q -1 -.8(Tw o)127
+397.8 T .218
+(people using the same program \(e.g., submit\) are considered "dif)3.518 F
+.219(ferent" so that duplicate)-.25 F .508(elimination doesn')102 409.8 R 3.008
+(td)-.18 G .508(elete one of them.)187.836 409.8 R -.15(Fo)5.508 G 3.008(re).15
+G .508(xample, tw)287.556 409.8 R 3.008(op)-.1 G .508(eople forw)345.412 409.8
+R .508(arding their email to |submit)-.1 F(will be treated as tw)102 421.8 Q
+2.5(or)-.1 G(ecipients.)193.27 421.8 Q .721(The mailstats program prints maile\
+r names and gets the location of the sendmail.st \214le from)127 438 R
+(/etc/sendmail.cf.)102 450 Q(Man)127 466.2 Q 2.5(ym)-.15 G(inor b)160.46 466.2
+Q(ugs ha)-.2 E .3 -.15(ve b)-.2 H(een \214x).15 E
+(ed, such as handling of backslashes inside of quotes.)-.15 E 2.5(Ah)127 482.4
+S(ook has been added to allo)141.72 482.4 Q 2.5(wr)-.25 G -.25(ew)260.89 482.4
+S(riting of local addresses after aliasing.).25 E F0 2.5(3. FUTURE)72 506.4 R
+-.1(WO)2.5 G(RK).1 E F1 1.719(The pre)112 522.6 R 1.719
+(vious section describes)-.25 F/F2 10/Times-Italic@0 SF(sendmail)4.219 E F1
+1.719(as of v)4.219 F 1.719(ersion 8.6.6.)-.15 F 1.718
+(There is still much to be done.)6.719 F(Some high points are described belo)87
+534.6 Q 3.8 -.65(w. T)-.25 H(his list is by no means e).65 E(xhausti)-.15 E
+-.15(ve)-.25 G(.).15 E F0 2.5(3.1. Full)87 558.6 R(MIME Support)2.5 E F1
+(Currently)127 574.8 Q F2(sendmail)3.305 E F1 .805(only supports se)3.305 F
+-.15(ve)-.25 G 3.305(nb).15 G .805(it MIME messages.)297.005 574.8 R .806
+(Although it can pass eight bit)5.805 F .371(MIME messages, it cannot adv)102
+586.8 R .371(ertise that f)-.15 F .37
+(act because the standards say that the mail agent must be)-.1 F .26
+(able to do 8- to 7-bit con)102 598.8 R -.15(ve)-.4 G .26(rsion to ha).15 F
+.561 -.15(ve f)-.2 H .261(ull 8-bit support.).15 F .261(This requires f)5.261 F
+.261(ar more e)-.1 F(xtensi)-.15 E .561 -.15(ve m)-.25 H(odi\214-).15 E
+(cation of the message body than is currently supported.)102 610.8 Q .464
+(The best w)127 627 R .464(ay to do this w)-.1 F .463
+(ould be to support the general concept of an e)-.1 F .463(xternal `)-.15 F
+.463(`message \214l-)-.74 F(ter')102 639 Q 3.319('t)-.74 G .819
+(hat could do arbitrary modi\214cations of the message.)124.569 639 R .819
+(This w)5.819 F .82(ould allo)-.1 F 3.32(wM)-.25 G .82(IME con)427.37 639 R
+-.15(ve)-.4 G .82(rsion as).15 F .63
+(well as such things as automatic encryption of messages sent o)102 651 R -.15
+(ve)-.15 G 3.129(re).15 G .629(xternal links.)379.264 651 R .629
+(This is probably)5.629 F(an e)102 663 Q(xtremely non-tri)-.15 E(vial change.)
+-.25 E F0 2.5(3.2. Ser)87 687 R(vice Switch Abstraction)-.1 E F1 .369(Most mod\
+ern systems include some concept of a \231service switch\232 \212 for e)127
+703.2 R .37(xample, to look up)-.15 F .984
+(host names you can try DNS, NIS, NIS+, te)102 715.2 R .984
+(xt tables, NetInfo, or other services in some arbitrary)-.15 F EP
+%%Page: 10 10
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 287.15(10 Changes)72 60 R(in Sendmail V)2.5 E(ersion 8)
+-1 E/F1 10/Times-Roman@0 SF(order)102 96 Q 5.174(.T)-.55 G .174
+(his is currently v)136.334 96 R .174(ery clumsy in)-.15 F/F2 10/Times-Italic@0
+SF(sendmail)2.674 E F1 2.674(,w)C .174
+(ith only limited control of the services pro)309.612 96 R(vided.)-.15 E F0 2.5
+(3.3. Mor)87 120 R 2.5(eC)-.18 G(ontr)139.86 120 Q(ol of Local Addr)-.18 E
+(esses)-.18 E F1 .943(Currently some addresses are declared as \231local\232 a\
+nd are handled specially \212 for e)127 136.2 R(xample,)-.15 E(the)102 148.2 Q
+3.455(ym)-.15 G .955(ay ha)130.305 148.2 R 1.255 -.15(ve .)-.2 H(forw).15 E
+.956(ard \214les, may be translated into program calls or \214le deli)-.1 F
+-.15(ve)-.25 G .956(ries, and so forth.).15 F .311(These should be brok)102
+160.2 R .311(en out into separate \215ags to allo)-.1 F 2.811(wt)-.25 G .31
+(he local system administrator to ha)330.29 160.2 R .61 -.15(ve m)-.2 H(ore).15
+E(\214ne-grained control o)102 172.2 Q -.15(ve)-.15 G 2.5(ro).15 G(perations.)
+208.62 172.2 Q F0 2.5(3.4. Mor)87 196.2 R 2.5(eR)-.18 G(un-T)139.86 196.2 Q
+(ime Con\214guration Options)-.18 E F1 .016(There are man)127 212.4 R 2.516(yo)
+-.15 G .016(ptions that are con\214gured at compile time, such as the method o\
+f \214le locking)197.148 212.4 R .719
+(and the use of the IDENT protocol [RFC1413].)102 224.4 R .719
+(These should be transfered to run time by adding)5.719 F(ne)102 236.4 Q 2.5
+(wo)-.25 G(ptions.)125.91 236.4 Q(Similarly)127 252.6 Q 3.413(,s)-.65 G .913
+(ome options are currently o)173.383 252.6 R -.15(ve)-.15 G .913
+(rloaded, that is, a single option controls more than).15 F(one thing.)102
+264.6 Q(These should probably be brok)5 E(en out into separate options.)-.1 E
+(This implies that options will change from single characters to w)127 280.8 Q
+(ords.)-.1 E F0 2.5(3.5. Mor)87 304.8 R 2.5(eC)-.18 G(on\214guration Contr)
+139.86 304.8 Q(ol Ov)-.18 E(er Err)-.1 E(ors)-.18 E F1(Currently)127 321 Q
+3.649(,t)-.65 G 1.148
+(he con\214guration \214le can generate an error message during parsing.)
+173.609 321 R(Ho)6.148 E(we)-.25 E -.15(ve)-.25 G 1.948 -.4(r, i).15 H(t).4 E
+.569(cannot tweak other operations, such as issuing a w)102 333 R .57
+(arning message to the system postmaster)-.1 F 5.57(.S)-.55 G(imi-)487.33 333 Q
+(larly)102 345 Q 2.558(,s)-.65 G .057
+(ome errors should not be triggered if the)128.628 345 R 2.557(ya)-.15 G .057
+(re in aliases during an alias \214le reb)302.237 345 R .057(uild, b)-.2 F .057
+(ut should)-.2 F(be triggered if that alias is actually used.)102 357 Q F0 2.5
+(3.6. Long)87 381 R -.92(Te)2.5 G(rm Host State).92 E F1(Currently)127 397.2 Q
+(,)-.65 E F2(sendmail)3.731 E F1 1.231
+(only remembers host status during a single queue run.)3.731 F 1.232
+(This should be)6.232 F(con)102 409.2 Q -.15(ve)-.4 G .492(rted to long term s\
+tatus stored on disk so it can be shared between instantiations of).15 F F2
+(sendmail)2.991 E F1(.)A .866(Entries will ha)102 421.2 R 1.167 -.15(ve t)-.2 H
+3.367(ob).15 G 3.367(et)190.666 421.2 S .867(imestamped so the)201.253 421.2 R
+3.367(yc)-.15 G .867(an time out.)290.084 421.2 R .867(This will allo)5.867 F
+(w)-.25 E F2(sendmail)3.367 E F1 .867(to implement)3.367 F -.15(ex)102 433.2 S
+(ponential back).15 E(of)-.1 E 2.5(fo)-.25 G 2.5(nq)188.7 433.2 S
+(ueue runs on a per)201.2 433.2 Q(-host basis.)-.2 E F0 2.5(3.7. Connection)87
+457.2 R(Contr)2.5 E(ol)-.18 E F1 .819(Modern netw)127 473.4 R .819(orks ha)-.1
+F 1.119 -.15(ve d)-.2 H(if).15 E .819(ferent types of connecti)-.25 F .818
+(vity than the past.)-.25 F .818(In particular)5.818 F 3.318(,t)-.4 G .818
+(he rising)468.462 473.4 R .636
+(prominence of dialup IP has created certain challenges for automated serv)102
+485.4 R 3.136(ers. It)-.15 F .636(is not uncommon)3.136 F .732(to try to mak)
+102 497.4 R 3.232(eac)-.1 G .732(onnection to a host and ha)175.27 497.4 R
+1.032 -.15(ve i)-.2 H 3.232(tf).15 G .732(ail, e)307.984 497.4 R -.15(ve)-.25 G
+3.232(nt).15 G .732(hough if you tried ag)348.208 497.4 R .732(ain it w)-.05 F
+.731(ould suc-)-.1 F 2.5(ceed. The)102 509.4 R
+(connection management could be a bit cle)2.5 E -.15(ve)-.25 G
+(rer to try to adapt to such situations.).15 E F0 2.5(3.8. Other)87 533.4 R
+(Caching)2.5 E F1 .074(When you do an MX record lookup, the name serv)127 549.6
+R .075(er automatically returns the IP addresses of)-.15 F .518
+(the associated MX serv)102 561.6 R 3.018(ers. This)-.15 F .518
+(information is currently ignored, and another query is done to get)3.018 F
+(this information.)102 573.6 Q(It should be cached to a)5 E -.2(vo)-.2 G(id e)
+.2 E(xcess name serv)-.15 E(er traf)-.15 E(\214c.)-.25 E F0 2.5(4. REFERENCES)
+72 597.6 R F1([Allman83a])87 613.8 Q .137(\231Sendmail \212 An Internetw)123
+625.8 R .137(ork Mail Router)-.1 F 4.037 -.7(.\232 E)-.55 H 2.638(.A).7 G 2.638
+(llman. In)327.58 625.8 R F2 .138(Unix Pr)2.638 F -.1(og)-.45 G -.15(ra).1 G
+(mmer).15 E(s')-.1 E 2.638(sM)-.4 G(anual,)463.582 625.8 Q F1(4.2)2.638 E(Berk)
+123 637.8 Q(ele)-.1 E 2.5(yS)-.15 G(oftw)166.91 637.8 Q(are Distrib)-.1 E
+(ution, v)-.2 E(olume 2C.)-.2 E(August 1983.)5 E([Allman83b])87 654 Q .384
+(\231Mail Systems and Addressing in 4.2BSD.)123 666 R 5.384<9a45>-.7 G 2.884
+(.A)311.544 666 S .383(llman In)324.148 666 R F2 .383(UNICOM Confer)2.883 F
+.383(ence Pr)-.37 F(oceedings.)-.45 E F1(San Die)123 678 Q(go, California.)-.15
+E(January 1983.)5 E([Allman&Amos85])87 694.2 Q -.74(``)123 706.2 S 1.145
+(Sendmail Re).74 F(visited.)-.25 E 5.125 -.74('' E)-.7 H 3.645(.A).74 G 1.145
+(llman and M. Amos.)241.215 706.2 R(In)6.145 E F2 1.145
+(Usenix Summer 1985 Confer)3.645 F 1.145(ence Pr)-.37 F(o-)-.45 E(ceedings.)123
+718.2 Q F1(Portland, Ore)5 E 2.5(gon. June)-.15 F(1985.)2.5 E EP
+%%Page: 11 11
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Changes in Sendmail V)72 60 Q(ersion 8)-1 E(11)494 60 Q
+/F1 10/Times-Roman@0 SF([ID)87 96 Q(A87])-.4 E/F2 10/Times-Italic@0 SF(Electr)
+1.97 E .983(onic Mail Addr)-.45 F .983(essing in Theory and Pr)-.37 F .982
+(actice with the ID)-.15 F 3.482(AS)-.35 G .982(endmail Enhancement Kit)398.156
+96 R .563(\(or The P)123 108 R(ostmaster')-.8 E 3.063(sL)-.4 G .563(ast W)
+215.989 108 R .564(ill and T)-.55 F(estament\).)-.92 E F1 .564(Lennart Lo)5.564
+F -.5(..)359.828 102 S 3.064(vstrand. Department)364.828 108 R .564
+(of Computer)3.064 F 1.267(and Information Science, Uni)123 120 R -.15(ve)-.25
+G 1.267(rsity of Link).15 F(o)-.1 E -.5(..)306.585 114 S 1.266
+(ping, Sweden, Report no. LiTH-ID)311.585 120 R(A-Ex-8715.)-.4 E(May 1987.)123
+132 Q([RFC821])87 148.2 Q F2(Simple Mail T)123 160.2 Q -.15(ra)-.55 G
+(nsport Pr).15 E(otocol.)-.45 E F1(J. Postel.)5 E(August 1982.)5 E([RFC1123])87
+176.4 Q F2(Requir)123 188.4 Q .163
+(ements for Internet Hosts \212 Application and Support.)-.37 F F1 .164
+(Internet Engineering T)5.164 F .164(ask F)-.8 F(orce,)-.15 E
+(R. Braden, Editor)123 200.4 Q 5(.O)-.55 G(ctober 1989.)207.72 200.4 Q
+([RFC1344])87 216.6 Q F2(Implications of MIME for Internet Mail Gate)123 228.6
+Q(ways.)-.15 E F1(N. Borenstein.)5 E(June 1992.)5 E([RFC1413])87 244.8 Q F2
+(Identi\214cation Pr)123 256.8 Q(otocol.)-.45 E F1(M. St. Johns.)5 E
+(February 1993.)5 E([RFC1425])87 273 Q F2 2.352(SMTP Service Extensions.)123
+285 R F1 2.352(J. Klensin, N. Freed, M. Rose, E. Stef)7.352 F 2.351
+(ferud, and D. Crock)-.25 F(er)-.1 E(.)-.55 E(February 1993.)123 297 Q
+([RFC1426])87 313.2 Q F2 .12(SMTP Service Extension for 8bit-MIMEtr)123 325.2 R
+(ansport.)-.15 E F1 .12(J. Klensin, N. Freed, M. Rose, E. Stef)5.12 F(ferud,)
+-.25 E(and D. Crock)123 337.2 Q(er)-.1 E 5(.F)-.55 G(ebruary 1993.)196.78 337.2
+Q([RFC1427])87 353.4 Q F2 .813(SMTP Service Extension for Messa)123 365.4 R
+1.013 -.1(ge S)-.1 H .813(ize Declar).1 F(ation.)-.15 E F1 .813
+(J. Klensin, N. Freed, and K. Moore.)5.813 F(February 1993.)123 377.4 Q
+([RFC1521])87 393.6 Q F2 2.033
+(MIME \(Multipurpose Internet Mail Extensions\) P)123 405.6 R 2.033
+(art One: Mec)-.8 F 2.033(hanisms for Specifying and)-.15 F .933
+(Describing the F)123 417.6 R .933(ormat of Internet Messa)-1.05 F 1.133 -.1
+(ge B)-.1 H(odies.).1 E F1 .932(N. Borenstein and N. Freed.)5.932 F(September)
+5.932 E(1993.)123 429.6 Q 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
index 000000000000..6fd40ad866e3
--- /dev/null
+++ b/usr.sbin/sendmail/doc/op/op.me
@@ -0,0 +1,7593 @@
+.\" Copyright (c) 1983, 1995 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.70 (Berkeley) 11/3/95
+.\"
+.\" 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
+.\" SB is bin if newaliases/mailq are installed in /usr/bin, ucb if in /usr/ucb
+.ds SB bin
+.nr si 3n
+.de $0
+.(x
+.in \\$3u*3n
+.ti -3n
+\\$2. \\$1
+.)x
+..
+.de $C
+.(x
+.in 0
+\\$1 \\$2. \\$3
+.)x
+..
+.sc
+.+c
+.(l C
+.sz 16
+.b SENDMAIL
+.sz 12
+.sp
+.b "INSTALLATION AND OPERATION GUIDE"
+.sz 10
+.sp
+.r
+Eric Allman
+Pang\(aea Reference Systems
+eric@Sendmail.ORG
+.sp
+Version 8.70
+.sp
+For Sendmail Version 8.7
+.)l
+.sp 2
+.pp
+.i Sendmail
+implements a general purpose internetwork mail routing facility
+under the UNIX\(rg
+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
+RFC821 (Simple Mail Transport Protocol),
+RFC822 (Internet Mail Format Protocol),
+RFC1123 (Internet Host Requirements),
+RFC1521 (MIME),
+RFC1651 (SMTP Service Extensions),
+and a series of as-yet-draft standards describing
+Delivery Status Notifications (DSNs),
+available from the internet drafts sites as
+draft-ietf-notary-mime-delivery-\fIXX\fP.txt,
+draft-ietf-notary-mime-report-\fIXX\fP.txt,
+draft-ietf-notary-smtp-drpt-\fIXX\fP.txt,
+and
+draft-ietf-notary-status-\fIXX\fP.txt
+(replace
+.i XX
+by the latest draft number).
+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
+describes configuration that can be done at compile time.
+Section seven
+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.
+.pp
+.b WARNING:
+Several major changes were introduced in version 8.7.
+You should not attempt to use this document
+for prior versions of
+.i sendmail .
+.bp 7
+.sh 1 "BASIC INSTALLATION"
+.pp
+There are two basic steps to installing
+.i sendmail .
+The hard part is to build the configuration table.
+This is a file that
+.i 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
+.i 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.4BSD.
+.pp
+If you are loading this off the tape,
+continue with the next section.
+If you have a running binary already on your system,
+you should probably skip to section 1.2.
+.sh 2 "Compiling Sendmail"
+.pp
+All
+.i 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.
+On most systems,
+you can do the appropriate compilation by typing
+.(b
+sh makesendmail
+.)b
+This will leave the binary in an appropriately named subdirectory.
+It works for multiple object versions
+compiled out of the same directory.
+.sh 3 "Tweaking the Makefile"
+.pp
+.i Sendmail
+supports two different formats
+for the local (on disk) version of databases,
+notably the
+.i aliases
+database.
+At least one of these should be defined if at all possible.
+.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 NIS defined,
+and if the alias file name includes the substring
+.q /yp/ ,
+.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.
+There are also several methods for remote database access:
+.ip NIS
+Sun's Network Information Services (formerly YP).
+.ip NISPLUS
+Sun's NIS+ services.
+.ip NETINFO
+NeXT's NetInfo service.
+.ip HESIOD
+Hesiod service (from Athena).
+.lp
+Other compilation flags are set in conf.h
+and should be predefined for you
+unless you are porting to a new environment.
+.sh 3 "Compilation and installation"
+.pp
+After making the local system configuration described above,
+You should be able to compile and install the system.
+The script
+.q makesendmail
+is the best approach on most systems:
+.(b
+sh makesendmail
+.)b
+This will use
+.i uname (1)
+to select the correct Makefile for your environment.
+.pp
+You may be able to install using
+.(b
+sh makesendmail install
+.)b
+This should install the binary in
+/usr/\*(SD
+and create links from
+/usr/\*(SB/newaliases
+and
+/usr/\*(SB/mailq
+to
+/usr/\*(SD/sendmail.
+On 4.4BSD 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 delivery mechanisms 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
+Our configuration files are processed by
+.i m4
+to facilitate local customization;
+the directory
+.i cf
+of the
+.i 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
+.i 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.
+The mailer types that are known in this distribution are
+fax,
+local,
+smtp,
+uucp,
+and usenet.
+For example, to include support for the UUCP-based mailers,
+use
+.q MAILER(uucp) .
+.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
+.i sendmail
+installation.
+.sh 3 "/usr/\*(SD/sendmail"
+.pp
+The binary for
+.i 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
+.i sendmail \**.
+.(f
+\**Actually, the pathname varies depending on the operating system;
+/etc is the preferred directory.
+Some older systems install it in
+.b /usr/lib/sendmail.cf ,
+and I've also seen it in
+.b /usr/ucblib
+and
+.b /etc/mail .
+If you want to move this file,
+change
+.i src/conf.h .
+.)f
+This and /etc/sendmail.pid
+are the only non-library file names compiled into
+.i sendmail \**.
+.(f
+\**The system libraries can reference other files;
+in particular, system library subroutines that
+.i sendmail
+calls probably reference
+.i /etc/passwd
+and
+.i /etc/resolv.conf .
+.)f
+.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/\*(SB/newaliases"
+.pp
+The
+.i newaliases
+command should just be a link to
+.i sendmail :
+.(b
+rm \-f /usr/\*(SB/newaliases
+ln \-s /usr/\*(SD/sendmail /usr/\*(SB/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/rc"
+.pp
+It will be necessary to start up the
+.i 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, see Figure 1
+for an example of a complex startup script.
+.(z
+.hl
+# 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 df files with no corresponding 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
+ mv $dffile `echo $dffile | sed 's/d/D/'`
+ fi
+done
+# announce files that have been saved during disaster recovery
+for xffile in [A-Z]f*
+do
+ echo \-n " <panic: $xffile>" > /dev/console
+done
+.sp
+.ce
+Figure 1 \(em A complex startup script
+.hl
+.)z
+.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/\*(SB/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 "The System Log"
+.pp
+The system log is supported by the
+.i syslogd \|(8)
+program.
+All messages from
+.i sendmail
+are logged under the
+.sm LOG_MAIL
+facility\**.
+.(f
+\**Except on Ultrix,
+which does not support facilities in the syslog.
+.)f
+.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\**.
+.(f
+\**This format may vary slightly if your vendor has changed
+the syntax.
+.)f
+Most messages are a sequence of
+.i name \c
+=\c
+.i value
+pairs.
+.pp
+The two most common lines are logged when a message is processed.
+The first logs the receipt of a message;
+there will be exactly one of these per message.
+Some fields may be omitted if they do not contain interesting information.
+Fields are:
+.ip from
+The envelope sender address.
+.ip size
+The size of the message in bytes.
+.ip class
+The class (i.e., numeric precedence) of the message.
+.ip pri
+The initial message priority (used for queue sorting).
+.ip nrcpts
+The number of envelope recipients for this message
+(after aliasing and forwarding).
+.ip msgid
+The message id of the message (from the header).
+.ip proto
+The protocol used to receive this message (e.g., ESMTP or UUCP)
+.ip relay
+The machine from which it was received.
+.lp
+There is also one line logged per delivery attempt
+(so there can be several per message if delivery is deferred
+or there are multiple recipients).
+Fields are:
+.ip to
+A comma-separated list of the recipients to this mailer.
+.ip ctladdr
+The ``controlling user'', that is, the name of the user
+whose credentials we use for delivery.
+.ip delay
+The total delay between the time this message was received
+and the time it was delivered.
+.ip xdelay
+The amount of time needed in this delivery attempt
+(normally indicative of the speed of the connection).
+.ip mailer
+The name of the mailer used to deliver to this recipient.
+.ip relay
+The name of the host that actually accepted (or rejected) this recipient.
+.ip stat
+The delivery status.
+.lp
+Not all fields are present in all messages;
+for example, the relay is not listed for local deliveries.
+.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
+.\" XREF
+4.6.
+.sh 2 "Dumping State"
+.pp
+You can ask
+.i sendmail
+to log a dump of the open files
+and the connection cache
+by sending it a
+.sm SIGUSR1
+signal.
+The results are logged at
+.sm LOG_DEBUG
+priority.
+.sh 2 "The Mail Queue"
+.pp
+Sometimes a host cannot handle a message immediately.
+For example, it may be down or overloaded, causing it to refuse connections.
+The sending host is then expected to save this message in
+its mail queue
+and attempt to deliver it later.
+.pp
+Under normal conditions the mail queue will 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
+.i 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
+.i 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 Service Switch"
+.pp
+The implementation of certain system services
+such as host and user name lookup
+is controlled by the service switch.
+If the host operating system supports such a switch
+.i sendmail
+will use the native version.
+Ultrix, Solaris, and DEC OSF/1 are examples of such systems.
+.pp
+If the underlying operating system does not support a service switch
+(e.g., SunOS, HP-UX, BSD)
+then
+.i sendmail
+will provide a stub implementation.
+The
+.b ServiceSwitchFile
+option points to the name of a file that has the service definitions
+Each line has the name of a service
+and the possible implementations of that service.
+For example, the file:
+.(b
+hosts dns files nis
+aliases files nis
+.)b
+will ask
+.i sendmail
+to look for hosts in the Domain Name System first.
+If the requested host name is not found,
+it tries local files,
+and if that fails it tries NIS.
+Similarly,
+when looking for aliases
+it will try the local files first
+followed by NIS.
+.pp
+Service switches are not completely integrated.
+For example, despite the fact that the host entry listed in the above example
+specifies to look in NIS,
+on SunOS this won't happen because the system implementation of
+.i gethostbyname \|(3)
+doesn't understand this.
+If there is enough demand
+.i sendmail
+may reimplement
+.i gethostbyname \|(3),
+.i gethostbyaddr \|(3),
+.i getpwent \|(3),
+and the other system routines that would be necessary
+to make this work seamlessly.
+.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
+(except on prep.ai.MIT.EDU,
+and they probably don't want me)\**.
+.(f
+\**Actually, any mailer that has the `A' mailer flag set
+will permit aliasing;
+this is normally limited to the local mailer.
+.)f
+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 ndbm \|(3)\**
+.(f
+\**The
+.i gdbm
+package probably works as well.
+.)f
+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
+The control of search order is actually set by the service switch.
+Essentially, the entry
+.(b
+OAswitch:aliases
+.)b
+is always added as the first alias entry;
+also, the first alias file name without a class
+(e.g., without
+.q nis:
+on the front)
+will be used as the name of the file for a ``files'' entry
+in the aliases switch.
+For example, if the configuration file contains
+.(b
+OA/etc/aliases
+.)b
+and the service switch contains
+.(b
+aliases nis files nisplus
+.)b
+then aliases will first be searched in the NIS database,
+then in /etc/aliases,
+then in the NIS+ database.
+.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 .
+Warning: if you build your own
+.sm NIS -based
+alias files,
+be sure to provide the
+.b \-l
+flag to
+.i makedbm (8)
+to map upper case letters in the keys to lower case;
+otherwise, aliases with upper case letters in their names
+won't match incoming addresses.
+.pp
+Additional flags can be added after the colon
+exactly like a
+.b K
+line \(em for example:
+.(b
+OAnis:\-N mail.aliases@my.nis.domain
+.)b
+will search the appropriate NIS map and always include null bytes in the key.
+.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
+.b RebuildAliases
+(old
+.b 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 the rebuild timeout
+(option
+.b AliasWait ,
+old
+.b a ,
+which is normally 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 NDBM 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 three 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,
+it locks the database source file during the rebuild \(em
+but that may not work over NFS or if the file is unwritable.
+Third,
+at the end of the rebuild
+it adds an alias of the form
+.(b
+@: @
+.)b
+(which is not normally legal).
+Before
+.i sendmail
+will access the database,
+it checks to insure that this entry exists\**.
+.(f
+\**The
+.b AliasWait
+option is required in the configuration
+for this action to occur.
+This should normally be specified.
+.)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: unix-wizards-request
+unix-wizards-request: 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,
+the
+.q owner-
+address normally points at the
+.q -request
+address; this causes messages to go out with the typical Internet convention
+of using ``\c
+.i list -request''
+as the return address.
+.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.
+.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 "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 UseErrorsTo
+option is set.
+.pp
+The Errors-To: header is official deprecated
+and will go away in a future release.
+.sh 3 "Apparently-To:"
+.pp
+RFC 822 requires at least one recipient field
+(To:, Cc:, or Bcc: line)
+in every message.
+If a message comes in with no recipients listed in the message
+then
+.i sendmail
+will adjust the header based on the
+.q NoRecipientAction
+option.
+One of the possible actions is to 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
+The Apparently-To: header is non-standard
+and is deprecated.
+.sh 3 "Precedence"
+.pp
+The Precedence: header can be used as a crude control of message priority.
+It tweaks the sort order in the queue
+and can be configured to change the message timeout values.
+.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
+.lp
+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
+.lp
+In some cases your system may not work properly with IDENT support
+due to a bug in the TCP/IP implementation.
+The symptoms will be that for some hosts
+the SMTP connection will be closed
+almost immediately.
+If this is true or if you do not want to use IDENT,
+you should set the IDENT timeout to zero;
+this will disable the IDENT protocol.
+.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 with delivery mode set to
+.b i
+or
+.b b
+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.
+(See also the MinQueueAge option.)
+.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
+.pp
+An alternative approach is to invoke sendmail from
+.i inetd (8)
+(use the
+.b \-bs
+flag to ask sendmail to speak SMTP on its standard input and output).
+This works and allows you to wrap
+.i sendmail
+in a TCP wrapper program,
+but may be a bit slower since the configuration file
+has to be re-read on every message that comes in.
+If you do this, you still need to have a
+.i sendmail
+running to flush the queue:
+.(b
+/usr/\*(SD/sendmail \-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 queue 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 "Changing the Values of Options"
+.pp
+Options can be overridden using the
+.b \-o
+or
+.b \-O
+command line flags.
+For example,
+.(b
+/usr/\*(SD/sendmail \-oT2m
+.)b
+sets the
+.b T
+(timeout) option to two minutes
+for this run only;
+the equivalent line using the long option name is
+.(b
+/usr/\*(SD/sendmail -OQueueTimeout=2m
+.)b
+.pp
+Some options have security implications.
+Sendmail allows you to set these,
+but relinquishes its setuid root permissions thereafter\**.
+.(f
+\**That is, it sets its effective uid to the real uid;
+thus, if you are executing as root,
+as from root's crontab file or during system startup
+the root permissions will still be honored.
+.)f
+.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 \-oQ/tmp/mqueue
+.)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.
+.pp
+.i Sendmail
+gives up its setuid root permissions
+when you use this flag, so it is common to use a publicly writable directory
+(such as /tmp)
+as the spool directory (QueueDirectory or Q option) while testing.
+.sh 2 "Logging Traffic"
+.pp
+Many SMTP implementations do not fully implement the protocol.
+For example, some personal computer based SMTPs
+do not understand continuation lines in reply codes.
+These can be very hard to trace.
+If you suspect such a problem, you can set traffic logging using the
+.b \-X
+flag.
+For example,
+.(b
+/usr/\*(SD/sendmail \-X /tmp/traffic \-bd
+.)b
+will log all traffic in the file
+.i /tmp/traffic .
+.pp
+This logs a lot of data very quickly and should
+.b NEVER
+be used
+during normal operations.
+After starting up such a daemon,
+force the errant implementation to send a message to your host.
+All message traffic in and out of
+.i sendmail ,
+including the incoming SMTP traffic,
+will be logged in this file.
+.sh 2 "Testing Configuration Files"
+.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,
+.i sendmail
+applies ruleset 3 to all addresses.
+In test mode
+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
+.pp
+As of version 8.7,
+some other syntaxes are available in test mode:
+.bu
+\&.D\|x\|value
+defines macro
+.i x
+to have the indicated
+.i value .
+This is useful when debugging rules that use the
+.b $& \c
+.i x
+syntax.
+.bu
+\&.C\|c\|value
+adds the indicated
+.i value
+to class
+.i c .
+.bu
+\&.S\|ruleset
+dumps the contents of the indicated ruleset.
+.bu
+\-d\|debug-spec
+is equivalent to the command-line flag.
+.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 "O Timeout.queuereturn=5d"
+sets option
+.q Timeout.queuereturn
+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.
+.pp
+All versions of
+.i sendmail
+prior to 8.7
+had single character option names.
+As of 8.7,
+options have long (multi-character names).
+Although old short names are still accepted,
+most new options do not have short equivalents.
+.pp
+This section only describes the options you are most likely
+to want to tweak;
+read section
+.\"XREF
+5
+for more details.
+.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
+Timeouts all have option names
+.q Timeout.\fIsuboption\fP .
+The recognized
+.i suboption s,
+their default values, and the minimum values
+allowed by RFC 1123 section 5.3.2 are:
+.nr ii 1i
+.ip connect
+The time to wait for an SMTP connection to open
+(the
+.i connect (2)
+system call)
+[0, unspecified].
+If zero, uses the kernel default.
+In no case can this option extend the timeout
+longer than the kernel provides, but it can shorten it.
+This is to get around kernels that provide an absurdly long connection timeout
+(90 minutes in one case).
+.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
+(see below).
+.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].
+.ip ident
+The timeout waiting for a reply to an IDENT query
+[30s\**, unspecified].
+.(f
+\**On some systems the default is zero to turn the protocol off entirely.
+.)f
+.lp
+For compatibility with old configuration files,
+if no
+.i suboption
+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, versions of
+.i sendmail
+prior to version 8.1 did 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 easily 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 a communications failure during the RCPT phase is rare,
+a long timeout is not onerous
+and may ultimately help reduce network load
+and duplicated messages.
+.pp
+For example, the lines:
+.(b
+O Timeout.command=25m
+O Timeout.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 five days.
+It is sometimes considered convenient to also send a warning message
+if the message is in the queue longer than a few hours
+(assuming you normally have good connectivity;
+if your messages normally took several hours to send
+you wouldn't want to do this because it wouldn't be an unusual event).
+These timeouts are set using the
+.b Timeout.queuereturn
+and
+.b Timeout.queuewarn
+options in the configuration file
+(previously both were set using the
+.b T
+option).
+.pp
+Since these options are global,
+and since you can not know
+.i "a priori"
+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 Timeout.queuewarn
+value can be piggybacked on the
+.b T
+option by indicating a time after which
+a warning message should be sent;
+the two timeouts are separated by a slash.
+For example, the line
+.(b
+OT5d/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 ForkEachJob
+(\c
+.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 ForkEachJob
+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 ForkEachJob
+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
+(which is determined from the Precedence: header)
+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 RecipientFactor
+(\c
+.b y )
+and
+.b ClassFactor
+(\c
+.b z )
+options respectively.
+They default to 30000 (for the recipient factor)
+and 1800
+(for the class factor).
+The initial priority is:
+.EQ
+pri = msgsize - (class times bold ClassFactor) + (nrcpt times bold RecipientFactor)
+.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 RetryFactor
+(\c
+.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 RetryFactor
+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 QueueLA
+(\c
+.b x )
+option.
+When the load average exceeds the value of the
+.b QueueLA
+option,
+the delivery mode is set to
+.b q
+(queue only)
+if the
+.b QueueFactor
+(\c
+.b q )
+option divided by the difference in the current load average and the
+.b QueueLA
+option
+plus one
+exceeds the priority of the message \(em
+that is, the message is queued iff:
+.EQ
+pri > { bold QueueFactor } over { LA - { bold QueueLA } + 1 }
+.EN
+The
+.b QueueFactor
+option defaults to 600000,
+so each point of load average is worth 600000
+priority points
+(as described above).
+.pp
+For drastic cases,
+the
+.b RefuseLA
+(\c
+.b X )
+option defines a load average at which
+.i 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
+.b DeliveryMode
+(\c
+.b 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)
+d defer delvery attempts (don't deliver)
+.)b
+There are tradeoffs.
+Mode
+.q i
+gives the sender the quickest feedback,
+but may slow down some mailers and
+is hardly ever necessary.
+Mode
+.q b
+delivers promptly but
+can cause large numbers of processes
+if you have a mailer that takes a long time to deliver a message.
+Mode
+.q q
+minimizes the load on your machine,
+but means that delivery may be delayed for up to the queue interval.
+Mode
+.q d
+is identical to mode
+.q q
+except that it also prevents all the early map lookups from working;
+it is intended for ``dial on demand'' sites where DNS lookups
+might cost real money.
+Some simple error messages
+(e.g., host unknown during the SMTP protocol)
+will be delayed using this mode.
+Mode
+.q b
+is the usual default.
+.pp
+If you run in mode
+.q q
+(queue only),
+.q d
+(defer),
+or
+.q b
+(deliver in background)
+.i sendmail
+will not expand aliases and follow .forward files
+upon initial receipt of the mail.
+This speeds up the response to RCPT commands.
+Mode
+.q i
+cannot be used by the SMTP server.
+.sh 2 "Log Level"
+.pp
+The level of logging can be set for
+.i 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 and alias database rebuilds.
+.ip 9
+Messages being deferred
+(due to a host being down, etc.).
+.ip 10
+Database expansion (alias, forward, and userdb lookups).
+.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 debugging output.
+No normal site would ever set these.
+.sh 2 "File Modes"
+.pp
+The modes used for files 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.
+.pp
+If you don't make
+.i sendmail
+setuid to root, it will still run but you lose a lot of functionality
+and a lot of privacy, since you'll have to make the queue directory
+world readable.
+You could also make
+.i sendmail
+setuid to some pseudo-user
+(e.g., create a user called
+.q sendmail
+and make
+.i sendmail
+setuid to that)
+which will fix the privacy problems
+but not the functionality issues.
+Also, this isn't a guarantee of security:
+for example,
+root occasionally sends mail,
+and the daemon often runs as root.
+.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
+.b AutoRebuildAliases
+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,
+.i 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 ConnectionCacheSize
+(\c
+.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
+.i sendmail
+will use during queue runs.
+Never set this higher than 4.
+.pp
+The
+.b ConnectionCacheTimeout
+(\c
+.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
+Control of host address lookups is set by the
+.b hosts
+service entry in your service switch file.
+If you are on a system that has built-in service switch support
+(e.g., Ultrix, Solaris, or DEC OSF/1)
+then your system is probably configured properly already.
+Otherwise,
+.i sendmail
+will consult the file
+.b /etc/service.switch ,
+which should be created.
+.i Sendmail
+only uses two entries:
+.b hosts
+and
+.b aliases .
+.pp
+However, some systems (such as SunOS)
+will do DNS lookups
+regardless of the setting of the service switch entry.
+In particular, the system routine
+.i gethostbyname (3)
+is used to look up host names,
+and many vendor versions try some combination of DNS, NIS,
+and file lookup in /etc/hosts
+without consulting a service switch.
+.i Sendmail
+makes no attempt to work around this problem,
+and the DNS lookup will be done anyway.
+If you do not have a nameserver configured at all,
+such as at a UUCP-only site,
+.i sendmail
+will get a
+.q "connection refused"
+message when it tries to connect to the name server.
+If the
+.b hosts
+switch entry has the service
+.q dns
+listed somewhere in the list,
+.i sendmail
+will interpret this to mean a temporary failure
+and will queue the mail for later processing;
+otherwise, it ignores the name server data.
+.pp
+The same technique is used to decide whether to do MX lookups.
+If you want MX support, you
+.i must
+have
+.q dns
+listed as a service in the
+.b hosts
+switch entry.
+.pp
+The
+.b ResolverOptions
+(\c
+.b I )
+option 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
+O ResolverOptions=+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.
+You can also include
+.q HasWildcardMX
+to specify that there is a wildcard MX record matching your domain;
+this turns off MX matching when canonifying names,
+which can lead to inappropriate canonifications.
+.pp
+Version level 1 configurations
+turn DNSRCH and DEFNAMES off when doing delivery lookups,
+but leave them on everywhere else.
+Version 8 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 being looked up
+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.
+.pp
+To completely turn off all name server access
+on systems without service switch support
+(such as SunOS)
+you will have to recompile with
+\-DNAMED_BIND=0
+and remove \-lresolv from the list of libraries to be searched
+when linking.
+.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 ForwardPath
+(\c
+.b J )
+option allows you to set a path of forward files.
+For example, the config file line
+.(b
+O ForwardPath=/var/forward/$u:$z/.forward.$w
+.)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
+``.forward.\c
+.i machinename ''
+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 one of the system calls in the
+.i statfs (2)
+family
+(including
+.i statvfs
+and
+.i ustat ),
+you can specify a minimum number of free blocks on the queue filesystem
+using the
+.b MinFreeBlocks
+(\c
+.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.
+.sh 2 "Maximum Message Size"
+.pp
+To avoid overflowing your system with a large message,
+the
+.b MaxMessageSize
+option can be set to set an absolute limit
+on the size of any one message.
+This will be advertised in the ESMTP dialogue
+and checked during message collection.
+.sh 2 "Privacy Flags"
+.pp
+The
+.b PrivacyOptions
+(\c
+.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
+or adding extra headers to indicate possible spoof attempts.
+.pp
+The option takes a series of flag names;
+the final privacy is the inclusive or of those flags.
+For example:
+.(b
+O PrivacyOptions=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 flags are detailed in section
+.\"XREF
+5.1.6.
+.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 MeToo
+(\c
+.b m )
+option is set in the configuration file,
+this behaviour is suppressed.
+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.
+.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
+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 2 "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 3 "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 3 "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 in the host database(s)
+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 $[ftp$]
+might become
+.q ftp.CS.Berkeley.EDU
+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 indicated
+.i default
+is inserted;
+if no default is specified and no lookup matches,
+the value is left unchanged.
+The
+.i arguments
+are passed to the map for possible use.
+.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.
+The
+.b $>
+syntax can only be used at the beginning of the right hand side;
+it can be only be preceded by
+.b $@
+or
+.b $: .
+.pp
+The
+.b $#
+syntax should
+.i only
+be used in ruleset zero
+or a subroutine of ruleset zero.
+It causes evaluation of the ruleset to terminate immediately,
+and signals to
+.i 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, in the address
+.q jgm+foo@CMU.EDU ;
+the
+.q +foo
+part 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).
+The
+.i user
+is later rewritten by the mailer-specific envelope rewriting set
+and assigned to the
+.b $u
+macro.
+As a special case, if the value to
+.b $#
+is
+.q local
+and the first character of the
+.b $:
+value is
+.q @ ,
+the
+.q @
+is stripped off, and a flag is set in the address descriptor
+that causes sendmail to not do ruleset 5 processing.
+.pp
+Normally, a rule that matches is retried,
+that is,
+the rule loops until it fails.
+A RHS may also be preceded by a
+.b $@
+or a
+.b $:
+to change this behavior.
+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 3 "Semantics of rewriting rule sets"
+.pp
+There are five rewriting sets
+that have specific semantics.
+Four of these are related as depicted by figure 1.
+.(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 1 \*- 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
+Ruleset three
+is applied by
+.i sendmail
+before doing anything with any address.
+.pp
+If no
+.q @
+sign is specified,
+then the
+host-domain-spec
+.i may
+be appended (box
+.q D
+in Figure 1)
+from the
+sender address
+(if the
+.b C
+flag is set in the mailer definition
+corresponding to the
+.i sending
+mailer).
+.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 3 "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.:
+.i
+This is intended only for situations where you have a network firewall
+or other host that will do special processing for all your mail,
+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.
+.r
+.sh 2 "D \*- Define Macro"
+.pp
+Macros are named with a single character
+or with a word in {braces}.
+Single character names 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.
+Long names beginning with a lower case letter or a punctuation character
+are reserved for use by sendmail,
+so user-defined long macro names should begin with an upper case letter.
+.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
+(which may be a single character
+or a word in braces)
+and
+.i val
+is the value it should have.
+There should be no spaces given
+that do not actually belong in the macro value.
+.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
+.i 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 are defined and/or used internally by
+.i sendmail
+for interpolation into argv's for mailers
+or for other contexts.
+The ones marked \(dg are information passed into sendmail\**,
+.(f
+\**As of version 8.6,
+all of these macros have reasonable defaults.
+Previous versions required that they be defined.
+.)f
+the ones marked \(dd are information passed both in and out of sendmail,
+and the unmarked macros are passed out of sendmail
+but are not otherwise used internally.
+These macros are:
+.nr ii 5n
+.ip $a
+The origination date in RFC 822 format.
+This is extracted from the Date: line.
+.ip $b
+The current date in RFC 822 format.
+.ip $c
+The hop count.
+This is a count of the number of Received: lines
+plus the value of the
+.b \-h
+command line flag.
+.ip $d
+The current date in UNIX (ctime) format.
+.ip $e\(dg
+(Obsolete; use SmtpGreetingMessage option instead.)
+The SMTP entry message.
+This is printed out when SMTP starts up.
+The first word must be the
+.b $j
+macro as specified by RFC821.
+Defaults to
+.q "$j Sendmail $v ready at $b" .
+Commonly redefined to include the configuration version number, e.g.,
+.q "$j Sendmail $v/$Z ready at $b"
+.ip $f
+The envelope sender (from) address.
+.ip $g
+The sender address relative to the recipient.
+For example, if
+.b $f
+is
+.q foo ,
+.b $g
+will be
+.q host!foo ,
+.q foo@host.domain ,
+or whatever is appropriate for the receiving mailer.
+.ip $h
+The recipient host.
+This is set in ruleset 0 from the $# field of a parsed address.
+.ip $i
+The queue id,
+e.g.,
+.q HAA12345 .
+.ip $j\(dd
+The \*(lqofficial\*(rq domain name for this site.
+This is fully qualified if the full qualification can be found.
+It
+.i must
+be redefined to be the fully qualified domain name
+if your system is not configured so that information can find
+it automatically.
+.ip $k
+The UUCP node name (from the uname system call).
+.ip $l\(dg
+(Obsolete; use UnixFromLine option instead.)
+The format of the UNIX from line.
+Unless you have changed the UNIX mailbox format,
+you should not change the default,
+which is
+.q "From $g $d" .
+.ip $m
+The domain part of the \fIgethostname\fP return value.
+Under normal circumstances,
+.b $j
+is equivalent to
+.b $w.$m .
+.ip $n\(dg
+The name of the daemon (for error messages).
+Defaults to
+.q MAILER-DAEMON .
+.ip $o\(dg
+(Obsolete: use OperatorChars option instead.)
+The set of \*(lqoperators\*(rq in addresses.
+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.
+Defaults to
+.q ".:@[]" ,
+which is the minimum set necessary to do RFC 822 parsing;
+a richer set of operators is
+.q ".:%@!/[]" ,
+which adds support for UUCP, the %-hack, and X.400 addresses.
+.ip $p
+Sendmail's process id.
+.ip $q\(dg
+Default format of sender address.
+The
+.b $q
+macro specifies how an address should appear in a message
+when it is defaulted.
+Defaults to
+.q "<$g>" .
+It is commonly redefined to be
+.q "$?x$x <$g>$|$g$."
+or
+.q "$g$?x ($x)$." ,
+corresponding 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.
+.ip $r
+Protocol used to receive the message.
+Set from the
+.b \-p
+command line flag or by the SMTP server code.
+.ip $s
+Sender's host name.
+Set from the
+.b \-p
+command line flag or by the SMTP server code.
+.ip $t
+A numeric representation of the current time.
+.ip $u
+The recipient user.
+.ip $v
+The version number of the
+.i sendmail
+binary.
+.ip $w\(dd
+The hostname of this site.
+This is the root name of this host (but see below for caveats).
+.ip $x
+The full name of the sender.
+.ip $z
+The home directory of the recipient.
+.ip $_
+The validated sender address.
+.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 macros
+.b $w ,
+.b $j ,
+and
+.b $m
+are set to the identity of this host.
+.i Sendmail
+tries to find the fully qualified name of the host
+if at all possible;
+it does this by calling
+.i gethostname (2)
+to get the current hostname
+and then passing that to
+.i gethostbyname (3)
+which is supposed to return the canonical version of that host name.\**
+.(f
+\**For example, on some systems
+.i gethostname
+might return
+.q foo
+which would be mapped to
+.q foo.bar.com
+by
+.i gethostbyname .
+.)f
+Assuming this is successful,
+.b $j
+is set to the fully qualified name
+and
+.b $m
+is set to the domain part of the name
+(everything after the first dot).
+The
+.b $w
+macro is set to the first word
+(everything before the first dot)
+if you have a level 5 or higher configuration file;
+otherwise, it is set to the same value as
+.b $j .
+If the canonification is not successful,
+it is imperative that the config file set
+.b $j
+to the fully qualified domain name\**.
+.(f
+\**Older versions of sendmail didn't pre-define
+.b $j
+at all, so up until 8.6,
+config files
+.i always
+had to define
+.b $j .
+.)f
+.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 .
+It can be defined in the
+.sm NAME
+environment variable.
+The third choice is the value of the
+.q Full-Name:
+line in the header if it exists,
+and the fourth 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.
+.pp
+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
+.i sendmail
+and the sending hostname.
+They can be set together using the
+.b \-p
+command line flag or separately using the
+.b \-M
+or
+.b \-oM
+flags.
+.pp
+The
+.b $_
+is set to a validated sender host name.
+If the sender is running an RFC 1413 compliant IDENT server
+and the receiver has the IDENT protocol turned on,
+it will include the user name on that host.
+.sh 2 "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 are named as a single letter or a word in {braces}.
+Class names beginning with lower case letters
+and special characters are reserved for system use.
+Classes defined in config files may be given names
+from the set of upper case letters for short names
+or beginning with an upper case letter for long names.
+.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 ``F'' form
+reads the elements of the class
+.i c
+from the named
+.i file .
+.pp
+Elements of classes can be accessed in rules using
+.b $=
+or
+.b $~ .
+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.
+.pp
+The class
+.b $=m
+is set to the set of domains by which this host is known,
+initially just
+.b $m .
+.pp
+The class
+.b $=t
+is set to the set of trusted users by the
+.b T
+configuration line.
+If you want to read trusted users from a file use
+.b Ft \c
+.i /file/name .
+.pp
+The class
+.b $=n
+can be set to the set of MIME body types
+that can never be eight to seven bit encoded.
+It defaults to
+.q multipart/signed .
+Message types
+.q message/*
+and
+.q multipart/*
+are never encoded directly.
+Multipart messages are always handled recursively.
+The handling of message/* messages
+are controlled by class
+.b $=s .
+The class
+.b $=e
+contains the Content-Transfer-Encodings that can be 8\(->7 bit encoded.
+It is predefined to contain
+.q 7bit ,
+.q 8bit ,
+and
+.q binary .
+The class
+.b $=s
+contains the set of subtypes of message that can be treated recursively.
+By default it contains only
+.q rfc822 .
+Other
+.q message/*
+types cannot be 8\(->7 bit encoded.
+If a message containing eight bit data is sent to a seven bit host,
+and that message cannot be encoded into seven bits,
+it will be stripped to 7 bits.
+.pp
+.i Sendmail
+can be compiled to allow a
+.i scanf (3)
+string on the
+.b F
+line.
+This lets you do simplistic parsing of text files.
+For example, to read all the user names in your system
+.i /etc/passwd
+file into a class, use
+.(b
+FL/etc/passwd %[^:]
+.)b
+which reads every line up to the first colon.
+.sh 2 "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 Rewriting set(s) for sender addresses
+Recipient Rewriting set(s) 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
+Userid The default user and group id to run as
+Nice The nice(2) increment for the mailer
+Charset The default character set for 8-bit characters
+Type The MTS type information (used for error messages)
+.)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.
+Flags marked with \(dg
+are not interpreted by the
+.i sendmail
+binary;
+these are the conventionally used to correlate to the flags portion
+of the
+.b H
+line.
+Flags marked with \(dd
+apply to the mailers for the sender address
+rather than the usual recipient mailers.
+.nr ii 4n
+.ip a
+Run Extended SMTP (ESMTP) protocol (defined in RFCs 1651, 1652, and 1653).
+This flag defaults on if the SMTP greeting message includes the word
+.q ESMTP .
+.ip A
+Look up the user part of the address in the alias database.
+Normally this is only set for local mailers.
+.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.
+This strips addresses of the form
+.q "Phrase <address>"
+or
+.q "address (Comment)"
+down to just
+.q address .
+.ip C\(dd
+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 envelope address
+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.
+However, it doesn't really work reliably.
+.ip D\(dg
+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\(dg
+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
+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 k
+Normally when
+.i sendmail
+connects to a host via SMTP,
+it checks to make sure that this isn't accidently the same host name
+as might happen if
+.i sendmail
+is misconfigured or if a long-haul network interface is set in loopback mode.
+This flag disables the loopback check.
+It should only be used under very unusual circumstances.
+.ip K
+Currently unimplemented.
+Reserved for chunking.
+.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\(dg
+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 o
+Always run as the owner of the recipient mailbox.
+Normally
+.i sendmail
+runs as the sender for locally generated mail
+or as
+.q daemon
+(actually, the user specified in the
+.b u
+option)
+when delivering network mail.
+The normal behaviour is required by most local mailers,
+which will not allow the envelope sender address
+to be set unless the mailer is running as daemon.
+This flag is ignored if the
+.b S
+flag is set.
+.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\(dg
+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 (" and \e) 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.
+If the
+.b U=
+field is also specified,
+this flag causes the user id to always be set to that user and group
+(instead of leaving it as root).
+.ip u
+Upper case should be preserved in user names
+for this mailer.
+.ip U
+This mailer wants UUCP-style
+.q From
+lines with the ugly
+.q "remote from <host>"
+on the end.
+.ip w
+The user must have a valid account on this machine,
+i.e.,
+getpwnam
+must succeed.
+If not,
+the mail is bounced.
+This is required to get
+.q \&.forward
+capability.
+.ip x\(dg
+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 5
+If no aliases are found for this address,
+pass the address through ruleset 5 for possible alternate resolution.
+This is intended to forward the mail to an alternate delivery spot.
+.ip 7
+Strip all output to seven bits.
+This is the default if the
+.b L
+flag is set.
+Note that clearing this option 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.
+Note that this option will only impact messages
+that didn't have 8\(->7 bit MIME conversions performed.
+.ip 8
+If set,
+it is acceptable to send eight bit data to this mailer;
+the usual attempt to do 8\(->7 bit MIME conversions will be bypassed.
+.ip :
+Check addresses to see if they begin
+.q :include: ;
+if they do, convert them to the
+.q *include*
+mailer.
+.ip |
+Check addresses to see if they begin with a `|';
+if they do, convert them to the
+.q prog
+mailer.
+.ip /
+Check addresses to see if they begin with a `/';
+if they do, convert them to the
+.q *file*
+mailer.
+.ip @
+Look up addresses in the user database.
+.pp
+Configuration files prior to level 6
+assume the `A', `w', `5', `:', `|', `/', and `@' options
+on the mailer named
+.q local .
+.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 rulesets zero or five.
+.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 ruleset id
+or may be two ids 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 unprivileged users
+.i csh
+scripts as recipients can fail.
+.pp
+The Userid
+specifies the default user and group id to run as,
+overriding the
+.b DefaultUser
+option (q.v.).
+If the
+.b S
+mailer flag is also specified,
+this is the user and group to run as in all circumstances.
+This may be given as
+.i user:group
+to set both the user and group id;
+either may be an integer or a symbolic name to be looked up
+in the
+.i passwd
+and
+.i group
+files respectively.
+If only a symbolic user name is specified,
+the group id in the
+.i passwd
+file for that user is used as the group id.
+.pp
+The Charset field
+is used when converting a message to MIME;
+this is the character set used in the
+Content-Type: header.
+If this is not set, the
+.b DefaultCharset
+option is used,
+and if that is not set, the value
+.q unknown-8bit
+is used.
+.b WARNING:
+this field applies to the sender's mailer,
+not the recipient's mailer.
+For example, if the envelope sender address
+lists an address on the local network
+and the recipient is on an external network,
+the character set will be set from the Charset= field
+for the local network mailer,
+not that of the external network mailer.
+.pp
+The Type= field
+sets the type information
+used in MIME error messages
+as defined by
+RFC XXX
+(not yet published).
+It is actually three values separated by slashes:
+the MTA-type (that is, the description of how hosts are named),
+the address type (the description of e-mail addresses),
+and the diagnostic type (the description of error diagnostic codes).
+Each of these must be a registered value
+or begin with
+.q X\- .
+The default is
+.q dns/rfc822/smtp .
+.sh 2 "H \*- Define Header"
+.pp
+The format of the header lines that
+.i 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 later.
+.sh 2 "O \*- Set Option"
+.pp
+There are a number of
+global
+options that
+can be set from a configuration file.
+Options are represented by full words;
+some are also representable as single characters
+for back compatibility.
+The syntax of this line is:
+.(b F
+.b O \0
+.i option \c
+.b = \c
+.i value
+.)b
+This sets option
+.i option
+to be
+.i value .
+Note that there
+.i must
+be a space between the letter `O' and the name of the option.
+An older version is:
+.(b F
+.b O \c
+.i o\|value
+.)b
+where the option
+.i o
+is a single character.
+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 (with the old, one character names in brackets) are:
+.nr ii 1i
+.ip "AliasFile=\fIspec, spec, ...\fP"
+[A]
+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
+.i 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 AliasWait=\fItimeout\fP
+[a]
+If set,
+wait up to
+.i timeout
+(units default to minutes)
+for an
+.q @:@
+entry to exist in the alias database
+before starting up.
+If it does not appear in the
+.i timeout
+interval
+rebuild the database
+(if the
+.b AutoRebuildAliases
+option is also set)
+or issue a warning.
+.ip AutoRebuildAliases
+[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 .
+Not recommended \(em can cause thrashing.
+.ip BlankSub=\fIc\fP
+[B]
+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 CheckAliases
+[n]
+Validate the RHS of aliases when rebuilding the alias database.
+.ip CheckpointInterval=\fIN\fP
+[C]
+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 ClassFactor=\fIfact\fP
+[z]
+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 ColonOkInAddr
+[no short name]
+If set, colons are acceptable in e-mail addresses
+(e.g.,
+.q host:user ).
+If not set, colons indicate the beginning of a RFC 822 group construct
+(\c
+.q "groupname: member1, member2, ... memberN;" ).
+Doubled colons are always acceptable
+(\c
+.q nodename::user )
+and proper route-addr nesting is understood
+(\c
+.q <@relay:user@host> ).
+Furthermore, this option defaults on if the configuration version level
+is less than 6 (for back compatibility).
+However, it must be off for full compatibility with RFC 822.
+.ip ConnectionCacheSize=\fIN\fP
+[k]
+The maximum number of open connections that will be cached at a time.
+The default is one.
+This delays closing the current connection until
+either this invocation of
+.i 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.
+Since this consumes file descriptors,
+the connection cache should be kept small:
+4 is probably a practical maximum.
+.ip ConnectionCacheTimeout=\fItimeout\fP
+[K]
+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
+.i sendmail
+uses a cached connection,
+it always sends a RSET 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 DaemonPortOptions=\fIoptions\fP
+[O]
+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)
+SndBufSize Size of TCP send buffer
+RcvBufSize Size of TCP receive buffer
+.)b
+The
+.i Addr ess
+mask may be a numeric address in dot notation
+or a network name.
+.ip DefaultCharSet=\fIcharset\fP
+[no short name]
+When a message that has 8-bit characters but is not in MIME format
+is converted to MIME
+(see the EightBitMode option)
+a character set must be included in the Content-Type: header.
+This character set is normally set from the Charset= field
+of the mailer descriptor.
+If that is not set, the value of this option is used.
+If this option is not set, the value
+.q unknown-8bit
+is used.
+.ip DefaultUser=\fIuser:group\fP
+[u]
+Set the default userid for mailers to
+.i user:group .
+If
+.i group
+is omitted and
+.i user
+is a user name
+(as opposed to a numeric user id)
+the default group listed in the /etc/passwd file for that user is used
+as the default group.
+Both
+.i user
+and
+.i group
+may be numeric.
+Mailers without the
+.i S
+flag in the mailer definition
+will run as this user.
+Defaults to 1:1.
+The value can also be given as a symbolic user name.\**
+.(f
+\**The old
+.b g
+option has been combined into the
+.b DefaultUser
+option.
+.)f
+.ip DeliveryMode=\fIx\fP
+[d]
+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)
+d Defer delivery and all map lookups (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'').
+The
+.b \-v
+command line flag sets this to
+.b i .
+.ip DialDelay=\fIsleeptime\fP
+[no short name]
+Dial-on-demand network connections can see timeouts
+if a connection is opened before the call is set up.
+If this is set to an interval and a connection times out
+on the first connection being attempted
+.i sendmail
+will sleep for this amount of time and try again.
+This should give your system time to establish the connection
+to your service provider.
+Units default to seconds, so
+.q DialDelay=5
+uses a five second delay.
+Defaults to zero
+(no retry).
+.ip DontExpandCnames
+[no short name]
+The standards say that all host addresses used in a mail message
+must be fully canonical.
+For example, if your host is named
+.q Cruft.Foo.ORG
+and also has an alias of
+.q FTP.Foo.ORG ,
+the former name must be used at all times.
+This is enforced during host name canonification
+($[ ... $] lookups).
+If this option is set, the protocols are ignored and the
+.q wrong
+thing is done.
+However, the IETF is moving toward changing this standard,
+so the behaviour may become acceptable.
+Please note that hosts downstream may still rewrite the address
+to be the true canonical name however.
+.ip DontInitGroups
+[no short name]
+If set,
+.i sendmail
+will avoid using the initgroups(3) call.
+If you are running NIS,
+this causes a sequential scan of the groups.byname map,
+which can cause your NIS server to be badly overloaded in a large domain.
+The cost of this is that the only group found for users
+will be their primary group (the one in the password file),
+which will make file access permissions somewhat more restrictive.
+Has no effect on systems that don't have group lists.
+.ip DontPruneRoutes
+[R]
+Normally,
+.i sendmail
+tries to eliminate any unnecessary explicit routes
+when sending an error message
+(as discussed in RFC 1123 \(sc 5.2.6).
+For example,
+when sending an error message to
+.(b
+<@known1,@known2,@known3:user@unknown>
+.)b
+.i sendmail
+will strip off the
+.q @known1,@known2
+in order to make the route as direct as possible.
+However, if the
+.b R
+option is set, this will be disabled,
+and the mail will be sent to the first address in the route,
+even if later addresses are known.
+This may be useful if you are caught behind a firewall.
+.ip EightBitMode=\fIaction\fP
+[8]
+Set handling of eight-bit data.
+There are two kinds of eight-bit data:
+that declared as such using the
+.b BODY=8BITMIME
+ESMTP declaration or the
+.b \-B8BITMIME
+command line flag,
+and undeclared 8-bit data, that is,
+input that just happens to be eight bits.
+There are three basic operations that can happen:
+undeclared 8-bit data can be automatically converted to 8BITMIME,
+undeclared 8-bit data can be passed as-is without conversion to MIME
+(``just send 8''),
+and declared 8-bit data can be converted to 7-bits
+for transmission to a non-8BITMIME mailer.
+The possible
+.i action s
+are:
+.(b
+.\" r Reject undeclared 8-bit data;
+.\" don't convert 8BITMIME\(->7BIT (``reject'')
+ s Reject undeclared 8-bit data (``strict'')
+.\" do convert 8BITMIME\(->7BIT (``strict'')
+.\" c Convert undeclared 8-bit data to MIME;
+.\" don't convert 8BITMIME\(->7BIT (``convert'')
+ m Convert undeclared 8-bit data to MIME (``mime'')
+.\" do convert 8BITMIME\(->7BIT (``mime'')
+.\" j Pass undeclared 8-bit data;
+.\" don't convert 8BITMIME\(->7BIT (``just send 8'')
+ p Pass undeclared 8-bit data (``pass'')
+.\" do convert 8BITMIME\(->7BIT (``pass'')
+.\" a Adaptive algorithm: see below
+.)b
+.\"The adaptive algorithm is to accept 8-bit data,
+.\"converting it to 8BITMIME only if the receiver understands that,
+.\"otherwise just passing it as undeclared 8-bit data;
+.\"8BITMIME\(->7BIT conversions are done.
+In all cases properly declared 8BITMIME data will be converted to 7BIT
+as needed.
+.ip ErrorHeader=\fIfile-or-message\fP
+[E]
+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 ErrorMode=\fIx\fP
+[e]
+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 FallbackMXhost=\fIfallbackhost\fP
+[V]
+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 ForkEachJob
+[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 ForwardPath=\fIpath\fP
+[J]
+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 HelpFile=\fIfile\fP
+[H]
+Specify the help file
+for SMTP.
+.ip HoldExpensive
+[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 IgnoreDots
+[i]
+Ignore dots in incoming messages.
+This is always disabled (that is, dots are always accepted)
+when reading SMTP mail.
+.ip LogLevel=\fIn\fP
+[L]
+Set the default log level to
+.i n .
+Defaults to 9.
+.ip M\fIx\|value\fP
+[no long version]
+Set the macro
+.i x
+to
+.i value .
+This is intended only for use from the command line.
+The
+.b \-M
+flag is preferred.
+.ip MatchGECOS
+[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 MaxHopCount=\fIN\fP
+[h]
+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 MaxHostStatAge=\fIage\fP
+[no short name]
+Not yet implemented.
+This option specifies how long host status information will be retained.
+For example, if a host is found to be down,
+connections to that host will not be retried for this interval.
+The units default to minutes.
+.ip MaxQueueRunSize=\fIN\fP
+[no short name]
+The maximum number of jobs that will be processed
+in a single queue run.
+If not set, there is no limit on the size.
+If you have very large queues or a very short queue run interval
+this could be unstable.
+However, since the first
+.i N
+jobs in queue directory order are run (rather than the
+.i N
+highest priority jobs)
+this should be set as high as possible to avoid
+.q losing
+jobs that happen to fall late in the queue directory.
+.ip MeToo
+[m]
+Send to me too,
+even if I am in an alias expansion.
+.ip MaxMessageSize=\fIN\fP
+[no short name]
+Specify the maximum message size
+to be advertised in the ESMTP EHLO response.
+Messages larger than this will be rejected.
+.ip MinFreeBlocks=\fIN\fP
+[b]
+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.
+.ip MinQueueAge=\fPage\fP
+[no short name]
+Don't process any queued jobs
+that have been in the queue less than the indicated time interval.
+This is intended to allow you to get responsiveness
+by processing the queue fairly frequently
+without thrashing your system by trying jobs too often.
+The default units are minutes.
+.ip NoRecipientAction
+[no short name]
+The action to take when you receive a message that has no valid
+recipient headers (To:, Cc:, Bcc:).
+It can be
+.b None
+to pass the message on unmodified,
+which violates the protocol,
+.b Add-To
+to add a To: header with any recipients it can find in the envelope
+(which might expose Bcc: recipients),
+.b Add-Apparently-To
+to add an Apparently-To: header
+(this is only for back-compatibility
+and is officially deprecated),
+.b Add-To-Undisclosed
+to add a header
+.q "To: undisclosed-recipients:;"
+to make the header legal without disclosing anything,
+or
+.b Add-Bcc
+to add an empty Bcc: header.
+.ip OldStyleHeaders
+[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.
+Defaults to off.
+.ip OperatorChars=\fIcharlist\fP
+[$o macro]
+The list of characters that are considered to be
+.q operators ,
+that is, characters that delimit tokens.
+All operator characters are tokens by themselves;
+sequences of non-operator characters are also tokens.
+White space characters separate tokens
+but are not tokens themselves \(em for example,
+.q AAA.BBB
+has three tokens, but
+.q "AAA BBB"
+has two.
+If not set, OperatorChars defaults to
+.q \&.\|:\|@\|[\|] ;
+additionally, the characters
+.q (\|)\|<\|>\|,\|;
+are always operators.
+.ip PostmasterCopy=\fIpostmaster\fP
+[P]
+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.
+Defaults to no postmaster copies.
+.ip PrivacyOptions=\fI\|opt,opt,...\fP
+[p]
+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
+restrictqrun Restrict \-q command line flag
+noreceipts Don't return success DSNs
+goaway Disallow essentially all SMTP status queries
+authwarnings Put X-Authentication-Warning: headers in messages
+.)b
+The
+.q goaway
+pseudo-flag sets all flags except
+.q restrictmailq
+and
+.q restrictqrun .
+If mailq is restricted,
+only people in the same group as the queue directory
+can print the queue.
+If queue runs are restricted,
+only root and the owner of the queue directory
+can run the queue.
+Authentication Warnings add warnings about various conditions
+that may indicate attempts to spoof the mail system,
+such as using an non-standard queue directory.
+.ip QueueDirectory=\fIdir\fP
+[Q]
+Use the named
+.i dir
+as the queue directory.
+.ip QueueFactor=\fIfactor\fP
+[q]
+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 QueueLA
+option)
+to determine the maximum message priority
+that will be sent.
+Defaults to 600000.
+.ip QueueLA=\fILA\fP
+[x]
+When the system load average exceeds
+.i LA ,
+just queue messages
+(i.e., don't try to send them).
+Defaults to 8.
+.ip QueueSortOrder=\fIalgorithm\fP
+[no short name]
+Sets the
+.i algorithm
+used for sorting the queue.
+Only the first character of the value is used.
+Legal values are
+.q host
+(to order by the name of the first host name of the first recipient)
+and
+.q priority
+(to order strictly by message priority).
+Host ordering makes better use of the connection cache,
+but may tend to process low priority messages
+that go to a single host
+over high priority messages that go to several hosts;
+it probably shouldn't be used on slow network links.
+Priority ordering is the default.
+.ip ResolverOptions=\fIoptions\fP
+[I]
+Set resolver options.
+Values can be set using
+.b + \c
+.i flag
+and cleared using
+.b \- \c
+.i flag ;
+the
+.i flag s
+can be
+.q debug ,
+.q aaonly ,
+.q usevc ,
+.q primary ,
+.q igntc ,
+.q recurse ,
+.q defnames ,
+.q stayopen ,
+or
+.q dnsrch .
+The string
+.q HasWildcardMX
+(without a
+.b +
+or
+.b \- )
+can be specified to turn off matching against MX records
+when doing name canonifications.
+.b N.B.
+Prior to 8.7,
+this option indicated that the name server be responding
+in order to accept addresses.
+This has been replaced by checking to see
+if the
+.q dns
+method is listed in the service switch entry for the
+.q hosts
+service.
+.ip SmtpGreetingMessage=\fImessage\fP
+[$e macro]
+The message printed when the SMTP server starts up.
+Defaults to
+.q "$j Sendmail $v ready at $b".
+.ip Timeout.\fItype\fP=\|\fItimeout\fP
+[r; subsumes old T option as well]
+Set timeout values.
+The actual timeout is indicated by the
+.i type .
+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]
+ident IDENT protocol timeout [30s, none]
+fileopen\(dg timeout on opening .forward and :include: files [60s, none]
+command\(dg command read [1h, 5m]
+queuereturn\(dg how long until a message is returned [5d, 5d]
+queuewarn\(dg how long until a warning is sent [none, none]
+.)b
+All but those marked with a dagger (\(dg)
+apply to client SMTP.
+If the message is submitted using the
+.sm NOTIFY
+.sm SMTP
+extension,
+warning messages will only be sent if
+.sm NOTIFY=DELAY
+is specified.
+The queuereturn and queuewarn timeouts
+can be further qualified with a tag based on the Precedence: field
+in the message;
+they must be one of
+.q urgent
+(indicating a positive non-zero precedence)
+.q normal
+(indicating a zero precedence), or
+.q non-urgent
+(indicating negative precedences).
+For example, setting
+.q Timeout.queuewarn.urgent=1h
+sets the warning timeout for urgent messages only
+to one hour.
+The default if no precedence is indicated
+is to set the timeout for all precedences.
+.ip RecipientFactor=\fIfact\fP
+[y]
+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 RefuseLA=\fILA\fP
+[X]
+When the system load average exceeds
+.i LA ,
+refuse incoming SMTP connections.
+Defaults to 12.
+.ip RetryFactor=\fIfact\fP
+[Z]
+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 SaveFromLine
+[f]
+Save
+Unix-style
+.q From
+lines at the front of headers.
+Normally they are assumed redundant
+and discarded.
+.ip SendMIMEErrors
+[j]
+If set, send error messages in MIME format
+(see RFC1521 and RFC1344 for details).
+.ip ServiceSwitchFile=\fIfilename\fP
+[no short name]
+If your host operating system has a service switch abstraction
+(e.g., /etc/nsswitch.conf on Solaris
+or /etc/svc.conf on Ultrix and DEC OSF/1)
+that service will be consulted and this option is ignored.
+Otherwise, this is the name of a file
+that provides the list of methods used to implement particular services.
+The syntax is a series of lines,
+each of which is a sequence of words.
+The first word is the service name,
+and following words are service types.
+The services that
+.i sendmail
+consults directly are
+.q aliases
+and
+.q hosts.
+Service types can be
+.q dns ,
+.q nis ,
+.q nisplus ,
+or
+.q files
+(with the caveat that the appropriate support
+must be compiled in
+before the service can be referenced).
+If ServiceSwitchFile is not specified, it defaults to /etc/service.switch.
+If that file does not exist, the default switch is:
+.(b
+aliases files
+hosts dns nis files
+.)b
+The default file is
+.q /etc/service.switch .
+.ip SevenBitInput
+[7]
+Strip input to seven bits for compatibility with old systems.
+This shouldn't be necessary.
+.ip StatusFile=\fIfile\fP
+[S]
+Log summary statistics in the named
+.i file .
+If not set,
+no summary statistics are saved.
+This file does not grow in size.
+It can be printed using the
+.i mailstats (8)
+program.
+.ip SuperSafe
+[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 client
+under any circumstances.
+This should really
+.i always
+be set.
+.ip TempFileMode=\fImode\fP
+[F]
+The file mode for queue files.
+It is interpreted in octal by default.
+Defaults to 0600.
+.ip TimeZoneSpec=\fItzinfo\fP
+[t]
+Set the local time zone info to
+.i tzinfo
+\*- for example,
+.q PST8PDT .
+Actually, if this is not set,
+the TZ environment variable is cleared (so the system default is used);
+if set but null, the user's TZ variable is used,
+and if set and non-null the TZ variable is set to this value.
+.ip TryNullMXList
+[w]
+If this system is the
+.q best
+(that is, lowest preference)
+MX for a given host,
+its configuration rules should normally detect this situation
+and treat that condition specially
+by forwarding the mail to a UUCP feed,
+treating it as local,
+or whatever.
+However, in some cases (such as Internet firewalls)
+you may want to try to connect directly to that host
+as though it had no MX records at all.
+Setting this option causes
+.i sendmail
+to try this.
+The downside is that errors in your configuration
+are likely to be diagnosed as
+.q "host unknown"
+or
+.q "message timed out"
+instead of something more meaningful.
+This option is disrecommended.
+.ip UnixFromLine=\fIfromline\fP
+[$l macro]
+Defines the format used when
+.i sendmail
+must add a UNIX-style From_ line
+(that is, a line beginning
+.q From<space>user ).
+Defaults to
+.q "From $g $d" .
+Don't change this unless your system uses a different UNIX mailbox format
+(very unlikely).
+.ip UseErrorsTo
+[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
+.i sendmail
+to violate RFC 1123.
+This option is disrecommended and deprecated.
+.ip UserDatabaseSpec=\fIudbspec\fP
+[U]
+The user database specification.
+.ip Verbose
+[v]
+Run in verbose mode.
+If this is set,
+.i sendmail
+adjusts options
+.b HoldExpensive
+(old
+.b c )
+and
+.b DeliveryMode
+(old
+.b d )
+so that all mail is delivered completely
+in a single job
+so that you can see the entire delivery process.
+Option
+.b Verbose
+should
+.i never
+be set in the configuration file;
+it is intended for command line use only.
+.lp
+All options can be specified on the command line using the
+\-O or \-o flag,
+but most will cause
+.i sendmail
+to relinquish its setuid permissions.
+The options that will not cause this are
+MinFreeBlocks [b],
+DeliveryMode [d],
+ErrorMode [e],
+IgnoreDots [i],
+LogLevel [L],
+MeToo [m],
+OldStyleHeaders [o],
+PrivacyOptions [p],
+Timeouts [r],
+SuperSafe [s],
+Verbose [v],
+CheckpointInterval [C],
+and
+SevenBitInput [7].
+Also, M (define macro) when defining the r or s macros
+is also considered
+.q safe .
+.sh 2 "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 2 "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
+.b N.B.:
+these version
+.i levels
+have nothing
+to do with the version
+.i number
+on the files.
+For example,
+as of this writing
+version 8 config files
+(specifically, 8.7)
+used version level 6 configurations.
+.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.
+.pp
+Version level four configurations
+are completely equivalent to level three
+for historical reasons.
+.pp
+Version level five configuration files
+change the default definition of
+.b $w
+to be just the first component of the hostname.
+.pp
+Version level six configuration files
+change many of the local processing options
+(such as aliasing and matching the beginning of the address for
+`|' characters)
+to be mailer flags;
+this allows fine-grained control over the special local processing.
+Level six configuration files may also use long option names.
+The
+.b ColonOkInAddr
+option (to allow colons in the local-part of addresses)
+defaults
+.b on
+for lower numbered configuration files;
+the configuration file requires some additional intelligence
+to properly handle the RFC 822 group construct.
+.pp
+The
+.b V
+line may have an optional
+.b / \c
+.i vendor
+to indicate that this configuration file uses modifications
+specific to a particular vendor\**.
+.(f
+\**And of course, vendors are encouraged to add themselves
+to the list of recognized vendors by editing the routine
+.i setvendor
+in
+.i conf.c .
+Please send e-mail to sendmail@CS.Berkeley.EDU
+to register your vendor dialect.
+.)f
+You may use
+.q /Berkeley
+to emphasize that this configuration file
+uses the Berkeley dialect of
+.i sendmail .
+.sh 2 "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
+.i 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 many defined classes.
+.ip dbm
+Database lookups using the ndbm(3) library.
+.i Sendmail
+must be compiled with
+.b NDBM
+defined.
+.ip btree
+Database lookups using the btree interface to the Berkeley db(3) library.
+.i Sendmail
+must be compiled with
+.b NEWDB
+defined.
+.ip hash
+Database lookups using the hash interface to the Berkeley db(3) library.
+.i Sendmail
+must be compiled with
+.b NEWDB
+defined.
+.ip nis
+NIS lookups.
+.i Sendmail
+must be compiled with
+.b NIS
+defined.
+.ip nisplus
+NIS+ lookups.
+.i Sendmail
+must be compiled with
+.b NISPLUS
+defined.
+The argument is the name of the table to use for lookups,
+and the
+.b \-k
+and
+.b \-v
+flags may be used to set the key and value columns respectively.
+.ip hesiod
+Hesiod lookups.
+.i Sendmail
+must be compiled with
+.b HESIOD
+defined.
+.ip netinfo
+NeXT NetInfo lookups.
+.i Sendmail
+must be compiled with
+.b NETINFO
+defined.
+.ip text
+Text file lookups.
+The format of the text file is defined by the
+.b \-k
+(key field number),
+.b \-v
+(value field number),
+and
+.b \-z
+(field delimiter)
+flags.
+.ip stab
+Internal symbol table lookups.
+Used internally for aliasing.
+.ip implicit
+Really should be called
+.q alias
+\(em this is used to get the default lookups
+for alias files,
+and is the default if no class is specified for alias files.
+.ip user
+Looks up users using
+.i getpwnam (3).
+The
+.b \-v
+flag can be used to specify the name of the field to return
+(although this is normally used only to check the existence
+of a user).
+.ip host
+Canonifies host domain names.
+Given a host name it calls the name server
+to find the canonical name for that host.
+.ip sequence
+The arguments on the `K' line are a list of maps;
+the resulting map searches the argument maps in order
+until it finds a match for the indicated key.
+For example, if the key definition is:
+.(b
+Kmap1 ...
+Kmap2 ...
+Kseqmap sequence map1 map2
+.)b
+then a lookup against
+.q seqmap
+first does a lookup in map1.
+If that is found, it returns immediately.
+Otherwise, the same key is used for map2.
+.ip switch
+Much like the
+.q sequence
+map except that the order of maps is determined by the service switch.
+The argument is the name of the service to be looked up;
+the values from the service switch are appended to the map name
+to create new map names.
+For example, consider the key definition:
+.(b
+Kali switch aliases
+.)b
+together with the service switch entry:
+.(b
+aliases nis files
+.)b
+This causes a query against the map
+.q ali
+to search maps named
+.q ali.nis
+and
+.q ali.files
+in that order.
+.ip dequote
+Strip double quotes (") from a name.
+It does not strip backslashes,
+and 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
+Most of these accept as arguments the same optional flags
+and a filename
+(or a mapname for NIS;
+the filename is the root of the database path,
+so that
+.q .db
+or some other extension appropriate for the database type
+will be added to get the actual database name).
+Known flags are:
+.ip "\-o"
+Indicates that this map is optional \*- that is,
+if it cannot be opened,
+no error is produced,
+and
+.i sendmail
+will behave as if the map existed but was empty.
+.ip "\-N, \-O"
+If neither
+.b \-N
+or
+.b \-O
+are specified,
+.i sendmail
+uses an adaptive algorithm to decide whether or not to look for null bytes
+on the end of keys.
+It starts by trying both;
+if it finds any key with a null byte it never tries again without a null byte
+and vice versa.
+If
+.b \-N
+is specified it never tries without a null byte and
+if
+.b \-O
+is specified it never tries with a null byte.
+Setting one of
+these can speed matches but are never necessary.
+If both
+.b \-N
+and
+.b \-O
+are specified,
+.i sendmail
+will never try any matches at all \(em
+that is, everything will appear to fail.
+.ip "\-a\fIx\fP"
+Append the string
+.i x
+on successful matches.
+For example, the default
+.i host
+map appends a dot on successful matches.
+.ip "\-f"
+Do not 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.
+.ip "\-k\fIkeycol\fP"
+The key column name (for NIS+) or number
+(for text lookups).
+.ip "\-v\fIvalcol\fP"
+The value column name (for NIS+) or number
+(for text lookups).
+.ip "\-z\fIdelim\fP"
+The column delimiter (for text lookups).
+It can be a single character or one of the special strings
+.q \|\en
+or
+.q \|\et
+to indicate newline or tab respectively.
+If omitted entirely,
+the column separator is any sequence of whitespace.
+.ip "\-s\fIspacesub\fP
+For the dequote map only,
+the character to use to replace space characters
+after a successful dequote.
+.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 .
+For example, the map specification
+.(b
+Kuucp dbm \-o \-N /usr/lib/uucpmap
+.)b
+specifies an optional map named
+.q uucp
+of class
+.q dbm ;
+it always has null bytes at the end of every string,
+and the data is located in
+/usr/lib/uucpmap.{dir,pag}.
+.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.
+.lp
+The
+.i sendmail
+daemon does not have to be restarted to read the new maps
+as long as you change them in place;
+file locking is used so that the maps won't be read
+while they are being updated.\**
+.(f
+\**That is, don't create new maps and then use
+.i mv (1)
+to move them into place.
+Since the maps are already open
+the new maps will never be seen.
+.)f
+.pp
+New classes can be added in the routine
+.b setupmaps
+in file
+.b conf.c .
+.sh 2 "The User Database"
+.pp
+If you have a version of
+.i 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 UserDatabaseSpec
+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
+.i 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 mailname
+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 3 "Creating the database\**"
+.(f
+\**These instructions are known to be incomplete.
+A future version of the user database is planned
+including things such as finger service \*- and good documentation.
+.)f
+.pp
+The user database is built from a text file
+using the
+.i makemap
+utility
+(in the distribution in the makemap subdirectory).
+The text file is a series of lines corresponding to userdb records;
+each line has a key and a value separated by white space.
+The key is always in the format described above \*-
+for example:
+.(b
+eric:maildrop
+.)b
+This file is normally installed in a system directory;
+for example, it might be called
+.i /etc/userdb .
+To make the database version of the map, run the program:
+.(b
+makemap btree /etc/userdb.db < /etc/userdb
+.)b
+Then create a config file that uses this.
+For example, using the V8 M4 configuration, include the
+following line in your .mc file:
+.(b
+define(\`confUSERDB_SPEC\', /etc/userdb.db)
+.)b
+.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.
+In most cases this should be unnecessary
+unless you are porting
+.i sendmail
+to a new environment.
+.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,
+.i sendmail
+will read DBM files,
+but will create and use NEWDB files.
+.ip NIS
+Include support for NIS.
+If set together with
+.i both
+NEWDB and NDBM,
+.i sendmail
+will create both DBM and NEWDB files if and only if
+an alias file includes the substring
+.q /yp/
+in the name.
+This is intended for compatibility with Sun Microsystems'
+.i mkalias
+program used on YP masters.
+.ip NISPLUS
+Compile in support for NIS+.
+.ip NETINFO
+Compile in support for NetInfo (NeXT stations).
+.ip HESIOD
+Compile in support for Hesiod.
+.ip _PATH_SENDMAILCF
+The pathname of the sendmail.cf file.
+.ip _PATH_SENDMAILPID
+The pathname of the sendmail.pid file.
+.pp
+There are also several compilation flags to indicate the environment
+such as
+.q _AIX3
+and
+.q _SCO_unix_ .
+See the READ_ME
+file for the latest scoop on these flags.
+.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.
+.pp
+This document is not the best source of information
+for compilation flags in conf.h \(em
+see src/READ_ME or src/conf.h itself.
+.nr ii 1.2i
+.ip "MAXLINE [2048]"
+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 [200]"
+The maximum number of rewriting sets
+that may be defined.
+The first half of these are reserved for numeric specification
+(e.g., ``S92''),
+while the upper half are reserved for auto-numbering
+(e.g., ``Sfoo'').
+Thus, with a value of 200 an attempt to use ``S99'' will succeed,
+but ``S100'' will fail.
+.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 [100]"
+The maximum number of items in the user environment
+that will be passed to subordinate mailers.
+.ip "MAXMXHOSTS [20]"
+The maximum number of MX records we will accept for any single host.
+.ip "MAXALIASDB [12]"
+The maximum number of alias databases that can be open at any time.
+Note that there may also be an open file limit.
+.ip "MAXMAPSTACK [12]"
+The maximum number of maps that may be "stacked" in a
+.b sequence
+class map.
+.ip "MAXMIMEARGS [20]"
+The maximum number of arguments in a MIME Content-Type: header;
+additional arguments will be ignored.
+.ip "MAXMIMENESTING [20]"
+The maximum depth to which MIME messages may be nested
+(that is, nested Message or Multipart documents;
+this does not limit the number of components in a single Multipart document).
+.lp
+A number of other compilation options exist.
+These specify whether or not specific code should be compiled in.
+Ones marked with \(dg
+are 0/1 valued.
+.nr ii 1.2i
+.ip NETINET\(dg
+If set,
+support for Internet protocol networking is compiled in.
+Previous versions of
+.i sendmail
+referred to this as
+.sm DAEMON ;
+this old usage is now incorrect.
+Defaults on;
+turn it off in the Makefile
+if your system doesn't support the Internet protocols.
+.ip NETISO\(dg
+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.
+.b "STRONGLY RECOMMENDED"
+\(em if you want no logging, turn it off in the configuration file.
+.ip MATCHGECOS\(dg
+Compile in the code to do ``fuzzy matching'' on the GECOS field
+in /etc/passwd.
+This also requires that the
+.b MatchGECOS
+option be turned on.
+.ip NAMED_BIND\(dg
+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 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 USERDB\(dg
+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.
+.lp
+The following options are normally turned on
+in per-operating-system clauses in conf.h.
+.ip IDENTPROTO\(dg
+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.
+.ip SYSTEM5
+Set all of the compilation parameters appropriate for System V.
+.ip HASFLOCK\(dg
+Use Berkeley-style
+.b flock
+instead of System V
+.b lockf
+to do file locking.
+Due to the highly unusual semantics of locks
+across forks in
+.b lockf ,
+this should always be used if at all possible.
+.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 HASGETDTABLESIZE
+Set this if you have the
+.i getdtablesize (2)
+system call.
+.ip HASWAITPID
+Set this if you have the
+.i haswaitpid (2)
+system call.
+.ip SFS_TYPE
+The mechanism that can be used to get file system capacity information.
+The values can be one of
+SFS_USTAT (use the ustat(2) syscall),
+SFS_4ARGS (use the four argument statfs(2) syscall),
+SFS_VFS (use the two argument statfs(2) syscall including <sys/vfs.h>),
+SFS_MOUNT (use the two argument statfs(2) syscall including <sys/mount.h>),
+SFS_STATFS (use the two argument statfs(2) syscall including <sys/statfs.h>),
+SFS_STATVFS (use the two argument statfs(2) syscall including <sys/statvfs.h>),
+or
+SFS_NONE (no way to get this information).
+.ip LA_TYPE
+The load average type.
+Details are described below.
+.lp
+The are several 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_SHORT
+The kernel stores the load average in the kernel as an array of short 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_MACH
+Use MACH-style load averages.
+.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 ,
+.sm LA_SHORT ,
+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 "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.
+.ip H_ERRORSTO
+Addresses in this header should receive error messages.
+.ip H_CTE
+This header is a Content-Transfer-Encoding header.
+.ip H_CTYPE
+This header is a Content-Type header.
+.ip H_STRIPVAL
+Strip the value from the header (for Bcc:).
+.nr ii 5n
+.lp
+Let's look at a sample
+.i HdrInfo
+specification:
+.(b
+.ta 4n +\w'"content-transfer-encoding", '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,
+ "errors-to", H_FROM\^|\^H_ERRORSTO,
+ /* destination fields */
+ "to", H_RCPT,
+ "resent-to", H_RCPT,
+ "cc", H_RCPT,
+ "bcc", H_RCPT\^|\^H_STRIPVAL,
+ /* message identification and control */
+ "message", H_EOH,
+ "text", H_EOH,
+ /* trace fields */
+ "received", H_TRACE\^|\^H_FORCE,
+ /* miscellaneous fields */
+ "content-transfer-encoding", H_CTE,
+ "content-type", H_CTYPE,
+
+ 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 && bitnset(M_LOCALMAILER, to\->q_mailer))
+ {
+ usrerr("Message too large for non-local delivery");
+ e\->e_flags |= EF_NORETURN;
+ return (EX_UNAVAILABLE);
+ }
+ return (EX_OK);
+}
+.sz
+.)b
+This would reject messages greater than 50000 bytes
+unless they were local.
+The
+.i EF_NORETURN
+flag can be set in
+.i e\(->e_flags
+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 several 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);
+ 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.
+If you are porting to a new environment
+you may need to add some new tweaks.\**
+.(f
+\**If you do, please send updates to
+sendmail@CS.Berkeley.EDU.
+.)f
+.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 assumes you have BSD style sockets.
+.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 8"
+.pp
+The following summarizes changes
+since the last commonly available version of
+.i sendmail
+(5.67).
+For a detailed list,
+consult the file
+RELEASE_NOTES
+in the root directory of the
+.i sendmail
+distribution.
+.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 8 notices this and tries to batch the messages.
+.sh 2 "RFC 1123 Compliance"
+.pp
+A number of changes have been made to make
+.i sendmail
+.q "conditionally compliant"
+(that is,
+.i sendmail
+satisfies all of the
+.q MUST
+clauses and most but not all of the
+.q SHOULD
+clauses in RFC 1123).
+.pp
+The major areas of change are (numbers are RFC 1123 section numbers):
+.nr ii \w'5.3.1.1\0\0'u
+.ip 5.2.7
+Response to RCPT command is fast.
+.ip 5.2.8
+Numeric IP addresses are logged in Received: lines.
+.ip 5.2.17
+Self domain literal is properly handled.
+.ip 5.3.2
+Better control over individual timeouts.
+.ip 5.3.3
+Error messages are sent as
+.q From:<> .
+.ip 5.3.3
+Error messages are never sent to
+.q <> .
+.ip 5.3.3
+Route-addrs are pruned.
+.lp
+The areas in which
+.i sendmail
+is not
+.q "unconditionally compliant"
+are:
+.ip 5.2.6
+.i Sendmail
+does do header munging.
+.ip 5.2.10
+.i Sendmail
+doesn't always use the exact SMTP message text
+as listed in RFC 821.
+.ip 5.3.1.1
+.i Sendmail
+doesn't guarantee only one connect for each host in queue runs.
+.ip 5.3.1.1
+.i Sendmail
+doesn't always provide adequate concurrency limits.
+.sh 2 "Extended SMTP Support"
+.pp
+Version 8 includes both sending and receiving support for Extended
+SMTP support as defined by RFC 1651 (basic) and RFC 1653 (SIZE);
+and limited support for RFC 1652 (BODY).
+.sh 2 "Eight-Bit Clean"
+.pp
+Previous versions of
+.i 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 output 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
+.i 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
+.i sendmail
+(albeit with a completely different implementation).
+They can be useful on large sites.
+.pp
+Version 8 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 Flags"
+.pp
+The
+.b \-B
+flag has been added to pass in body type information.
+.pp
+The
+.b \-p
+flag has been added
+to pass in protocol information.
+.pp
+The
+.b \-X
+flag has been added
+to allow logging of all protocol in and out of
+.i sendmail
+for debugging.
+.pp
+The
+.b \-O
+flag simplies setting long-form options.
+.sh 2 "Enhanced Command Line Flags"
+.pp
+The
+.b \-q
+flag can limit limit a queue run to specific recipients, senders, or queue ids
+using
+.b \-qR\c
+.i substring ,
+.b \-qS\c
+.i substring ,
+or
+.b \-qI\c
+.i substring
+respectively.
+.sh 2 "New and Old Configuration Line Types"
+.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.
+.pp
+The
+.b M
+line has a
+.q D=
+field that lets you change into a temporary directory while that mailer
+is running.
+It also has a
+.q U=
+field to allow you to set the user and group id to be used
+when running the mailer.
+.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,
+.nr ii 0.5i
+.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
+.i sendmail .
+.ip O
+Set incoming SMTP daemon options, such as an alternate SMTP port.
+.ip p
+Privacy options.
+.ip R
+Don't prune route-addrs.
+.ip U
+User database spec.
+.ip V
+Fallback
+.q MX
+host.
+.ip w
+.q "Best MX"
+handling technique.
+.ip 7
+Do not run eight bit clean.
+.ip 8
+Eight bit data handling mode.
+.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 Flags"
+.pp
+Several new mailer flags have been added.
+.ip a
+Try to use ESMTP when creating a connection.
+If this is not set,
+.i sendmail
+will still try if the other end hints that it knows about ESMTP
+in its greeting message;
+this flag says to try even if it doesn't hint.
+If the EHLO (extended hello)
+command fails,
+.i sendmail
+falls back to old SMTP.
+.ip A
+Try the user part of addresses for this mailer as aliases.
+.ip b
+Ensure that there is a blank line at the end of all messages.
+.ip c
+Strip all comments from addresses;
+this should only be used as a last resort
+when dealing with cranky mailers.
+.ip g
+Never use the null sender as the envelope sender,
+even when running SMTP.
+Although this violates RFC 1123,
+it may be necessary when you must deal with some obnoxious old hosts.
+.ip k
+Turn off the loopback check in the HELO protocol;
+doing this may cause mailer loops.
+.ip o
+Always run the mailer as the recipient of the message.
+.ip w
+This user should have a passwd file entry.
+.ip 5
+Try ruleset 5 if no local aliases.
+.ip 7
+Strip all output to 7 bits.
+.ip :
+Check for :include: files.
+.ip |
+Check for |program addresses.
+.ip /
+Check for /file addresses.
+.ip @
+Check this user against the user database.
+.sh 2 "Long Option Names"
+.pp
+All options can be specified using long names,
+and some new options can only be specified with long names.
+.sh 2 "New Pre-Defined Macros"
+.pp
+The following macros are pre-defined:
+.ip $k
+The UUCP node name,
+nominally from
+.i uname (2)
+call.
+.ip $m
+The domain part of our full hostname.
+.ip $_
+The RFC 1413-provided sender address.
+.sh 2 "New LHS Token"
+.pp
+Version 8 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 8 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 8 has changed the default parameters
+for tuning queue costs
+to make the number of recipients more important
+than the size of the message (for small messages).
+This is reasonable if you are connected with reasonably fast links.
+.sh 2 "Auto-Quoting in Addresses"
+.pp
+Previously, the
+.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.
+EXPN still does.
+.pp
+As an optimization, if you run with your default delivery mode being
+queue-only or deliver-in-background,
+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
+.i 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 2 "Miscellaneous Changes"
+.pp
+.i Sendmail
+writes a
+.i /etc/sendmail.pid
+file with the current process id of the SMTP daemon.
+.pp
+Two people using the same program in their .forward file
+are considered different
+so that duplicate elimination doesn't delete one of them.
+.pp
+The
+.i mailstats
+program prints mailer names
+and gets the location of the
+.i sendmail.st
+file from
+.i /etc/sendmail.cf .
+.pp
+Many minor bugs have been fixed, such as handling of backslashes
+inside of quotes.
+.pp
+A hook (ruleset 5) has been added
+to allow rewriting of local addresses after aliasing.
+.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
+the University of California at Berkeley,
+at Britton Lee,
+and again on the Mammoth and Titan Projects 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 8 in particular was a group project.
+The following people made notable contributions:
+.(l
+John Beck, Hewlett-Packard
+Keith Bostic, CSRG, University of California, Berkeley
+Andrew Cheng, Sun Microsystems
+Michael J. Corrigan, University of California, San Diego
+Bryan Costales, International Computer Science Institute
+Pa\*:r (Pell) Emanuelsson
+Craig Everhart, Transarc Corporation
+Tom Ivar Helbekkmo, Norwegian School of Economics
+Allan E. Johannesen, WPI
+Jonathan Kamens, OpenVision Technologies, Inc.
+Takahiro Kanbe, Fuji Xerox Information Systems Co., Ltd.
+Brian Kantor, University of California, San Diego
+Murray S. Kucherawy, HookUp Communication Corp.
+Bruce Lilly, Sony U.S.
+Karl London
+Motonori Nakamura, Ritsumeikan University & Kyoto University
+John Gardiner Myers, Carnegie Mellon University
+Neil Rickert, Northern Illinois University
+Eric Schnoebelen, Convex Computer Corp.
+Eric Wassenaar, National Institute for Nuclear and High Energy Physics, Amsterdam
+Christophe Wolfhugel, Pasteur Institute & Herve Schauer Consultants (Paris)
+.)l
+I apologize for anyone I have omitted, misspelled, misattributed, or
+otherwise missed.
+At this point, I suspect that at least a hundred people
+have contributed code,
+and many more have contributed ideas, comments, and encouragement.
+I've tried to list them in the RELEASE_NOTES in the distribution directory.
+I appreciate their contribution as well.
+.pp
+Special thanks are reserved for Michael Corrigan and Christophe Wolfhugel,
+who besides being wonderful guinea pigs and contributors
+have also consented to be added to the ``sendmail@CS.Berkeley.EDU'' list
+and, by answering the bulk of the questions sent to that list,
+have freed me up to do other work.
+.++ 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
+a\(dg ``Arpanet'' mode (get envelope sender information from header)
+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
+.)b
+.(f
+\(dgDeprecated.
+.)f
+.ip \-B\fItype\fP
+Indicate body type.
+.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 Section 5.6.
+.ip \-O\fIoption\fP\fB=\fP\fIvalue\fP
+Set
+.i option
+to the specified
+.i value
+(for long form option names).
+These options are described in Section 5.6.
+.ip \-M\fIx\|value
+Set macro
+.i x
+to the specified
+.i value .
+.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
+.i 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.
+.ip "\-X \fIlogfile\fP"
+Log all traffic in and out of
+.i sendmail
+in the indicated
+.i logfile
+for debugging mailer problems.
+This produces a lot of data very quickly and should be used sparingly.
+.pp
+There are a number of options that may be specified as
+primitive flags.
+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 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 V
+The version number of the queue file format,
+used to allow new
+.i sendmail
+binaries to read queue files created by older versions.
+Defaults to version zero.
+Must be the first line of the file if present.
+.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 Q
+The ``original recipient'',
+specified by the ORCPT= field in an ESMTP transaction.
+Used exclusively for Delivery Status Notifications.
+It applies only to the immediately following `R' line.
+.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.
+Version 1 qf files
+also include a leading colon-terminated list of flags,
+which can be
+`S' to return a message on successful final delivery,
+`F' to return a message on failure,
+`D' to return a message if the message is delayed,
+`B' to indicate that the body should be returned,
+`N' to suppress returning the body,
+and
+`P' to declare this as a ``primary'' (command line or SMTP-session) address.
+.ip S
+The sender address.
+There may only be one of these lines.
+.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 N
+The total number of delivery attempts.
+.ip K
+The time (as seconds since January 1, 1970)
+of the last delivery attempt.
+.ip I
+The i-number of the data file;
+this can be used to recover your mail queue
+after a disastrous disk crash.
+.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 .
+.ip O
+The original MTS value (from the ESMTP transaction).
+For Deliver Status Notifications only.
+.ip Z
+The original envelope id (from the ESMTP transaction).
+For Deliver Status Notifications only.
+.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
+Seric
+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 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/\*(SB/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/\*(SB/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 /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.70
+.\".ce 0
+.bp 2
+.rs
+.sp |4i
+.ce 2
+This page intentionally left blank;
+replace it with a blank sheet for double-sided output.
+.bp 3
+.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
index 000000000000..355b3fc8c9a9
--- /dev/null
+++ b/usr.sbin/sendmail/doc/op/op.ps
@@ -0,0 +1,5944 @@
+%!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: 69
+%%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 -.15(Pa)233.085 208.2 S
+(ng\346a Reference Systems).15 E(eric@Sendmail.ORG)245.205 220.2 Q -1.11(Ve)
+262.725 244.2 S(rsion 8.70)1.11 E -.15(Fo)236.965 268.2 S 2.5(rS).15 G
+(endmail V)258.765 268.2 Q(ersion 8.7)-1.11 E/F3 10/Times-Italic@0 SF(Sendmail)
+97 312.6 Q F2 .482(implements a general purpose internetw)2.982 F .482
+(ork mail routing f)-.1 F .481(acility under the UNIX\256 operat-)-.1 F .378
+(ing system.)72 324.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 324.6 R .378
+(ened to a crossbar switch,)-.1 F 1.036
+(relaying messages from one domain into another)72 336.6 R 6.036(.I)-.55 G
+3.536(nt)284.502 336.6 S 1.036
+(he process, it can do a limited amount of message)295.818 336.6 R .604(header\
+ editing to put the message into a format that is appropriate for the recei)72
+348.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 360.6 Q .711
+(Due to the requirements of \215e)97 376.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 376.8 R .71(what unap-)-.25 F 2.893(proachable. Ho)72 388.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 388.8 R .646(ration \214les ha)72 400.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 412.8 Q(.)-.65 E F3(Sendmail)97 429 Q F2 .15
+(is based on RFC821 \(Simple Mail T)2.65 F .15
+(ransport Protocol\), RFC822 \(Internet Mail F)-.35 F .15(ormat Pro-)-.15 F
+.423(tocol\), RFC1123 \(Internet Host Requirements\), RFC1521 \(MIME\), RFC165\
+1 \(SMTP Service Extensions\),)72 441 R .994
+(and a series of as-yet-draft standards describing Deli)72 453 R -.15(ve)-.25 G
+.995(ry Status Noti\214cations \(DSNs\), a).15 F -.25(va)-.2 G .995
+(ilable from the).25 F 1.529
+(internet drafts sites as draft-ietf-notary-mime-deli)72 465 R -.15(ve)-.25 G
+(ry-).15 E F3(XX)A F2 1.528(.txt, draft-ietf-notary-mime-report-)B F3(XX)A F2
+1.528(.txt, draft-)B(ietf-notary-smtp-drpt-)72 477 Q F3(XX)A F2 1.93
+(.txt, and draft-ietf-notary-status-)B F3(XX)A F2 1.93(.txt \(replace)B F3(XX)
+4.43 E F2 1.93(by the latest draft number\).)4.43 F(Ho)72 489 Q(we)-.25 E -.15
+(ve)-.25 G .831 -.4(r, s).15 H(ince).4 E F3(sendmail)2.531 E F2 .031
+(is designed to w)2.531 F .031(ork in a wider w)-.1 F .03(orld, in man)-.1 F
+2.53(yc)-.15 G .03(ases it can be con\214gured to e)365.12 489 R(xceed)-.15 E
+(these protocols.)72 501 Q(These cases are described herein.)5 E(Although)97
+517.2 Q F3(sendmail)3.547 E F2 1.048(is intended to run without the need for m\
+onitoring, it has a number of features)3.547 F 1.972(that may be used to monit\
+or or adjust the operation under unusual circumstances.)72 529.2 R 1.972
+(These features are)6.972 F(described.)72 541.2 Q .816
+(Section one describes ho)97 557.4 R 3.316(wt)-.25 G 3.316(od)211.664 557.4 S
+3.316(oab)224.98 557.4 S(asic)246.052 557.4 Q F3(sendmail)3.316 E F2 3.317
+(installation. Section)3.317 F(tw)3.317 E 3.317(oe)-.1 G .817
+(xplains the day-to-day)412.936 557.4 R .283(information you should kno)72
+569.4 R 2.783(wt)-.25 G 2.783(om)196.772 569.4 S .282
+(aintain your mail system.)212.335 569.4 R .282(If you ha)5.282 F .582 -.15
+(ve a r)-.2 H(elati).15 E -.15(ve)-.25 G .282(ly normal site, these tw).15 F(o)
+-.1 E .634(sections should contain suf)72 581.4 R .635
+(\214cient information for you to install)-.25 F F3(sendmail)3.135 E F2 .635
+(and k)3.135 F .635(eep it happ)-.1 F 4.435 -.65(y. S)-.1 H .635(ection three)
+.65 F .925(describes some parameters that may be safely tweak)72 593.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 .885(mand line ar)72 605.4 R 3.385(guments. Section)-.18
+F<8c76>3.385 E 3.385(ec)-.15 G .886
+(ontains the nitty-gritty information about the con\214guration \214le.)221.915
+605.4 R(This)5.886 E .005
+(section is for masochists and people who must write their o)72 617.4 R .004
+(wn con\214guration \214le.)-.25 F .004(Section six describes con-)5.004 F .886
+(\214guration that can be done at compile time.)72 629.4 R .886(Section se)
+5.886 F -.15(ve)-.25 G 3.386(ng).15 G -2.15 -.25(iv e)322.098 629.4 T 3.386
+(sab).25 G .886(rief description of dif)354.02 629.4 R .886(ferences in this)
+-.25 F -.15(ve)72 641.4 S 1.62(rsion of).15 F F3(sendmail)4.12 E F2 6.62(.T)C
+1.62(he appendix)169.2 641.4 R 1.62(es gi)-.15 F 1.92 -.15(ve a b)-.25 H 1.619
+(rief b).15 F 1.619(ut detailed e)-.2 F 1.619
+(xplanation of a number of features not)-.15 F
+(described in the rest of the paper)72 653.4 Q(.)-.55 E/F4 10/Times-Bold@0 SF
+-1.2(WA)97 669.6 S(RNING:)1.2 E F2(Se)3.267 E -.15(ve)-.25 G .767
+(ral major changes were introduced in v).15 F .767(ersion 8.7.)-.15 F -1.1(Yo)
+5.767 G 3.267(us)1.1 G .767(hould not attempt to use)404.26 669.6 R
+(this document for prior v)72 681.6 Q(ersions of)-.15 E F3(sendmail)2.5 E F2(.)
+A F4(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-1)457.9 756 Q EP
+%%Page: 7 2
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-7)457.9 60 Q 2.5(1. B)72 96 R(ASIC INST)-.3 E(ALLA)-.9 E(TION)-.95 E/F1
+10/Times-Roman@0 SF .234(There are tw)112 112.2 R 2.733(ob)-.1 G .233
+(asic steps to installing)175.631 112.2 R/F2 10/Times-Italic@0 SF(sendmail)
+2.733 E F1 5.233(.T)C .233(he hard part is to b)317.076 112.2 R .233
+(uild the con\214guration table.)-.2 F 1.185(This is a \214le that)87 124.2 R
+F2(sendmail)3.686 E F1 1.186
+(reads when it starts up that describes the mailers it kno)3.686 F 1.186
+(ws about, ho)-.25 F 3.686(wt)-.25 G(o)499 124.2 Q .715(parse addresses, ho)87
+136.2 R 3.215(wt)-.25 G 3.215(or)178.315 136.2 S -.25(ew)189.86 136.2 S .715
+(rite the message header).25 F 3.215(,a)-.4 G .715(nd the settings of v)306.75
+136.2 R .714(arious options.)-.25 F .714(Although the)5.714 F .852
+(con\214guration table is quite comple)87 148.2 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 160.2 R
+1.078(The second part is actually doing the installation, i.e., creating the n\
+ecessary)6.078 F(\214les, etc.)87 172.2 Q .192
+(The remainder of this section will describe the installation of)112 188.4 R F2
+(sendmail)2.692 E F1 .192(assuming you can use one)2.692 F 1.432(of the e)87
+200.4 R 1.432(xisting con\214gurations and that the standard installation para\
+meters are acceptable.)-.15 F 1.431(All path-)6.431 F 8.62(names and e)87 212.4
+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 212.4 R F2(sendmail)378.16 212.4 Q F1 8.62
+(subtree, normally)425.39 212.4 R F2(/usr/sr)87 224.4 Q(c/usr)-.37 E
+(.sbin/sendmail)-1.11 E F1(on 4.4BSD.)2.5 E .543(If you are loading this of)112
+240.6 R 3.042(ft)-.25 G .542(he tape, continue with the ne)222.766 240.6 R .542
+(xt section.)-.15 F .542(If you ha)5.542 F .842 -.15(ve a r)-.2 H .542
+(unning binary).15 F
+(already on your system, you should probably skip to section 1.2.)87 252.6 Q F0
+2.5(1.1. Compiling)87 276.6 R(Sendmail)2.5 E F1(All)127 292.8 Q F2(sendmail)
+2.934 E F1 .434(source is in the)2.934 F F2(sr)2.934 E(c)-.37 E F1
+(subdirectory)2.934 E 5.434(.I)-.65 G 2.934(fy)321.652 292.8 S .435
+(ou are running on a 4.4BSD system, com-)332.916 292.8 R .179
+(pile by typing \231mak)102 304.8 R 2.679(e\232. On)-.1 F .179
+(other systems, you may ha)2.679 F .479 -.15(ve t)-.2 H 2.679(om).15 G(ak)
+350.719 304.8 Q 2.679(es)-.1 G .178(ome other adjustments.)371.068 304.8 R .178
+(On most)5.178 F(systems, you can do the appropriate compilation by typing)102
+316.8 Q(sh mak)142 333 Q(esendmail)-.1 E .364(This will lea)102 349.2 R .664
+-.15(ve t)-.2 H .364(he binary in an appropriately named subdirectory).15 F
+5.364(.I)-.65 G 2.864(tw)377.37 349.2 S .364(orks for multiple object v)390.134
+349.2 R(er)-.15 E(-)-.2 E(sions compiled out of the same directory)102 361.2 Q
+(.)-.65 E F0 2.5(1.1.1. T)102 385.2 R(weaking the Mak)-.74 E(e\214le)-.1 E F2
+(Sendmail)142 401.4 Q F1 2.181(supports tw)4.681 F 4.681(od)-.1 G(if)247.053
+401.4 Q 2.181(ferent formats for the local \(on disk\) v)-.25 F 2.18
+(ersion of databases,)-.15 F(notably the)117 413.4 Q F2(aliases)2.5 E F1 2.5
+(database. At)2.5 F(least one of these should be de\214ned if at all possible.)
+2.5 E 39.5(NDBM The)117 429.6 R -.74(``)3.166 G(ne).74 E 3.166(wD)-.25 G(BM')
+240.432 429.6 Q 3.166('f)-.74 G .666(ormat, a)268.408 429.6 R -.25(va)-.2 G
+.666(ilable on nearly all systems around today).25 F 5.667(.T)-.65 G(his)492.33
+429.6 Q -.1(wa)189 441.6 S 3.541(st).1 G 1.041
+(he preferred format prior to 4.4BSD.)210.771 441.6 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 441.6 R
+(multiple databases and closing a currently open database.)189 453.6 Q 32.84
+(NEWDB The)117 469.8 R(ne)3.323 E 3.323(wd)-.25 G .824
+(atabase package from Berk)232.606 469.8 R(ele)-.1 E 4.624 -.65(y. I)-.15 H
+3.324(fy).65 G .824(ou ha)382.716 469.8 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 481.8 R -1.1(Yo)189 493.8 S 3.581(uc)1.1 G 1.081
+(an de\214ne this in conjunction with one of the other tw)213.141 493.8 R 1.082
+(o; if you do, old)-.1 F .693(databases are read, b)189 505.8 R .693
+(ut when a ne)-.2 F 3.193(wd)-.25 G .693
+(atabase is created it will be in NEWDB)341.681 505.8 R 2.851(format. As)189
+517.8 R 2.851(an)2.851 G .351(asty hack, if you ha)249.763 517.8 R .652 -.15
+(ve N)-.2 H .352(EWDB, NDBM, and NIS de\214ned, and).15 F .952
+(if the alias \214le name includes the substring \231/yp/\232,)189 529.8 R F2
+(sendmail)3.451 E F1 .951(will create both)3.451 F(ne)189 541.8 Q 3.975(wa)-.25
+G 1.475(nd old v)213.825 541.8 R 1.475(ersions of the alias \214le during a)
+-.15 F F2(ne)3.976 E(walias)-.15 E F1 3.976(command. This)3.976 F(is)3.976 E
+.711(required because the Sun NIS/YP system reads the DBM v)189 553.8 R .71
+(ersion of the alias)-.15 F 2.5(\214le. It')189 565.8 R 2.5(su)-.55 G
+(gly as sin, b)229.56 565.8 Q(ut it w)-.2 E(orks.)-.1 E 1.112
+(If neither of these are de\214ned,)117 582 R F2(sendmail)3.612 E F1 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 1.043(This can be slo)117 594 R 3.543(wa)-.25 G
+1.043(nd should be a)195.352 594 R -.2(vo)-.2 G 3.543(ided. There).2 F 1.043
+(are also se)3.543 F -.15(ve)-.25 G 1.042(ral methods for remote database).15 F
+(access:)117 606 Q 53.39(NIS Sun')117 622.2 R 2.5(sN)-.55 G(etw)220.95 622.2 Q
+(ork Information Services \(formerly YP\).)-.1 E 28.94(NISPLUS Sun')117 638.4 R
+2.5(sN)-.55 G(IS+ services.)220.95 638.4 Q 26.73(NETINFO NeXT')117 654.6 R 2.5
+(sN)-.55 G(etInfo service.)230.38 654.6 Q 32.84(HESIOD Hesiod)117 670.8 R
+(service \(from Athena\).)2.5 E .042(Other compilation \215ags are set in conf\
+.h and should be prede\214ned for you unless you are porting)117 687 R(to a ne)
+117 699 Q 2.5(we)-.25 G -.4(nv)157.57 699 S(ironment.).4 E EP
+%%Page: 8 3
+%%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 2.5(1.1.2. Compilation)102 96 R
+(and installation)2.5 E/F1 10/Times-Roman@0 SF .309
+(After making the local system con\214guration described abo)142 112.2 R -.15
+(ve)-.15 G 2.808(,Y).15 G .308(ou should be able to com-)398.86 112.2 R
+(pile and install the system.)117 124.2 Q(The script \231mak)5 E
+(esendmail\232 is the best approach on most systems:)-.1 E(sh mak)157 140.4 Q
+(esendmail)-.1 E(This will use)117 156.6 Q/F2 10/Times-Italic@0 SF(uname)2.5 E
+F1(\(1\) to select the correct Mak)A(e\214le for your en)-.1 E(vironment.)-.4 E
+-1.1(Yo)142 172.8 S 2.5(um)1.1 G(ay be able to install using)168.4 172.8 Q
+(sh mak)157 189 Q(esendmail install)-.1 E 3.346
+(This should install the binary in /usr/sbin and create links from /usr/bin/ne)
+117 205.2 R -.1(wa)-.25 G 3.346(liases and).1 F 1.577
+(/usr/bin/mailq to /usr/sbin/sendmail.)117 217.2 R 1.577
+(On 4.4BSD systems it will also format and install man)6.577 F(pages.)117 229.2
+Q F0 2.5(1.2. Con\214guration)87 253.2 R(Files)2.5 E F2(Sendmail)127 269.4 Q F1
+2.079(cannot operate without a con\214guration \214le.)4.579 F 2.079
+(The con\214guration de\214nes the mail)7.079 F(deli)102 281.4 Q -.15(ve)-.25 G
+.889(ry mechanisms understood at this site, ho).15 F 3.389(wt)-.25 G 3.389(oa)
+309.783 281.4 S .889(ccess them, ho)322.612 281.4 R 3.388(wt)-.25 G 3.388(of)
+396.128 281.4 S(orw)407.846 281.4 Q .888(ard email to remote)-.1 F .088
+(mail systems, and a number of tuning parameters.)102 293.4 R .088
+(This con\214guration \214le is detailed in the later por)5.088 F(-)-.2 E
+(tion of this document.)102 305.4 Q(The)127 321.6 Q F2(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 333.6 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 345.6 Q(xity)-.15 E(.)-.65 E .47
+(These con\214guration \214les are simpler than old v)127 361.8 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 373.8 R 3.948(,t)-.4 G -.15(ex)197.604 373.8 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 385.8 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 402 R .361(is, instead of naming hosts as \231host!user\232 the)
+102 414 R 2.861(yw)-.15 G .361(ill use \231host.domain!user\232.)299.435 414 R
+.361(The con\214guration \214les)5.361 F(can be customized to w)102 426 Q
+(ork around this, b)-.1 E(ut it is more comple)-.2 E(x.)-.15 E .658
+(Our con\214guration \214les are processed by)127 442.2 R F2(m4)3.158 E F1 .658
+(to f)3.158 F .657(acilitate local customization; the directory)-.1 F F2(cf)
+3.157 E F1 .396(of the)102 454.2 R F2(sendmail)2.896 E F1(distrib)2.896 E .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 466.2 Q 61.73(cf Both)102 482.4 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 494.4 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 506.4 R .536(connected host or \231uu\
+cpproto.mc\232 as a general description of a UUCP-connected)174 518.4 R 3.291
+(host\). Files)174 530.4 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 542.4 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 554.4 Q -.65(w.)-.25 G 39.5(domain Site-dependent)102 570.6
+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 582.6 R .292
+(ants to do addressing.)-.1 F -.15(Fo)5.292 G 2.792(re).15 G(xample,)313.122
+582.6 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 594.6 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 606.6 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 618.6 R -.15(ve)-.25 G 2.628
+(rything looks lik).15 F 5.128(ei)-.1 G 5.128(tc)362.038 618.6 S 2.627
+(omes from CS.Berk)374.386 618.6 R(ele)-.1 E -.65(y.)-.15 G(EDU\).).65 E
+(These are referenced using the)174 630.6 Q/F3 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 41.74
+(feature De\214nitions)102 646.8 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 658.8 R F3(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 \(which tells)174 670.8 R F2
+(sendmail)3.816 E F1 1.317(to read an /etc/sendmail.cw \214le on startup to)
+3.816 F(\214nd the set of local names\).)174 682.8 Q 50.62(hack Local)102 699 R
+1.886(hacks, referenced using the)4.387 F F3(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 711 Q(ving them here is to mak)-.2 E 2.5(ei)-.1 G
+2.5(tc)325.91 711 S(lear that the)335.63 711 Q 2.5(ys)-.15 G(mell.)394.08 711 Q
+EP
+%%Page: 9 4
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-9)457.9 60 Q/F1 10/Times-Roman@0 SF 56.72(m4 Site-independent)102 96 R
+/F2 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 108 Q
+(This can be thought of as a \231#include\232 directory)5 E(.)-.65 E 43.95
+(mailer De\214nitions)102 124.2 R .152(of mailers, referenced using the)2.653 F
+/F3 9/Times-Roman@0 SF(MAILER)2.652 E F0(m4)2.652 E F1 2.652(macro. The)2.652 F
+.152(mailer types)2.652 F 1.786(that are kno)174 136.2 R 1.787
+(wn in this distrib)-.25 F 1.787(ution are f)-.2 F 1.787
+(ax, local, smtp, uucp, and usenet.)-.1 F -.15(Fo)6.787 G(r).15 E -.15(ex)174
+148.2 S(ample, to include support for the UUCP-based mailers, use \231MAILER\(\
+uucp\)\232.).15 E 43.39(ostype De\214nitions)102 164.4 R 1.157(describing v)
+3.657 F 1.157(arious operating system en)-.25 F 1.156
+(vironments \(such as the loca-)-.4 F(tion of support \214les\).)174 176.4 Q
+(These are referenced using the)5 E F3(OSTYPE)2.5 E F0(m4)2.5 E F1(macro.)2.5 E
+60.61(sh Shell)102 192.6 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 192.6 Q 2.5(th)-.18
+G -2.25 -.2(av e)404.18 192.6 T(to mess with these.)2.7 E 30.61
+(sitecon\214g Local)102 208.8 R .49
+(site con\214guration information, such as UUCP connecti)2.99 F(vity)-.25 E
+5.49(.T)-.65 G(he)450.61 208.8 Q 2.99(yn)-.15 G(ormally)472.89 208.8 Q
+(contain lists of site information, for e)174 220.8 Q(xample:)-.15 E
+(SITE\(contessa\))214 237 Q(SITE\(hoptoad\))214 249 Q(SITE\(nkainc\))214 261 Q
+(SITE\(well\))214 273 Q(The)174 289.2 Q 2.5(ya)-.15 G
+(re referenced using the SITECONFIG macro:)201.34 289.2 Q
+(SITECONFIG\(site.con\214g.\214le, name_of_site, X\))214 305.4 Q(where)174
+321.6 Q F2(X)2.704 E F1 .204(is the macro/class name to use.)2.704 F .203
+(It can be U \(indicating locally connected)5.204 F(hosts\) or one of W)174
+333.6 Q 2.5(,X)-.92 G 2.5(,o)259.73 333.6 S 2.5(rYf)269.73 333.6 S
+(or up to three remote UUCP hubs.)288.61 333.6 Q .756(If you are in a ne)127
+349.8 R 3.256(wd)-.25 G .756(omain \(e.g., a compan)214.036 349.8 R .757
+(y\), you will probably w)-.15 F .757(ant to create a cf/domain)-.1 F .871
+(\214le for your domain.)102 361.8 R .871
+(This consists primarily of relay de\214nitions: for e)5.871 F .87
+(xample, Berk)-.15 F(ele)-.1 E(y')-.15 E 3.37(sd)-.55 G(omain)479 361.8 Q .16
+(de\214nition de\214nes relays for BitNET)102 373.8 R 2.66(,C)-.74 G(SNET)
+257.61 373.8 Q 2.66(,a)-.74 G .16(nd UUCP)291.47 373.8 R 5.16(.O)-1.11 G 2.66
+(ft)344.57 373.8 S .16(hese, only the UUCP relay is particu-)353.34 373.8 R .46
+(larly speci\214c to Berk)102 385.8 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 385.8 Q(-)-.2 E(tain the)102 397.8 Q 2.5(ya)-.15
+G(re reasonable for your domain.)143.51 397.8 Q 1.406(Subdomains at Berk)127
+414 R(ele)-.1 E 3.906(ya)-.15 G 1.407
+(re also represented in the cf/domain directory)235.678 414 R 6.407(.F)-.65 G
+1.407(or e)439.406 414 R 1.407(xample, the)-.15 F 1.491(domain cs-e)102 426 R
+1.491(xposed is the Computer Science subdomain with the local hostname sho)-.15
+F 1.49(wn to other)-.25 F 1.41(users; cs-hidden mak)102 438 R 1.411
+(es users appear to be from the CS.Berk)-.1 F(ele)-.1 E -.65(y.)-.15 G 1.411
+(EDU subdomain \(with no local).65 F 1.084(host information included\).)102 450
+R -1.1(Yo)6.084 G 3.584(uw)1.1 G 1.084(ill probably ha)246.336 450 R 1.384 -.15
+(ve t)-.2 H 3.584(ou).15 G 1.083(pdate this directory to be appropriate for)
+335.872 450 R(your domain.)102 462 Q -1.1(Yo)127 478.2 S 4.372(uw)1.1 G 1.872
+(ill ha)154.712 478.2 R 2.172 -.15(ve t)-.2 H 4.372(ou).15 G 1.872
+(se or create)207.478 478.2 R F0(.mc)4.372 E F1 1.872(\214les in the)4.372 F F2
+(cf/cf)4.372 E F1 1.873(subdirectory for your hosts.)4.373 F 1.873(This is)
+6.873 F(detailed in the cf/README \214le.)102 490.2 Q F0 2.5(1.3. Details)87
+514.2 R(of Installation Files)2.5 E F1
+(This subsection describes the \214les that comprise the)127 530.4 Q F2
+(sendmail)2.5 E F1(installation.)2.5 E F0 2.5(1.3.1. /usr/sbin/sendmail)102
+554.4 R F1 .079(The binary for)142 572.6 R F2(sendmail)2.579 E F1 .079
+(is located in /usr/sbin)2.579 F/F4 7/Times-Roman@0 SF(1)326.703 568.6 Q F1
+5.079(.I)330.203 572.6 S 2.579(ts)341.112 572.6 S .08(hould be setuid root.)
+350.361 572.6 R -.15(Fo)5.08 G 2.58(rs).15 G .08(ecurity rea-)458.11 572.6 R
+(sons, /, /usr)117 586.6 Q 2.5(,a)-.4 G(nd /usr/sbin should be o)171.6 586.6 Q
+(wned by root, mode 755)-.25 E F4(2)364.4 582.6 Q F1(.)367.9 586.6 Q F0 2.5
+(1.3.2. /etc/sendmail.cf)102 610.6 R F1 .699
+(This is the con\214guration \214le for)142 628.8 R F2(sendmail)3.199 E F4(3)
+311.744 624.8 Q F1 5.698(.T)315.244 628.8 S .698
+(his and /etc/sendmail.pid are the only non-)329.552 628.8 R .32 LW 76 638.4 72
+638.4 DL 80 638.4 76 638.4 DL 84 638.4 80 638.4 DL 88 638.4 84 638.4 DL 92
+638.4 88 638.4 DL 96 638.4 92 638.4 DL 100 638.4 96 638.4 DL 104 638.4 100
+638.4 DL 108 638.4 104 638.4 DL 112 638.4 108 638.4 DL 116 638.4 112 638.4 DL
+120 638.4 116 638.4 DL 124 638.4 120 638.4 DL 128 638.4 124 638.4 DL 132 638.4
+128 638.4 DL 136 638.4 132 638.4 DL 140 638.4 136 638.4 DL 144 638.4 140 638.4
+DL 148 638.4 144 638.4 DL 152 638.4 148 638.4 DL 156 638.4 152 638.4 DL 160
+638.4 156 638.4 DL 164 638.4 160 638.4 DL 168 638.4 164 638.4 DL 172 638.4 168
+638.4 DL 176 638.4 172 638.4 DL 180 638.4 176 638.4 DL 184 638.4 180 638.4 DL
+188 638.4 184 638.4 DL 192 638.4 188 638.4 DL 196 638.4 192 638.4 DL 200 638.4
+196 638.4 DL 204 638.4 200 638.4 DL 208 638.4 204 638.4 DL 212 638.4 208 638.4
+DL 216 638.4 212 638.4 DL/F5 5/Times-Roman@0 SF(1)93.6 648.8 Q/F6 8
+/Times-Roman@0 SF .385(This is usually /usr/sbin on 4.4BSD and ne)3.2 J .385
+(wer systems; man)-.2 F 2.385(ys)-.12 G .385(ystems install it in /usr/lib)
+302.966 652 R 4.384(.I)-.32 G .384(understand it is in /usr/ucblib on)398.744
+652 R(System V Release 4.)72 661.6 Q F5(2)93.6 672 Q F6 .15(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/F7 8/Times-Italic@0 SF(sendmail)2.15 E F6 4.15(.O)C .149(ther important di-)
+447.262 675.2 R(rectories that should ha)72 684.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 F5(3)93.6 695.2 Q F6
+(Actually)3.2 I 2.276(,t)-.52 G .276(he pathname v)129.632 698.4 R .276
+(aries depending on the operating system; /etc is the preferred directory)-.2 F
+4.276(.S)-.52 G .277(ome older systems install it)415.332 698.4 R(in)72 708 Q
+/F8 8/Times-Bold@0 SF(/usr/lib/sendmail.cf)2 E F6 2(,a)C(nd I')153.344 708 Q
+.24 -.12(ve a)-.4 H(lso seen it in).12 E F8(/usr/ucblib)2 E F6(and)2 E F8
+(/etc/mail)2 E F6 4(.I)C 2(fy)313.928 708 S(ou w)322.592 708 Q(ant to mo)-.08 E
+.24 -.12(ve t)-.12 H(his \214le, change).12 E F7(sr)2 E(c/conf)-.296 E(.h)-.12
+E F6(.)A EP
+%%Page: 10 5
+%%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
+(library \214le names compiled into)117 98 Q/F2 10/Times-Italic@0 SF(sendmail)
+2.5 E/F3 7/Times-Roman@0 SF(4)283.38 94 Q F1(.)286.88 98 Q .721
+(The con\214guration \214le is normally created using the distrib)142 114.2 R
+.721(ution \214les described abo)-.2 F -.15(ve)-.15 G 5.72(.I).15 G(f)500.67
+114.2 Q .64(you ha)117 126.2 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
+138.2 Q F0 2.5(1.3.3. /usr/bin/newaliases)102 162.2 R F1(The)142 178.4 Q F2(ne)
+2.5 E(waliases)-.15 E F1(command should just be a link to)2.5 E F2(sendmail)2.5
+E F1(:)A(rm \255f /usr/bin/ne)157 194.6 Q -.1(wa)-.25 G(liases).1 E
+(ln \255s /usr/sbin/sendmail /usr/bin/ne)157 206.6 Q -.1(wa)-.25 G(liases).1 E
+(This can be installed in whate)117 222.8 Q -.15(ve)-.25 G 2.5(rs).15 G
+(earch path you prefer for your system.)254.91 222.8 Q F0 2.5(1.3.4. /v)102
+246.8 R(ar/spool/mqueue)-.1 E F1 .218(The directory)142 263 R F2
+(/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 275 Q
+(wned by root.)-.25 E(The actual path of this directory is de\214ned in the)142
+291.2 Q F0(Q)2.5 E F1(option of the)2.5 E F2(sendmail.cf)2.5 E F1(\214le.)2.5 E
+F0 2.5(1.3.5. /etc/aliases*)102 315.2 R F1 1.492
+(The system aliases are held in \231/etc/aliases\232.)142 331.4 R 3.992(As)
+6.492 G 1.492(ample is gi)350.006 331.4 R -.15(ve)-.25 G 3.993(ni).15 G 3.993
+<6e99>417.694 331.4 S 1.493(lib/aliases\232 which)431.127 331.4 R
+(includes some aliases which)117 343.4 Q F2(must)2.5 E F1(be de\214ned:)2.5 E
+(cp lib/aliases /etc/aliases)157 359.6 Q F2(edit /etc/aliases)157 371.6 Q F1
+-1.1(Yo)117 387.8 S 2.5(us)1.1 G(hould e)139.51 387.8 Q
+(xtend this \214le with an)-.15 E 2.5(ya)-.15 G
+(liases that are apropos to your system.)267.54 387.8 Q(Normally)142 404 Q F2
+(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 F2(dbm)3.609 E F1 1.109
+(\(3\) or)1.666 F F2(db)3.609 E F1(\(3\))1.666 E 3.46(routines. These)117 416 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 428 R 1.022
+(These can initially be created as empty)6.022 F(\214les, b)117 440 Q(ut the)
+-.2 E 2.5(yw)-.15 G(ill ha)180.54 440 Q .3 -.15(ve t)-.2 H 2.5(ob).15 G 2.5(ei)
+227.69 440 S(nitialized promptly)237.41 440 Q 5(.T)-.65 G
+(hese should be mode 644:)326.76 440 Q(cp /de)157 456.2 Q
+(v/null /etc/aliases.dir)-.25 E(cp /de)157 468.2 Q(v/null /etc/aliases.pag)-.25
+E(chmod 644 /etc/aliases.*)157 480.2 Q(ne)157 492.2 Q -.1(wa)-.25 G(liases).1 E
+(The)117 508.4 Q F2(db)2.79 E F1 .29(routines preset the mode reasonably)2.79 F
+2.79(,s)-.65 G 2.79(ot)301.68 508.4 S .29(his step can be skipped.)312.25 508.4
+R .29(The actual path of this)5.29 F(\214le is de\214ned in the)117 520.4 Q F0
+(A)2.5 E F1(option of the)2.5 E F2(sendmail.cf)2.5 E F1(\214le.)2.5 E F0 2.5
+(1.3.6. /etc/r)102 544.4 R(c)-.18 E F1 .156
+(It will be necessary to start up the)142 560.6 R F2(sendmail)2.655 E F1 .155
+(daemon when your system reboots.)2.655 F .155(This dae-)5.155 F 1.537
+(mon performs tw)117 572.6 R 4.037(of)-.1 G 1.537
+(unctions: it listens on the SMTP sock)201.221 572.6 R 1.537
+(et for connections \(to recei)-.1 F 1.838 -.15(ve m)-.25 H(ail).15 E .442(fro\
+m a remote system\) and it processes the queue periodically to insure that mai\
+l gets deli)117 584.6 R -.15(ve)-.25 G(red).15 E(when hosts come up.)117 596.6
+Q .505(Add the follo)142 612.8 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 624.8 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(4)93.6 679.6 Q/F5 8/Times-Roman@0 SF .588
+(The system libraries can reference other \214les; in particular)3.2 J 2.589
+(,s)-.32 G .589(ystem library subroutines that)294.805 682.8 R/F6 8
+/Times-Italic@0 SF(sendmail)2.589 E F5 .589(calls probably reference)2.589 F F6
+(/etc/passwd)72 692.4 Q F5(and)2 E F6(/etc/r)2 E(esolv)-.296 E(.conf)-.592 E F5
+(.)A EP
+%%Page: 11 6
+%%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
+(if [ \255f /usr/sbin/sendmail \255a \255f /etc/sendmail.cf ]; then)157 96 Q
+(\(cd /v)193 108 Q(ar/spool/mqueue; rm \255f [lnx]f*\))-.25 E
+(/usr/sbin/sendmail \255bd \255q30m &)193 120 Q(echo \255n ' sendmail' >/de)193
+132 Q(v/console)-.25 E<8c>157 144 Q .174
+(The \231cd\232 and \231rm\232 commands insure that all lock \214les ha)117
+160.2 R .473 -.15(ve b)-.2 H .173(een remo).15 F -.15(ve)-.15 G .173(d; e).15 F
+.173(xtraneous lock \214les)-.15 F .004
+(may be left around if the system goes do)117 172.2 R .005
+(wn in the middle of processing a message.)-.25 F .005(The line that)5.005 F
+2.294(actually in)117 184.2 R -.2(vo)-.4 G -.1(ke).2 G(s).1 E/F2 10
+/Times-Italic@0 SF(sendmail)4.794 E F1 2.294(has tw)4.794 F 4.794<6f8d>-.1 G
+2.293(ags: \231\255bd\232 causes it to listen on the SMTP port, and)272.94
+184.2 R(\231\255q30m\232 causes it to run the queue e)117 196.2 Q -.15(ve)-.25
+G(ry half hour).15 E(.)-.55 E .378(Some people use a more comple)142 212.4 R
+2.879(xs)-.15 G .379(tartup script, remo)285.209 212.4 R .379
+(ving zero length qf \214les and df \214les)-.15 F 1.121
+(for which there is no qf \214le.)117 224.4 R -.15(Fo)6.121 G 3.621(re).15 G
+1.12(xample, see Figure 1 for an e)262.868 224.4 R 1.12(xample of a comple)-.15
+F 3.62(xs)-.15 G(tartup)480.67 224.4 Q(script.)117 236.4 Q .755
+(If you are not running a v)142 252.6 R .755(ersion of UNIX that supports Berk)
+-.15 F(ele)-.1 E 3.256(yT)-.15 G(CP/IP)416.722 252.6 Q 3.256(,d)-1.11 G 3.256
+(on)450.268 252.6 S .756(ot include)463.524 252.6 R(the)117 264.6 Q F0(\255bd)
+2.5 E F1(\215ag.)2.5 E F0 2.5(1.3.7. /usr/lib/sendmail.hf)102 288.6 R F1 2.078
+(This is the help \214le used by the SMTP)142 304.8 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 316.8 Q(cp lib/sendmail.hf /usr/lib)157 333 Q
+(The actual path of this \214le is de\214ned in the)117 349.2 Q F0(H)2.5 E F1
+(option of the)2.5 E F2(sendmail.cf)2.5 E F1(\214le.)2.5 E F0 2.5
+(1.3.8. /etc/sendmail.st)102 373.2 R F1 3.04
+(If you wish to collect statistics about your mail traf)142 389.4 R 3.04
+(\214c, you should create the \214le)-.25 F(\231/etc/sendmail.st\232:)117 401.4
+Q(cp /de)157 417.6 Q(v/null /etc/sendmail.st)-.25 E(chmod 666 /etc/sendmail.st)
+157 429.6 Q .716(This \214le does not gro)117 445.8 R 4.516 -.65(w. I)-.25 H
+3.216(ti).65 G 3.216(sp)231.506 445.8 S .716
+(rinted with the program \231mailstats/mailstats.c.)243.612 445.8 R 5.715<9a54>
+-.7 G .715(he actual path)447.03 445.8 R(of this \214le is de\214ned in the)117
+457.8 Q F0(S)2.5 E F1(option of the)2.5 E F2(sendmail.cf)2.5 E F1(\214le.)2.5 E
+F0 2.5(1.3.9. /usr/bin/mailq)102 481.8 R F1(If)142 498 Q F2(sendmail)3.439 E F1
+.939(is in)3.439 F -.2(vo)-.4 G -.1(ke).2 G 3.439(da).1 G 3.439<7399>241.156
+498 S(mailq,)252.925 498 Q 3.439<9a69>-.7 G 3.439(tw)288.164 498 S .939
+(ill simulate the)301.603 498 R F0(\255bp)3.439 E F1 .94(\215ag \(i.e.,)3.44 F
+F2(sendmail)3.44 E F1 .94(will print)3.44 F
+(the contents of the mail queue; see belo)117 510 Q 2.5(w\). This)-.25 F
+(should be a link to /usr/sbin/sendmail.)2.5 E F0 2.5(2. NORMAL)72 534 R(OPERA)
+2.5 E(TIONS)-.95 E 2.5(2.1. The)87 558 R(System Log)2.5 E F1 1.511
+(The system log is supported by the)127 574.2 R F2(syslo)4.011 E(gd)-.1 E F1
+1.511(\(8\) program.)1.666 F 1.511(All messages from)6.511 F F2(sendmail)4.011
+E F1(are)4.011 E(logged under the)102 588.2 Q/F3 9/Times-Roman@0 SF(LOG_MAIL)
+2.5 E F1 -.1(fa)2.5 G(cility).1 E/F4 7/Times-Roman@0 SF(5)248.43 584.2 Q F1(.)
+251.93 588.2 Q F0 2.5(2.1.1. F)102 612.2 R(ormat)-.25 E F1 .574(Each line in t\
+he system log consists of a timestamp, the name of the machine that gener)142
+628.4 R(-)-.2 E .849(ated it \(for logging from se)117 640.4 R -.15(ve)-.25 G
+.849(ral machines o).15 F -.15(ve)-.15 G 3.349(rt).15 G .848
+(he local area netw)316.942 640.4 R .848(ork\), the w)-.1 F .848
+(ord \231sendmail:\232,)-.1 F(and a message)117 654.4 Q F4(6)174.76 650.4 Q F1
+5(.M)178.26 654.4 S(ost messages are a sequence of)194.65 654.4 Q F2(name)2.5 E
+F1(=)A F2(value)A F1(pairs.)2.5 E .32 LW 76 665.2 72 665.2 DL 80 665.2 76 665.2
+DL 84 665.2 80 665.2 DL 88 665.2 84 665.2 DL 92 665.2 88 665.2 DL 96 665.2 92
+665.2 DL 100 665.2 96 665.2 DL 104 665.2 100 665.2 DL 108 665.2 104 665.2 DL
+112 665.2 108 665.2 DL 116 665.2 112 665.2 DL 120 665.2 116 665.2 DL 124 665.2
+120 665.2 DL 128 665.2 124 665.2 DL 132 665.2 128 665.2 DL 136 665.2 132 665.2
+DL 140 665.2 136 665.2 DL 144 665.2 140 665.2 DL 148 665.2 144 665.2 DL 152
+665.2 148 665.2 DL 156 665.2 152 665.2 DL 160 665.2 156 665.2 DL 164 665.2 160
+665.2 DL 168 665.2 164 665.2 DL 172 665.2 168 665.2 DL 176 665.2 172 665.2 DL
+180 665.2 176 665.2 DL 184 665.2 180 665.2 DL 188 665.2 184 665.2 DL 192 665.2
+188 665.2 DL 196 665.2 192 665.2 DL 200 665.2 196 665.2 DL 204 665.2 200 665.2
+DL 208 665.2 204 665.2 DL 212 665.2 208 665.2 DL 216 665.2 212 665.2 DL/F5 5
+/Times-Roman@0 SF(5)93.6 675.6 Q/F6 8/Times-Roman@0 SF
+(Except on Ultrix, which does not support f)3.2 I(acilities in the syslog.)-.08
+E F5(6)93.6 689.2 Q F6(This format may v)3.2 I(ary slightly if your v)-.2 E
+(endor has changed the syntax.)-.12 E EP
+%%Page: 12 7
+%%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 .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 2.5(#r)72 132 S(emo)82.83 132 Q .3 -.15(ve z)
+-.15 H(ero length qf \214les).15 E(for qf)72 144 Q(\214le in qf*)-.25 E(do)72
+156 Q(if [ \255r $qf)108 168 Q(\214le ])-.25 E(then)108 180 Q(if [ ! \255s $qf)
+144 192 Q(\214le ])-.25 E(then)144 204 Q(echo \255n " <zero: $qf)180 216 Q
+(\214le>" > /de)-.25 E(v/console)-.25 E(rm \255f $qf)180 228 Q(\214le)-.25 E
+<8c>144 240 Q<8c>108 252 Q(done)72 264 Q 2.5(#r)72 276 S
+(ename tf \214les to be qf if the qf does not e)82.83 276 Q(xist)-.15 E(for tf)
+72 288 Q(\214le in tf*)-.25 E(do)72 300 Q(qf)108 312 Q(\214le=`echo $tf)-.25 E
+(\214le | sed ')-.25 E(s/t/q/'`)-.55 E(if [ \255r $tf)108 324 Q
+(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 E(then)108 336 Q
+(echo \255n " <reco)144 348 Q -.15(ve)-.15 G(ring: $tf).15 E(\214le>" > /de)
+-.25 E(v/console)-.25 E(mv $tf)144 360 Q(\214le $qf)-.25 E(\214le)-.25 E(else)
+108 372 Q(echo \255n " <e)144 384 Q(xtra: $tf)-.15 E(\214le>" > /de)-.25 E
+(v/console)-.25 E(rm \255f $tf)144 396 Q(\214le)-.25 E<8c>108 408 Q(done)72 420
+Q 2.5(#r)72 432 S(emo)82.83 432 Q .3 -.15(ve d)-.15 H 2.5<668c>.15 G
+(les with no corresponding qf \214les)128.08 432 Q(for df)72 444 Q
+(\214le in df*)-.25 E(do)72 456 Q(qf)108 468 Q(\214le=`echo $df)-.25 E
+(\214le | sed ')-.25 E(s/d/q/'`)-.55 E(if [ \255r $df)108 480 Q
+(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 E(then)108 492 Q
+(echo \255n " <incomplete: $df)144 504 Q(\214le>" > /de)-.25 E(v/console)-.25 E
+(mv $df)144 516 Q(\214le `echo $df)-.25 E(\214le | sed ')-.25 E(s/d/D/'`)-.55 E
+<8c>108 528 Q(done)72 540 Q 2.5(#a)72 552 S(nnounce \214les that ha)83.94 552 Q
+.3 -.15(ve b)-.2 H(een sa).15 E -.15(ve)-.2 G 2.5(dd).15 G(uring disaster reco)
+229.32 552 Q -.15(ve)-.15 G(ry).15 E(for xf)72 564 Q(\214le in [A-Z]f*)-.25 E
+(do)72 576 Q(echo \255n " <panic: $xf)108 588 Q(\214le>" > /de)-.25 E
+(v/console)-.25 E(done)72 600 Q(Figure 1 \212 A comple)214.47 624 Q 2.5(xs)-.15
+G(tartup script)313.48 624 Q 77 636 72 636 DL 79 636 74 636 DL 84 636 79 636 DL
+89 636 84 636 DL 94 636 89 636 DL 99 636 94 636 DL 104 636 99 636 DL 109 636
+104 636 DL 114 636 109 636 DL 119 636 114 636 DL 124 636 119 636 DL 129 636 124
+636 DL 134 636 129 636 DL 139 636 134 636 DL 144 636 139 636 DL 149 636 144 636
+DL 154 636 149 636 DL 159 636 154 636 DL 164 636 159 636 DL 169 636 164 636 DL
+174 636 169 636 DL 179 636 174 636 DL 184 636 179 636 DL 189 636 184 636 DL 194
+636 189 636 DL 199 636 194 636 DL 204 636 199 636 DL 209 636 204 636 DL 214 636
+209 636 DL 219 636 214 636 DL 224 636 219 636 DL 229 636 224 636 DL 234 636 229
+636 DL 239 636 234 636 DL 244 636 239 636 DL 249 636 244 636 DL 254 636 249 636
+DL 259 636 254 636 DL 264 636 259 636 DL 269 636 264 636 DL 274 636 269 636 DL
+279 636 274 636 DL 284 636 279 636 DL 289 636 284 636 DL 294 636 289 636 DL 299
+636 294 636 DL 304 636 299 636 DL 309 636 304 636 DL 314 636 309 636 DL 319 636
+314 636 DL 324 636 319 636 DL 329 636 324 636 DL 334 636 329 636 DL 339 636 334
+636 DL 344 636 339 636 DL 349 636 344 636 DL 354 636 349 636 DL 359 636 354 636
+DL 364 636 359 636 DL 369 636 364 636 DL 374 636 369 636 DL 379 636 374 636 DL
+384 636 379 636 DL 389 636 384 636 DL 394 636 389 636 DL 399 636 394 636 DL 404
+636 399 636 DL 409 636 404 636 DL 414 636 409 636 DL 419 636 414 636 DL 424 636
+419 636 DL 429 636 424 636 DL 434 636 429 636 DL 439 636 434 636 DL 444 636 439
+636 DL 449 636 444 636 DL 454 636 449 636 DL 459 636 454 636 DL 464 636 459 636
+DL 469 636 464 636 DL 474 636 469 636 DL 479 636 474 636 DL 484 636 479 636 DL
+489 636 484 636 DL 494 636 489 636 DL 499 636 494 636 DL 504 636 499 636 DL .68
+(The tw)142 672 R 3.18(om)-.1 G .68
+(ost common lines are logged when a message is processed.)186.59 672 R .68
+(The \214rst logs the)5.68 F .376(receipt of a message; there will be e)117 684
+R .376(xactly one of these per message.)-.15 F .376(Some \214elds may be omit-)
+5.376 F(ted if the)117 696 Q 2.5(yd)-.15 G 2.5(on)164.9 696 S
+(ot contain interesting information.)177.4 696 Q(Fields are:)5 E 50.06
+(from The)117 712.2 R(en)2.5 E -.15(ve)-.4 G(lope sender address.).15 E EP
+%%Page: 13 8
+%%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 53.95(size The)117 96 R
+(size of the message in bytes.)2.5 E 50.06(class The)117 112.2 R
+(class \(i.e., numeric precedence\) of the message.)2.5 E 58.39(pri The)117
+128.4 R(initial message priority \(used for queue sorting\).)2.5 E 45.06
+(nrcpts The)117 144.6 R 1.514(number of en)4.014 F -.15(ve)-.4 G 1.515
+(lope recipients for this message \(after aliasing and for).15 F(-)-.2 E -.1
+(wa)189 156.6 S(rding\).).1 E 45.05(msgid The)117 172.8 R
+(message id of the message \(from the header\).)2.5 E 48.39(proto The)117 189 R
+(protocol used to recei)2.5 E .3 -.15(ve t)-.25 H
+(his message \(e.g., ESMTP or UUCP\)).15 E 49.51(relay The)117 205.2 R
+(machine from which it w)2.5 E(as recei)-.1 E -.15(ve)-.25 G(d.).15 E .43
+(There is also one line logged per deli)117 221.4 R -.15(ve)-.25 G .43
+(ry attempt \(so there can be se).15 F -.15(ve)-.25 G .43
+(ral per message if deli).15 F(v-)-.25 E
+(ery is deferred or there are multiple recipients\).)117 233.4 Q(Fields are:)5
+E 61.72(to A)117 249.6 R(comma-separated list of the recipients to this mailer)
+2.5 E(.)-.55 E 41.73(ctladdr The)117 265.8 R -.74(``)2.726 G .226
+(controlling user').74 F .226
+(', that is, the name of the user whose credentials we use)-.74 F(for deli)189
+277.8 Q -.15(ve)-.25 G(ry).15 E(.)-.65 E 47.84(delay The)117 294 R 1.303
+(total delay between the time this message w)3.804 F 1.303(as recei)-.1 F -.15
+(ve)-.25 G 3.803(da).15 G 1.303(nd the time it)447.031 294 R -.1(wa)189 306 S
+2.5(sd).1 G(eli)211.95 306 Q -.15(ve)-.25 G(red.).15 E 42.84(xdelay The)117
+322.2 R .116(amount of time needed in this deli)2.615 F -.15(ve)-.25 G .116
+(ry attempt \(normally indicati).15 F .416 -.15(ve o)-.25 H 2.616(ft).15 G(he)
+494.56 322.2 Q(speed of the connection\).)189 334.2 Q 43.95(mailer The)117
+350.4 R(name of the mailer used to deli)2.5 E -.15(ve)-.25 G 2.5(rt).15 G 2.5
+(ot)348.57 350.4 S(his recipient.)358.85 350.4 Q 49.51(relay The)117 366.6 R
+(name of the host that actually accepted \(or rejected\) this recipient.)2.5 E
+55.61(stat The)117 382.8 R(deli)2.5 E -.15(ve)-.25 G(ry status.).15 E
+(Not all \214elds are present in all messages; for e)117 399 Q
+(xample, the relay is not listed for local deli)-.15 E -.15(ve)-.25 G(ries.).15
+E F0 2.5(2.1.2. Le)102 423 R -.1(ve)-.15 G(ls).1 E F1 .205(If you ha)142 439.2
+R -.15(ve)-.2 G/F2 10/Times-Italic@0 SF(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 451.2 S(ar)127.007 451.2 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 463.2 R .651(west le)-.25 F -.15(ve)-.25 G 3.151(lo).15 G
+.651(nly e)201.724 463.2 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 463.2 Q .825(most mundane and uninteresting e)117 475.2 R
+-.15(ve)-.25 G .825(nts are recorded for posterity).15 F 5.826(.A)-.65 G 3.326
+(sac)400.266 475.2 S(on)419.688 475.2 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 487.2 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 487.2 R .2(ed for deb)-.15 F .2(ugging pur)-.2 F(-)-.2 E 2.5(poses. Le)
+117 499.2 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 515.4
+S(omplete description of the log le)156.16 515.4 Q -.15(ve)-.25 G(ls is gi).15
+E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ns)340.35 515.4 S(ection 4.6.)351.74 515.4 Q
+F0 2.5(2.2. Dumping)87 539.4 R(State)2.5 E F1 -1.1(Yo)127 555.6 S 2.563(uc)1.1
+G .063(an ask)150.123 555.6 R F2(sendmail)2.563 E F1 .064
+(to log a dump of the open \214les and the connection cache by sending it a)
+2.563 F/F3 9/Times-Roman@0 SF(SIGUSR1)102 567.6 Q F1 2.5(signal. The)2.5 F
+(results are logged at)2.5 E F3(LOG_DEB)2.5 E(UG)-.09 E F1(priority)2.5 E(.)
+-.65 E F0 2.5(2.3. The)87 591.6 R(Mail Queue)2.5 E F1 1.283
+(Sometimes a host cannot handle a message immediately)127 607.8 R 6.283(.F)-.65
+G 1.283(or e)374.224 607.8 R 1.283(xample, it may be do)-.15 F 1.282(wn or)-.25
+F -.15(ove)102 619.8 S .042(rloaded, causing it to refuse connections.).15 F
+.043(The sending host is then e)5.043 F .043(xpected to sa)-.15 F .343 -.15
+(ve t)-.2 H .043(his message).15 F(in its mail queue and attempt to deli)102
+631.8 Q -.15(ve)-.25 G 2.5(ri).15 G 2.5(tl)263.26 631.8 S(ater)271.32 631.8 Q
+(.)-.55 E .568
+(Under normal conditions the mail queue will be processed transparently)127 648
+R 5.568(.H)-.65 G -.25(ow)434.764 648 S -2.15 -.25(ev e).25 H 1.368 -.4(r, y)
+.25 H .568(ou may).4 F .993(\214nd that manual interv)102 660 R .993
+(ention is sometimes necessary)-.15 F 5.993(.F)-.65 G .993(or e)332.711 660 R
+.993(xample, if a major host is do)-.15 F .994(wn for a)-.25 F 1.699
+(period of time the queue may become clogged.)102 672 R(Although)6.699 E F2
+(sendmail)4.199 E F1 1.699(ought to reco)4.199 F -.15(ve)-.15 G 4.199(rg).15 G
+(racefully)468.46 672 Q(when the host comes up, you may \214nd performance una\
+cceptably bad in the meantime.)102 684 Q EP
+%%Page: 14 9
+%%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 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)2.5 E F2(sendmail)2.5 E F1(\):)A(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.137
+(should run the queue automatically at interv)3.637 F 3.638(als. The)-.25 F
+1.138(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 .355(hen it attempts to run the job,)384.37 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 .339(ime, since there)440.282 249 R .095
+(is no guarantee that a job cannot tak)117 261 R 2.595(ef)-.1 G(ore)272.07 261
+Q -.15(ve)-.25 G 2.595(rt).15 G 2.595(op)302.585 261 S .094(rocess \(ho)315.18
+261 R(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G F2(sendmail)2.994 E F1 .094
+(does include heuris-)2.594 F 1.086
+(tics to try to abort jobs that are taking absurd amounts of time; technically)
+117 273 R 3.587(,t)-.65 G 1.087(his violates RFC)435.146 273 R .462(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.086
+(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.346 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.351(rr).15 G .851(eturns can accumulate man)145.491 309 R 3.351(yp)-.15 G
+.851(rocesses in your system.)269.825 309 R(Unfortunately)5.851 E 3.351(,t)-.65
+G .85(here is no com-)439.52 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 .083
+(wn for a couple of days may create)-.25 F 2.925(ap)117 349.2 S(rohibiti)
+129.365 349.2 Q -.15(ve)-.25 G .425(ly lar).15 F .425(ge queue.)-.18 F .424
+(This will result in)5.425 F F2(sendmail)2.924 E F1 .424
+(spending an inordinate amount of time)2.924 F 1.084(sorting the queue.)117
+361.2 R 1.084(This situation can be \214x)6.084 F 1.084(ed by mo)-.15 F 1.085
+(ving the queue to a temporary place and)-.15 F .023(creating a ne)117 373.2 R
+2.523(wq)-.25 G 2.523(ueue. The)182.629 373.2 R .022
+(old queue can be run later when the of)2.523 F .022
+(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.708(us)1.1 G .208(hould then kill the e)139.718 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.868 E F1 .367
+(\215ag speci\214es an alternate queue directory and the)2.868 F F0<ad71>2.867
+E F1 .367(\215ag says to just run e)2.867 F -.15(ve)-.25 G .367(ry job in).15 F
+.593(the queue.)117 506.4 R .593(If you ha)5.593 F .893 -.15(ve a t)-.2 H
+(endenc).15 E 3.093(yt)-.15 G -2.1 -.25(ow a)263.111 506.4 T .593(rd v).25 F
+-.1(oy)-.2 G .593(eurism, you can use the).1 F F0<ad76>3.094 E F1 .594
+(\215ag to w)3.094 F .594(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(Ser)2.5 E(vice Switch)-.1 E F1 1.416(The implementation of \
+certain system services such as host and user name lookup is con-)127 595.2 R
+.335(trolled by the service switch.)102 607.2 R .336
+(If the host operating system supports such a switch)5.335 F F2(sendmail)2.836
+E F1 .336(will use)2.836 F(the nati)102 619.2 Q .3 -.15(ve ve)-.25 H 2.5
+(rsion. Ultrix,).15 F(Solaris, and DEC OSF/1 are e)2.5 E
+(xamples of such systems.)-.15 E .969(If the underlying operating system does \
+not support a service switch \(e.g., SunOS, HP-UX,)127 635.4 R .975(BSD\) then)
+102 647.4 R F2(sendmail)3.475 E F1 .975(will pro)3.475 F .975
+(vide a stub implementation.)-.15 F(The)5.975 E F0(Ser)3.475 E(viceSwitchFile)
+-.1 E F1 .975(option points to)3.475 F .382(the name of a \214le that has the \
+service de\214nitions Each line has the name of a service and the possi-)102
+659.4 R(ble implementations of that service.)102 671.4 Q -.15(Fo)5 G 2.5(re).15
+G(xample, the \214le:)270.57 671.4 Q 12.94(hosts dns)142 687.6 R(\214les nis)
+2.5 E 6.84(aliases \214les)142 699.6 R(nis)2.5 E .328(will ask)102 715.8 R F2
+(sendmail)2.828 E F1 .328(to look for hosts in the Domain Name System \214rst.)
+2.828 F .329(If the requested host name is)5.329 F EP
+%%Page: 15 10
+%%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 .379
+(not found, it tries local \214les, and if that f)102 96 R .379
+(ails it tries NIS.)-.1 F(Similarly)5.379 E 2.879(,w)-.65 G .379
+(hen looking for aliases it will)385.166 96 R
+(try the local \214les \214rst follo)102 108 Q(wed by NIS.)-.25 E 1.269
+(Service switches are not completely inte)127 124.2 R 3.769(grated. F)-.15 F
+1.269(or e)-.15 F 1.269(xample, despite the f)-.15 F 1.27(act that the host)-.1
+F .294(entry listed in the abo)102 136.2 R .594 -.15(ve ex)-.15 H .293
+(ample speci\214es to look in NIS, on SunOS this w).15 F(on')-.1 E 2.793(th)
+-.18 G .293(appen because the)430.664 136.2 R 1.398(system implementation of)
+102 148.2 R/F2 10/Times-Italic@0 SF -.1(ge)3.898 G(thostbyname).1 E F1 1.398
+(\(3\) doesn')1.666 F 3.898(tu)-.18 G 1.399(nderstand this.)327.856 148.2 R
+1.399(If there is enough demand)6.399 F F2(sendmail)102 160.2 Q F1 .015
+(may reimplement)2.515 F F2 -.1(ge)2.515 G(thostbyname).1 E F1(\(3\),)1.666 E
+F2 -.1(ge)2.515 G(thostbyaddr).1 E F1(\(3\),)1.666 E F2 -.1(ge)2.515 G(tpwent)
+.1 E F1 .014(\(3\), and the other system)1.666 F(routines that w)102 172.2 Q
+(ould be necessary to mak)-.1 E 2.5(et)-.1 G(his w)272.05 172.2 Q
+(ork seamlessly)-.1 E(.)-.65 E F0 2.5(2.5. The)87 196.2 R(Alias Database)2.5 E
+F1 .36(The alias database e)127 212.4 R .36(xists in tw)-.15 F 2.86(of)-.1 G
+2.861(orms. One)261.11 212.4 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 224.4 Q(name: name1, name2, ...)142 240.6 Q
+(Only local names may be aliased; e.g.,)102 256.8 Q(eric@prep.ai.MIT)142 273 Q
+(.EDU: eric@CS.Berk)-.74 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E 1.088
+(will not ha)102 291.2 R 1.388 -.15(ve t)-.2 H 1.088(he desired ef).15 F 1.088
+(fect \(e)-.25 F 1.088(xcept on prep.ai.MIT)-.15 F 1.088(.EDU, and the)-.74 F
+3.588(yp)-.15 G 1.088(robably don')400.868 291.2 R 3.587(tw)-.18 G 1.087
+(ant me\))466.643 291.2 R/F3 7/Times-Roman@0 SF(7)498 287.2 Q F1(.)501.5 291.2
+Q .561(Aliases may be continued by starting an)102 303.2 R 3.061(yc)-.15 G .561
+(ontinuation lines with a space or a tab)277.697 303.2 R 5.562(.B)-.4 G .562
+(lank lines and)447.326 303.2 R(lines be)102 315.2 Q
+(ginning with a sharp sign \(\231#\232\) are comments.)-.15 E 1.478
+(The second form is processed by the)127 333.4 R F2(ndbm)3.978 E F1(\(3\))1.666
+E F3(8)321.472 329.4 Q F1(or)328.95 333.4 Q F2(db)3.978 E F1 1.478
+(\(3\) library)1.666 F 6.478(.T)-.65 G 1.478(his form is in the \214les)409.66
+333.4 R F2(/etc/aliases.dir)102 345.4 Q F1(and)3.028 E F2(/etc/aliases.pa)3.028
+E -.15(g.)-.1 G F1 .528(This is the form that)5.678 F F2(sendmail)3.029 E F1
+.529(actually uses to resolv)3.029 F 3.029(ea)-.15 G(liases.)479.28 345.4 Q
+(This technique is used to impro)102 357.4 Q .3 -.15(ve p)-.15 H(erformance.)
+.15 E(The control of search order is actually set by the service switch.)127
+373.6 Q(Essentially)5 E 2.5(,t)-.65 G(he entry)437.96 373.6 Q -.35(OA)142 389.8
+S(switch:aliases).35 E .927(is al)102 406 R -.1(wa)-.1 G .927(ys added as the \
+\214rst alias entry; also, the \214rst alias \214le name without a class \(e.g\
+., without).1 F .268
+(\231nis:\232 on the front\) will be used as the name of the \214le for a `)102
+418 R(`\214les')-.74 E 2.769('e)-.74 G .269(ntry in the aliases switch.)382.535
+418 R -.15(Fo)5.269 G(r).15 E -.15(ex)102 430 S
+(ample, if the con\214guration \214le contains).15 E -.35(OA)142 446.2 S
+(/etc/aliases).35 E(and the service switch contains)102 462.4 Q 6.84
+(aliases nis)142 478.6 R(\214les nisplus)2.5 E 2.449(then aliases will \214rst\
+ be searched in the NIS database, then in /etc/aliases, then in the NIS+)102
+494.8 R(database.)102 506.8 Q -1.1(Yo)127 523 S 2.5(uc)1.1 G(an also use)150.06
+523 Q/F4 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 523 Q -.35(OA)142 539.2 S
+(/etc/aliases).35 E -.35(OA)142 551.2 S(nis:mail.aliases@my).35 E(.nis.domain)
+-.65 E 1.725(will \214rst search the /etc/aliases \214le and then the map name\
+d \231mail.aliases\232 in \231my)102 567.4 R(.nis.domain\232.)-.65 E -.8(Wa)102
+579.4 S .59(rning: if you b).8 F .59(uild your o)-.2 F(wn)-.25 E F4(NIS)3.09 E
+F1 .589(-based alias \214les, be sure to pro)B .589(vide the)-.15 F F0<ad6c>
+3.089 E F1 .589(\215ag to)3.089 F F2(mak)3.089 E(edbm)-.1 E F1(\(8\))A .159
+(to map upper case letters in the k)102 591.4 R -.15(ey)-.1 G 2.659(st).15 G
+2.659(ol)253.55 591.4 S -.25(ow)263.989 591.4 S .159
+(er case; otherwise, aliases with upper case letters in their).25 F(names w)102
+603.4 Q(on')-.1 E 2.5(tm)-.18 G(atch incoming addresses.)163.38 603.4 Q
+(Additional \215ags can be added after the colon e)127 619.6 Q(xactly lik)-.15
+E 2.5(ea)-.1 G F0(K)A F1(line \212 for e)2.5 E(xample:)-.15 E -.35(OA)142 635.8
+S(nis:\255N mail.aliases@my).35 E(.nis.domain)-.65 E
+(will search the appropriate NIS map and al)102 652 Q -.1(wa)-.1 G
+(ys include null bytes in the k).1 E -.15(ey)-.1 G(.)-.5 E .32 LW 76 665.2 72
+665.2 DL 80 665.2 76 665.2 DL 84 665.2 80 665.2 DL 88 665.2 84 665.2 DL 92
+665.2 88 665.2 DL 96 665.2 92 665.2 DL 100 665.2 96 665.2 DL 104 665.2 100
+665.2 DL 108 665.2 104 665.2 DL 112 665.2 108 665.2 DL 116 665.2 112 665.2 DL
+120 665.2 116 665.2 DL 124 665.2 120 665.2 DL 128 665.2 124 665.2 DL 132 665.2
+128 665.2 DL 136 665.2 132 665.2 DL 140 665.2 136 665.2 DL 144 665.2 140 665.2
+DL 148 665.2 144 665.2 DL 152 665.2 148 665.2 DL 156 665.2 152 665.2 DL 160
+665.2 156 665.2 DL 164 665.2 160 665.2 DL 168 665.2 164 665.2 DL 172 665.2 168
+665.2 DL 176 665.2 172 665.2 DL 180 665.2 176 665.2 DL 184 665.2 180 665.2 DL
+188 665.2 184 665.2 DL 192 665.2 188 665.2 DL 196 665.2 192 665.2 DL 200 665.2
+196 665.2 DL 204 665.2 200 665.2 DL 208 665.2 204 665.2 DL 212 665.2 208 665.2
+DL 216 665.2 212 665.2 DL/F5 5/Times-Roman@0 SF(7)93.6 675.6 Q/F6 8
+/Times-Roman@0 SF(Actually)3.2 I 2(,a)-.52 G .24 -.12(ny m)130.684 678.8 T
+(ailer that has the `).12 E 1.776 -.888(A' m)-.64 H(ailer \215ag set will perm\
+it aliasing; this is normally limited to the local mailer).888 E(.)-.44 E F5(8)
+93.6 689.2 Q F6(The)3.2 I/F7 8/Times-Italic@0 SF(gdbm)2 E F6
+(package probably w)2 E(orks as well.)-.08 E EP
+%%Page: 16 11
+%%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 2.5(2.5.1. Reb)102 96 R
+(uilding the alias database)-.2 E/F1 10/Times-Roman@0 SF .542(The DB or DBM v)
+142 112.2 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
+124.2 Q(ne)157 140.4 Q -.1(wa)-.25 G(liases).1 E(This is equi)117 156.6 Q -.25
+(va)-.25 G(lent to gi).25 E(ving)-.25 E/F2 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
+172.8 Q 2.29(If the)142 193.2 R F0(Reb)4.79 E(uildAliases)-.2 E F1(\(old)4.79 E
+F0(D)4.79 E F1 4.79(\)o)C 2.29(ption is speci\214ed in the con\214guration,)
+280.19 193.2 R F2(sendmail)4.79 E F1(will)4.79 E(reb)117 205.2 Q .775
+(uild the alias database automatically if possible when it is out of date.)-.2
+F(Auto-reb)5.774 E .774(uild can be)-.2 F 1.853(dangerous on hea)117 217.2 R
+1.853(vily loaded machines with lar)-.2 F 1.853
+(ge alias \214les; if it might tak)-.18 F 4.354(em)-.1 G 1.854(ore than the)
+453.082 217.2 R(reb)117 229.2 Q 2.832(uild timeout \(option)-.2 F F0(AliasW)
+5.332 E(ait)-.65 E F1 5.332(,o)C(ld)275.538 229.2 Q F0(a)5.332 E F1 5.332(,w)C
+2.831(hich is normally \214v)308.702 229.2 R 5.331(em)-.15 G 2.831
+(inutes\) to reb)412.657 229.2 R 2.831(uild the)-.2 F
+(database, there is a chance that se)117 241.2 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 257.4 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 269.4 Q(xample, it can reb)-.15 E
+(uild NDBM databases b)-.2 E(ut not NIS databases\).)-.2 E F0 2.5(2.5.2. P)102
+293.4 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
+309.6 R(The)6.13 E 3.63(ya)-.15 G 1.13(ll result)472.59 309.6 R 1.103(from a)
+117 321.6 R F2(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 333.6 R 3.749(oc)-.1 G 1.248
+(ircumstances: One process accesses the database while another process is)
+199.237 333.6 R(reb)117 345.6 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 357.6 Q(uild.)-.2 E .401
+(Sendmail has three techniques to try to relie)142 373.8 R .701 -.15(ve t)-.25
+H .401(hese problems.).15 F .4(First, it ignores interrupts)5.401 F .045
+(while reb)117 385.8 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
+.177(partially reb)117 397.8 R .177(uilt database.)-.2 F .177
+(Second, it locks the database source \214le during the reb)5.177 F .176
+(uild \212 b)-.2 F .176(ut that)-.2 F .812(may not w)117 409.8 R .812(ork o)-.1
+F -.15(ve)-.15 G 3.312(rN).15 G .812(FS or if the \214le is unwritable.)205.388
+409.8 R .813(Third, at the end of the reb)5.813 F .813(uild it adds an)-.2 F
+(alias of the form)117 421.8 Q(@: @)157 438 Q .336(\(which is not normally le)
+117 454.2 R -.05(ga)-.15 G 2.836(l\). Before).05 F F2(sendmail)2.836 E F1 .336
+(will access the database, it checks to insure that)2.836 F(this entry e)117
+468.2 Q(xists)-.15 E/F3 7/Times-Roman@0 SF(9)179.63 464.2 Q F1(.)183.13 468.2 Q
+F0 2.5(2.5.3. List)102 492.2 R -.1(ow)2.5 G(ners).1 E F1 .4
+(If an error occurs on sending to a certain address, say \231)142 508.4 R F2(x)
+A F1<9a2c>A F2(sendmail)2.901 E F1 .401(will look for an alias)2.901 F .418
+(of the form \231o)117 520.4 R(wner)-.25 E(-)-.2 E F2(x)A F1 2.918<9a74>C 2.918
+(or)212.632 520.4 S(ecei)223.88 520.4 Q .718 -.15(ve t)-.25 H .418(he errors.)
+.15 F .417(This is typically useful for a mailing list where the)5.418 F 1.116
+(submitter of the list has no control o)117 532.4 R -.15(ve)-.15 G 3.617(rt).15
+G 1.117(he maintenance of the list itself; in this case the list)288.4 532.4 R
+(maintainer w)117 544.4 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 544.4 Q
+(unix-wizards: eric@ucbarpa, wnj@monet, nosuchuser)157 560.6 Q(,)-.4 E
+(sam@matisse)193 572.6 Q -.25(ow)157 584.6 S(ner).25 E
+(-unix-wizards: unix-wizards-request)-.2 E(unix-wizards-request: eric@ucbarpa)
+157 596.6 Q -.1(wo)117 612.8 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 624.8 Q
+.958(List o)142 641 R .958(wners also cause the en)-.25 F -.15(ve)-.4 G .959
+(lope sender address to be modi\214ed.).15 F .959(The contents of the)5.959 F
+-.25(ow)117 653 S .429(ner alias are used if the).25 F 2.929(yp)-.15 G .429
+(oint to a single user)236.364 653 R 2.928(,o)-.4 G .428
+(therwise the name of the alias itself is used.)326.436 653 R -.15(Fo)117 665 S
+3.454(rt).15 G .954(his reason, and to obe)136.974 665 R 3.454(yI)-.15 G .954
+(nternet con)239.354 665 R -.15(ve)-.4 G .954(ntions, the \231o).15 F(wner)-.25
+E .955(-\232 address normally points at the)-.2 F .504(\231-request\232 addres\
+s; this causes messages to go out with the typical Internet con)117 677 R -.15
+(ve)-.4 G .503(ntion of using).15 F .32 LW 76 686.6 72 686.6 DL 80 686.6 76
+686.6 DL 84 686.6 80 686.6 DL 88 686.6 84 686.6 DL 92 686.6 88 686.6 DL 96
+686.6 92 686.6 DL 100 686.6 96 686.6 DL 104 686.6 100 686.6 DL 108 686.6 104
+686.6 DL 112 686.6 108 686.6 DL 116 686.6 112 686.6 DL 120 686.6 116 686.6 DL
+124 686.6 120 686.6 DL 128 686.6 124 686.6 DL 132 686.6 128 686.6 DL 136 686.6
+132 686.6 DL 140 686.6 136 686.6 DL 144 686.6 140 686.6 DL 148 686.6 144 686.6
+DL 152 686.6 148 686.6 DL 156 686.6 152 686.6 DL 160 686.6 156 686.6 DL 164
+686.6 160 686.6 DL 168 686.6 164 686.6 DL 172 686.6 168 686.6 DL 176 686.6 172
+686.6 DL 180 686.6 176 686.6 DL 184 686.6 180 686.6 DL 188 686.6 184 686.6 DL
+192 686.6 188 686.6 DL 196 686.6 192 686.6 DL 200 686.6 196 686.6 DL 204 686.6
+200 686.6 DL 208 686.6 204 686.6 DL 212 686.6 208 686.6 DL 216 686.6 212 686.6
+DL/F4 5/Times-Roman@0 SF(9)93.6 697 Q/F5 8/Times-Roman@0 SF(The)3.2 I/F6 8
+/Times-Bold@0 SF(AliasW)2 E(ait)-.52 E F5
+(option is required in the con\214guration for this action to occur)2 E 4(.T)
+-.44 G(his should normally be speci\214ed.)352.228 700.2 Q EP
+%%Page: 17 12
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-17)452.9 60 Q/F1 10/Times-Roman@0 SF -.74(``)117 96 S/F2 10
+/Times-Italic@0 SF(list).74 E F1(-request')A 2.5('a)-.74 G 2.5(st)180.22 96 S
+(he return address.)189.39 96 Q F0 2.5(2.6. User)87 120 R(Inf)2.5 E
+(ormation Database)-.25 E F1 1.059(If you ha)127 136.2 R 1.359 -.15(ve a ve)-.2
+H 1.059(rsion of).15 F F2(sendmail)3.559 E F1 1.06
+(with the user information database compiled in, and you)3.559 F(ha)102 148.2 Q
+2.206 -.15(ve s)-.2 H 1.906(peci\214ed one or more databases using the).15 F F0
+(U)4.406 E F1 1.905(option, the databases will be searched for a)4.406 F F2
+(user)102 160.2 Q F1(:maildrop entry)A 5(.I)-.65 G 2.5(ff)191.34 160.2 S
+(ound, the mail will be sent to the speci\214ed address.)200.5 160.2 Q F0 2.5
+(2.7. P)87 184.2 R(er)-.2 E(-User F)-.37 E(orwarding \(.f)-.25 E
+(orward Files\))-.25 E F1 .12(As an alternati)127 200.4 R .42 -.15(ve t)-.25 H
+2.62(ot).15 G .12(he alias database, an)210.4 200.4 R 2.62(yu)-.15 G .121
+(ser may put a \214le with the name \231.forw)304.87 200.4 R .121
+(ard\232 in his)-.1 F .205(or her home directory)102 212.4 R 5.205(.I)-.65 G
+2.705(ft)199.92 212.4 S .205(his \214le e)208.735 212.4 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 224.4 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
+224.4 R(ard)-.1 E(\214le with contents:)102 236.4 Q(mckusick@ernie)142 252.6 Q
+(kirk@calder)142 264.6 Q(then an)102 280.8 Q 2.5(ym)-.15 G(ail arri)146.29
+280.8 Q
+(ving for \231mckusick\232 will be redirected to the speci\214ed accounts.)-.25
+E(Actually)127 297 Q 3.375(,t)-.65 G .874
+(he con\214guration \214le de\214nes a sequence of \214lenames to check.)
+169.445 297 R .874(By def)5.874 F .874(ault, this is)-.1 F .687(the user')102
+309 R 3.187(s.)-.55 G(forw)146.424 309 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 321 R
+.693 -.15(ve t)-.2 H 2.893(oi).15 G .393
+(nform your user base of the change; .forw)193.065 321 R .393
+(ard is pretty well incorporated into)-.1 F(the collecti)102 333 Q .3 -.15
+(ve s)-.25 H(ubconscious.).15 E F0 2.5(2.8. Special)87 357 R(Header Lines)2.5 E
+F1(Se)127 373.2 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 385.2 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 397.2 S(iltins are described here.).2 E F0 2.5(2.8.1. Err)102 421.2 R
+(ors-T)-.18 E(o:)-.92 E F1 .22(If errors occur an)142 437.4 R .22
+(ywhere during processing, this header will cause error messages to go to)-.15
+F(the listed addresses.)117 449.4 Q(This is intended for mailing lists.)5 E
+.385(The Errors-T)142 465.6 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 465.6 R .889(distinction between an en)117 477.6 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 477.6 Q .81
+(passed as the en)117 489.6 R -.15(ve)-.4 G .81(lope sender address.).15 F .809
+(It should go a)5.81 F -.1(wa)-.15 G 4.609 -.65(y. I).1 H 3.309(ti).65 G 3.309
+(so)374.125 489.6 S .809(nly used if the)386.324 489.6 R F0(UseErr)3.309 E
+(orsT)-.18 E(o)-.92 E F1(option is set.)117 501.6 Q(The Errors-T)142 517.8 Q
+(o: header is of)-.8 E(\214cial deprecated and will go a)-.25 E -.1(wa)-.15 G
+2.5(yi).1 G 2.5(naf)392.3 517.8 S(uture release.)410.07 517.8 Q F0 2.5
+(2.8.2. A)102 541.8 R(ppar)-.25 E(ently-T)-.18 E(o:)-.92 E F1 .044
+(RFC 822 requires at least one recipient \214eld \(T)142 558 R .045
+(o:, Cc:, or Bcc: line\) in e)-.8 F -.15(ve)-.25 G .045(ry message.).15 F .045
+(If a)5.045 F .562
+(message comes in with no recipients listed in the message then)117 570 R F2
+(sendmail)3.062 E F1 .562(will adjust the header)3.062 F .085
+(based on the \231NoRecipientAction\232 option.)117 582 R .085
+(One of the possible actions is to add an \231)5.085 F(Apparently-)-.8 E -.8
+(To)117 594 S .08(:\232 header line for an).8 F 2.58(yr)-.15 G .08
+(ecipients it is a)218.36 594 R -.1(wa)-.15 G .08(re of.).1 F .08
+(This is not put in as a standard recipient line to)5.08 F -.1(wa)117 606 S
+(rn an).1 E 2.5(yr)-.15 G(ecipients that the list is not complete.)159.51 606 Q
+(The Apparently-T)142 622.2 Q(o: header is non-standard and is deprecated.)-.8
+E F0 2.5(2.8.3. Pr)102 646.2 R(ecedence)-.18 E F1 .425
+(The Precedence: header can be used as a crude control of message priority)142
+662.4 R 5.425(.I)-.65 G 2.925(tt)455.38 662.4 S .425(weaks the)463.865 662.4 R
+(sort order in the queue and can be con\214gured to change the message timeout\
+ v)117 674.4 Q(alues.)-.25 E EP
+%%Page: 18 13
+%%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 2.5(2.9. IDENT)87 96 R(Pr)2.5 E
+(otocol Support)-.18 E/F1 10/Times-Italic@0 SF(Sendmail)127 112.2 Q/F2 10
+/Times-Roman@0 SF 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 124.2 R
+.29(`call back')-.74 F 2.79('t)-.74 G 2.79(ot)396.17 124.2 S .29
+(he originating system to)406.74 124.2 R .469(include the o)102 136.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 148.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:)102 160.2 Q
+2.5(6. Security)127 176.4 R(Considerations)2.5 E .006
+(The information returned by this protocol is at most as trustw)127 192.6 R
+(orth)-.1 E 2.505(ya)-.05 G 2.505(st)400.505 192.6 S .005(he host pro)409.68
+192.6 R .005(viding it OR)-.15 F .273(the or)127 204.6 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 204.6 R 2.774(wi)-.25 G 2.774(fa)
+448.612 204.6 S .574 -.15(ny c)459.156 204.6 T(ontrols).15 E .987(on it to pre)
+127 216.6 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 216.6 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 228.6 R(neous and misleading.)127 240.6 Q .521(The Identi\214cati\
+on Protocol is not intended as an authorization or access control protocol.)127
+256.8 R(At)5.52 E 1.036(best, it pro)127 268.8 R 1.037
+(vides some additional auditing information with respect to TCP connections.)
+-.15 F(At)6.037 E -.1(wo)127 280.8 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 297 R 2.697(couraged. Speci\214cally)127 309 R 2.697(,u)
+-.65 G .197(sing Identi\214cation Protocol information to mak)228.114 309 R
+2.697(ea)-.1 G .197(ccess control deci-)429.186 309 R .514(sions - either as t\
+he primary method \(i.e., no other checks\) or as an adjunct to other methods)
+127 321 R(may result in a weak)127 333 Q(ening of normal host security)-.1 E(.)
+-.65 E 1.778(An Identi\214cation serv)127 349.2 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 361.2 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 373.2 R .806
+(vided by some phone companies and man)-.15 F 3.306(yo)-.15 G(f)500.67 373.2 Q
+1.398(the same pri)127 385.2 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 397.2 R 1.045(you w)3.545 F(ouldn')-.1 E 3.545(tr)
+-.18 G 1.045(un a "\214nger" serv)260.33 397.2 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 409.2 Q(ant to run this protocol.)-.1 E .377
+(In some cases your system may not w)102 425.4 R .377
+(ork properly with IDENT support due to a b)-.1 F .376(ug in the TCP/IP)-.2 F
+3.675(implementation. The)102 437.4 R 1.175
+(symptoms will be that for some hosts the SMTP connection will be closed)3.675
+F .566(almost immediately)102 449.4 R 5.566(.I)-.65 G 3.066(ft)192.482 449.4 S
+.565(his is true or if you do not w)201.658 449.4 R .565(ant to use IDENT)-.1 F
+3.065(,y)-.74 G .565(ou should set the IDENT)401.75 449.4 R
+(timeout to zero; this will disable the IDENT protocol.)102 461.4 Q F0 2.5
+(3. ARGUMENTS)72 485.4 R F2 .017(The complete list of ar)112 501.6 R .017
+(guments to)-.18 F F1(sendmail)2.517 E F2 .017
+(is described in detail in Appendix A.)2.517 F .018(Some important)5.018 F(ar)
+87 513.6 Q(guments are described here.)-.18 E F0 2.5(3.1. Queue)87 537.6 R
+(Inter)2.5 E -.1(va)-.1 G(l).1 E F2 .455(The amount of time between forking a \
+process to run through the queue is de\214ned by the)127 553.8 R F0<ad71>2.955
+E F2 2.675(\215ag. If)102 565.8 R .175(you run with deli)2.675 F -.15(ve)-.25 G
+.175(ry mode set to).15 F F0(i)2.675 E F2(or)2.675 E F0(b)2.675 E F2 .176
+(this can be relati)2.675 F -.15(ve)-.25 G .176(ly lar).15 F .176
+(ge, since it will only be rel-)-.18 F -.25(eva)102 577.8 S .207
+(nt when a host that w).25 F .207(as do)-.1 F .207(wn comes back up.)-.25 F
+.206(If you run in)5.207 F F0(q)2.706 E F2 .206(mode it should be relati)2.706
+F -.15(ve)-.25 G .206(ly short,).15 F 1.039(since it de\214nes the maximum amo\
+unt of time that a message may sit in the queue.)102 589.8 R 1.039
+(\(See also the)6.039 F(MinQueueAge option.\))102 601.8 Q 1.336
+(RFC 1123 section 5.3.1.1 says that this v)127 618 R 1.335
+(alue should be at least 30 minutes \(although that)-.25 F(probably doesn')102
+630 Q 2.5(tm)-.18 G(ak)179.59 630 Q 2.5(es)-.1 G(ense if you use `)199.76 630 Q
+(`queue-only')-.74 E 2.5('m)-.74 G(ode\).)329.08 630 Q F0 2.5(3.2. Daemon)87
+654 R(Mode)2.5 E F2 .084(If you allo)127 670.2 R 2.584(wi)-.25 G .084
+(ncoming mail o)181.162 670.2 R -.15(ve)-.15 G 2.585(ra).15 G 2.585(nI)263.605
+670.2 S .085(PC connection, you should ha)274.52 670.2 R .385 -.15(ve a d)-.2 H
+.085(aemon running.).15 F(This)5.085 E .07(should be set by your)102 682.2 R F1
+(/etc/r)2.57 E(c)-.37 E F2 .07(\214le using the)2.57 F F0(\255bd)2.57 E F2
+2.569(\215ag. The)2.57 F F0(\255bd)2.569 E F2 .069(\215ag and the)2.569 F F0
+<ad71>2.569 E F2 .069(\215ag may be combined)2.569 F(in one call:)102 694.2 Q
+(/usr/sbin/sendmail \255bd \255q30m)142 710.4 Q EP
+%%Page: 19 14
+%%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 .292(An alternati)127 96 R .592
+-.15(ve a)-.25 H .292(pproach is to in).15 F -.2(vo)-.4 G .493 -.1(ke s).2 H
+.293(endmail from).1 F/F2 10/Times-Italic@0 SF(inetd)2.793 E F1 .293
+(\(8\) \(use the)B F0(\255bs)2.793 E F1 .293(\215ag to ask sendmail)2.793 F
+.255(to speak SMTP on its standard input and output\).)102 108 R .255(This w)
+5.255 F .255(orks and allo)-.1 F .255(ws you to wrap)-.25 F F2(sendmail)2.755 E
+F1 .255(in a)2.755 F 1.39(TCP wrapper program, b)102 120 R 1.39
+(ut may be a bit slo)-.2 F 1.39
+(wer since the con\214guration \214le has to be re-read on)-.25 F -2.15 -.25
+(ev e)102 132 T .556(ry message that comes in.).25 F .556
+(If you do this, you still need to ha)5.556 F .856 -.15(ve a)-.2 H F2(sendmail)
+3.206 E F1 .555(running to \215ush the)3.055 F(queue:)102 144 Q
+(/usr/sbin/sendmail \255q30m)142 160.2 Q F0 2.5(3.3. F)87 188.4 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 204.6 R -1.1(Yo)5.04 G 2.54(uc)1.1 G .04
+(an force)471.48 204.6 R 3.185(aq)102 216.6 S .685(ueue run using the)114.625
+216.6 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 228.6 Q
+(atch what happens:)-.1 E(/usr/sbin/sendmail \255q \255v)142 244.8 Q -1.1(Yo)
+127 265.2 S 4.004(uc)1.1 G 1.504
+(an also limit the jobs to those with a particular queue identi\214er)151.564
+265.2 R 4.004(,s)-.4 G(ender)428.362 265.2 Q 4.004(,o)-.4 G 4.004(rr)461.676
+265.2 S(ecipient)472.34 265.2 Q .687(using one of the queue modi\214ers.)102
+277.2 R -.15(Fo)5.687 G 3.187(re).15 G .687(xample, \231\255qRberk)265.659
+277.2 R(ele)-.1 E .686(y\232 restricts the queue run to jobs that)-.15 F(ha)102
+289.2 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 289.2 R
+(its the run to particular senders and \231\255qIstring\232 limits it to parti\
+cular queue identi\214ers.)102 301.2 Q F0 2.5(3.4. Deb)87 325.2 R(ugging)-.2 E
+F1 1.365(There are a f)127 341.4 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
+(sendmail)3.865 E F1 6.365(.E)C 1.365(ach deb)417.65 341.4 R 1.365
+(ug \215ag has a)-.2 F 1.116(number and a le)102 353.4 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 365.4 R -.15(ve)-.25 G .294
+(ls greater than nine are \231absurd,).15 F 2.794<9a69>-.7 G .294(.e., the)
+274.018 365.4 R 2.794(yp)-.15 G .293(rint out so much information that you w)
+313.616 365.4 R(ouldn')-.1 E(t)-.18 E .691(normally w)102 377.4 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 389.4 Q F0<ad64>2.5 E F1
+(option; the syntax is:)2.5 E(deb)142 405.6 Q(ug-\215ag:)-.2 E F0<ad64>200.13
+405.6 Q F1(deb)2.5 E(ug-list)-.2 E(deb)142 417.6 Q 13.05(ug-list: deb)-.2 F
+(ug-option [ , deb)-.2 E(ug-option ]*)-.2 E(deb)142 429.6 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 441.6 Q 3.07(ug-range: inte)-.2 F(ger | inte)-.15 E
+(ger \255 inte)-.15 E(ger)-.15 E(deb)142 453.6 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 469.8
+Q 5(.F)-.65 G(or e)268.64 469.8 Q(xample,)-.15 E 34.99(\255d12 Set)142 486 R
+(\215ag 12 to le)2.5 E -.15(ve)-.25 G 2.5(l1).15 G 27.49(\255d12.3 Set)142 498
+R(\215ag 12 to le)2.5 E -.15(ve)-.25 G 2.5(l3).15 G 24.35(\255d3\25517 Set)142
+510 R(\215ags 3 through 17 to le)2.5 E -.15(ve)-.25 G 2.5(l1).15 G 16.85
+(\255d3\25517.4 Set)142 522 R(\215ags 3 through 17 to le)2.5 E -.15(ve)-.25 G
+2.5(l4).15 G -.15(Fo)102 538.2 S 4.066(rac).15 G 1.566(omplete list of the a)
+132.752 538.2 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 538.2 R 4.065(ya)-.15 G 1.565(re too)479.385 538.2
+R(dynamic to k)102 550.2 Q(eep this documentation up to date\).)-.1 E F0 2.5
+(3.5. Changing)87 574.2 R(the V)2.5 E(alues of Options)-.92 E F1
+(Options can be o)127 590.4 Q -.15(ve)-.15 G(rridden using the).15 E F0<ad6f>
+2.5 E F1(or)2.5 E F0<ad4f>2.5 E F1(command line \215ags.)2.5 E -.15(Fo)5 G 2.5
+(re).15 G(xample,)420.27 590.4 Q(/usr/sbin/sendmail \255oT2m)142 606.6 Q .02
+(sets the)102 622.8 R F0(T)2.52 E F1 .02(\(timeout\) option to tw)2.52 F 2.52
+(om)-.1 G .021(inutes for this run only; the equi)246.77 622.8 R -.25(va)-.25 G
+.021(lent line using the long option).25 F(name is)102 634.8 Q
+(/usr/sbin/sendmail -OQueueT)142 651 Q(imeout=2m)-.35 E .72(Some options ha)127
+671.4 R 1.02 -.15(ve s)-.2 H .72(ecurity implications.).15 F .72(Sendmail allo)
+5.72 F .72(ws you to set these, b)-.25 F .72(ut relinquishes)-.2 F EP
+%%Page: 20 15
+%%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
+(its setuid root permissions thereafter)102 98 Q/F2 7/Times-Roman@0 SF(10)
+247.54 94 Q F1(.)254.54 98 Q F0 2.5(3.6. T)87 122 R(rying a Differ)-.74 E
+(ent Con\214guration File)-.18 E F1(An alternati)127 138.2 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 \255oQ/tmp/mqueue)142 154.4 Q .429
+(uses the con\214guration \214le)102 170.6 R/F3 10/Times-Italic@0 SF(test.cf)
+2.928 E F1 .428(instead of the def)2.928 F(ault)-.1 E F3(/etc/sendmail.cf)2.928
+E(.)-.15 E F1 .428(If the)5.428 F F0<ad43>2.928 E F1 .428(\215ag has no v)2.928
+F(alue)-.25 E(it def)102 182.6 Q(aults to)-.1 E F3(sendmail.cf)2.5 E F1
+(in the current directory)2.5 E(.)-.65 E F3(Sendmail)127 198.8 Q F1(gi)2.679 E
+-.15(ve)-.25 G 2.679(su).15 G 2.679(pi)195.288 198.8 S .18
+(ts setuid root permissions when you use this \215ag, so it is common to use a)
+205.747 198.8 R .069(publicly writable directory \(such as /tmp\) as the spool\
+ directory \(QueueDirectory or Q option\) while)102 210.8 R(testing.)102 222.8
+Q F0 2.5(3.7. Logging)87 246.8 R -.74(Tr)2.5 G(af\214c).74 E F1(Man)127 263 Q
+3.254(yS)-.15 G .754(MTP implementations do not fully implement the protocol.)
+158.994 263 R -.15(Fo)5.754 G 3.254(re).15 G .755(xample, some per)428.54 263 R
+(-)-.2 E 1.178(sonal computer based SMTPs do not understand continuation lines\
+ in reply codes.)102 275 R 1.177(These can be)6.178 F -.15(ve)102 287 S .13
+(ry hard to trace.).15 F .13(If you suspect such a problem, you can set traf)
+5.13 F .13(\214c logging using the)-.25 F F0<ad58>2.63 E F1 2.63(\215ag. F)2.63
+F(or)-.15 E -.15(ex)102 299 S(ample,).15 E(/usr/sbin/sendmail \255X /tmp/traf)
+142 315.2 Q(\214c \255bd)-.25 E(will log all traf)102 331.4 Q
+(\214c in the \214le)-.25 E F3(/tmp/tr)2.5 E(af)-.15 E<8c63>-.18 E F1(.)A .998
+(This logs a lot of data v)127 347.6 R .997(ery quickly and should)-.15 F F0
+(NEVER)3.497 E F1 .997(be used during normal operations.)3.497 F .962(After st\
+arting up such a daemon, force the errant implementation to send a message to \
+your host.)102 359.6 R .609(All message traf)102 371.6 R .609
+(\214c in and out of)-.25 F F3(sendmail)3.109 E F1 3.109(,i)C .609
+(ncluding the incoming SMTP traf)281.882 371.6 R .608(\214c, will be logged in)
+-.25 F(this \214le.)102 383.6 Q F0 2.5(3.8. T)87 407.6 R
+(esting Con\214guration Files)-.92 E F1 .643(When you b)127 423.8 R .644(uild \
+a con\214guration table, you can do a certain amount of testing using the \231\
+test)-.2 F(mode\232 of)102 435.8 Q F3(sendmail)2.5 E F1 5(.F)C(or e)191.01
+435.8 Q(xample, you could in)-.15 E -.2(vo)-.4 G -.1(ke).2 G F3(sendmail)2.6 E
+F1(as:)2.5 E(sendmail \255bt \255Ctest.cf)142 452 Q .448(which w)102 468.2 R
+.448(ould read the con\214guration \214le \231test.cf\232 and enter test mode.)
+-.1 F .447(In this mode, you enter lines)5.447 F(of the form:)102 480.2 Q
+(rwset address)142 496.4 Q(where)102 512.6 Q F3(rwset)3.006 E F1 .506
+(is the re)3.006 F .506(writing set you w)-.25 F .506(ant to use and)-.1 F F3
+(addr)3.007 E(ess)-.37 E F1 .507(is an address to apply the set to.)3.007 F -.7
+(Te)5.507 G(st).7 E .794(mode sho)102 524.6 R .794(ws you the steps it tak)-.25
+F .794(es as it proceeds, \214nally sho)-.1 F .794
+(wing you the address it ends up with.)-.25 F -1.1(Yo)102 536.6 S 3.331(um)1.1
+G .832(ay use a comma separated list of rwsets for sequential application of r\
+ules to an input.)129.231 536.6 R -.15(Fo)5.832 G(r).15 E -.15(ex)102 548.6 S
+(ample:).15 E(3,1,21,4 monet:bollard)142 564.8 Q .622
+(\214rst applies ruleset three to the input \231monet:bollard.)102 581 R 5.622
+<9a52>-.7 G .622(uleset one is then applied to the output of)334.036 581 R
+(ruleset three, follo)102 593 Q(wed similarly by rulesets twenty-one and four)
+-.25 E(.)-.55 E 1.084(If you need more detail, you can also use the \231\255d2\
+1\232 \215ag to turn on more deb)127 609.2 R 3.585(ugging. F)-.2 F(or)-.15 E
+-.15(ex)102 621.2 S(ample,).15 E(sendmail \255bt \255d21.99)142 637.4 Q .689
+(turns on an incredible amount of information; a single w)102 653.6 R .688
+(ord address is probably going to print out)-.1 F(se)102 665.6 Q -.15(ve)-.25 G
+(ral pages w).15 E(orth of information.)-.1 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(10)93.6 689.2 Q/F5 8/Times-Roman@0 SF .497
+(That is, it sets its ef)3.2 J(fecti)-.2 E .737 -.12(ve u)-.2 H .497
+(id to the real uid; thus, if you are e).12 F -.12(xe)-.12 G .497
+(cuting as root, as from root').12 F 2.497(sc)-.44 G .497
+(rontab \214le or during system)413.572 692.4 R
+(startup the root permissions will still be honored.)72 702 Q EP
+%%Page: 21 16
+%%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.1(Yo)127 96 S 2.574(us)1.1 G
+.074(hould be w)149.584 96 R .074(arned that internally)-.1 F(,)-.65 E/F2 10
+/Times-Italic@0 SF(sendmail)2.575 E F1 .075
+(applies ruleset 3 to all addresses.)2.575 F .075(In test mode)5.075 F
+(you will ha)102 108 Q .3 -.15(ve t)-.2 H 2.5(od).15 G 2.5(ot)173.87 108 S
+(hat manually)184.15 108 Q 5(.F)-.65 G(or e)248.35 108 Q(xample, older v)-.15 E
+(ersions allo)-.15 E(wed you to use)-.25 E 2.5(0b)142 124.2 S
+(ruce@broadcast.son)154.5 124.2 Q -.65(y.)-.15 G(com).65 E(This v)102 140.4 Q
+(ersion requires that you use:)-.15 E(3,0 bruce@broadcast.son)142 156.6 Q -.65
+(y.)-.15 G(com).65 E(As of v)127 177 Q(ersion 8.7, some other syntax)-.15 E
+(es are a)-.15 E -.25(va)-.2 G(ilable in test mode:).25 E 5<832e>107 193.2 S
+1.666(Dxv)118 193.2 S .328(alue de\214nes macro)-1.916 F F2(x)2.828 E F1 .328
+(to ha)2.828 F .628 -.15(ve t)-.2 H .328(he indicated).15 F F2(value)2.828 E F1
+5.328(.T)C .328(his is useful when deb)346.134 193.2 R .327(ugging rules that)
+-.2 F(use the)115.5 205.2 Q F0($&)2.5 E F2(x)A F1(syntax.)2.5 E 5<832e>107
+217.2 S 1.666(Ccv)118 217.2 S(alue adds the indicated)-1.916 E F2(value)2.5 E
+F1(to class)2.5 E F2(c)2.5 E F1(.)A 5<832e>107 229.2 S 1.666(Sr)118 229.2 S
+(uleset dumps the contents of the indicated ruleset.)-1.666 E 5<83ad>107 241.2
+S 1.666(dd)121.14 241.2 S(eb)-1.666 E(ug-spec is equi)-.2 E -.25(va)-.25 G
+(lent to the command-line \215ag.).25 E F0 2.5(4. TUNING)72 265.2 R F1 1.922
+(There are a number of con\214guration parameters you may w)112 281.4 R 1.922
+(ant to change, depending on the)-.1 F .367(requirements of your site.)87 293.4
+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 293.4 Q(the line \231O T)
+87 305.4 Q(imeout.queuereturn=5d\232 sets option \231T)-.35 E
+(imeout.queuereturn\232 to the v)-.35 E(alue \2315d\232 \(\214v)-.25 E 2.5(ed)
+-.15 G(ays\).)476.47 305.4 Q .735(Most of these options ha)112 321.6 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 333.6 R
+2.546(yn)-.15 G .046(eed to tune them as appropriate for their mail load.)
+193.47 333.6 R .045(In particular)5.045 F 2.545(,s)-.4 G .045(ites e)459.395
+333.6 R(xperi-)-.15 E 1.087(encing a lar)87 345.6 R 1.087
+(ge number of small messages, man)-.18 F 3.587(yo)-.15 G 3.588(fw)294.496 345.6
+S 1.088(hich are deli)308.634 345.6 R -.15(ve)-.25 G 1.088(red to man).15 F
+3.588(yr)-.15 G 1.088(ecipients, may \214nd)425.994 345.6 R(that the)87 357.6 Q
+2.5(yn)-.15 G(eed to adjust the parameters dealing with queue priorities.)
+129.07 357.6 Q .524(All v)112 373.8 R .524(ersions of)-.15 F F2(sendmail)3.024
+E F1 .524(prior to 8.7 had single character option names.)3.024 F .523
+(As of 8.7, options ha)5.524 F -.15(ve)-.2 G 1.215
+(long \(multi-character names\).)87 385.8 R 1.216
+(Although old short names are still accepted, most ne)6.215 F 3.716(wo)-.25 G
+1.216(ptions do not)449.338 385.8 R(ha)87 397.8 Q .3 -.15(ve s)-.2 H(hort equi)
+.15 E -.25(va)-.25 G(lents.).25 E .802
+(This section only describes the options you are most lik)112 414 R .802
+(ely to w)-.1 F .801(ant to tweak; read section 5 for)-.1 F(more details.)87
+426 Q F0 2.5(4.1. T)87 450 R(imeouts)-.18 E F1 .582(All time interv)127 466.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.138 466.2 R
+(whereas \2312h30m\232 represents tw)102 478.2 Q 2.5(oa)-.1 G(nd a half hours.)
+241.3 478.2 Q(The full set of scales is:)5 E 16.11(ss)142 494.4 S(econds)165.89
+494.4 Q 12.22(mm)142 506.4 S(inutes)169.78 506.4 Q 15(hh)142 518.4 S(ours)167
+518.4 Q 15(dd)142 530.4 S(ays)167 530.4 Q 12.78(ww)142 542.4 S(eeks)169.22
+542.4 Q F0 2.5(4.1.1. Queue)102 570.6 R(inter)2.5 E -.1(va)-.1 G(l).1 E F1 .18
+(The ar)142 586.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 586.8 R .18(This is)5.18 F .967
+(typically set to between \214fteen minutes and one hour)117 598.8 R 5.968(.R)
+-.55 G .968(FC 1123 section 5.3.1.1 recommends)350.968 598.8 R
+(that this be at least 30 minutes.)117 610.8 Q F0 2.5(4.1.2. Read)102 634.8 R
+(timeouts)2.5 E F1 -.35(Ti)142 651 S 1.053(meouts all ha).35 F 1.352 -.15(ve o)
+-.2 H 1.052(ption names \231T).15 F(imeout.)-.35 E F2(suboption)A F1 3.552
+(\232. The)B(recognized)3.552 E F2(suboption)3.552 E F1 1.052(s, their)B(def)
+117 663 Q(ault v)-.1 E(alues, and the minimum v)-.25 E(alues allo)-.25 E
+(wed by RFC 1123 section 5.3.2 are:)-.25 E 38.4(connect The)117 679.2 R .16
+(time to w)2.66 F .161(ait for an SMTP connection to open \(the)-.1 F F2
+(connect)2.661 E F1 .161(\(2\) system call\))B 1.154([0, unspeci\214ed].)189
+691.2 R 1.153(If zero, uses the k)6.153 F 1.153(ernel def)-.1 F 3.653(ault. In)
+-.1 F 1.153(no case can this option)3.653 F -.15(ex)189 703.2 S .518
+(tend the timeout longer than the k).15 F .518(ernel pro)-.1 F .519(vides, b)
+-.15 F .519(ut it can shorten it.)-.2 F(This)5.519 E .58(is to get around k)189
+715.2 R .579(ernels that pro)-.1 F .579
+(vide an absurdly long connection timeout \(90)-.15 F EP
+%%Page: 22 17
+%%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
+(minutes in one case\).)189 96 Q 46.16(initial The)117 112.2 R -.1(wa)2.5 G
+(it for the initial 220 greeting message [5m, 5m].).1 E 52.28(helo The)117
+128.4 R -.1(wa)4.226 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 140.4 R 2.6(em)-.15 G .1
+(inutes is probably a reasonable)380.29 140.4 R(minimum.)189 152.4 Q 46.72
+(mail\207 The)117 168.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
+184.8 R -.1(wa)3.481 G .981(it for a reply from a RCPT command [1h, 5m].).1 F
+.982(This should be long)5.982 F 1.556
+(because it could be pointing at a list that tak)189 196.8 R 1.556
+(es a long time to e)-.1 F 1.556(xpand \(see)-.15 F(belo)189 208.8 Q(w\).)-.25
+E 34.5(datainit\207 The)117 225 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
+241.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
+253.2 R/F2 10/Times-Italic@0 SF(send-)3.12 E(mail)189 265.2 Q F1(which ha)2.5 E
+.3 -.15(ve n)-.2 H 2.5(og).15 G(uarantee of promptness.)274.75 265.2 Q 30.06
+(data\214nal\207 The)117 281.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 293.4 R -.15(ve)-.25 G
+3.383(rt).15 G 3.383(od)412.881 293.4 S(eli)426.264 293.4 Q -.15(ve)-.25 G
+3.383(rt).15 G .883(he message,)454.797 293.4 R(duplicates will be generated.)
+189 305.4 Q(This is discussed in RFC 1047.)5 E 55.06(rset The)117 321.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 337.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 354 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 366 Q(erbose mode\).)-.15 E([2m, unspeci\214ed].)5 E 25.06(command\207 In)
+117 382.2 R(serv)2.5 E(er SMTP)-.15 E 2.5(,t)-1.11 G(he time to w)259.4 382.2 Q
+(ait for another command.)-.1 E([1h, 5m].)5 E 49.5(ident The)117 400.4 R
+(timeout w)2.5 E(aiting for a reply to an IDENT query [30s)-.1 E/F3 7
+/Times-Roman@0 SF(11)413.86 396.4 Q F1 2.5(,u)420.86 400.4 S(nspeci\214ed].)
+430.86 400.4 Q -.15(Fo)117 416.6 S 4.609(rc).15 G 2.109
+(ompatibility with old con\214guration \214les, if no)139.789 416.6 R F2
+(suboption)4.608 E F1 2.108(is speci\214ed, all the timeouts)4.608 F(mark)117
+428.6 Q(ed with \207 are set to the indicated v)-.1 E(alue.)-.25 E(Man)142
+444.8 Q 2.5(yo)-.15 G 2.5(ft)172.68 444.8 S(he RFC 1123 minimum v)181.29 444.8
+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 444.8 R .712
+(the RFC 822 protocols, which did not specify read timeouts; hence, v)117 456.8
+R .711(ersions of)-.15 F F2(sendmail)3.211 E F1(prior)3.211 E .864(to v)117
+468.8 R .865(ersion 8.1 did not guarantee to reply to messages promptly)-.15 F
+5.865(.I)-.65 G 3.365(np)386.24 468.8 S(articular)399.605 468.8 Q 3.365(,a\231)
+-.4 G .865(RCPT\232 com-)450.635 468.8 R .061
+(mand specifying a mailing list will e)117 480.8 R .061(xpand and v)-.15 F .06
+(erify the entire list; a lar)-.15 F .06(ge list on a slo)-.18 F 2.56(ws)-.25 G
+(ystem)480.11 480.8 Q .436(may easily tak)117 494.8 R 2.936(em)-.1 G .436
+(ore than \214v)190.698 494.8 R 2.936(em)-.15 G(inutes)252.126 494.8 Q F3(12)
+276.016 490.8 Q F1 5.436(.I)283.016 494.8 S .435
+(recommend a one hour timeout \212 since a commu-)297.218 494.8 R 1.365
+(nications f)117 506.8 R 1.366(ailure during the RCPT phase is rare, a long ti\
+meout is not onerous and may ulti-)-.1 F(mately help reduce netw)117 518.8 Q
+(ork load and duplicated messages.)-.1 E -.15(Fo)142 535 S 2.5(re).15 G
+(xample, the lines:)162.53 535 Q 2.5(OT)157 551.2 S(imeout.command=25m)172.48
+551.2 Q 2.5(OT)157 563.2 S(imeout.datablock=3h)172.48 563.2 Q .344
+(sets the serv)117 579.4 R .344(er SMTP command timeout to 25 minutes and the \
+input data block timeout to three)-.15 F(hours.)117 591.4 Q F0 2.5
+(4.1.3. Message)102 615.4 R(timeouts)2.5 E F1 .237
+(After sitting in the queue for a fe)142 631.6 R 2.737(wd)-.25 G .237
+(ays, a message will time out.)289.726 631.6 R .238(This is to insure that at)
+5.238 F .568(least the sender is a)117 643.6 R -.1(wa)-.15 G .568
+(re of the inability to send a message.).1 F .567
+(The timeout is typically set to \214v)5.568 F(e)-.15 E 2.599(days. It)117
+655.6 R .099(is sometimes considered con)2.599 F -.15(ve)-.4 G .099
+(nient to also send a w).15 F .1(arning message if the message is in)-.1 F .32
+LW 76 665.2 72 665.2 DL 80 665.2 76 665.2 DL 84 665.2 80 665.2 DL 88 665.2 84
+665.2 DL 92 665.2 88 665.2 DL 96 665.2 92 665.2 DL 100 665.2 96 665.2 DL 104
+665.2 100 665.2 DL 108 665.2 104 665.2 DL 112 665.2 108 665.2 DL 116 665.2 112
+665.2 DL 120 665.2 116 665.2 DL 124 665.2 120 665.2 DL 128 665.2 124 665.2 DL
+132 665.2 128 665.2 DL 136 665.2 132 665.2 DL 140 665.2 136 665.2 DL 144 665.2
+140 665.2 DL 148 665.2 144 665.2 DL 152 665.2 148 665.2 DL 156 665.2 152 665.2
+DL 160 665.2 156 665.2 DL 164 665.2 160 665.2 DL 168 665.2 164 665.2 DL 172
+665.2 168 665.2 DL 176 665.2 172 665.2 DL 180 665.2 176 665.2 DL 184 665.2 180
+665.2 DL 188 665.2 184 665.2 DL 192 665.2 188 665.2 DL 196 665.2 192 665.2 DL
+200 665.2 196 665.2 DL 204 665.2 200 665.2 DL 208 665.2 204 665.2 DL 212 665.2
+208 665.2 DL 216 665.2 212 665.2 DL/F4 5/Times-Roman@0 SF(11)93.6 675.6 Q/F5 8
+/Times-Roman@0 SF(On some systems the def)3.2 I
+(ault is zero to turn the protocol of)-.08 E 2(fe)-.2 G(ntirely)293.848 678.8 Q
+(.)-.52 E F4(12)93.6 689.2 Q F5 .212(This v)3.2 J .212
+(eri\214cation includes looking up e)-.12 F -.12(ve)-.2 G .212
+(ry address with the name serv).12 F .212(er; this in)-.12 F -.16(vo)-.32 G(lv)
+.16 E .212(es netw)-.12 F .213(ork delays, and can in some cases)-.08 F
+(can be considerable.)72 702 Q EP
+%%Page: 23 18
+%%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 .176(the queue longer than a fe)
+117 96 R 2.675(wh)-.25 G .175(ours \(assuming you normally ha)236.105 96 R .475
+-.15(ve g)-.2 H .175(ood connecti).15 F .175(vity; if your mes-)-.25 F .645
+(sages normally took se)117 108 R -.15(ve)-.25 G .645(ral hours to send you w)
+.15 F(ouldn')-.1 E 3.145(tw)-.18 G .645(ant to do this because it w)355.055 108
+R(ouldn')-.1 E 3.145(tb)-.18 G(e)499.56 108 Q 3.871(an unusual e)117 120 R -.15
+(ve)-.25 G 6.371(nt\). These).15 F 3.871(timeouts are set using the)6.371 F F0
+-.18(Ti)6.371 G(meout.queuer).18 E(etur)-.18 E(n)-.15 E F1(and)6.371 E F0 -.18
+(Ti)6.37 G(me-).18 E(out.queuewar)117 132 Q(n)-.15 E F1
+(options in the con\214guration \214le \(pre)2.5 E
+(viously both were set using the)-.25 E F0(T)2.5 E F1(option\).)2.5 E .106
+(Since these options are global, and since you can not kno)142 148.2 R(w)-.25 E
+/F2 10/Times-Italic@0 SF 2.606(ap)2.606 G(riori)393.822 148.2 Q F1(ho)2.607 E
+2.607(wl)-.25 G .107(ong another host)437.126 148.2 R .476
+(outside your domain will be do)117 160.2 R .475(wn, a \214v)-.25 F 2.975(ed)
+-.15 G .475(ay timeout is recommended.)291.785 160.2 R .475(This allo)5.475 F
+.475(ws a recipient)-.25 F 1.579(to \214x the problem e)117 172.2 R -.15(ve)
+-.25 G 4.079(ni).15 G 4.079(fi)222.545 172.2 S 4.079(to)232.734 172.2 S 1.579
+(ccurs at the be)244.593 172.2 R 1.58(ginning of a long week)-.15 F 4.08
+(end. RFC)-.1 F 1.58(1123 section)4.08 F
+(5.3.1.1 says that this parameter should be `)117 184.2 Q
+(`at least 4\2555 days')-.74 E('.)-.74 E(The)142 200.4 Q F0 -.18(Ti)2.923 G
+(meout.queuewar).18 E(n)-.15 E F1 -.25(va)2.923 G .423(lue can be piggyback).25
+F .422(ed on the)-.1 F F0(T)2.922 E F1 .422(option by indicating a time)2.922 F
+.845(after which a w)117 212.4 R .845(arning message should be sent; the tw)-.1
+F 3.346(ot)-.1 G .846(imeouts are separated by a slash.)349.104 212.4 R -.15
+(Fo)5.846 G(r).15 E -.15(ex)117 224.4 S(ample, the line).15 E -.4(OT)157 240.6
+S(5d/4h).4 E .972(causes email to f)117 256.8 R .971(ail after \214v)-.1 F
+3.471(ed)-.15 G .971(ays, b)245.329 256.8 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 268.8 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
+292.8 R(orking During Queue Runs)-.25 E F1 .848(By setting the)127 309 R F0
+-.25(Fo)3.348 G(rkEachJ).25 E(ob)-.15 E F1(\()3.348 E F0(Y)A F1 3.348(\)o)C
+(ption,)271.12 309 Q F2(sendmail)3.348 E F1 .849(will fork before each indi)
+3.348 F .849(vidual message)-.25 F .293(while running the queue.)102 321 R .293
+(This will pre)5.293 F -.15(ve)-.25 G(nt).15 E F2(sendmail)2.793 E F1 .293
+(from consuming lar)2.793 F .293(ge amounts of memory)-.18 F 2.792(,s)-.65 G(o)
+499 321 Q 1.11(it may be useful in memory-poor en)102 333 R 3.61
+(vironments. Ho)-.4 F(we)-.25 E -.15(ve)-.25 G 1.91 -.4(r, i).15 H 3.61(ft).4 G
+(he)359.95 333 Q F0 -.25(Fo)3.61 G(rkEachJ).25 E(ob)-.15 E F1 1.11
+(option is not set,)3.61 F F2(sendmail)102 345 Q F1 .085(will k)2.585 F .085
+(eep track of hosts that are do)-.1 F .084
+(wn during a queue run, which can impro)-.25 F .384 -.15(ve p)-.15 H
+(erformance).15 E(dramatically)102 357 Q(.)-.65 E(If the)127 373.2 Q F0 -.25
+(Fo)2.5 G(rkEachJ).25 E(ob)-.15 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 397.2 R(Priorities)
+2.5 E F1(Ev)127 413.4 Q 1.128(ery message is assigned a priority when it is \
+\214rst instantiated, consisting of the message)-.15 F .286
+(size \(in bytes\) of)102 425.4 R .286(fset by the message class \(which is de\
+termined from the Precedence: header\) times)-.25 F .342(the \231w)102 437.4 R
+.342(ork class f)-.1 F .343
+(actor\232 and the number of recipients times the \231w)-.1 F .343
+(ork recipient f)-.1 F(actor)-.1 E 4.243 -.7(.\232 T)-.55 H .343(he priority).7
+F .073(is used to order the queue.)102 449.4 R .073
+(Higher numbers for the priority mean that the message will be processed)5.073
+F(later when running the queue.)102 461.4 Q .328
+(The message size is included so that lar)127 477.6 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 477.6 R .285(The message class allo)102 489.6 R
+.285(ws users to send \231high priority\232 messages by including a \231Preced\
+ence:\232 \214eld)-.25 F .007(in their message; the v)102 501.6 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 513.6 R 1.967
+(fects the amount of load a message presents to the system, this is also)-.25 F
+(included into the priority)102 525.6 Q(.)-.65 E .53(The recipient and class f)
+127 541.8 R .53(actors can be set in the con\214guration \214le using the)-.1 F
+F0(RecipientF)3.03 E(actor)-.25 E F1(\()102 553.8 Q F0(y)A F1 3.443(\)a)C(nd)
+121.543 553.8 Q F0(ClassF)3.443 E(actor)-.25 E F1(\()3.442 E F0(z)A F1 3.442
+(\)o)C .942(ptions respecti)208.82 553.8 R -.15(ve)-.25 G(ly).15 E 5.942(.T)
+-.65 G(he)298.534 553.8 Q 3.442(yd)-.15 G(ef)321.266 553.8 Q .942
+(ault to 30000 \(for the recipient f)-.1 F .942(actor\) and)-.1 F
+(1800 \(for the class f)102 565.8 Q 2.5(actor\). The)-.1 F
+(initial priority is:)2.5 E F2(pri)168.495 583.8 Q/F3 10/Symbol SF(=)3.16 E F2
+(msgsize)3.18 E F3(-)2.38 E F1(\()2.2 E F2(class).2 E F3<b4>2.47 E F0
+(ClassFactor\))2.2 E F3(+)2.2 E F1(\()2.2 E F2(nrcpt).36 E F3<b4>2.88 E F0
+(RecipientFactor\))2.2 E F1(\(Remember)102 601.8 Q 3.328(,h)-.4 G .828(igher v)
+159.638 601.8 R .828
+(alues for this parameter actually mean that the job will be treated with lo)
+-.25 F(wer)-.25 E(priority)102 613.8 Q(.\))-.65 E 1.519(The priority of a job \
+can also be adjusted each time it is processed \(that is, each time an)127 630
+R .235(attempt is made to deli)102 642 R -.15(ve)-.25 G 2.736(ri).15 G .236
+(t\) using the \231w)211.938 642 R .236(ork time f)-.1 F(actor)-.1 E 1.636 -.7
+(,\232 s)-.4 H .236(et by the).7 F F0(RetryF)2.736 E(actor)-.25 E F1(\()2.736 E
+F0(Z)A F1 2.736(\)o)C 2.736(ption. This)457.924 642 R .367
+(is added to the priority)102 654 R 2.867(,s)-.65 G 2.867(oi)202.625 654 S
+2.867(tn)213.272 654 S .366
+(ormally decreases the precedence of the job, on the grounds that jobs)223.919
+654 R .137(that ha)102 666 R .437 -.15(ve f)-.2 H .137(ailed man).05 F 2.637
+(yt)-.15 G .137(imes will tend to f)193.598 666 R .137(ail ag)-.1 F .137
+(ain in the future.)-.05 F(The)5.137 E F0(RetryF)2.637 E(actor)-.25 E F1 .137
+(option def)2.637 F .138(aults to)-.1 F(90000.)102 678 Q EP
+%%Page: 24 19
+%%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 2.5(4.4. Load)87 96 R(Limiting)2.5 E/F1
+10/Times-Italic@0 SF(Sendmail)127 112.2 Q/F2 10/Times-Roman@0 SF .102
+(can be ask)2.602 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 .101
+(rage gets too high).15 F .483(using the)102 124.2 R F0(QueueLA)2.983 E F2(\()
+2.983 E F0(x)A F2 2.983(\)o)C 2.983(ption. When)206.152 124.2 R .483
+(the load a)2.983 F -.15(ve)-.2 G .483(rage e).15 F .483(xceeds the v)-.15 F
+.484(alue of the)-.25 F F0(QueueLA)2.984 E F2(option,)2.984 E .532(the deli)102
+136.2 R -.15(ve)-.25 G .532(ry mode is set to).15 F F0(q)3.032 E F2 .532
+(\(queue only\) if the)3.032 F F0(QueueF)3.032 E(actor)-.25 E F2(\()3.032 E F0
+(q)A F2 3.032(\)o)C .531(ption di)379.066 136.2 R .531(vided by the dif)-.25 F
+(ference)-.25 E .004(in the current load a)102 148.2 R -.15(ve)-.2 G .004
+(rage and the).15 F F0(QueueLA)2.504 E F2 .004(option plus one e)2.504 F .004
+(xceeds the priority of the message \212)-.15 F
+(that is, the message is queued if)102 160.2 Q(f:)-.25 E F1(pri)251.425 183.61
+Q F2(>)3.16 E F0(QueueFactor)287.21 176.61 Q F1(LA)276.475 190.61 Q/F3 10
+/Symbol SF(-)2.23 E F0(QueueLA)2.2 E F3(+)2.2 E .4 LW 354.625 181.01 275.895
+181.01 DL F2(1)349.625 190.61 Q(The)102 206.87 Q F0(QueueF)2.616 E(actor)-.25 E
+F2 .116(option def)2.616 F .116(aults to 600000, so each point of load a)-.1 F
+-.15(ve)-.2 G .116(rage is w).15 F .116(orth 600000 priority)-.1 F
+(points \(as described abo)102 218.87 Q -.15(ve)-.15 G(\).).15 E -.15(Fo)127
+235.07 S 3.893(rd).15 G 1.393(rastic cases, the)149.633 235.07 R F0(RefuseLA)
+3.893 E F2(\()3.893 E F0(X)A F2 3.893(\)o)C 1.394(ption de\214nes a load a)
+288.228 235.07 R -.15(ve)-.2 G 1.394(rage at which).15 F F1(sendmail)3.894 E F2
+(will)3.894 E .69(refuse to accept netw)102 247.07 R .689(ork connections.)-.1
+F .689(Locally generated mail \(including incoming UUCP mail\) is)5.689 F
+(still accepted.)102 259.07 Q F0 2.5(4.5. Deli)87 283.07 R -.1(ve)-.1 G
+(ry Mode).1 E F2 .253(There are a number of deli)127 299.27 R -.15(ve)-.25 G
+.253(ry modes that).15 F F1(sendmail)2.753 E F2 .254
+(can operate in, set by the)2.753 F F0(Deli)2.754 E -.1(ve)-.1 G(ryMode).1 E F2
+(\()102 311.27 Q F0(d)A F2 3.599(\)c)C 1.099(on\214guration option.)122.259
+311.27 R 1.099(These modes specify ho)6.099 F 3.598(wq)-.25 G 1.098
+(uickly mail will be deli)324.142 311.27 R -.15(ve)-.25 G 3.598(red. Le).15 F
+-.05(ga)-.15 G 3.598(lm).05 G(odes)485.67 311.27 Q(are:)102 323.27 Q 17.22(id)
+142 339.47 S(eli)167 339.47 Q -.15(ve)-.25 G 2.5(ri).15 G(nteracti)194.65
+339.47 Q -.15(ve)-.25 G(ly \(synchronously\)).15 E 15(bd)142 351.47 S(eli)167
+351.47 Q -.15(ve)-.25 G 2.5(ri).15 G 2.5(nb)194.65 351.47 S
+(ackground \(asynchronously\))207.15 351.47 Q 15(qq)142 363.47 S
+(ueue only \(don')167 363.47 Q 2.5(td)-.18 G(eli)240.42 363.47 Q -.15(ve)-.25 G
+(r\)).15 E 15(dd)142 375.47 S(efer delv)167 375.47 Q(ery attempts \(don')-.15 E
+2.5(td)-.18 G(eli)285.53 375.47 Q -.15(ve)-.25 G(r\)).15 E 1.273
+(There are tradeof)102 391.67 R 3.773(fs. Mode)-.25 F 1.273(\231i\232 gi)3.773
+F -.15(ve)-.25 G 3.773(st).15 G 1.273(he sender the quick)258.938 391.67 R
+1.273(est feedback, b)-.1 F 1.274(ut may slo)-.2 F 3.774(wd)-.25 G -.25(ow)
+462.146 391.67 S 3.774(ns).25 G(ome)486.78 391.67 Q .799
+(mailers and is hardly e)102 403.67 R -.15(ve)-.25 G 3.299(rn).15 G(ecessary)
+216.405 403.67 Q 5.799(.M)-.65 G .799(ode \231b\232 deli)266.814 403.67 R -.15
+(ve)-.25 G .799(rs promptly b).15 F .798(ut can cause lar)-.2 F .798
+(ge numbers of)-.18 F .223(processes if you ha)102 415.67 R .524 -.15(ve a m)
+-.2 H .224(ailer that tak).15 F .224(es a long time to deli)-.1 F -.15(ve)-.25
+G 2.724(ram).15 G 2.724(essage. Mode)370.904 415.67 R .224
+(\231q\232 minimizes the)2.724 F .597(load on your machine, b)102 427.67 R .597
+(ut means that deli)-.2 F -.15(ve)-.25 G .596
+(ry may be delayed for up to the queue interv).15 F 3.096(al. Mode)-.25 F .039
+(\231d\232 is identical to mode \231q\232 e)102 439.67 R .039
+(xcept that it also pre)-.15 F -.15(ve)-.25 G .04
+(nts all the early map lookups from w).15 F .04(orking; it is)-.1 F .086
+(intended for `)102 451.67 R .086(`dial on demand')-.74 F 2.586('s)-.74 G .085
+(ites where DNS lookups might cost real mone)233.42 451.67 R 3.885 -.65(y. S)
+-.15 H .085(ome simple error).65 F .817(messages \(e.g., host unkno)102 463.67
+R .817(wn during the SMTP protocol\) will be delayed using this mode.)-.25 F
+(Mode)5.818 E(\231b\232 is the usual def)102 475.67 Q(ault.)-.1 E .052(If you \
+run in mode \231q\232 \(queue only\), \231d\232 \(defer\), or \231b\232 \(deli)
+127 491.87 R -.15(ve)-.25 G 2.552(ri).15 G 2.552(nb)389.136 491.87 S
+(ackground\))401.688 491.87 Q F1(sendmail)2.551 E F2(will)2.551 E 1.391(not e)
+102 503.87 R 1.392(xpand aliases and follo)-.15 F 3.892(w.)-.25 G(forw)232.428
+503.87 Q 1.392(ard \214les upon initial receipt of the mail.)-.1 F 1.392
+(This speeds up the)6.392 F(response to RCPT commands.)102 515.87 Q
+(Mode \231i\232 cannot be used by the SMTP serv)5 E(er)-.15 E(.)-.55 E F0 2.5
+(4.6. Log)87 539.87 R(Le)2.5 E -.1(ve)-.15 G(l).1 E F2 .19(The le)127 556.07 R
+-.15(ve)-.25 G 2.69(lo).15 G 2.69(fl)171.97 556.07 S .19(ogging can be set for)
+180.77 556.07 R F1(sendmail)2.689 E F2 5.189(.T)C .189(he def)317.996 556.07 R
+.189(ault using a standard con\214guration table)-.1 F(is le)102 568.07 Q -.15
+(ve)-.25 G 2.5(l9).15 G 5(.T)137.71 568.07 S(he le)151.32 568.07 Q -.15(ve)-.25
+G(ls are as follo).15 E(ws:)-.25 E 31(0N)102 584.27 S 2.5(ol)145.22 584.27 S
+(ogging.)155.5 584.27 Q 31(1S)102 600.47 S(erious system f)143.56 600.47 Q
+(ailures and potential security problems.)-.1 E 31(2L)102 616.67 S
+(ost communications \(netw)144.11 616.67 Q(ork problems\) and protocol f)-.1 E
+(ailures.)-.1 E 31(3O)102 632.87 S(ther serious f)145.22 632.87 Q(ailures.)-.1
+E 31(4M)102 649.07 S(inor f)146.89 649.07 Q(ailures.)-.1 E 31(5M)102 665.27 S
+(essage collection statistics.)146.89 665.27 Q 31(6C)102 681.47 S
+(reation of error messages, VRFY and EXPN commands.)144.67 681.47 Q 31(7D)102
+697.67 S(eli)145.22 697.67 Q -.15(ve)-.25 G(ry f).15 E
+(ailures \(host or user unkno)-.1 E(wn, etc.\).)-.25 E 31(8S)102 713.87 S
+(uccessful deli)143.56 713.87 Q -.15(ve)-.25 G(ries and alias database reb).15
+E(uilds.)-.2 E EP
+%%Page: 25 20
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-25)452.9 60 Q/F1 10/Times-Roman@0 SF 31(9M)102 96 S
+(essages being deferred \(due to a host being do)146.89 96 Q(wn, etc.\).)-.25 E
+23.5(10 Database)102 112.2 R -.15(ex)2.5 G(pansion \(alias, forw).15 E
+(ard, and userdb lookups\).)-.1 E 23.5(20 Logs)102 128.4 R .603
+(attempts to run lock)3.102 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 140.4 Q 23.5(30 Lost)102 156.6 R
+(locks \(only if using lockf instead of \215ock\).)2.5 E(Additionally)102 172.8
+Q 2.717(,v)-.65 G .217(alues abo)161.877 172.8 R .516 -.15(ve 6)-.15 H 2.716
+(4a).15 G .216(re reserv)228.596 172.8 R .216(ed for e)-.15 F .216(xtremely v)
+-.15 F .216(erbose deb)-.15 F .216(ugging output.)-.2 F .216(No normal site)
+5.216 F -.1(wo)102 184.8 S(uld e).1 E -.15(ve)-.25 G 2.5(rs).15 G(et these.)
+152.6 184.8 Q F0 2.5(4.7. File)87 208.8 R(Modes)2.5 E F1 .264
+(The modes used for \214les depend on what functionality you w)127 225 R .264
+(ant and the le)-.1 F -.15(ve)-.25 G 2.764(lo).15 G 2.764(fs)448.482 225 S .264
+(ecurity you)458.466 225 R(require.)102 237 Q F0 2.5(4.7.1. T)102 261 R 2.5(os)
+-.92 G(uid or not to suid?)146.64 261 Q/F2 10/Times-Italic@0 SF(Sendmail)142
+277.2 Q F1 .934(can safely be made setuid to root.)3.434 F .934
+(At the point where it is about to)5.934 F F2 -.2(ex)3.433 G(ec).2 E F1 .933
+(\(2\) a)1.666 F(mailer)117 289.2 Q 2.582(,i)-.4 G 2.582(tc)150.012 289.2 S
+.082(hecks to see if the userid is zero; if so, it resets the userid and group\
+id to a def)159.814 289.2 R .083(ault \(set)-.1 F .577(by the)117 301.2 R F0(u)
+3.077 E F1(and)3.077 E F0(g)3.077 E F1 3.077(options\). \(This)3.077 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 .576(\215ag to the mailer for mailers)3.076 F 1.531
+(that are trusted and must be called as root.\))117 313.2 R(Ho)6.531 E(we)-.25
+E -.15(ve)-.25 G 2.331 -.4(r, t).15 H 1.532
+(his will cause mail processing to be).4 F(accounted \(using)117 325.2 Q F2(sa)
+2.5 E F1(\(8\)\) to root rather than to the user sending the mail.)1.666 E .339
+(If you don')142 341.4 R 2.839(tm)-.18 G(ak)200.887 341.4 Q(e)-.1 E F2
+(sendmail)2.839 E F1 .339(setuid to root, it will still run b)2.839 F .339
+(ut you lose a lot of functional-)-.2 F .007(ity and a lot of pri)117 353.4 R
+-.25(va)-.25 G -.15(cy).25 G 2.507(,s)-.5 G .008(ince you')215.452 353.4 R .008
+(ll ha)-.1 F .308 -.15(ve t)-.2 H 2.508(om).15 G(ak)300.024 353.4 Q 2.508(et)
+-.1 G .008(he queue directory w)319.092 353.4 R .008(orld readable.)-.1 F -1.1
+(Yo)5.008 G 2.508(uc)1.1 G(ould)486.22 353.4 Q .501(also mak)117 365.4 R(e)-.1
+E F2(sendmail)3.001 E F1 .501(setuid to some pseudo-user \(e.g., create a user\
+ called \231sendmail\232 and mak)3.001 F(e)-.1 E F2(sendmail)117 377.4 Q F1
+1.533(setuid to that\) which will \214x the pri)4.033 F -.25(va)-.25 G 1.834
+-.15(cy p).25 H 1.534(roblems b).15 F 1.534(ut not the functionality issues.)
+-.2 F .642(Also, this isn')117 389.4 R 3.142(tag)-.18 G .641
+(uarantee of security: for e)192.448 389.4 R .641
+(xample, root occasionally sends mail, and the dae-)-.15 F
+(mon often runs as root.)117 401.4 Q F0 2.5(4.7.2. Should)102 425.4 R
+(my alias database be writable?)2.5 E F1 .058(At Berk)142 441.6 R(ele)-.1 E
+2.558(yw)-.15 G 2.558(eh)200.186 441.6 S -2.25 -.2(av e)212.184 441.6 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 453.6 R -.2(vo)-.2 G 1.718
+(ids potential security problems with a globally).2 F(writable database.)117
+465.6 Q 1.19(The database that)142 481.8 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
+481.8 Q F2(aliases.dir)3.691 E F1(and)3.691 E F2(aliases.pa)117 493.8 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 493.8 Q
+(ele)-.1 E 2.658(yd)-.15 G .158(atabase prim-)449.692 493.8 R(iti)117 505.8 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 517.8 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 517.8
+R .719(desired changes through to the actual database.)117 529.8 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 541.8 Q(yw)-.15 E(ay)-.1 E(.)-.65 E
+.621(If your DBM \214les are not writable by the w)142 558 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 3.028(\(with the)117 570 R F0 -.5(Au)5.528 G(toReb).5 E
+(uildAliases)-.2 E F1 3.028
+(option\), then you must be careful to reconstruct the alias)5.528 F
+(database each time you change the te)117 582 Q(xt v)-.15 E(ersion:)-.15 E(ne)
+157 598.2 Q -.1(wa)-.25 G(liases).1 E(If this step is ignored or for)117 614.4
+Q(gotten an)-.18 E 2.5(yi)-.15 G(ntended changes will also be ignored or for)
+273.32 614.4 Q(gotten.)-.18 E F0 2.5(4.8. Connection)87 638.4 R(Caching)2.5 E
+F1 .642(When processing the queue,)127 654.6 R F2(sendmail)3.142 E F1 .642
+(will try to k)3.142 F .642(eep the last fe)-.1 F 3.142(wo)-.25 G .642
+(pen connections open to)405.144 654.6 R -.2(avo)102 666.6 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 682.8 R
+.287(If an open connection is found,)5.286 F .92
+(it is probed to see if it is still acti)102 694.8 R 1.22 -.15(ve b)-.25 H 3.42
+(ys).15 G .92(ending a)270.892 694.8 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 706.8 Q EP
+%%Page: 26 21
+%%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 -1 -.8(Tw o)127
+96 T .408(parameters control the connection cache.)3.708 F(The)5.408 E F0
+(ConnectionCacheSize)2.908 E F1(\()2.908 E F0(k)A F1 2.908(\)o)C .408
+(ption de\214nes)452.202 96 R .145
+(the number of simultaneous open connections that will be permitted.)102 108 R
+.145(If it is set to zero, connections)5.145 F .212
+(will be closed as quickly as possible.)102 120 R .212(The def)5.212 F .212
+(ault is one.)-.1 F .213(This should be set as appropriate for your)5.212 F .63
+(system size; it will limit the amount of system resources that)102 132 R/F2 10
+/Times-Italic@0 SF(sendmail)3.129 E F1 .629(will use during queue runs.)3.129 F
+(Ne)102 144 Q -.15(ve)-.25 G 2.5(rs).15 G(et this higher than 4.)132.42 144 Q
+(The)127 160.2 Q F0(ConnectionCacheT)2.74 E(imeout)-.18 E F1(\()2.741 E F0(K)A
+F1 2.741(\)o)C .241(ption speci\214es the maximum time that an)281.692 160.2 R
+2.741(yc)-.15 G .241(ached con-)460.169 160.2 R .9
+(nection will be permitted to idle.)102 172.2 R .899(When the idle time e)5.9 F
+.899(xceeds this v)-.15 F .899(alue the connection is closed.)-.25 F .34
+(This number should be small \(under ten minutes\) to pre)102 184.2 R -.15(ve)
+-.25 G .34(nt you from grabbing too man).15 F 2.84(yr)-.15 G(esources)469.57
+184.2 Q(from other hosts.)102 196.2 Q(The def)5 E(ault is \214v)-.1 E 2.5(em)
+-.15 G(inutes.)257.57 196.2 Q F0 2.5(4.9. Name)87 220.2 R(Ser)2.5 E -.1(ve)-.1
+G 2.5(rA).1 G(ccess)172.33 220.2 Q F1 .104
+(Control of host address lookups is set by the)127 236.4 R F0(hosts)2.604 E F1
+.103(service entry in your service switch \214le.)2.603 F(If)5.103 E .99
+(you are on a system that has b)102 248.4 R .99
+(uilt-in service switch support \(e.g., Ultrix, Solaris, or DEC OSF/1\))-.2 F
+.336(then your system is probably con\214gured properly already)102 260.4 R
+5.335(.O)-.65 G(therwise,)347.885 260.4 Q F2(sendmail)2.835 E F1 .335
+(will consult the \214le)2.835 F F0(/etc/ser)102 272.4 Q(vice.switch)-.1 E F1
+2.5(,w)C(hich should be created.)191.04 272.4 Q F2(Sendmail)5 E F1
+(only uses tw)2.5 E 2.5(oe)-.1 G(ntries:)389.8 272.4 Q F0(hosts)2.5 E F1(and)
+2.5 E F0(aliases)2.5 E F1(.)A(Ho)127 288.6 Q(we)-.25 E -.15(ve)-.25 G .908 -.4
+(r, s).15 H .108(ome systems \(such as SunOS\) will do DNS lookups re).4 F -.05
+(ga)-.15 G .108(rdless of the setting of the).05 F 1.558(service switch entry)
+102 300.6 R 6.558(.I)-.65 G 4.058(np)196.834 300.6 S(articular)210.892 300.6 Q
+4.058(,t)-.4 G 1.558(he system routine)253.15 300.6 R F2 -.1(ge)4.058 G
+(thostbyname).1 E F1 1.558(\(3\) is used to look up host)B .461(names, and man)
+102 312.6 R 2.961(yv)-.15 G .461(endor v)180.293 312.6 R .461
+(ersions try some combination of DNS, NIS, and \214le lookup in /etc/hosts)-.15
+F .537(without consulting a service switch.)102 324.6 R F2(Sendmail)5.537 E F1
+(mak)3.037 E .536(es no attempt to w)-.1 F .536(ork around this problem, and)
+-.1 F .27(the DNS lookup will be done an)102 336.6 R(yw)-.15 E(ay)-.1 E 5.27
+(.I)-.65 G 2.77(fy)264.36 336.6 S .271(ou do not ha)275.46 336.6 R .571 -.15
+(ve a n)-.2 H(ameserv).15 E .271(er con\214gured at all, such as at)-.15 F
+2.855(aU)102 348.6 S .355(UCP-only site,)116.515 348.6 R F2(sendmail)2.855 E F1
+.354
+(will get a \231connection refused\232 message when it tries to connect to the)
+2.855 F .622(name serv)102 360.6 R(er)-.15 E 5.622(.I)-.55 G 3.122(ft)161.964
+360.6 S(he)171.196 360.6 Q F0(hosts)3.122 E F1 .623
+(switch entry has the service \231dns\232 listed some)3.122 F .623
+(where in the list,)-.25 F F2(sendmail)3.123 E F1 .912
+(will interpret this to mean a temporary f)102 372.6 R .912
+(ailure and will queue the mail for later processing; other)-.1 F(-)-.2 E
+(wise, it ignores the name serv)102 384.6 Q(er data.)-.15 E .672
+(The same technique is used to decide whether to do MX lookups.)127 400.8 R
+.673(If you w)5.673 F .673(ant MX support,)-.1 F(you)102 412.8 Q F2(must)2.5 E
+F1(ha)2.5 E .3 -.15(ve \231)-.2 H(dns\232 listed as a service in the).15 E F0
+(hosts)2.5 E F1(switch entry)2.5 E(.)-.65 E(The)127 429 Q F0(Resolv)3.87 E
+(erOptions)-.1 E F1(\()3.87 E F0(I)A F1 3.869(\)o)C 1.369(ption allo)240.719
+429 R 1.369(ws you to tweak name serv)-.25 F 1.369(er options.)-.15 F 1.369
+(The command)6.369 F .892(line tak)102 441 R .892
+(es a series of \215ags as documented in)-.1 F F2 -.37(re)3.392 G(solver).37 E
+F1 .892(\(3\) \(with the leading \231RES_\232 deleted\).)B(Each)5.892 E
+(can be preceded by an optional `+' or `)102 453 Q/F3 10/Symbol SF(-)A F1 2.5
+('. F)B(or e)-.15 E(xample, the line)-.15 E 2.5(OR)142 469.2 S(esolv)158.39
+469.2 Q(erOptions=+AA)-.15 E(ONL)-.55 E(Y)-1 E F3(-)2.5 E F1(DNSRCH)A .862
+(turns on the AA)102 485.4 R(ONL)-.55 E 3.362(Y\()-1 G .862(accept authoritati)
+201.658 485.4 R 1.162 -.15(ve a)-.25 H .861(nswers only\) and turns of).15 F
+3.361(ft)-.25 G .861(he DNSRCH \(search the)402.827 485.4 R 2.039
+(domain path\) options.)102 497.4 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 .503(\215ags on and all others of)102 509.4 R 3.003(f. Y)-.25 F .503
+(ou can also include \231HasW)-1.1 F .503
+(ildcardMX\232 to specify that there is a wild-)-.4 F 1.972
+(card MX record matching your domain; this turns of)102 521.4 R 4.472(fM)-.25 G
+4.473(Xm)344.188 521.4 S 1.973(atching when canonifying names,)363.661 521.4 R
+(which can lead to inappropriate canoni\214cations.)102 533.4 Q -1.11(Ve)127
+549.6 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 549.6 R 2.256(AMES of)-.35 F
+4.756(fw)-.25 G 2.256(hen doing deli)424.898 549.6 R -.15(ve)-.25 G(ry).15 E
+2.06(lookups, b)102 561.6 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 8 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
+573.6 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 573.6 Q(to do automatic name e)102 585.6 Q
+(xtension, don')-.15 E 2.5(tc)-.18 G(all $[ ... $].)261.93 585.6 Q .485
+(The search rules for $[ ... $] are some)127 601.8 R .485(what dif)-.25 F .485
+(ferent than usual.)-.25 F .486(If the name being look)5.485 F .486(ed up)-.1 F
+.11(has at least one dot, it al)102 613.8 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 625.8 R .124
+(ut only for names without a dot, since names with a dot)-.2 F(ha)102 637.8 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
+637.8 S .488(atch the site in Czechoslo)378.578 637.8 R -.25(va)-.15 G(kia).25
+E 1.587(rather than the site in your local Computer Science department.)102
+649.8 R 1.588(It also prefers A and CN)6.587 F(AME)-.35 E .513(records o)102
+661.8 R -.15(ve)-.15 G 3.013(rM).15 G 3.013(Xr)163.816 661.8 S .513
+(ecords \212 that is, if it \214nds an MX record it mak)177.379 661.8 R .512
+(es note of it, b)-.1 F .512(ut k)-.2 F .512(eeps looking.)-.1 F 1.541(This w)
+102 673.8 R(ay)-.1 E 4.041(,i)-.65 G 4.041(fy)149.052 673.8 S 1.541(ou ha)
+161.423 673.8 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 685.8 Q 3.454 -.8(To c)127 702 T 1.853(ompletely turn of).8 F
+4.353(fa)-.25 G 1.853(ll name serv)231.123 702 R 1.853
+(er access on systems without service switch support)-.15 F .578
+(\(such as SunOS\) you will ha)102 714 R .878 -.15(ve t)-.2 H 3.078(or).15 G
+.579(ecompile with \255DN)245.406 714 R .579(AMED_BIND=0 and remo)-.35 F .879
+-.15(ve \255)-.15 H .579(lresolv from).15 F EP
+%%Page: 27 22
+%%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
+(the list of libraries to be searched when linking.)102 96 Q F0 2.5(4.10. Mo)87
+120 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 136.2 R 3.272(sh)-.55 G .772
+(ome directory from a local disk on their w)256.13 136.2 R .772
+(orkstation, so that)-.1 F .575(local access is f)102 148.2 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 148.2 R .216(can e)102 160.2 R -.15(ve)-.25 G
+2.716(nb).15 G 2.716(ed)144.792 160.2 S(eli)156.948 160.2 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 172.2 Q(.)-.55 E
+(The)127 188.4 Q F0 -.25(Fo)2.743 G(rwardP).25 E(ath)-.1 E F1(\()2.743 E F0(J)A
+F1 2.743(\)o)C .243(ption allo)224.859 188.4 R .243
+(ws you to set a path of forw)-.25 F .243(ard \214les.)-.1 F -.15(Fo)5.243 G
+2.743(re).15 G .244(xample, the con-)436.582 188.4 R(\214g \214le line)102
+200.4 Q 2.5(OF)142 216.6 S(orw)157.13 216.6 Q(ardP)-.1 E(ath=/v)-.15 E(ar/forw)
+-.25 E(ard/$u:$z/.forw)-.1 E(ard.$w)-.1 E -.1(wo)102 232.8 S .208
+(uld \214rst look for a \214le with the same name as the user').1 F 2.707(sl)
+-.55 G .207(ogin in /v)343.191 232.8 R(ar/forw)-.25 E .207
+(ard; if that is not found)-.1 F 1.17(\(or is inaccessible\) the \214le `)102
+244.8 R(`.forw)-.74 E(ard.)-.1 E/F2 10/Times-Italic@0 SF(mac)A(hinename)-.15 E
+F1 2.651 -.74('' i)D 3.671(nt).74 G 1.171(he user')337.014 244.8 R 3.671(sh)
+-.55 G 1.171(ome directory is searched.)382.126 244.8 R(A)6.171 E(truly perv)
+102 256.8 Q(erse site could also search by sender by using $r)-.15 E 2.5(,$)-.4
+G(s, or $f.)343.07 256.8 Q .69(If you create a directory such as /v)127 273 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 273 Q(should be set\).)102 285 Q
+(Users should create the \214les mode 644.)5 E F0 2.5(4.11. Fr)87 309 R
+(ee Space)-.18 E F1 1.405(On systems that ha)127 325.2 R 1.705 -.15(ve o)-.2 H
+1.405(ne of the system calls in the).15 F F2(statfs)3.906 E F1 1.406(\(2\) f)B
+1.406(amily \(including)-.1 F F2(statvfs)3.906 E F1(and)3.906 E F2(ustat)102
+337.2 Q F1 .839(\), you can specify a minimum number of free blocks on the que\
+ue \214lesystem using the)B F0(Min-)3.339 E(Fr)102 349.2 Q(eeBlocks)-.18 E F1
+(\()2.553 E F0(b)A F1 2.553(\)o)C 2.553(ption. If)171.916 349.2 R .053
+(there are fe)2.553 F .053
+(wer than the indicated number of blocks free on the \214lesystem)-.25 F 1.355
+(on which the queue is mounted the SMTP serv)102 361.2 R 1.355
+(er will reject mail with the 452 error code.)-.15 F(This)6.354 E(in)102 373.2
+Q(vites the SMTP client to try ag)-.4 E(ain later)-.05 E(.)-.55 E(Be)127 389.4
+Q -.1(wa)-.25 G .746(re of setting this option too high; it can cause rejectio\
+n of email when that mail w).1 F(ould)-.1 E(be processed without dif)102 401.4
+Q(\214culty)-.25 E(.)-.65 E F0 2.5(4.12. Maximum)87 425.4 R(Message Size)2.5 E
+F1 2.078 -.8(To a)127 441.6 T -.2(vo).6 G .478(id o).2 F -.15(ve)-.15 G(r\215o)
+.15 E .478(wing your system with a lar)-.25 F .478(ge message, the)-.18 F F0
+(MaxMessageSize)2.977 E F1 .477(option can be)2.977 F .692
+(set to set an absolute limit on the size of an)102 453.6 R 3.193(yo)-.15 G
+.693(ne message.)294.176 453.6 R .693(This will be adv)5.693 F .693
+(ertised in the ESMTP)-.15 F(dialogue and check)102 465.6 Q
+(ed during message collection.)-.1 E F0 2.5(4.13. Pri)87 489.6 R -.1(va)-.1 G
+(cy Flags).1 E F1(The)127 505.8 Q F0(Pri)2.96 E -.1(va)-.1 G(cyOptions).1 E F1
+(\()2.96 E F0(p)A F1 2.96(\)o)C .46(ption allo)235.12 505.8 R .46
+(ws you to set certain `)-.25 F(`pri)-.74 E -.25(va)-.25 G -.15(cy).25 G 1.94
+-.74('' \215).15 H 2.96(ags. Actually).74 F 2.96(,m)-.65 G(an)478.42 505.8 Q
+2.96(yo)-.15 G(f)500.67 505.8 Q .533(them don')102 517.8 R 3.033(tg)-.18 G
+-2.15 -.25(iv e)153.996 517.8 T .533(you an)3.283 F 3.034(ye)-.15 G .534
+(xtra pri)208.496 517.8 R -.25(va)-.25 G -.15(cy).25 G 3.034(,r)-.5 G .534
+(ather just insisting that client SMTP serv)264.634 517.8 R .534
+(ers use the HELO)-.15 F 2.87
+(command before using certain commands or adding e)102 529.8 R 2.87
+(xtra headers to indicate possible spoof)-.15 F(attempts.)102 541.8 Q .123
+(The option tak)127 558 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
+558 R .424 -.15(ve o)-.25 H 2.624(ro).15 G 2.624(ft)434.058 558 S .124
+(hose \215ags.)442.792 558 R -.15(Fo)5.124 G(r).15 E -.15(ex)102 570 S(ample:)
+.15 E 2.5(OP)142 586.2 S(ri)157.28 586.2 Q -.25(va)-.25 G -.15(cy).25 G
+(Options=needmailhelo, noe).15 E(xpn)-.15 E .928(insists that the HELO or EHLO\
+ command be used before a MAIL command is accepted and dis-)102 602.4 R
+(ables the EXPN command.)102 614.4 Q
+(The \215ags are detailed in section 5.1.6.)127 630.6 Q F0 2.5(4.14. Send)87
+654.6 R(to Me T)2.5 E(oo)-.92 E F1(Normally)127 670.8 Q(,)-.65 E F2(sendmail)
+3.423 E F1 .923(deletes the \(en)3.423 F -.15(ve)-.4 G .923
+(lope\) sender from an).15 F 3.423(yl)-.15 G .924(ist e)375.484 670.8 R 3.424
+(xpansions. F)-.15 F .924(or e)-.15 F .924(xample, if)-.15 F .761(\231matt\232\
+ sends to a list that contains \231matt\232 as one of the members he w)102
+682.8 R(on')-.1 E 3.261(tg)-.18 G .761(et a cop)416.705 682.8 R 3.261(yo)-.1 G
+3.261(ft)462.488 682.8 S .761(he mes-)471.859 682.8 R 2.882(sage. If)102 694.8
+R(the)2.882 E F0<ad6d>2.882 E F1 .383
+(\(me too\) command line \215ag, or if the)2.882 F F0(MeT)2.883 E(oo)-.92 E F1
+(\()2.883 E F0(m)A F1 2.883(\)o)C .383(ption is set in the con\214guration)
+377.915 694.8 R(\214le, this beha)102 706.8 Q(viour is suppressed.)-.2 E
+(Some sites lik)5 E 2.5(et)-.1 G 2.5(or)305.31 706.8 S(un the)316.14 706.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 EP
+%%Page: 28 23
+%%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 2.5(5. THE)72 96 R
+(WHOLE SCOOP ON THE CONFIGURA)2.5 E(TION FILE)-.95 E/F1 10/Times-Roman@0 SF
+(This section describes the con\214guration \214le in detail.)112 112.2 Q .648
+(There is one point that should be made clear immediately: the syntax of the c\
+on\214guration \214le is)112 128.4 R 1.076
+(designed to be reasonably easy to parse, since this is done e)87 140.4 R -.15
+(ve)-.25 G 1.077(ry time).15 F/F2 10/Times-Italic@0 SF(sendmail)3.577 E F1
+1.077(starts up, rather than)3.577 F(easy for a human to read or write.)87
+152.4 Q
+(On the \231future project\232 list is a con\214guration-\214le compiler)5 E(.)
+-.55 E .243(The con\214guration \214le is or)112 168.6 R -.05(ga)-.18 G .243
+(nized as a series of lines, each of which be).05 F .243
+(gins with a single charac-)-.15 F .102
+(ter de\214ning the semantics for the rest of the line.)87 180.6 R .102
+(Lines be)5.102 F .102(ginning with a space or a tab are continuation)-.15 F
+1.323(lines \(although the semantics are not well de\214ned in man)87 192.6 R
+3.823(yp)-.15 G 3.822(laces\). Blank)340.61 192.6 R 1.322(lines and lines be)
+3.822 F(ginning)-.15 E(with a sharp symbol \(`#'\) are comments.)87 204.6 Q F0
+2.5(5.1. R)87 228.6 R(and S \212 Rewriting Rules)2.5 E F1 .465
+(The core of address parsing are the re)127 244.8 R .466(writing rules.)-.25 F
+.466(These are an ordered production system.)5.466 F F2(Sendmail)102 256.8 Q F1
+.19(scans through the set of re)2.69 F .19
+(writing rules looking for a match on the left hand side \(LHS\) of)-.25 F
+(the rule.)102 268.8 Q(When a rule matches, the address is replaced by the rig\
+ht hand side \(RHS\) of the rule.)5 E .921(There are se)127 285 R -.15(ve)-.25
+G .921(ral sets of re).15 F .921(writing rules.)-.25 F .921(Some of the re)
+5.921 F .922(writing sets are used internally and)-.25 F .36(must ha)102 297 R
+.66 -.15(ve s)-.2 H .36(peci\214c semantics.).15 F .359(Other re)5.359 F .359
+(writing sets do not ha)-.25 F .659 -.15(ve s)-.2 H .359
+(peci\214cally assigned semantics, and).15 F
+(may be referenced by the mailer de\214nitions or by other re)102 309 Q
+(writing sets.)-.25 E(The syntax of these tw)127 325.2 Q 2.5(oc)-.1 G
+(ommands are:)229.38 325.2 Q F0(S)142 341.4 Q F2(n)A F1 .248
+(Sets the current ruleset being collected to)102 357.6 R F2(n)2.748 E F1 5.248
+(.I)C 2.748(fy)287.284 357.6 S .248(ou be)298.362 357.6 R .249
+(gin a ruleset more than once it deletes the old)-.15 F(de\214nition.)102 369.6
+Q F0(R)142 385.8 Q F2(lhs rhs comments)A F1 1.185(The \214elds must be separat\
+ed by at least one tab character; there may be embedded spaces in the)102 402 R
+2.594(\214elds. The)102 414 R F2(lhs)2.594 E F1 .095
+(is a pattern that is applied to the input.)2.594 F .095
+(If it matches, the input is re)5.095 F .095(written to the)-.25 F F2(rhs)2.595
+E F1(.)A(The)102 426 Q F2(comments)2.5 E F1(are ignored.)2.5 E .755(Macro e)127
+442.2 R .755(xpansions of the form)-.15 F F0($)3.255 E F2(x)A F1 .755
+(are performed when the con\214guration \214le is read.)3.255 F(Expan-)5.755 E
+.283(sions of the form)102 454.2 R F0($&)2.783 E F2(x)A F1 .284
+(are performed at run time using a some)2.783 F .284
+(what less general algorithm.)-.25 F .284(This for)5.284 F
+(is intended only for referencing internally de\214ned macros such as)102 466.2
+Q F0($h)2.5 E F1(that are changed at runtime.)2.5 E F0 2.5(5.1.1. The)102 490.2
+R(left hand side)2.5 E F1 2.771(The left hand side of re)142 506.4 R 2.771
+(writing rules contains a pattern.)-.25 F 2.77(Normal w)7.771 F 2.77
+(ords are simply)-.1 F(matched directly)117 518.4 Q 5(.M)-.65 G
+(etasyntax is introduced using a dollar sign.)199.67 518.4 Q
+(The metasymbols are:)5 E F0($*)157 534.6 Q F1(Match zero or more tok)177.14
+534.6 Q(ens)-.1 E F0($+)157 546.6 Q F1(Match one or more tok)9.44 E(ens)-.1 E
+F0<24ad>157 558.6 Q F1(Match e)9.44 E(xactly one tok)-.15 E(en)-.1 E F0($=)157
+570.6 Q F2(x)A F1(Match an)5 E 2.5(yp)-.15 G(hrase in class)226.98 570.6 Q F2
+(x)2.5 E F0($~)157 582.6 Q F2(x)A F1(Match an)7.37 E 2.5(yw)-.15 G
+(ord not in class)229.1 582.6 Q F2(x)2.5 E F1 .131(If an)117 598.8 R 2.631(yo)
+-.15 G 2.631(ft)148.212 598.8 S .131(hese match, the)156.953 598.8 R 2.631(ya)
+-.15 G .132(re assigned to the symbol)231.066 598.8 R F0($)2.632 E F2(n)A F1
+.132(for replacement on the right hand side,)2.632 F(where)117 610.8 Q F2(n)2.5
+E F1(is the inde)2.5 E 2.5(xi)-.15 G 2.5(nt)202.67 610.8 S(he LHS.)212.95 610.8
+Q -.15(Fo)5 G 2.5(re).15 G(xample, if the LHS:)271.81 610.8 Q($\255:$+)157 627
+Q(is applied to the input:)117 643.2 Q(UCB)157 659.4 Q(ARP)-.35 E(A:eric)-.92 E
+(the rule will match, and the v)117 675.6 Q(alues passed to the RHS will be:)
+-.25 E 7.5($1 UCB)157 691.8 R(ARP)-.35 E(A)-.92 E 7.5($2 eric)157 703.8 R EP
+%%Page: 29 24
+%%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(Additionally)142 96 Q 2.705(,t)
+-.65 G .204(he LHS can include)199.895 96 R F0($@)2.704 E F1 .204
+(to match zero tok)2.704 F 2.704(ens. This)-.1 F(is)2.704 E/F2 10
+/Times-Italic@0 SF(not)2.704 E F1 .204(bound to a)2.704 F F0($)2.704 E F2(n)A
+F1(on)2.704 E(the RHS, and is normally only used when it stands alone in order\
+ to match the null input.)117 108 Q F0 2.5(5.1.2. The)102 132 R
+(right hand side)2.5 E F1 .648(When the left hand side of a re)142 148.2 R .649
+(writing rule matches, the input is deleted and replaced by)-.25 F 1.037
+(the right hand side.)117 160.2 R -.8(To)6.037 G -.1(ke).8 G 1.036
+(ns are copied directly from the RHS unless the).1 F 3.536(yb)-.15 G -.15(eg)
+430.772 160.2 S 1.036(in with a dollar).15 F 2.5(sign. Metasymbols)117 172.2 R
+(are:)2.5 E F0($)157 188.4 Q F2(n)A F1(Substitute inde\214nite tok)207.55 188.4
+Q(en)-.1 E F2(n)2.5 E F1(from LHS)2.5 E F0($[)157 200.4 Q F2(name)A F0($])A F1
+(Canonicalize)207.55 200.4 Q F2(name)2.5 E F0($\()157 212.4 Q F2(map k)A -.3
+(ey)-.1 G F0($@)2.8 E F2(ar)A(guments)-.37 E F0($:)2.5 E F2(default)A F0($\))
+2.5 E F1(Generalized k)207.55 224.4 Q -.15(ey)-.1 G(ed mapping function).15 E
+F0($>)157 236.4 Q F2(n)A F1(\231Call\232 ruleset)207.55 236.4 Q F2(n)2.5 E F0
+($#)157 248.4 Q F2(mailer)A F1(Resolv)207.55 248.4 Q 2.5(et)-.15 G(o)244.9
+248.4 Q F2(mailer)2.5 E F0($@)157 260.4 Q F2(host)A F1(Specify)207.55 260.4 Q
+F2(host)2.5 E F0($:)157 272.4 Q F2(user)A F1(Specify)207.55 272.4 Q F2(user)2.5
+E F1(The)142 292.8 Q F0($)3.136 E F2(n)A F1 .637
+(syntax substitutes the corresponding v)3.136 F .637(alue from a)-.25 F F0($+)
+3.137 E F1(,)A F0<24ad>3.137 E F1(,)A F0($*)3.137 E F1(,)A F0($=)3.137 E F1
+3.137(,o)C(r)448.489 292.8 Q F0($~)3.137 E F1 .637(match on)3.137 F(the LHS.)
+117 304.8 Q(It may be used an)5 E(ywhere.)-.15 E 2.706(Ah)142 321 S .206
+(ost name enclosed between)156.926 321 R F0($[)2.706 E F1(and)2.706 E F0($])
+2.706 E F1 .206(is look)2.706 F .205
+(ed up in the host database\(s\) and replaced)-.1 F 1.683
+(by the canonical name)117 335 R/F3 7/Times-Roman@0 SF(13)211.749 331 Q F1
+6.683(.F)218.749 335 S 1.683(or e)233.342 335 R 1.683
+(xample, \231$[ftp$]\232 might become \231ftp.CS.Berk)-.15 F(ele)-.1 E -.65(y.)
+-.15 G 1.683(EDU\232 and).65 F 2.707(\231$[[128.32.130.2]$]\232 w)117 347 R
+2.707(ould become \231v)-.1 F(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G
+(EDU.).65 E<9a>-.7 E F2(Sendmail)7.707 E F1 2.706(recognizes it')5.206 F(s)-.55
+E(numeric IP address without calling the name serv)117 359 Q
+(er and replaces it with it')-.15 E 2.5(sc)-.55 G(anonical name.)424.3 359 Q
+(The)142 375.2 Q F0($\()3.003 E F1(...)3.003 E F0($\))5.503 E F1 .503
+(syntax is a more general form of lookup; it uses a named map instead of an)
+3.003 F .81(implicit map.)117 387.2 R .81(If no lookup is found, the indicated)
+5.81 F F2(default)3.309 E F1 .809(is inserted; if no def)3.309 F .809
+(ault is speci\214ed)-.1 F .775(and no lookup matches, the v)117 399.2 R .776
+(alue is left unchanged.)-.25 F(The)5.776 E F2(ar)3.276 E(guments)-.37 E F1
+.776(are passed to the map for)3.276 F(possible use.)117 411.2 Q(The)142 427.4
+Q F0($>)2.62 E F2(n)A F1 .119(syntax causes the remainder of the line to be su\
+bstituted as usual and then passed)2.62 F .586(as the ar)117 439.4 R .586
+(gument to ruleset)-.18 F F2(n)3.086 E F1 5.586(.T)C .586(he \214nal v)244.206
+439.4 R .586(alue of ruleset)-.25 F F2(n)3.087 E F1 .587
+(then becomes the substitution for this)3.087 F 3.075(rule. The)117 451.4 R F0
+($>)3.075 E F1 .575(syntax can only be used at the be)3.075 F .575
+(ginning of the right hand side; it can be only be)-.15 F(preceded by)117 463.4
+Q F0($@)2.5 E F1(or)2.5 E F0($:)2.5 E F1(.)A(The)142 479.6 Q F0($#)2.507 E F1
+.007(syntax should)2.507 F F2(only)2.507 E F1 .008
+(be used in ruleset zero or a subroutine of ruleset zero.)2.507 F .008
+(It causes)5.008 F -.25(eva)117 491.6 S .685
+(luation of the ruleset to terminate immediately).25 F 3.184(,a)-.65 G .684
+(nd signals to)329.502 491.6 R F2(sendmail)3.184 E F1 .684
+(that the address has)3.184 F(completely resolv)117 503.6 Q 2.5(ed. The)-.15 F
+(complete syntax is:)2.5 E F0($#)157 519.8 Q F2(mailer)A F0($@)2.5 E F2(host)A
+F0($:)2.5 E F2(user)A F1 1.394(This speci\214es the {mailer)117 536 R 3.894(,h)
+-.4 G 1.394(ost, user} 3-tuple necessary to direct the mailer)234.466 536 R
+6.394(.I)-.55 G 3.894(ft)444.548 536 S 1.394(he mailer is)454.552 536 R .774
+(local the host part may be omitted)117 550 R F3(14)257.744 546 Q F1 5.774(.T)
+264.744 550 S(he)279.128 550 Q F2(mailer)3.274 E F1 .775(must be a single w)
+3.274 F .775(ord, b)-.1 F .775(ut the)-.2 F F2(host)3.275 E F1(and)3.275 E F2
+(user)3.275 E F1 .253(may be multi-part.)117 562 R .253(If the)5.253 F F2
+(mailer)2.753 E F1 .253(is the b)2.753 F .253(uiltin IPC mailer)-.2 F 2.753(,t)
+-.4 G(he)354.733 562 Q F2(host)2.753 E F1 .253(may be a colon-separated list)
+2.753 F .5(of hosts that are searched in order for the \214rst w)117 574 R .5
+(orking address \(e)-.1 F .5(xactly lik)-.15 F 3(eM)-.1 G 3(Xr)437.47 574 S 3
+(ecords\). The)451.02 574 R F2(user)117 586 Q F1 .036(is later re)2.536 F .036
+(written by the mailer)-.25 F .036(-speci\214c en)-.2 F -.15(ve)-.4 G .036
+(lope re).15 F .036(writing set and assigned to the)-.25 F F0($u)2.536 E F1
+(macro.)2.536 E .492(As a special case, if the v)117 598 R .492(alue to)-.25 F
+F0($#)2.992 E F1 .492(is \231local\232 and the \214rst character of the)2.992 F
+F0($:)2.992 E F1 -.25(va)2.992 G .492(lue is \231@\232, the).25 F .017
+(\231@\232 is stripped of)117 610 R .017(f, and a \215ag is set in the address\
+ descriptor that causes sendmail to not do rule-)-.25 F(set 5 processing.)117
+622 Q(Normally)142 638.2 Q 3.251(,ar)-.65 G .751
+(ule that matches is retried, that is, the rule loops until it f)196.452 638.2
+R 3.252(ails. A)-.1 F .752(RHS may)3.252 F 1.086(also be preceded by a)117
+650.2 R F0($@)3.586 E F1 1.085(or a)3.585 F F0($:)3.585 E F1 1.085
+(to change this beha)3.585 F(vior)-.2 E 6.085(.A)-.55 G F0($@)375.685 650.2 Q
+F1 1.085(pre\214x causes the ruleset to)3.585 F .32 LW 76 659.8 72 659.8 DL 80
+659.8 76 659.8 DL 84 659.8 80 659.8 DL 88 659.8 84 659.8 DL 92 659.8 88 659.8
+DL 96 659.8 92 659.8 DL 100 659.8 96 659.8 DL 104 659.8 100 659.8 DL 108 659.8
+104 659.8 DL 112 659.8 108 659.8 DL 116 659.8 112 659.8 DL 120 659.8 116 659.8
+DL 124 659.8 120 659.8 DL 128 659.8 124 659.8 DL 132 659.8 128 659.8 DL 136
+659.8 132 659.8 DL 140 659.8 136 659.8 DL 144 659.8 140 659.8 DL 148 659.8 144
+659.8 DL 152 659.8 148 659.8 DL 156 659.8 152 659.8 DL 160 659.8 156 659.8 DL
+164 659.8 160 659.8 DL 168 659.8 164 659.8 DL 172 659.8 168 659.8 DL 176 659.8
+172 659.8 DL 180 659.8 176 659.8 DL 184 659.8 180 659.8 DL 188 659.8 184 659.8
+DL 192 659.8 188 659.8 DL 196 659.8 192 659.8 DL 200 659.8 196 659.8 DL 204
+659.8 200 659.8 DL 208 659.8 204 659.8 DL 212 659.8 208 659.8 DL 216 659.8 212
+659.8 DL/F4 5/Times-Roman@0 SF(13)93.6 670.2 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(14)93.6 683.8 Q F5
+-.88(Yo)3.2 K 2.726(um).88 G .726(ay w)120.446 687 R .726
+(ant to use it for special \231per user\232 e)-.08 F 2.726(xtensions. F)-.12 F
+.726(or e)-.12 F .725
+(xample, in the address \231jgm+foo@CMU.EDU\232; the \231+foo\232)-.12 F(part \
+is not part of the user name, and is passed to the local mailer for local use.)
+72 696.6 Q EP
+%%Page: 30 25
+%%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 1.46
+(return with the remainder of the RHS as the v)117 96 R 3.96(alue. A)-.25 F F0
+($:)3.96 E F1 1.46(pre\214x causes the rule to terminate)3.96 F(immediately)117
+108 Q 3.756(,b)-.65 G 1.256(ut the ruleset to continue; this can be used to a)
+177.406 108 R -.2(vo)-.2 G 1.256(id continued application of a).2 F 2.5
+(rule. The)117 120 R(pre\214x is stripped before continuing.)2.5 E(The)142
+136.2 Q F0($@)2.5 E F1(and)2.5 E F0($:)2.5 E F1(pre\214x)2.5 E
+(es may precede a)-.15 E F0($>)2.5 E F1(spec; for e)2.5 E(xample:)-.15 E 20.19
+(R$+ $:)157 152.4 R($>7 $1)2.5 E 1.256(matches an)117 168.6 R 1.256
+(ything, passes that to ruleset se)-.15 F -.15(ve)-.25 G 1.256
+(n, and continues; the).15 F F0($:)3.756 E F1 1.256(is necessary to a)3.756 F
+-.2(vo)-.2 G 1.256(id an).2 F(in\214nite loop.)117 180.6 Q 1.205(Substitution \
+occurs in the order described, that is, parameters from the LHS are substi-)142
+196.8 R .219(tuted, hostnames are canonicalized, \231subroutines\232 are calle\
+d, and \214nally)117 208.8 R F0($#)2.719 E F1(,)A F0($@)2.719 E F1 2.72(,a)C
+(nd)448.64 208.8 Q F0($:)2.72 E F1 .22(are pro-)2.72 F(cessed.)117 220.8 Q F0
+2.5(5.1.3. Semantics)102 244.8 R(of r)2.5 E(ewriting rule sets)-.18 E F1 1.523
+(There are \214v)142 261 R 4.023(er)-.15 G -.25(ew)207.779 261 S 1.523
+(riting sets that ha).25 F 1.823 -.15(ve s)-.2 H 1.523(peci\214c semantics.).15
+F -.15(Fo)6.523 G 1.523(ur of these are related as).15 F
+(depicted by \214gure 1.)117 273 Q 1.029
+(Ruleset three should turn the address into \231canonical form.)142 289.2 R
+6.029<9a54>-.7 G 1.03(his form should ha)401.351 289.2 R 1.33 -.15(ve t)-.2 H
+(he).15 E(basic syntax:)117 301.2 Q(local-part@host-domain-spec)157 317.4 Q
+(Ruleset three is applied by)117 333.6 Q/F2 10/Times-Italic@0 SF(sendmail)2.5 E
+F1(before doing an)2.5 E(ything with an)-.15 E 2.5(ya)-.15 G(ddress.)396.39
+333.6 Q .302(If no \231@\232 sign is speci\214ed, then the host-domain-spec)142
+349.8 R F2(may)2.801 E F1 .301(be appended \(box \231D\232 in Fig-)2.801 F .577
+(ure 1\) from the sender address \(if the)117 361.8 R F0(C)3.077 E F1 .577
+(\215ag is set in the mailer de\214nition corresponding to the)3.077 F F2
+(sending)117 373.8 Q F1(mailer\).)2.5 E 1.021(Ruleset zero is applied after ru\
+leset three to addresses that are going to actually specify)142 390 R 3.663
+(recipients. It)117 402 R 1.163(must resolv)3.663 F 3.663(et)-.15 G 3.664(oa)
+232.602 402 S F2({mailer)A 3.664(,h)-1.11 G 1.164(ost, user})289.534 402 R F1
+3.664(triple. The)3.664 F F2(mailer)3.664 E F1 1.164(must be de\214ned in the)
+3.664 F .752(mailer de\214nitions from the con\214guration \214le.)117 414 R
+(The)5.751 E F2(host)3.251 E F1 .751(is de\214ned into the)3.251 F F0($h)3.251
+E F1 .751(macro for use in)3.251 F(the ar)117 426 Q(gv e)-.18 E
+(xpansion of the speci\214ed mailer)-.15 E(.)-.55 E .452(Rulesets one and tw)
+142 442.2 R 2.952(oa)-.1 G .452
+(re applied to all sender and recipient addresses respecti)235.918 442.2 R -.15
+(ve)-.25 G(ly).15 E 5.453(.T)-.65 G(he)489.71 442.2 Q(y)-.15 E
+(are applied before an)117 454.2 Q 2.5(ys)-.15 G
+(peci\214cation in the mailer de\214nition.)212.37 454.2 Q(The)5 E 2.5(ym)-.15
+G(ust ne)391.1 454.2 Q -.15(ve)-.25 G 2.5(rr).15 G(esolv)432.91 454.2 Q(e.)-.15
+E .4 LW 77 483.6 72 483.6 DL 79 483.6 74 483.6 DL 84 483.6 79 483.6 DL 89 483.6
+84 483.6 DL 94 483.6 89 483.6 DL 99 483.6 94 483.6 DL 104 483.6 99 483.6 DL 109
+483.6 104 483.6 DL 114 483.6 109 483.6 DL 119 483.6 114 483.6 DL 124 483.6 119
+483.6 DL 129 483.6 124 483.6 DL 134 483.6 129 483.6 DL 139 483.6 134 483.6 DL
+144 483.6 139 483.6 DL 149 483.6 144 483.6 DL 154 483.6 149 483.6 DL 159 483.6
+154 483.6 DL 164 483.6 159 483.6 DL 169 483.6 164 483.6 DL 174 483.6 169 483.6
+DL 179 483.6 174 483.6 DL 184 483.6 179 483.6 DL 189 483.6 184 483.6 DL 194
+483.6 189 483.6 DL 199 483.6 194 483.6 DL 204 483.6 199 483.6 DL 209 483.6 204
+483.6 DL 214 483.6 209 483.6 DL 219 483.6 214 483.6 DL 224 483.6 219 483.6 DL
+229 483.6 224 483.6 DL 234 483.6 229 483.6 DL 239 483.6 234 483.6 DL 244 483.6
+239 483.6 DL 249 483.6 244 483.6 DL 254 483.6 249 483.6 DL 259 483.6 254 483.6
+DL 264 483.6 259 483.6 DL 269 483.6 264 483.6 DL 274 483.6 269 483.6 DL 279
+483.6 274 483.6 DL 284 483.6 279 483.6 DL 289 483.6 284 483.6 DL 294 483.6 289
+483.6 DL 299 483.6 294 483.6 DL 304 483.6 299 483.6 DL 309 483.6 304 483.6 DL
+314 483.6 309 483.6 DL 319 483.6 314 483.6 DL 324 483.6 319 483.6 DL 329 483.6
+324 483.6 DL 334 483.6 329 483.6 DL 339 483.6 334 483.6 DL 344 483.6 339 483.6
+DL 349 483.6 344 483.6 DL 354 483.6 349 483.6 DL 359 483.6 354 483.6 DL 364
+483.6 359 483.6 DL 369 483.6 364 483.6 DL 374 483.6 369 483.6 DL 379 483.6 374
+483.6 DL 384 483.6 379 483.6 DL 389 483.6 384 483.6 DL 394 483.6 389 483.6 DL
+399 483.6 394 483.6 DL 404 483.6 399 483.6 DL 409 483.6 404 483.6 DL 414 483.6
+409 483.6 DL 419 483.6 414 483.6 DL 424 483.6 419 483.6 DL 429 483.6 424 483.6
+DL 434 483.6 429 483.6 DL 439 483.6 434 483.6 DL 444 483.6 439 483.6 DL 449
+483.6 444 483.6 DL 454 483.6 449 483.6 DL 459 483.6 454 483.6 DL 464 483.6 459
+483.6 DL 469 483.6 464 483.6 DL 474 483.6 469 483.6 DL 479 483.6 474 483.6 DL
+484 483.6 479 483.6 DL 489 483.6 484 483.6 DL 494 483.6 489 483.6 DL 499 483.6
+494 483.6 DL 504 483.6 499 483.6 DL(addr)91.915 578 Q 133.2 576 111.6 576 DL
+133.2 576 126 577.8 DL 133.2 576 126 574.2 DL(3)141.5 578 Q 133.2 565.2 133.2
+586.8 DL 154.8 565.2 133.2 565.2 DL 154.8 586.8 154.8 565.2 DL 133.2 586.8
+154.8 586.8 DL 176.4 576 154.8 576 DL 176.4 576 169.2 577.8 DL 176.4 576 169.2
+574.2 DL(D)183.59 578 Q 176.4 565.2 176.4 586.8 DL 198 565.2 176.4 565.2 DL 198
+586.8 198 565.2 DL 176.4 586.8 198 586.8 DL 219.6 576 198 576 DL 277.2 558
+255.6 558 DL 277.2 558 270 559.8 DL 277.2 558 270 556.2 DL(1)285.5 560 Q 277.2
+547.2 277.2 568.8 DL 298.8 547.2 277.2 547.2 DL 298.8 568.8 298.8 547.2 DL
+277.2 568.8 298.8 568.8 DL 320.4 558 298.8 558 DL 320.4 558 313.2 559.8 DL
+320.4 558 313.2 556.2 DL(S)328.42 560 Q 320.4 547.2 320.4 568.8 DL 342 547.2
+320.4 547.2 DL 342 568.8 342 547.2 DL 320.4 568.8 342 568.8 DL 363.6 558 342
+558 DL 277.2 594 255.6 594 DL 277.2 594 270 595.8 DL 277.2 594 270 592.2 DL(2)
+285.5 596 Q 277.2 583.2 277.2 604.8 DL 298.8 583.2 277.2 583.2 DL 298.8 604.8
+298.8 583.2 DL 277.2 604.8 298.8 604.8 DL 320.4 594 298.8 594 DL 320.4 594
+313.2 595.8 DL 320.4 594 313.2 592.2 DL(R)327.865 596 Q 320.4 583.2 320.4 604.8
+DL 342 583.2 320.4 583.2 DL 342 604.8 342 583.2 DL 320.4 604.8 342 604.8 DL
+363.6 594 342 594 DL 421.2 576 399.6 576 DL 421.2 576 414 577.8 DL 421.2 576
+414 574.2 DL(4)429.5 578 Q 421.2 565.2 421.2 586.8 DL 442.8 565.2 421.2 565.2
+DL 442.8 586.8 442.8 565.2 DL 421.2 586.8 442.8 586.8 DL 464.4 576 442.8 576 DL
+464.4 576 457.2 577.8 DL 464.4 576 457.2 574.2 DL(msg)466.865 578 Q 255.6 558
+219.6 576 DL 255.6 594 219.6 576 DL 399.6 576 363.6 558 DL 399.6 576 363.6 594
+DL 208.8 522 187.2 522 DL 208.8 522 201.6 523.8 DL 208.8 522 201.6 520.2 DL(0)
+217.1 524 Q 208.8 511.2 208.8 532.8 DL 230.4 511.2 208.8 511.2 DL 230.4 532.8
+230.4 511.2 DL 208.8 532.8 230.4 532.8 DL 252 522 230.4 522 DL 252 522 244.8
+523.8 DL 252 522 244.8 520.2 DL(resolv)265.69 524 Q(ed address)-.15 E 187.2 522
+162 576 DL(Figure 1 \212 Re)216.045 624 Q(writing set semantics)-.25 E 2.5
+(D\212s)209.35 636 S(ender domain addition)235.46 636 Q 2.5(S\212m)209.35 648 S
+(ailer)237.69 648 Q(-speci\214c sender re)-.2 E(writing)-.25 E 2.5(R\212m)
+209.35 660 S(ailer)238.8 660 Q(-speci\214c recipient re)-.2 E(writing)-.25 E 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 EP
+%%Page: 31 26
+%%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.266
+(Ruleset four is applied to all addresses in the message.)142 96 R 1.265
+(It is typically used to translate)6.265 F(internal to e)117 108 Q
+(xternal form.)-.15 E F0 2.5(5.1.4. IPC)102 132 R(mailers)2.5 E F1 1.332
+(Some special processing occurs if the ruleset zero resolv)142 148.2 R 1.333
+(es to an IPC mailer \(that is, a)-.15 F 1.179
+(mailer that has \231[IPC]\232 listed as the P)117 160.2 R 1.179(ath in the)
+-.15 F F0(M)3.679 E F1 1.179(con\214guration line.)3.679 F 1.178
+(The host name passed)6.178 F .168(after \231$@\232 has MX e)117 172.2 R .168
+(xpansion performed; this looks the name up in DNS to \214nd alternate deli)
+-.15 F(v-)-.25 E(ery sites.)117 184.2 Q(The host name can also be pro)142 200.4
+Q(vided as a dotted quad in square brack)-.15 E(ets; for e)-.1 E(xample:)-.15 E
+([128.32.149.78])157 216.6 Q(This causes direct con)117 232.8 Q -.15(ve)-.4 G
+(rsion of the numeric v).15 E(alue to a TCP/IP host address.)-.25 E .214(The h\
+ost name passed in after the \231$@\232 may also be a colon-separated list of \
+hosts.)142 249 R(Each)5.213 E .484(is separately MX e)117 261 R .484
+(xpanded and the results are concatenated to mak)-.15 F 2.985(e\()-.1 G .485
+(essentially\) one long MX)401.165 261 R 3.465(list. The)117 273 R .964
+(intent here is to create \231f)3.465 F(ak)-.1 E .964
+(e\232 MX records that are not published in DNS for pri)-.1 F -.25(va)-.25 G
+(te).25 E(internal netw)117 285 Q(orks.)-.1 E
+(As a \214nal special case, the host name can be passed in as a te)142 301.2 Q
+(xt string in square brack)-.15 E(ets:)-.1 E([ucb)157 317.4 Q -.25(va)-.15 G
+(x.berk).25 E(ele)-.1 E -.65(y.)-.15 G(edu]).65 E .312(This form a)117 333.6 R
+-.2(vo)-.2 G .312(ids the MX mapping.).2 F F0(N.B.:)5.312 E/F2 10
+/Times-Italic@0 SF .313(This is intended only for situations wher)2.812 F 2.813
+(ey)-.37 G .313(ou have a)464.494 333.6 R .338(network \214r)117 345.6 R -.15
+(ew)-.37 G .337(all or other host that will do special pr).15 F .337
+(ocessing for all your mail, so that your MX)-.45 F -.37(re)117 357.6 S(cor).37
+E 3.958(dp)-.37 G 1.458(oints to a gate)151.878 357.6 R 1.458(way mac)-.15 F
+1.458(hine; this mac)-.15 F 1.459(hine could then do dir)-.15 F 1.459
+(ect delivery to mac)-.37 F(hines)-.15 E .09(within your local domain.)117
+369.6 R .09(Use of this featur)5.09 F 2.59(ed)-.37 G(ir)306.8 369.6 Q .09
+(ectly violates RFC 1123 section 5.3.5: it should)-.37 F(not be used lightly)
+117 381.6 Q(.)-.55 E F0 2.5(5.2. D)87 405.6 R 2.5<8a44>2.5 G(e\214ne Macr)
+136.44 405.6 Q(o)-.18 E F1 .081
+(Macros are named with a single character or with a w)127 421.8 R .082
+(ord in {braces}.)-.1 F .082(Single character names)5.082 F .45
+(may be selected from the entire ASCII set, b)102 433.8 R .45(ut user)-.2 F .45
+(-de\214ned macros should be selected from the set)-.2 F .446
+(of upper case letters only)102 445.8 R 5.446(.L)-.65 G -.25(ow)217.72 445.8 S
+.446(er case letters and special symbols are used internally).25 F 5.446(.L)
+-.65 G .446(ong names)460.504 445.8 R(be)102 457.8 Q .913(ginning with a lo)
+-.15 F .913(wer case letter or a punctuation character are reserv)-.25 F .912
+(ed for use by sendmail, so)-.15 F(user)102 469.8 Q
+(-de\214ned long macro names should be)-.2 E(gin with an upper case letter)-.15
+E(.)-.55 E(The syntax for macro de\214nitions is:)127 486 Q F0(D)142 502.2 Q F2
+1.666(xv)C(al)-1.666 E F1(where)102 518.4 Q F2(x)3.068 E F1 .568
+(is the name of the macro \(which may be a single character or a w)3.068 F .569
+(ord in braces\) and)-.1 F F2(val)3.069 E F1(is)3.069 E .479(the v)102 530.4 R
+.479(alue it should ha)-.25 F -.15(ve)-.2 G 5.479(.T).15 G .478
+(here should be no spaces gi)212.395 530.4 R -.15(ve)-.25 G 2.978(nt).15 G .478
+(hat do not actually belong in the macro)344.284 530.4 R -.25(va)102 542.4 S
+(lue.).25 E .494(Macros are interpolated using the construct)127 558.6 R F0($)
+2.994 E F2(x)A F1 2.994(,w)C(here)327.638 558.6 Q F2(x)2.994 E F1 .494
+(is the name of the macro to be inter)2.994 F(-)-.2 E 2.933(polated. This)102
+570.6 R .433(interpolation is done when the con\214guration \214le is read, e)
+2.933 F .432(xcept in)-.15 F F0(M)2.932 E F1 2.932(lines. The)2.932 F(spe-)
+2.932 E(cial construct)102 582.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:)127 598.8 Q($?x te)142 615 Q
+(xt1 $| te)-.15 E(xt2 $.)-.15 E 1.127(This interpolates)102 631.2 R F2(te)3.627
+E(xt1)-.2 E F1 1.127(if the macro)3.627 F F0($x)3.627 E F1 1.128(is set, and)
+3.628 F F2(te)3.628 E(xt2)-.2 E F1 3.628(otherwise. The)3.628 F 1.128
+(\231else\232 \()3.628 F F0($|)A F1 3.628(\)c)C 1.128(lause may be)449.534
+631.2 R(omitted.)102 643.2 Q(Lo)127 659.4 Q .58
+(wer case macro names are reserv)-.25 F .58(ed to ha)-.15 F .88 -.15(ve s)-.2 H
+.58(pecial semantics, used to pass information in).15 F 1.56(or out of)102
+671.4 R F2(sendmail)4.06 E F1 4.06(,a)C 1.561(nd special characters are reserv)
+190.73 671.4 R 1.561(ed to pro)-.15 F 1.561(vide conditionals, etc.)-.15 F
+1.561(Upper case)6.561 F(names \(that is,)102 683.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)232.82 683.4 Q
+(ed for con\214guration \214le authors.)-.15 E 1.303(The follo)127 699.6 R
+1.303(wing macros are de\214ned and/or used internally by)-.25 F F2(sendmail)
+3.802 E F1 1.302(for interpolation into)3.802 F EP
+%%Page: 32 27
+%%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(ar)102 98 Q(gv')
+-.18 E 2.792(sf)-.55 G .292(or mailers or for other conte)132.382 98 R 2.793
+(xts. The)-.15 F .293(ones mark)2.793 F .293
+(ed \207 are information passed into sendmail)-.1 F/F2 7/Times-Roman@0 SF(15)
+494.5 94 Q F1(,)501.5 98 Q .036(the ones mark)102 110 R .036
+(ed \210 are information passed both in and out of sendmail, and the unmark)-.1
+F .035(ed macros are)-.1 F(passed out of sendmail b)102 122 Q
+(ut are not otherwise used internally)-.2 E 5(.T)-.65 G(hese macros are:)354.45
+122 Q 13.06($a The)102 138.2 R(origination date in RFC 822 format.)2.5 E
+(This is e)5 E(xtracted from the Date: line.)-.15 E 12.5($b The)102 154.4 R
+(current date in RFC 822 format.)2.5 E 13.06($c The)102 170.6 R .002
+(hop count.)2.502 F .002(This is a count of the number of Recei)5.002 F -.15
+(ve)-.25 G .003(d: lines plus the v).15 F .003(alue of the)-.25 F F0<ad68>2.503
+E F1(com-)2.503 E(mand line \215ag.)127 182.6 Q 12.5($d The)102 198.8 R
+(current date in UNIX \(ctime\) format.)2.5 E 8.06($e\207 \(Obsolete;)102 215 R
+1.814(use SmtpGreetingMessage option instead.\))4.314 F 1.814
+(The SMTP entry message.)6.814 F 1.814(This is)6.814 F 2.008
+(printed out when SMTP starts up.)127 227 R 2.008(The \214rst w)7.008 F 2.008
+(ord must be the)-.1 F F0($j)4.508 E F1 2.009(macro as speci\214ed by)4.508 F
+2.732(RFC821. Def)127 239 R .232(aults to \231$j Sendmail $v ready at $b\232.)
+-.1 F .231(Commonly rede\214ned to include the con-)5.231 F(\214guration v)127
+251 Q(ersion number)-.15 E 2.5(,e)-.4 G
+(.g., \231$j Sendmail $v/$Z ready at $b\232)239.77 251 Q 14.17($f The)102 267.2
+R(en)2.5 E -.15(ve)-.4 G(lope sender \(from\) address.).15 E 12.5($g The)102
+283.4 R .017(sender address relati)2.517 F .317 -.15(ve t)-.25 H 2.517(ot).15 G
+.017(he recipient.)251.375 283.4 R -.15(Fo)5.017 G 2.517(re).15 G .018
+(xample, if)326.386 283.4 R F0($f)2.518 E F1 .018(is \231foo\232,)2.518 F F0
+($g)2.518 E F1 .018(will be \231host!foo\232,)2.518 F
+(\231foo@host.domain\232, or whate)127 295.4 Q -.15(ve)-.25 G 2.5(ri).15 G 2.5
+(sa)264.95 295.4 S(ppropriate for the recei)275.78 295.4 Q(ving mailer)-.25 E
+(.)-.55 E 12.5($h The)102 311.6 R(recipient host.)2.5 E
+(This is set in ruleset 0 from the $# \214eld of a parsed address.)5 E 14.72
+($i The)102 327.8 R(queue id, e.g., \231HAA12345\232.)2.5 E 9.72($j\210 The)102
+344 R(\231of)2.747 E .247(\214cial\232 domain name for this site.)-.25 F .247
+(This is fully quali\214ed if the full quali\214cation can be)5.247 F 3.093
+(found. It)127 356 R/F3 10/Times-Italic@0 SF(must)3.093 E F1 .594(be rede\214n\
+ed to be the fully quali\214ed domain name if your system is not con-)3.093 F
+(\214gured so that information can \214nd it automatically)127 368 Q(.)-.65 E
+12.5($k The)102 384.2 R(UUCP node name \(from the uname system call\).)2.5 E
+9.72($l\207 \(Obsolete;)102 400.4 R 1.282(use UnixFromLine option instead.\))
+3.782 F 1.282(The format of the UNIX from line.)6.282 F(Unless)6.281 E 1.409
+(you ha)127 412.4 R 1.709 -.15(ve c)-.2 H 1.409
+(hanged the UNIX mailbox format, you should not change the def).15 F 1.41
+(ault, which is)-.1 F(\231From $g)127 424.4 Q($d\232.)5 E 9.72($m The)102 440.6
+R .719(domain part of the)3.219 F F3 -.1(ge)3.219 G(thostname).1 E F1 .718
+(return v)3.219 F 3.218(alue. Under)-.25 F .718(normal circumstances,)3.218 F
+F0($j)3.218 E F1 .718(is equi)3.218 F(v-)-.25 E(alent to)127 452.6 Q F0($w)2.5
+E(.$m)-.7 E F1(.)A 7.5($n\207 The)102 468.8 R
+(name of the daemon \(for error messages\).)2.5 E(Def)5 E
+(aults to \231MAILER-D)-.1 E(AEMON\232.)-.4 E 7.5($o\207 \(Obsolete:)102 485 R
+.65(use OperatorChars option instead.\))3.15 F .651
+(The set of \231operators\232 in addresses.)5.651 F 3.151(Al)5.651 G .651
+(ist of)483.069 485 R .582(characters which will be considered tok)127 497 R
+.581(ens and which will separate tok)-.1 F .581(ens when doing pars-)-.1 F
+3.277(ing. F)127 509 R .777(or e)-.15 F .777(xample, if \231@\232 were in the)
+-.15 F F0($o)3.278 E F1 .778(macro, then the input \231a@b\232 w)3.278 F .778
+(ould be scanned as)-.1 F .628(three tok)127 521 R .628(ens: \231a,)-.1 F 3.128
+<9a99>-.7 G(@,)204.724 521 Q 3.128<9a61>-.7 G .628(nd \231b)227.742 521 R 4.527
+-.7(.\232 D)-.4 H(ef).7 E .627
+(aults to \231.:@[]\232, which is the minimum set necessary to)-.1 F .856(do R\
+FC 822 parsing; a richer set of operators is \231.:%@!/[]\232, which adds supp\
+ort for UUCP)127 533 R(,)-1.11 E(the %-hack, and X.400 addresses.)127 545 Q
+12.5($p Sendmail')102 561.2 R 2.5(sp)-.55 G(rocess id.)178.95 561.2 Q 7.5
+($q\207 Def)102 577.4 R .404(ault format of sender address.)-.1 F(The)5.404 E
+F0($q)2.903 E F1 .403(macro speci\214es ho)2.903 F 2.903(wa)-.25 G 2.903(na)
+388.955 577.4 S .403(ddress should appear in a)401.298 577.4 R 1.18
+(message when it is def)127 589.4 R 3.681(aulted. Def)-.1 F 1.181
+(aults to \231<$g>\232.)-.1 F 1.181(It is commonly rede\214ned to be \231$?x$x)
+6.181 F(<$g>$|$g$.)127 601.4 Q 5<9a6f>-.7 G 2.5<7299>186.52 601.4 S
+($g$?x \($x\)$.)196.79 601.4 Q(\232, corresponding to the follo)-.7 E(wing tw)
+-.25 E 2.5(of)-.1 G(ormats:)403.21 601.4 Q(Eric Allman <eric@CS.Berk)167 617.6
+Q(ele)-.1 E -.65(y.)-.15 G(EDU>).65 E(eric@CS.Berk)167 629.6 Q(ele)-.1 E -.65
+(y.)-.15 G(EDU \(Eric Allman\)).65 E F3(Sendmail)127 645.8 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 14.17($r Protocol)102 662
+R .977(used to recei)3.477 F 1.277 -.15(ve t)-.25 H .976(he message.).15 F .976
+(Set from the)5.976 F F0<ad70>3.476 E F1 .976
+(command line \215ag or by the SMTP)3.476 F(serv)127 674 Q(er code.)-.15 E .32
+LW 76 688.4 72 688.4 DL 80 688.4 76 688.4 DL 84 688.4 80 688.4 DL 88 688.4 84
+688.4 DL 92 688.4 88 688.4 DL 96 688.4 92 688.4 DL 100 688.4 96 688.4 DL 104
+688.4 100 688.4 DL 108 688.4 104 688.4 DL 112 688.4 108 688.4 DL 116 688.4 112
+688.4 DL 120 688.4 116 688.4 DL 124 688.4 120 688.4 DL 128 688.4 124 688.4 DL
+132 688.4 128 688.4 DL 136 688.4 132 688.4 DL 140 688.4 136 688.4 DL 144 688.4
+140 688.4 DL 148 688.4 144 688.4 DL 152 688.4 148 688.4 DL 156 688.4 152 688.4
+DL 160 688.4 156 688.4 DL 164 688.4 160 688.4 DL 168 688.4 164 688.4 DL 172
+688.4 168 688.4 DL 176 688.4 172 688.4 DL 180 688.4 176 688.4 DL 184 688.4 180
+688.4 DL 188 688.4 184 688.4 DL 192 688.4 188 688.4 DL 196 688.4 192 688.4 DL
+200 688.4 196 688.4 DL 204 688.4 200 688.4 DL 208 688.4 204 688.4 DL 212 688.4
+208 688.4 DL 216 688.4 212 688.4 DL/F4 5/Times-Roman@0 SF(15)93.6 698.8 Q/F5 8
+/Times-Roman@0 SF(As of v)3.2 I(ersion 8.6, all of these macros ha)-.12 E .24
+-.12(ve r)-.16 H(easonable def).12 E 2(aults. Pre)-.08 F(vious v)-.2 E
+(ersions required that the)-.12 E 2(yb)-.12 G 2(ed)424.728 702 S(e\214ned.)
+434.28 702 Q EP
+%%Page: 33 28
+%%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 13.61($s Sender')102 96 R 2.5(sh)
+-.55 G(ost name.)168.94 96 Q(Set from the)5 E F0<ad70>2.5 E F1
+(command line \215ag or by the SMTP serv)2.5 E(er code.)-.15 E 14.72($t A)102
+112.2 R(numeric representation of the current time.)2.5 E 12.5($u The)102 128.4
+R(recipient user)2.5 E(.)-.55 E 12.5($v The)102 144.6 R -.15(ve)2.5 G
+(rsion number of the).15 E/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1(binary)2.5
+E(.)-.65 E 5.28($w\210 The)102 160.8 R(hostname of this site.)2.5 E
+(This is the root name of this host \(b)5 E(ut see belo)-.2 E 2.5(wf)-.25 G
+(or ca)432.64 160.8 Q -.15(ve)-.2 G(ats\).).15 E 12.5($x The)102 177 R
+(full name of the sender)2.5 E(.)-.55 E 13.06($z The)102 193.2 R
+(home directory of the recipient.)2.5 E 12.5($_ The)102 209.4 R -.25(va)2.5 G
+(lidated sender address.).25 E .749
+(There are three types of dates that can be used.)127 225.6 R(The)5.749 E F0
+($a)3.249 E F1(and)3.249 E F0($b)3.249 E F1 .749(macros are in RFC 822 for)
+3.249 F(-)-.2 E(mat;)102 237.6 Q F0($a)3.214 E F1 .714(is the time as e)3.214 F
+.713(xtracted from the \231Date:\232 line of the message \(if there w)-.15 F
+.713(as one\), and)-.1 F F0($b)3.213 E F1(is)3.213 E .056
+(the current date and time \(used for postmarks\).)102 249.6 R .057
+(If no \231Date:\232 line is found in the incoming message,)5.056 F F0($a)102
+261.6 Q F1 .305(is set to the current time also.)2.805 F(The)5.305 E F0($d)
+2.805 E F1 .304(macro is equi)2.805 F -.25(va)-.25 G .304(lent to the).25 F F0
+($b)2.804 E F1 .304(macro in UNIX \(ctime\) for)2.804 F(-)-.2 E(mat.)102 273.6
+Q .238(The macros)127 289.8 R F0($w)2.738 E F1(,)A F0($j)2.738 E F1 2.738(,a)C
+(nd)212.372 289.8 Q F0($m)2.738 E F1 .238
+(are set to the identity of this host.)2.738 F F2(Sendmail)5.239 E F1 .239
+(tries to \214nd the fully)2.739 F .335
+(quali\214ed name of the host if at all possible; it does this by calling)102
+301.8 R F2 -.1(ge)2.834 G(thostname).1 E F1 .334(\(2\) to get the current)B
+.457(hostname and then passing that to)102 313.8 R F2 -.1(ge)2.957 G
+(thostbyname).1 E F1 .457(\(3\) which is supposed to return the canonical v)B
+(er)-.15 E(-)-.2 E .279(sion of that host name.)102 327.8 R/F3 7/Times-Roman@0
+SF(16)193.946 323.8 Q F1 .279(Assuming this is successful,)203.725 327.8 R F0
+($j)2.778 E F1 .278(is set to the fully quali\214ed name and)2.778 F F0($m)
+2.778 E F1(is)2.778 E .706(set to the domain part of the name \(e)102 339.8 R
+-.15(ve)-.25 G .706(rything after the \214rst dot\).).15 F(The)5.706 E F0($w)
+3.206 E F1 .706(macro is set to the \214rst)3.206 F -.1(wo)102 351.8 S .359
+(rd \(e).1 F -.15(ve)-.25 G .358(rything before the \214rst dot\) if you ha).15
+F .658 -.15(ve a l)-.2 H -2.15 -.25(ev e).15 H 2.858(l5o).25 G 2.858(rh)345
+351.8 S .358(igher con\214guration \214le; otherwise, it)356.188 351.8 R .404
+(is set to the same v)102 363.8 R .405(alue as)-.25 F F0($j)2.905 E F1 5.405
+(.I)C 2.905(ft)229.965 363.8 S .405
+(he canoni\214cation is not successful, it is imperati)238.98 363.8 R .705 -.15
+(ve t)-.25 H .405(hat the con\214g).15 F(\214le set)102 377.8 Q F0($j)2.5 E F1
+(to the fully quali\214ed domain name)2.5 E F3(17)279.77 373.8 Q F1(.)286.77
+377.8 Q(The)127 394 Q F0($f)2.833 E F1 .333(macro is the id of the sender as o\
+riginally determined; when mailing to a speci\214c host)2.833 F(the)102 406 Q
+F0($g)3.224 E F1 .724(macro is set to the address of the sender)3.224 F F2 -.37
+(re)3.225 G .725(lative to the r).37 F(ecipient.)-.37 E F1 -.15(Fo)5.725 G
+3.225(re).15 G .725(xample, if I send to)423.61 406 R
+(\231bollard@matisse.CS.Berk)102 418 Q(ele)-.1 E -.65(y.)-.15 G .425
+(EDU\232 from the machine \231v).65 F(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)
+-.15 G .424(EDU\232 the).65 F F0($f)2.924 E F1(macro)2.924 E
+(will be \231eric\232 and the)102 430 Q 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)127 446.2 Q F0($x)2.562 E F1 .062
+(macro is set to the full name of the sender)2.562 F 5.062(.T)-.55 G .062
+(his can be determined in se)338.824 446.2 R -.15(ve)-.25 G .063(ral w).15 F
+2.563(ays. It)-.1 F .63(can be passed as \215ag to)102 458.2 R F2(sendmail)3.13
+E F1 5.629(.I)C 3.129(tc)249.439 458.2 S .629(an be de\214ned in the)259.788
+458.2 R/F4 9/Times-Roman@0 SF -.315(NA)3.129 G(ME).315 E F1(en)3.129 E .629
+(vironment v)-.4 F 3.129(ariable. The)-.25 F(third)3.129 E .948
+(choice is the v)102 470.2 R .948
+(alue of the \231Full-Name:\232 line in the header if it e)-.25 F .949
+(xists, and the fourth choice is the)-.15 F .526
+(comment \214eld of a \231From:\232 line.)102 482.2 R .526(If all of these f)
+5.526 F .526(ail, and if the message is being originated locally)-.1 F(,)-.65 E
+(the full name is look)102 494.2 Q(ed up in the)-.1 E F2(/etc/passwd)2.5 E F1
+(\214le.)2.5 E 1.32(When sending, the)127 510.4 R F0($h)3.82 E F1(,)A F0($u)
+3.82 E F1 3.82(,a)C(nd)246.37 510.4 Q F0($z)3.82 E F1 1.321
+(macros get set to the host, user)3.82 F 3.821(,a)-.4 G 1.321
+(nd home directory \(if)414.777 510.4 R .517(local\) of the recipient.)102
+522.4 R .517(The \214rst tw)5.517 F 3.016(oa)-.1 G .516(re set from the)256.878
+522.4 R F0($@)3.016 E F1(and)3.016 E F0($:)3.016 E F1 .516(part of the re)3.016
+F .516(writing rules, respec-)-.25 F(ti)102 534.4 Q -.15(ve)-.25 G(ly).15 E(.)
+-.65 E(The)127 550.6 Q F0($p)3.806 E F1(and)3.806 E F0($t)3.806 E F1 1.306(mac\
+ros are used to create unique strings \(e.g., for the \231Message-Id:\232 \214\
+eld\).)3.806 F(The)102 562.6 Q F0($i)3.252 E F1 .751(macro is set to the queue\
+ id on this host; if put into the timestamp line it can be e)3.252 F(xtremely)
+-.15 E .164(useful for tracking messages.)102 574.6 R(The)5.164 E F0($v)2.664 E
+F1 .164(macro is set to be the v)2.664 F .165(ersion number of)-.15 F F2
+(sendmail)2.665 E F1 2.665(;t)C .165(his is nor)463.87 574.6 R(-)-.2 E
+(mally put in timestamps and has been pro)102 586.6 Q -.15(ve)-.15 G 2.5(ne).15
+G(xtremely useful for deb)289.31 586.6 Q(ugging.)-.2 E(The)127 602.8 Q F0($c)
+3.548 E F1 1.048(\214eld is set to the \231hop count,)3.548 F 3.548<9a69>-.7 G
+1.048(.e., the number of times this message has been pro-)290.162 602.8 R 2.856
+(cessed. This)102 614.8 R .356(can be determined by the)2.856 F F0<ad68>2.856 E
+F1 .357(\215ag on the command line or by counting the timestamps)2.856 F
+(in the message.)102 626.8 Q(The)127 643 Q F0($r)2.833 E F1(and)2.833 E F0($s)
+2.833 E F1 .333(\214elds are set to the protocol used to communicate with)2.833
+F F2(sendmail)2.833 E F1 .333(and the send-)2.833 F .194(ing hostname.)102 655
+R(The)5.194 E 2.694(yc)-.15 G .194(an be set together using the)191.032 655 R
+F0<ad70>2.694 E F1 .194(command line \215ag or separately using the)2.694 F F0
+<ad4d>2.695 E F1(or)102 667 Q F0(\255oM)2.5 E F1(\215ags.)2.5 E .32 LW 76 676.6
+72 676.6 DL 80 676.6 76 676.6 DL 84 676.6 80 676.6 DL 88 676.6 84 676.6 DL 92
+676.6 88 676.6 DL 96 676.6 92 676.6 DL 100 676.6 96 676.6 DL 104 676.6 100
+676.6 DL 108 676.6 104 676.6 DL 112 676.6 108 676.6 DL 116 676.6 112 676.6 DL
+120 676.6 116 676.6 DL 124 676.6 120 676.6 DL 128 676.6 124 676.6 DL 132 676.6
+128 676.6 DL 136 676.6 132 676.6 DL 140 676.6 136 676.6 DL 144 676.6 140 676.6
+DL 148 676.6 144 676.6 DL 152 676.6 148 676.6 DL 156 676.6 152 676.6 DL 160
+676.6 156 676.6 DL 164 676.6 160 676.6 DL 168 676.6 164 676.6 DL 172 676.6 168
+676.6 DL 176 676.6 172 676.6 DL 180 676.6 176 676.6 DL 184 676.6 180 676.6 DL
+188 676.6 184 676.6 DL 192 676.6 188 676.6 DL 196 676.6 192 676.6 DL 200 676.6
+196 676.6 DL 204 676.6 200 676.6 DL 208 676.6 204 676.6 DL 212 676.6 208 676.6
+DL 216 676.6 212 676.6 DL/F5 5/Times-Roman@0 SF(16)93.6 687 Q/F6 8
+/Times-Roman@0 SF -.12(Fo)3.2 K 2(re).12 G(xample, on some systems)115.024
+690.2 Q/F7 8/Times-Italic@0 SF -.08(ge)2 G(thostname).08 E F6
+(might return \231foo\232 which w)2 E(ould be mapped to \231foo.bar)-.08 E
+(.com\232 by)-.44 E F7 -.08(ge)2 G(thostbyname).08 E F6(.)A F5(17)93.6 700.6 Q
+F6(Older v)3.2 I(ersions of sendmail didn')-.12 E 2(tp)-.144 G(re-de\214ne)
+211.88 703.8 Q/F8 8/Times-Bold@0 SF($j)2 E F6
+(at all, so up until 8.6, con\214g \214les)2 E F7(always)2 E F6
+(had to de\214ne)2 E F8($j)2 E F6(.)A EP
+%%Page: 34 29
+%%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(The)127 96 Q F0
+($_)2.967 E F1 .467(is set to a v)2.967 F .467(alidated sender host name.)-.25
+F .466(If the sender is running an RFC 1413 compli-)5.467 F .384
+(ant IDENT serv)102 108 R .384(er and the recei)-.15 F -.15(ve)-.25 G 2.884(rh)
+.15 G .384(as the IDENT protocol turned on, it will include the user name)
+249.254 108 R(on that host.)102 120 Q F0 2.5(5.3. C)87 144 R
+(and F \212 De\214ne Classes)2.5 E F1 .66
+(Classes of phrases may be de\214ned to match on the left hand side of re)127
+160.2 R .659(writing rules, where a)-.25 F .192(\231phrase\232 is a sequence o\
+f characters that do not contain space characters.)102 172.2 R -.15(Fo)5.192 G
+2.692(re).15 G .192(xample a class of all)421.582 172.2 R 1.428(local names fo\
+r this site might be created so that attempts to send to oneself can be elimin\
+ated.)102 184.2 R .041(These can either be de\214ned directly in the con\214gu\
+ration \214le or read in from another \214le.)102 196.2 R .041(Classes are)
+5.041 F .649(named as a single letter or a w)102 208.2 R .649(ord in {braces}.)
+-.1 F .649(Class names be)5.649 F .649(ginning with lo)-.15 F .648
+(wer case letters and)-.25 F .638(special characters are reserv)102 220.2 R
+.638(ed for system use.)-.15 F .639
+(Classes de\214ned in con\214g \214les may be gi)5.639 F -.15(ve)-.25 G 3.139
+(nn).15 G(ames)483.45 220.2 Q 1.05
+(from the set of upper case letters for short names or be)102 232.2 R 1.05
+(ginning with an upper case letter for long)-.15 F(names.)102 244.2 Q
+(The syntax is:)127 260.4 Q F0(C)142 276.6 Q/F2 10/Times-Italic@0 SF 1.666(cp)C
+(hr)-1.666 E(ase1 phr)-.15 E(ase2...)-.15 E F0(F)142 288.6 Q F2 1.666<638c>C
+(le)-1.666 E F1 .661(The \214rst form de\214nes the class)102 304.8 R F2(c)
+3.161 E F1 .661(to match an)3.161 F 3.161(yo)-.15 G 3.161(ft)300.1 304.8 S .661
+(he named w)309.371 304.8 R 3.161(ords. It)-.1 F .661
+(is permissible to split them)3.161 F(among multiple lines; for e)102 316.8 Q
+(xample, the tw)-.15 E 2.5(of)-.1 G(orms:)280.07 316.8 Q(CHmonet ucbmonet)142
+333 Q(and)102 349.2 Q(CHmonet)142 365.4 Q(CHucbmonet)142 377.4 Q(are equi)102
+393.6 Q -.25(va)-.25 G 2.5(lent. The).25 F -.74(``)2.5 G(F').74 E 2.5('f)-.74 G
+(orm reads the elements of the class)206.65 393.6 Q F2(c)2.5 E F1
+(from the named)2.5 E F2(\214le)2.5 E F1(.)A 1.339
+(Elements of classes can be accessed in rules using)127 409.8 R F0($=)3.839 E
+F1(or)3.839 E F0($~)3.839 E F1 6.339(.T)C(he)392.048 409.8 Q F0($~)3.839 E F1
+1.338(\(match entries not in)3.839 F(class\) only matches a single w)102 421.8
+Q(ord; multi-w)-.1 E(ord entries in the class are ignored in this conte)-.1 E
+(xt.)-.15 E 1.098(The class)127 438 R F0($=w)3.598 E F1 1.098
+(is set to be the set of all names this host is kno)3.598 F 1.098(wn by)-.25 F
+6.098(.T)-.65 G 1.098(his can be used to)428.506 438 R(match local hostnames.)
+102 450 Q(The class)127 466.2 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.)297.69 466.2 Q(The class)
+127 482.4 Q F0($=m)2.5 E F1
+(is set to the set of domains by which this host is kno)2.5 E
+(wn, initially just)-.25 E F0($m)2.5 E F1(.)A .239(The class)127 498.6 R F0
+($=t)2.739 E F1 .239(is set to the set of trusted users by the)2.739 F F0(T)
+2.739 E F1 .239(con\214guration line.)2.739 F .239(If you w)5.239 F .239
+(ant to read)-.1 F(trusted users from a \214le use)102 510.6 Q F0(Ft)2.5 E F2
+(/\214le/name)A F1(.)A .635(The class)127 526.8 R F0($=n)3.135 E F1 .635
+(can be set to the set of MIME body types that can ne)3.135 F -.15(ve)-.25 G
+3.136(rb).15 G 3.136(ee)426.306 526.8 S .636(ight to se)438.322 526.8 R -.15
+(ve)-.25 G 3.136(nb).15 G(it)498.44 526.8 Q 2.76(encoded. It)102 538.8 R(def)
+2.76 E .26(aults to \231multipart/signed\232.)-.1 F .26
+(Message types \231message/*\232 and \231multipart/*\232 are ne)5.26 F -.15(ve)
+-.25 G(r).15 E .942(encoded directly)102 550.8 R 5.942(.M)-.65 G .943
+(ultipart messages are al)185.994 550.8 R -.1(wa)-.1 G .943(ys handled recursi)
+.1 F -.15(ve)-.25 G(ly).15 E 5.943(.T)-.65 G .943(he handling of message/*)
+399.241 550.8 R .658(messages are controlled by class)102 562.8 R F0($=s)3.158
+E F1 5.658(.T)C .657(he class)266.618 562.8 R F0($=e)3.157 E F1 .657
+(contains the Content-T)3.157 F(ransfer)-.35 E .657(-Encodings that)-.2 F .007
+(can be 8)102 574.8 R/F3 10/Symbol SF<ae>A F1 2.507(7b)C .007(it encoded.)
+157.711 574.8 R .007
+(It is prede\214ned to contain \2317bit\232, \2318bit\232, and \231binary\232.)
+5.007 F .007(The class)5.007 F F0($=s)2.507 E F1(con-)2.508 E 1.52
+(tains the set of subtypes of message that can be treated recursi)102 586.8 R
+-.15(ve)-.25 G(ly).15 E 6.52(.B)-.65 G 4.02(yd)398.58 586.8 S(ef)412.6 586.8 Q
+1.52(ault it contains only)-.1 F 3.213(\231rfc822\232. Other)102 598.8 R .713
+(\231message/*\232 types cannot be 8)3.213 F F3<ae>A F1 3.214(7b)C .714
+(it encoded.)319.862 598.8 R .714(If a message containing eight bit)5.714 F
+1.714(data is sent to a se)102 610.8 R -.15(ve)-.25 G 4.214(nb).15 G 1.714
+(it host, and that message cannot be encoded into se)206.314 610.8 R -.15(ve)
+-.25 G 4.213(nb).15 G 1.713(its, it will be)448.851 610.8 R
+(stripped to 7 bits.)102 622.8 Q F2(Sendmail)127 639 Q F1 .182
+(can be compiled to allo)2.682 F 2.682(wa)-.25 G F2(scanf)A F1 .182
+(\(3\) string on the)B F0(F)2.682 E F1 2.683(line. This)2.683 F .183
+(lets you do simplistic)2.683 F .555(parsing of te)102 651 R .555(xt \214les.)
+-.15 F -.15(Fo)5.555 G 3.055(re).15 G .554
+(xample, to read all the user names in your system)209.595 651 R F2
+(/etc/passwd)3.054 E F1 .554(\214le into a)3.054 F(class, use)102 663 Q
+(FL/etc/passwd %[^:])142 679.2 Q(which reads e)102 695.4 Q -.15(ve)-.25 G
+(ry line up to the \214rst colon.).15 E EP
+%%Page: 35 30
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-35)452.9 60 Q 2.5(5.4. M)87 96 R 2.5<8a44>2.5 G(e\214ne Mailer)138.66
+96 Q/F1 10/Times-Roman@0 SF(Programs and interf)127 112.2 Q
+(aces to mailers are de\214ned in this line.)-.1 E(The format is:)5 E F0(M)142
+128.4 Q/F2 10/Times-Italic@0 SF(name)A F1 2.5(,{)C F2(\214eld)182.9 128.4 Q F1
+(=)A F2(value)A F1(}*)1.666 E(where)102 144.6 Q F2(name)4.244 E F1 1.744(is th\
+e name of the mailer \(used internally only\) and the \231\214eld=name\232 pai\
+rs de\214ne)4.244 F(attrib)102 156.6 Q(utes of the mailer)-.2 E 5(.F)-.55 G
+(ields are:)205.13 156.6 Q -.15(Pa)142 172.8 S 51.87(th The).15 F
+(pathname of the mailer)2.5 E 47.83(Flags Special)142 184.8 R
+(\215ags for this mailer)2.5 E 41.73(Sender Re)142 196.8 R
+(writing set\(s\) for sender addresses)-.25 E 31.17(Recipient Re)142 208.8 R
+(writing set\(s\) for recipient addresses)-.25 E(Ar)142 220.8 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)142 232.8 R(end-of-line string for this mailer)2.5 E 35.62
+(Maxsize The)142 244.8 R(maximum message length to this mailer)2.5 E 32.27
+(Linelimit The)142 256.8 R(maximum line length in the message body)2.5 E 31.18
+(Directory The)142 268.8 R -.1(wo)2.5 G(rking directory for the mailer).1 E
+42.84(Userid The)142 280.8 R(def)2.5 E(ault user and group id to run as)-.1 E
+50.62(Nice The)142 292.8 R(nice\(2\) increment for the mailer)2.5 E 38.95
+(Charset The)142 304.8 R(def)2.5 E(ault character set for 8-bit characters)-.1
+E -.8(Ty)142 316.8 S 49.75(pe The).8 F
+(MTS type information \(used for error messages\))2.5 E
+(Only the \214rst character of the \214eld name is check)102 333 Q(ed.)-.1 E
+.397(The follo)127 349.2 R .396
+(wing \215ags may be set in the mailer description.)-.25 F(An)5.396 E 2.896(yo)
+-.15 G .396(ther \215ags may be used freely)386.77 349.2 R .075
+(to conditionally assign headers to messages destined for particular mailers.)
+102 361.2 R .075(Flags mark)5.075 F .075(ed with \207 are)-.1 F 1.193
+(not interpreted by the)102 373.2 R F2(sendmail)3.693 E F1 1.193
+(binary; these are the con)3.693 F -.15(ve)-.4 G 1.192
+(ntionally used to correlate to the \215ags).15 F .737(portion of the)102 385.2
+R F0(H)3.237 E F1 3.237(line. Flags)3.237 F(mark)3.237 E .737
+(ed with \210 apply to the mailers for the sender address rather than)-.1 F
+(the usual recipient mailers.)102 397.2 Q 15.56(aR)102 413.4 S .987(un Extende\
+d SMTP \(ESMTP\) protocol \(de\214ned in RFCs 1651, 1652, and 1653\).)128.67
+413.4 R .986(This \215ag)5.987 F(def)122 425.4 Q
+(aults on if the SMTP greeting message includes the w)-.1 E(ord \231ESMTP\232.)
+-.1 E 12.78(AL)102 441.6 S .762
+(ook up the user part of the address in the alias database.)128.11 441.6 R .763
+(Normally this is only set for local)5.762 F(mailers.)122 453.6 Q 15(bF)102
+469.8 S .456(orce a blank line on the end of a message.)127.41 469.8 R .456
+(This is intended to w)5.456 F .456(ork around some stupid v)-.1 F(er)-.15 E(-)
+-.2 E .361(sions of /bin/mail that require a blank line, b)122 481.8 R .362
+(ut do not pro)-.2 F .362(vide it themselv)-.15 F 2.862(es. It)-.15 F -.1(wo)
+2.862 G .362(uld not nor).1 F(-)-.2 E(mally be used on netw)122 493.8 Q
+(ork mail.)-.1 E 15.56(cD)102 510 S 2.663(on)129.22 510 S .163
+(ot include comments in addresses.)141.883 510 R .163
+(This should only be used if you ha)5.163 F .463 -.15(ve t)-.2 H 2.663(ow).15 G
+.163(ork around a)453.135 510 R 1.846
+(remote mailer that gets confused by comments.)122 522 R 1.846
+(This strips addresses of the form \231Phrase)6.846 F
+(<address>\232 or \231address \(Comment\)\232 do)122 534 Q
+(wn to just \231address\232.)-.25 E 5.83(C\210 If)102 550.2 R .214(mail is)
+2.714 F F2 -.37(re)2.714 G(ceived).37 E F1 .213
+(from a mailer with this \215ag set, an)2.713 F 2.713(ya)-.15 G .213
+(ddresses in the header that do not ha)348.169 550.2 R -.15(ve)-.2 G .97
+(an at sign \(\231@\232\) after being re)122 562.2 R .97
+(written by ruleset three will ha)-.25 F 1.27 -.15(ve t)-.2 H .97
+(he \231@domain\232 clause from).15 F(the sender en)122 574.2 Q -.15(ve)-.4 G
+(lope address tack).15 E(ed on.)-.1 E(This allo)5 E
+(ws mail with headers of the form:)-.25 E(From: usera@hosta)162 590.4 Q -.8(To)
+162 602.4 S 2.5(:u).8 G(serb@hostb, userc)182.59 602.4 Q(to be re)122 618.6 Q
+(written as:)-.25 E(From: usera@hosta)162 634.8 Q -.8(To)162 646.8 S 2.5(:u).8
+G(serb@hostb, userc@hosta)182.59 646.8 Q(automatically)122 663 Q 5(.H)-.65 G
+-.25(ow)190.51 663 S -2.15 -.25(ev e).25 H .8 -.4(r, i).25 H 2.5(td).4 G(oesn')
+236.95 663 Q 2.5(tr)-.18 G(eally w)267.04 663 Q(ork reliably)-.1 E(.)-.65 E
+5.28(D\207 This)102 679.2 R(mailer w)2.5 E(ants a \231Date:\232 header line.)
+-.1 E 15.56(eT)102 695.4 S .174(his mailer is e)128.11 695.4 R(xpensi)-.15 E
+.474 -.15(ve t)-.25 H 2.674(oc).15 G .173(onnect to, so try to a)237.03 695.4 R
+-.2(vo)-.2 G .173(id connecting normally; an).2 F 2.673(yn)-.15 G .173
+(ecessary con-)449.687 695.4 R(nection will occur during a queue run.)122 707.4
+Q EP
+%%Page: 36 31
+%%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 13.89(EE)102 96
+S(scape lines be)128.11 96 Q
+(ginning with \231From\232 in the message with a `>' sign.)-.15 E 16.67(fT)102
+112.2 S .19(he mailer w)128.11 112.2 R .19(ants a)-.1 F F0<ad66>2.69 E/F2 10
+/Times-Italic@0 SF(fr)2.69 E(om)-.45 E F1 .19(\215ag, b)2.69 F .19
+(ut only if this is a netw)-.2 F .19(ork forw)-.1 F .19
+(ard operation \(i.e., the mailer)-.1 F(will gi)122 124.2 Q .3 -.15(ve a)-.25 H
+2.5(ne).15 G(rror if the e)175.76 124.2 Q -.15(xe)-.15 G
+(cuting user does not ha).15 E .3 -.15(ve s)-.2 H(pecial permissions\).).15 E
+6.94(F\207 This)102 140.4 R(mailer w)2.5 E(ants a \231From:\232 header line.)
+-.1 E 15(gN)102 156.6 S(ormally)129.22 156.6 Q(,)-.65 E F2(sendmail)4.893 E F1
+2.393(sends internally generated email \(e.g., error messages\) using the null)
+4.893 F 1.327(return address as required by RFC 1123.)122 168.6 R(Ho)6.327 E
+(we)-.25 E -.15(ve)-.25 G 2.127 -.4(r, s).15 H 1.327(ome mailers don').4 F
+3.827(ta)-.18 G 1.328(ccept a null return)427.537 168.6 R 3.311(address. If)122
+180.6 R(necessary)3.311 E 3.311(,y)-.65 G .811(ou can set the)219.303 180.6 R
+F0(g)3.311 E F1 .811(\215ag to pre)3.311 F -.15(ve)-.25 G(nt).15 E F2(sendmail)
+3.31 E F1 .81(from obe)3.31 F .81(ying the standards;)-.15 F 1.57
+(error messages will be sent as from the MAILER-D)122 192.6 R 1.57
+(AEMON \(actually)-.4 F 4.07(,t)-.65 G 1.57(he v)425.76 192.6 R 1.57
+(alue of the)-.25 F F0($n)4.07 E F1(macro\).)122 204.6 Q 15(hU)102 220.8 S
+(pper case should be preserv)129.22 220.8 Q(ed in host names for this mailer)
+-.15 E(.)-.55 E 16.67(IT)102 237 S .475
+(his mailer will be speaking SMTP to another)128.11 237 R F2(sendmail)2.974 E
+F1 2.974<8a61>2.974 G 2.974(ss)370.066 237 S .474
+(uch it can use special protocol)380.82 237 R 3.632(features. This)122 249 R
+1.133(option is not required \(i.e., if this option is omitted the transmissio\
+n will still)3.632 F(operate successfully)122 261 Q 2.5(,a)-.65 G
+(lthough perhaps not as ef)211.6 261 Q(\214ciently as possible\).)-.25 E 15(kN)
+102 277.2 S 1.03(ormally when)129.22 277.2 R F2(sendmail)3.53 E F1 1.03
+(connects to a host via SMTP)3.53 F 3.529(,i)-1.11 G 3.529(tc)356.257 277.2 S
+1.029(hecks to mak)367.006 277.2 R 3.529(es)-.1 G 1.029(ure that this isn')
+433.593 277.2 R(t)-.18 E .562(accidently the same host name as might happen if)
+122 289.2 R F2(sendmail)3.062 E F1 .562(is miscon\214gured or if a long-haul)
+3.062 F(netw)122 301.2 Q 1.074(ork interf)-.1 F 1.074
+(ace is set in loopback mode.)-.1 F 1.073
+(This \215ag disables the loopback check.)6.074 F 1.073(It should)6.073 F
+(only be used under v)122 313.2 Q(ery unusual circumstances.)-.15 E 12.78(KC)
+102 329.4 S(urrently unimplemented.)128.67 329.4 Q(Reserv)5 E(ed for chunking.)
+-.15 E 17.22(lT)102 345.6 S(his mailer is local \(i.e., \214nal deli)128.11
+345.6 Q -.15(ve)-.25 G(ry will be performed\).).15 E 13.89(LL)102 361.8 S .819
+(imit the line lengths as speci\214ed in RFC821.)128.11 361.8 R .82
+(This deprecated option should be replaced by)5.819 F(the)122 373.8 Q F0(L=)2.5
+E F1(mail declaration.)2.5 E -.15(Fo)5 G 2.5(rh).15 G(istoric reasons, the)
+245.04 373.8 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)102 390 S .464
+(his mailer can send to multiple users on the same host in one transaction.)
+128.11 390 R .463(When a)5.463 F F0($u)2.963 E F1(macro)2.963 E .731
+(occurs in the)122 402 R F2(ar)3.231 E(gv)-.37 E F1 .732(part of the mailer de\
+\214nition, that \214eld will be repeated as necessary for all)3.231 F
+(qualifying users.)122 414 Q 3.61(M\207 This)102 430.2 R(mailer w)2.5 E
+(ants a \231Message-Id:\232 header line.)-.1 E 15(nD)102 446.4 S 2.5(on)129.22
+446.4 S(ot insert a UNIX-style \231From\232 line on the front of the message.)
+141.72 446.4 Q 15(oA)102 462.6 S -.1(lwa)129.22 462.6 S .816(ys run as the o).1
+F .816(wner of the recipient mailbox.)-.25 F(Normally)5.816 E F2(sendmail)3.316
+E F1 .816(runs as the sender for)3.316 F .198
+(locally generated mail or as \231daemon\232 \(actually)122 474.6 R 2.698(,t)
+-.65 G .198(he user speci\214ed in the)321.576 474.6 R F0(u)2.698 E F1 .198
+(option\) when deli)2.698 F(v-)-.25 E .981(ering netw)122 486.6 R .981
+(ork mail.)-.1 F .981(The normal beha)5.981 F .981
+(viour is required by most local mailers, which will not)-.2 F(allo)122 498.6 Q
+2.52(wt)-.25 G .02(he en)149.27 498.6 R -.15(ve)-.4 G .021
+(lope sender address to be set unless the mailer is running as daemon.).15 F
+.021(This \215ag is)5.021 F(ignored if the)122 510.6 Q F0(S)2.5 E F1
+(\215ag is set.)2.5 E 15(pU)102 526.8 S .498(se the route-addr style re)129.22
+526.8 R -.15(ve)-.25 G .498(rse-path in the SMTP \231MAIL FR).15 F .497
+(OM:\232 command rather than just)-.4 F .385
+(the return address; although this is required in RFC821 section 3.1, man)122
+538.8 R 2.886(yh)-.15 G .386(osts do not process)427.012 538.8 R(re)122 550.8 Q
+-.15(ve)-.25 G(rse-paths properly).15 E 5(.R)-.65 G -2.15 -.25(ev e)224.81
+550.8 T(rse-paths are of).25 E(\214cially discouraged by RFC 1123.)-.25 E 6.94
+(P\207 This)102 567 R(mailer w)2.5 E(ants a \231Return-P)-.1 E(ath:\232 line.)
+-.15 E 16.67(rS)102 583.2 S(ame as)127.56 583.2 Q F0(f)2.5 E F1 2.5(,b)C
+(ut sends a)170.68 583.2 Q F0<ad72>2.5 E F1(\215ag.)2.5 E 16.11(sS)102 599.4 S
+(trip quote characters \(" and \\\) of)127.56 599.4 Q 2.5(fo)-.25 G 2.5(ft)
+266.07 599.4 S(he address before calling the mailer)274.68 599.4 Q(.)-.55 E
+14.44(SD)102 615.6 S(on')129.22 615.6 Q 3.332(tr)-.18 G .832
+(eset the userid before calling the mailer)151.812 615.6 R 5.831(.T)-.55 G .831
+(his w)328.433 615.6 R .831(ould be used in a secure en)-.1 F(vironment)-.4 E
+(where)122 627.6 Q F2(sendmail)3.317 E F1 .817(ran as root.)3.317 F .817
+(This could be used to a)5.817 F -.2(vo)-.2 G .817(id for).2 F .817
+(ged addresses.)-.18 F .817(If the)5.817 F F0(U=)3.317 E F1 .818(\214eld is)
+3.317 F .974(also speci\214ed, this \215ag causes the user id to al)122 639.6 R
+-.1(wa)-.1 G .974(ys be set to that user and group \(instead of).1 F(lea)122
+651.6 Q(ving it as root\).)-.2 E 15(uU)102 667.8 S(pper case should be preserv)
+129.22 667.8 Q(ed in user names for this mailer)-.15 E(.)-.55 E 12.78(UT)102
+684 S(his mailer w)128.11 684 Q(ants UUCP-style \231From\232 lines with the ug\
+ly \231remote from <host>\232 on the end.)-.1 E 12.78(wT)102 700.2 S .565
+(he user must ha)128.11 700.2 R .865 -.15(ve a v)-.2 H .566
+(alid account on this machine, i.e., getpwnam must succeed.)-.1 F .566
+(If not, the)5.566 F(mail is bounced.)122 712.2 Q
+(This is required to get \231.forw)5 E(ard\232 capability)-.1 E(.)-.65 E EP
+%%Page: 37 32
+%%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 7.5(x\207 This)102 96 R(mailer w)
+2.5 E(ants a \231Full-Name:\232 header line.)-.1 E 12.78(XT)102 112.2 S .972
+(his mailer w)128.11 112.2 R .972
+(ant to use the hidden dot algorithm as speci\214ed in RFC821; basically)-.1 F
+3.472(,a)-.65 G 1.272 -.15(ny l)475.678 112.2 T(ine).15 E(be)122 124.2 Q .796
+(ginning with a dot will ha)-.15 F 1.096 -.15(ve a)-.2 H 3.296(ne).15 G .797
+(xtra dot prepended \(to be stripped at the other end\).)267.742 124.2 R(This)
+5.797 E(insures that lines in the message containing a dot will not terminate \
+the message prematurely)122 136.2 Q(.)-.65 E 15(5I)102 152.4 S 2.717(fn)125.33
+152.4 S 2.717(oa)136.377 152.4 S .217(liases are found for this address, pass \
+the address through ruleset 5 for possible alternate)148.534 152.4 R 2.5
+(resolution. This)122 164.4 R(is intended to forw)2.5 E
+(ard the mail to an alternate deli)-.1 E -.15(ve)-.25 G(ry spot.).15 E 15(7S)
+102 180.6 S 1.14(trip all output to se)127.56 180.6 R -.15(ve)-.25 G 3.64(nb)
+.15 G 3.64(its. This)230.36 180.6 R 1.14(is the def)3.64 F 1.141(ault if the)
+-.1 F F0(L)3.641 E F1 1.141(\215ag is set.)3.641 F 1.141
+(Note that clearing this)6.141 F .295(option is not suf)122 192.6 R .295
+(\214cient to get full eight bit data passed through)-.25 F/F2 10
+/Times-Italic@0 SF(sendmail)2.795 E F1 5.295(.I)C 2.795(ft)423.635 192.6 S(he)
+432.54 192.6 Q F0(7)2.795 E F1 .295(option is set,)2.795 F .716
+(this is essentially al)122 204.6 R -.1(wa)-.1 G .717
+(ys set, since the eighth bit w).1 F .717(as stripped on input.)-.1 F .717
+(Note that this option)5.717 F(will only impact messages that didn')122 216.6 Q
+2.5(th)-.18 G -2.25 -.2(av e)279.04 216.6 T(8)2.7 E/F3 10/Symbol SF<ae>A F1 2.5
+(7b)C(it MIME con)322.44 216.6 Q -.15(ve)-.4 G(rsions performed.).15 E 15(8I)
+102 232.8 S 3.783(fs)125.33 232.8 S 1.283(et, it is acceptable to send eight b\
+it data to this mailer; the usual attempt to do 8)136.333 232.8 R F3<ae>A F1
+3.782(7b)C(it)498.44 232.8 Q(MIME con)122 244.8 Q -.15(ve)-.4 G
+(rsions will be bypassed.).15 E 17.22(:C)102 261 S .982
+(heck addresses to see if the)128.67 261 R 3.482(yb)-.15 G -.15(eg)255.492 261
+S .982(in \231:include:\232; if the).15 F 3.482(yd)-.15 G .982(o, con)361.33
+261 R -.15(ve)-.4 G .982(rt them to the \231*include*\232).15 F(mailer)122 273
+Q(.)-.55 E 18(|C)102 289.2 S(heck addresses to see if the)128.67 289.2 Q 2.5
+(yb)-.15 G -.15(eg)249.6 289.2 S(in with a `|'; if the).15 E 2.5(yd)-.15 G
+(o, con)343.51 289.2 Q -.15(ve)-.4 G(rt them to the \231prog\232 mailer).15 E
+(.)-.55 E 17.22(/C)102 305.4 S(heck addresses to see if the)128.67 305.4 Q 2.5
+(yb)-.15 G -.15(eg)249.6 305.4 S(in with a `/'; if the).15 E 2.5(yd)-.15 G
+(o, con)344.29 305.4 Q -.15(ve)-.4 G(rt them to the \231*\214le*\232 mailer).15
+E(.)-.55 E 10.79(@L)102 321.6 S(ook up addresses in the user database.)128.11
+321.6 Q .268(Con\214guration \214les prior to le)127 337.8 R -.15(ve)-.25 G
+2.768(l6a).15 G .268(ssume the `)271.538 337.8 R -1.11(A')-.8 G 2.768(,`)1.11 G
+.268(w', `5', `:', `|', `/', and `@' options on the)334.862 337.8 R
+(mailer named \231local\232.)102 349.8 Q .306(The mailer with the special name\
+ \231error\232 can be used to generate a user error)127 366 R 5.306(.T)-.55 G
+.306(he \(optional\))452.314 366 R .324(host \214eld is an e)102 378 R .323
+(xit status to be returned, and the user \214eld is a message to be printed.)
+-.15 F .323(The e)5.323 F .323(xit sta-)-.15 F .891
+(tus may be numeric or one of the v)102 390 R .891(alues USA)-.25 F .891
+(GE, NOUSER, NOHOST)-.4 F 3.391(,U)-.74 G -.35(NA)409.869 390 S -1.35(VA)-1 G
+.891(ILABLE, SOFT)1.35 F(-)-.92 E -1.2(WA)102 402 S 1.573(RE, TEMPF)1.2 F 1.573
+(AIL, PR)-.74 F -1.88 -.4(OT O)-.4 H 1.573
+(COL, or CONFIG to return the corresponding EX_ e).4 F 1.572(xit code.)-.15 F
+-.15(Fo)6.572 G(r).15 E -.15(ex)102 414 S(ample, the entry:).15 E
+($#error $@ NOHOST $: Host unkno)142 430.2 Q(wn in this domain)-.25 E .145(on \
+the RHS of a rule will cause the speci\214ed error to be generated and the \
+\231Host unkno)102 446.4 R .146(wn\232 e)-.25 F .146(xit sta-)-.15 F
+(tus to be returned if the LHS matches.)102 458.4 Q
+(This mailer is only functional in rulesets zero or \214v)5 E(e.)-.15 E .468
+(The mailer named \231local\232)127 474.6 R F2(must)2.968 E F1 .468
+(be de\214ned in e)2.968 F -.15(ve)-.25 G .468(ry con\214guration \214le.).15 F
+.468(This is used to deli)5.468 F -.15(ve)-.25 G(r).15 E .25
+(local mail, and is treated specially in se)102 486.6 R -.15(ve)-.25 G .25
+(ral w).15 F 2.75(ays. Additionally)-.1 F 2.75(,t)-.65 G .25
+(hree other mailers named \231prog\232,)369.43 486.6 R .942
+(\231*\214le*\232, and \231*include*\232 may be de\214ned to tune the deli)102
+498.6 R -.15(ve)-.25 G .942(ry of messages to programs, \214les, and).15 F
+(:include: lists respecti)102 510.6 Q -.15(ve)-.25 G(ly).15 E 5(.T)-.65 G(he)
+219 510.6 Q 2.5(yd)-.15 G(ef)240.79 510.6 Q(ault to:)-.1 E
+(Mprog, P=/bin/sh, F=lsD, A=sh \255c $u)142 526.8 Q(M*\214le*, P=/de)142 538.8
+Q(v/null, F=lsDFMPEu, A=FILE)-.25 E(M*include*, P=/de)142 550.8 Q
+(v/null, F=su, A=INCLUDE)-.25 E .615(The Sender and Recipient re)127 571.2 R
+.615(writing sets may either be a simple ruleset id or may be tw)-.25 F 3.116
+(oi)-.1 G(ds)495.11 571.2 Q .576(separated by a slash; if so, the \214rst re)
+102 583.2 R .575(writing set is applied to en)-.25 F -.15(ve)-.4 G .575
+(lope addresses and the second is).15 F(applied to headers.)102 595.2 Q .196
+(The Directory is actually a colon-separated path of directories to try)127
+611.4 R 5.197(.F)-.65 G .197(or e)413.019 611.4 R .197(xample, the de\214ni-)
+-.15 F .104(tion \231D=$z:/\232 \214rst tries to e)102 623.4 R -.15(xe)-.15 G
+.104(cute in the recipient').15 F 2.604(sh)-.55 G .104
+(ome directory; if that is not a)315.196 623.4 R -.25(va)-.2 G .103
+(ilable, it tries to).25 F -.15(exe)102 635.4 S .816
+(cute in the root of the \214lesystem.).15 F .816
+(This is intended to be used only on the \231prog\232 mailer)5.816 F 3.317(,s)
+-.4 G(ince)487.34 635.4 Q .368(some shells \(such as)102 647.4 R F2(csh)2.868 E
+F1 2.868(\)r)C .368(efuse to e)210.21 647.4 R -.15(xe)-.15 G .368(cute if the)
+.15 F 2.868(yc)-.15 G .367(annot read the home directory)311.29 647.4 R 5.367
+(.S)-.65 G .367(ince the queue)445.506 647.4 R
+(directory is not normally readable by unpri)102 659.4 Q(vile)-.25 E(ged users)
+-.15 E F2(csh)2.5 E F1(scripts as recipients can f)2.5 E(ail.)-.1 E 1.862
+(The Userid speci\214es the def)127 675.6 R 1.863
+(ault user and group id to run as, o)-.1 F -.15(ve)-.15 G 1.863(rriding the).15
+F F0(DefaultUser)4.363 E F1 .287(option \(q.v)102 687.6 R 2.787(.\). If)-.65 F
+(the)2.787 E F0(S)2.787 E F1 .287(mailer \215ag is also speci\214ed, this is t\
+he user and group to run as in all circum-)2.787 F 2.587(stances. This)102
+699.6 R .088(may be gi)2.587 F -.15(ve)-.25 G 2.588(na).15 G(s)219.518 699.6 Q
+F2(user:gr)2.588 E(oup)-.45 E F1 .088
+(to set both the user and group id; either may be an inte)2.588 F(ger)-.15 E
+.541(or a symbolic name to be look)102 711.6 R .541(ed up in the)-.1 F F2
+(passwd)3.041 E F1(and)3.041 E F2(gr)3.041 E(oup)-.45 E F1 .541
+(\214les respecti)3.041 F -.15(ve)-.25 G(ly).15 E 5.541(.I)-.65 G 3.041(fo)
+432.657 711.6 S .541(nly a symbolic)444.028 711.6 R
+(user name is speci\214ed, the group id in the)102 723.6 Q F2(passwd)2.5 E F1
+(\214le for that user is used as the group id.)2.5 E EP
+%%Page: 38 33
+%%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 .545
+(The Charset \214eld is used when con)127 96 R -.15(ve)-.4 G .545
+(rting a message to MIME; this is the character set used).15 F .466
+(in the Content-T)102 108 R .466(ype: header)-.8 F 5.466(.I)-.55 G 2.966(ft)
+225.824 108 S .466(his is not set, the)234.9 108 R F0(DefaultCharset)2.966 E F1
+.465(option is used, and if that is not)2.965 F .257(set, the v)102 120 R .257
+(alue \231unkno)-.25 F .257(wn-8bit\232 is used.)-.25 F F0 -1.2(WA)5.257 G
+(RNING:)1.2 E F1 .257(this \214eld applies to the sender')2.757 F 2.758(sm)-.55
+G(ailer)453.614 120 Q 2.758(,n)-.4 G .258(ot the)481.242 120 R(recipient')102
+132 Q 2.702(sm)-.55 G(ailer)154.142 132 Q 5.202(.F)-.55 G .202(or e)184.474 132
+R .202(xample, if the en)-.15 F -.15(ve)-.4 G .201
+(lope sender address lists an address on the local netw).15 F(ork)-.1 E .48
+(and the recipient is on an e)102 144 R .48(xternal netw)-.15 F .48
+(ork, the character set will be set from the Charset= \214eld for)-.1 F
+(the local netw)102 156 Q(ork mailer)-.1 E 2.5(,n)-.4 G(ot that of the e)208.98
+156 Q(xternal netw)-.15 E(ork mailer)-.1 E(.)-.55 E .795(The T)127 172.2 R .795
+(ype= \214eld sets the type information used in MIME error messages as de\214n\
+ed by RFC)-.8 F .15(XXX \(not yet published\).)102 184.2 R .15
+(It is actually three v)5.15 F .151(alues separated by slashes: the MT)-.25 F
+.151(A-type \(that is, the)-.93 F .36(description of ho)102 196.2 R 2.86(wh)
+-.25 G .359(osts are named\), the address type \(the description of e-mail add\
+resses\), and the)185.32 196.2 R .221
+(diagnostic type \(the description of error diagnostic codes\).)102 208.2 R
+.222(Each of these must be a re)5.221 F .222(gistered v)-.15 F(alue)-.25 E
+(or be)102 220.2 Q(gin with \231X\255\232.)-.15 E(The def)5 E
+(ault is \231dns/rfc822/smtp\232.)-.1 E F0 2.5(5.5. H)87 244.2 R 2.5<8a44>2.5 G
+(e\214ne Header)137 244.2 Q F1 1.136(The format of the header lines that)127
+260.4 R/F2 10/Times-Italic@0 SF(sendmail)3.636 E F1 1.135
+(inserts into the message are de\214ned by the)3.636 F F0(H)3.635 E F1 2.5
+(line. The)102 272.4 R(syntax of this line is:)2.5 E F0(H)142 288.6 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
+1.058(Continuation lines in this spec are re\215ected directly into the outgoi\
+ng message.)102 304.8 R(The)6.058 E F2(htemplate)3.558 E F1(is)3.558 E 1.098
+(macro e)102 316.8 R 1.098(xpanded before insertion into the message.)-.15 F
+1.098(If the)6.098 F F2(m\215a)3.598 E(gs)-.1 E F1 1.097
+(\(surrounded by question marks\))3.597 F .161(are speci\214ed, at least one o\
+f the speci\214ed \215ags must be stated in the mailer de\214nition for this h\
+eader)102 328.8 R .192(to be automatically output.)102 340.8 R .191
+(If one of these headers is in the input it is re\215ected to the output re)
+5.192 F -.05(ga)-.15 G(rd-).05 E(less of these \215ags.)102 352.8 Q
+(Some headers ha)127 369 Q .3 -.15(ve s)-.2 H
+(pecial semantics that will be described later).15 E(.)-.55 E F0 2.5(5.6. O)87
+393 R 2.5<8a53>2.5 G(et Option)135.34 393 Q F1 .962(There are a number of glob\
+al options that can be set from a con\214guration \214le.)127 409.2 R .963
+(Options are)5.963 F .86(represented by full w)102 421.2 R .86
+(ords; some are also representable as single characters for back compatibility)
+-.1 F(.)-.65 E(The syntax of this line is:)102 433.2 Q F0(O)142 449.4 Q F2
+(option)7.5 E F0(=)A F2(value)A F1 .562(This sets option)102 465.6 R F2(option)
+3.062 E F1 .562(to be)3.062 F F2(value)3.062 E F1 5.562(.N)C .562
+(ote that there)258.434 465.6 R F2(must)3.062 E F1 .562
+(be a space between the letter `O' and the)3.062 F(name of the option.)102
+477.6 Q(An older v)5 E(ersion is:)-.15 E F0(O)142 493.8 Q F2 1.666(ov)C(alue)
+-1.666 E F1 .13(where the option)102 510 R F2(o)2.63 E F1 .13
+(is a single character)2.63 F 5.13(.D)-.55 G .13(epending on the option,)273.56
+510 R F2(value)2.63 E F1 .13(may be a string, an inte)2.63 F(ger)-.15 E(,)-.4 E
+2.5(ab)102 522 S(oolean \(with le)113.94 522 Q -.05(ga)-.15 G 2.5(lv).05 G
+(alues \231t\232, \231T\232, \231f\232, or \231F\232; the def)193.2 522 Q
+(ault is TR)-.1 E(UE\), or a time interv)-.4 E(al.)-.25 E
+(The options supported \(with the old, one character names in brack)127 538.2 Q
+(ets\) are:)-.1 E(AliasFile=)102 554.4 Q F2(spec, spec, ...)A F1 .439
+([A] Specify possible alias \214le\(s\).)174 566.4 R(Each)5.439 E F2(spec)2.939
+E F1 .439(should be in the format `)2.939 F(`)-.74 E F2(class)A F0(:)A F2
+(\214le)2.94 E F1 -.74('')C(where)174 578.4 Q F2(class)3.1 E F0(:)A F1 .599
+(is optional and def)3.099 F .599(aults to `)-.1 F(`implicit')-.74 E 3.099
+('. Depending)-.74 F .599(on ho)3.099 F(w)-.25 E F2(sendmail)3.099 E F1 .186
+(is compiled, v)174 590.4 R .187(alid classes are \231implicit\232 \(search th\
+rough a compiled-in list of alias)-.25 F 2.055
+(\214le types, for back compatibility\), \231hash\232 \(if)174 602.4 R/F3 9
+/Times-Roman@0 SF(NEWDB)4.555 E F1 2.055(is speci\214ed\), \231dbm\232 \(if)
+4.555 F F3(NDBM)174 614.4 Q F1 1.588(is speci\214ed\), \231stab\232 \(internal\
+ symbol table \212 not normally used unless)4.088 F .075(you ha)174 626.4 R
+.375 -.15(ve n)-.2 H 2.575(oo).15 G .075
+(ther database lookup\), or \231nis\232 \(if)230.255 626.4 R F3(NIS)2.574 E F1
+.074(is speci\214ed\).)2.574 F .074(If a list of)5.074 F F2(spec)2.574 E F1(s)A
+(are pro)174 638.4 Q(vided,)-.15 E F2(sendmail)2.5 E F1(searches them in order)
+2.5 E(.)-.55 E(AliasW)102 654.6 Q(ait=)-.8 E F2(timeout)A F1 .14([a] If set, w)
+174 666.6 R .14(ait up to)-.1 F F2(timeout)2.64 E F1 .141(\(units def)2.641 F
+.141(ault to minutes\) for an \231@:@\232 entry to e)-.1 F(xist)-.15 E .518
+(in the alias database before starting up.)174 678.6 R .517
+(If it does not appear in the)5.517 F F2(timeout)3.017 E F1(inter)3.017 E(-)-.2
+E -.25(va)174 690.6 S 3.21(lr).25 G(eb)192.51 690.6 Q .71
+(uild the database \(if the)-.2 F F0 -.5(Au)3.21 G(toReb).5 E(uildAliases)-.2 E
+F1 .71(option is also set\) or issue a)3.21 F -.1(wa)174 702.6 S(rning.).1 E EP
+%%Page: 39 34
+%%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(AutoReb)102 96 Q(uildAliases)-.2 E
+.128([D] If set, reb)174 108 R .128
+(uild the alias database if necessary and possible.)-.2 F .128
+(If this option is not)5.128 F(set,)174 120 Q/F2 10/Times-Italic@0 SF(sendmail)
+4.885 E F1 2.385(will ne)4.885 F -.15(ve)-.25 G 4.885(rr).15 G(eb)283.96 120 Q
+2.385(uild the alias database unless e)-.2 F 2.385(xplicitly requested)-.15 F
+(using)174 132 Q F0(\255bi)2.5 E F1 5(.N)C
+(ot recommended \212 can cause thrashing.)226.93 132 Q(BlankSub=)102 148.2 Q F2
+(c)A F1 1.255([B] Set the blank substitution character to)174 148.2 R F2(c)
+3.755 E F1 6.255(.U)C 1.255(nquoted spaces in addresses are)372.35 148.2 R
+(replaced by this character)174 160.2 Q 5(.D)-.55 G(ef)290.63 160.2 Q
+(aults to space \(i.e., no change is made\).)-.1 E 14.51(CheckAliases [n])102
+176.4 R -1.11(Va)2.5 G(lidate the RHS of aliases when reb)1.11 E
+(uilding the alias database.)-.2 E(CheckpointInterv)102 192.6 Q(al=)-.25 E F2
+(N)A F1 1.296([C] Checkpoints the queue e)174 204.6 R -.15(ve)-.25 G(ry).15 E
+F2(N)3.797 E F1(\(def)3.797 E 1.297(ault 10\) addresses sent.)-.1 F 1.297
+(If your system)6.297 F .747(crashes during deli)174 216.6 R -.15(ve)-.25 G
+.746(ry to a lar).15 F .746(ge list, this pre)-.18 F -.15(ve)-.25 G .746
+(nts retransmission to an).15 F 3.246(yb)-.15 G .746(ut the)480.754 216.6 R
+(last recipients.)174 228.6 Q(ClassF)102 244.8 Q(actor=)-.15 E F2(fact)A F1
+1.624([z] The indicated)4.29 F F2(fact)4.124 E F1 1.624
+(or is multiplied by the message class \(determined by the)B .719
+(Precedence: \214eld in the user header and the)174 256.8 R F0(P)3.219 E F1
+.718(lines in the con\214guration \214le\) and)3.218 F 2.637
+(subtracted from the priority)174 268.8 R 7.637(.T)-.65 G 2.637
+(hus, messages with a higher Priority: will be)307.768 268.8 R -.1(fa)174 280.8
+S -.2(vo)-.1 G 2.5(red. Def).2 F(aults to 1800.)-.1 E 3.95(ColonOkInAddr [no)
+102 297 R 4.679
+(short name] If set, colons are acceptable in e-mail addresses \(e.g.,)7.18 F
+3.54(\231host:user\232\). If)174 309 R 1.04(not set, colons indicate the be)
+3.54 F 1.04(ginning of a RFC 822 group con-)-.15 F 1.988
+(struct \(\231groupname: member1, member2, ... memberN;\232\).)174 321 R 1.987
+(Doubled colons are)6.987 F(al)174 333 Q -.1(wa)-.1 G 2.215(ys acceptable \(\
+\231nodename::user\232\) and proper route-addr nesting is under).1 F(-)-.2 E
+1.037(stood \(\231<@relay:user@host>\232\).)174 345 R 1.037
+(Furthermore, this option def)6.037 F 1.036(aults on if the con-)-.1 F .853
+(\214guration v)174 357 R .853(ersion le)-.15 F -.15(ve)-.25 G 3.353(li).15 G
+3.353(sl)274.059 357 S .853(ess than 6 \(for back compatibility\).)284.082 357
+R(Ho)5.854 E(we)-.25 E -.15(ve)-.25 G 1.654 -.4(r, i).15 H 3.354(tm).4 G(ust)
+492.33 357 Q(be of)174 369 Q 2.5(ff)-.25 G(or full compatibility with RFC 822.)
+203.18 369 Q(ConnectionCacheSize=)102 385.2 Q F2(N)A F1 .242
+([k] The maximum number of open connections that will be cached at a time.)174
+397.2 R(The)5.242 E(def)174 409.2 Q .385(ault is one.)-.1 F .386
+(This delays closing the current connection until either this in)5.386 F -.2
+(vo)-.4 G(ca-).2 E 1.192(tion of)174 421.2 R F2(sendmail)3.692 E F1 1.191
+(needs to connect to another host or it terminates.)3.692 F 1.191
+(Setting it to)6.191 F 2.046(zero def)174 433.2 R 2.046(aults to the old beha)
+-.1 F(vior)-.2 E 4.546(,t)-.4 G 2.047
+(hat is, connections are closed immediately)322.496 433.2 R(.)-.65 E .266
+(Since this consumes \214le descriptors, the connection cache should be k)174
+445.2 R .265(ept small: 4)-.1 F(is probably a practical maximum.)174 457.2 Q
+(ConnectionCacheT)102 473.4 Q(imeout=)-.35 E F2(timeout)A F1 .708
+([K] The maximum amount of time a cached connection will be permitted to idle)
+174 485.4 R 1.083(without acti)174 497.4 R(vity)-.25 E 6.083(.I)-.65 G 3.583
+(ft)249.156 497.4 S 1.083(his time is e)258.849 497.4 R 1.082
+(xceeded, the connection is immediately closed.)-.15 F .417(This v)174 509.4 R
+.418(alue should be small \(on the order of ten minutes\).)-.25 F(Before)5.418
+E F2(sendmail)2.918 E F1 .418(uses a)2.918 F .508(cached connection, it al)174
+521.4 R -.1(wa)-.1 G .507(ys sends a RSET command to check the connection; if)
+.1 F .401(this f)174 533.4 R .401(ails, it reopens the connection.)-.1 F .401
+(This k)5.401 F .402(eeps your end from f)-.1 F .402(ailing if the other)-.1 F
+1.545(end times out.)174 545.4 R 1.545
+(The point of this option is to be a good netw)6.545 F 1.544(ork neighbor and)
+-.1 F -.2(avo)174 557.4 S(id using up e).2 E(xcessi)-.15 E .3 -.15(ve r)-.25 H
+(esources on the other end.).15 E(The def)5 E(ault is \214v)-.1 E 2.5(em)-.15 G
+(inutes.)470.25 557.4 Q(DaemonPortOptions=)102 573.6 Q F2(options)A F1
+([O] Set serv)174 585.6 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:)490.2 585.6 Q 52.83(Port Name/number)214 601.8 R
+(of listening port \(def)2.5 E(aults to "smtp"\))-.1 E 48.95(Addr Address)214
+613.8 R(mask \(def)2.5 E(aults IN)-.1 E(ADDR_ANY\))-.35 E -.15(Fa)214 625.8 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)214 637.8 R(of listen queue \(def)2.5 E(aults to 10\))-.1 E
+21.72(SndBufSize Size)214 649.8 R(of TCP send b)2.5 E(uf)-.2 E(fer)-.25 E 21.17
+(RcvBufSize Size)214 661.8 R(of TCP recei)2.5 E .3 -.15(ve b)-.25 H(uf)-.05 E
+(fer)-.25 E(The)174 678 Q F2(Addr)2.5 E F1
+(ess mask may be a numeric address in dot notation or a netw)A(ork name.)-.1 E
+(Def)102 694.2 Q(aultCharSet=)-.1 E F2 -.15(ch)C(ar).15 E(set)-.1 E F1 .16
+([no short name] When a message that has 8-bit characters b)174 706.2 R .161
+(ut is not in MIME for)-.2 F(-)-.2 E .495(mat is con)174 718.2 R -.15(ve)-.4 G
+.495(rted to MIME \(see the EightBitMode option\) a character set must be).15 F
+EP
+%%Page: 40 35
+%%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 .487
+(included in the Content-T)174 96 R .487(ype: header)-.8 F 5.487(.T)-.55 G .488
+(his character set is normally set from the)338.115 96 R .133
+(Charset= \214eld of the mailer descriptor)174 108 R 5.133(.I)-.55 G 2.633(ft)
+337.64 108 S .133(hat is not set, the v)346.383 108 R .133
+(alue of this option is)-.25 F 2.5(used. If)174 120 R
+(this option is not set, the v)2.5 E(alue \231unkno)-.25 E
+(wn-8bit\232 is used.)-.25 E(Def)102 136.2 Q(aultUser=)-.1 E/F2 10
+/Times-Italic@0 SF(user:gr)A(oup)-.45 E F1 .013([u] Set the def)174 148.2 R
+.013(ault userid for mailers to)-.1 F F2(user:gr)2.513 E(oup)-.45 E F1 5.013
+(.I)C(f)386.587 148.2 Q F2(gr)2.513 E(oup)-.45 E F1 .014(is omitted and)2.514 F
+F2(user)2.514 E F1(is)2.514 E 4.307(au)174 160.2 S 1.807
+(ser name \(as opposed to a numeric user id\) the def)187.747 160.2 R 1.806
+(ault group listed in the)-.1 F 1.153
+(/etc/passwd \214le for that user is used as the def)174 172.2 R 1.153
+(ault group.)-.1 F(Both)6.153 E F2(user)3.653 E F1(and)3.653 E F2(gr)3.653 E
+(oup)-.45 E F1 1.153(may be numeric.)174 184.2 R 1.152(Mailers without the)
+6.152 F F2(S)3.652 E F1 1.152(\215ag in the mailer de\214nition will run as)
+3.652 F .142(this user)174 198.2 R 5.142(.D)-.55 G(ef)222.064 198.2 Q .142
+(aults to 1:1.)-.1 F .142(The v)5.142 F .142(alue can also be gi)-.25 F -.15
+(ve)-.25 G 2.642(na).15 G 2.642(sas)400.612 198.2 S .142(ymbolic user name.)
+418.116 198.2 R/F3 7/Times-Roman@0 SF(18)497 194.2 Q F1(Deli)102 214.4 Q -.15
+(ve)-.25 G(ryMode=).15 E F2(x)A F1([d] Deli)4 E -.15(ve)-.25 G 2.5(ri).15 G 2.5
+(nm)223.03 214.4 S(ode)238.31 214.4 Q F2(x)2.5 E F1 5(.L)C -2.25 -.15(eg a)
+273.3 214.4 T 2.5(lm).15 G(odes are:)300.04 214.4 Q 17.22(iD)214 230.6 S(eli)
+241.22 230.6 Q -.15(ve)-.25 G 2.5(ri).15 G(nteracti)268.87 230.6 Q -.15(ve)-.25
+G(ly \(synchronously\)).15 E 15(bD)214 242.6 S(eli)241.22 242.6 Q -.15(ve)-.25
+G 2.5(ri).15 G 2.5(nb)268.87 242.6 S(ackground \(asynchronously\))281.37 242.6
+Q 15(qJ)214 254.6 S(ust queue the message \(deli)237.89 254.6 Q -.15(ve)-.25 G
+2.5(rd).15 G(uring queue run\))367.74 254.6 Q 15(dD)214 266.6 S(efer deli)
+241.22 266.6 Q -.15(ve)-.25 G(ry and all map lookups \(deli).15 E -.15(ve)-.25
+G 2.5(rd).15 G(uring queue run\))415.66 266.6 Q(Def)174 282.8 Q .712
+(aults to `)-.1 F(`b')-.74 E 3.212('i)-.74 G 3.212(fn)244.816 282.8 S 3.211(oo)
+256.358 282.8 S .711(ption is speci\214ed, `)269.569 282.8 R(`i')-.74 E 3.211
+('i)-.74 G 3.211(fi)365.093 282.8 S 3.211(ti)374.414 282.8 S 3.211(ss)383.185
+282.8 S .711(peci\214ed b)394.176 282.8 R .711(ut gi)-.2 F -.15(ve)-.25 G 3.211
+(nn).15 G 3.211(oa)474.869 282.8 S -.18(rg)487.52 282.8 S(u-).18 E .094
+(ment \(i.e., `)174 294.8 R(`Od')-.74 E 2.594('i)-.74 G 2.594(se)246.672 294.8
+S(qui)257.596 294.8 Q -.25(va)-.25 G .094(lent to `).25 F(`Odi')-.74 E 2.594
+('\). The)-.74 F F0<ad76>2.594 E F1 .094(command line \215ag sets this to)2.594
+F F0(i)2.594 E F1(.)A(DialDelay=)102 311 Q F2(sleeptime)A F1 .799
+([no short name] Dial-on-demand netw)174 323 R .798
+(ork connections can see timeouts if a con-)-.1 F .665
+(nection is opened before the call is set up.)174 335 R .665
+(If this is set to an interv)5.665 F .665(al and a con-)-.25 F .743
+(nection times out on the \214rst connection being attempted)174 347 R F2
+(sendmail)3.242 E F1 .742(will sleep for)3.242 F .31
+(this amount of time and try ag)174 359 R 2.81(ain. This)-.05 F .31(should gi)
+2.81 F .61 -.15(ve y)-.25 H .31(our system time to establish).15 F 1.543
+(the connection to your service pro)174 371 R(vider)-.15 E 6.543(.U)-.55 G
+1.543(nits def)354.188 371 R 1.542(ault to seconds, so \231DialDe-)-.1 F
+(lay=5\232 uses a \214v)174 383 Q 2.5(es)-.15 G(econd delay)251.7 383 Q 5(.D)
+-.65 G(ef)313.81 383 Q(aults to zero \(no retry\).)-.1 E(DontExpandCnames)102
+399.2 Q .559([no short name] The standards say that all host addresses used in\
+ a mail message)174 411.2 R 1.408(must be fully canonical.)174 423.2 R -.15(Fo)
+6.407 G 3.907(re).15 G 1.407(xample, if your host is named \231Cruft.F)302.668
+423.2 R(oo.ORG\232)-.15 E 1.462(and also has an alias of \231FTP)174 435.2 R
+(.F)-1.11 E 1.462(oo.ORG\232, the former name must be used at all)-.15 F 2.631
+(times. This)174 447.2 R .131
+(is enforced during host name canoni\214cation \($[ ... $] lookups\).)2.631 F
+.13(If this)5.13 F .661
+(option is set, the protocols are ignored and the \231wrong\232 thing is done.)
+174 459.2 R(Ho)5.662 E(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G .455
+(the IETF is mo)174 471.2 R .455(ving to)-.15 F -.1(wa)-.25 G .455
+(rd changing this standard, so the beha).1 F .455(viour may become)-.2 F 3.009
+(acceptable. Please)174 483.2 R .509(note that hosts do)3.009 F .509
+(wnstream may still re)-.25 F .509(write the address to be)-.25 F
+(the true canonical name ho)174 495.2 Q(we)-.25 E -.15(ve)-.25 G -.55(r.).15 G
+6.17(DontInitGroups [no)102 511.4 R .25(short name] If set,)2.75 F F2(sendmail)
+2.75 E F1 .25(will a)2.75 F -.2(vo)-.2 G .25
+(id using the initgroups\(3\) call.).2 F .25(If you are)5.25 F .583(running NI\
+S, this causes a sequential scan of the groups.byname map, which can)174 523.4
+R .436(cause your NIS serv)174 535.4 R .436(er to be badly o)-.15 F -.15(ve)
+-.15 G .435(rloaded in a lar).15 F .435(ge domain.)-.18 F .435
+(The cost of this)5.435 F .697(is that the only group found for users will be \
+their primary group \(the one in the)174 547.4 R(passw)174 559.4 Q 1.189
+(ord \214le\), which will mak)-.1 F 3.689<658c>-.1 G 1.189
+(le access permissions some)315.845 559.4 R 1.189(what more restric-)-.25 F(ti)
+174 571.4 Q -.15(ve)-.25 G 5(.H).15 G(as no ef)203.32 571.4 Q
+(fect on systems that don')-.25 E 2.5(th)-.18 G -2.25 -.2(av e)344.26 571.4 T
+(group lists.)2.7 E -1.61(DontPruneRoutes [R])102 587.6 R(Normally)3.905 E(,)
+-.65 E F2(sendmail)3.905 E F1 1.405(tries to eliminate an)3.905 F 3.905(yu)-.15
+G 1.405(nnecessary e)372.465 587.6 R 1.405(xplicit routes when)-.15 F .155
+(sending an error message \(as discussed in RFC 1123 \247 5.2.6\).)174 599.6 R
+-.15(Fo)5.154 G 2.654(re).15 G .154(xample, when)447.746 599.6 R
+(sending an error message to)174 611.6 Q(<@kno)214 627.8 Q(wn1,@kno)-.25 E
+(wn2,@kno)-.25 E(wn3:user@unkno)-.25 E(wn>)-.25 E F2(sendmail)174 644 Q F1
+1.155(will strip of)3.655 F 3.655(ft)-.25 G 1.155(he \231@kno)272.26 644 R
+(wn1,@kno)-.25 E 1.155(wn2\232 in order to mak)-.25 F 3.655(et)-.1 G 1.155
+(he route as)458.37 644 R .813(direct as possible.)174 656 R(Ho)5.813 E(we)-.25
+E -.15(ve)-.25 G 1.613 -.4(r, i).15 H 3.313(ft).4 G(he)306.435 656 Q F0(R)3.313
+E F1 .812(option is set, this will be disabled, and the)3.313 F .009
+(mail will be sent to the \214rst address in the route, e)174 668 R -.15(ve)
+-.25 G 2.51(ni).15 G 2.51(fl)392.86 668 S .01(ater addresses are kno)401.48 668
+R(wn.)-.25 E(This may be useful if you are caught behind a \214re)174 680 Q -.1
+(wa)-.25 G(ll.).1 E .32 LW 76 689.6 72 689.6 DL 80 689.6 76 689.6 DL 84 689.6
+80 689.6 DL 88 689.6 84 689.6 DL 92 689.6 88 689.6 DL 96 689.6 92 689.6 DL 100
+689.6 96 689.6 DL 104 689.6 100 689.6 DL 108 689.6 104 689.6 DL 112 689.6 108
+689.6 DL 116 689.6 112 689.6 DL 120 689.6 116 689.6 DL 124 689.6 120 689.6 DL
+128 689.6 124 689.6 DL 132 689.6 128 689.6 DL 136 689.6 132 689.6 DL 140 689.6
+136 689.6 DL 144 689.6 140 689.6 DL 148 689.6 144 689.6 DL 152 689.6 148 689.6
+DL 156 689.6 152 689.6 DL 160 689.6 156 689.6 DL 164 689.6 160 689.6 DL 168
+689.6 164 689.6 DL 172 689.6 168 689.6 DL 176 689.6 172 689.6 DL 180 689.6 176
+689.6 DL 184 689.6 180 689.6 DL 188 689.6 184 689.6 DL 192 689.6 188 689.6 DL
+196 689.6 192 689.6 DL 200 689.6 196 689.6 DL 204 689.6 200 689.6 DL 208 689.6
+204 689.6 DL 212 689.6 208 689.6 DL 216 689.6 212 689.6 DL/F4 5/Times-Roman@0
+SF(18)93.6 700 Q/F5 8/Times-Roman@0 SF(The old)3.2 I/F6 8/Times-Bold@0 SF(g)2 E
+F5(option has been combined into the)2 E F6(DefaultUser)2 E F5(option.)2 E EP
+%%Page: 41 36
+%%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(EightBitMode=)102 96 Q/F2 10
+/Times-Italic@0 SF(action)A F1 1.956([8] Set handling of eight-bit data.)174
+108 R 1.955(There are tw)6.955 F 4.455(ok)-.1 G 1.955
+(inds of eight-bit data: that)392.85 108 R 3.334(declared as such using the)174
+120 R F0(BOD)5.834 E(Y=8BITMIME)-.4 E F1 3.335(ESMTP declaration or the)5.835 F
+F0(\255B8BITMIME)174 132 Q F1 .948
+(command line \215ag, and undeclared 8-bit data, that is, input that)3.449 F
+1.18(just happens to be eight bits.)174 144 R 1.18
+(There are three basic operations that can happen:)6.18 F .996
+(undeclared 8-bit data can be automatically con)174 156 R -.15(ve)-.4 G .995
+(rted to 8BITMIME, undeclared).15 F .887
+(8-bit data can be passed as-is without con)174 168 R -.15(ve)-.4 G .887
+(rsion to MIME \(`).15 F .887(`just send 8')-.74 F .887('\), and)-.74 F 5.989
+(declared 8-bit data can be con)174 180 R -.15(ve)-.4 G 5.989
+(rted to 7-bits for transmission to a).15 F(non-8BITMIME mailer)174 192 Q 5(.T)
+-.55 G(he possible)281.77 192 Q F2(action)2.5 E F1 2.5(sa)C(re:)364.82 192 Q
+11.11(sR)219 208.2 S(eject undeclared 8-bit data \(`)240.67 208.2 Q(`strict')
+-.74 E('\))-.74 E 7.22(mC)219 220.2 S(on)240.67 220.2 Q -.15(ve)-.4 G
+(rt undeclared 8-bit data to MIME \(`).15 E(`mime')-.74 E('\))-.74 E 10(pP)219
+232.2 S(ass undeclared 8-bit data \(`)239.41 232.2 Q(`pass')-.74 E('\))-.74 E
+2.227(In all cases properly declared 8BITMIME data will be con)174 248.4 R -.15
+(ve)-.4 G 2.228(rted to 7BIT as).15 F(needed.)174 260.4 Q(ErrorHeader=)102
+276.6 Q F2(\214le-or)A(-messa)-.2 E -.1(ge)-.1 G F1 .486
+([E] Prepend error messages with the indicated message.)174 288.6 R .486
+(If it be)5.486 F .486(gins with a slash,)-.15 F .246(it is assumed to be the \
+pathname of a \214le containing a message \(this is the recom-)174 300.6 R .86
+(mended setting\).)174 312.6 R .86(Otherwise, it is a literal message.)5.86 F
+.86(The error \214le might contain)5.86 F 1.116
+(the name, email address, and/or phone number of a local postmaster who could)
+174 324.6 R(pro)174 336.6 Q .174(vide assistance in to end users.)-.15 F .173
+(If the option is missing or null, or if it names a)5.174 F
+(\214le which does not e)174 348.6 Q
+(xist or which is not readable, no message is printed.)-.15 E(ErrorMode=)102
+364.8 Q F2(x)A F1([e] Dispose of errors using mode)174 364.8 Q F2(x)2.5 E F1 5
+(.T)C(he v)325.91 364.8 Q(alues for)-.25 E F2(x)2.5 E F1(are:)2.5 E 15(pP)214
+381 S(rint error messages \(def)239.56 381 Q(ault\))-.1 E 15(qN)214 393 S 2.5
+(om)241.22 393 S(essages, just gi)256.5 393 Q .3 -.15(ve ex)-.25 H(it status)
+.15 E 12.22(mM)214 405 S(ail back errors)242.89 405 Q 12.78(wW)214 417 S
+(rite back errors \(mail if user not logged in\))243.44 417 Q 15.56(eM)214 429
+S(ail back errors and gi)242.89 429 Q .3 -.15(ve z)-.25 H(ero e).15 E
+(xit stat al)-.15 E -.1(wa)-.1 G(ys).1 E -.15(Fa)102 449.4 S(llbackMXhost=).15
+E F2(fallbac)A(khost)-.2 E F1 .796([V] If speci\214ed, the)174 461.4 R F2
+(fallbac)3.296 E(khost)-.2 E F1 .796(acts lik)3.296 F 3.296(eav)-.1 G .797
+(ery lo)359.608 461.4 R 3.297(wp)-.25 G .797(riority MX on e)398.722 461.4 R
+-.15(ve)-.25 G .797(ry host.).15 F
+(This is intended to be used by sites with poor netw)174 473.4 Q(ork connecti)
+-.1 E(vity)-.25 E(.)-.65 E -.15(Fo)102 489.6 S 16.88(rkEachJob [Y]).15 F .708
+(If set, deli)3.208 F -.15(ve)-.25 G 3.208(re).15 G .707
+(ach job that is run from the queue in a separate process.)252.792 489.6 R(Use)
+5.707 E .274(this option if you are short of memory)174 501.6 R 2.774(,s)-.65 G
+.274(ince the def)336.922 501.6 R .275(ault tends to consume consid-)-.1 F
+(erable amounts of memory while the queue is being processed.)174 513.6 Q -.15
+(Fo)102 529.8 S(rw).15 E(ardP)-.1 E(ath=)-.15 E F2(path)A F1 4.675
+([J] Set the path for searching for users' .forw)174 541.8 R 4.675
+(ard \214les.)-.1 F 4.675(The def)9.675 F 4.675(ault is)-.1 F(\231$z/.forw)174
+553.8 Q 3.23(ard\232. Some)-.1 F .731
+(sites that use the automounter may prefer to change this to)3.23 F(\231/v)174
+565.8 Q(ar/forw)-.25 E 1.696
+(ard/$u\232 to search a \214le with the same name as the user in a system)-.1 F
+(directory)174 577.8 Q 5.487(.I)-.65 G 2.987(tc)220.767 577.8 S .488
+(an also be set to a sequence of paths separated by colons;)230.974 577.8 R F2
+(sendmail)2.988 E F1 4.218
+(stops at the \214rst \214le it can successfully and safely open.)174 589.8 R
+-.15(Fo)9.217 G 6.717(re).15 G(xample,)472.06 589.8 Q(\231/v)174 601.8 Q
+(ar/forw)-.25 E(ard/$u:$z/.forw)-.1 E .681(ard\232 will search \214rst in /v)
+-.1 F(ar/forw)-.25 E(ard/)-.1 E F2(username)A F1 .682(and then)3.182 F(in)174
+613.8 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(HelpFile=)102
+630 Q F2(\214le)A F1([H] Specify the help \214le for SMTP)174 630 Q(.)-1.11 E
+(HoldExpensi)102 646.2 Q 8.54 -.15(ve [)-.25 H 1.394
+(c] If an outgoing mailer is mark).15 F 1.393(ed as being e)-.1 F(xpensi)-.15 E
+-.15(ve)-.25 G 3.893(,d).15 G(on')415.294 646.2 Q 3.893(tc)-.18 G 1.393
+(onnect immedi-)439.557 646.2 R(ately)174 658.2 Q 5.267(.T)-.65 G .268
+(his requires that queueing be compiled in, since it will depend on a queue)
+206.667 658.2 R(run process to actually send the mail.)174 670.2 Q 24.51
+(IgnoreDots [i])102 686.4 R 1.172(Ignore dots in incoming messages.)3.672 F
+1.172(This is al)6.172 F -.1(wa)-.1 G 1.171(ys disabled \(that is, dots are).1
+F(al)174 698.4 Q -.1(wa)-.1 G(ys accepted\) when reading SMTP mail.).1 E EP
+%%Page: 42 37
+%%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(LogLe)102 96 Q
+-.15(ve)-.25 G(l=).15 E/F2 10/Times-Italic@0 SF(n)A F1([L] Set the def)174 96 Q
+(ault log le)-.1 E -.15(ve)-.25 G 2.5(lt).15 G(o)289.04 96 Q F2(n)2.5 E F1 5
+(.D)C(ef)316.26 96 Q(aults to 9.)-.1 E(M)102 112.2 Q F2 1.666(xv)C(alue)-1.666
+E F1 .255([no long v)174 112.2 R .255(ersion] Set the macro)-.15 F F2(x)2.755 E
+F1(to)2.755 E F2(value)2.755 E F1 5.255(.T)C .255
+(his is intended only for use from the)357.505 112.2 R(command line.)174 124.2
+Q(The)5 E F0<ad4d>2.5 E F1(\215ag is preferred.)2.5 E 11.17(MatchGECOS [G])102
+140.4 R(Allo)3.334 E 3.334(wf)-.25 G .834(uzzy matching on the GECOS \214eld.)
+222.628 140.4 R .833(If this \215ag is set, and the usual)5.833 F .867
+(user name lookups f)174 152.4 R .867
+(ail \(that is, there is no alias with this name and a)-.1 F F2 -.1(ge)3.368 G
+(tpwnam).1 E F1 -.1(fa)174 164.4 S 1.155(ils\), sequentially search the passw)
+.1 F 1.155(ord \214le for a matching entry in the GECOS)-.1 F 3.696
+(\214eld. This)174 176.4 R 1.196(also requires that MA)3.696 F 1.196
+(TCHGECOS be turned on during compilation.)-1.11 F
+(This option is not recommended.)174 188.4 Q(MaxHopCount=)102 204.6 Q F2(N)A F1
+1.238([h] The maximum hop count.)174 216.6 R 1.238(Messages that ha)6.238 F
+1.537 -.15(ve b)-.2 H 1.237(een processed more than).15 F F2(N)3.737 E F1
+(times are assumed to be in a loop and are rejected.)174 228.6 Q(Def)5 E
+(aults to 25.)-.1 E(MaxHostStatAge=)102 244.8 Q F2 -.1(age)C F1 .438
+([no short name] Not yet implemented.)174 256.8 R .438
+(This option speci\214es ho)5.438 F 2.939(wl)-.25 G .439(ong host status)
+443.672 256.8 R .36(information will be retained.)174 268.8 R -.15(Fo)5.36 G
+2.86(re).15 G .36(xample, if a host is found to be do)315.76 268.8 R .36
+(wn, connec-)-.25 F .246
+(tions to that host will not be retried for this interv)174 280.8 R 2.746
+(al. The)-.25 F .246(units def)2.746 F .246(ault to minutes.)-.1 F
+(MaxQueueRunSize=)102 297 Q F2(N)A F1 .677
+([no short name] The maximum number of jobs that will be processed in a single)
+174 309 R .501(queue run.)174 321 R .501
+(If not set, there is no limit on the size.)5.501 F .501(If you ha)5.501 F .802
+-.15(ve ve)-.2 H .502(ry lar).15 F .502(ge queues)-.18 F .445(or a v)174 333 R
+.445(ery short queue run interv)-.15 F .445(al this could be unstable.)-.25 F
+(Ho)5.445 E(we)-.25 E -.15(ve)-.25 G 1.245 -.4(r, s).15 H .445
+(ince the \214rst).4 F F2(N)174 345 Q F1 1.115
+(jobs in queue directory order are run \(rather than the)3.615 F F2(N)3.615 E
+F1 1.115(highest priority jobs\))3.615 F .136
+(this should be set as high as possible to a)174 357 R -.2(vo)-.2 G .136
+(id \231losing\232 jobs that happen to f).2 F .136(all late)-.1 F
+(in the queue directory)174 369 Q(.)-.65 E(MeT)102 385.2 Q 40.86(oo [m])-.8 F
+(Send to me too, e)2.5 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(fIa)279.98 385.2 S 2.5
+(mi)296.08 385.2 S 2.5(na)309.14 385.2 S 2.5(na)321.08 385.2 S(lias e)333.02
+385.2 Q(xpansion.)-.15 E(MaxMessageSize=)102 401.4 Q F2(N)A F1 2.562
+([no short name] Specify the maximum message size to be adv)174 413.4 R 2.563
+(ertised in the)-.15 F(ESMTP EHLO response.)174 425.4 Q(Messages lar)5 E
+(ger than this will be rejected.)-.18 E(MinFreeBlocks=)102 441.6 Q F2(N)A F1
+1.539([b] Insist on at least)174 453.6 R F2(N)4.039 E F1 1.538
+(blocks free on the \214lesystem that holds the queue \214les)4.039 F .845
+(before accepting email via SMTP)174 465.6 R 5.846(.I)-1.11 G 3.346(ft)322.368
+465.6 S .846(here is insuf)331.824 465.6 R .846(\214cient space)-.25 F F2
+(sendmail)3.346 E F1(gi)3.346 E -.15(ve)-.25 G 3.346(sa).15 G
+(452 response to the MAIL command.)174 477.6 Q(This in)5 E
+(vites the sender to try ag)-.4 E(ain later)-.05 E(.)-.55 E(MinQueueAge=age)102
+493.8 Q .887([no short name] Don')174 505.8 R 3.387(tp)-.18 G .887(rocess an)
+274.018 505.8 R 3.387(yq)-.15 G .886(ueued jobs that ha)325.072 505.8 R 1.186
+-.15(ve b)-.2 H .886(een in the queue less).15 F 1.899
+(than the indicated time interv)174 517.8 R 4.399(al. This)-.25 F 1.899
+(is intended to allo)4.399 F 4.399(wy)-.25 G 1.9(ou to get respon-)430.81 517.8
+R(si)174 529.8 Q -.15(ve)-.25 G .665(ness by processing the queue f).15 F .665
+(airly frequently without thrashing your system)-.1 F
+(by trying jobs too often.)174 541.8 Q(The def)5 E(ault units are minutes.)-.1
+E(NoRecipientAction)102 558 Q .554([no short name] The action to tak)174 570 R
+3.055(ew)-.1 G .555(hen you recei)325.25 570 R .855 -.15(ve a m)-.25 H .555
+(essage that has no v).15 F(alid)-.25 E .062(recipient headers \(T)174 582 R
+.062(o:, Cc:, Bcc:\).)-.8 F .062(It can be)5.062 F F0(None)2.561 E F1 .061
+(to pass the message on unmodi-)2.561 F .51
+(\214ed, which violates the protocol,)174 594 R F0(Add-T)3.01 E(o)-.92 E F1 .51
+(to add a T)3.01 F .51(o: header with an)-.8 F 3.01(yr)-.15 G(ecipients)468.45
+594 Q 4.41(it can \214nd in the en)174 606 R -.15(ve)-.4 G 4.41
+(lope \(which might e).15 F 4.41(xpose Bcc: recipients\),)-.15 F F0(Add-)6.91 E
+-.25(Ap)174 618 S(par).25 E(ently-T)-.18 E(o)-.92 E F1 4.664
+(to add an Apparently-T)7.164 F 4.664(o: header \(this is only for back-)-.8 F
+.875(compatibility and is of)174 630 R .875(\214cially deprecated\),)-.25 F F0
+(Add-T)3.374 E(o-Undisclosed)-.92 E F1 .874(to add a header)3.374 F<9954>174
+642 Q 1.594(o: undisclosed-recipients:;\232 to mak)-.8 F 4.094(et)-.1 G 1.594
+(he header le)339.456 642 R -.05(ga)-.15 G 4.095(lw).05 G 1.595
+(ithout disclosing an)414.29 642 R(y-)-.15 E(thing, or)174 654 Q F0(Add-Bcc)2.5
+E F1(to add an empty Bcc: header)2.5 E(.)-.55 E 1.18(OldStyleHeaders [o])102
+670.2 R 1.713
+(Assume that the headers may be in old format, i.e., spaces delimit names.)
+4.214 F 1.068(This actually turns on an adapti)174 682.2 R 1.368 -.15(ve a)-.25
+H 1.068(lgorithm: if an).15 F 3.569(yr)-.15 G 1.069
+(ecipient address contains a)393.873 682.2 R 1.681
+(comma, parenthesis, or angle brack)174 694.2 R 1.681
+(et, it will be assumed that commas already)-.1 F -.15(ex)174 706.2 S 2.825
+(ist. If).15 F .325(this \215ag is not on, only commas delimit names.)2.825 F
+.325(Headers are al)5.325 F -.1(wa)-.1 G .325(ys out-).1 F
+(put with commas between the names.)174 718.2 Q(Def)5 E(aults to of)-.1 E(f.)
+-.25 E EP
+%%Page: 43 38
+%%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(OperatorChars=)102 96 Q/F2 10
+/Times-Italic@0 SF -.15(ch)C(arlist).15 E F1 1.438([$o macro] The list of char\
+acters that are considered to be \231operators\232, that is,)174 108 R .82
+(characters that delimit tok)174 120 R 3.32(ens. All)-.1 F .82
+(operator characters are tok)3.32 F .82(ens by themselv)-.1 F(es;)-.15 E .078
+(sequences of non-operator characters are also tok)174 132 R 2.578(ens. White)
+-.1 F .078(space characters sep-)2.578 F .269(arate tok)174 144 R .269(ens b)
+-.1 F .269(ut are not tok)-.2 F .269(ens themselv)-.1 F .269(es \212 for e)-.15
+F .269(xample, \231)-.15 F .27(AAA.BBB\232 has three)-.8 F(tok)174 156 Q .433
+(ens, b)-.1 F .433(ut \231)-.2 F .433(AAA BBB\232 has tw)-.8 F 2.933(o. If)-.1
+F .433(not set, OperatorChars def)2.933 F .433(aults to \231.)-.1 F 1.666(:@[])
+1.666 G<9a3b>-1.666 E(additionally)174 168 Q 2.5(,t)-.65 G
+(he characters \231\()228.91 168 Q 1.666(\)<>,;)1.666 G 2.5<9a61>-1.666 G
+(re al)331.25 168 Q -.1(wa)-.1 G(ys operators.).1 E(PostmasterCop)102 184.2 Q
+(y=)-.1 E F2(postmaster)A F1 .003
+([P] If set, copies of error messages will be sent to the named)174 196.2 R F2
+(postmaster)2.504 E F1 5.004(.O)C .004(nly the)476.496 196.2 R .627
+(header of the f)174 208.2 R .627(ailed message is sent.)-.1 F .626
+(Since most errors are user problems, this is)5.626 F .453
+(probably not a good idea on lar)174 220.2 R .453(ge sites, and ar)-.18 F .453
+(guably contains all sorts of pri)-.18 F -.25(va)-.25 G -.15(cy).25 G 1.979
+(violations, b)174 232.2 R 1.978
+(ut it seems to be popular with certain operating systems v)-.2 F(endors.)-.15
+E(Def)174 244.2 Q(aults to no postmaster copies.)-.1 E(Pri)102 260.4 Q -.25(va)
+-.25 G -.15(cy).25 G(Options=).15 E F2(opt,opt,...)1.666 E F1 1.191
+([p] Set the pri)174 272.4 R -.25(va)-.25 G -.15(cy).25 G F2(opt)3.841 E F1
+3.691(ions. `)B(`Pri)-.74 E -.25(va)-.25 G -.15(cy).25 G 2.671 -.74('' i).15 H
+3.692(sr).74 G 1.192(eally a misnomer; man)352.028 272.4 R 3.692(yo)-.15 G
+3.692(ft)460.526 272.4 S 1.192(hese are)470.328 272.4 R .929(just a w)174 284.4
+R .928(ay of insisting on stricter adherence to the SMTP protocol.)-.1 F(The)
+5.928 E F2(opt)3.428 E F1(ions)A(can be selected from:)174 296.4 Q 40.26
+(public Allo)214 312.6 R 2.5(wo)-.25 G(pen access)314.01 312.6 Q 11.38
+(needmailhelo Insist)214 324.6 R(on HELO or EHLO command before MAIL)2.5 E
+(neede)214 336.6 Q 9.87(xpnhelo Insist)-.15 F
+(on HELO or EHLO command before EXPN)2.5 E(noe)214 348.6 Q 35.97(xpn Disallo)
+-.15 F 2.5(wE)-.25 G(XPN entirely)326.23 348.6 Q 12.5(needvrfyhelo Insist)214
+360.6 R(on HELO or EHLO command before VRFY)2.5 E(no)214 372.6 Q 38.75
+(vrfy Disallo)-.15 F 2.5(wV)-.25 G(RFY entirely)327.34 372.6 Q 14.71
+(restrictmailq Restrict)214 384.6 R(mailq command)2.5 E 19.16
+(restrictqrun Restrict)214 396.6 R(\255q command line \215ag)2.5 E 24.16
+(noreceipts Don')214 408.6 R 2.5(tr)-.18 G(eturn success DSNs)310.74 408.6 Q
+(goa)214 420.6 Q -.1(wa)-.15 G 36.91(yD).1 G(isallo)288.98 420.6 Q 2.5(we)-.25
+G(ssentially all SMTP status queries)324.56 420.6 Q(authw)214 432.6 Q 11.48
+(arnings Put)-.1 F(X-Authentication-W)2.5 E(arning: headers in messages)-.8 E
+.485(The \231goa)174 448.8 R -.1(wa)-.15 G .485
+(y\232 pseudo-\215ag sets all \215ags e).1 F .486
+(xcept \231restrictmailq\232 and \231restrictqrun\232.)-.15 F 1.175(If mailq i\
+s restricted, only people in the same group as the queue directory can)174
+460.8 R .207(print the queue.)174 472.8 R .207
+(If queue runs are restricted, only root and the o)5.207 F .208
+(wner of the queue)-.25 F .066(directory can run the queue.)174 484.8 R .066
+(Authentication W)5.066 F .066(arnings add w)-.8 F .066(arnings about v)-.1 F
+(arious)-.25 E .77(conditions that may indicate attempts to spoof the mail sys\
+tem, such as using an)174 496.8 R(non-standard queue directory)174 508.8 Q(.)
+-.65 E(QueueDirectory=)102 525 Q F2(dir)A F1([Q] Use the named)174 537 Q F2
+(dir)2.5 E F1(as the queue directory)2.5 E(.)-.65 E(QueueF)102 553.2 Q(actor=)
+-.15 E F2(factor)A F1 .614([q] Use)174 565.2 R F2(factor)3.114 E F1 .613
+(as the multiplier in the map function to decide when to just queue)3.114 F
+.415(up jobs rather than run them.)174 577.2 R .415(This v)5.415 F .415
+(alue is di)-.25 F .415(vided by the dif)-.25 F .415(ference between the)-.25 F
+1.004(current load a)174 589.2 R -.15(ve)-.2 G 1.004(rage and the load a).15 F
+-.15(ve)-.2 G 1.004(rage limit \().15 F F0(QueueLA)A F1 1.003
+(option\) to determine)3.503 F(the maximum message priority that will be sent.)
+174 601.2 Q(Def)5 E(aults to 600000.)-.1 E(QueueLA=)102 617.4 Q F2(LA)A F1 .164
+([x] When the system load a)174 617.4 R -.15(ve)-.2 G .165(rage e).15 F(xceeds)
+-.15 E F2(LA)2.665 E F1 2.665(,j)C .165(ust queue messages \(i.e., don')367.265
+617.4 R 2.665(tt)-.18 G(ry)495.67 617.4 Q(to send them\).)174 629.4 Q(Def)5 E
+(aults to 8.)-.1 E(QueueSortOrder=)102 645.6 Q F2(algorithm)A F1 .097
+([no short name] Sets the)174 657.6 R F2(algorithm)2.597 E F1 .096
+(used for sorting the queue.)2.597 F .096(Only the \214rst char)5.096 F(-)-.2 E
+1.021(acter of the v)174 669.6 R 1.021(alue is used.)-.25 F(Le)6.021 E -.05(ga)
+-.15 G 3.521(lv).05 G 1.021
+(alues are \231host\232 \(to order by the name of the)317.357 669.6 R .922(\
+\214rst host name of the \214rst recipient\) and \231priority\232 \(to order s\
+trictly by message)174 681.6 R 2.527(priority\). Host)174 693.6 R .027
+(ordering mak)2.527 F .028(es better use of the connection cache, b)-.1 F .028
+(ut may tend to)-.2 F .323(process lo)174 705.6 R 2.823(wp)-.25 G .322
+(riority messages that go to a single host o)229.386 705.6 R -.15(ve)-.15 G
+2.822(rh).15 G .322(igh priority messages)417.806 705.6 R 1.824(that go to se)
+174 717.6 R -.15(ve)-.25 G 1.824(ral hosts; it probably shouldn').15 F 4.325
+(tb)-.18 G 4.325(eu)376.345 717.6 S 1.825(sed on slo)390.11 717.6 R 4.325(wn)
+-.25 G(etw)450.055 717.6 Q 1.825(ork links.)-.1 F EP
+%%Page: 44 39
+%%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/F1 10/Times-Roman@0 SF
+(Priority ordering is the def)174 96 Q(ault.)-.1 E(Resolv)102 112.2 Q
+(erOptions=)-.15 E/F2 10/Times-Italic@0 SF(options)A F1 .128([I] Set resolv)174
+124.2 R .127(er options.)-.15 F -1.11(Va)5.127 G .127(lues can be set using)
+1.11 F F0(+)2.627 E F2<8d61>A(g)-.1 E F1 .127(and cleared using)2.627 F F0<ad>
+2.627 E F2<8d61>A(g)-.1 E F1 2.627(;t)C(he)494.56 124.2 Q F2<8d61>174 136.2 Q
+(g)-.1 E F1 5.013(sc)C 2.513(an be \231deb)202.243 136.2 R 2.513
+(ug\232, \231aaonly\232, \231use)-.2 F 2.514
+(vc\232, \231primary\232, \231igntc\232, \231recurse\232, \231def-)-.25 F .867
+(names\232, \231stayopen\232, or \231dnsrch\232.)174 148.2 R .867
+(The string \231HasW)5.867 F .867(ildcardMX\232 \(without a)-.4 F F0(+)3.367 E
+F1(or)3.367 E F0<ad>174 160.2 Q F1 3.82(\)c)C 1.32
+(an be speci\214ed to turn of)191.29 160.2 R 3.82(fm)-.25 G 1.32(atching ag)
+311.72 160.2 R 1.32(ainst MX records when doing name)-.05 F(canoni\214cations.)
+174 172.2 Q F0(N.B.)5.918 E F1 .917
+(Prior to 8.7, this option indicated that the name serv)5.918 F .917(er be)-.15
+F 1.025(responding in order to accept addresses.)174 184.2 R 1.025
+(This has been replaced by checking to)6.025 F .078(see if the \231dns\232 met\
+hod is listed in the service switch entry for the \231hosts\232 service.)174
+196.2 R(SmtpGreetingMessage=)102 212.4 Q F2(messa)A -.1(ge)-.1 G F1 .344
+([$e macro] The message printed when the SMTP serv)174 224.4 R .345
+(er starts up.)-.15 F(Def)5.345 E .345(aults to \231$j)-.1 F
+(Sendmail $v ready at $b\232.)174 236.4 Q -.35(Ti)102 252.6 S(meout.).35 E F2
+(type)A F1(=)A F2(timeout)1.666 E F1 .297
+([r; subsumes old T option as well] Set timeout v)174 264.6 R 2.796(alues. The)
+-.25 F .296(actual timeout is indi-)2.796 F 1.678(cated by the)174 276.6 R F2
+(type)4.178 E F1 6.678(.T)C 1.678(he recognized timeouts and their def)261.802
+276.6 R 1.679(ault v)-.1 F 1.679(alues, and their)-.25 F(minimum v)174 288.6 Q
+(alues speci\214ed in RFC 1123 section 5.3.2 are:)-.25 E 23.6(initial w)214
+304.8 R(ait for initial greeting message [5m, 5m])-.1 E 29.72(helo reply)214
+316.8 R(to HELO or EHLO command [5m, none])2.5 E 29.16(mail reply)214 328.8 R
+(to MAIL command [10m, 5m])2.5 E 31.39(rcpt reply)214 340.8 R
+(to RCPT command [1h, 5m])2.5 E 16.94(datainit reply)214 352.8 R(to D)2.5 E
+-1.21 -1.11(AT A)-.4 H(command [5m, 2m])3.61 E 8.06(datablock data)214 364.8 R
+(block read [1h, 3m])2.5 E 12.5(data\214nal reply)214 376.8 R(to \214nal `)2.5
+E(`.)-.74 E 1.48 -.74('' i)-.7 H 2.5(nd).74 G(ata [1h, 10m])348.47 376.8 Q 32.5
+(rset reply)214 388.8 R(to RSET command [5m, none])2.5 E 31.38(quit reply)214
+400.8 R(to Q)2.5 E(UIT command [2m, none])-.1 E 28.05(misc reply)214 412.8 R
+(to NOOP and VERB commands [2m, none])2.5 E 26.94(ident IDENT)214 424.8 R
+(protocol timeout [30s, none])2.5 E 9.72(\214leopen\207 timeout)214 436.8 R
+(on opening .forw)2.5 E(ard and :include: \214les [60s, none])-.1 E 2.5
+(command\207 command)214 448.8 R(read [1h, 5m])2.5 E(queuereturn\207ho)214
+460.8 Q 2.5(wl)-.25 G(ong until a message is returned [5d, 5d])289.01 460.8 Q
+(queue)214 472.8 Q -.1(wa)-.25 G -1.58(rn\207 ho).1 F 2.5(wl)-.25 G
+(ong until a w)285.69 472.8 Q(arning is sent [none, none])-.1 E .893(All b)174
+489 R .893(ut those mark)-.2 F .893
+(ed with a dagger \(\207\) apply to client SMTP)-.1 F 5.892(.I)-1.11 G 3.392
+(ft)437.724 489 S .892(he message is)447.226 489 R .273(submitted using the)174
+501 R/F3 9/Times-Roman@0 SF(NO)2.773 E .523(TIFY SMTP)-.36 F F1 -.15(ex)2.773 G
+.273(tension, w).15 F .274(arning messages will only be sent)-.1 F(if)174 513 Q
+F3(NO)3.038 E(TIFY=DELA)-.36 E(Y)-.945 E F1 .538(is speci\214ed.)3.038 F .537
+(The queuereturn and queue)5.537 F -.1(wa)-.25 G .537(rn timeouts can be).1 F
+1.234(further quali\214ed with a tag based on the Precedence: \214eld in the m\
+essage; the)174 525 R(y)-.15 E 1.9(must be one of \231ur)174 537 R 1.9
+(gent\232 \(indicating a positi)-.18 F 2.2 -.15(ve n)-.25 H 1.9
+(on-zero precedence\) \231normal\232).15 F .251
+(\(indicating a zero precedence\), or \231non-ur)174 549 R .251
+(gent\232 \(indicating ne)-.18 F -.05(ga)-.15 G(ti).05 E .552 -.15(ve p)-.25 H
+(recedences\).).15 E -.15(Fo)174 561 S 4.423(re).15 G 1.923
+(xample, setting \231T)196.453 561 R(imeout.queue)-.35 E -.1(wa)-.25 G(rn.ur).1
+E 1.923(gent=1h\232 sets the w)-.18 F 1.922(arning timeout)-.1 F .222(for ur)
+174 573 R .223(gent messages only to one hour)-.18 F 5.223(.T)-.55 G .223
+(he def)336.749 573 R .223(ault if no precedence is indicated is)-.1 F
+(to set the timeout for all precedences.)174 585 Q(RecipientF)102 601.2 Q
+(actor=)-.15 E F2(fact)A F1 .638([y] The indicated)174 613.2 R F2(fact)3.137 E
+F1 .637(or is added to the priority \(thus)B F2(lowering)3.137 E F1 .637
+(the priority of the)3.137 F .23(job\) for each recipient, i.e., this v)174
+625.2 R .231(alue penalizes jobs with lar)-.25 F .231(ge numbers of recipi-)
+-.18 F 2.5(ents. Def)174 637.2 R(aults to 30000.)-.1 E(RefuseLA=)102 653.4 Q F2
+(LA)A F1 1.012([X] When the system load a)174 653.4 R -.15(ve)-.2 G 1.012
+(rage e).15 F(xceeds)-.15 E F2(LA)3.512 E F1 3.512(,r)C 1.011
+(efuse incoming SMTP connec-)376.816 653.4 R 2.5(tions. Def)174 665.4 R
+(aults to 12.)-.1 E(RetryF)102 681.6 Q(actor=)-.15 E F2(fact)A F1 .771([Z] The)
+3.74 F F2(fact)3.271 E F1 .771(or is added to the priority e)B -.15(ve)-.25 G
+.772(ry time a job is processed.).15 F .772(Thus, each)5.772 F .994
+(time a job is processed, its priority will be decreased by the indicated v)174
+693.6 R 3.493(alue. In)-.25 F 1.107(most en)174 705.6 R 1.107
+(vironments this should be positi)-.4 F -.15(ve)-.25 G 3.608(,s).15 G 1.108
+(ince hosts that are do)357.354 705.6 R 1.108(wn are all too)-.25 F(often do)
+174 717.6 Q(wn for a long time.)-.25 E(Def)5 E(aults to 90000.)-.1 E EP
+%%Page: 45 40
+%%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(Sa)102 96 Q -.15(ve)-.2 G 10.41
+(FromLine [f]).15 F(Sa)4.909 E 2.709 -.15(ve U)-.2 H 2.408
+(nix-style \231From\232 lines at the front of headers.).15 F 2.408
+(Normally the)7.408 F 4.908(ya)-.15 G(re)496.23 96 Q
+(assumed redundant and discarded.)174 108 Q(SendMIMEErrors)102 124.2 Q .815
+([j] If set, send error messages in MIME format \(see RFC1521 and RFC1344 for)
+174 136.2 R(details\).)174 148.2 Q(ServiceSwitchFile=)102 164.4 Q/F2 10
+/Times-Italic@0 SF(\214lename)A F1 1.533([no short name] If your host operatin\
+g system has a service switch abstraction)174 176.4 R .003(\(e.g., /etc/nsswit\
+ch.conf on Solaris or /etc/svc.conf on Ultrix and DEC OSF/1\) that)174 188.4 R
+.814(service will be consulted and this option is ignored.)174 200.4 R .814
+(Otherwise, this is the name)5.814 F 1.082(of a \214le that pro)174 212.4 R
+1.082(vides the list of methods used to implement particular services.)-.15 F
+1.069(The syntax is a series of lines, each of which is a sequence of w)174
+224.4 R 3.569(ords. The)-.1 F(\214rst)3.569 E -.1(wo)174 236.4 S 1.363
+(rd is the service name, and follo).1 F 1.363(wing w)-.25 F 1.364
+(ords are service types.)-.1 F 1.364(The services)6.364 F(that)174 248.4 Q F2
+(sendmail)4.11 E F1 1.61(consults directly are \231aliases\232 and \231hosts.)
+4.11 F 6.61<9a53>-.7 G 1.61(ervice types can be)422.81 248.4 R 1.754
+(\231dns\232, \231nis\232, \231nisplus\232, or \231\214les\232 \(with the ca)
+174 260.4 R -.15(ve)-.2 G 1.755(at that the appropriate support).15 F .791
+(must be compiled in before the service can be referenced\).)174 272.4 R .79
+(If ServiceSwitchFile)5.791 F 1.303(is not speci\214ed, it def)174 284.4 R
+1.303(aults to /etc/service.switch.)-.1 F 1.303(If that \214le does not e)6.303
+F 1.304(xist, the)-.15 F(def)174 296.4 Q(ault switch is:)-.1 E 20.28
+(aliases \214les)214 312.6 R 26.38(hosts dns)214 324.6 R(nis \214les)2.5 E
+(The def)174 340.8 Q(ault \214le is \231/etc/service.switch\232.)-.1 E(Se)102
+357 Q -.15(ve)-.25 G 12.12(nBitInput [7]).15 F .322(Strip input to se)2.822 F
+-.15(ve)-.25 G 2.822(nb).15 G .321(its for compatibility with old systems.)
+274.93 357 R .321(This shouldn')5.321 F 2.821(tb)-.18 G(e)499.56 357 Q
+(necessary)174 369 Q(.)-.65 E(StatusFile=)102 385.2 Q F2(\214le)A F1 .299
+([S] Log summary statistics in the named)174 385.2 R F2(\214le)2.799 E F1 5.299
+(.I)C 2.799(fn)363.602 385.2 S .3(ot set, no summary statistics are)374.731
+385.2 R(sa)174 397.2 Q -.15(ve)-.2 G 3.775(d. This).15 F 1.275
+(\214le does not gro)3.775 F 3.775(wi)-.25 G 3.775(ns)308.82 397.2 S 3.775
+(ize. It)321.485 397.2 R 1.275(can be printed using the)3.775 F F2(mailstats)
+3.775 E F1(\(8\))A(program.)174 409.2 Q 28.4(SuperSafe [s])102 425.4 R .372
+(Be super)2.872 F .372(-safe when running things, i.e., al)-.2 F -.1(wa)-.1 G
+.373(ys instantiate the queue \214le, e).1 F -.15(ve)-.25 G(n).15 E .697
+(if you are going to attempt immediate deli)174 437.4 R -.15(ve)-.25 G(ry).15 E
+(.)-.65 E F2(Sendmail)5.697 E F1(al)3.197 E -.1(wa)-.1 G .697
+(ys instantiates the).1 F 2.688
+(queue \214le before returning control the client under an)174 449.4 R 5.188
+(yc)-.15 G 5.188(ircumstances. This)423.822 449.4 R(should really)174 461.4 Q
+F2(always)2.5 E F1(be set.)2.5 E -.7(Te)102 477.6 S(mpFileMode=).7 E F2(mode)A
+F1 .332([F] The \214le mode for queue \214les.)174 489.6 R .331
+(It is interpreted in octal by def)5.331 F 2.831(ault. Def)-.1 F .331(aults to)
+-.1 F(0600.)174 501.6 Q -.35(Ti)102 517.8 S(meZoneSpec=).35 E F2(tzinfo)A F1
+.218([t] Set the local time zone info to)174 529.8 R F2(tzinfo)2.718 E F1 2.718
+<8a66>2.718 G .218(or e)351.168 529.8 R .218(xample, \231PST8PDT\232.)-.15 F
+(Actually)5.218 E 2.718(,i)-.65 G(f)500.67 529.8 Q 1.346
+(this is not set, the TZ en)174 541.8 R 1.346(vironment v)-.4 F 1.346
+(ariable is cleared \(so the system def)-.25 F 1.345(ault is)-.1 F .208
+(used\); if set b)174 553.8 R .208(ut null, the user')-.2 F 2.708(sT)-.55 G
+2.708(Zv)306.916 553.8 S .208(ariable is used, and if set and non-null the TZ)
+320.484 553.8 R -.25(va)174 565.8 S(riable is set to this v).25 E(alue.)-.25 E
+-.35(Tr)102 582 S 5.96(yNullMXList [w]).35 F .114
+(If this system is the \231best\232 \(that is, lo)2.614 F .114
+(west preference\) MX for a gi)-.25 F -.15(ve)-.25 G 2.613(nh).15 G .113
+(ost, its)477.767 582 R 1.168(con\214guration rules should normally detect thi\
+s situation and treat that condition)174 594 R .258(specially by forw)174 606 R
+.258(arding the mail to a UUCP feed, treating it as local, or whate)-.1 F -.15
+(ve)-.25 G -.55(r.).15 G(Ho)174 618 Q(we)-.25 E -.15(ve)-.25 G 1.685 -.4(r, i)
+.15 H 3.385(ns).4 G .886(ome cases \(such as Internet \214re)230.54 618 R -.1
+(wa)-.25 G .886(lls\) you may w).1 F .886(ant to try to con-)-.1 F .07
+(nect directly to that host as though it had no MX records at all.)174 630 R
+.07(Setting this option)5.07 F(causes)174 642 Q F2(sendmail)3.013 E F1 .514
+(to try this.)3.013 F .514(The do)5.514 F .514
+(wnside is that errors in your con\214guration are)-.25 F(lik)174 654 Q 2.116
+(ely to be diagnosed as \231host unkno)-.1 F 2.116
+(wn\232 or \231message timed out\232 instead of)-.25 F
+(something more meaningful.)174 666 Q(This option is disrecommended.)5 E
+(UnixFromLine=)102 682.2 Q F2(fr)A(omline)-.45 E F1 .236
+([$l macro] De\214nes the format used when)174 694.2 R F2(sendmail)2.736 E F1
+.236(must add a UNIX-style From_)2.736 F 1.325(line \(that is, a line be)174
+706.2 R 1.325(ginning \231From<space>user\232\).)-.15 F(Def)6.324 E 1.324
+(aults to \231From $g)-.1 F($d\232.)6.324 E(Don')174 718.2 Q 2.645(tc)-.18 G
+.146(hange this unless your system uses a dif)204.235 718.2 R .146
+(ferent UNIX mailbox format \(v)-.25 F(ery)-.15 E EP
+%%Page: 46 41
+%%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(unlik)174 96 Q
+(ely\).)-.1 E(UseErrorsT)102 112.2 Q 21.15(o[)-.8 G .826
+(l] If there is an \231Errors-T)177.33 112.2 R .826(o:\232 header)-.8 F 3.326
+(,s)-.4 G .826(end error messages to the addresses listed)332.414 112.2 R 3.134
+(there. The)174 124.2 R 3.134(yn)-.15 G .634(ormally go to the en)230.658 124.2
+R -.15(ve)-.4 G .635(lope sender).15 F 5.635(.U)-.55 G .635
+(se of this option causes)383.895 124.2 R/F2 10/Times-Italic@0 SF(send-)3.135 E
+(mail)174 136.2 Q F1(to violate RFC 1123.)2.5 E
+(This option is disrecommended and deprecated.)5 E(UserDatabaseSpec=)102 152.4
+Q F2(udbspec)A F1([U] The user database speci\214cation.)174 164.4 Q -1.11(Ve)
+102 180.6 S 37.29(rbose [v])1.11 F .561(Run in v)3.061 F .561(erbose mode.)-.15
+F .561(If this is set,)5.561 F F2(sendmail)3.061 E F1 .56(adjusts options)3.061
+F F0(HoldExpensi)3.06 E -.1(ve)-.1 G F1(\(old)174 192.6 Q F0(c)2.635 E F1 2.635
+(\)a)C(nd)207.59 192.6 Q F0(Deli)2.635 E -.1(ve)-.1 G(ryMode).1 E F1(\(old)
+2.635 E F0(d)2.635 E F1 2.635(\)s)C 2.635(ot)317.36 192.6 S .135
+(hat all mail is deli)327.775 192.6 R -.15(ve)-.25 G .136
+(red completely in a sin-).15 F 1.244
+(gle job so that you can see the entire deli)174 204.6 R -.15(ve)-.25 G 1.244
+(ry process.).15 F(Option)6.244 E F0 -1(Ve)3.743 G(rbose)1 E F1(should)3.743 E
+F2(ne)174 216.6 Q(ver)-.15 E F1(be set in the con\214guration \214le; it is in\
+tended for command line use only)2.5 E(.)-.65 E .108(All options can be speci\
+\214ed on the command line using the \255O or \255o \215ag, b)102 232.8 R .109
+(ut most will cause)-.2 F F2(send-)2.609 E(mail)102 244.8 Q F1 1.135
+(to relinquish its setuid permissions.)3.635 F 1.135
+(The options that will not cause this are MinFreeBlocks)6.135 F .513([b], Deli)
+102 256.8 R -.15(ve)-.25 G .513
+(ryMode [d], ErrorMode [e], IgnoreDots [i], LogLe).15 F -.15(ve)-.25 G 3.014
+(l[).15 G .514(L], MeT)369.118 256.8 R .514(oo [m], OldStyleHeaders)-.8 F .53
+([o], Pri)102 268.8 R -.25(va)-.25 G -.15(cy).25 G .53(Options [p], T).15 F .53
+(imeouts [r], SuperSafe [s], V)-.35 F .53(erbose [v], CheckpointInterv)-1.11 F
+.53(al [C], and Se)-.25 F(v-)-.25 E(enBitInput [7].)102 280.8 Q(Also, M \(de\
+\214ne macro\) when de\214ning the r or s macros is also considered \231safe\
+\232.)5 E F0 2.5(5.7. P)87 304.8 R 2.5<8a50>2.5 G -.18(re)134.22 304.8 S
+(cedence De\214nitions).18 E F1 -1.11(Va)127 321 S .164
+(lues for the \231Precedence:\232 \214eld may be de\214ned using the)1.11 F F0
+(P)2.664 E F1 .164(control line.)2.664 F .164(The syntax of this)5.164 F
+(\214eld is:)102 333 Q F0(P)142 349.2 Q F2(name)A F0(=)A F2(num)A F1 .384
+(When the)102 365.4 R F2(name)2.884 E F1 .384
+(is found in a \231Precedence:\232 \214eld, the message class is set to)2.884 F
+F2(num)2.883 E F1 5.383(.H)C .383(igher numbers)446.127 365.4 R .85
+(mean higher precedence.)102 377.4 R .85(Numbers less than zero ha)5.85 F 1.15
+-.15(ve t)-.2 H .85(he special property that if an error occurs).15 F 1.551
+(during processing the body of the message will not be returned; this is e)102
+389.4 R 1.551(xpected to be used for)-.15 F<9962>102 401.4 Q .461
+(ulk\232 mail such as through mailing lists.)-.2 F .461(The def)5.461 F .461
+(ault precedence is zero.)-.1 F -.15(Fo)5.461 G 2.962(re).15 G .462
+(xample, our list of)429.284 401.4 R(precedences is:)102 413.4 Q
+(P\214rst-class=0)142 429.6 Q(Pspecial-deli)142 441.6 Q -.15(ve)-.25 G(ry=100)
+.15 E(Plist=\25530)142 453.6 Q(Pb)142 465.6 Q(ulk=\25560)-.2 E(Pjunk=\255100)
+142 477.6 Q 1.059(People writing mailing list e)102 493.8 R 1.058
+(xploders are encouraged to use \231Precedence: list\232.)-.15 F 1.058(Older v)
+6.058 F 1.058(ersions of)-.15 F F2(sendmail)102 505.8 Q F1 1.19
+(\(which discarded all error returns for ne)3.69 F -.05(ga)-.15 G(ti).05 E 1.49
+-.15(ve p)-.25 H 1.19(recedences\) didn').15 F 3.69(tr)-.18 G 1.19
+(ecognize this name,)422.47 505.8 R(gi)102 517.8 Q .599(ving it a def)-.25 F
+.598(ault precedence of zero.)-.1 F .598(This allo)5.598 F .598
+(ws list maintainers to see error returns on both old)-.25 F(and ne)102 529.8 Q
+2.5(wv)-.25 G(ersions of)142.7 529.8 Q F2(sendmail)2.5 E F1(.)A F0 2.5(5.8. V)
+87 553.8 R 2.5<8a43>2.5 G(on\214guration V)136.44 553.8 Q(ersion Le)-1 E -.1
+(ve)-.15 G(l).1 E F1 3.181 -.8(To p)127 570 T(ro).8 E 1.581
+(vide compatibility with old con\214guration \214les, the)-.15 F F0(V)4.081 E
+F1 1.582(line has been added to de\214ne)4.082 F 1.11(some v)102 582 R 1.11
+(ery basic semantics of the con\214guration \214le.)-.15 F 1.11
+(These are not intended to be long term sup-)6.11 F .033(ports; rather)102 594
+R 2.533(,t)-.4 G(he)158.046 594 Q 2.533(yd)-.15 G .033
+(escribe compatibility features which will probably be remo)179.869 594 R -.15
+(ve)-.15 G 2.533(di).15 G 2.533(nf)435.903 594 S .034(uture releases.)446.766
+594 R F0(N.B.:)127 610.2 Q F1 .197(these v)2.697 F(ersion)-.15 E F2(le)2.697 E
+(vels)-.15 E F1(ha)2.697 E .496 -.15(ve n)-.2 H .196(othing to do with the v)
+.15 F(ersion)-.15 E F2(number)2.696 E F1 .196(on the \214les.)2.696 F -.15(Fo)
+5.196 G 2.696(re).15 G(xam-)483.45 610.2 Q(ple, as of this writing v)102 622.2
+Q(ersion 8 con\214g \214les \(speci\214cally)-.15 E 2.5(,8)-.65 G(.7\) used v)
+333.41 622.2 Q(ersion le)-.15 E -.15(ve)-.25 G 2.5(l6c).15 G(on\214gurations.)
+432.84 622.2 Q 1.102(\231Old\232 con\214guration \214les are de\214ned as v)127
+638.4 R 1.102(ersion le)-.15 F -.15(ve)-.25 G 3.602(lo).15 G 3.602(ne. V)
+353.006 638.4 R 1.102(ersion le)-1.11 F -.15(ve)-.25 G 3.602(lt).15 G 1.302 -.1
+(wo \214)430.622 638.4 T 1.103(les mak).1 F 3.603(et)-.1 G(he)494.56 638.4 Q
+(follo)102 650.4 Q(wing changes:)-.25 E 12.5(\(1\) Host)107 666.6 R .727(name \
+canoni\214cation \($[ ... $]\) appends a dot if the name is recognized; this g\
+i)3.227 F -.15(ve)-.25 G 3.226(st).15 G(he)494.56 666.6 Q 1.974
+(con\214g \214le a w)133.66 678.6 R 1.974(ay of \214nding out if an)-.1 F 1.974
+(ything matched.)-.15 F(\(Actually)6.974 E 4.475(,t)-.65 G 1.975
+(his just initializes the)413.345 678.6 R .739
+(\231host\232 map with the \231\255a.)133.66 690.6 R 5.739<9a8d>-.7 G .739
+(ag \212 you can reset it to an)251.445 690.6 R .738
+(ything you prefer by declaring the)-.15 F(map e)133.66 702.6 Q(xplicitly)-.15
+E(.\))-.65 E EP
+%%Page: 47 42
+%%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 12.5(\(2\) Def)107 96 R .384
+(ault host name e)-.1 F .385(xtension is consistent throughout processing; v)
+-.15 F .385(ersion le)-.15 F -.15(ve)-.25 G 2.885(lo).15 G .385(ne con\214gu-)
+458.345 96 R .83(rations turned of)133.66 108 R 3.33(fd)-.25 G .83(omain e)
+212.83 108 R .83
+(xtension \(that is, adding the local domain name\) during certain)-.15 F .4
+(points in processing.)133.66 120 R -1.11(Ve)5.4 G .4(rsion le)1.11 F -.15(ve)
+-.25 G 2.9(lt).15 G .6 -.1(wo c)280.53 120 T .4(on\214gurations are e).1 F .4
+(xpected to include a trailing dot)-.15 F
+(to indicate that the name is already canonical.)133.66 132 Q 12.5(\(3\) Local)
+107 148.2 R .072(names that are not aliases are passed through a ne)2.572 F
+2.572(wd)-.25 G .072(istinguished ruleset \214v)372.752 148.2 R .072
+(e; this can)-.15 F 1.426(be used to append a local relay)133.66 160.2 R 6.426
+(.T)-.65 G 1.426(his beha)279.902 160.2 R 1.426(viour can be pre)-.2 F -.15(ve)
+-.25 G 1.426(nted by resolving the local).15 F .209(name with an initial `@'.)
+133.66 172.2 R .209(That is, something that resolv)5.209 F .209
+(es to a local mailer and a user name)-.15 F 1.072
+(of \231vikki\232 will be passed through ruleset \214v)133.66 184.2 R 1.072
+(e, b)-.15 F 1.073(ut a user name of \231@vikki\232 will ha)-.2 F 1.373 -.15
+(ve t)-.2 H(he).15 E .417
+(`@' stripped, will not be passed through ruleset \214v)133.66 196.2 R .417
+(e, b)-.15 F .416(ut will otherwise be treated the same)-.2 F 1.702
+(as the prior e)133.66 208.2 R 4.202(xample. The)-.15 F -.15(ex)4.202 G 1.703
+(pectation is that this might be used to implement a polic).15 F(y)-.15 E .136
+(where mail sent to \231vikki\232 w)133.66 220.2 R .135
+(as handled by a central hub, b)-.1 F .135
+(ut mail sent to \231vikki@localhost\232)-.2 F -.1(wa)133.66 232.2 S 2.5(sd).1
+G(eli)156.61 232.2 Q -.15(ve)-.25 G(red directly).15 E(.)-.65 E -1.11(Ve)127
+248.4 S 1.382(rsion le)1.11 F -.15(ve)-.25 G 3.882(lt).15 G 1.382
+(hree \214les allo)187.134 248.4 R 3.882(w#i)-.25 G 1.382
+(nitiated comments on all lines.)266.292 248.4 R 1.383
+(Exceptions are backslash)6.383 F(escaped # marks and the $# syntax.)102 260.4
+Q -1.11(Ve)127 276.6 S 1.208(rsion le)1.11 F -.15(ve)-.25 G 3.708(lf).15 G
+1.208(our con\214gurations are completely equi)187.336 276.6 R -.25(va)-.25 G
+1.207(lent to le).25 F -.15(ve)-.25 G 3.707(lt).15 G 1.207
+(hree for historical rea-)411.249 276.6 R(sons.)102 288.6 Q -1.11(Ve)127 304.8
+S 1.234(rsion le)1.11 F -.15(ve)-.25 G 3.734<6c8c>.15 G 1.534 -.15(ve c)189.618
+304.8 T 1.234(on\214guration \214les change the def).15 F 1.234
+(ault de\214nition of)-.1 F F0($w)3.734 E F1 1.234(to be just the \214rst)3.734
+F(component of the hostname.)102 316.8 Q -1.11(Ve)127 333 S 1.589(rsion le)1.11
+F -.15(ve)-.25 G 4.089(ls).15 G 1.589(ix con\214guration \214les change man)
+188.658 333 R 4.088(yo)-.15 G 4.088(ft)342.272 333 S 1.588
+(he local processing options \(such as)352.47 333 R .48
+(aliasing and matching the be)102 345 R .481
+(ginning of the address for `|' characters\) to be mailer \215ags; this allo)
+-.15 F(ws)-.25 E 1.345(\214ne-grained control o)102 357 R -.15(ve)-.15 G 3.845
+(rt).15 G 1.345(he special local processing.)210.435 357 R(Le)6.345 E -.15(ve)
+-.25 G 3.845(ls).15 G 1.344(ix con\214guration \214les may also use)360.34 357
+R 1.221(long option names.)102 369 R(The)6.221 E F0(ColonOkInAddr)3.721 E F1
+1.221(option \(to allo)3.721 F 3.722(wc)-.25 G 1.222
+(olons in the local-part of addresses\))355.42 369 R(def)102 381 Q(aults)-.1 E
+F0(on)3.44 E F1 .94(for lo)3.44 F .94(wer numbered con\214guration \214les; th\
+e con\214guration \214le requires some additional)-.25 F
+(intelligence to properly handle the RFC 822 group construct.)102 393 Q(The)127
+409.2 Q F0(V)2.677 E F1 .177(line may ha)2.677 F .477 -.15(ve a)-.2 H 2.677(no)
+.15 G(ptional)231.022 409.2 Q F0(/)2.677 E/F2 10/Times-Italic@0 SF(vendor)A F1
+.178(to indicate that this con\214guration \214le uses modi\214ca-)2.677 F .865
+(tions speci\214c to a particular v)102 423.2 R(endor)-.15 E/F3 7/Times-Roman@0
+SF(19)246.986 419.2 Q F1 5.866(.Y)253.986 423.2 S .866(ou may use \231/Berk)
+268.472 423.2 R(ele)-.1 E .866(y\232 to emphasize that this con\214gura-)-.15 F
+(tion \214le uses the Berk)102 435.2 Q(ele)-.1 E 2.5(yd)-.15 G(ialect of)213.13
+435.2 Q F2(sendmail)2.5 E F1(.)A F0 2.5(5.9. K)87 459.2 R 2.5<8a4b>2.5 G
+(ey File Declaration)137.31 459.2 Q F1
+(Special maps can be de\214ned using the line:)127 475.4 Q
+(Kmapname mapclass ar)142 491.6 Q(guments)-.18 E(The)102 507.8 Q F2(mapname)
+2.751 E F1 .251(is the handle by which this map is referenced in the re)2.751 F
+.25(writing rules.)-.25 F(The)5.25 E F2(mapclass)2.75 E F1(is)2.75 E 1.889
+(the name of a type of map; these are compiled in to)102 519.8 R F2(sendmail)
+4.389 E F1 6.889(.T)C(he)384.013 519.8 Q F2(ar)4.389 E(guments)-.37 E F1 1.889
+(are interpreted)4.389 F .791(depending on the class; typically)102 531.8 R
+3.291(,t)-.65 G .791(here w)244.185 531.8 R .791(ould be a single ar)-.1 F .79
+(gument naming the \214le containing the)-.18 F(map.)102 543.8 Q
+(Maps are referenced using the syntax:)127 560 Q($\()142 576.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 .64(where either or both of the)102 592.4 R F2(ar)3.14 E
+(guments)-.37 E F1(or)3.141 E F2(default)3.141 E F1 .641
+(portion may be omitted.)3.141 F(The)5.641 E F2 .641($@ ar)3.141 F(guments)-.37
+E F1(may)3.141 E 1.277(appear more than once.)102 604.4 R 1.277(The indicated)
+6.277 F F2 -.1(ke)3.777 G(y)-.2 E F1(and)3.776 E F2(ar)3.776 E(guments)-.37 E
+F1 1.276(are passed to the appropriate mapping)3.776 F 3.253(function. If)102
+616.4 R .753(it returns a v)3.253 F .753(alue, it replaces the input.)-.25 F
+.753(If it does not return a v)5.753 F .753(alue and the)-.25 F F2(default)
+3.253 E F1(is)3.253 E(speci\214ed, the)102 628.4 Q F2(default)2.5 E F1
+(replaces the input.)2.5 E(Otherwise, the input is unchanged.)5 E 1.042
+(During replacement of either a map v)127 644.6 R 1.042(alue or def)-.25 F
+1.042(ault the string \231%)-.1 F F2(n)A F1 3.542<9a28>C(where)417.414 644.6 Q
+F2(n)3.542 E F1 1.041(is a digit\) is)3.541 F .481
+(replaced by the corresponding)102 656.6 R F2(ar)2.981 E(gument)-.37 E F1 5.481
+(.A)C -.18(rg)280.385 656.6 S .482(ument zero is al).18 F -.1(wa)-.1 G .482
+(ys the database k).1 F -.15(ey)-.1 G 5.482(.F)-.5 G .482(or e)456.458 656.6 R
+(xample,)-.15 E(the rule)102 668.6 Q .32 LW 76 678.2 72 678.2 DL 80 678.2 76
+678.2 DL 84 678.2 80 678.2 DL 88 678.2 84 678.2 DL 92 678.2 88 678.2 DL 96
+678.2 92 678.2 DL 100 678.2 96 678.2 DL 104 678.2 100 678.2 DL 108 678.2 104
+678.2 DL 112 678.2 108 678.2 DL 116 678.2 112 678.2 DL 120 678.2 116 678.2 DL
+124 678.2 120 678.2 DL 128 678.2 124 678.2 DL 132 678.2 128 678.2 DL 136 678.2
+132 678.2 DL 140 678.2 136 678.2 DL 144 678.2 140 678.2 DL 148 678.2 144 678.2
+DL 152 678.2 148 678.2 DL 156 678.2 152 678.2 DL 160 678.2 156 678.2 DL 164
+678.2 160 678.2 DL 168 678.2 164 678.2 DL 172 678.2 168 678.2 DL 176 678.2 172
+678.2 DL 180 678.2 176 678.2 DL 184 678.2 180 678.2 DL 188 678.2 184 678.2 DL
+192 678.2 188 678.2 DL 196 678.2 192 678.2 DL 200 678.2 196 678.2 DL 204 678.2
+200 678.2 DL 208 678.2 204 678.2 DL 212 678.2 208 678.2 DL 216 678.2 212 678.2
+DL/F4 5/Times-Roman@0 SF(19)93.6 688.6 Q/F5 8/Times-Roman@0 SF .214
+(And of course, v)3.2 J .214(endors are encouraged to add themselv)-.12 F .214
+(es to the list of recognized v)-.12 F .214(endors by editing the routine)-.12
+F/F6 8/Times-Italic@0 SF(setvendor)2.214 E F5(in)2.214 E F6(conf)72 701.4 Q(.c)
+-.12 E F5 4(.P)C(lease send e-mail to sendmail@CS.Berk)101.656 701.4 Q(ele)-.08
+E -.52(y.)-.12 G(EDU to re).52 E(gister your v)-.12 E(endor dialect.)-.12 E EP
+%%Page: 48 43
+%%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(R$\255 ! $+)142
+96 Q($: $\(uucp $1 $@ $2 $: %1 @ %0 . UUCP $\))250 96 Q 1.269(Looks up the UUC\
+P name in a \(user de\214ned\) UUCP map; if not found it turns it into \231.UU\
+CP\232)102 112.2 R 2.5(form. The)102 124.2 R
+(database might contain records lik)2.5 E(e:)-.1 E(decv)142 140.4 Q 77.43
+(ax %1@%0.DEC.COM)-.25 F 72.19(research %1@%0.A)142 152.4 R(TT)-1.11 E(.COM)
+-.74 E .741(The b)127 172.8 R .741(uilt in map with both name and class \231ho\
+st\232 is the host name canonicalization lookup.)-.2 F(Thus, the syntax:)102
+184.8 Q($\(host)142 201 Q/F2 10/Times-Italic@0 SF(hostname)2.5 E F1($\))A
+(is equi)102 217.2 Q -.25(va)-.25 G(lent to:).25 E($[)142 233.4 Q F2(hostname)A
+F1($])A(There are man)127 253.8 Q 2.5(yd)-.15 G(e\214ned classes.)197.1 253.8 Q
+51.72(dbm Database)102 270 R 1.623(lookups using the ndbm\(3\) library)4.123 F
+(.)-.65 E F2(Sendmail)6.623 E F1 1.623(must be compiled with)4.123 F F0(NDBM)
+174 282 Q F1(de\214ned.)2.5 E 49.51(btree Database)102 298.2 R 1.284
+(lookups using the btree interf)3.784 F 1.285(ace to the Berk)-.1 F(ele)-.1 E
+3.785(yd)-.15 G 1.285(b\(3\) library)425.99 298.2 R(.)-.65 E F2(Send-)6.285 E
+(mail)174 310.2 Q F1(must be compiled with)2.5 E F0(NEWDB)2.5 E F1(de\214ned.)
+2.5 E 51.17(hash Database)102 326.4 R .122(lookups using the hash interf)2.622
+F .122(ace to the Berk)-.1 F(ele)-.1 E 2.622(yd)-.15 G .121(b\(3\) library)
+413.868 326.4 R(.)-.65 E F2(Sendmail)5.121 E F1(must be compiled with)174 338.4
+Q F0(NEWDB)2.5 E F1(de\214ned.)2.5 E 57.83(nis NIS)102 354.6 R(lookups.)2.5 E
+F2(Sendmail)5 E F1(must be compiled with)2.5 E F0(NIS)2.5 E F1(de\214ned.)2.5 E
+41.16(nisplus NIS+)102 370.8 R(lookups.)3.733 E F2(Sendmail)6.233 E F1 1.233
+(must be compiled with)3.733 F F0(NISPLUS)3.733 E F1 3.733(de\214ned. The)3.733
+F(ar)3.733 E(gu-)-.18 E .495
+(ment is the name of the table to use for lookups, and the)174 382.8 R F0<ad6b>
+2.995 E F1(and)2.995 E F0<ad76>2.995 E F1 .495(\215ags may be)2.995 F
+(used to set the k)174 394.8 Q .3 -.15(ey a)-.1 H(nd v).15 E
+(alue columns respecti)-.25 E -.15(ve)-.25 G(ly).15 E(.)-.65 E 43.39
+(hesiod Hesiod)102 411 R(lookups.)2.5 E F2(Sendmail)5 E F1
+(must be compiled with)2.5 E F0(HESIOD)2.5 E F1(de\214ned.)2.5 E 41.17
+(netinfo NeXT)102 427.2 R(NetInfo lookups.)2.5 E F2(Sendmail)5 E F1
+(must be compiled with)2.5 E F0(NETINFO)2.5 E F1(de\214ned.)2.5 E(te)102 443.4
+Q 54.65(xt T)-.15 F -.15(ex)-.7 G 2.917<748c>.15 G .417(le lookups.)199.957
+443.4 R .417(The format of the te)5.417 F .418(xt \214le is de\214ned by the)
+-.15 F F0<ad6b>2.918 E F1(\(k)2.918 E .718 -.15(ey \214)-.1 H .418(eld num-).15
+F(ber\),)174 455.4 Q F0<ad76>2.5 E F1(\(v)2.5 E(alue \214eld number\), and)-.25
+E F0<ad7a>2.5 E F1(\(\214eld delimiter\) \215ags.)2.5 E 53.39(stab Internal)102
+471.6 R(symbol table lookups.)2.5 E(Used internally for aliasing.)5 E 38.38
+(implicit Really)102 487.8 R .546
+(should be called \231alias\232 \212 this is used to get the def)3.046 F .546
+(ault lookups for alias)-.1 F(\214les, and is the def)174 499.8 Q
+(ault if no class is speci\214ed for alias \214les.)-.1 E 52.84(user Looks)102
+516 R .476(up users using)2.976 F F2 -.1(ge)2.976 G(tpwnam).1 E F1 2.976
+(\(3\). The)B F0<ad76>2.976 E F1 .477(\215ag can be used to specify the name)
+2.976 F .142
+(of the \214eld to return \(although this is normally used only to check the e)
+174 528 R .142(xistence of)-.15 F 2.5(au)174 540 S(ser\).)185.94 540 Q 52.83
+(host Canoni\214es)102 556.2 R .2(host domain names.)2.7 F(Gi)5.2 E -.15(ve)
+-.25 G 2.7(nah).15 G .2(ost name it calls the name serv)343.68 556.2 R .2
+(er to \214nd)-.15 F(the canonical name for that host.)174 568.2 Q 32.85
+(sequence The)102 584.4 R(ar)3.35 E .849
+(guments on the `K' line are a list of maps; the resulting map searches the)
+-.18 F(ar)174 596.4 Q .438
+(gument maps in order until it \214nds a match for the indicated k)-.18 F -.15
+(ey)-.1 G 5.439(.F)-.5 G .439(or e)456.501 596.4 R(xample,)-.15 E(if the k)174
+608.4 Q .3 -.15(ey d)-.1 H(e\214nition is:).15 E(Kmap1 ...)214 624.6 Q
+(Kmap2 ...)214 636.6 Q(Kseqmap sequence map1 map2)214 648.6 Q .968
+(then a lookup ag)174 664.8 R .968
+(ainst \231seqmap\232 \214rst does a lookup in map1.)-.05 F .968
+(If that is found, it)5.968 F(returns immediately)174 676.8 Q 5(.O)-.65 G
+(therwise, the same k)268.34 676.8 Q .3 -.15(ey i)-.1 H 2.5(su).15 G
+(sed for map2.)375.85 676.8 Q 43.39(switch Much)102 693 R(lik)2.8 E 2.8(et)-.1
+G .3(he \231sequence\232 map e)220.61 693 R .301
+(xcept that the order of maps is determined by the)-.15 F .392(service switch.)
+174 705 R .392(The ar)5.392 F .391
+(gument is the name of the service to be look)-.18 F .391(ed up; the v)-.1 F
+(al-)-.25 E 1.492
+(ues from the service switch are appended to the map name to create ne)174 717
+R 3.993(wm)-.25 G(ap)494.56 717 Q EP
+%%Page: 49 44
+%%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 10/Times-Roman@0 SF 2.5(names. F)174 96 R(or e)-.15 E
+(xample, consider the k)-.15 E .3 -.15(ey d)-.1 H(e\214nition:).15 E
+(Kali switch aliases)214 112.2 Q(together with the service switch entry:)174
+128.4 Q 78.84(aliases nis)214 144.6 R(\214les)2.5 E 1.633
+(This causes a query ag)174 160.8 R 1.633
+(ainst the map \231ali\232 to search maps named \231ali.nis\232 and)-.05 F
+(\231ali.\214les\232 in that order)174 172.8 Q(.)-.55 E 37.84(dequote Strip)102
+189 R .96(double quotes \("\) from a name.)3.46 F .961
+(It does not strip backslashes, and will not)5.961 F .173
+(strip quotes if the resulting string w)174 201 R .172
+(ould contain unscannable syntax \(that is, basic)-.1 F .386(errors lik)174 213
+R 2.886(eu)-.1 G .386(nbalanced angle brack)222.992 213 R .386
+(ets; more sophisticated errors such as unkno)-.1 F(wn)-.25 E .252
+(hosts are not check)174 225 R 2.752(ed\). The)-.1 F .251
+(intent is for use when trying to accept mail from sys-)2.752 F
+(tems such as DECnet that routinely quote odd syntax such as)174 237 Q
+("49ers::ubell")214 253.2 Q 2.5(At)174 269.4 S
+(ypical usage is probably something lik)186.5 269.4 Q(e:)-.1 E
+(Kdequote dequote)214 285.6 Q(...)214 309.6 Q 88.19(R$\255 $:)214 333.6 R
+($\(dequote $1 $\))2.5 E(R$\255 $+)214 345.6 Q($: $>3 $1 $2)322 345.6 Q
+(Care must be tak)174 361.8 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")
+214 378 Q 1.31(will ha)174 394.2 R 1.61 -.15(ve q)-.2 H 1.31(uotes stripped, b)
+.15 F 1.31(ut the result is probably not what you had in mind.)-.2 F -.15(Fo)
+174 406.2 S(rtunately these cases are rare.).15 E .488
+(Most of these accept as ar)127 422.4 R .488
+(guments the same optional \215ags and a \214lename \(or a mapname for)-.18 F
+.31(NIS; the \214lename is the root of the database path, so that \231.db\232 \
+or some other e)102 434.4 R .31(xtension appropriate)-.15 F
+(for the database type will be added to get the actual database name\).)102
+446.4 Q(Kno)5 E(wn \215ags are:)-.25 E 58.86(\255o Indicates)102 462.6 R 1.147
+(that this map is optional \212 that is, if it cannot be opened, no error is)
+3.648 F(produced, and)174 474.6 Q/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1
+(will beha)2.5 E .3 -.15(ve a)-.2 H 2.5(si).15 G 2.5(ft)333.9 474.6 S(he map e)
+342.51 474.6 Q(xisted b)-.15 E(ut w)-.2 E(as empty)-.1 E(.)-.65 E .647
+(\255N, \255O)102 490.8 R .647(If neither)174.647 490.8 R F0<ad4e>3.147 E F1
+(or)3.147 E F0<ad4f>3.147 E F1 .647(are speci\214ed,)3.147 F F2(sendmail)3.147
+E F1 .647(uses an adapti)3.147 F .947 -.15(ve a)-.25 H .648(lgorithm to decide)
+.15 F .108(whether or not to look for null bytes on the end of k)174 502.8 R
+-.15(ey)-.1 G 2.608(s. It).15 F .107(starts by trying both; if)2.608 F .819
+(it \214nds an)174 514.8 R 3.319(yk)-.15 G 1.119 -.15(ey w)228.157 514.8 T .819
+(ith a null byte it ne).15 F -.15(ve)-.25 G 3.319(rt).15 G .82(ries ag)345.83
+514.8 R .82(ain without a null byte and vice)-.05 F -.15(ve)174 526.8 S 2.828
+(rsa. If).15 F F0<ad4e>2.828 E F1 .328(is speci\214ed it ne)2.828 F -.15(ve)
+-.25 G 2.828(rt).15 G .328(ries without a null byte and if)311.696 526.8 R F0
+<ad4f>2.827 E F1 .327(is speci\214ed it)2.827 F(ne)174 538.8 Q -.15(ve)-.25 G
+2.886(rt).15 G .386(ries with a null byte.)201.476 538.8 R .386
+(Setting one of these can speed matches b)5.386 F .386(ut are ne)-.2 F -.15(ve)
+-.25 G(r).15 E(necessary)174 550.8 Q 5.546(.I)-.65 G 3.046(fb)223.596 550.8 S
+(oth)234.972 550.8 Q F0<ad4e>3.046 E F1(and)3.046 E F0<ad4f>3.046 E F1 .545
+(are speci\214ed,)3.045 F F2(sendmail)3.045 E F1 .545(will ne)3.045 F -.15(ve)
+-.25 G 3.045(rt).15 G .545(ry an)442.52 550.8 R 3.045(ym)-.15 G(atches)479.01
+550.8 Q(at all \212 that is, e)174 562.8 Q -.15(ve)-.25 G
+(rything will appear to f).15 E(ail.)-.1 E<ad61>102 579 Q F2(x)A F1 1.356
+(Append the string)174 579 R F2(x)3.856 E F1 1.357(on successful matches.)3.856
+F -.15(Fo)6.357 G 3.857(re).15 G 1.357(xample, the def)382.852 579 R(ault)-.1 E
+F2(host)3.857 E F1(map)3.857 E(appends a dot on successful matches.)174 591 Q
+60.53(\255f Do)102 607.2 R(not fold upper to lo)2.5 E
+(wer case before looking up the k)-.25 E -.15(ey)-.1 G(.)-.5 E 56.08
+(\255m Match)102 623.4 R .4(only \(without replacing the v)2.9 F 2.899
+(alue\). If)-.25 F .399(you only care about the e)2.899 F .399(xistence of)-.15
+F 7.306(ak)174 635.4 S 5.107 -.15(ey a)190.646 635.4 T 4.807(nd not the v).15 F
+4.807(alue \(as you might when searching the NIS map)-.25 F 1.947
+(\231hosts.byname\232 for e)174 647.4 R 1.947(xample\), this \215ag pre)-.15 F
+-.15(ve)-.25 G 1.947(nts the map from substituting the).15 F -.25(va)174 659.4
+S 2.849(lue. Ho).25 F(we)-.25 E -.15(ve)-.25 G 1.149 -.4(r, T).15 H .349
+(he \255a ar).4 F .349(gument is still appended on a match, and the def)-.18 F
+.35(ault is)-.1 F(still tak)174 671.4 Q(en if the match f)-.1 E(ails.)-.1 E
+<ad6b>102 687.6 Q F2 -.1(ke)C(ycol)-.2 E F1(The k)174 687.6 Q .3 -.15(ey c)-.1
+H(olumn name \(for NIS+\) or number \(for te).15 E(xt lookups\).)-.15 E<ad76>
+102 703.8 Q F2(valcol)A F1(The v)174 703.8 Q
+(alue column name \(for NIS+\) or number \(for te)-.25 E(xt lookups\).)-.15 E
+EP
+%%Page: 50 45
+%%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<ad7a>102 96 Q/F2
+10/Times-Italic@0 SF(delim)A F1 .219(The column delimiter \(for te)174 96 R
+.219(xt lookups\).)-.15 F .218(It can be a single character or one of the)5.219
+F 1.825(special strings \231)174 108 R 1.825(\\n\232 or \231)1.666 F 1.826
+(\\t\232 to indicate ne)1.666 F 1.826(wline or tab respecti)-.25 F -.15(ve)-.25
+G(ly).15 E 6.826(.I)-.65 G 4.326(fo)465.784 108 S(mitted)478.44 108 Q(entirely)
+174 120 Q 2.5(,t)-.65 G(he column separator is an)211.68 120 Q 2.5(ys)-.15 G
+(equence of whitespace.)325.12 120 Q<ad73>102 136.2 Q F2(spacesub)A F1 -.15(Fo)
+174 136.2 S 3.101(rt).15 G .601(he dequote map only)193.621 136.2 R 3.101(,t)
+-.65 G .601(he character to use to replace space characters after a)286.755
+136.2 R(successful dequote.)174 148.2 Q(The)127 164.4 Q F2(dbm)3.356 E F1 .856
+(map appends the strings \231.pag\232 and \231.dir\232 to the gi)3.356 F -.15
+(ve)-.25 G 3.356<6e8c>.15 G .856(lename; the tw)399.052 164.4 R(o)-.1 E F2(db)
+3.356 E F1(-based)A(maps append \231.db\232.)102 176.4 Q -.15(Fo)5 G 2.5(re).15
+G(xample, the map speci\214cation)206.4 176.4 Q -.15(Ku)142 192.6 S
+(ucp dbm \255o \255N /usr/lib/uucpmap).15 E .21
+(speci\214es an optional map named \231uucp\232 of class \231dbm\232; it al)102
+208.8 R -.1(wa)-.1 G .21(ys has null bytes at the end of e).1 F -.15(ve)-.25 G
+(ry).15 E(string, and the data is located in /usr/lib/uucpmap.{dir)102 220.8 Q
+(,pag}.)-.4 E 1.094(The program)127 237 R F2(mak)3.594 E(emap)-.1 E F1 1.094
+(\(8\) can be used to b)B 1.094(uild an)-.2 F 3.594(yo)-.15 G 3.594(ft)347.736
+237 S 1.095(he three database-oriented maps.)357.44 237 R(It)6.095 E(tak)102
+249 Q(es the follo)-.1 E(wing \215ags:)-.25 E 60.53(\255f Do)102 265.2 R
+(not fold upper to lo)2.5 E(wer case in the map.)-.25 E 56.64(\255N Include)102
+281.4 R(null bytes in k)2.5 E -.15(ey)-.1 G(s.).15 E 58.86(\255o Append)102
+297.6 R(to an e)2.5 E(xisting \(old\) \214le.)-.15 E 60.53(\255r Allo)102 313.8
+R 3.669(wr)-.25 G 1.169(eplacement of e)205.749 313.8 R 1.168(xisting k)-.15 F
+-.15(ey)-.1 G 1.168(s; normally).15 F 3.668(,r)-.65 G 1.168(e-inserting an e)
+371.63 313.8 R 1.168(xisting k)-.15 F 1.468 -.15(ey i)-.1 H 3.668(sa).15 G(n)
+499 313.8 Q(error)174 325.8 Q(.)-.55 E 58.86(\255v Print)102 342 R
+(what is happening.)2.5 E(The)102 358.2 Q F2(sendmail)3.605 E F1 1.105
+(daemon does not ha)3.605 F 1.405 -.15(ve t)-.2 H 3.605(ob).15 G 3.605(er)
+272.975 358.2 S 1.106(estarted to read the ne)284.35 358.2 R 3.606(wm)-.25 G
+1.106(aps as long as you change)394.88 358.2 R
+(them in place; \214le locking is used so that the maps w)102 372.2 Q(on')-.1 E
+2.5(tb)-.18 G 2.5(er)336.71 372.2 S(ead while the)346.98 372.2 Q 2.5(ya)-.15 G
+(re being updated.)412.09 372.2 Q/F3 7/Times-Roman@0 SF(20)481.24 368.2 Q F1
+(Ne)127 388.4 Q 2.5(wc)-.25 G(lasses can be added in the routine)152.57 388.4 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.10. The)87 412.4 R(User Database)2.5 E F1 .108(If you ha)127 428.6 R .408
+-.15(ve a ve)-.2 H .109(rsion of).15 F F2(sendmail)2.609 E F1 .109
+(with the user database package compiled in, the handling of)2.609 F
+(sender and recipient addresses is modi\214ed.)102 440.6 Q
+(The location of this database is controlled with the)127 456.8 Q F0
+(UserDatabaseSpec)2.5 E F1(option.)2.5 E F0 2.5(5.10.1. Structur)102 480.8 R
+2.5(eo)-.18 G 2.5(ft)182.92 480.8 S(he user database)192.08 480.8 Q F1
+(The database is a sorted \(BT)142 497 Q(ree-based\) structure.)-.35 E
+(User records are stored with the k)5 E -.15(ey)-.1 G(:).15 E F2(user)157 513.2
+Q(-name)-.2 E F0(:)A F2(\214eld-name)A F1 .128
+(The sorted database format ensures that user records are clustered together)
+117 529.4 R 5.128(.M)-.55 G .128(eta-information is)432.492 529.4 R(al)117
+541.4 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 557.6 Q 2.5
+(alue. De\214ned)-.25 F(\214elds include:)2.5 E 33.39(maildrop The)117 573.8 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 573.8 R 2.373(alues of this)-.25 F 2.675
+(record. In)189 585.8 R(particular)2.675 E 2.675(,m)-.4 G .175
+(ailing lists will ha)284.095 585.8 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 597.8 Q
+30.06(mailname The)117 614 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 614 R .08
+(be an appropriate)189 626 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 626
+R .08(See also)5.08 F F2(:default:mailname)189 638 Q F1(.)A 25.62
+(mailsender Changes)117 654.2 R(an)3.447 E 3.447(ym)-.15 G .947
+(ail sent to this address to ha)252.404 654.2 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 2.736
+(This is intended for mailing lists, and will normally be the name of an)189
+666.2 R .32 LW 76 675.8 72 675.8 DL 80 675.8 76 675.8 DL 84 675.8 80 675.8 DL
+88 675.8 84 675.8 DL 92 675.8 88 675.8 DL 96 675.8 92 675.8 DL 100 675.8 96
+675.8 DL 104 675.8 100 675.8 DL 108 675.8 104 675.8 DL 112 675.8 108 675.8 DL
+116 675.8 112 675.8 DL 120 675.8 116 675.8 DL 124 675.8 120 675.8 DL 128 675.8
+124 675.8 DL 132 675.8 128 675.8 DL 136 675.8 132 675.8 DL 140 675.8 136 675.8
+DL 144 675.8 140 675.8 DL 148 675.8 144 675.8 DL 152 675.8 148 675.8 DL 156
+675.8 152 675.8 DL 160 675.8 156 675.8 DL 164 675.8 160 675.8 DL 168 675.8 164
+675.8 DL 172 675.8 168 675.8 DL 176 675.8 172 675.8 DL 180 675.8 176 675.8 DL
+184 675.8 180 675.8 DL 188 675.8 184 675.8 DL 192 675.8 188 675.8 DL 196 675.8
+192 675.8 DL 200 675.8 196 675.8 DL 204 675.8 200 675.8 DL 208 675.8 204 675.8
+DL 212 675.8 208 675.8 DL 216 675.8 212 675.8 DL/F4 5/Times-Roman@0 SF(20)93.6
+686.2 Q/F5 8/Times-Roman@0 SF .466(That is, don')3.2 J 2.466(tc)-.144 G .466
+(reate ne)148.294 689.4 R 2.466(wm)-.2 G .466(aps and then use)188.122 689.4 R
+/F6 8/Times-Italic@0 SF(mv)2.466 E F5 .466(\(1\) to mo)B .706 -.12(ve t)-.12 H
+.466(hem into place.).12 F .465(Since the maps are already open the ne)4.466 F
+2.465(wm)-.2 G(aps)493.336 689.4 Q(will ne)72 699 Q -.12(ve)-.2 G 2(rb).12 G 2
+(es)109.896 699 S(een.)118.56 699 Q EP
+%%Page: 51 46
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-51)452.9 60 Q/F1 10/Times-Roman@0 SF .655
+(appropriate -request address.)189 96 R .656(It is v)5.656 F .656
+(ery similar to the o)-.15 F(wner)-.25 E(-)-.2 E/F2 10/Times-Italic@0 SF(list)A
+F1 .656(syntax in the)3.156 F(alias \214le.)189 108 Q 33.95(fullname The)117
+124.2 R(full name of the user)2.5 E(.)-.55 E(of)117 140.4 Q 13.66
+(\214ce-address The)-.25 F(of)2.5 E(\214ce address for this user)-.25 E(.)-.55
+E(of)117 156.6 Q 19.21(\214ce-phone The)-.25 F(of)2.5 E
+(\214ce phone number for this user)-.25 E(.)-.55 E(of)117 172.8 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 189 R(home address for this user)2.5 E(.)-.55
+E 19.51(home-phone The)117 205.2 R(home phone number for this user)2.5 E(.)-.55
+E(home-f)117 221.4 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 237.6 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 249.6 S
+(rsity this is often just the name of their graduate advisor).15 E(.)-.55 E
+52.28(plan A)117 265.8 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 282 R 3.424(wo)-.25 G 3.424(ft)273.208
+282 S .925(hese \214elds are actually being used by)282.742 282 R F2(sendmail)
+3.425 E F1(:)A F2(mail-)3.425 E(dr)117 294 Q(op)-.45 E F1(and)2.5 E F2
+(mailname)2.5 E F1 5(.A)C F2(\214ng)211.54 294 Q(er)-.1 E F1
+(program that uses the other \214elds is planned.)2.5 E F0 2.5(5.10.2. User)102
+318 R(database semantics)2.5 E F1 .996(When the re)142 334.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 334.2 R .78(through the alias \214le.)117 346.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
+358.2 R 2.077 -.15(ey i)-.1 H 4.277(nt).15 G 1.777(he user database.)375.985
+358.2 R 1.777(If no match)6.777 F
+(occurs \(or if the maildrop points at the same address\), forw)117 370.2 Q
+(arding is tried.)-.1 E .55(If the \214rst tok)142 386.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 398.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
+410.4 R 1.533(vision\); mail sent to a speci\214c machine should ignore)-.25 F
+(these def)117 422.4 Q(aults.)-.1 E .351
+(When mail is sent, the name of the sending user is look)142 438.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 450.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 450.6 R(might ha)117 462.6 Q .3 -.15
+(ve a r)-.2 H(ecord:).15 E 48.29(eric:mailname Eric.Allman@CS.Berk)157 478.8 R
+(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(This w)117 495 Q
+(ould cause my outgoing mail to be sent as Eric.Allman.)-.1 E .52
+(If a \231maildrop\232 is found for the user)142 511.2 R 3.019(,b)-.4 G .519
+(ut no corresponding \231mailname\232 record e)299.686 511.2 R .519(xists, the)
+-.15 F 1.127(record \231:def)117 523.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 535.2 R -.15(Fo)5.625 G 3.125(re).15
+G .625(xample, in our case we w)185.515 535.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 547.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 559.2 S 2.5(tp).2 G
+(eople not listed in the database use the local hostname.)137.08 559.2 Q F0 2.5
+(5.10.3. Cr)102 585.2 R(eating the database)-.18 E/F3 7/Times-Bold@0 SF(21)
+228.2 581.2 Q F1 .375(The user database is b)142 601.4 R .375(uilt from a te)
+-.2 F .375(xt \214le using the)-.15 F F2(mak)2.875 E(emap)-.1 E F1 .375
+(utility \(in the distrib)2.875 F .375(ution in)-.2 F 1.039(the mak)117 613.4 R
+1.039(emap subdirectory\).)-.1 F 1.039(The te)6.039 F 1.038
+(xt \214le is a series of lines corresponding to userdb records;)-.15 F 1.588
+(each line has a k)117 625.4 R 1.889 -.15(ey a)-.1 H 1.589(nd a v).15 F 1.589
+(alue separated by white space.)-.25 F 1.589(The k)6.589 F 1.889 -.15(ey i)-.1
+H 4.089(sa).15 G -.1(lwa)421.943 625.4 S 1.589(ys in the format).1 F
+(described abo)117 637.4 Q .3 -.15(ve \212 f)-.15 H(or e).15 E(xample:)-.15 E
+(eric:maildrop)157 653.6 Q .448
+(This \214le is normally installed in a system directory; for e)117 669.8 R
+.447(xample, it might be called)-.15 F F2(/etc/user)2.947 E(db)-.37 E F1(.)A
+.32 LW 76 679.4 72 679.4 DL 80 679.4 76 679.4 DL 84 679.4 80 679.4 DL 88 679.4
+84 679.4 DL 92 679.4 88 679.4 DL 96 679.4 92 679.4 DL 100 679.4 96 679.4 DL 104
+679.4 100 679.4 DL 108 679.4 104 679.4 DL 112 679.4 108 679.4 DL 116 679.4 112
+679.4 DL 120 679.4 116 679.4 DL 124 679.4 120 679.4 DL 128 679.4 124 679.4 DL
+132 679.4 128 679.4 DL 136 679.4 132 679.4 DL 140 679.4 136 679.4 DL 144 679.4
+140 679.4 DL 148 679.4 144 679.4 DL 152 679.4 148 679.4 DL 156 679.4 152 679.4
+DL 160 679.4 156 679.4 DL 164 679.4 160 679.4 DL 168 679.4 164 679.4 DL 172
+679.4 168 679.4 DL 176 679.4 172 679.4 DL 180 679.4 176 679.4 DL 184 679.4 180
+679.4 DL 188 679.4 184 679.4 DL 192 679.4 188 679.4 DL 196 679.4 192 679.4 DL
+200 679.4 196 679.4 DL 204 679.4 200 679.4 DL 208 679.4 204 679.4 DL 212 679.4
+208 679.4 DL 216 679.4 212 679.4 DL/F4 5/Times-Roman@0 SF(21)93.6 689.8 Q/F5 8
+/Times-Roman@0 SF .289(These instructions are kno)3.2 J .289
+(wn to be incomplete.)-.2 F 2.289(Af)4.289 G .289(uture v)266.464 693 R .289
+(ersion of the user database is planned including things such as \214n-)-.12 F
+(ger service \212 and good documentation.)72 702.6 Q EP
+%%Page: 52 47
+%%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 1.6 -.8(To m)117
+96 T(ak).8 E 2.5(et)-.1 G(he database v)156.65 96 Q
+(ersion of the map, run the program:)-.15 E(mak)157 112.2 Q
+(emap btree /etc/userdb)-.1 E(.db < /etc/userdb)-.4 E .077
+(Then create a con\214g \214le that uses this.)117 128.4 R -.15(Fo)5.077 G
+2.577(re).15 G .077(xample, using the V8 M4 con\214guration, include the)
+296.531 128.4 R(follo)117 140.4 Q(wing line in your .mc \214le:)-.25 E
+(de\214ne\(\222confUSERDB_SPEC\264, /etc/userdb)157 156.6 Q(.db\))-.4 E F0 2.5
+(6. O)72 184.8 R(THER CONFIGURA)-.4 E(TION)-.95 E F1 .907
+(There are some con\214guration changes that can be made by recompiling)112 201
+R/F2 10/Times-Italic@0 SF(sendmail)3.407 E F1 5.907(.T)C .906(his section)
+460.594 201 R 1.139
+(describes what changes can be made and what has to be modi\214ed to mak)87 213
+R 3.639(et)-.1 G 3.639(hem. In)403.894 213 R 1.139(most cases this)3.639 F
+(should be unnecessary unless you are porting)87 225 Q F2(sendmail)2.5 E F1
+(to a ne)2.5 E 2.5(we)-.25 G -.4(nv)349.76 225 S(ironment.).4 E F0 2.5(6.1. P)
+87 249 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 265.2 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 277.2 Q(e\214le.)-.1 E 39.5
+(NDBM If)102 293.4 R .664(set, the ne)3.164 F 3.164(wv)-.25 G .664
+(ersion of the DBM library that allo)240.406 293.4 R .665
+(ws multiple databases will be)-.25 F 2.543(used. If)174 305.4 R .042
+(neither NDBM nor NEWDB are set, a much less ef)2.543 F .042
+(\214cient method of alias)-.25 F(lookup is used.)174 317.4 Q 32.84(NEWDB If)
+102 333.6 R .141(set, use the ne)2.641 F 2.642(wd)-.25 G .142
+(atabase package from Berk)254.436 333.6 R(ele)-.1 E 2.642(y\()-.15 G .142
+(from 4.4BSD\).)385.814 333.6 R .142(This package)5.142 F .267
+(is substantially f)174 345.6 R .267(aster than DBM or NDBM.)-.1 F .267
+(If NEWDB and NDBM are both set,)5.267 F F2(sendmail)174 357.6 Q F1
+(will read DBM \214les, b)2.5 E(ut will create and use NEWDB \214les.)-.2 E
+53.39(NIS Include)102 373.8 R .119(support for NIS.)2.619 F .119
+(If set together with)5.119 F F2(both)2.619 E F1 .119(NEWDB and NDBM,)2.619 F
+F2(sendmail)2.62 E F1 .947(will create both DBM and NEWDB \214les if and only \
+if an alias \214le includes the)174 385.8 R 3.409
+(substring \231/yp/\232 in the name.)174 397.8 R 3.409
+(This is intended for compatibility with Sun)8.409 F(Microsystems')174 409.8 Q
+F2(mkalias)2.5 E F1(program used on YP masters.)2.5 E 28.94(NISPLUS Compile)102
+426 R(in support for NIS+.)2.5 E 26.73(NETINFO Compile)102 442.2 R
+(in support for NetInfo \(NeXT stations\).)2.5 E 32.84(HESIOD Compile)102 458.4
+R(in support for Hesiod.)2.5 E(_P)102 474.6 Q -1.11(AT)-.92 G(H_SENDMAILCF)1.11
+E(The pathname of the sendmail.cf \214le.)174 486.6 Q(_P)102 502.8 Q -1.11(AT)
+-.92 G(H_SENDMAILPID)1.11 E(The pathname of the sendmail.pid \214le.)174 514.8
+Q 1.44(There are also se)127 531 R -.15(ve)-.25 G 1.439
+(ral compilation \215ags to indicate the en).15 F 1.439
+(vironment such as \231_AIX3\232 and)-.4 F 2.5(\231_SCO_unix_\232. See)102 543
+R(the READ_ME \214le for the latest scoop on these \215ags.)2.5 E F0 2.5
+(6.2. P)87 567 R(arameters in sr)-.1 E(c/conf)-.18 E(.h)-.15 E F1 -.15(Pa)127
+583.2 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 595.2 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 607.2 Q
+(The numbers follo)5 E(wing the parameters are their def)-.25 E(ault v)-.1 E
+(alue.)-.25 E 1.247(This document is not the best source of information for co\
+mpilation \215ags in conf.h \212 see)127 623.4 R
+(src/READ_ME or src/conf.h itself.)102 635.4 Q 1.91(MAXLINE [2048])102 651.6 R
+1.909(The maximum line length of an)190.31 651.6 R 4.409(yi)-.15 G 1.909
+(nput line.)338.276 651.6 R 1.909(If message lines e)6.909 F 1.909(xceed this)
+-.15 F .575(length the)188.4 663.6 R 3.075(yw)-.15 G .575
+(ill still be processed correctly; ho)243.84 663.6 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
+675.6 Q(MAXN)102 691.8 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 691.8 Q .231(MAXPV [40])
+102 708 R .231(The maximum number of parameters to an)188.631 708 R 2.731(ym)
+-.15 G(ailer)376.458 708 Q 5.231(.T)-.55 G .23(his limits the number of)407.519
+708 R .375(recipients that may be passed in one transaction.)188.4 720 R .376
+(It can be set to an)5.376 F 2.876(ya)-.15 G(rbitrary)474.01 720 Q EP
+%%Page: 53 48
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-53)452.9 60 Q/F1 10/Times-Roman@0 SF .876(number abo)188.4 96 R 1.176
+-.15(ve a)-.15 H .876(bout 10, since).15 F/F2 10/Times-Italic@0 SF(sendmail)
+3.376 E F1 .876(will break up a deli)3.376 F -.15(ve)-.25 G .875
+(ry into smaller).15 F .886(batches as needed.)188.4 108 R 3.386(Ah)5.886 G
+.887(igher number may reduce load on your system, ho)285.804 108 R(w-)-.25 E
+-2.15 -.25(ev e)188.4 120 T -.55(r.).25 G(MAXA)102 136.2 Q -.18(TO)-1.11 G
+2.559(M[).18 G 8.26(100] The)159.369 136.2 R .059
+(maximum number of atoms \(tok)2.559 F .058(ens\) in a single address.)-.1 F
+-.15(Fo)5.058 G 2.558(re).15 G .058(xample, the)457.282 136.2 R
+(address \231eric@CS.Berk)188.4 148.2 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 148.2 Q .112(MAXMAILERS [25])102
+164.4 R .112(The maximum number of mailers that may be de\214ned in the con\
+\214guration \214le.).02 F(MAXR)102 180.6 Q .401(WSETS [200])-.55 F .401
+(The maximum number of re).01 F .401(writing sets that may be de\214ned.)-.25 F
+.4(The \214rst half of)5.4 F .034(these are reserv)188.4 192.6 R .034
+(ed for numeric speci\214cation \(e.g., `)-.15 F(`S92')-.74 E .035
+('\), while the upper half)-.74 F .492(are reserv)188.4 204.6 R .492
+(ed for auto-numbering \(e.g., `)-.15 F(`Sfoo')-.74 E 2.992('\). Thus,)-.74 F
+.492(with a v)2.992 F .491(alue of 200 an)-.25 F(attempt to use `)188.4 216.6 Q
+(`S99')-.74 E 2.5('w)-.74 G(ill succeed, b)284.13 216.6 Q(ut `)-.2 E(`S100')
+-.74 E 2.5('w)-.74 G(ill f)388.82 216.6 Q(ail.)-.1 E(MAXPRIORITIES [25])102
+232.8 Q 2.481(The maximum number of v)188.4 244.8 R 2.482
+(alues for the \231Precedence:\232 \214eld that may be)-.25 F
+(de\214ned \(using the)188.4 256.8 Q F0(P)2.5 E F1(line in sendmail.cf\).)2.5 E
+(MAXUSERENVIR)102 273 Q(ON [100])-.4 E .399
+(The maximum number of items in the user en)188.4 285 R .399
+(vironment that will be passed to)-.4 F(subordinate mailers.)188.4 297 Q
+(MAXMXHOSTS [20])102 313.2 Q
+(The maximum number of MX records we will accept for an)188.4 325.2 Q 2.5(ys)
+-.15 G(ingle host.)439.03 325.2 Q .712(MAXALIASDB [12])102 341.4 R .712
+(The maximum number of alias databases that can be open at an).58 F 3.213(yt)
+-.15 G 3.213(ime. Note)461.347 341.4 R
+(that there may also be an open \214le limit.)188.4 353.4 Q(MAXMAPST)102 369.6
+Q -.4(AC)-.93 G 2.5(K[).4 G(12])184.28 369.6 Q 1.65
+(The maximum number of maps that may be "stack)188.4 381.6 R 1.65(ed" in a)-.1
+F F0(sequence)4.15 E F1(class)4.15 E(map.)188.4 393.6 Q(MAXMIMEARGS [20])102
+409.8 Q .718(The maximum number of ar)188.4 421.8 R .718
+(guments in a MIME Content-T)-.18 F .718(ype: header; addi-)-.8 F(tional ar)
+188.4 433.8 Q(guments will be ignored.)-.18 E(MAXMIMENESTING [20])102 450 Q .4
+(The maximum depth to which MIME messages may be nested \(that is, nested)188.4
+462 R 1.344
+(Message or Multipart documents; this does not limit the number of compo-)188.4
+474 R(nents in a single Multipart document\).)188.4 486 Q 2.851(An)102 502.2 S
+.351(umber of other compilation options e)117.071 502.2 R 2.851(xist. These)
+-.15 F .35(specify whether or not speci\214c code should be)2.851 F
+(compiled in.)102 514.2 Q(Ones mark)5 E(ed with \207 are 0/1 v)-.1 E(alued.)
+-.25 E 36.69(NETINET\207 If)102 530.4 R .829
+(set, support for Internet protocol netw)3.329 F .829(orking is compiled in.)
+-.1 F(Pre)5.829 E .83(vious v)-.25 F(er)-.15 E(-)-.2 E .178(sions of)188.4
+542.4 R F2(sendmail)2.678 E F1 .178(referred to this as)2.678 F/F3 9
+/Times-Roman@0 SF -.36(DA)2.678 G(EMON).36 E F1 2.677(;t)C .177
+(his old usage is no)381.715 542.4 R 2.677(wi)-.25 G(ncorrect.)468.74 542.4 Q
+(Def)188.4 554.4 Q 1.87(aults on; turn it of)-.1 F 4.37(fi)-.25 G 4.37(nt)
+292.67 554.4 S 1.87(he Mak)304.82 554.4 R 1.87(e\214le if your system doesn')
+-.1 F 4.37(ts)-.18 G 1.87(upport the)461.3 554.4 R(Internet protocols.)188.4
+566.4 Q 43.35(NETISO\207 If)102 582.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 594.6 Q(e\214le instead of conf.h\).)
+-.1 E 63.35(LOG If)102 610.8 R .5(set, the)3 F F2(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 622.8 R
+.504(es a higher priority log)-.1 F .052(record for internal system errors.)
+188.4 634.8 R F0(STR)5.052 E(ONGL)-.3 E 2.552(YR)-.92 G(ECOMMENDED)389.682
+634.8 Q F1 2.553<8a69>2.552 G 2.553(fy)483.117 634.8 S(ou)494 634.8 Q -.1(wa)
+188.4 646.8 S(nt no logging, turn it of).1 E 2.5(fi)-.25 G 2.5(nt)301.66 646.8
+S(he con\214guration \214le.)311.94 646.8 Q(MA)102 663 Q 11.12
+(TCHGECOS\207 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 663 S 3.555
+(he GECOS \214eld in)418.055 663 R 2.5(/etc/passwd. This)188.4 675 R
+(also requires that the)2.5 E F0(MatchGECOS)2.5 E F1(option be turned on.)2.5 E
+-.35(NA)102 691.2 S 13.15(MED_BIND\207 Compile).35 F .412
+(in code to use the Berk)2.912 F(ele)-.1 E 2.913(yI)-.15 G .413
+(nternet Name Domain \(BIND\) serv)342.405 691.2 R .413(er to)-.15 F(resolv)
+188.4 703.2 Q 2.5(eT)-.15 G(CP/IP host names.)225.74 703.2 Q EP
+%%Page: 54 49
+%%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(NO)102 96 Q
+38.76(TUNIX If)-.4 F .248
+(you are using a non-UNIX mail format, you can set this \215ag to turn of)2.748
+F 2.747(fs)-.25 G(pe-)491.23 96 Q
+(cial processing of UNIX-style \231From \232 lines.)188.4 108 Q -.1(QU)102
+124.2 S 50.12(EUE This).1 F 1.559
+(\215ag should be set to compile in the queueing code.)4.059 F 1.56
+(If this is not set,)6.56 F
+(mailers must accept the mail immediately or it will be returned to the sender)
+188.4 136.2 Q(.)-.55 E 57.78(SMTP If)102 152.4 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
+164.4 R(means most machines e)188.4 176.4 Q -.15(ve)-.25 G(rywhere\).).15 E
+39.45(USERDB\207 Include)102 192.6 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 192.6 R(This)5.948 E .27(adds a ne)188.4 204.6 R 2.77(wl)-.25 G -2.15
+-.25(ev e)238.67 204.6 T 2.77(lo).25 G 2.77(fl)262.7 204.6 S .27(ocal name e)
+271.58 204.6 R .27(xpansion between aliasing and forw)-.15 F 2.77(arding. It)
+-.1 F(also uses the NEWDB package.)188.4 216.6 Q
+(This may change in future releases.)5 E(The follo)102 232.8 Q
+(wing options are normally turned on in per)-.25 E
+(-operating-system clauses in conf.h.)-.2 E(IDENTPR)102 249 Q -1.88 -.4(OT O)
+-.4 H 19.61<8743>.4 G .376
+(ompile in the IDENT protocol as de\214ned in RFC 1413.)195.07 249 R .375
+(This def)5.375 F .375(aults on for)-.1 F 1.053(all systems e)188.4 261 R 1.053
+(xcept Ultrix, which apparently has the interesting \231feature\232 that)-.15 F
+.83(when it recei)188.4 273 R -.15(ve)-.25 G 3.33(sa\231).15 G .83
+(host unreachable\232 message it closes all open connections)270.18 273 R 1.921
+(to that host.)188.4 285 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 297 R(recei)188.4 309 Q .3 -.15(ve e)-.25 H(mail from such hosts.).15 E
+39.45(SYSTEM5 Set)102 325.2 R
+(all of the compilation parameters appropriate for System V)2.5 E(.)-1.29 E
+26.12(HASFLOCK\207 Use)102 341.4 R(Berk)2.844 E(ele)-.1 E(y-style)-.15 E F0
+(\215ock)2.844 E F1 .344(instead of System V)2.844 F F0(lockf)2.845 E F1 .345
+(to do \214le locking.)2.845 F .345(Due to)5.345 F .184
+(the highly unusual semantics of locks across forks in)188.4 353.4 R F0(lockf)
+2.684 E F1 2.684(,t)C .184(his should al)432.722 353.4 R -.1(wa)-.1 G(ys).1 E
+(be used if at all possible.)188.4 365.4 Q(HASINITGR)102 381.6 Q 4.86(OUPS Set)
+-.4 F 1.284(this if your system has the)3.783 F/F2 10/Times-Italic@0 SF(initgr)
+3.784 E(oups\(\))-.45 E F1 1.284(call \(if you ha)3.784 F 1.584 -.15(ve m)-.2 H
+1.284(ultiple group).15 F 4.417(support\). This)188.4 393.6 R 1.917(is the def)
+4.417 F 1.917(ault if SYSTEM5 is)-.1 F F2(not)4.416 E F1 1.916
+(de\214ned or if you are on)4.416 F(HPUX.)188.4 405.6 Q(HASUN)102 421.8 Q 27.59
+(AME Set)-.35 F 1.148(this if you ha)3.648 F 1.448 -.15(ve t)-.2 H(he).15 E F2
+(uname)3.648 E F1 1.149(\(2\) system call \(or corresponding library rou-)B 2.5
+(tine\). Set)188.4 433.8 R(by def)2.5 E(ault if SYSTEM5 is set.)-.1 E(HASGETDT)
+102 450 Q(ABLESIZE)-.93 E(Set this if you ha)188.4 462 Q .3 -.15(ve t)-.2 H(he)
+.15 E F2 -.1(ge)2.5 G(tdtablesize).1 E F1(\(2\) system call.)A(HASW)102 478.2 Q
+22.89(AITPID Set)-1.2 F(this if you ha)2.5 E .3 -.15(ve t)-.2 H(he).15 E F2
+(haswaitpid)2.5 E F1(\(2\) system call.)A 37.22(SFS_TYPE The)102 494.4 R .517
+(mechanism that can be used to get \214le system capacity information.)3.017 F
+(The)5.516 E -.25(va)188.4 506.4 S .214(lues can be one of SFS_UST).25 F 2.435
+-1.11(AT \()-.93 H .215(use the ustat\(2\) syscall\), SFS_4ARGS \(use)1.11 F
+.415(the four ar)188.4 518.4 R .415
+(gument statfs\(2\) syscall\), SFS_VFS \(use the tw)-.18 F 2.915(oa)-.1 G -.18
+(rg)435.165 518.4 S .415(ument statfs\(2\)).18 F .716
+(syscall including <sys/vfs.h>\), SFS_MOUNT \(use the tw)188.4 530.4 R 3.217
+(oa)-.1 G -.18(rg)434.863 530.4 S .717(ument statfs\(2\)).18 F 4.32
+(syscall including <sys/mount.h>\), SFS_ST)188.4 542.4 R -1.11(AT)-.93 G 4.32
+(FS \(use the tw)1.11 F 6.82(oa)-.1 G -.18(rg)470.85 542.4 S(ument).18 E 1.108
+(statfs\(2\) syscall including <sys/statfs.h>\), SFS_ST)188.4 554.4 R -1.11(AT)
+-.93 G 1.109(VFS \(use the tw)1.11 F 3.609(oa)-.1 G -.18(rg)487.52 554.4 S(u-)
+.18 E 1.511
+(ment statfs\(2\) syscall including <sys/statvfs.h>\), or SFS_NONE \(no w)188.4
+566.4 R 1.511(ay to)-.1 F(get this information\).)188.4 578.4 Q 40.57
+(LA_TYPE The)102 594.6 R(load a)2.5 E -.15(ve)-.2 G(rage type.).15 E
+(Details are described belo)5 E -.65(w.)-.25 G .342(The are se)102 610.8 R -.15
+(ve)-.25 G .342(ral b).15 F .342(uilt-in w)-.2 F .342
+(ays of computing the load a)-.1 F -.15(ve)-.2 G(rage.).15 E F2(Sendmail)5.342
+E F1 .343(tries to auto-con\214gure them)2.842 F .267
+(based on imperfect guesses; you can select one using the)102 622.8 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 622.8 Q F2(type)2.766 E F1(is:)102 634.8 Q 48.91(LA_INT The)102
+651 R -.1(ke)3.452 G .952(rnel stores the load a).1 F -.15(ve)-.2 G .952
+(rage in the k).15 F .952(ernel as an array of long inte)-.1 F(gers.)-.15 E
+(The actual v)188.4 663 Q(alues are scaled by a f)-.25 E(actor FSCALE \(def)-.1
+E(ault 256\).)-.1 E(LA_SHOR)102 679.2 Q 35.89(TT)-.6 G .794(he k)194.51 679.2 R
+.794(ernel stores the load a)-.1 F -.15(ve)-.2 G .794(rage in the k).15 F .793
+(ernel as an array of short inte)-.1 F(gers.)-.15 E(The actual v)188.4 691.2 Q
+(alues are scaled by a f)-.25 E(actor FSCALE \(def)-.1 E(ault 256\).)-.1 E
+(LA_FLO)102 707.4 Q 37.03 -1.11(AT T)-.35 H .088(he k)1.11 F .088
+(ernel stores the load a)-.1 F -.15(ve)-.2 G .089(rage in the k).15 F .089
+(ernel as an array of double precision)-.1 F(\215oats.)188.4 719.4 Q EP
+%%Page: 55 50
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-55)452.9 60 Q/F1 10/Times-Roman@0 SF(LA_MA)102 96 Q 35.97(CH Use)-.4 F
+(MA)2.5 E(CH-style load a)-.4 E -.15(ve)-.2 G(rages.).15 E 39.45(LA_SUBR Call)
+102 112.2 R(the)2.5 E/F2 10/Times-Italic@0 SF -.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 128.4 Q 42.36(OA)-.4 G -.1(lwa)195.62 128.4 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 .494(If type)102 144.6 R/F3 9/Times-Roman@0 SF
+(LA_INT)2.994 E F1(,)A F3(LA_SHOR)2.994 E(T)-.54 E F1 2.994(,o)C(r)224.806
+144.6 Q F3(LA_FLO)2.993 E -.999(AT)-.315 G F1 .493
+(is speci\214ed, you may also need to specify)3.992 F F3(_P)2.993 E -.999(AT)
+-.828 G(H_UNIX).999 E F1 .948(\(the path to your system binary\) and)102 156.6
+R F3(LA_A)3.448 E(VENR)-1.215 E(UN)-.36 E F1 .949(\(the name of the v)3.448 F
+.949(ariable containing the load)-.25 F -2.25 -.2(av e)102 168.6 T
+(rage in the k).2 E(ernel; 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.3. Con\214guration)87 192.6 R(in sr)2.5 E(c/conf)-.18 E(.c)-.15 E F1
+(The follo)127 208.8 Q(wing changes can be made in conf.c.)-.25 E F0 2.5
+(6.3.1. Built-in)102 232.8 R(Header Semantics)2.5 E F1 1.248
+(Not all header semantics are de\214ned in the con\214guration \214le.)142 249
+R 1.247(Header lines that should)6.247 F .305(only be included by certain mail\
+ers \(as well as other more obscure semantics\) must be speci\214ed)117 261 R
+.047(in the)117 273 R F2(HdrInfo)2.547 E F1 .047(table in)2.547 F F2(conf)2.547
+E(.c)-.15 E F1 5.047(.T)C .046
+(his table contains the header name \(which should be in all lo)246.842 273 R
+(wer)-.25 E(case\) and a set of header control \215ags \(described belo)117 285
+Q(w\), The \215ags are:)-.25 E(H_A)117 301.2 Q 30.97(CHECK Normally)-.4 F .007
+(when the check is made to see if a header line is compatible with)2.507 F
+2.941(am)203.4 313.2 S(ailer)218.561 313.2 Q(,)-.4 E F2(sendmail)2.941 E F1
+.441(will not delete an e)2.941 F .441(xisting line.)-.15 F .44
+(If this \215ag is set,)5.441 F F2(send-)2.94 E(mail)203.4 325.2 Q F1 .152
+(will delete e)2.652 F -.15(ve)-.25 G 2.652(ne).15 G .152
+(xisting header lines.)293.998 325.2 R .152
+(That is, if this bit is set and the)5.152 F 1.425(mailer does not ha)203.4
+337.2 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
+349.2 R F2(always)4.704 E F1(deleted.)203.4 361.2 Q 51.13(H_EOH If)117 377.4 R
+.206(this header \214eld is set, treat it lik)2.706 F 2.706(eab)-.1 G .206
+(lank line, i.e., it will signal the end)363.95 377.4 R
+(of the header and the be)203.4 389.4 Q(ginning of the message te)-.15 E(xt.)
+-.15 E 39.45(H_FORCE Add)117 405.6 R 2.038(this header entry e)4.538 F -.15(ve)
+-.25 G 4.538(ni).15 G 4.538(fo)326.22 405.6 S 2.038(ne e)339.088 405.6 R 2.039
+(xisted in the message before.)-.15 F 2.039(If a)7.039 F 2.189
+(header entry does not ha)203.4 417.6 R 2.488 -.15(ve t)-.2 H 2.188
+(his bit set,).15 F F2(sendmail)4.688 E F1 2.188(will not add another)4.688 F
+.62(header line if a header line of this name already e)203.4 429.6 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 441.6 Q -.15(ve)-.25 G
+(ryone who handled it.).15 E(H_TRA)117 457.8 Q 39.3(CE If)-.4 F 1.044
+(set, this is a timestamp \(trace\) \214eld.)3.544 F 1.043
+(If the number of trace \214elds in a)6.043 F .705(message e)203.4 469.8 R .705
+(xceeds a preset amount the message is returned on the assump-)-.15 F
+(tion that it has an aliasing loop.)203.4 481.8 Q 46.67(H_RCPT If)117 498 R
+.332(set, this \214eld contains recipient addresses.)2.833 F .332
+(This is used by the)5.332 F F0<ad74>2.832 E F1 .332(\215ag to)2.832 F 1.349
+(determine who to send to when it is collecting recipients from the mes-)203.4
+510 R(sage.)203.4 522 Q(H_FR)117 538.2 Q 43.74(OM This)-.4 F 1.673
+(\215ag indicates that this \214eld speci\214es a sender)4.174 F 6.673(.T)-.55
+G 1.673(he order of these)432.061 538.2 R .898(\214elds in the)203.4 550.2 R F2
+(HdrInfo)3.398 E F1 .898(table speci\214es)3.398 F F2(sendmail)3.398 E F1 1.998
+-.55('s p)D .898(reference for which \214eld).55 F
+(to return error messages to.)203.4 562.2 Q(H_ERR)117 578.4 Q(ORST)-.4 E 22.53
+(OA)-.18 G(ddresses in this header should recei)210.62 578.4 Q .3 -.15(ve e)
+-.25 H(rror messages.).15 E 52.79(H_CTE This)117 594.6 R(header is a Content-T)
+2.5 E(ransfer)-.35 E(-Encoding header)-.2 E(.)-.55 E 40.01(H_CTYPE This)117
+610.8 R(header is a Content-T)2.5 E(ype header)-.8 E(.)-.55 E(H_STRIPV)117 627
+Q 25.25(AL Strip)-1.35 F(the v)2.5 E(alue from the header \(for Bcc:\).)-.25 E
+(Let')117 643.2 Q 2.5(sl)-.55 G(ook at a sample)142.28 643.2 Q F2(HdrInfo)2.5 E
+F1(speci\214cation:)2.5 E EP
+%%Page: 56 51
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-56 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(struct hdrinfo)
+157 96 Q(HdrInfo[] =)295.76 96 Q({)157 108 Q
+(/* originator \214elds, most to least signi\214cant)189.5 120 Q(*/)5 E 52.29
+("resent-sender", H_FR)177 132 R(OM,)-.4 E 58.95("resent-from", H_FR)177 144 R
+(OM,)-.4 E 79.5("sender", H_FR)177 156 R(OM,)-.4 E 86.16("from", H_FR)177 168 R
+(OM,)-.4 E 66.72("full-name", H_A)177 180 R(CHECK,)-.4 E 71.17
+("errors-to", H_FR)177 192 R -1.667(OM | H_ERR)-.4 F(ORST)-.4 E(O,)-.18 E
+(/* destination \214elds */)189.5 204 Q 97.82("to", H_RCPT)177 216 R(,)-.74 E
+70.61("resent-to", H_RCPT)177 228 R(,)-.74 E 96.72("cc", H_RCPT)177 240 R(,)
+-.74 E 91.72("bcc", H_RCPT)177 252 R .833(|H).833 G(_STRIPV)-.833 E(AL,)-1.35 E
+(/* message identi\214cation and control */)189.5 264 Q 71.72
+("message", H_EOH,)177 276 R("te)177 288 Q 90.75(xt", H_EOH,)-.15 F
+(/* trace \214elds */)189.5 300 Q("recei)177 312 Q -.15(ve)-.25 G 72.13
+(d", H_TRA).15 F -1.667(CE | H_FORCE,)-.4 F(/* miscellaneous \214elds */)189.5
+324 Q("content-transfer)177 336 Q 2.5(-encoding", H_CTE,)-.2 F 55.61
+("content-type", H_CTYPE,)177 348 R 87.1(NULL, 0,)177 372 R(};)157 384 Q 2.435
+(This structure indicates that the \231T)117 400.2 R 2.435
+(o:\232, \231Resent-T)-.8 F 2.435
+(o:\232, and \231Cc:\232 \214elds all specify recipient)-.8 F 3.161
+(addresses. An)117 412.2 R 3.161<7999>-.15 G .662(Full-Name:\232 \214eld will \
+be deleted unless the required mailer \215ag \(indicated in)188.152 412.2 R
+.246(the con\214guration \214le\) is speci\214ed.)117 424.2 R .245
+(The \231Message:\232 and \231T)5.246 F -.15(ex)-.7 G .245
+(t:\232 \214elds will terminate the header;).15 F 1.936
+(these are used by random dissenters around the netw)117 436.2 R 1.936(ork w)
+-.1 F 4.436(orld. The)-.1 F(\231Recei)4.436 E -.15(ve)-.25 G 1.937
+(d:\232 \214eld will).15 F(al)117 448.2 Q -.1(wa)-.1 G
+(ys be added, and can be used to trace messages.).1 E .446
+(There are a number of important points here.)142 464.4 R .445
+(First, header \214elds are not added automati-)5.446 F .656
+(cally just because the)117 476.4 R 3.156(ya)-.15 G .656(re in the)216.674
+476.4 R/F2 10/Times-Italic@0 SF(HdrInfo)3.157 E F1 .657(structure; the)3.157 F
+3.157(ym)-.15 G .657(ust be speci\214ed in the con\214guration)358.225 476.4 R
+.728(\214le in order to be added to the message.)117 488.4 R(An)5.727 E 3.227
+(yh)-.15 G .727(eader \214elds mentioned in the con\214guration \214le)312.988
+488.4 R -.2(bu)117 500.4 S 3.24(tn).2 G .74(ot mentioned in the)137.82 500.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 500.4 Q
+1.375(added unless the)117 512.4 R 3.875(yw)-.15 G 1.375
+(ere in the message already)201.795 512.4 R 6.375(.S)-.65 G 1.374(econd, the)
+326.6 512.4 R F2(HdrInfo)3.874 E F1 1.374(structure only speci\214es)3.874 F
+.324
+(cliched processing; certain headers are processed specially by ad hoc code re)
+117 524.4 R -.05(ga)-.15 G .325(rdless of the sta-).05 F .481
+(tus speci\214ed in)117 536.4 R F2(HdrInfo)2.981 E F1 5.481(.F)C .481(or e)
+226.554 536.4 R .481
+(xample, the \231Sender:\232 and \231From:\232 \214elds are al)-.15 F -.1(wa)
+-.1 G .48(ys scanned on).1 F(ARP)117 550.4 Q .751
+(ANET mail to determine the sender)-.92 F/F3 7/Times-Roman@0 SF(22)282.315
+546.4 Q F1 3.251(;t)289.315 550.4 S .75
+(his is used to perform the \231return to sender\232 func-)298.126 550.4 R
+2.976(tion. The)117 562.4 R .476(\231From:\232 and \231Full-Name:\232 \214elds\
+ are used to determine the full name of the sender if)2.976 F
+(possible; this is stored in the macro)117 574.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 598.4
+R(Use of Email)2.5 E F1 .15
+(If it is necessary to restrict mail through a relay)142 614.6 R 2.649(,t)-.65
+G(he)339.755 614.6 Q F2 -.15(ch)2.649 G(ec).15 E(kcompat)-.2 E F1 .149
+(routine can be modi\214ed.)2.649 F .163(This routine is called for e)117 626.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 638.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 .263(later try)117 650.6 R 2.763(,a)-.65 G
+.263(nd other v)157.696 650.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.372 650.6 R .264(It is up to)5.264 F F2 -.15(ch)2.764 G(ec).15 E(k-)-.2 E
+(compat)117 662.6 Q F1 2.477(to print an error message \(using)4.978 F F2(usr)
+4.977 E(err)-.37 E F1 4.977(\)i)C 4.977(ft)331.418 662.6 S 2.477
+(he message is rejected.)342.505 662.6 R -.15(Fo)7.477 G 4.977(re).15 G
+(xample,)472.06 662.6 Q .32 LW 76 672.2 72 672.2 DL 80 672.2 76 672.2 DL 84
+672.2 80 672.2 DL 88 672.2 84 672.2 DL 92 672.2 88 672.2 DL 96 672.2 92 672.2
+DL 100 672.2 96 672.2 DL 104 672.2 100 672.2 DL 108 672.2 104 672.2 DL 112
+672.2 108 672.2 DL 116 672.2 112 672.2 DL 120 672.2 116 672.2 DL 124 672.2 120
+672.2 DL 128 672.2 124 672.2 DL 132 672.2 128 672.2 DL 136 672.2 132 672.2 DL
+140 672.2 136 672.2 DL 144 672.2 140 672.2 DL 148 672.2 144 672.2 DL 152 672.2
+148 672.2 DL 156 672.2 152 672.2 DL 160 672.2 156 672.2 DL 164 672.2 160 672.2
+DL 168 672.2 164 672.2 DL 172 672.2 168 672.2 DL 176 672.2 172 672.2 DL 180
+672.2 176 672.2 DL 184 672.2 180 672.2 DL 188 672.2 184 672.2 DL 192 672.2 188
+672.2 DL 196 672.2 192 672.2 DL 200 672.2 196 672.2 DL 204 672.2 200 672.2 DL
+208 672.2 204 672.2 DL 212 672.2 208 672.2 DL 216 672.2 212 672.2 DL/F5 5
+/Times-Roman@0 SF(22)93.6 682.6 Q/F6 8/Times-Roman@0 SF(Actually)3.2 I 2.631
+(,t)-.52 G .631
+(his is no longer true in SMTP; this information is contained in the en)132.487
+685.8 R -.12(ve)-.32 G 2.632(lope. The).12 F .632(older ARP)2.632 F .632
+(ANET protocols did)-.736 F(not completely distinguish en)72 695.4 Q -.12(ve)
+-.32 G(lope from header).12 E(.)-.44 E EP
+%%Page: 57 52
+%%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-Italic@0 SF -.15(ch)117 96 S(ec).15 E
+(kcompat)-.2 E/F2 10/Times-Roman@0 SF(could read:)2.5 E/F3 9/Times-Roman@0 SF
+(int)157 111 Q(checkcompat\(to, e\))157 121.8 Q(re)175 132.6 Q
+(gister ADDRESS *to;)-.135 E(re)175 143.4 Q(gister ENVELOPE *e;)-.135 E({)157
+154.2 Q(re)175 165 Q(gister ST)-.135 E(AB *s;)-.837 E 2.25(s=s)175 186.6 S
+(tab\("pri)191.578 186.6 Q -.225(va)-.225 G(te", ST_MAILER, ST_FIND\);).225 E
+(if \(s != NULL && e\255>e_from.q_mailer != LocalMailer &&)175 197.4 Q
+(to->q_mailer == s->s_mailer\))184 208.2 Q({)175 219 Q(usrerr\("No pri)193
+229.8 Q -.225(va)-.225 G(te net mail allo).225 E(wed through this machine"\);)
+-.225 E(return \(EX_UN)193 240.6 Q -1.215(AVA)-.315 G(ILABLE\);)1.215 E(})175
+251.4 Q(if \(MsgSize > 50000 && bitnset\(M_LOCALMAILER, to\255>q_mailer\)\))175
+262.2 Q({)175 273 Q(usrerr\("Message too lar)193 283.8 Q(ge for non-local deli)
+-.162 E -.135(ve)-.225 G(ry"\);).135 E(e\255>e_\215ags |= EF_NORETURN;)193
+294.6 Q(return \(EX_UN)193 305.4 Q -1.215(AVA)-.315 G(ILABLE\);)1.215 E(})175
+316.2 Q(return \(EX_OK\);)175 327 Q(})157 337.8 Q F2 5.146(This w)117 354 R
+5.147(ould reject messages greater than 50000 bytes unless the)-.1 F 7.647(yw)
+-.15 G 5.147(ere local.)436.506 354 R(The)488.45 354 Q F1(EF_NORETURN)117 366 Q
+F2 .942(\215ag can be set in)3.442 F F1(e)3.441 E/F4 10/Symbol SF<ae>A F1
+(e_\215a)A(gs)-.1 E F2 .941(to suppress the return of the actual body of the)
+3.441 F .128(message in the error return.)117 378 R .129
+(The actual use of this routine is highly dependent on the implemen-)5.129 F
+(tation, and use should be limited.)117 390 Q F0 2.5(6.3.3. Load)102 414 R -.6
+-1(Av e)2.5 H(rage Computation)1 E F2 .18(The routine)142 430.2 R F1 -.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 442.2 Q(ger)-.15 E 5(.T)-.55 G(here are se)
+157.68 442.2 Q -.15(ve)-.25 G(ral v).15 E
+(ersions included on compilation \215ags as described abo)-.15 E -.15(ve)-.15 G
+(.).15 E F0 2.5(6.3.4. New)102 466.2 R(Database Map Classes)2.5 E F2(Ne)142
+482.4 Q 2.875(wk)-.25 G .675 -.15(ey m)168.405 482.4 T .375(aps can be added b\
+y creating a class initialization function and a lookup func-).15 F 2.5
+(tion. These)117 494.4 R(are then added to the routine)2.5 E F1(setupmaps.)2.5
+E F2(The initialization function is called as)142 510.6 Q F1(xxx)157 526.8 Q F2
+(_map_init\(MAP *map, char *mapname, char *ar)A(gs\))-.18 E(The)117 543 Q F1
+(map)2.555 E F2 .055(is an internal data structure.)2.555 F(The)5.055 E F1
+(mapname)2.555 E F2 .054(is the name of the map \(used for error mes-)2.554 F
+2.819(sages\). The)117 555 R F1(ar)2.819 E(gs)-.37 E F2 .32(is a pointer to th\
+e rest of the con\214guration \214le line; \215ags and \214lenames can be)2.819
+F -.15(ex)117 567 S .675(tracted from this line.).15 F .675
+(The initialization function must return)5.675 F F3(TR)3.175 E(UE)-.36 E F2
+.674(if it successfully opened)3.174 F(the map,)117 579 Q F3 -.666(FA)2.5 G
+(LSE).666 E F2(otherwise.)2.5 E(The lookup function is called as)142 595.2 Q F1
+(xxx)157 611.4 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 627.6 Q
+F1(map)3.475 E F2 .975(de\214nes the map internally)3.475 F 5.975(.T)-.65 G
+.975(he parameters)277.18 627.6 R F1 -.2(bu)3.475 G(f).2 E F2(and)3.475 E F1
+-.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 627.6 Q .043
+(may be \(and often is\) used destructi)117 639.6 R -.15(ve)-.25 G(ly).15 E
+5.043(.T)-.65 G(he)289.831 639.6 Q F1(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
+651.6 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 651.6 R 1.155(the map lookup f)3.655 F(ails,)
+-.1 E F1(*statp)117 663.6 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 663.6 S
+1.271(hould be set to)368.093 663.6 R F3(EX_TEMPF)3.771 E(AIL)-.666 E F2(if)
+3.771 E(reco)117 675.6 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 675.6 Q EP
+%%Page: 58 53
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-58 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E 2.5(6.3.5. Queueing)102 96 R(Function)
+2.5 E/F1 10/Times-Roman@0 SF .782(The routine)142 112.2 R/F2 10/Times-Italic@0
+SF(shouldqueue)3.282 E F1 .783
+(is called to decide if a message should be queued or processed)3.283 F
+(immediately)117 124.2 Q 6.619(.T)-.65 G 1.618
+(ypically this compares the message priority to the current load a)180.779
+124.2 R -.15(ve)-.2 G 4.118(rage. The).15 F(def)117 136.2 Q
+(ault de\214nition is:)-.1 E(bool)157 152.4 Q(shouldqueue\(pri, ctime\))157
+164.4 Q(long pri;)175 176.4 Q(time_t ctime;)175 188.4 Q({)157 200.4 Q
+(if \(CurrentLA < QueueLA\))175 212.4 Q(return \(F)193 224.4 Q(ALSE\);)-.74 E
+(return \(pri > \(QueueF)175 236.4 Q
+(actor / \(CurrentLA \255 QueueLA + 1\)\)\);)-.15 E(})157 248.4 Q 2.062
+(If the current load a)117 264.6 R -.15(ve)-.2 G 2.062(rage \(global v).15 F
+(ariable)-.25 E F2(Curr)4.562 E(entLA)-.37 E F1 4.562(,w)C 2.062
+(hich is set before this function is)361.636 264.6 R 1.058
+(called\) is less than the lo)117 276.6 R 3.558(wt)-.25 G 1.058
+(hreshold load a)234.198 276.6 R -.15(ve)-.2 G 1.058(rage \(option).15 F F0(x)
+3.557 E F1 3.557(,v)C(ariable)375.526 276.6 Q F2(QueueLA)3.557 E F1(\),)A F2
+(shouldqueue)3.557 E F1(returns)117 288.6 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
+300.6 R -.15(ve)-.2 G .588(rage \(option).15 F F0(X)3.087 E F1 3.087(,v)C
+(ariable)281.846 300.6 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 312.6 Q
+7.125(.O)-.65 G 2.125
+(therwise, it computes the function based on the message priority)152.635 312.6
+R 4.626(,t)-.65 G 2.126(he queue f)438.208 312.6 R(actor)-.1 E(\(option)117
+324.6 Q F0(q)2.5 E F1 2.5(,g)C(lobal v)163.95 324.6 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 340.8 R 3.567(et)-.1 G
+1.066(he actual age of the message into account can also)293.625 340.8 R 1.41
+(use the)117 352.8 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 352.8 R 1.41
+(as \214rst submitted to)-.1 F F2(sendmail)3.91 E F1(.)A .929(Note that the)117
+364.8 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 376.8 R .395
+(wer the priority of the message with time\); the e)-.25 F .395
+(xpectation is that)-.15 F(the)117 388.8 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 412.8 R
+(Incoming SMTP Connections)2.5 E F1 1.148(The function)142 429 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 441
+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 453 Q -.15(ve)-.2 G(rage option \(option).15 E F0(X)2.5 E F1
+2.5(,g)C(lobal v)273.56 453 Q(ariable)-.25 E F2(RefuseLA)2.5 E F1(\):)A(bool)
+157 469.2 Q(refuseconnections\(\))157 481.2 Q({)157 493.2 Q
+(return \(CurrentLA >= RefuseLA\);)175 505.2 Q(})157 517.2 Q 2.5(Am)117 533.4 S
+(ore cle)134.5 533.4 Q -.15(ve)-.25 G 2.5(ri).15 G
+(mplementation could look at more system resources.)179.08 533.4 Q F0 2.5
+(6.3.7. Load)102 557.4 R -.6 -1(Av e)2.5 H(rage Computation)1 E F1 .243
+(The routine)142 573.6 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 1.157(includes se)117 585.6 R -.15(ve)-.25 G 1.157
+(ral possible implementations.).15 F 1.157(If you are porting to a ne)6.157 F
+3.657(we)-.25 G -.4(nv)418.757 585.6 S 1.157(ironment you may).4 F
+(need to add some ne)117 599.6 Q 2.5(wt)-.25 G(weaks.)210.9 599.6 Q/F4 7
+/Times-Roman@0 SF(23)238.39 595.6 Q F0 2.5(6.4. Con\214guration)87 623.6 R
+(in sr)2.5 E(c/daemon.c)-.18 E F1 .4(The \214le)127 639.8 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 651.8 Q 2.5(vironment. The)-.4 F -.15(ve)2.5 G
+(rsion supplied assumes you ha).15 E .3 -.15(ve B)-.2 H(SD style sock).15 E
+(ets.)-.1 E 2.16(In pre)127 668 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 680 S 1.918
+(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.904 680 T 1.918
+(ecommend that you create a ne).25 F 4.419(wk)-.25 G -.15(ey)463.631 680 S
+1.919(ed map).15 F .32 LW 76 689.6 72 689.6 DL 80 689.6 76 689.6 DL 84 689.6 80
+689.6 DL 88 689.6 84 689.6 DL 92 689.6 88 689.6 DL 96 689.6 92 689.6 DL 100
+689.6 96 689.6 DL 104 689.6 100 689.6 DL 108 689.6 104 689.6 DL 112 689.6 108
+689.6 DL 116 689.6 112 689.6 DL 120 689.6 116 689.6 DL 124 689.6 120 689.6 DL
+128 689.6 124 689.6 DL 132 689.6 128 689.6 DL 136 689.6 132 689.6 DL 140 689.6
+136 689.6 DL 144 689.6 140 689.6 DL 148 689.6 144 689.6 DL 152 689.6 148 689.6
+DL 156 689.6 152 689.6 DL 160 689.6 156 689.6 DL 164 689.6 160 689.6 DL 168
+689.6 164 689.6 DL 172 689.6 168 689.6 DL 176 689.6 172 689.6 DL 180 689.6 176
+689.6 DL 184 689.6 180 689.6 DL 188 689.6 184 689.6 DL 192 689.6 188 689.6 DL
+196 689.6 192 689.6 DL 200 689.6 196 689.6 DL 204 689.6 200 689.6 DL 208 689.6
+204 689.6 DL 212 689.6 208 689.6 DL 216 689.6 212 689.6 DL/F5 5/Times-Roman@0
+SF(23)93.6 700 Q/F6 8/Times-Roman@0 SF
+(If you do, please send updates to sendmail@CS.Berk)3.2 I(ele)-.08 E -.52(y.)
+-.12 G(EDU.).52 E EP
+%%Page: 59 54
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-59)452.9 60 Q/F1 10/Times-Roman@0 SF(instead.)102 96 Q F0 2.5
+(7. CHANGES)72 120 R(IN VERSION 8)2.5 E F1 .196(The follo)112 136.2 R .196
+(wing summarizes changes since the last commonly a)-.25 F -.25(va)-.2 G .196
+(ilable v).25 F .196(ersion of)-.15 F/F2 10/Times-Italic@0 SF(sendmail)2.695 E
+F1(\(5.67\).)2.695 E -.15(Fo)87 148.2 S 2.702(rad).15 G .202
+(etailed list, consult the \214le RELEASE_NO)115.584 148.2 R .203
+(TES in the root directory of the)-.4 F F2(sendmail)2.703 E F1(distrib)2.703 E
+(ution.)-.2 E F0 2.5(7.1. Connection)87 172.2 R(Caching)2.5 E F1 .398
+(Instead of closing SMTP connections immediately)127 188.4 R 2.897(,t)-.65 G
+.397(hose connections are cached for possible)339.005 188.4 R .597(future use.)
+102 200.4 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 212.4 Q
+-.15(ve)-.15 G(ments can be e).15 E(xpected for queue processing.)-.15 E F0 2.5
+(7.2. MX)87 236.4 R(Piggybacking)2.5 E F1 1.258(If tw)127 252.6 R 3.757(oh)-.1
+G 1.257(osts with dif)161.075 252.6 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 264.6 R 3.44(yc)-.15 G .94
+(an be sent in the same transaction.)153.45 264.6 R -1.11(Ve)5.94 G .94
+(rsion 8 notices this and tries to batch the mes-)1.11 F(sages.)102 276.6 Q F0
+2.5(7.3. RFC)87 300.6 R(1123 Compliance)2.5 E F1 3.463(An)127 316.8 S .963
+(umber of changes ha)142.683 316.8 R 1.262 -.15(ve b)-.2 H .962
+(een made to mak).15 F(e)-.1 E F2(sendmail)3.462 E F1 .962
+(\231conditionally compliant\232 \(that is,)3.462 F F2(sendmail)102 328.8 Q F1
+.049(satis\214es all of the \231MUST\232 clauses and most b)2.549 F .05
+(ut not all of the \231SHOULD\232 clauses in RFC)-.2 F(1123\).)102 340.8 Q
+(The major areas of change are \(numbers are RFC 1123 section numbers\):)127
+357 Q 15(5.2.7 Response)102 373.2 R(to RCPT command is f)2.5 E(ast.)-.1 E 15
+(5.2.8 Numeric)102 389.4 R(IP addresses are logged in Recei)2.5 E -.15(ve)-.25
+G(d: lines.).15 E 10(5.2.17 Self)102 405.6 R
+(domain literal is properly handled.)2.5 E 15(5.3.2 Better)102 421.8 R
+(control o)2.5 E -.15(ve)-.15 G 2.5(ri).15 G(ndi)220.02 421.8 Q
+(vidual timeouts.)-.25 E 15(5.3.3 Error)102 438 R
+(messages are sent as \231From:<>\232.)2.5 E 15(5.3.3 Error)102 454.2 R
+(messages are ne)2.5 E -.15(ve)-.25 G 2.5(rs).15 G(ent to \231<>\232.)246.28
+454.2 Q 15(5.3.3 Route-addrs)102 470.4 R(are pruned.)2.5 E(The areas in which)
+102 486.6 Q F2(sendmail)2.5 E F1(is not \231unconditionally compliant\232 are:)
+2.5 E(5.2.6)102 502.8 Q F2(Sendmail)139.5 502.8 Q F1(does do header munging.)
+2.5 E(5.2.10)102 519 Q F2(Sendmail)139.5 519 Q F1(doesn')2.5 E 2.5(ta)-.18 G
+-.1(lwa)215.42 519 S(ys use the e).1 E(xact SMTP message te)-.15 E
+(xt as listed in RFC 821.)-.15 E(5.3.1.1)102 535.2 Q F2(Sendmail)139.5 535.2 Q
+F1(doesn')2.5 E 2.5(tg)-.18 G
+(uarantee only one connect for each host in queue runs.)215.98 535.2 Q(5.3.1.1)
+102 551.4 Q F2(Sendmail)139.5 551.4 Q F1(doesn')2.5 E 2.5(ta)-.18 G -.1(lwa)
+215.42 551.4 S(ys pro).1 E(vide adequate concurrenc)-.15 E 2.5(yl)-.15 G
+(imits.)366.54 551.4 Q F0 2.5(7.4. Extended)87 575.4 R(SMTP Support)2.5 E F1
+-1.11(Ve)127 591.6 S .155(rsion 8 includes both sending and recei)1.11 F .154
+(ving support for Extended SMTP support as de\214ned)-.25 F(by RFC 1651 \(basi\
+c\) and RFC 1653 \(SIZE\); and limited support for RFC 1652 \(BOD)102 603.6 Q
+(Y\).)-.55 E F0 2.5(7.5. Eight-Bit)87 627.6 R(Clean)2.5 E F1(Pre)127 643.8 Q
+1.263(vious v)-.25 F 1.263(ersions of)-.15 F F2(sendmail)3.763 E F1 1.264
+(used the 0200 bit for quoting.)3.763 F 1.264(This v)6.264 F 1.264(ersion a)
+-.15 F -.2(vo)-.2 G 1.264(ids that use.).2 F(Ho)102 655.8 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 655.8 Q(Indi)127 672 Q
+(vidual mailers can still produce se)-.25 E -.15(ve)-.25 G 2.5(nb).15 G
+(it output using the `7' mailer \215ag.)300.77 672 Q F0 2.5(7.6. User)87 696 R
+(Database)2.5 E F1 1.073(The user database is an as-yet e)127 712.2 R 1.072
+(xperimental attempt to pro)-.15 F 1.072(vide uni\214ed lar)-.15 F 1.072
+(ge-site name sup-)-.18 F 2.5(port. W)102 724.2 R 2.5(ea)-.8 G
+(re installing it at Berk)145.63 724.2 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
+724.2 Q EP
+%%Page: 60 55
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-60 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E 2.5(7.7. Impr)87 96 R -.1(ove)-.18 G
+2.5(dB).1 G(IND Support)158.01 96 Q/F1 10/Times-Roman@0 SF .489
+(The BIND support, particularly for MX records, had a number of anno)127 112.2
+R .49(ying \231features\232 which)-.1 F(ha)102 124.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 124.2 S .912
+(his release.)198.308 124.2 R .912(In particular)5.912 F 3.412(,t)-.4 G .912
+(hese more tightly bind \(pun intended\) the name)307.916 124.2 R(serv)102
+136.2 Q(er to)-.15 E/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1 2.5(,s)C 2.5(ot)
+184.06 136.2 S(hat the name serv)194.34 136.2 Q
+(er resolution rules are incorporated directly into)-.15 E F0(sendmail)2.5 E F1
+(.)A F0 2.5(7.8. K)87 160.2 R(ey)-.25 E(ed Files)-.1 E F1 .365(Generalized k)
+127 176.4 R -.15(ey)-.1 G .365(ed \214les is an idea tak).15 F .365
+(en directly from)-.1 F/F3 9/Times-Roman@0 SF(ID)2.866 E(A)-.36 E F2(sendmail)
+2.866 E F1 .366(\(albeit with a completely)2.866 F(dif)102 188.4 Q
+(ferent implementation\).)-.25 E(The)5 E 2.5(yc)-.15 G(an be useful on lar)
+239.63 188.4 Q(ge sites.)-.18 E -1.11(Ve)127 204.6 S
+(rsion 8 also understands YP)1.11 E(.)-1.11 E F0 2.5(7.9. Multi-W)87 228.6 R
+(ord Classes)-.75 E F1(Classes can no)127 244.8 Q 2.5(wb)-.25 G 2.5(em)200.35
+244.8 S(ultiple w)215.07 244.8 Q 2.5(ords. F)-.1 F(or e)-.15 E(xample,)-.15 E
+(CShofmann.CS.Berk)142 261 Q(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(allo)102 277.2
+Q 2.664(ws you to match the entire string \231hofmann.CS.Berk)-.25 F(ele)-.1 E
+-.65(y.)-.15 G 2.663(EDU\232 using the single construct).65 F(\231$=S\232.)102
+289.2 Q F0 2.5(7.10. Deferr)87 313.2 R(ed Macr)-.18 E 2.5(oE)-.18 G(xpansion)
+189.94 313.2 Q F1(The)127 329.4 Q F0($&)2.5 E F2(x)A F1
+(construct has been adopted from)2.5 E F3(ID)2.5 E(A)-.36 E F1(.)A F0 2.5
+(7.11. IDENT)87 353.4 R(Pr)2.5 E(otocol Support)-.18 E F1
+(The IDENT protocol as de\214ned in RFC 1413 is supported.)127 369.6 Q F0 2.5
+(7.12. P)87 393.6 R(arsing Bug Fixes)-.1 E F1 4.03(An)127 409.8 S 1.53
+(umber of small b)143.25 409.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 409.8 R(comments ha)102 421.8 Q .3
+-.15(ve b)-.2 H(een \214x).15 E(ed.)-.15 E F0 2.5(7.13. Separate)87 445.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 462 R -.15(ve)-.4
+G .854(lope sender).15 F 3.354(,t)-.4 G .854(hese ha)420.978 462 R 1.154 -.15
+(ve b)-.2 H .854(oth been).15 F .427(made visible; the)102 474 R F0($g)2.927 E
+F1 .427(macro is set to the en)2.927 F -.15(ve)-.4 G .428
+(lope sender during processing of mailer ar).15 F .428(gument v)-.18 F(ec-)-.15
+E(tors and the header sender during processing of headers.)102 486 Q .085
+(It is also possible to specify separate per)127 502.2 R .085(-mailer en)-.2 F
+-.15(ve)-.4 G .084(lope and header processing.).15 F(The)5.084 E F0(S)2.584 E
+F1(ender)A(-)-.2 E -.55(RW)102 514.2 S .512(Set and).55 F F0(R)3.012 E F1
+(ecipientR)A .512(Wset ar)-.55 F .512
+(guments for mailers can be speci\214ed as)-.18 F F2(en)3.013 E(velope/header)
+-.4 E F1 .513(to gi)3.013 F .813 -.15(ve d)-.25 H(if-).15 E(ferent re)102 526.2
+Q(writings for en)-.25 E -.15(ve)-.4 G(lope v).15 E(ersus header addresses.)
+-.15 E F0 2.5(7.14. Owner)87 550.2 R(-List Pr)-.37 E(opagates to En)-.18 E -.1
+(ve)-.4 G(lope).1 E F1 1.001(When an alias has an associated o)127 566.4 R 1
+(wner\255list name, that alias is used to change the en)-.25 F -.15(ve)-.4 G
+(lope).15 E(sender address.)102 578.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.15. Dynamic)87 602.4 R(Header Allocation)2.5 E F1(The \214x)127 618.6 Q
+(ed size limit on header lines has been eliminated.)-.15 E F0 2.5(7.16. New)87
+642.6 R(Command Line Flags)2.5 E F1(The)127 658.8 Q F0<ad42>2.5 E F1
+(\215ag has been added to pass in body type information.)2.5 E(The)127 675 Q F0
+<ad70>2.5 E F1(\215ag has been added to pass in protocol information.)2.5 E
+(The)127 691.2 Q F0<ad58>2.6 E F1 .1(\215ag has been added to allo)2.6 F 2.6
+(wl)-.25 G .1(ogging of all protocol in and out of)279.89 691.2 R F2(sendmail)
+2.6 E F1 .1(for deb)2.6 F(ug-)-.2 E(ging.)102 703.2 Q EP
+%%Page: 61 56
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-61)452.9 60 Q/F1 10/Times-Roman@0 SF(The)127 96 Q F0<ad4f>2.5 E F1
+(\215ag simplies setting long-form options.)2.5 E F0 2.5(7.17. Enhanced)87 120
+R(Command Line Flags)2.5 E F1(The)127 136.2 Q F0<ad71>4.007 E F1 1.507(\215ag \
+can limit limit a queue run to speci\214c recipients, senders, or queue ids us\
+ing)4.007 F F0(\255qR)102 148.2 Q/F2 10/Times-Italic@0 SF(substring)A F0 2.5
+<2cad>C(qS)168.41 148.2 Q F2(substring)A F0 2.5(,o)C 2.5<72ad>226.76 148.2 S
+(qI)239.4 148.2 Q F2(substring)A F0 -.18(re)2.5 G(specti).18 E -.1(ve)-.1 G(ly)
+.1 E(.)-.7 E 2.5(7.18. New)87 172.2 R(and Old Con\214guration Line T)2.5 E
+(ypes)-.74 E F1(The)127 188.4 Q F0(K)2.5 E F1
+(line has been added to declare database maps.)2.5 E(The)127 204.6 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(The)127 220.8 Q F0(M)2.796 E F1 .297(line has a \231D=\
+\232 \214eld that lets you change into a temporary directory while that mailer)
+2.796 F .581(is running.)102 232.8 R .581
+(It also has a \231U=\232 \214eld to allo)5.581 F 3.081(wy)-.25 G .58
+(ou to set the user and group id to be used when run-)289.85 232.8 R
+(ning the mailer)102 244.8 Q(.)-.55 E F0 2.5(7.19. New)87 268.8 R(Options)2.5 E
+F1(Se)127 285 Q -.15(ve)-.25 G .9(ral ne).15 F 3.4(wo)-.25 G .9(ptions ha)184.8
+285 R 1.2 -.15(ve b)-.2 H .9(een added, man).15 F 3.4(yt)-.15 G 3.4(os)314.89
+285 S .9(upport ne)327.18 285 R 3.4(wf)-.25 G .9(eatures, others to allo)379.83
+285 R 3.4(wt)-.25 G(uning)481.22 285 Q 1.187(that w)102 297 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 297 R(Brie\215y)102 309 Q(,)-.65 E 31(bI)102 325.2 S
+(nsist on a minimum number of disk blocks.)141.33 325.2 Q 29.33(CS)102 341.4 S
+(et checkpoint interv)143.56 341.4 Q(al.)-.25 E 29.89(ED)102 357.6 S(ef)145.22
+357.6 Q(ault error message.)-.1 E 28.78(GE)102 373.8 S(nable GECOS matching.)
+144.11 373.8 Q 31(hM)102 390 S(aximum hop count.)146.89 390 Q 33.22(jS)102
+406.2 S(end errors in MIME-encapsulated format.)143.56 406.2 Q 32.11(JF)102
+422.4 S(orw)143.41 422.4 Q(ard \214le path.)-.1 E 31(kC)102 438.6 S
+(onnection cache size)144.67 438.6 Q 28.78(KC)102 454.8 S
+(onnection cache lifetime.)144.67 454.8 Q 33.22(lE)102 471 S .333
+(nable Errors-T)144.11 471 R .333(o: header)-.8 F 5.334(.T)-.55 G .334
+(hese headers violate RFC 1123; this option is included to pro-)252.89 471 R
+(vide back compatibility with old v)138 483 Q(ersions of)-.15 E F2(sendmail)2.5
+E F1(.)A 28.78(OS)102 499.2 S
+(et incoming SMTP daemon options, such as an alternate SMTP port.)143.56 499.2
+Q 31(pP)102 515.4 S(ri)143.56 515.4 Q -.25(va)-.25 G .3 -.15(cy o).25 H
+(ptions.).15 E 29.33(RD)102 531.6 S(on')145.22 531.6 Q 2.5(tp)-.18 G
+(rune route-addrs.)168.65 531.6 Q 28.78(UU)102 547.8 S(ser database spec.)
+145.22 547.8 Q 28.78(VF)102 564 S(allback \231MX\232 host.)143.41 564 Q 28.78
+<7799>102 580.2 S(Best MX\232 handling technique.)142.44 580.2 Q 31(7D)102
+596.4 S 2.5(on)145.22 596.4 S(ot run eight bit clean.)157.72 596.4 Q 31(8E)102
+612.6 S(ight bit data handling mode.)144.11 612.6 Q F0 2.5(7.20. Extended)87
+636.6 R(Options)2.5 E F1(The)127 652.8 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 664.8 Q
+F0 2.5(7.21. New)87 688.8 R(Mailer Flags)2.5 E F1(Se)127 705 Q -.15(ve)-.25 G
+(ral ne).15 E 2.5(wm)-.25 G(ailer \215ags ha)185.78 705 Q .3 -.15(ve b)-.2 H
+(een added.).15 E EP
+%%Page: 62 57
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-62 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 31.56(aT)102 96
+S .636(ry to use ESMTP when creating a connection.)143.76 96 R .636
+(If this is not set,)5.636 F/F2 10/Times-Italic@0 SF(sendmail)3.136 E F1 .636
+(will still try if)3.136 F .221(the other end hints that it kno)138 108 R .22
+(ws about ESMTP in its greeting message; this \215ag says to try)-.25 F -2.15
+-.25(ev e)138 120 T 2.595(ni).25 G 2.595(fi)161.855 120 S 2.595(td)170.56 120 S
+(oesn')180.935 120 Q 2.595(th)-.18 G 2.595(int. If)212.79 120 R .095
+(the EHLO \(e)2.595 F .095(xtended hello\) command f)-.15 F(ails,)-.1 E F2
+(sendmail)2.596 E F1 -.1(fa)2.596 G .096(lls back to).1 F(old SMTP)138 132 Q(.)
+-1.11 E 28.78(AT)102 148.2 S
+(ry the user part of addresses for this mailer as aliases.)143.76 148.2 Q 31
+(bE)102 164.4 S(nsure that there is a blank line at the end of all messages.)
+144.11 164.4 Q 31.56(cS)102 180.6 S .68(trip all comments from addresses; this\
+ should only be used as a last resort when dealing)143.56 180.6 R(with crank)
+138 192.6 Q 2.5(ym)-.15 G(ailers.)195.62 192.6 Q 31(gN)102 208.8 S -2.15 -.25
+(ev e)145.22 208.8 T 2.64(ru).25 G .14(se the null sender as the en)169.67
+208.8 R -.15(ve)-.4 G .141(lope sender).15 F 2.641(,e)-.4 G -.15(ve)341.495
+208.8 S 2.641(nw).15 G .141(hen running SMTP)365.646 208.8 R 5.141(.A)-1.11 G
+.141(lthough this)456.349 208.8 R 1.521(violates RFC 1123, it may be necessary\
+ when you must deal with some obnoxious old)138 220.8 R(hosts.)138 232.8 Q 31
+(kT)102 249 S(urn of)143.66 249 Q 2.5(ft)-.25 G
+(he loopback check in the HELO protocol; doing this may cause mailer loops.)
+176.18 249 Q 31(oA)102 265.2 S -.1(lwa)145.22 265.2 S
+(ys run the mailer as the recipient of the message.).1 E 28.78(wT)102 281.4 S
+(his user should ha)144.11 281.4 Q .3 -.15(ve a p)-.2 H(asswd \214le entry).15
+E(.)-.65 E 31(5T)102 297.6 S(ry ruleset 5 if no local aliases.)143.76 297.6 Q
+31(7S)102 313.8 S(trip all output to 7 bits.)143.56 313.8 Q 33.22(:C)102 330 S
+(heck for :include: \214les.)144.67 330 Q 34(|C)102 346.2 S
+(heck for |program addresses.)144.67 346.2 Q 33.22(/C)102 362.4 S
+(heck for /\214le addresses.)144.67 362.4 Q 26.79(@C)102 378.6 S
+(heck this user ag)144.67 378.6 Q(ainst the user database.)-.05 E F0 2.5
+(7.22. Long)87 402.6 R(Option Names)2.5 E F1 .856
+(All options can be speci\214ed using long names, and some ne)127 418.8 R 3.356
+(wo)-.25 G .856(ptions can only be speci\214ed)389.476 418.8 R
+(with long names.)102 430.8 Q F0 2.5(7.23. New)87 454.8 R(Pr)2.5 E
+(e-De\214ned Macr)-.18 E(os)-.18 E F1(The follo)127 471 Q
+(wing macros are pre-de\214ned:)-.25 E 23.5($k The)102 487.2 R
+(UUCP node name, nominally from)2.5 E F2(uname)2.5 E F1(\(2\) call.)A 20.72
+($m The)102 503.4 R(domain part of our full hostname.)2.5 E 23.5($_ The)102
+519.6 R(RFC 1413-pro)2.5 E(vided sender address.)-.15 E F0 2.5(7.24. New)87
+543.6 R(LHS T)2.5 E(ok)-.92 E(en)-.1 E F1 -1.11(Ve)127 559.8 S 1.376
+(rsion 8 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
+571.8 Q F0 2.5(7.25. Bigger)87 595.8 R(Defaults)2.5 E F1 -1.11(Ve)127 612 S
+1.283(rsion 8 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 624 Q
+(ed for)-.15 E F2(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
+640.2 Q .335(The number of queued messages that can be handled at one time has\
+ been raised from 600 to)127 656.4 R(1000.)102 668.4 Q F0 2.5(7.26. Differ)87
+692.4 R(ent Default T)-.18 E(uning P)-.92 E(arameters)-.1 E F1 -1.11(Ve)127
+708.6 S .8(rsion 8 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 708.6 R .712(recipients more important than the size of t\
+he message \(for small messages\).)102 720.6 R .712(This is reasonable if)5.712
+F EP
+%%Page: 63 58
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q
+(SMM:08-63)452.9 60 Q/F1 10/Times-Roman@0 SF
+(you are connected with reasonably f)102 96 Q(ast links.)-.1 E F0 2.5(7.27. A)
+87 120 R(uto-Quoting in Addr)-.5 E(esses)-.18 E F1(Pre)127 136.2 Q(viously)-.25
+E 2.61(,t)-.65 G .111(he \231Full Name <email address>\232 syntax w)176.77
+136.2 R .111(ould generate incorrect protocol output)-.1 F
+(if \231Full Name\232 had special characters such as dot.)102 148.2 Q(This v)5
+E(ersion puts quotes around such names.)-.15 E F0 2.5(7.28. Symbolic)87 172.2 R
+(Names On Err)2.5 E(or Mailer)-.18 E F1(Se)127 188.4 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.29. SMTP)87 212.4 R(VRFY Doesn't Expand)2.5 E F1(Pre)127 228.6 Q 1.438
+(vious v)-.25 F 1.438(ersions of)-.15 F/F2 10/Times-Italic@0 SF(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 240.6 Q 2.5(te)-.18 G
+(xpand aliases or follo)138.05 240.6 Q 2.5(w.)-.25 G(forw)235.84 240.6 Q
+(ard \214les.)-.1 E(EXPN still does.)5 E .681
+(As an optimization, if you run with your def)127 256.8 R .682(ault deli)-.1 F
+-.15(ve)-.25 G .682(ry mode being queue-only or deli).15 F -.15(ve)-.25 G -.2
+(r-).15 G 1.582
+(in-background, the RCPT command will also not chase aliases and .forw)102
+268.8 R 1.582(ard \214les.)-.1 F 1.582(It will chase)6.582 F
+(them when it processes the queue.)102 280.8 Q F0 2.5(7.30. [IPC])87 304.8 R
+(Mailers Allo)2.5 E 2.5(wM)-.1 G(ultiple Hosts)210.49 304.8 Q F1 .447
+(When an address resolv)127 321 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 333 R
+.137(This asks)5.137 F F2(sendmail)2.637 E F1 .137(to search the)2.637 F .16
+(list for the \214rst entry that is a)102 345 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 357 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 369 Q(vidual items.)-.25 E F0
+2.5(7.31. Aliases)87 393 R(Extended)2.5 E F1 1.456
+(The implementation has been mer)127 409.2 R 1.457(ged with maps.)-.18 F 1.457
+(Among other things, this supports NIS-)6.457 F(based aliases.)102 421.2 Q F0
+2.5(7.32. P)87 445.2 R(ortability and Security Enhancements)-.2 E F1 2.5(An)127
+461.4 S(umber of internal changes ha)141.72 461.4 Q .3 -.15(ve b)-.2 H
+(een made to enhance portability).15 E(.)-.65 E(Se)127 477.6 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
+(7.33. Miscellaneous)87 501.6 R(Changes)2.5 E F2(Sendmail)127 517.8 Q F1
+(writes a)2.5 E F2(/etc/sendmail.pid)2.5 E F1
+(\214le with the current process id of the SMTP daemon.)2.5 E -1 -.8(Tw o)127
+534 T 1.647(people using the same program in their .forw)4.947 F 1.646
+(ard \214le are considered dif)-.1 F 1.646(ferent so that)-.25 F
+(duplicate elimination doesn')102 546 Q 2.5(td)-.18 G(elete one of them.)225.98
+546 Q(The)127 562.2 Q F2(mailstats)3.18 E F1 .681
+(program prints mailer names and gets the location of the)3.18 F F2
+(sendmail.st)3.181 E F1 .681(\214le from)3.181 F F2(/etc/sendmail.cf)102 574.2
+Q F1(.)A(Man)127 590.4 Q 2.5(ym)-.15 G(inor b)160.46 590.4 Q(ugs ha)-.2 E .3
+-.15(ve b)-.2 H(een \214x).15 E
+(ed, such as handling of backslashes inside of quotes.)-.15 E 2.5(Ah)127 606.6
+S(ook \(ruleset 5\) has been added to allo)141.72 606.6 Q 2.5(wr)-.25 G -.25
+(ew)304.21 606.6 S(riting of local addresses after aliasing.).25 E F0 2.5(8. A)
+72 630.6 R(CKNO)-.55 E(WLEDGEMENTS)-.5 E F1(I')112 646.8 Q 2.037 -.15(ve w)-.5
+H(ork).05 E 1.737(ed on)-.1 F F2(sendmail)4.237 E F1 1.737(for man)4.237 F
+4.237(yy)-.15 G 1.737(ears, and man)267.502 646.8 R 4.237(ye)-.15 G(mplo)
+339.763 646.8 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 658.8 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
+658.8 R .282(INGRES Project at the Uni)87 670.8 R -.15(ve)-.25 G .282
+(rsity of California at Berk).15 F(ele)-.1 E 1.582 -.65(y, a)-.15 H 2.782(tB)
+.65 G .282(ritton Lee, and ag)348.21 670.8 R .281(ain on the Mammoth)-.05 F
+(and T)87 682.8 Q(itan Projects at Berk)-.35 E(ele)-.1 E -.65(y.)-.15 G .453
+(Much of the second w)112 699 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 .454
+(As he)5.454 F .781(passed me drafts of his book on)87 711 R F2(sendmail)3.281
+E F1 3.281(Iw)3.281 G .781(as inspired to start w)274.741 711 R .781
+(orking on things ag)-.1 F 3.281(ain. Bryan)-.05 F -.1(wa)3.281 G(s).1 E
+(also a)87 723 Q -.25(va)-.2 G(ilable to bounce ideas of).25 E 2.5(fo)-.25 G
+(f.)227.38 723 Q EP
+%%Page: 64 59
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-64 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(Man)112 96 Q
+2.856 -.65(y, m)-.15 H(an).65 E 4.056(yp)-.15 G 1.556(eople contrib)172.212 96
+R 1.556(uted chunks of code and ideas to)-.2 F/F2 10/Times-Italic@0 SF
+(sendmail)4.056 E F1 6.556(.I)C 4.056(th)418.476 96 S 1.557(as pro)430.312 96 R
+-.15(ve)-.15 G 4.057(nt).15 G 4.057(ob)477.006 96 S 4.057(ea)491.063 96 S .464
+(group netw)87 108 R .464(ork ef)-.1 F 2.964(fort. V)-.25 F .464
+(ersion 8 in particular w)-1.11 F .463(as a group project.)-.1 F .463
+(The follo)5.463 F .463(wing people made notable)-.25 F(contrib)87 120 Q
+(utions:)-.2 E(John Beck, He)127 136.2 Q(wlett-P)-.25 E(ackard)-.15 E -.25(Ke)
+127 148.2 S(ith Bostic, CSRG, Uni).25 E -.15(ve)-.25 G
+(rsity of California, Berk).15 E(ele)-.1 E(y)-.15 E(Andre)127 160.2 Q 2.5(wC)
+-.25 G(heng, Sun Microsystems)168.13 160.2 Q(Michael J. Corrig)127 172.2 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 184.2 Q -.15(Pa)
+127 196.2 S -.5(..)132.298 190.2 S 2.5(r\()136.85 196.2 S(Pell\) Emanuelsson)
+146.01 196.2 Q(Craig Ev)127 208.2 Q(erhart, T)-.15 E(ransarc Corporation)-.35 E
+-.8(To)127 220.2 S 2.5(mI).8 G -.25(va)150.92 220.2 S 2.5(rH).25 G
+(elbekkmo, Norwe)173.16 220.2 Q(gian School of Economics)-.15 E
+(Allan E. Johannesen, WPI)127 232.2 Q(Jonathan Kamens, OpenV)127 244.2 Q
+(ision T)-.6 E(echnologies, Inc.)-.7 E -.8(Ta)127 256.2 S
+(kahiro Kanbe, Fuji Xerox Information Systems Co., Ltd.).8 E(Brian Kantor)127
+268.2 Q 2.5(,U)-.4 G(ni)191.31 268.2 Q -.15(ve)-.25 G
+(rsity of California, San Die).15 E(go)-.15 E(Murray S. K)127 280.2 Q(uchera)
+-.15 E(wy)-.15 E 2.5(,H)-.65 G(ookUp Communication Corp.)227.41 280.2 Q
+(Bruce Lilly)127 292.2 Q 2.5(,S)-.65 G(on)182.74 292.2 Q 2.5(yU)-.15 G(.S.)
+207.31 292.2 Q(Karl London)127 304.2 Q(Motonori Nakamura, Ritsumeikan Uni)127
+316.2 Q -.15(ve)-.25 G(rsity & K).15 E(yoto Uni)-.25 E -.15(ve)-.25 G(rsity).15
+E(John Gardiner Myers, Carne)127 328.2 Q(gie Mellon Uni)-.15 E -.15(ve)-.25 G
+(rsity).15 E(Neil Rick)127 340.2 Q(ert, Northern Illinois Uni)-.1 E -.15(ve)
+-.25 G(rsity).15 E(Eric Schnoebelen, Con)127 352.2 Q .3 -.15(vex C)-.4 H
+(omputer Corp.).15 E(Eric W)127 364.2 Q(assenaar)-.8 E 2.5(,N)-.4 G
+(ational Institute for Nuclear and High Ener)200.49 364.2 Q(gy Ph)-.18 E
+(ysics, Amsterdam)-.05 E(Christophe W)127 376.2 Q(olfhugel, P)-.8 E
+(asteur Institute & Herv)-.15 E 2.5(eS)-.15 G(chauer Consultants \(P)330.05
+376.2 Q(aris\))-.15 E 3.219(Ia)87 392.4 S .719(pologize for an)97.989 392.4 R
+.719(yone I ha)-.15 F 1.019 -.15(ve o)-.2 H .719(mitted, misspelled, misattrib)
+.15 F .719(uted, or otherwise missed.)-.2 F .72(At this point, I)5.72 F 1.093
+(suspect that at least a hundred people ha)87 404.4 R 1.393 -.15(ve c)-.2 H
+(ontrib).15 E 1.093(uted code, and man)-.2 F 3.592(ym)-.15 G 1.092(ore ha)
+393.524 404.4 R 1.392 -.15(ve c)-.2 H(ontrib).15 E 1.092(uted ideas,)-.2 F
+1.533(comments, and encouragement.)87 416.4 R(I')6.534 E 1.834 -.15(ve t)-.5 H
+1.534(ried to list them in the RELEASE_NO).15 F 1.534(TES in the distrib)-.4 F
+(ution)-.2 E(directory)87 428.4 Q 5(.I)-.65 G(appreciate their contrib)135.78
+428.4 Q(ution as well.)-.2 E .743(Special thanks are reserv)112 444.6 R .743
+(ed for Michael Corrig)-.15 F .742(an and Christophe W)-.05 F .742
+(olfhugel, who besides being)-.8 F -.1(wo)87 456.6 S 5.714
+(nderful guinea pigs and contrib).1 F 5.714(utors ha)-.2 F 6.015 -.15(ve a)-.2
+H 5.715(lso consented to be added to the `).15 F(`send-)-.74 E(mail@CS.Berk)87
+468.6 Q(ele)-.1 E -.65(y.)-.15 G(EDU').65 E 3.335('l)-.74 G .835
+(ist and, by answering the b)199.005 468.6 R .835
+(ulk of the questions sent to that list, ha)-.2 F 1.134 -.15(ve f)-.2 H(reed)
+.15 E(me up to do other w)87 480.6 Q(ork.)-.1 E EP
+%%Page: 65 60
+%%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 8.06(a\207 `)184 257.4 R -.8(`A)-.74 G
+(rpanet').8 E 2.5('m)-.74 G(ode \(get en)257.53 257.4 Q -.15(ve)-.4 G
+(lope sender information from header\)).15 E 15(dR)184 269.4 S(un as a daemon)
+210.67 269.4 Q 17.22(tR)184 281.4 S(un in test mode)210.67 281.4 Q 15(vJ)184
+293.4 S(ust v)207.89 293.4 Q(erify addresses, don')-.15 E 2.5(tc)-.18 G
+(ollect or deli)319.48 293.4 Q -.15(ve)-.25 G(r).15 E 17.22(iI)184 305.4 S
+(nitialize the alias database)207.33 305.4 Q 15(pP)184 317.4 S
+(rint the mail queue)209.56 317.4 Q<ad42>72 337.8 Q F2(type)A F1
+(Indicate body type.)144 337.8 Q<ad43>72 354 Q F2(\214le)A F1 .946(Use a dif)
+144 354 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 366 Q<ad64>72 382.2 Q F2(le)A(vel)-.15 E
+F1(Set deb)144 382.2 Q(ugging le)-.2 E -.15(ve)-.25 G(l.).15 E<ad66>72 398.4 Q
+F2(addr)2.5 E F1(The sender')144 398.4 Q 2.5(sm)-.55 G(achine address is)205.1
+398.4 Q F2(addr)2.5 E F1(.)A<ad46>72 414.6 Q F2(name)A F1
+(Sets the full name of this user to)144 414.6 Q F2(name)2.5 E F1(.)A<ad68>72
+430.8 Q F2(cnt)2.5 E F1 .726(Sets the \231hop count\232 to)144 430.8 R F2(cnt)
+3.226 E F1 5.725(.T)C .725
+(his represents the number of times this message has been)269.455 430.8 R .02
+(processed by)144 442.8 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 454.8 R F2(sendmail)4.02 E F1(thro)144 466.8 Q(ws a)-.25 E -.1(wa)-.15 G
+2.5(yt).1 G(he message with an error)199.6 466.8 Q(.)-.55 E 58.86(\255n Don')72
+483 R 2.5(td)-.18 G 2.5(oa)174.65 483 S(liasing or forw)186.59 483 Q(arding.)
+-.1 E<ad72>72 499.2 Q F2(addr)2.5 E F1(An obsolete form of)144 499.2 Q/F3 10
+/Times-Bold@0 SF<ad66>2.5 E F1(.)A<ad6f>72 515.4 Q F2 1.666(xv)C(alue)-1.666 E
+F1(Set option)144 515.4 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 Section 5.6.)292.6 515.4 Q<ad4f>72
+531.6 Q F2(option)A F3(=)A F2(value)A F1(Set)6.22 E F2(option)5.173 E F1 2.674
+(to the speci\214ed)5.173 F F2(value)5.174 E F1 2.674
+(\(for long form option names\).)5.174 F 2.674(These options are)7.674 F
+(described in Section 5.6.)144 543.6 Q<ad4d>72 559.8 Q F2 1.666(xv)C 27.204
+(alue Set)-1.666 F(macr)2.5 E 2.5(oxt)-.45 G 2.5(ot)196.04 559.8 S
+(he speci\214ed value)206.32 559.8 Q(.)-.15 E F1<ad70>72 576 Q F2(pr)A(otocol)
+-.45 E F1 .401(Set the sending protocol.)144 576 R .401
+(Programs are encouraged to set this.)5.401 F .4(The protocol \214eld can be)
+5.401 F .114(in the form)144 588 R F2(pr)2.614 E(otocol)-.45 E F3(:)A F2(host)A
+F1 .114(to set both the sending protocol and sending host.)2.614 F -.15(Fo)
+5.115 G 2.615(re).15 G(xample,)472.06 588 Q 2.147(\231\255pUUCP:uunet\232 sets\
+ the sending protocol to UUCP and the sending host to uunet.)144 600 R .973
+(\(Some e)144 612 R .974
+(xisting programs use \255oM to set the r and s macros; this is equi)-.15 F
+-.25(va)-.25 G .974(lent to using).25 F(\255p.\))144 624 Q<ad71>72 640.2 Q F2
+(time)A F1 -.35(Tr)144 640.2 S 3.168(yt).35 G 3.167(op)164.038 640.2 S .667
+(rocess the queued up mail.)177.205 640.2 R .667(If the time is gi)5.667 F -.15
+(ve)-.25 G .667(n, a).15 F F2(sendmail)3.167 E F1 .667(will run through the)
+3.167 F(queue at the speci\214ed interv)144 652.2 Q(al to deli)-.25 E -.15(ve)
+-.25 G 2.5(rq).15 G(ueued mail; otherwise, it only runs once.)310.82 652.2 Q
+<ad71>72 668.4 Q F2(Xstring)A F1 .312
+(Run the queue once, limiting the jobs to those matching)144 668.4 R F2
+(Xstring)2.813 E F1 5.313(.T)C .313(he k)416.325 668.4 R .613 -.15(ey l)-.1 H
+(etter).15 E F2(X)2.813 E F1 .313(can be)2.813 F F3(I)144 680.4 Q F1 .671
+(to limit based on queue identi\214er)3.171 F(,)-.4 E F3(R)3.171 E F1 .67
+(to limit based on recipient, or)3.171 F F3(S)3.17 E F1 .67(to limit based on)
+3.17 F .32 LW 76 690 72 690 DL 80 690 76 690 DL 84 690 80 690 DL 88 690 84 690
+DL 92 690 88 690 DL 96 690 92 690 DL 100 690 96 690 DL 104 690 100 690 DL 108
+690 104 690 DL 112 690 108 690 DL 116 690 112 690 DL 120 690 116 690 DL 124 690
+120 690 DL 128 690 124 690 DL 132 690 128 690 DL 136 690 132 690 DL 140 690 136
+690 DL 144 690 140 690 DL 148 690 144 690 DL 152 690 148 690 DL 156 690 152 690
+DL 160 690 156 690 DL 164 690 160 690 DL 168 690 164 690 DL 172 690 168 690 DL
+176 690 172 690 DL 180 690 176 690 DL 184 690 180 690 DL 188 690 184 690 DL 192
+690 188 690 DL 196 690 192 690 DL 200 690 196 690 DL 204 690 200 690 DL 208 690
+204 690 DL 212 690 208 690 DL 216 690 212 690 DL/F4 8/Times-Roman@0 SF
+(\207Deprecated.)93.6 702 Q F3(Sendmail Installation and Operation Guide)72 756
+Q(SMM:08-65)452.9 756 Q EP
+%%Page: 66 61
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-66 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(sender)144 96 Q
+6.053(.A)-.55 G 1.054
+(particular queued job is accepted if one of the corresponding addresses con-)
+188.876 96 R(tains the indicated)144 108 Q/F2 10/Times-Italic@0 SF(string)2.5 E
+F1(.)A 61.08(\255t Read)72 124.2 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.539(lists. The)144 136.2 R .039
+(\231Bcc:\232 line will be deleted before sending.)2.539 F(An)5.039 E 2.539(ya)
+-.15 G .04(ddresses in the ar)385.31 136.2 R .04(gument v)-.18 F(ec-)-.15 E
+(tor will be deleted from the send list.)144 148.2 Q<ad58>72 164.4 Q F2(lo)3.18
+E(g\214le)-.1 E F1 .68(Log all traf)144.68 164.4 R .68(\214c in and out of)-.25
+F F2(sendmail)3.179 E F1 .679(in the indicated)3.179 F F2(lo)3.179 E(g\214le)
+-.1 E F1 .679(for deb)3.179 F .679(ugging mailer prob-)-.2 F 2.5(lems. This)144
+176.4 R(produces a lot of data v)2.5 E
+(ery quickly and should be used sparingly)-.15 E(.)-.65 E .637
+(There are a number of options that may be speci\214ed as primiti)97 192.6 R
+.938 -.15(ve \215)-.25 H 3.138(ags. These).15 F .638(are the e, i, m, and v)
+3.138 F 2.5(options. Also,)72 204.6 R(the f option may be speci\214ed as the)
+2.5 E F0<ad73>2.5 E F1(\215ag.)2.5 E EP
+%%Page: 67 62
+%%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 31(qT)72 313.8 S
+(he queue control \214le.)114.11 313.8 Q
+(This \214le contains the information necessary to process the job)5 E(.)-.4 E
+33.22(tA)72 330 S .345(temporary \214le.)118.065 330 R .344
+(These are an image of the)5.345 F F2(qf)2.844 E F1 .344
+(\214le when it is being reb)2.844 F 2.844(uilt. It)-.2 F .344
+(should be renamed)2.844 F(to a)108 342 Q F2(qf)2.5 E F1(\214le v)2.5 E
+(ery quickly)-.15 E(.)-.65 E 31(xA)72 358.2 S .566(transcript \214le, e)118.286
+358.2 R .567(xisting during the life of a session sho)-.15 F .567(wing e)-.25 F
+-.15(ve)-.25 G .567(rything that happens during that).15 F(session.)108 370.2 Q
+(The)97 386.4 Q F2(qf)3.334 E F1 .834
+(\214le is structured as a series of lines each be)3.334 F .833
+(ginning with a code letter)-.15 F 5.833(.T)-.55 G .833(he lines are as fol-)
+427.358 386.4 R(lo)72 398.4 Q(ws:)-.25 E 28.78(VT)72 414.6 S .819(he v)114.11
+414.6 R .819(ersion number of the queue \214le format, used to allo)-.15 F 3.32
+(wn)-.25 G -.25(ew)359.35 414.6 S F3(sendmail)3.57 E F1 .82
+(binaries to read queue)3.32 F .004(\214les created by older v)108 426.6 R
+2.504(ersions. Def)-.15 F .004(aults to v)-.1 F .004(ersion zero.)-.15 F .004
+(Must be the \214rst line of the \214le if present.)5.004 F 28.78(HA)72 442.8 S
+.329(header de\214nition.)118.049 442.8 R .329(There may be an)5.329 F 2.829
+(yn)-.15 G .329(umber of these lines.)274.283 442.8 R .33
+(The order is important: the)5.33 F 2.83(yr)-.15 G(epre-)483.46 442.8 Q .046
+(sent the order in the \214nal message.)108 454.8 R .046
+(These use the same syntax as header de\214nitions in the con\214gu-)5.046 F
+(ration \214le.)108 466.8 Q 29.33(CT)72 483 S .575(he controlling address.)
+114.11 483 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 495 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 .561(/etc/passwd \214le\);)108 507 R F3
+(aliasname)3.061 E F1 .561(is the name of the alias that e)3.061 F .562
+(xpanded to this address \(used for print-)-.15 F(ing messages\).)108 519 Q
+28.78(QT)72 535.2 S .798(he `)114.11 535.2 R .798(`original recipient')-.74 F
+.798(', speci\214ed by the ORCPT= \214eld in an ESMTP transaction.)-.74 F .797
+(Used e)5.797 F(xclu-)-.15 E(si)108 547.2 Q -.15(ve)-.25 G(ly for Deli).15 E
+-.15(ve)-.25 G(ry Status Noti\214cations.).15 E
+(It applies only to the immediately follo)5 E(wing `R' line.)-.25 E 29.33(RA)72
+563.4 S .705(recipient address.)118.425 563.4 R .705
+(This will normally be completely aliased, b)5.705 F .705
+(ut is actually realiased when the)-.2 F .493(job is processed.)108 575.4 R
+.492(There will be one line for each recipient.)5.493 F -1.11(Ve)5.492 G .492
+(rsion 1 qf \214les also include a lead-)1.11 F .689(ing colon-terminated list\
+ of \215ags, which can be `S' to return a message on successful \214nal deli)
+108 587.4 R(v-)-.25 E(ery)108 599.4 Q 3.328(,`)-.65 G .828
+(F' to return a message on f)129.278 599.4 R .828
+(ailure, `D' to return a message if the message is delayed, `B' to)-.1 F .94
+(indicate that the body should be returned, `N' to suppress returning the body)
+108 611.4 R 3.441(,a)-.65 G .941(nd `P' to declare)434.807 611.4 R(this as a `)
+108 623.4 Q(`primary')-.74 E 2.5('\()-.74 G
+(command line or SMTP-session\) address.)192.05 623.4 Q 30.44(ST)72 639.6 S
+(he sender address.)114.11 639.6 Q(There may only be one of these lines.)5 E
+29.89(TT)72 655.8 S(he job creation time.)114.11 655.8 Q
+(This is used to compute when to time out the job)5 E(.)-.4 E 30.44(PT)72 672 S
+.114(he current message priority)114.11 672 R 5.114(.T)-.65 G .113
+(his is used to order the queue.)236.666 672 R .113(Higher numbers mean lo)
+5.113 F .113(wer priori-)-.25 F 3.676(ties. The)108 684 R 1.176
+(priority changes as the message sits in the queue.)3.676 F 1.177
+(The initial priority depends on the)6.176 F
+(message class and the size of the message.)108 696 Q 27.11(MA)72 712.2 S 2.704
+(message. This)117.924 712.2 R .204(line is printed by the)2.704 F F3(mailq)
+2.704 E F1 .203(command, and is generally used to store status infor)2.704 F(-)
+-.2 E 2.5(mation. It)108 724.2 R(can contain an)2.5 E 2.5(yt)-.15 G -.15(ex)
+219.78 724.2 S(t.).15 E F2(Sendmail Installation and Operation Guide)72 756 Q
+(SMM:08-67)452.9 756 Q EP
+%%Page: 68 63
+%%BeginPageSetup
+BP
+%%EndPageSetup
+/F0 10/Times-Bold@0 SF 193.36(SMM:08-68 Sendmail)72 60 R
+(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 30.44(FF)72 96 S
+.043(lag bits, represented as one letter per \215ag.)113.56 96 R .043
+(De\214ned \215ag bits are)5.043 F F0(r)2.543 E F1 .044
+(indicating that this is a response)2.544 F .143(message and)108 108 R F0(w)
+2.643 E F1 .143(indicating that a w)2.643 F .142
+(arning message has been sent announcing that the mail has been)-.1 F(delayed.)
+108 120 Q 28.78(NT)72 136.2 S(he total number of deli)114.11 136.2 Q -.15(ve)
+-.25 G(ry attempts.).15 E 28.78(KT)72 152.4 S
+(he time \(as seconds since January 1, 1970\) of the last deli)114.11 152.4 Q
+-.15(ve)-.25 G(ry attempt.).15 E 32.67(IT)72 168.6 S .724
+(he i-number of the data \214le; this can be used to reco)114.11 168.6 R -.15
+(ve)-.15 G 3.225(ry).15 G .725(our mail queue after a disastrous disk)350.23
+168.6 R(crash.)108 180.6 Q 31($A)72 196.8 S .83(macro de\214nition.)118.55
+196.8 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 196.8 R
+(through to the queue run phase.)108 208.8 Q 29.33(BT)72 225 S .924
+(he body type.)114.11 225 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 237 R(Le)5.008 E -.05(ga)-.15 G(l).05 E -.25(va)
+108 249 S(lues are \2317BIT\232 and \2318BITMIME\232.).25 E 28.78(OT)72 265.2 S
+(he original MTS v)114.11 265.2 Q(alue \(from the ESMTP transaction\).)-.25 E
+-.15(Fo)5 G 2.5(rD).15 G(eli)359.52 265.2 Q -.15(ve)-.25 G 2.5(rS).15 G
+(tatus Noti\214cations only)389.95 265.2 Q(.)-.65 E 29.89(ZT)72 281.4 S
+(he original en)114.11 281.4 Q -.15(ve)-.4 G
+(lope id \(from the ESMTP transaction\).).15 E -.15(Fo)5 G 2.5(rD).15 G(eli)
+360.88 281.4 Q -.15(ve)-.25 G 2.5(rS).15 G(tatus Noti\214cations only)391.31
+281.4 Q(.)-.65 E 4.072(As an e)97 297.6 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 311.6 Q(eef)-.1 E(fe.CS.Berk)
+-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU\232).65 E/F2 7/Times-Roman@0 SF(1)219.09
+307.6 Q F1(:)222.59 311.6 Q(P835771)112 327.8 Q(T404261372)112 339.8 Q(Seric)
+112 351.8 Q(Ceric:sendmail@v)112 363.8 Q(angogh.CS.Berk)-.25 E(ele)-.1 E -.65
+(y.)-.15 G(EDU).65 E(Reric@mammoth.Berk)112 375.8 Q(ele)-.1 E -.65(y.)-.15 G
+(EDU).65 E(Rbostic@ok)112 387.8 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 399.8 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
+411.8 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
+423.8 Q(Hrecei)112 435.8 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 447.8 Q
+(Hrecei)112 459.8 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 471.8 Q(Hrecei)112 483.8 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 495.8 Q(H?F?from: eric@foo.bar)112
+507.8 Q(.baz.de \(Eric Allman\))-.55 E(H?x?full-name: Eric Allman)112 519.8 Q
+(Hmessage-id: <9207170931.AA22757@foo.bar)112 531.8 Q(.baz.de>)-.55 E(HT)112
+543.8 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 555.8 Q(xample message)-.15 E .657(This sho)72
+572 R .658(ws the person who sent the message, the submission time \(in second\
+s since January 1, 1970\), the)-.25 F(message priority)72 584 Q 2.5(,t)-.65 G
+(he message class, the recipients, and the headers for the message.)145.51 584
+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/F3 5/Times-Roman@0 SF(1)93.6
+679.6 Q/F4 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: 69 64
+%%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.52(This is a summary of the support \214les that)97
+201 R/F2 10/Times-Italic@0 SF(sendmail)4.019 E F1 1.519(creates or generates.)
+4.019 F(Man)6.519 E 4.019(yo)-.15 G 4.019(ft)444.743 201 S 1.519(hese can be)
+454.872 201 R(changed by editing the sendmail.cf \214le; check there to \214nd\
+ the actual 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.734(Al)144 269.4 S 1.235
+(ink to /usr/sbin/sendmail; causes the alias database to be reb)157.734 269.4 R
+3.735(uilt. Running)-.2 F 1.235(this pro-)3.735 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.703(al)3.703 G 1.203
+(isting of the mail queue.)181.966 297.6 R 1.202(This program is equi)6.203 F
+-.25(va)-.25 G 1.202(lent to using the).25 F F3(\255bp)3.702 E F1 1.202
+(\215ag to)3.702 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
+(/usr/lib/sendmail.hf)72 342 Q(The SMTP help \214le.)144 354 Q 7
+(/etc/sendmail.st A)72 370.2 R(statistics \214le; need not be present.)2.5 E
+.89(/etc/sendmail.pid Created)72 386.4 R .318
+(in daemon mode; it contains the process id of the current SMTP daemon.)2.818 F
+.318(If you)5.318 F .338(use this in scripts; use `)144 398.4 R .338
+(`head \2551')-.74 F 2.838('t)-.74 G 2.838(og)285.786 398.4 S .338
+(et just the \214rst line; later v)298.624 398.4 R .337(ersions of)-.15 F F2
+(sendmail)2.837 E F1(may)2.837 E(add information to subsequent lines.)144 410.4
+Q 25.62(/etc/aliases The)72 426.6 R(te)2.5 E(xtual v)-.15 E
+(ersion of the alias \214le.)-.15 E(/etc/aliases.{pag,dir})72 442.8 Q
+(The alias \214le in)144 454.8 Q F2(dbm)2.5 E F1(\(3\) format.)1.666 E(/v)72
+471 Q(ar/spool/mqueue)-.25 E
+(The directory in which the mail queue and temporary \214les reside.)144 483 Q
+(/v)72 499.2 Q(ar/spool/mqueue/qf*)-.25 E
+(Control \(queue\) \214les for messages.)144 511.2 Q(/v)72 527.4 Q
+(ar/spool/mqueue/df*)-.25 E(Data \214les.)144 539.4 Q(/v)72 555.6 Q
+(ar/spool/mqueue/tf*)-.25 E -.7(Te)144 567.6 S(mporary v).7 E
+(ersions of the qf \214les, used during queue \214le reb)-.15 E(uild.)-.2 E(/v)
+72 583.8 Q(ar/spool/mqueue/xf*)-.25 E 2.5(At)144 595.8 S
+(ranscript of the current session.)156.5 595.8 Q F3
+(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-69)452.9 756 Q EP
+%%Page: 2 65
+%%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 10/Times-Roman@0 SF
+(This page intentionally left blank;)256.225 300 Q
+(replace it with a blank sheet for double-sided output.)218.6 312 Q EP
+%%Page: 3 66
+%%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 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(7)499
+124.8 Q 2.5(1.1. Compiling)87 139.2 R .43(Sendmail ...........................\
+..............................................................................\
+.....)2.5 F(7)499 139.2 Q 2.5(1.1.1. T)102 153.6 R(weaking the Mak)-.8 E 1.64(\
+e\214le ......................................................................\
+...........................)-.1 F(7)499 153.6 Q 2.5(1.1.2. Compilation)102 168
+R(and installation)2.5 E 28.5(................................................\
+........................................ 8)4.6 F 2.5(1.2. Con\214guration)87
+182.4 R .99(Files ............................................................\
+....................................................)2.5 F(8)499 182.4 Q 2.5
+(1.3. Details)87 196.8 R(of Installation Files)2.5 E 28.5(....................\
+..............................................................................\
+. 9)4.89 F 2.5(1.3.1. /usr/sbin/sendmail)102 211.2 R 28.5(....................\
+..............................................................................\
+....... 9)2.66 F 2.5(1.3.2. /etc/sendmail.cf)102 225.6 R 28.5(................\
+..............................................................................\
+.............. 9)4.9 F 2.5(1.3.3. /usr/bin/ne)102 240 R -.1(wa)-.25 G 2.19(lia\
+ses ..........................................................................\
+.............................).1 F(10)494 240 Q 2.5(1.3.4. /v)102 254.4 R 1.81
+(ar/spool/mqueue .............................................................\
+...........................................)-.25 F(10)494 254.4 Q 2.5
+(1.3.5. /etc/aliases*)102 268.8 R 23.5(.......................................\
+........................................................................... 10)
+4.62 F 2.5(1.3.6. /etc/rc)102 283.2 R 23.5(...................................\
+..............................................................................\
+........... 10)3.51 F 2.5(1.3.7. /usr/lib/sendmail.hf)102 297.6 R 23.5(.......\
+..............................................................................\
+.................. 11)2.94 F 2.5(1.3.8. /etc/sendmail.st)102 312 R 23.5(......\
+..............................................................................\
+......................... 11)3.5 F 2.5(1.3.9. /usr/bin/mailq)102 326.4 R 23.5(\
+..............................................................................\
+................................. 11)4.88 F 2.5(2. NORMAL)72 340.8 R(OPERA)2.5
+E 1.56(TIONS .................................................................\
+............................................)-1.11 F(11)494 340.8 Q 2.5
+(2.1. The)87 355.2 R(System Log)2.5 E 23.5(...................................\
+..............................................................................\
+... 11)4.89 F 2.5(2.1.1. F)102 369.6 R 2.26(ormat ............................\
+..............................................................................\
+................)-.15 F(11)494 369.6 Q 2.5(2.1.2. Le)102 384 R -.15(ve)-.25 G
+2.24(ls ......................................................................\
+.....................................................).15 F(13)494 384 Q 2.5
+(2.2. Dumping)87 398.4 R .72(State ...........................................\
+............................................................................)
+2.5 F(13)494 398.4 Q 2.5(2.3. The)87 412.8 R(Mail Queue)2.5 E 23.5(...........\
+..............................................................................\
+............................ 13)2.96 F 2.5(2.3.1. Printing)102 427.2 R
+(the queue)2.5 E 23.5(........................................................\
+................................................. 14)2.67 F 2.5(2.3.2. F)102
+441.6 R(orcing the queue)-.15 E 23.5(.........................................\
+................................................................ 14)3.94 F 2.5
+(2.4. The)87 456 R(Service Switch)2.5 E 23.5(.................................\
+..............................................................................\
+. 14)2.68 F 2.5(2.5. The)87 470.4 R(Alias Database)2.5 E 23.5(................\
+..............................................................................\
+.................. 15)2.69 F 2.5(2.5.1. Reb)102 484.8 R
+(uilding the alias database)-.2 E 23.5(.......................................\
+................................................ 16)4.27 F 2.5
+(2.5.2. Potential)102 499.2 R .72(problems ...................................\
+.....................................................................)2.5 F(16)
+494 499.2 Q 2.5(2.5.3. List)102 513.6 R -.25(ow)2.5 G 1.81(ners ..............\
+..............................................................................\
+.......................).25 F(16)494 513.6 Q 2.5(2.6. User)87 528 R
+(Information Database)2.5 E 23.5(.............................................\
+....................................................... 17)2.7 F 2.5(2.7. Per)
+87 542.4 R(-User F)-.2 E(orw)-.15 E(arding \(.forw)-.1 E(ard Files\))-.1 E 23.5
+(.............................................................................\
+...... 17)4.09 F 2.5(2.8. Special)87 556.8 R(Header Lines)2.5 E 23.5(.........\
+..............................................................................\
+...................... 17)2.97 F 2.5(2.8.1. Errors-T)102 571.2 R 2.09(o: .....\
+..............................................................................\
+..................................)-.8 F(17)494 571.2 Q 2.5
+(2.8.2. Apparently-T)102 585.6 R 2.09(o: .....................................\
+........................................................................)-.8 F
+(17)494 585.6 Q 2.5(2.8.3. Precedence)102 600 R 23.5(.........................\
+..............................................................................\
+............. 17)2.97 F 2.5(2.9. IDENT)87 614.4 R(Protocol Support)2.5 E 23.5(\
+..............................................................................\
+......................... 18)2.95 F 2.5(3. ARGUMENTS)72 628.8 R 23.5(.........\
+..............................................................................\
+........................................ 18)3.78 F 2.5(3.1. Queue)87 643.2 R
+(Interv)2.5 E 1.55(al ........................................................\
+...............................................................)-.25 F(18)494
+643.2 Q 2.5(3.2. Daemon)87 657.6 R 1.29(Mode .................................\
+..............................................................................\
+........)2.5 F(18)494 657.6 Q 2.5(3.3. F)87 672 R(orcing the Queue)-.15 E 23.5
+(.............................................................................\
+.................................... 19)4.22 F 2.5(3.4. Deb)87 686.4 R 1.76(ug\
+ging .........................................................................\
+....................................................)-.2 F(19)494 686.4 Q 2.5
+(3.5. Changing)87 700.8 R(the V)2.5 E(alues of Options)-1.11 E 23.5(..........\
+..............................................................................\
+.... 19)3.23 F 2.5(3.6. T)87 715.2 R(rying a Dif)-.35 E
+(ferent Con\214guration File)-.25 E 23.5(.....................................\
+.............................................. 20)4.67 F EP
+%%Page: 4 67
+%%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
+(3.7. Logging)87 96 R -.35(Tr)2.5 G(af).35 E .5(\214c ........................\
+..............................................................................\
+................)-.25 F(20)494 96 Q 2.5(3.8. T)87 110.4 R
+(esting Con\214guration Files)-.7 E 23.5(.....................................\
+.............................................................. 20)4.19 F 2.5
+(4. TUNING)72 124.8 R 23.5(...................................................\
+..............................................................................\
+........ 21)2.68 F 2.5(4.1. T)87 139.2 R 1.07(imeouts ........................\
+..............................................................................\
+..........................)-.35 F(21)494 139.2 Q 2.5(4.1.1. Queue)102 153.6 R
+(interv)2.5 E 2.1(al .........................................................\
+.....................................................)-.25 F(21)494 153.6 Q 2.5
+(4.1.2. Read)102 168 R 1(timeouts ............................................\
+...................................................................)2.5 F(21)
+494 168 Q 2.5(4.1.3. Message)102 182.4 R 1.56(timeouts .......................\
+..............................................................................\
+....)2.5 F(22)494 182.4 Q 2.5(4.2. F)87 196.8 R(orking During Queue Runs)-.15 E
+23.5(.........................................................................\
+........................ 23)4.49 F 2.5(4.3. Queue)87 211.2 R .73(Priorities ..\
+..............................................................................\
+.....................................)2.5 F(23)494 211.2 Q 2.5(4.4. Load)87
+225.6 R .44(Limiting .........................................................\
+...............................................................)2.5 F(24)494
+225.6 Q 2.5(4.5. Deli)87 240 R -.15(ve)-.25 G(ry Mode).15 E 23.5(.............\
+..............................................................................\
+............................ 24)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(................................................\
+..............................................................................\
+ 24)153 254.4 R 2.5(4.7. File)87 268.8 R .72(Modes ...........................\
+..............................................................................\
+....................)2.5 F(25)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(......................................\
+........................................................... 25)6.52 F 2.5
+(4.7.2. Should)102 297.6 R(my alias database be writable?)2.5 E 23.5
+(........................................................................ 25)
+5.47 F 2.5(4.8. Connection)87 312 R 1.56(Caching .............................\
+..............................................................................\
+...)2.5 F(25)494 312 Q 2.5(4.9. Name)87 326.4 R(Serv)2.5 E(er Access)-.15 E
+23.5(.........................................................................\
+..................................... 26)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(...........\
+......................................................................... 27)
+3.84 F 2.5(4.11. Free)87 355.2 R 1.85(Space ..................................\
+..............................................................................\
+...........)2.5 F(27)494 355.2 Q 2.5(4.12. Maximum)87 369.6 R(Message Size)2.5
+E 23.5(.......................................................................\
+.............................. 27)4.62 F 2.5(4.13. Pri)87 384 R -.25(va)-.25 G
+.3 -.15(cy F).25 H 1.93(lags .................................................\
+......................................................................).15 F
+(27)494 384 Q 2.5(4.14. Send)87 398.4 R(to Me T)2.5 E 2.08(oo ................\
+..............................................................................\
+.....................)-.8 F(27)494 398.4 Q 2.5(5. THE)72 412.8 R
+(WHOLE SCOOP ON THE CONFIGURA)2.5 E(TION FILE)-1.11 E 23.5
+(........................................................ 28)4.64 F 2.5(5.1. R)
+87 427.2 R(and S \212 Re)2.5 E(writing Rules)-.25 E 23.5(.....................\
+............................................................................. \
+28)4.3 F 2.5(5.1.1. The)102 441.6 R(left hand side)2.5 E 23.5(................\
+..............................................................................\
+........... 28)4.07 F 2.5(5.1.2. The)102 456 R(right hand side)2.5 E 23.5(....\
+..............................................................................\
+..................... 29)3.51 F 2.5(5.1.3. Semantics)102 470.4 R(of re)2.5 E
+(writing rule sets)-.25 E 23.5(...............................................\
+.................................... 30)4.6 F 2.5(5.1.4. IPC)102 484.8 R 1(mai\
+lers .........................................................................\
+..........................................)2.5 F(31)494 484.8 Q 2.5(5.2. D)87
+499.2 R 2.5<8a44>2.5 G(e\214ne Macro)136.44 499.2 Q 23.5(.....................\
+..............................................................................\
+............. 31)3.52 F 2.5(5.3. C)87 513.6 R(and F \212 De\214ne Classes)2.5 E
+23.5(.........................................................................\
+............................ 34)2.67 F 2.5(5.4. M)87 528 R 2.5<8a44>2.5 G
+(e\214ne Mailer)138.11 528 Q 23.5(............................................\
+................................................................... 35)3.79 F
+2.5(5.5. H)87 542.4 R 2.5<8a44>2.5 G(e\214ne Header)136.44 542.4 Q 23.5(......\
+..............................................................................\
+........................... 38)3.25 F 2.5(5.6. O)87 556.8 R 2.5<8a53>2.5 G
+(et Option)134.78 556.8 Q 23.5(...............................................\
+...................................................................... 38)3.22
+F 2.5(5.7. P)87 571.2 R 2.5<8a50>2.5 G(recedence De\214nitions)133.12 571.2 Q
+23.5(.........................................................................\
+......................... 46)2.96 F 2.5(5.8. V)87 585.6 R 2.5<8a43>2.5 G
+(on\214guration V)135.89 585.6 Q(ersion Le)-1.11 E -.15(ve)-.25 G 2.8(l.).15 G
+23.5(.........................................................................\
+............... 46)248 585.6 R 2.5(5.9. K)87 600 R 2.5<8a4b>2.5 G .3 -.15(ey F)
+136.19 600 T(ile Declaration).15 E 23.5(......................................\
+............................................................... 47)2.81 F 2.5
+(5.10. The)87 614.4 R(User Database)2.5 E 23.5(...............................\
+..............................................................................\
+. 50)4.92 F 2.5(5.10.1. Structure)102 628.8 R(of the user database)2.5 E 23.5(\
+..............................................................................\
+....... 50)2.7 F 2.5(5.10.2. User)102 643.2 R(database semantics)2.5 E 23.5(..\
+..............................................................................\
+............. 51)3.25 F 2.5(5.10.3. Creating)102 659.6 R(the database)2.5 E/F2
+7/Times-Roman@0 SF(21)220.59 655.6 Q F1 23.5(.................................\
+.............................................................. 51)230.5 659.6 R
+2.5(6. O)72 674 R(THER CONFIGURA)-.4 E 1.97(TION .............................\
+............................................................................)
+-1.11 F(52)494 674 Q 2.5(6.1. P)87 688.4 R(arameters in src/Mak)-.15 E 1.55(e\
+\214le .......................................................................\
+.............................)-.1 F(52)494 688.4 Q 2.5(6.2. P)87 702.8 R
+(arameters in src/conf.h)-.15 E 23.5(.........................................\
+............................................................... 52)4.23 F 2.5
+(6.3. Con\214guration)87 717.2 R(in src/conf.c)2.5 E 23.5(....................\
+..............................................................................\
+.. 55)3.51 F EP
+%%Page: 5 68
+%%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(6.3.1. Built-in)102 96 R
+(Header Semantics)2.5 E 23.5(.................................................\
+.......................................... 55)4.9 F 2.5(6.3.2. Restricting)102
+110.4 R(Use of Email)2.5 E 23.5(..............................................\
+................................................ 56)4.34 F 2.5(6.3.3. Load)102
+124.8 R -1.17 -.74(Av e)2.5 H(rage Computation).74 E 23.5(....................\
+...................................................................... 57)2.74
+F 2.5(6.3.4. Ne)102 139.2 R 2.5(wD)-.25 G(atabase Map Classes)157.85 139.2 Q
+23.5(.........................................................................\
+................ 57)4.89 F 2.5(6.3.5. Queueing)102 153.6 R 1.56(Function .....\
+..............................................................................\
+....................)2.5 F(58)494 153.6 Q 2.5(6.3.6. Refusing)102 168 R
+(Incoming SMTP Connections)2.5 E 23.5
+(....................................................................... 58)
+2.94 F 2.5(6.3.7. Load)102 182.4 R -1.17 -.74(Av e)2.5 H(rage Computation).74 E
+23.5(.........................................................................\
+................. 58)2.74 F 2.5(6.4. Con\214guration)87 196.8 R
+(in src/daemon.c)2.5 E 23.5(..................................................\
+............................................ 58)4.62 F 2.5(7. CHANGES)72 211.2
+R(IN VERSION 8)2.5 E 23.5(....................................................\
+...................................................... 59)4.9 F 2.5
+(7.1. Connection)87 225.6 R 1.56(Caching .....................................\
+.........................................................................)2.5 F
+(59)494 225.6 Q 2.5(7.2. MX)87 240 R 2.39(Piggybacking .......................\
+..............................................................................\
+............)2.5 F(59)494 240 Q 2.5(7.3. RFC)87 254.4 R(1123 Compliance)2.5 E
+23.5(.........................................................................\
+................................. 59)3.77 F 2.5(7.4. Extended)87 268.8 R
+(SMTP Support)2.5 E 23.5(.....................................................\
+.................................................. 59)2.94 F 2.5
+(7.5. Eight-Bit)87 283.2 R .44(Clean .........................................\
+.............................................................................)
+2.5 F(59)494 283.2 Q 2.5(7.6. User)87 297.6 R .47(Database ...................\
+..............................................................................\
+.......................)2.5 F(59)494 297.6 Q 2.5(7.7. Impro)87 312 R -.15(ve)
+-.15 G 2.5(dB).15 G(IND Support)154.75 312 Q 23.5(............................\
+........................................................................... 60)
+3.81 F 2.5(7.8. K)87 326.4 R -.15(ey)-.25 G(ed Files).15 E 23.5(..............\
+..............................................................................\
+................................ 60)3.35 F 2.5(7.9. Multi-W)87 340.8 R
+(ord Classes)-.8 E 23.5(......................................................\
+......................................................... 60)3.47 F 2.5
+(7.10. Deferred)87 355.2 R(Macro Expansion)2.5 E 23.5(........................\
+......................................................................... 60)
+4.65 F 2.5(7.11. IDENT)87 369.6 R(Protocol Support)2.5 E 23.5(................\
+..............................................................................\
+....... 60)2.95 F 2.5(7.12. P)87 384 R(arsing Bug Fix)-.15 E .46(es ..........\
+..............................................................................\
+........................)-.15 F(60)494 384 Q 2.5(7.13. Separate)87 398.4 R(En)
+2.5 E -.15(ve)-.4 G(lope/Header Processing).15 E 23.5(........................\
+........................................................ 60)4.37 F 2.5
+(7.14. Owner)87 412.8 R(-List Propag)-.2 E(ates to En)-.05 E -.15(ve)-.4 G 1.27
+(lope ........................................................................\
+............).15 F(60)494 412.8 Q 2.5(7.15. Dynamic)87 427.2 R
+(Header Allocation)2.5 E 23.5(................................................\
+................................................ 60)3.25 F 2.5(7.16. Ne)87
+441.6 R 2.5(wC)-.25 G(ommand Line Flags)139.8 441.6 Q 23.5(...................\
+..............................................................................\
+. 60)3.2 F 2.5(7.17. Enhanced)87 456 R(Command Line Flags)2.5 E 23.5(.........\
+..............................................................................\
+.. 61)4.9 F 2.5(7.18. Ne)87 470.4 R 2.5(wa)-.25 G
+(nd Old Con\214guration Line T)137.57 470.4 Q .4(ypes ........................\
+......................................................)-.8 F(61)494 470.4 Q 2.5
+(7.19. Ne)87 484.8 R 2.5(wO)-.25 G .7(ptions .................................\
+..............................................................................\
+.........)140.35 484.8 R(61)494 484.8 Q 2.5(7.20. Extended)87 499.2 R 1.56(Opt\
+ions .........................................................................\
+.......................................)2.5 F(61)494 499.2 Q 2.5(7.21. Ne)87
+513.6 R 2.5(wM)-.25 G(ailer Flags)142.02 513.6 Q 23.5(........................\
+..............................................................................\
+.......... 61)4.04 F 2.5(7.22. Long)87 528 R(Option Names)2.5 E 23.5(.........\
+..............................................................................\
+..................... 62)4.34 F 2.5(7.23. Ne)87 542.4 R 2.5(wP)-.25 G
+(re-De\214ned Macros)138.69 542.4 Q 23.5(.....................................\
+............................................................... 62)4.06 F 2.5
+(7.24. Ne)87 556.8 R 2.5(wL)-.25 G(HS T)139.24 556.8 Q(ok)-.8 E 1.33(en ......\
+..............................................................................\
+..............................)-.1 F(62)494 556.8 Q 2.5(7.25. Bigger)87 571.2 R
+(Def)2.5 E(aults .............................................................\
+.......................................................)-.1 E(62)494 571.2 Q
+2.5(7.26. Dif)87 585.6 R(ferent Def)-.25 E(ault T)-.1 E(uning P)-.45 E 1.99(ar\
+ameters ......................................................................\
+............)-.15 F(62)494 585.6 Q 2.5(7.27. Auto-Quoting)87 600 R
+(in Addresses)2.5 E 23.5(.....................................................\
+............................................ 63)3.51 F 2.5(7.28. Symbolic)87
+614.4 R(Names On Error Mailer)2.5 E 23.5(.....................................\
+................................................. 63)4.91 F 2.5(7.29. SMTP)87
+628.8 R(VRFY Doesn')2.5 E 2.5(tE)-.18 G 1.18(xpand ...........................\
+.................................................................)209.88 628.8
+R(63)494 628.8 Q 2.5(7.30. [IPC])87 643.2 R(Mailers Allo)2.5 E 2.5(wM)-.25 G
+(ultiple Hosts)205.91 643.2 Q 23.5(...........................................\
+........................................ 63)3.75 F 2.5(7.31. Aliases)87 657.6 R
+1.29(Extended ................................................................\
+.................................................)2.5 F(63)494 657.6 Q 2.5
+(7.32. Portability)87 672 R(and Security Enhancements)2.5 E 23.5(.............\
+.................................................................. 63)2.68 F
+2.5(7.33. Miscellaneous)87 686.4 R 1.29(Changes ..............................\
+.........................................................................)2.5 F
+(63)494 686.4 Q 2.5(8. A)72 700.8 R(CKNO)-.4 E .1(WLEDGEMENTS ................\
+..............................................................................\
+..............)-.35 F(63)494 700.8 Q(Appendix A.)72 715.2 Q(COMMAND LINE FLA)5
+E 1.97(GS ....................................................................\
+.....................)-.4 F(65)494 715.2 Q EP
+%%Page: 6 69
+%%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(Appendix B.)72
+96 Q -.1(QU)5 G(EUE FILE FORMA).1 E 1.38(TS ..................................\
+..........................................................)-1.11 F(67)494 96 Q
+(Appendix C.)72 110.4 Q(SUMMAR)5 E 2.5(YO)-.65 G 2.5(FS)188.85 110.4 S(UPPOR)
+202.47 110.4 Q 2.5(TF)-.6 G 1.12(ILES ........................................\
+......................................)248.27 110.4 R(69)494 110.4 Q EP
+%%Trailer
+end
+%%EOF
diff --git a/usr.sbin/sendmail/mail.local/Makefile b/usr.sbin/sendmail/mail.local/Makefile
new file mode 100644
index 000000000000..e8556d8ea5c6
--- /dev/null
+++ b/usr.sbin/sendmail/mail.local/Makefile
@@ -0,0 +1,9 @@
+# @(#)Makefile 8.1 (Berkeley) 7/19/93
+
+PROG= mail.local
+MAN8= mail.local.0
+BINOWN= root
+BINMODE=4555
+INSTALLFLAGS=-fschg
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/mail.local/mail.local.8 b/usr.sbin/sendmail/mail.local/mail.local.8
new file mode 100644
index 000000000000..661615c462f8
--- /dev/null
+++ b/usr.sbin/sendmail/mail.local/mail.local.8
@@ -0,0 +1,105 @@
+.\" 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
+.\" 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.
+.\"
+.\" @(#)mail.local.8 8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt MAIL.LOCAL 8
+.Os
+.Sh NAME
+.Nm mail.local
+.Nd store mail in a mailbox
+.Sh SYNOPSIS
+.Nm mail.local
+.Op Fl f Ar from
+.Ar user ...
+.Sh DESCRIPTION
+.Nm Mail.local
+reads the standard input up to an end-of-file and appends it to each
+.Ar user's
+.Pa mail
+file.
+The
+.Ar user
+must be a valid user name.
+.Pp
+The options are as follows:
+.Bl -tag -width xxxfrom
+.It Fl f Ar from
+Specify the sender's name.
+.El
+.Pp
+Individual mail messages in the mailbox are delimited by an empty
+line followed by a line beginning with the string ``From ''.
+A line containing the string ``From '', the sender's name and a time stamp
+is prepended to each delivered mail message.
+A blank line is appended to each message.
+A greater-than character (``>'') is prepended to any line in the message
+which could be mistaken for a ``From '' delimiter line.
+.Pp
+The mail files are exclusively locked with
+.Xr flock 2
+while mail is appended.
+.Pp
+If the ``biff'' service is returned by
+.Xr getservbyname 3 ,
+the biff server is notified of delivered mail.
+.Pp
+The
+.Nm mail.local
+utility exits 0 on success, and >0 if an error occurs.
+.Sh ENVIRONMENT
+.Bl -tag -width indent
+.It Ev TZ
+Used to set the appropriate time zone on the timestamp.
+.El
+.Sh FILES
+.Bl -tag -width /tmp/local.XXXXXX -compact
+.It Pa /tmp/local.XXXXXX
+temporary files
+.It Pa /var/mail/user
+user's mailbox directory
+.El
+.Sh SEE ALSO
+.Xr mail 1 ,
+.Xr xsend 1 ,
+.Xr flock 2 ,
+.Xr getservbyname 3 ,
+.Xr comsat 8 ,
+.Xr sendmail 8
+.Sh HISTORY
+A superset of
+.Nm mail.local
+(handling mailbox reading as well as mail delivery)
+appeared in
+.At v7 .
+as the program
+.Nm mail .
diff --git a/usr.sbin/sendmail/mail.local/mail.local.c b/usr.sbin/sendmail/mail.local/mail.local.c
new file mode 100644
index 000000000000..1ee4466c36b5
--- /dev/null
+++ b/usr.sbin/sendmail/mail.local/mail.local.c
@@ -0,0 +1,868 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * 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) 1990, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mail.local.c 8.22 (Berkeley) 6/21/95";
+#endif /* not lint */
+
+/*
+ * This is not intended to compile on System V derived systems
+ * such as Solaris or HP-UX, since they use a totally different
+ * approach to mailboxes (essentially, they have a setgid program
+ * rather than setuid, and they rely on the ability to "give away"
+ * files to do their work). IT IS NOT A BUG that this doesn't
+ * compile on such architectures.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifndef LOCK_EX
+# include <sys/file.h>
+#endif
+
+#ifdef BSD4_4
+# include "pathnames.h"
+#endif
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(protos) protos
+# else
+# define __P(protos) ()
+# define const
+# endif
+#endif
+#ifndef __dead
+# if defined(__GNUC__) && (__GNUC__ < 2 || __GNUC_MINOR__ < 5) && !defined(__STRICT_ANSI__)
+# define __dead __volatile
+# else
+# define __dead
+# endif
+#endif
+
+#ifndef BSD4_4
+# define _BSD_VA_LIST_ va_list
+extern char *strerror __P((int));
+extern int snprintf __P((char *, int, const char *, ...));
+#endif
+
+/*
+ * If you don't have setreuid, and you have saved uids, and you have
+ * a seteuid() call that doesn't try to emulate using setuid(), then
+ * you can try defining USE_SETEUID.
+ */
+#ifdef USE_SETEUID
+# define setreuid(r, e) seteuid(e)
+#endif
+
+#ifndef _PATH_LOCTMP
+# define _PATH_LOCTMP "/tmp/local.XXXXXX"
+#endif
+#ifndef _PATH_MAILDIR
+# define _PATH_MAILDIR "/var/spool/mail"
+#endif
+
+#ifndef S_ISREG
+# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG)
+#endif
+
+int eval = EX_OK; /* sysexits.h error value. */
+
+void deliver __P((int, char *));
+void e_to_sys __P((int));
+__dead void err __P((const char *, ...));
+void notifybiff __P((char *));
+int store __P((char *));
+void usage __P((void));
+void vwarn __P((const char *, _BSD_VA_LIST_));
+void warn __P((const char *, ...));
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct passwd *pw;
+ int ch, fd;
+ uid_t uid;
+ char *from;
+ extern char *optarg;
+ extern int optind;
+
+ /* make sure we have some open file descriptors */
+ for (fd = 10; fd < 30; fd++)
+ (void) close(fd);
+
+ /* use a reasonable umask */
+ (void) umask(0077);
+
+#ifdef LOG_MAIL
+ openlog("mail.local", 0, LOG_MAIL);
+#else
+ openlog("mail.local", 0);
+#endif
+
+ from = NULL;
+ while ((ch = getopt(argc, argv, "df:r:")) != EOF)
+ switch(ch) {
+ case 'd': /* Backward compatible. */
+ break;
+ case 'f':
+ case 'r': /* Backward compatible. */
+ if (from != NULL) {
+ warn("multiple -f options");
+ usage();
+ }
+ from = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (!*argv)
+ usage();
+
+ /*
+ * If from not specified, use the name from getlogin() if the
+ * uid matches, otherwise, use the name from the password file
+ * corresponding to the uid.
+ */
+ uid = getuid();
+ if (!from && (!(from = getlogin()) ||
+ !(pw = getpwnam(from)) || pw->pw_uid != uid))
+ from = (pw = getpwuid(uid)) ? pw->pw_name : "???";
+
+ /*
+ * There is no way to distinguish the error status of one delivery
+ * from the rest of the deliveries. So, if we failed hard on one
+ * or more deliveries, but had no failures on any of the others, we
+ * return a hard failure. If we failed temporarily on one or more
+ * deliveries, we return a temporary failure regardless of the other
+ * failures. This results in the delivery being reattempted later
+ * at the expense of repeated failures and multiple deliveries.
+ */
+ for (fd = store(from); *argv; ++argv)
+ deliver(fd, *argv);
+ exit(eval);
+}
+
+int
+store(from)
+ char *from;
+{
+ FILE *fp;
+ time_t tval;
+ int fd, eline;
+ char line[2048];
+ char tmpbuf[sizeof _PATH_LOCTMP + 1];
+
+ strcpy(tmpbuf, _PATH_LOCTMP);
+ if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) {
+ e_to_sys(errno);
+ err("unable to open temporary file");
+ }
+ (void)unlink(tmpbuf);
+
+ (void)time(&tval);
+ (void)fprintf(fp, "From %s %s", from, ctime(&tval));
+
+ line[0] = '\0';
+ for (eline = 1; fgets(line, sizeof(line), stdin);) {
+ if (line[0] == '\n')
+ eline = 1;
+ else {
+ if (eline && line[0] == 'F' &&
+ !memcmp(line, "From ", 5))
+ (void)putc('>', fp);
+ eline = 0;
+ }
+ (void)fprintf(fp, "%s", line);
+ if (ferror(fp)) {
+ e_to_sys(errno);
+ err("temporary file write error");
+ }
+ }
+
+ /* If message not newline terminated, need an extra. */
+ if (!strchr(line, '\n'))
+ (void)putc('\n', fp);
+ /* Output a newline; note, empty messages are allowed. */
+ (void)putc('\n', fp);
+
+ if (fflush(fp) == EOF || ferror(fp)) {
+ e_to_sys(errno);
+ err("temporary file write error");
+ }
+ return (fd);
+}
+
+void
+deliver(fd, name)
+ int fd;
+ char *name;
+{
+ struct stat fsb, sb;
+ struct passwd *pw;
+ int mbfd, nr, nw, off;
+ char *p;
+ char biffmsg[100], buf[8*1024], path[MAXPATHLEN];
+ off_t curoff;
+
+ /*
+ * Disallow delivery to unknown names -- special mailboxes can be
+ * handled in the sendmail aliases file.
+ */
+ if (!(pw = getpwnam(name))) {
+ if (eval != EX_TEMPFAIL)
+ eval = EX_UNAVAILABLE;
+ warn("unknown name: %s", name);
+ return;
+ }
+ endpwent();
+
+ /*
+ * Keep name reasonably short to avoid buffer overruns.
+ * This isn't necessary on BSD because of the proper
+ * definition of snprintf(), but it can cause problems
+ * on other systems.
+ * Also, clear out any bogus characters.
+ */
+
+ if (strlen(name) > 40)
+ name[40] = '\0';
+ for (p = name; *p != '\0'; p++)
+ {
+ if (!isascii(*p))
+ *p &= 0x7f;
+ else if (!isprint(*p))
+ *p = '.';
+ }
+
+ (void)snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name);
+
+ /*
+ * If the mailbox is linked or a symlink, fail. There's an obvious
+ * race here, that the file was replaced with a symbolic link after
+ * the lstat returned, but before the open. We attempt to detect
+ * this by comparing the original stat information and information
+ * returned by an fstat of the file descriptor returned by the open.
+ *
+ * NB: this is a symptom of a larger problem, that the mail spooling
+ * directory is writeable by the wrong users. If that directory is
+ * writeable, system security is compromised for other reasons, and
+ * it cannot be fixed here.
+ *
+ * If we created the mailbox, set the owner/group. If that fails,
+ * just return. Another process may have already opened it, so we
+ * can't unlink it. Historically, binmail set the owner/group at
+ * each mail delivery. We no longer do this, assuming that if the
+ * ownership or permissions were changed there was a reason.
+ *
+ * XXX
+ * open(2) should support flock'ing the file.
+ */
+tryagain:
+ lockmbox(path);
+ if (lstat(path, &sb)) {
+ mbfd = open(path,
+ O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (mbfd == -1) {
+ if (errno == EEXIST)
+ goto tryagain;
+ } else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) {
+ e_to_sys(errno);
+ warn("chown %u.%u: %s", pw->pw_uid, pw->pw_gid, name);
+ goto err1;
+ }
+ } else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) {
+ e_to_sys(errno);
+ warn("%s: irregular file", path);
+ goto err0;
+ } else if (sb.st_uid != pw->pw_uid) {
+ warn("%s: wrong ownership (%d)", path, sb.st_uid);
+ unlockmbox();
+ return;
+ } else {
+ mbfd = open(path, O_APPEND|O_WRONLY, 0);
+ if (mbfd != -1 &&
+ (fstat(mbfd, &fsb) || fsb.st_nlink != 1 ||
+ !S_ISREG(fsb.st_mode) || sb.st_dev != fsb.st_dev ||
+ sb.st_ino != fsb.st_ino || sb.st_uid != fsb.st_uid)) {
+ warn("%s: file changed after open", path);
+ goto err1;
+ }
+ }
+
+ if (mbfd == -1) {
+ e_to_sys(errno);
+ warn("%s: %s", path, strerror(errno));
+ goto err0;
+ }
+
+ /* Wait until we can get a lock on the file. */
+ if (flock(mbfd, LOCK_EX)) {
+ e_to_sys(errno);
+ warn("%s: %s", path, strerror(errno));
+ goto err1;
+ }
+
+ /* Get the starting offset of the new message for biff. */
+ curoff = lseek(mbfd, (off_t)0, SEEK_END);
+ (void)snprintf(biffmsg, sizeof(biffmsg),
+ sizeof curoff > sizeof(long) ? "%s@%qd\n" : "%s@%ld\n",
+ name, curoff);
+
+ /* Copy the message into the file. */
+ if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) {
+ e_to_sys(errno);
+ warn("temporary file: %s", strerror(errno));
+ goto err1;
+ }
+ if (setreuid(0, pw->pw_uid) < 0) {
+ e_to_sys(errno);
+ warn("setreuid(0, %d): %s (r=%d, e=%d)",
+ pw->pw_uid, strerror(errno), getuid(), geteuid());
+ goto err1;
+ }
+#ifdef DEBUG
+ printf("new euid = %d\n", geteuid());
+#endif
+ while ((nr = read(fd, buf, sizeof(buf))) > 0)
+ for (off = 0; off < nr; off += nw)
+ if ((nw = write(mbfd, buf + off, nr - off)) < 0) {
+ e_to_sys(errno);
+ warn("%s: %s", path, strerror(errno));
+ goto err3;
+ }
+ if (nr < 0) {
+ e_to_sys(errno);
+ warn("temporary file: %s", strerror(errno));
+ goto err3;
+ }
+
+ /* Flush to disk, don't wait for update. */
+ if (fsync(mbfd)) {
+ e_to_sys(errno);
+ warn("%s: %s", path, strerror(errno));
+err3:
+ if (setreuid(0, 0) < 0) {
+ e_to_sys(errno);
+ warn("setreuid(0, 0): %s", strerror(errno));
+ }
+#ifdef DEBUG
+ printf("reset euid = %d\n", geteuid());
+#endif
+err2: (void)ftruncate(mbfd, curoff);
+err1: (void)close(mbfd);
+err0: unlockmbox();
+ return;
+ }
+
+ /* Close and check -- NFS doesn't write until the close. */
+ if (close(mbfd)) {
+ e_to_sys(errno);
+ warn("%s: %s", path, strerror(errno));
+ unlockmbox();
+ return;
+ }
+
+ if (setreuid(0, 0) < 0) {
+ e_to_sys(errno);
+ warn("setreuid(0, 0): %s", strerror(errno));
+ }
+#ifdef DEBUG
+ printf("reset euid = %d\n", geteuid());
+#endif
+ unlockmbox();
+ notifybiff(biffmsg);
+}
+
+/*
+ * user.lock files are necessary for compatibility with other
+ * systems, e.g., when the mail spool file is NFS exported.
+ * Alas, mailbox locking is more than just a local matter.
+ * EPA 11/94.
+ */
+
+char lockname[MAXPATHLEN];
+int locked = 0;
+
+lockmbox(path)
+ char *path;
+{
+ int statfailed = 0;
+
+ if (locked)
+ return;
+ sprintf(lockname, "%s.lock", path);
+ for (;; sleep(5)) {
+ int fd;
+ struct stat st;
+ time_t now;
+
+ fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0);
+ if (fd >= 0) {
+ locked = 1;
+ close(fd);
+ return;
+ }
+ if (stat(lockname, &st) < 0) {
+ if (statfailed++ > 5)
+ return;
+ continue;
+ }
+ statfailed = 0;
+ time(&now);
+ if (now < st.st_ctime + 300)
+ continue;
+ unlink(lockname);
+ }
+}
+
+unlockmbox()
+{
+ if (!locked)
+ return;
+ unlink(lockname);
+ locked = 0;
+}
+
+void
+notifybiff(msg)
+ char *msg;
+{
+ static struct sockaddr_in addr;
+ static int f = -1;
+ struct hostent *hp;
+ struct servent *sp;
+ int len;
+
+ if (!addr.sin_family) {
+ /* Be silent if biff service not available. */
+ if (!(sp = getservbyname("biff", "udp")))
+ return;
+ if (!(hp = gethostbyname("localhost"))) {
+ warn("localhost: %s", strerror(errno));
+ return;
+ }
+ addr.sin_family = hp->h_addrtype;
+ memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
+ addr.sin_port = sp->s_port;
+ }
+ if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ warn("socket: %s", strerror(errno));
+ return;
+ }
+ len = strlen(msg) + 1;
+ if (sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr))
+ != len)
+ warn("sendto biff: %s", strerror(errno));
+}
+
+void
+usage()
+{
+ eval = EX_USAGE;
+ err("usage: mail.local [-f from] user ...");
+}
+
+#if __STDC__
+void
+err(const char *fmt, ...)
+#else
+void
+err(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarn(fmt, ap);
+ va_end(ap);
+
+ exit(eval);
+}
+
+void
+#if __STDC__
+warn(const char *fmt, ...)
+#else
+warn(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ va_list ap;
+
+#if __STDC__
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ vwarn(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(fmt, ap)
+ const char *fmt;
+ _BSD_VA_LIST_ ap;
+{
+ /*
+ * Log the message to stderr.
+ *
+ * Don't use LOG_PERROR as an openlog() flag to do this,
+ * it's not portable enough.
+ */
+ if (eval != EX_USAGE)
+ (void)fprintf(stderr, "mail.local: ");
+ (void)vfprintf(stderr, fmt, ap);
+ (void)fprintf(stderr, "\n");
+
+#if !defined(ultrix) && !defined(__osf__)
+ /* Log the message to syslog. */
+ vsyslog(LOG_ERR, fmt, ap);
+#else
+ {
+ char fmtbuf[10240];
+
+ (void) sprintf(fmtbuf, fmt, ap);
+ syslog(LOG_ERR, "%s", fmtbuf);
+ }
+#endif
+}
+
+/*
+ * e_to_sys --
+ * Guess which errno's are temporary. Gag me.
+ */
+void
+e_to_sys(num)
+ int num;
+{
+ /* Temporary failures override hard errors. */
+ if (eval == EX_TEMPFAIL)
+ return;
+
+ switch(num) { /* Hopefully temporary errors. */
+#ifdef EAGAIN
+ case EAGAIN: /* Resource temporarily unavailable */
+#endif
+#ifdef EDQUOT
+ case EDQUOT: /* Disc quota exceeded */
+#endif
+#ifdef EBUSY
+ case EBUSY: /* Device busy */
+#endif
+#ifdef EPROCLIM
+ case EPROCLIM: /* Too many processes */
+#endif
+#ifdef EUSERS
+ case EUSERS: /* Too many users */
+#endif
+#ifdef ECONNABORTED
+ case ECONNABORTED: /* Software caused connection abort */
+#endif
+#ifdef ECONNREFUSED
+ case ECONNREFUSED: /* Connection refused */
+#endif
+#ifdef ECONNRESET
+ case ECONNRESET: /* Connection reset by peer */
+#endif
+#ifdef EDEADLK
+ case EDEADLK: /* Resource deadlock avoided */
+#endif
+#ifdef EFBIG
+ case EFBIG: /* File too large */
+#endif
+#ifdef EHOSTDOWN
+ case EHOSTDOWN: /* Host is down */
+#endif
+#ifdef EHOSTUNREACH
+ case EHOSTUNREACH: /* No route to host */
+#endif
+#ifdef EMFILE
+ case EMFILE: /* Too many open files */
+#endif
+#ifdef ENETDOWN
+ case ENETDOWN: /* Network is down */
+#endif
+#ifdef ENETRESET
+ case ENETRESET: /* Network dropped connection on reset */
+#endif
+#ifdef ENETUNREACH
+ case ENETUNREACH: /* Network is unreachable */
+#endif
+#ifdef ENFILE
+ case ENFILE: /* Too many open files in system */
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS: /* No buffer space available */
+#endif
+#ifdef ENOMEM
+ case ENOMEM: /* Cannot allocate memory */
+#endif
+#ifdef ENOSPC
+ case ENOSPC: /* No space left on device */
+#endif
+#ifdef EROFS
+ case EROFS: /* Read-only file system */
+#endif
+#ifdef ESTALE
+ case ESTALE: /* Stale NFS file handle */
+#endif
+#ifdef ETIMEDOUT
+ case ETIMEDOUT: /* Connection timed out */
+#endif
+#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK
+ case EWOULDBLOCK: /* Operation would block. */
+#endif
+ eval = EX_TEMPFAIL;
+ break;
+ default:
+ eval = EX_UNAVAILABLE;
+ break;
+ }
+}
+
+#ifndef BSD4_4
+
+# ifndef __osf__
+char *
+strerror(eno)
+ int eno;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ static char ebuf[60];
+
+ if (eno >= 0 && eno <= sys_nerr)
+ return sys_errlist[eno];
+ (void) sprintf(ebuf, "Error %d", eno);
+ return ebuf;
+}
+# endif
+
+# if __STDC__
+snprintf(char *buf, int bufsiz, const char *fmt, ...)
+# else
+snprintf(buf, bufsiz, fmt, va_alist)
+ char *buf;
+ int bufsiz;
+ const char *fmt;
+ va_dcl
+# endif
+{
+ va_list ap;
+
+# if __STDC__
+ va_start(ap, fmt);
+# else
+ va_start(ap);
+# endif
+ vsprintf(buf, fmt, ap);
+ va_end(ap);
+}
+
+#endif
+
+#ifdef ultrix
+
+/*
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+static int _gettemp();
+
+mkstemp(path)
+ char *path;
+{
+ int fd;
+
+ return (_gettemp(path, &fd) ? fd : -1);
+}
+
+/*
+char *
+mktemp(path)
+ char *path;
+{
+ return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
+}
+*/
+
+static
+_gettemp(path, doopen)
+ char *path;
+ register int *doopen;
+{
+ extern int errno;
+ register char *start, *trv;
+ struct stat sbuf;
+ u_int pid;
+
+ pid = getpid();
+ for (trv = path; *trv; ++trv); /* extra X's get set to 0's */
+ while (*--trv == 'X') {
+ *trv = (pid % 10) + '0';
+ pid /= 10;
+ }
+
+ /*
+ * check the target directory; if you have six X's and it
+ * doesn't exist this runs for a *very* long time.
+ */
+ for (start = trv + 1;; --trv) {
+ if (trv <= path)
+ break;
+ if (*trv == '/') {
+ *trv = '\0';
+ if (stat(path, &sbuf))
+ return(0);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return(0);
+ }
+ *trv = '/';
+ break;
+ }
+ }
+
+ for (;;) {
+ if (doopen) {
+ if ((*doopen =
+ open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+ return(1);
+ if (errno != EEXIST)
+ return(0);
+ }
+ else if (stat(path, &sbuf))
+ return(errno == ENOENT ? 1 : 0);
+
+ /* tricky little algorithm for backward compatibility */
+ for (trv = start;;) {
+ if (!*trv)
+ return(0);
+ if (*trv == 'z')
+ *trv++ = 'a';
+ else {
+ if (isdigit(*trv))
+ *trv = 'a';
+ else
+ ++*trv;
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
+
+#endif
diff --git a/usr.sbin/sendmail/mail.local/pathnames.h b/usr.sbin/sendmail/mail.local/pathnames.h
new file mode 100644
index 000000000000..8e43925450f6
--- /dev/null
+++ b/usr.sbin/sendmail/mail.local/pathnames.h
@@ -0,0 +1,37 @@
+/*-
+ * 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
+ * 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.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/4/93
+ */
+#include <paths.h>
+
+#define _PATH_LOCTMP "/tmp/local.XXXXXX"
diff --git a/usr.sbin/sendmail/mailstats/mailstats.c b/usr.sbin/sendmail/mailstats/mailstats.c
new file mode 100644
index 000000000000..97ec33be7e92
--- /dev/null
+++ b/usr.sbin/sendmail/mailstats/mailstats.c
@@ -0,0 +1,227 @@
+/*
+ * 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 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[] = "@(#)mailstats.c 8.4 (Berkeley) 8/14/94";
+#endif /* not lint */
+
+#include <sendmail.h>
+#include <mailstats.h>
+#include <pathnames.h>
+
+#define MNAMELEN 20 /* max length of mailer name */
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern char *optarg;
+ extern int optind;
+ struct statistics stat;
+ register int i;
+ int mno;
+ int ch, fd;
+ char *sfile;
+ char *cfile;
+ FILE *cfp;
+ bool mnames;
+ long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0;
+ 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;
+
+ case 'f':
+ sfile = optarg;
+ break;
+
+ case 'o':
+ mnames = FALSE;
+ break;
+
+ case '?':
+ default:
+ usage:
+ fputs("usage: mailstats [-C cffile] [-f stfile]\n", stderr);
+ exit(EX_USAGE);
+ }
+ }
+ 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 (strncasecmp(b, " StatusFile", 11) == 0 &&
+ !isalnum(b[11]))
+ {
+ /* new form -- find value */
+ b = strchr(b, '=');
+ if (b == NULL)
+ continue;
+ while (isspace(*++b))
+ continue;
+ }
+ else if (*b++ != 'S')
+ {
+ /* something else boring */
+ continue;
+ }
+
+ /* this is the S or StatusFile option -- save it */
+ strcpy(sfilebuf, b);
+ b = strchr(sfilebuf, '#');
+ if (b == NULL)
+ b = strchr(sfilebuf, '\n');
+ if (b == NULL)
+ b = &sfilebuf[strlen(sfilebuf)];
+ while (isspace(*--b))
+ continue;
+ *++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) ||
+ stat.stat_size != sizeof(stat))
+ {
+ 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%s\n",
+ mnames ? " Mailer" : "");
+ for (i = 0; i < MAXMAILERS; i++)
+ {
+ if (stat.stat_nf[i] || stat.stat_nt[i])
+ {
+ printf("%2d %6ld %10ldK %6ld %10ldK", i,
+ stat.stat_nf[i], stat.stat_bf[i],
+ stat.stat_nt[i], stat.stat_bt[i]);
+ if (mnames)
+ printf(" %s", mtable[i]);
+ printf("\n");
+ frmsgs += stat.stat_nf[i];
+ frbytes += stat.stat_bf[i];
+ tomsgs += stat.stat_nt[i];
+ tobytes += stat.stat_bt[i];
+ }
+ }
+ printf("========================================\n");
+ printf(" T %6ld %10ldK %6ld %10ldK\n",
+ frmsgs, frbytes, tomsgs, tobytes);
+ exit(EX_OK);
+}
diff --git a/usr.sbin/sendmail/makemap/makemap.8 b/usr.sbin/sendmail/makemap/makemap.8
new file mode 100644
index 000000000000..23ac522a568f
--- /dev/null
+++ b/usr.sbin/sendmail/makemap/makemap.8
@@ -0,0 +1,134 @@
+.\" 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.3 (Berkeley) 7/24/94
+.\"
+.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 d
+.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 d
+Allow duplicate keys in the map.
+This is only allowed on B-Tree format maps.
+If two identical keys are read,
+they will both be inserted into the map.
+.It Fl f
+Normally all upper case letters in the key
+are folded to lower case.
+This flag disables that behaviour.
+This is intended to mesh with the
+\-f flag in the
+\fBK\fP
+line in sendmail.cf.
+The value is never 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
index 000000000000..371b229a2175
--- /dev/null
+++ b/usr.sbin/sendmail/makemap/makemap.c
@@ -0,0 +1,496 @@
+/*
+ * 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.14 (Berkeley) 11/5/95";
+#endif /* not lint */
+
+#include <stdio.h>
+#include <sysexits.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/errno.h>
+#ifndef ISC_UNIX
+# include <sys/file.h>
+#endif
+#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;
+ size_t size;
+ } xx;
+};
+
+#define BUFSIZE 1024
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *progname;
+ bool inclnull = FALSE;
+ bool notrunc = FALSE;
+ bool allowreplace = FALSE;
+ bool allowdups = FALSE;
+ bool verbose = FALSE;
+ bool foldcase = TRUE;
+ int exitstat;
+ int opt;
+ char *typename;
+ char *mapname;
+ char *ext;
+ char *lext;
+ int lineno;
+ int st;
+ int mode;
+ enum type type;
+ int fd;
+ union
+ {
+#ifdef NDBM
+ DBM *dbm;
+#endif
+#ifdef NEWDB
+ DB *db;
+#endif
+ void *dbx;
+ } dbp;
+ union dbent key, val;
+#ifdef NEWDB
+ BTREEINFO bti;
+#endif
+ char ibuf[BUFSIZE];
+ char fbuf[MAXNAME];
+ char lbuf[MAXNAME];
+ extern char *optarg;
+ extern int optind;
+ extern bool lockfile();
+
+ progname = argv[0];
+
+ while ((opt = getopt(argc, argv, "Ndforv")) != EOF)
+ {
+ switch (opt)
+ {
+ case 'N':
+ inclnull = TRUE;
+ break;
+
+ case 'd':
+ allowdups = TRUE;
+ break;
+
+ case 'f':
+ foldcase = FALSE;
+ 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];
+ ext = NULL;
+ lext = NULL;
+
+ if (strcmp(typename, "dbm") == 0)
+ {
+ type = T_DBM;
+ lext = ".dir";
+ }
+ else if (strcmp(typename, "btree") == 0)
+ {
+ type = T_BTREE;
+ ext = ".db";
+ }
+ else if (strcmp(typename, "hash") == 0)
+ {
+ type = T_HASH;
+ ext = ".db";
+ }
+ else
+ type = T_UNKNOWN;
+ }
+
+ switch (type)
+ {
+ case T_ERR:
+ fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-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);
+
+#ifdef NEWDB
+ case T_BTREE:
+ bzero(&bti, sizeof bti);
+ if (allowdups)
+ bti.flags |= R_DUP;
+ break;
+
+ case T_HASH:
+#endif
+#ifdef NDBM
+ case T_DBM:
+#endif
+ if (allowdups)
+ {
+ fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n",
+ progname, typename);
+ exit(EX_UNAVAILABLE);
+ }
+ break;
+ }
+
+ /*
+ ** Adjust file names.
+ */
+
+ if (ext != NULL)
+ {
+ int el, fl;
+
+ el = strlen(ext);
+ fl = strlen(mapname);
+ if (fl < el || strcmp(&mapname[fl - el], ext) != 0)
+ {
+ strcpy(fbuf, mapname);
+ strcat(fbuf, ext);
+ mapname = fbuf;
+ }
+ }
+
+ strcpy(lbuf, mapname);
+ if (lext != NULL)
+ strcat(lbuf, lext);
+
+ /*
+ ** Create the database.
+ */
+
+ mode = O_RDWR;
+ if (!notrunc)
+ mode |= O_CREAT|O_TRUNC;
+#ifdef O_EXLOCK
+ mode |= O_EXLOCK;
+#else
+ /* pre-lock the database */
+ fd = open(lbuf, mode & ~O_TRUNC, 0644);
+ if (fd < 0)
+ {
+ fprintf(stderr, "%s: cannot create type %s map %s\n",
+ progname, typename, mapname);
+ exit(EX_CANTCREAT);
+ }
+ (void) lockfile(fd);
+#endif
+ 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);
+ if (dbp.db != NULL)
+ {
+# if OLD_NEWDB
+ (void) (*dbp.db->sync)(dbp.db);
+# else
+ (void) (*dbp.db->sync)(dbp.db, 0);
+# endif
+ }
+ break;
+
+ case T_BTREE:
+ dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti);
+ if (dbp.db != NULL)
+ {
+# if OLD_NEWDB
+ (void) (*dbp.db->sync)(dbp.db);
+# else
+ (void) (*dbp.db->sync)(dbp.db, 0);
+# endif
+ }
+ break;
+#endif
+
+ default:
+ fprintf(stderr, "%s: internal error: type %d\n", progname, type);
+ exit(EX_SOFTWARE);
+ }
+
+ if (dbp.dbx == NULL)
+ {
+ fprintf(stderr, "%s: cannot open 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 != NULL)
+ *p = '\0';
+ else if (!feof(stdin))
+ {
+ fprintf(stderr, "%s: %s: line %d: line too long (%d bytes max)\n",
+ progname, mapname, lineno, sizeof ibuf);
+ continue;
+ }
+
+ 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
+ }
+
+#ifndef O_EXLOCK
+ /* release locks */
+ close(fd);
+#endif
+
+ exit (exitstat);
+}
+ /*
+** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
+**
+** Parameters:
+** fd -- the file descriptor of the file.
+**
+** Returns:
+** TRUE if the lock was acquired.
+** FALSE otherwise.
+*/
+
+bool
+lockfile(fd)
+ int fd;
+{
+# if !HASFLOCK
+ int action;
+ struct flock lfd;
+ extern int errno;
+
+ bzero(&lfd, sizeof lfd);
+ lfd.l_type = F_WRLCK;
+ action = F_SETLKW;
+
+ if (fcntl(fd, action, &lfd) >= 0)
+ return TRUE;
+
+ /*
+ ** On SunOS, if you are testing using -oQ/tmp/mqueue or
+ ** -oA/tmp/aliases or anything like that, and /tmp is mounted
+ ** as type "tmp" (that is, served from swap space), the
+ ** previous fcntl will fail with "Invalid argument" errors.
+ ** Since this is fairly common during testing, we will assume
+ ** that this indicates that the lock is successfully grabbed.
+ */
+
+ if (errno == EINVAL)
+ return TRUE;
+
+# else /* HASFLOCK */
+
+ if (flock(fd, LOCK_EX) >= 0)
+ return TRUE;
+
+# endif
+
+ return FALSE;
+}
diff --git a/usr.sbin/sendmail/rmail/Makefile b/usr.sbin/sendmail/rmail/Makefile
new file mode 100644
index 000000000000..eb2fb4800850
--- /dev/null
+++ b/usr.sbin/sendmail/rmail/Makefile
@@ -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
index 000000000000..2079d4e9f8a7
--- /dev/null
+++ b/usr.sbin/sendmail/rmail/rmail.8
@@ -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
index 000000000000..29af02a90f6d
--- /dev/null
+++ b/usr.sbin/sendmail/rmail/rmail.c
@@ -0,0 +1,373 @@
+/*
+ * 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.3 (Berkeley) 5/15/95";
+#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>
+
+#ifndef MAX
+# define MAX(a, b) ((a) < (b) ? (b) : (a))
+#endif
+
+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 (*addrp == '\0')
+ addrp = "<>";
+ 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. */
+
+ /* set from system and protocol used */
+ if (from_sys == NULL)
+ (void)snprintf(buf, sizeof(buf), "-p%s", domain);
+ else if (strchr(from_sys, '.') == NULL)
+ (void)snprintf(buf, sizeof(buf), "-p%s:%s.%s",
+ domain, from_sys, domain);
+ else
+ (void)snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys);
+ 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.
+ * To prevent confusion of sendmail wrap < and > around
+ * the address (helps to pass addrs like @gw1,@gw2:aa@bb)
+ */
+ while (*argv) {
+ if (**argv == '-')
+ err(EX_USAGE, "dash precedes argument: %s", *argv);
+ if (strchr(*argv, ',') == NULL || strchr(*argv, '<') != NULL)
+ args[i++] = *argv;
+ else {
+ if ((args[i] = malloc(strlen(*argv) + 3)) == NULL)
+ err(EX_TEMPFAIL, "Cannot malloc");
+ sprintf (args [i++], "<%s>", *argv);
+ }
+ argv++;
+ }
+ args[i] = 0;
+
+ 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);
+}
diff --git a/usr.sbin/sendmail/smrsh/Makefile b/usr.sbin/sendmail/smrsh/Makefile
new file mode 100644
index 000000000000..f2629a8c1926
--- /dev/null
+++ b/usr.sbin/sendmail/smrsh/Makefile
@@ -0,0 +1,8 @@
+# @(#)Makefile 8.1 (Berkeley) 7/2/95
+
+PROG= smrsh
+MAN8= smrsh.0
+CFLAGS+=-I${.CURDIR}/../src -DNDBM -DNEWDB
+
+.include "../../Makefile.inc"
+.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/smrsh/README b/usr.sbin/sendmail/smrsh/README
new file mode 100644
index 000000000000..13f545c7e666
--- /dev/null
+++ b/usr.sbin/sendmail/smrsh/README
@@ -0,0 +1,144 @@
+
+
+
+README smrsh - sendmail restricted shell.
+
+ @(#)README 8.2 11/11/95
+
+
+This README file is provided as a courtesy of the CERT Coordination Center,
+Software Engineering Institute, Carnegie Mellon University. This file is
+intended as a supplement to the CERT advisory CA-93:16.sendmail.vulnerability,
+and to the software, smrsh.c, written by Eric Allman.
+
+
+
+The smrsh(8) program is intended as a replacement for /bin/sh in the
+program mailer definition of sendmail(8). This README file describes
+the steps needed to compile and install smrsh.
+
+smrsh is a restricted shell utility that provides the ability to
+specify, through a configuration, an explicit list of executable
+programs. When used in conjunction with sendmail, smrsh effectively
+limits sendmail's scope of program execution to only those programs
+specified in smrsh's configuration.
+
+smrsh has been written with portability in mind, and uses traditional
+Unix library utilities. As such, smrsh should compile on most
+Unix C compilers.
+
+
+
+To compile smrsh.c, use the following command:
+
+host.domain% cc -o smrsh smrsh.c
+
+For machines that provide dynamic linking, it is advisable to compile
+smrsh without dynamic linking. As an example with the Sun Microsystems
+compiler, you should compile with the -Bstatic option.
+
+host.domain% cc -Bstatic -o smrsh smrsh.c
+
+
+Choose a directory that smrsh will reside in. We will use the traditional
+/usr/local/etc directory for the remainder of this document.
+
+As root, install smrsh in /usr/local/etc directory, with mode 511.
+
+host.domain# mv smrsh /usr/local/etc
+host.domain# chmod 511 /usr/local/etc/smrsh
+
+
+
+Next, determine the list of commands that smrsh should allow sendmail
+to run. This list of allowable commands can be determined by:
+
+ 1. examining your /etc/aliases file, to indicate what commands
+ are being used by the system.
+
+ 2. surveying your host's .forward files, to determine what
+ commands users have specified.
+
+See the man page for aliases(5) if you are unfamiliar with the format of
+these specifications. Additionally, you should include in the list,
+popular commands such as /usr/ucb/vacation.
+
+You should NOT include interpreter programs such as sh(1), csh(1),
+perl(1), uudecode(1) or the stream editor sed(1) in your list of
+acceptable commands.
+
+
+You will next need to create the directory /usr/adm/sm.bin and populate
+it with the programs that your site feels are allowable for sendmail
+to execute. This directory is explicitly specified in the source
+code for smrsh, so changing this directory must be accompanied with
+a change in smrsh.c.
+
+
+You will have to be root to make these modifications.
+
+After creating the /usr/adm/sm.bin directory, either copy the programs
+to the directory, or establish links to the allowable programs from
+/usr/adm/sm.bin. Change the file permissions, so that these programs
+can not be modified by non-root users. If you use links, you should
+ensure that the target programs are not modifiable.
+
+To allow the popular vacation(1) program by creating a link in the
+/usr/adm/sm.bin directory, you should:
+
+host.domain# cd /usr/adm/sm.bin
+host.domain# ln -s /usr/ucb/vacation vacation
+
+
+
+
+After populating the /usr/adm/sm.bin directory, you can now configure
+sendmail to use the restricted shell. Save the current sendmail.cf
+file prior to modifying it, as a prudent precaution.
+
+Typically, the program mailer is defined by a single line in the
+sendmail configuration file, sendmail.cf. This file is traditionally
+found in the /etc, /usr/lib or /etc/mail directories, depending on
+the UNIX vendor.
+
+If you are unsure of the location of the actual sendmail configuration
+file, a search of the strings(1) output of the sendmail binary, will
+help to locate it.
+
+In order to configure sendmail to use smrsh, you must modify the Mprog
+definition in the sendmail.cf file, by replacing the /bin/sh specification
+with /usr/local/etc/smrsh.
+
+As an example:
+
+In most Sun Microsystems' sendmail.cf files, the line is:
+Mprog, P=/bin/sh, F=lsDFMeuP, S=10, R=20, A=sh -c $u
+
+which should be changed to:
+Mprog, P=/usr/local/etc/smrsh, F=lsDFMeuP, S=10, R=20, A=sh -c $u
+ ^^^^^^^^^^^^^^^^^^^^
+
+A more generic line may be:
+Mprog, P=/bin/sh, F=lsDFM, A=sh -c $u
+
+and should be changed to;
+Mprog, P=/usr/local/etc/smrsh, F=lsDFM, A=sh -c $u
+
+
+After modifying the Mprog definition in the sendmail.cf file, if a frozen
+configuration file is being used, it is essential to create a new one.
+You can determine if you need a frozen configuration by discovering
+if a sendmail.fc file currently exists in either the /etc/, /usr/lib,
+or /etc/mail directories. The specific location can be determined using
+a search of the strings(1) output of the sendmail binary.
+
+In order to create a new frozen configuration, if it is required:
+host.domain# /usr/lib/sendmail -bz
+
+Now re-start the sendmail process. An example of how to do this on
+a typical system follows:
+
+host.domain# /usr/bin/ps aux | /usr/bin/grep sendmail
+root 130 0.0 0.0 168 0 ? IW Oct 2 0:10 /usr/lib/sendmail -bd -q
+host.domain# /bin/kill -9 130
+host.domain# /usr/lib/sendmail -bd -q30m
diff --git a/usr.sbin/sendmail/smrsh/smrsh.8 b/usr.sbin/sendmail/smrsh/smrsh.8
new file mode 100644
index 000000000000..3e547fcc892c
--- /dev/null
+++ b/usr.sbin/sendmail/smrsh/smrsh.8
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1993 Eric P. Allman
+.\" Copyright (c) 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.
+.\"
+.\" @(#)smrsh.8 8.1 (Berkeley) 11/13/94
+.\"
+.TH SMRSH 8 11/02/93
+.SH NAME
+smrsh \- restricted shell for sendmail
+.SH SYNOPSIS
+.B smrsh
+.B \-c
+command
+.SH DESCRIPTION
+The
+.I smrsh
+program is intended as a replacement for
+.I sh
+for use in the ``prog'' mailer in
+.IR sendmail (8)
+configuration files.
+It sharply limits the commands that can be run using the
+``|program'' syntax of
+.I sendmail
+in order to improve the over all security of your system.
+Briefly, even if a ``bad guy'' can get sendmail to run a program
+without going through an alias or forward file,
+.I smrsh
+limits the set of programs that he or she can execute.
+.PP
+Briefly,
+.I smrsh
+limits programs to be in the directory
+/usr/adm/sm.bin,
+allowing the system administrator to choose the set of acceptable commands.
+It also rejects any commands with the characters
+`\`', `<', `>', `|', `;', `&', `$', `(', `)', `\r' (carriage return),
+or `\n' (newline)
+on the command line to prevent ``end run'' attacks.
+.PP
+Initial pathnames on programs are stripped,
+so forwarding to ``/usr/ucb/vacation'',
+``/usr/bin/vacation'',
+``/home/server/mydir/bin/vacation'',
+and
+``vacation''
+all actually forward to
+``/usr/adm/sm.bin/vacation''.
+.PP
+System administrators should be conservative about populating
+/usr/adm/sm.bin.
+Reasonable additions are
+.IR vacation (1),
+.IR procmail (1),
+and the like.
+No matter how brow-beaten you may be,
+never include any shell or shell-like program
+(such as
+.IR perl (1))
+in the
+sm.bin
+directory.
+Note that this does not restrict the use of shell or perl scripts
+in the sm.bin directory (using the ``#!'' syntax);
+it simply disallows execution of arbitrary programs.
+.SH COMPILATION
+Compilation should be trivial on most systems.
+You may need to use \-DPATH=\e"\fIpath\fP\e"
+to adjust the default search path
+(defaults to ``/bin:/usr/bin:/usr/ucb'')
+and/or \-DCMDBIN=\e"\fIdir\fP\e"
+to change the default program directory
+(defaults to ``/usr/adm/sm.bin'').
+.SH FILES
+/usr/adm/sm.bin \- directory for restricted programs
+.SH SEE ALSO
+sendmail(8)
diff --git a/usr.sbin/sendmail/smrsh/smrsh.c b/usr.sbin/sendmail/smrsh/smrsh.c
new file mode 100644
index 000000000000..662ec828302b
--- /dev/null
+++ b/usr.sbin/sendmail/smrsh/smrsh.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 1993 Eric P. Allman
+ * Copyright (c) 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[] = "@(#)smrsh.c 8.4 (Berkeley) 11/11/95";
+#endif /* not lint */
+
+/*
+** SMRSH -- sendmail restricted shell
+**
+** This is a patch to get around the prog mailer bugs in most
+** versions of sendmail.
+**
+** Use this in place of /bin/sh in the "prog" mailer definition
+** in your sendmail.cf file. You then create CMDDIR (owned by
+** root, mode 755) and put links to any programs you want
+** available to prog mailers in that directory. This should
+** include things like "vacation" and "procmail", but not "sed"
+** or "sh".
+**
+** Leading pathnames are stripped from program names so that
+** existing .forward files that reference things like
+** "/usr/ucb/vacation" will continue to work.
+**
+** The following characters are completely illegal:
+** < > | ^ ; & $ ` ( ) \n \r
+** This is more restrictive than strictly necessary.
+**
+** To use this, edit /etc/sendmail.cf, search for ^Mprog, and
+** change P=/bin/sh to P=/usr/local/etc/smrsh, where this compiled
+** binary is installed /usr/local/etc/smrsh.
+**
+** This can be used on any version of sendmail.
+**
+** In loving memory of RTM. 11/02/93.
+*/
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/file.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef EX_OK
+# undef EX_OK
+#endif
+#include <sysexits.h>
+#include <syslog.h>
+
+/* directory in which all commands must reside */
+#ifndef CMDDIR
+# define CMDDIR "/usr/adm/sm.bin"
+#endif
+
+/* characters disallowed in the shell "-c" argument */
+#define SPECIALS "<|>^();&`$\r\n"
+
+/* default search path */
+#ifndef PATH
+# define PATH "/bin:/usr/bin:/usr/ucb"
+#endif
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register char *p;
+ register char *q;
+ register char *cmd;
+ int i;
+ char *newenv[2];
+ char cmdbuf[1000];
+ char pathbuf[1000];
+
+#ifndef LOG_MAIL
+ openlog("smrsh", 0);
+#else
+ openlog("smrsh", LOG_ODELAY|LOG_CONS, LOG_MAIL);
+#endif
+
+ strcpy(pathbuf, "PATH=");
+ strcat(pathbuf, PATH);
+ newenv[0] = pathbuf;
+ newenv[1] = NULL;
+
+ /*
+ ** Do basic argv usage checking
+ */
+
+ if (argc != 3 || strcmp(argv[1], "-c") != 0)
+ {
+ fprintf(stderr, "Usage: %s -c command\n", argv[0]);
+ syslog(LOG_ERR, "usage");
+ exit(EX_USAGE);
+ }
+
+ /*
+ ** Disallow special shell syntax. This is overly restrictive,
+ ** but it should shut down all attacks.
+ ** Be sure to include 8-bit versions, since many shells strip
+ ** the address to 7 bits before checking.
+ */
+
+ strcpy(cmdbuf, SPECIALS);
+ for (p = cmdbuf; *p != '\0'; p++)
+ *p |= '\200';
+ strcat(cmdbuf, SPECIALS);
+ p = strpbrk(argv[2], cmdbuf);
+ if (p != NULL)
+ {
+ fprintf(stderr, "%s: cannot use %c in command\n",
+ argv[0], *p);
+ syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s",
+ getuid(), *p, argv[2]);
+ exit(EX_UNAVAILABLE);
+ }
+
+ /*
+ ** Do a quick sanity check on command line length.
+ */
+
+ i = strlen(argv[2]);
+ if (i > (sizeof cmdbuf - sizeof CMDDIR - 2))
+ {
+ fprintf(stderr, "%s: command too long: %s\n", argv[0], argv[2]);
+ syslog(LOG_WARNING, "command too long: %.40s", argv[2]);
+ exit(EX_UNAVAILABLE);
+ }
+
+ /*
+ ** Strip off a leading pathname on the command name. For
+ ** example, change /usr/ucb/vacation to vacation.
+ */
+
+ /* strip leading spaces */
+ for (q = argv[2]; *q != '\0' && isascii(*q) && isspace(*q); )
+ q++;
+
+ /* find the end of the command name */
+ p = strpbrk(q, " \t");
+ if (p == NULL)
+ cmd = &q[strlen(q)];
+ else
+ {
+ *p = '\0';
+ cmd = p;
+ }
+
+ /* search backwards for last / (allow for 0200 bit) */
+ while (cmd > q)
+ {
+ if ((*--cmd & 0177) == '/')
+ {
+ cmd++;
+ break;
+ }
+ }
+
+ /* cmd now points at final component of path name */
+
+ /*
+ ** Check to see if the command name is legal.
+ */
+
+ (void) strcpy(cmdbuf, CMDDIR);
+ (void) strcat(cmdbuf, "/");
+ (void) strcat(cmdbuf, cmd);
+#ifdef DEBUG
+ printf("Trying %s\n", cmdbuf);
+#endif
+ if (access(cmdbuf, X_OK) < 0)
+ {
+ /* oops.... crack attack possiblity */
+ fprintf(stderr, "%s: %s not available for sendmail programs\n",
+ argv[0], cmd);
+ if (p != NULL)
+ *p = ' ';
+ syslog(LOG_CRIT, "uid %d: attempt to use %s", getuid(), cmd);
+ exit(EX_UNAVAILABLE);
+ }
+ if (p != NULL)
+ *p = ' ';
+
+ /*
+ ** Create the actual shell input.
+ */
+
+ strcpy(cmdbuf, CMDDIR);
+ strcat(cmdbuf, "/");
+ strcat(cmdbuf, cmd);
+
+ /*
+ ** Now invoke the shell
+ */
+
+#ifdef DEBUG
+ printf("%s\n", cmdbuf);
+#endif
+ execle("/bin/sh", "/bin/sh", "-c", cmdbuf, NULL, newenv);
+ syslog(LOG_CRIT, "Cannot exec /bin/sh: %m");
+ perror("/bin/sh");
+ exit(EX_OSFILE);
+}
diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile
new file mode 100644
index 000000000000..57a7df0b3911
--- /dev/null
+++ b/usr.sbin/sendmail/src/Makefile
@@ -0,0 +1,47 @@
+# @(#)Makefile 8.7 (Berkeley) 10/31/95
+
+#########################################################################
+# This Makefile is for 4.4BSD only!!! For all other systems, use #
+# the "makesendmail" script. #
+#########################################################################
+
+PROG= sendmail
+
+# 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
+
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO
+
+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 mime.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=
+LDADD=
+MAN1= mailq.0 newaliases.0
+MAN5= aliases.0
+MAN8= sendmail.0
+LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
+ /usr/sbin/sendmail /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 644 /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/READ_ME b/usr.sbin/sendmail/src/READ_ME
new file mode 100644
index 000000000000..82889ff53389
--- /dev/null
+++ b/usr.sbin/sendmail/src/READ_ME
@@ -0,0 +1,1183 @@
+# Copyright (c) 1983, 1995 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.
+#
+# @(#)READ_ME 8.112 (Berkeley) 11/18/95
+#
+
+This directory contains the source files for sendmail.
+
+*********************
+!! DO NOT USE MAKE !! to compile sendmail -- instead, use the
+********************* "makesendmail" script located in the src
+directory. It will find an appropriate Makefile, and create an
+appropriate obj.* subdirectory so that multiplatform support
+works easily.
+
+The Makefile is for the new (4.4BSD) Berkeley make and uses syntax
+that is not recognized by older makes. It also has assumptions
+about the 4.4 file system layout built in. See below for details
+about other Makefiles.
+
+If you are porting to a new architecture for which there is no existing
+Makefile, you might start with Makefile.dist. This works on the old
+traditional make, but isn't customized for any particular architecture.
+
+ **************************************************
+ ** Read below for more details of Makefiles. **
+ **************************************************
+
+**************************************************************************
+** IMPORTANT: DO NOT USE OPTIMIZATION (``-O'') IF YOU ARE RUNNING **
+** GCC 2.4.x or 2.5.x. THERE IS A BUG IN THE GCC OPTIMIZER THAT **
+** CAUSES SENDMAIL COMPILES TO FAIL MISERABLY. **
+**************************************************************************
+
+Jim Wilson of Cygnus believes he has found the problem -- it will
+probably be fixed in GCC 2.5.6 -- but until this is verified, be
+very suspicious of gcc -O.
+
+This problem is reported to have been fixed in gcc 2.6.
+
+**************************************************************************
+** IMPORTANT: Read the appropriate paragraphs in the section on **
+** ``Operating System and Compile Quirks''. **
+**************************************************************************
+
+For detailed instructions, please read the document ../doc/op.me:
+
+ eqn ../doc/op.me | pic | ditroff -me
+
+
++-----------+
+| MAKEFILES |
++-----------+
+
+By far, the easiest way to compile sendmail is to use the "makesendmail"
+script:
+
+ sh makesendmail
+
+This uses the "uname" command to figure out what architecture you are
+on and selects a proper Makefile accordingly. It also creates a
+subdirectory per object format, so that multiarchitecture support is
+easy. In general this should be all you need. However, if for some
+reason this doesn't work (e.g., NeXT systems don't have the "uname"
+command) you may have to set up your compile environment by hand.
+
+The "Makefile"s in these directories are from 4.4 BSD, and hence
+really only work properly if you are on a 4.4 system. In particular,
+they use new syntax that will not be recognized on old make programs,
+and some of them do things like ``.include ../../Makefile.inc'' to
+pick up some system defines. If you are getting sendmail separately,
+these files won't be included in the distribution, as they are
+outside of the sendmail tree.
+
+Instead, you should use one of the other Makefiles, such as
+Makefile.SunOS for a SunOS system, and so forth. These should
+work with the version of make that is appropriate for that
+system. All other Makefiles are in the "src/Makefiles" subdirectory.
+They use the version of make that is native for that system. These
+are the Makefiles that I use, and they have "Berkeley quirks" in them.
+I can't guarantee that they will work unmodified in your environment.
+In particular, Many of them include -I/usr/sww/include/db and
+-L/usr/sww/lib -- these are Berkeley's locations in the ``Software
+Warehouse'' for the new database libraries, described below. You don't
+have to remove these definitions if you don't have these directories,
+but you may have to remove -DNEWDB from the DBMDEF definition.
+
+Please look for an appropriate Makefile before you start trying to
+compile with Makefile or Makefile.dist.
+
+If you want to port the new Berkeley make, you can get it from
+ftp.uu.net in the directory /systems/unix/bsd-sources/usr.bin/make.
+Diffs and instructions for building this version of make under
+SunOS 4.1.x are available on ftp.css.itd.umich.edu in
+/pub/systems/sun/Net2-make-sun4.diff.Z. Diffs and instructions
+for building this version of make under IBM AIX 3.2.4 are available
+on ftp.uni-stuttgart.de in /sw/src/patches/bsd-make-rus-patches.
+For Ultrix, try ftp.vix.com:~ftp/pub/patches/pmake-for-ultrix.Z.
+Paul Southworth <pauls@umich.edu> published a description of porting
+this make in comp.unix.bsd.
+
+The complete text of the Makefile.inc that is in the parent of the
+sendmail directory is:
+
+ # @(#)Makefile.inc 8.1 (Berkeley) 6/6/93
+
+ BINDIR?= /usr/sbin
+
+
++----------------------+
+| DATABASE DEFINITIONS |
++----------------------+
+
+There are several database formats that can be used for the alias files
+and for general maps. When used for alias files they interact in an
+attempt to be back compatible.
+
+The three options are NEWDB (the new Berkeley DB package), NDBM (the
+older DBM implementation -- the very old V7 implementation is no
+longer supported), and NIS (Network Information Services). Used alone
+these just include the support they indicate. [If you are using NEWDB,
+get the latest version from FTP.CS.Berkeley.EDU in /ucb/4bsd/db.tar.Z
+(or db.tar.gz). DO NOT use the version from the Net2 distribution!
+However, if you are on BSD/386 or 386BSD-based systems, use the one
+that already exists on your system. You may need to #define OLD_NEWDB
+1 to do this.]
+
+[NOTE WELL: it is CRITICAL that you remove ndbm.o from libdb.a and
+ndbm.h from the appropriate include directories if you want to get
+ndbm support. These files OVERRIDE calls to ndbm routines -- in
+particular, if you leave ndbm.h in, you can find yourself using
+the new db package even if you don't define NEWDB.]
+
+If NEWDB and NDBM are defined (but not NIS), then sendmail will read
+NDBM format alias files, but the next time a newaliases is run the
+format will be converted to NEWDB; that format will be used forever
+more. This is intended as a transition feature. [Note however that
+the NEWDB library also catches and maps NDBM calls; you will have to
+back out this feature to get this to work. See ``Quirks'' section
+below for details.]
+
+If all three are defined and the name of the file includes the string
+"/yp/", sendmail will rebuild BOTH the NEWDB and NDBM format alias
+files. However, it will only read the NEWDB file; the NDBM format file
+is used only by the NIS subsystem.
+
+If NDBM and NIS are defined (regardless of the definition of NEWDB),
+and the filename includes the string "/yp/", sendmail adds the special
+tokens "YP_LAST_MODIFIED" and "YP_MASTER_NAME", both of which are
+required if the NDBM file is to be used as an NIS map.
+
+There is also preliminary support for NIS+ (-DNISPLUS), Hesiod
+(-DHESIOD), and NetInfo (-DNETINFO). These have not been well
+tested.
+
+All of -DNEWDB, -DNDBM, -DNIS, -DNISPLUS, -DHESIOD, and -DNETINFO are
+normally defined in the DBMDEF line in the Makefile.
+
+If you define NEWDB or HESIOD you get the User Database (USERDB)
+automatically. Generally you do want to have NEWDB for it to do
+anything interesting. See above for getting the Berkeley "db"
+package (i.e., NEWDB). There is no separate "user database"
+package -- don't bother searching for it on the net.
+
+
++---------------+
+| COMPILE FLAGS |
++---------------+
+
+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 available, requiring that a compilation flag be defined in
+the Makefile; see the Makefiles subdirectory for the supported
+architectures.
+
+If you are a system to which sendmail has already been ported you
+should not have to touch the following symbols. But if you are porting,
+you may have to tweak the following compilation flags in conf.h in order
+to get it to compile and link properly:
+
+SYSTEM5 Adjust for System V (not necessarily Release 4).
+SYS5SIGNALS Use System V signal semantics -- the signal handler
+ is automatically dropped when the signal is caught.
+ If this is not set, use POSIX/BSD semantics, where the
+ signal handler stays in force until an exec or an
+ explicit delete. Implied by SYSTEM5.
+SYS5SETPGRP Use System V setpgrp() semantics. Implied by SYSTEM5.
+HASFCHMOD Define this to one if you have the fchmod(2) system call.
+ This improves security.
+HASFLOCK Set this if you prefer to use the flock(2) system call
+ rather than using fcntl-based locking. Fcntl locking
+ has some semantic gotchas, but many vendor systems
+ also interface it to lockd(8) to do NFS-style locking.
+ Unfortunately, may vendors implementations of fcntl locking
+ is just plain broken (e.g., locks are never released,
+ causing your sendmail to deadlock; when the kernel runs
+ out of locks your system crashes). For this reason, I
+ recommend always defining this unless you are absolutely
+ certain that your fcntl locking implementation really works.
+HASUNAME Set if you have the "uname" system call. Implied by
+ SYSTEM5.
+HASUNSETENV Define this if your system library has the "unsetenv"
+ subroutine.
+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.
+HASSETVBUF Define this if you have the setvbuf(3) library call.
+ If you don't, setlinebuf will be used instead. This
+ defaults on if your compiler defines __STDC__.
+HASSETREUID Define this if you have setreuid(2) ***AND*** root can
+ use setreuid to change to an arbitrary user. This second
+ condition is not satisfied on AIX 3.x. You may find that
+ your system has setresuid(2), (for example, on HP-UX) in
+ which case you will also have to #define setreuid(r, e)
+ to be the appropriate call. Some systems (such as Solaris)
+ have a compatibility routine that doesn't work properly,
+ but may have "saved user ids" properly implemented so you
+ can ``#define setreuid(r, e) seteuid(e)'' and have it work.
+ The important thing is that you have a call that will set
+ the effective uid independently of the real or saved uid
+ and be able to set the effective uid back again when done.
+ There's a test program in ../test/t_setreuid.c that will
+ try things on your system. Setting this improves the
+ security, since sendmail doesn't have to read .forward
+ and :include: files as root. There are certain attacks
+ that may be unpreventable without this call.
+USESETEUID Define this to 1 if you have seteuid(2) if you have a seteuid
+ system call that will allow root to set only the effective
+ user id to an arbitrary value ***AND*** you have saved user
+ ids. This is preferable to HASSETREUID if these conditions
+ are fulfilled. These are the semantics of the to-be-released
+ revision of Posix.1. The test program ../test/t_seteuid.c
+ will try this out on your system. If you define both
+ HASSETREUID and USESETEUID, the former is ignored.
+HASLSTAT Define this if you have symbolic links (and thus the
+ lstat(2) system call). This improves security. Unlike
+ most other options, this one is on by default, so you
+ need to #undef it in conf.h if you don't have symbolic
+ links (these days everyone does).
+HASSETRLIMIT Define this to 1 if you have the setrlimit(2) syscall.
+ You can define it to 0 to force it off. It is assumed
+ if you are running a BSD-like system.
+HASULIMIT Define this if you have the ulimit(2) syscall (System V
+ style systems). HASSETRLIMIT overrides, as it is more
+ general.
+HASWAITPID Define this if you have the waitpid(2) syscall.
+HASGETDTABLESIZE
+ Define this if you have the getdtablesize(2) syscall.
+NEEDGETOPT Define this if you need a reimplementation of getopt(3).
+ On some systems, getopt does very odd things if called
+ to scan the arguments twice. This flag will ask sendmail
+ to compile in a local version of getopt that works
+ properly.
+NEEDSTRTOL Define this if your standard C library does not define
+ strtol(3). This will compile in a local version.
+NEEDVPRINTF Define this if your standard C library does not define
+ vprintf(3). Note that the resulting fake implementation
+ is not very elegant and may not even work on some
+ architectures.
+NEEDFSYNC Define this if your standard C library does not define
+ fsync(2). This will try to simulate the operation using
+ fcntl(2); if that is not available it does nothing, which
+ isn't great, but at least it compiles and runs.
+HASGETUSERSHELL Define this to 1 if you have getusershell(3) in your
+ standard C library. If this is not defined, or is defined
+ to be 0, sendmail will scan the /etc/shells file (no
+ NIS-style support, defaults to /bin/sh and /bin/csh if
+ that file does not exist) to get a list of unrestricted
+ user shells. This is used to determine whether users
+ are allowed to forward their mail to a program or a file.
+NEEDPUTENV Define this if your system needs am emulation of the
+ putenv(3) call. Define to 1 to implement it in terms
+ of setenv(3) or to 2 to do it in terms of primitives.
+NOFTRUNCATE Define this if you don't have the ftruncate(2) syscall.
+ If you don't have this system call, there is an unavoidable
+ race condition that occurs when creating alias databases.
+GIDSET_T The type of entries in a gidset passed as the second
+ argument to getgroups(2). Historically this has been an
+ int, so this is the default, but some systems (such as
+ IRIX) pass it as a gid_t, which is an unsigned short.
+ This will make a difference, so it is important to get
+ this right! However, it is only an issue if you have
+ group sets.
+SLEEP_T The type returned by the system sleep() function.
+ Defaults to "unsigned int". Don't worry about this
+ if you don't have compilation problems.
+ARBPTR_T The type of an arbitrary pointer -- defaults to "void *".
+ If you are an very old compiler you may need to define
+ this to be "char *".
+LA_TYPE The type of load average your kernel supports. These
+ can be one of:
+ LA_ZERO (1) -- it always returns the load average as
+ "zero" (and does so on all architectures).
+ LA_INT (2) to read /dev/kmem for the symbol avenrun and
+ interpret as a long integer.
+ LA_FLOAT (3) same, but interpret the result as a floating
+ point number.
+ LA_SHORT (6) to interpret as a short integer.
+ LA_SUBR (4) if you have the getloadavg(3) routine in your
+ system library.
+ LA_MACH (5) to use MACH-style load averages (calls
+ processor_set_info()),
+ LA_PROCSTR (7) to read /proc/loadavg and interpret it
+ as a string representing a floating-point
+ number (Linux-style).
+ LA_READKSYM (8) is an implementation suitable for some
+ versions of SVr4 that uses the MIOC_READKSYM ioctl
+ call to read /dev/kmem.
+ LA_DGUX (9) is a special implementation for DG/UX that uses
+ the dg_sys_info system call.
+ LA_HPUX (10) is an HP-UX specific version that uses the
+ pstat_getdynamic system call.
+ LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several
+ other parameters that they try to divine: the name of your
+ kernel, the name of the variable in the kernel to examine,
+ the number of bits of precision in a fixed point load average,
+ and so forth.
+ In desperation, use LA_ZERO. The actual code is in
+ conf.c -- it can be tweaked if you are brave.
+FSHIFT For LA_INT, LA_SHORT, and LA_READKSYM, this is the number
+ of bits of load average after the binary point -- i.e.,
+ the number of bits to shift right in order to scale the
+ integer to get the true integer load average. Defaults to 8.
+_PATH_UNIX The path to your kernel. Needed only for LA_INT, LA_SHORT,
+ and LA_FLOAT. Defaults to "/unix" on System V, "/vmunix"
+ everywhere else.
+LA_AVENRUN For LA_INT, LA_SHORT, and LA_FLOAT, the name of the kernel
+ variable that holds the load average. Defaults to "avenrun"
+ on System V, "_avenrun" everywhere else.
+SFS_TYPE Encodes how your kernel can locate the amount of free
+ space on a disk partition. This can be set to SFS_NONE
+ (0) if you have no way of getting this information,
+ SFS_USTAT (1) if you have the ustat(2) system call,
+ SFS_4ARGS (2) if you have a four-argument statfs(2)
+ system call (and the include file is <sys/statfs.h>),
+ SFS_VFS (3), SFS_MOUNT (4), SFS_STATFS (5) if you have
+ the two-argument statfs(2) system call with includes in
+ <sys/vfs.h>, <sys/mount.h>, or <sys/statfs.h> respectively,
+ or SFS_STATVFS (6) if you have the two-argument statvfs(2)
+ call. The default if nothing is defined is SFS_NONE.
+SFS_BAVAIL with SFS_4ARGS hou can also set SFS_BAVAIL to the field name
+ in the statfs structure that holds the useful information;
+ this defaults to f_bavail.
+SPT_TYPE Encodes how your system can display what a process is doing
+ on a ps(1) command (SPT stands for Set Process Title). Can
+ be set to:
+ SPT_NONE (0) -- Don't try to set the process title at all.
+ SPT_REUSEARGV (1) -- Pad out your argv with the information;
+ this is the default if none specified.
+ SPT_BUILTIN (2) -- The system library has setproctitle.
+ SPT_PSTAT (3) -- Use the PSTAT_SETCMD option to pstat(2)
+ to set the process title; this is used by HP-UX.
+ SPT_PSSTRINGS (4) -- Use the magic PS_STRINGS pointer (4.4BSD).
+SPT_PADCHAR Character used to pad the process title; if undefined,
+ the space character (0x20) is used. This is ignored if
+ SPT_TYPE != SPT_REUSEARGV
+ERRLIST_PREDEFINED
+ If set, assumes that some header file defines sys_errlist.
+ This may be needed if you get type conflicts on this
+ variable -- otherwise don't worry about it.
+WAITUNION The wait(2) routine takes a "union wait" argument instead
+ of an integer argument. This is for compatibility with
+ old versions of BSD.
+SCANF You can set this to extend the F command to accept a
+ scanf string -- this gives you a primitive parser for
+ class definitions -- BUT it can make you vulnerable to
+ core dumps if the target file is poorly formed.
+SYSLOG_BUFSIZE You can define this to be the size of the buffer that
+ syslog accepts. If it is not defined, it assumes a
+ 1024-byte buffer. If the buffer is very small (under
+ 256 bytes) the log message format changes -- each
+ e-mail message will log many more messages, since it
+ will log each piece of information as a separate line
+ in syslog.
+BROKEN_RES_SEARCH
+ On Ultrix (and maybe other systems?) if you use the
+ res_search routine with an unknown host name, it returns
+ -1 but sets h_errno to 0 instead of HOST_NOT_FOUND. If
+ you set this, sendmail considers 0 to be the same as
+ HOST_NOT_FOUND.
+NAMELISTMASK If defined, values returned by nlist(3) are masked
+ against this value before use -- a common value is
+ 0x7fffffff to strip off the top bit.
+BSD4_4_SOCKADDR If defined, socket addresses have an sa_len field that
+ defines the length of this address.
+
+
+
++-----------------------+
+| COMPILE-TIME FEATURES |
++-----------------------+
+
+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.
+ Normally defined in the Makefile.
+NEWDB Include support for Berkeley "db" package (hash & btree)
+ for aliases and maps. Normally defined in the Makefile.
+OLD_NEWDB If non-zero, the version of NEWDB you have is the old
+ one that does not include the "fd" call. This call was
+ added in version 1.5 of the Berkeley DB code. If you
+ use -DOLD_NEWDB=0 it forces you to use the new interface.
+NIS Define this to get NIS (YP) support for aliases and maps.
+ Normally defined in the Makefile.
+NISPLUS Define this to get NIS+ support for aliases and maps.
+ Normally defined in the Makefile.
+HESIOD Define this to get Hesiod support for aliases and maps.
+ Normally defined in the Makefile.
+NETINFO Define this to get NeXT NetInfo support for aliases and maps.
+ Normally defined in the Makefile.
+USERDB Define this to 1 to include support for the User Information
+ Database. Implied by NEWDB or HESIOD. You can use
+ -DUSERDB=0 to explicitly turn it off.
+IDENTPROTO Define this as 1 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. You can define it to be 0 to explicitly
+ turn off IDENT protocol support. If defined off, the code
+ is actually still compiled in, but it defaults off; you
+ can turn it on by setting the IDENT timeout to 30s in the
+ configuration file.
+IP_SRCROUTE Define this to 1 to get IP source routing information
+ displayed in the Received: header. This is assumed on
+ most systems, but some (e.g., Ultrix) apparently have a
+ broken version of getsockopt that doesn't properly
+ support the IP_OPTIONS call. You probably want this if
+ your OS can cope with it. Symptoms of failure will be that
+ it won't compile properly (that is, no support for fetching
+ IP_OPTIONs), or it compiles but source-routed TCP connections
+ either refuse to open or open and hang for no apparent reason.
+ Ultrix and AIX are known to fail this way.
+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.
+NETUNIX Define this to get Unix domain networking support. Defined
+ by default. A few bizarre systems (SCO, ISC, Altos) don't
+ support this networking domain.
+SMTP Define this to get the SMTP code. Implied by NETINET
+ or NETISO.
+NAMED_BIND If non-zero, include DNS (name daemon) support, including
+ MX support. The specs say you must use this if you run
+ SMTP. You don't have to be running a name server daemon
+ on your machine to need this -- any use of the DNS resolver,
+ including remote access to another machine, requires this
+ option. Defined by default in conf.h. Define it to zero
+ ONLY on machines that do not use DNS in any way.
+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.
+MIME8TO7 If non-zero, include 8 to 7 bit MIME conversions. This
+ also controls advertisement of 8BITMIME in the ESMTP
+ startup dialogue.
+MIME7TO8 If non-zero, include 7 to 8 bit MIME conversions. Not yet
+ implemented.
+HES_GETMAILHOST Define this to 1 if you are using Hesiod with the
+ hes_getmailhost() routine. This is included with the MIT
+ Hesiod distribution, but not with the DEC Hesiod distribution.
+XDEBUG Do additional internal checking. These don't cost too
+ much; you might as well leave this on.
+
+
++---------------------+
+| DNS/RESOLVER ISSUES |
++---------------------+
+
+Many systems have old versions of the resolver library. At a minimum,
+you should be running BIND 4.8.3; older versions may compile, but they
+have known bugs that should give you pause.
+
+Common problems in old versions include "undefined" errors for
+dn_skipname.
+
+Some people have had a problem with BIND 4.9; it uses some routines
+that it expects to be externally defined such as strerror(). It may
+help to link with "-l44bsd" to solve this problem.
+
+!PLEASE! be sure to link with the same version of the resolver as
+the header files you used -- some people have used the 4.9 headers
+and linked with BIND 4.8 or vice versa, and it doesn't work.
+Unfortunately, it doesn't fail in an obvious way -- things just
+subtly don't work.
+
+WILDCARD MX RECORDS ARE A BAD IDEA! The only situation in which they
+work reliably is if you have two versions of DNS, one in the real world
+which has a wildcard pointing to your firewall, and a completely
+different version of the database internally that does not include
+wildcard MX records that match your domain. ANYTHING ELSE WILL GIVE
+YOU HEADACHES!
+
+
++-------------------------------------+
+| OPERATING SYSTEM AND COMPILE QUIRKS |
++-------------------------------------+
+
+GCC 2.5.x problems *** IMPORTANT ***
+ Date: Mon, 29 Nov 93 19:08:44 PST
+ From: wilson@cygnus.com (Jim Wilson)
+ Message-Id: <9311300308.AA04608@cygnus.com>
+ To: kenner@vlsi1.ultra.nyu.edu
+ Subject: [cattelan@thebarn.com: gcc 2.5.4-2.5.5 -O bug]
+ Cc: cattelan@thebarn.com, rms@gnu.ai.mit.edu, sendmail@cs.berkeley.edu
+
+ This fixes a problem that occurs when gcc 2.5.5 is used to compile
+ sendmail 8.6.4 with optimization on a sparc.
+
+ Mon Nov 29 19:00:14 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * reload.c (find_reloads_toplev): Replace obsolete reference to
+ BYTE_LOADS_*_EXTEND with LOAD_EXTEND_OP.
+
+ *** clean-ss-931128/reload.c Sun Nov 14 16:20:01 1993
+ --- ss-931128/reload.c Mon Nov 29 18:52:55 1993
+ *************** find_reloads_toplev (x, opnum, type, ind
+ *** 3888,3894 ****
+ force a reload in that case. So we should not do anything here. */
+
+ else if (regno >= FIRST_PSEUDO_REGISTER
+ ! #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
+ && (GET_MODE_SIZE (GET_MODE (x))
+ <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ #endif
+ --- 3888,3894 ----
+ force a reload in that case. So we should not do anything here. */
+
+ else if (regno >= FIRST_PSEUDO_REGISTER
+ ! #ifdef LOAD_EXTEND_OP
+ && (GET_MODE_SIZE (GET_MODE (x))
+ <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ #endif
+
+GCC 2.7.x problems
+ Apparently GCC 2.7.0 on the Pentium processor has optimization
+ problems. I recommend against using -O on that architecture. This
+ has been seen on FreeBSD 2.0.5 RELEASE.
+
+
+SunOS 4.x (Solaris 1.x)
+ You may have to use -lresolv on SunOS. However, beware that
+ this links in a new version of gethostbyname that does not
+ understand NIS, so you must have all of your hosts in DNS.
+
+ Some people have reported problems with the SunOS version of
+ -lresolv and/or in.named, and suggest that you get a newer
+ version. The symptoms are delays when you connect to the
+ SMTP server on a SunOS machine or having your domain added to
+ addresses inappropriately. There is a version of BIND
+ version 4.9 on gatekeeper.DEC.COM in pub/BSD/bind/4.9.
+
+ There is substantial disagreement about whether you can make
+ this work with resolv+, which allows you to specify a search-path
+ of services. Some people report that it works fine, others
+ claim it doesn't work at all (including causing sendmail to
+ drop core when it tries to do multiple resolv+ lookups for a
+ single job). I haven't tried resolv+, as we use DNS exclusively.
+
+ Should you want to try resolv+, it is on ftp.uu.net in
+ /networking/ip/dns.
+
+ Apparently getservbyname() can fail under moderate to high
+ load under some circumstances. This will exhibit itself as
+ the message ``554 makeconnection: service "smtp" unknown''.
+ The problem has been traced to one or more blank lines in
+ /etc/services on the NIS server machine. Delete these
+ and it should work. This info is thanks to Brian Bartholomew
+ <bb@math.ufl.edu> of I-Kinetics, Inc.
+
+SunOS 4.0.2 (Sun 386i)
+ Date: Fri, 25 Aug 1995 11:13:58 +0200 (MET DST)
+ From: teus@oce.nl
+
+ Sendmail 8.7.Beta.12 compiles and runs nearly out of the box with the
+ following changes:
+ * Don't use /usr/5bin in your PATH, but make /usr/5bin/uname
+ available as "uname" command.
+ * Use the defines "-DBSD4_3 -DNAMED_BIND=0" in the
+ Makefile.SunOS.4.0, which is selected via the "uname" command.
+ I recommend to make available the db-library on the system first
+ (and change the Makefile to use this library).
+ Note that the sendmail.cf and aliases files are found in /etc.
+
+SunOS 4.1.3_U1
+ Sendmail causes crashes on SunOS 4.1.3_U1. According to Sun
+ bug number 1077939:
+
+ If an application does a getsockopt() on a SOCK_STREAM (TCP) socket
+ after the other side of the connection has sent a TCP RESET for
+ the stream, the kernel gets a Bus Trap in the tcp_ctloutput() or
+ ip_ctloutput() routine.
+
+ This is fixed in patch 101790-01 (SunOS 4.1.3_U1: TCP socket and
+ reset problems).
+
+Solaris 2.x (SunOS 5.x)
+ To compile for Solaris, be sure you use -DSOLARIS.
+
+ To the best of my knowledge, Solaris does not have the
+ gethostbyname problem described above. However, it does
+ have another one:
+
+ From a correspondent:
+
+ For solaris 2.2, I have
+
+ hosts: files dns
+
+ in /etc/nsswitch.conf and /etc/hosts has to have the fully
+ qualified host name. I think "files" has to be before "dns"
+ in /etc/nsswitch.conf during bootup.
+
+ From another correspondent:
+
+ When running sendmail under Solaris, the gethostbyname()
+ hack in conf.c which should perform proper canonicalization
+ of host names could fail. Result: the host name is not
+ canonicalized despite the hack, and you'll have to define $j
+ and $m in sendmail.cf somewhere.
+
+ The reason could be that /etc/nsswitch.conf is improperly
+ configured (at least from sendmail's point of view). For
+ example, the line
+
+ hosts: files nisplus dns
+
+ will make gethostbyname() look in /etc/hosts first, then ask
+ nisplus, then dns. However, if /etc/hosts does not contain
+ the full canonicalized hostname, then no amount of
+ gethostbyname()s will work.
+
+ Solution (or rather, a workaround): Ask nisplus first, then
+ dns, then local files:
+
+ hosts: nisplus dns [NOTFOUND=return] files
+
+ The Solaris "syslog" function is apparently limited to something
+ about 90 characters because of a kernel limitation. If you have
+ source code, you can probably up this number. You can get patches
+ that fix this problem: the patch ids are:
+
+ Solaris 2.1 100834
+ Solaris 2.2 100999
+ Solaris 2.3 101318
+
+ Be sure you have the appropriate patch installed or you won't
+ see system logging.
+
+Solaris 2.4 (SunOS 5.4)
+ If you include /usr/lib at the end of your LD_LIBRARY_PATH you run
+ the risk of getting the wrong libraries under some circumstances.
+ This is because of a new feature in Solaris 2.4, described by
+ Rod.Evans@Eng.Sun.COM:
+
+ >> Prior to SunOS 5.4, any LD_LIBRARY_PATH setting was ignored by the
+ >> runtime linker if the application was setxid (secure), thus your
+ >> applications search path would be:
+ >>
+ >> /usr/local/lib LD_LIBRARY_PATH component - IGNORED
+ >> /usr/lib LD_LIBRARY_PATH component - IGNORED
+ >> /usr/local/lib RPATH - honored
+ >> /usr/lib RPATH - honored
+ >>
+ >> the effect is that path 3 would be the first used, and this would
+ >> satisfy your resolv.so lookup.
+ >>
+ >> In SunOS 5.4 we made the LD_LIBRARY_PATH a little more flexible.
+ >> People who developed setxid applications wanted to be able to alter
+ >> the library search path to some degree to allow for their own
+ >> testing and debugging mechanisms. It was decided that the only
+ >> secure way to do this was to allow a `trusted' path to be used in
+ >> LD_LIBRARY_PATH. The only trusted directory we presently define
+ >> is /usr/lib. Thus a setuid root developer could play with some
+ >> alternative shared object implementations and place them in
+ >> /usr/lib (being root we assume they'ed have access to write in this
+ >> directory). This change was made as part of 1155380 - after a
+ >> *huge* amount of discussion regarding the security aspect of things.
+ >>
+ >> So, in SunOS 5.4 your applications search path would be:
+ >>
+ >> /usr/local/lib from LD_LIBRARY_PATH - IGNORED (untrustworthy)
+ >> /usr/lib from LD_LIBRARY_PATH - honored (trustworthy)
+ >> /usr/local/lib from RPATH - honored
+ >> /usr/lib from RPATH - honored
+ >>
+ >> here, path 2 would be the first used.
+
+Ultrix
+ By default, the IDENT protocol is turned off on Ultrix. If you
+ are running Ultrix 4.4 or later, or if you have included patch
+ CXO-8919 for Ultrix 4.2 or 4.3 to fix the TCP problem, you can turn
+ IDENT on in the configuration file by setting the "ident" timeout
+ to 30 seconds.
+
+OSF/1
+ If you are compiling on OSF/1 (DEC Alpha), you must use
+ -L/usr/shlib (otherwise it core dumps on startup). You may also
+ need -mld to get the nlist() function, although some versions
+ apparently don't need this.
+
+ Also, the enclosed makefile removed /usr/sbin/smtpd; if you need
+ it, just create the link to the sendmail binary.
+
+IRIX
+ The header files on SGI IRIX are completely prototyped, and as
+ a result you can sometimes get some warning messages during
+ compilation. These can be ignored. There are two errors in
+ deliver only if you are using gcc, both of the form ``warning:
+ passing arg N of `execve' from incompatible pointer type''.
+ Also, if you compile with -DNIS, you will get a complaint
+ about a declaration of struct dom_binding in a prototype
+ when compiling map.c; this is not important because the
+ function being prototyped is not used in that file.
+
+ In order to compile sendmail you will have had to install
+ the developers' option in order to get the necessary include
+ files.
+
+NeXT or NEXTSTEP
+ NEXTSTEP 3.3 and earlier ship with the old DBM library. You will
+ need to acquire the new Berkeley DB from ftp.cs.berkeley.edu.
+ Install it in /usr/local/{lib,include}.
+
+ If you are compiling on NEXTSTEP, you will have to create an
+ empty file "unistd.h" and create a file "dirent.h" containing:
+
+ #include <sys/dir.h>
+ #define dirent direct
+
+ (The Makefile.NeXT should try to do both of these for you.)
+
+ Apparently, there is a bug in getservbyname on Nextstep 3.0
+ that causes it to fail under some circumstances with the
+ message "SYSERR: service "smtp" unknown" logged. You should
+ be able to work around this by including the line:
+
+ OOPort=25
+
+ in your .cf file.
+
+ You may have to use -DNeXT.
+
+BSDI (BSD/386) 1.0, NetBSD 0.9, FreeBSD 1.0
+ The "m4" from BSDI won't handle the config files properly.
+ I haven't had a chance to test this myself.
+
+ The M4 shipped in FreeBSD and NetBSD 0.9 don't handle the config
+ files properly. One must use either GNU m4 1.1 or the PD-M4
+ recently posted in comp.os.386bsd.bugs (and maybe others).
+ NetBSD-current includes the PD-M4 (as stated in the NetBSD file
+ CHANGES).
+
+ FreeBSD 1.0 RELEASE has uname(2) now. Use -DUSEUNAME in order to
+ use it (look into Makefile.FreeBSD). NetBSD-current may have
+ it too but it has not been verified.
+
+ You cannot port the latest version of the Berkeley db library
+ and use it with sendmail without recompiling the world. This
+ is because C library routines use the older version which have
+ incompatible header files -- the result is that it can't read
+ other system files, such as /etc/passwd, unless you use the
+ new db format throughout your system. You should normally just
+ use the version of db supplied in your release. You may need
+ to use -DOLD_NEWDB=1 to make this work -- this turns off some
+ new interface calls (for file locking) that are not in older
+ versions of db. You'll get compile errors if you need this
+ flag and don't have it set.
+
+4.3BSD
+ If you are running a "virgin" version of 4.3BSD, you'll have
+ a very old resolver and be missing some header files. The
+ header files are simple -- create empty versions and everything
+ will work fine. For the resolver you should really port a new
+ version (4.8.3 or later) of the resolver; 4.9 is available on
+ gatekeeper.DEC.COM in pub/BSD/bind/4.9. If you are really
+ determined to continue to use your old, buggy version (or as
+ a shortcut to get sendmail working -- I'm sure you have the
+ best intentions to port a modern version of BIND), you can
+ copy ../contrib/oldbind.compat.c into src and add
+ oldbind.compat.o to OBJADD in the Makefile.
+
+A/UX
+ Date: Tue, 12 Oct 1993 18:28:28 -0400 (EDT)
+ From: "Eric C. Hagberg" <hagberg@med.cornell.edu>
+ Subject: Fix for A/UX ndbm
+
+ I guess this isn't really a sendmail bug, however, it is something
+ that A/UX users should be aware of when compiling sendmail 8.6.
+
+ Apparently, the calls that sendmail is using to the ndbm routines
+ in A/UX 3.0.x contain calls to "broken" routines, in that the
+ aliases database will break when it gets "just a little big"
+ (sorry I don't have exact numbers here, but it broke somewhere
+ around 20-25 aliases for me.), making all aliases non-functional
+ after exceeding this point.
+
+ What I did was to get the gnu-dbm-1.6 package, compile it, and
+ then re-compile sendmail with "-lgdbm", "-DNDBM", and using the
+ ndbm.h header file that comes with the gnu-package. This makes
+ things behave properly.
+
+ I suppose porting the New Berkeley db package is another route,
+ however, I made a quick attempt at it, and found it difficult
+ (not easy at least); the gnu-dbm package "configured" and
+ compiled easily.
+
+SCO Unix
+ From: Thomas Essebier <tom@stallion.oz.au>
+ Organisation: Stallion Technologies Pty Ltd.
+
+ It will probably help those who are trying to configure sendmail 8.6.9
+ to know that if they are on SCO, they had better set
+ OI-dnsrch
+ or they will core dump as soon as they try to use the resolver.
+ ie. although SCO has _res.dnsrch defined, and is kinda BIND 4.8.3, it
+ does not inititialise it, nor does it understand 'search' in
+ /etc/named.boot.
+ - sigh -
+
+DG/UX
+ Doug Anderson <dlander@afterlife.ncsc.mil> has successfully run
+ V8 on the DG/UX 5.4.2 and 5.4R3.x platforms under heavy usage.
+ Originally, the DG /bin/mail program wasn't compatible with
+ the V8 sendmail, since the DG /bin/mail requires the environment
+ variable "_FORCE_MAIL_LOCAL_=yes" be set. Version 8.7 now includes
+ this in the environment before invoking the local mailer. Some
+ have used procmail to avoid this problem in the past. It works
+ but some have experienced file locking problems with their DG/UX
+ ports of procmail.
+
+Apollo DomainOS
+ If you are compiling on Apollo, you will have to create an empty
+ file "unistd.h" and create a file "dirent.h" containing:
+
+ #include <sys/dir.h>
+ #define dirent direct
+
+ (The Makefile.DomainOS will attempt to do both of these for you.)
+
+HP-UX 8.00
+ Date: Mon, 24 Jan 1994 13:25:45 +0200
+ From: Kimmo Suominen <Kimmo.Suominen@lut.fi>
+ Subject: 8.6.5 w/ HP-UX 8.00 on s300
+
+ Just compiled and fought with sendmail 8.6.5 on a HP9000/360 (ie. a
+ series 300 machine) running HP-UX 8.00.
+
+ I was getting segmentation fault when delivering to a local user.
+ With debugging I saw it was faulting when doing _free@libc... *sigh*
+ It seems the new implementation of malloc on s300 is buggy as of 8.0,
+ so I tried out the one in -lmalloc (malloc(3X)). With that it seems
+ to work just dandy.
+
+ When linking, you will get the following error:
+
+ ld: multiply defined symbol _freespace in file /usr/lib/libmalloc.a
+
+ but you can just ignore it. You might want to add this info to the
+ README file for the future...
+
+Linux
+ Something broke between versions 0.99.13 and 0.99.14 of Linux:
+ the flock() system call gives errors. If you are running .14,
+ you must not use flock. You can do this with -DHASFLOCK=0.
+
+ Around the inclusion of bind-4.9.3 & linux libc-4.6.20, the
+ initialization of the _res structure changed. If /etc/hosts.conf
+ was configured as "hosts, bind" the resolver code could return
+ "Name server failure" errors. This is supposedly fixed in
+ later versions of libc (>= 4.6.29?), and later versions of
+ sendmail (> 8.6.10) try to work around the problem.
+
+ Some older versions (< 4.6.20?) of the libc/include files conflict
+ with sendmail's version of cdefs.h. Deleting sendmail's version
+ on those systems should be non-harmful, and new versions don't care.
+
+ Sendmail assumes that libc has snprintf, which has been true since
+ libc 4.7.0. If you are running an older version, you will need to
+ use -DHASSNPRINTF=0 in the Makefile. If may be able to use -lbsd
+ (which includes snprintf) instead of turning this off on versions
+ of libc between 4.4.4 and 4.7.0 (snprintf improves security, so
+ you want to use this if at all possible).
+
+AIX
+ This version of sendmail does not support MB, MG, and MR resource
+ records, which are supported by AIX sendmail.
+
+ Several people have reported that the IBM-supplied named returns
+ fairly random results -- the named should be replaced. It is not
+ necessary to replace the resolver, which will simplify installation.
+ A new BIND resolver can be found at http://www.isc.org/isc/.
+
+RISC/os
+ RISC/os from MIPS is a merged AT&T/Berkeley system. When you
+ compile on that platform you will get duplicate definitions
+ on many files. You can ignore these.
+
+System V Release 4 Based Systems
+ There is a single Makefile that is intended for all SVR4-based
+ systems (called Makefile.SVR4). It defines __svr4__, which is
+ predefined by some compilers. If your compiler already defines
+ this compile variable, you can delete the definition from the
+ Makefile.
+
+ It's been tested on Dell Issue 2.2.
+
+DELL SVR4
+ Date: Mon, 06 Dec 1993 10:42:29 EST
+ From: "Kimmo Suominen" <kim@grendel.lut.fi>
+ Message-ID: <2d0352f9.lento29@lento29.UUCP>
+ To: eric@cs.berkeley.edu
+ Cc: sendmail@cs.berkeley.edu
+ Subject: Notes for DELL SVR4
+
+ Eric,
+
+ Here are some notes for compiling Sendmail 8.6.4 on DELL SVR4. I ran
+ across these things when helping out some people who contacted me by
+ e-mail.
+
+ 1) Use gcc 2.4.5 (or later?). Dell distributes gcc 2.1 with their
+ Issue 2.2 Unix. It is too old, and gives you problems with
+ clock.c, because sigset_t won't get defined in <sys/signal.h>.
+ This is due to a problematic protection rule in there, and is
+ fixed with gcc 2.4.5.
+
+ 2) If you don't use the new Berkeley DB (-DNEWDB), then you need
+ to add "-lc -lucb" to the libraries to link with. This is because
+ the -ldbm distributed by Dell needs the bcopy, bcmp and bzero
+ functions. It is important that you specify both libraries in
+ the given order to be sure you only get the BSTRING functions
+ from the UCB library (and not the signal routines etc.).
+
+ 3) Don't leave out "-lelf" even if compiling with "-lc -lucb".
+ The UCB library also has another copy of the nlist routines,
+ but we do want the ones from "-lelf".
+
+ If anyone needs a compiled gcc 2.4.5 and/or a ported DB library, they
+ can use anonymous ftp to fetch them from lut.fi in the /kim directory.
+ They are copies of what I use on grendel.lut.fi, and offering them
+ does not imply that I would also support them. I have sent the DB
+ port for SVR4 back to Keith Bostic for inclusion in the official
+ distribution, but I haven't heard anything from him as of today.
+
+ - gcc-2.4.5-svr4.tar.gz (gcc 2.4.5 and the corresponding libg++)
+ - db-1.72.tar.gz (with source, objects and a installed copy)
+
+ Cheers
+ + Kim
+ --
+ * Kimmo.Suominen@lut.fi * SysVr4 enthusiast at GRENDEL.LUT.FI *
+ * KIM@FINFILES.BITNET * Postmaster and Hostmaster at LUT.FI *
+ * + 358 200 865 718 * Unix area moderator at NIC.FUNET.FI *
+
+ConvexOS 10.1 and below
+ In order to use the name server, you must create the file
+ /etc/use_nameserver. If this file does not exist, the call
+ to res_init() will fail and you will have absolutely no
+ access to DNS, including MX records.
+
+Amdahl UTS 2.1.5
+ In order to get UTS to work, you will have to port BIND 4.9.
+ The vendor's BIND is reported to be ``totally inadequate.''
+ See sendmail/contrib/AmdahlUTS.patch for the patches necessary
+ to get BIND 4.9 compiled for UTS.
+
+UnixWare 2.0
+ According to Alexander Kolbasov <sasha@unitech.gamma.ru>,
+ the m4 on UnixWare 2.0 (still in Beta) will core dump on the
+ config files. GNU m4 and the m4 from UnixWare 1.x both work.
+
+UNICOS 8.0.3.4
+ Some people have reported that the -O flag on UNICOS can cause
+ problems. You may want to turn this off if you have problems
+ running sendmail. Reported by Jerry G. DeLapp <jgd@acl.lanl.gov>.
+
+Non-DNS based sites
+ This version of sendmail always tries to connect to the Domain
+ Name System (DNS) to resolve names, regardless of the setting
+ of the `I' option. On most systems that are not running DNS,
+ this will fail quickly and sendmail will continue, but on some
+ systems it has a long timeout. If you have this problem, you
+ will have to recompile without NAMED_BIND. Some people have
+ claimed that they have successfully used "OI+USEVC" to force
+ sendmail to use a virtual circuit -- this will always time out
+ quickly, but also tells sendmail that a failed connection
+ should requeue the message (probably not what you intended).
+ A future release of sendmail will correct this problem.
+
+Both NEWDB and NDBM
+ 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.
+
+GNU getopt
+ I'm told that GNU getopt has a problem in that it gets confused
+ by the double call. Use the version in conf.c instead.
+
+BIND 4.9.2 and Ultrix
+ If you are running on Ultrix, be sure you read conf/Info.Ultrix
+ in the BIND distribution very carefully -- there is information
+ in there that you need to know in order to avoid errors of the
+ form:
+
+ /lib/libc.a(gethostent.o): sethostent: multiply defined
+ /lib/libc.a(gethostent.o): endhostent: multiply defined
+ /lib/libc.a(gethostent.o): gethostbyname: multiply defined
+ /lib/libc.a(gethostent.o): gethostbyaddr: multiply defined
+
+ during the link stage.
+
+strtoul
+ Some compilers (notably gcc) claim to be ANSI C but do not
+ include the ANSI-required routine "strtoul". If your compiler
+ has this problem, you will get an error in srvrsmtp.c on the
+ code:
+
+ # ifdef defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY)
+ e->e_msgsize = strtoul(vp, (char **) NULL, 10);
+ # else
+ e->e_msgsize = strtol(vp, (char **) NULL, 10);
+ # endif
+
+ You can use -DBROKEN_ANSI_LIBRARY to get around this problem.
+
+Listproc 6.0c
+ Date: 23 Sep 1995 23:56:07 GMT
+ Message-ID: <95925101334.~INN-AUMa00187.comp-news@dl.ac.uk>
+ From: alansz@mellers1.psych.berkeley.edu (Alan Schwartz)
+ Subject: Listproc 6.0c + Sendmail 8.7 [Helpful hint]
+
+ Just upgraded to sendmail 8.7, and discovered that listproc 6.0c
+ breaks, because it, by default, sends a blank "HELO" rather than
+ a "HELO hostname" when using the 'system' or 'telnet' mailmethod.
+
+ The fix is to include -DZMAILER in the compilation, which will
+ cause it to use "HELO hostname" (which Z-mail apparently requires
+ as well. :)
+
+
+
++--------------+
+| MANUAL PAGES |
++--------------+
+
+The manual pages have been written against the -mandoc macros
+instead of the -man macros. The latest version of groff has them
+included. You can also get a copy from FTP.UU.NET in directory
+/systems/unix/bsd-sources/share/tmac.
+
+
++-----------------+
+| DEBUGGING HOOKS |
++-----------------+
+
+As of 8.6.5, sendmail daemons will catch a SIGUSR1 signal and log
+some debugging output (logged at LOG_DEBUG severity). The
+information dumped is:
+
+ * The value of the $j macro.
+ * A warning if $j is not in the set $=w.
+ * A list of the open file descriptors.
+ * The contents of the connection cache.
+ * If ruleset 89 is defined, it is evaluated and the results printed.
+
+This allows you to get information regarding the runtime state of the
+daemon on the fly. This should not be done too frequently, since
+the process of rewriting may lose memory which will not be recovered.
+Also, ruleset 89 may call non-reentrant routines, so there is a small
+non-zero probability that this will cause other problems. It is
+really only for debugging serious problems.
+
+A typical formulation of ruleset 89 would be:
+
+ R$* $@ $>0 some test address
+
+
++-----------------------------+
+| DESCRIPTION OF SOURCE FILES |
++-----------------------------+
+
+The following list describes the files in this directory:
+
+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.
+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
+ in sendmail -- e.g., timeouts.
+collect.c The routine that actually reads the mail into a temp
+ file. It also does a certain amount of parsing of
+ the header, etc.
+conf.c The configuration file. This contains information
+ that is presumed to be quite static and non-
+ controversial, or code compiled in for efficiency
+ reasons. Most of the configuration is in sendmail.cf.
+conf.h Configuration that must be known everywhere.
+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.
+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.
+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.
+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
+ translates it to internal form.
+recipient.c Routines that manipulate the recipient list.
+savemail.c Routines which save the letter on processing errors.
+sendmail.h Main header file for sendmail.
+srvrsmtp.c Routines to implement server SMTP.
+stab.c Routines to manage the symbol table.
+stats.c Routines to collect and post the statistics.
+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.
+udb.c The user database interface module.
+usersmtp.c Routines to implement user SMTP.
+util.c Some general purpose routines used by sendmail.
+version.c The version number and information about this
+ version of sendmail. Theoretically, this gets
+ modified on every change.
+
+Eric Allman
+
+(Version 8.112, last update 11/18/95 08:44:31)
diff --git a/usr.sbin/sendmail/src/TRACEFLAGS b/usr.sbin/sendmail/src/TRACEFLAGS
new file mode 100644
index 000000000000..f2499aac0913
--- /dev/null
+++ b/usr.sbin/sendmail/src/TRACEFLAGS
@@ -0,0 +1,71 @@
+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, shouldqueue
+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
+18 usersmtp.c reply, smtpmessage, smtpinit, smtpmailfrom
+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
+43 mime.c mime8to7
+44 recipient.c writeable
+44 util.c safefile
+45 envelope.c setsender
+46 envelope.c openxscript
+49 conf.c checkcompat
+50 envelope.c dropenvelope
+51 queue.c unlockqueue
+52 main.c disconnect
+53 util.c xfclose
+54 err.c putoutmsg
+55 conf.c lockfile
+59 Extended Load Average implementation from Christophe Wolfhugel
+60 map.c
+61 conf.c sm_gethostbyname
+80 content length
+81 sun remote mode
+91 mci.c syslogging of MCI cache information
+99 main.c avoid backgrounding (no printed output)
diff --git a/usr.sbin/sendmail/src/alias.c b/usr.sbin/sendmail/src/alias.c
new file mode 100644
index 000000000000..2bc4487d4a36
--- /dev/null
+++ b/usr.sbin/sendmail/src/alias.c
@@ -0,0 +1,835 @@
+/*
+ * Copyright (c) 1983, 1995 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
+static char sccsid[] = "@(#)alias.c 8.52 (Berkeley) 10/28/95";
+#endif /* not lint */
+
+
+MAP *AliasFileMap = NULL; /* the actual aliases.files map */
+int NAliasFileMaps; /* the number of entries in AliasFileMap */
+ /*
+** ALIAS -- Compute aliases.
+**
+** Scans the alias file for an alias for the given address.
+** If found, it arranges to deliver to the alias list instead.
+** Uses libdbm database if -DDBM.
+**
+** Parameters:
+** a -- address to alias.
+** sendq -- a pointer to the head of the send queue
+** to put the aliases in.
+** aliaslevel -- the current alias nesting depth.
+** e -- the current envelope.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Aliases found are expanded.
+**
+** Deficiencies:
+** It should complain about names that are aliased to
+** nothing.
+*/
+
+void
+alias(a, sendq, aliaslevel, e)
+ register ADDRESS *a;
+ ADDRESS **sendq;
+ int aliaslevel;
+ register ENVELOPE *e;
+{
+ register char *p;
+ int naliases;
+ char *owner;
+ auto int stat = EX_OK;
+ char obuf[MAXNAME + 6];
+ extern char *aliaslookup();
+
+ if (tTd(27, 1))
+ printf("alias(%s)\n", a->q_user);
+
+ /* don't realias already aliased names */
+ if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
+ return;
+
+ if (NoAlias)
+ return;
+
+ e->e_to = a->q_paddr;
+
+ /*
+ ** Look up this name.
+ **
+ ** If the map was unavailable, we will queue this message
+ ** until the map becomes available; otherwise, we could
+ ** bounce messages inappropriately.
+ */
+
+ p = aliaslookup(a->q_user, &stat, e);
+ if (stat == EX_TEMPFAIL || stat == EX_UNAVAILABLE)
+ {
+ a->q_flags |= QQUEUEUP;
+ if (e->e_message == NULL)
+ e->e_message = "alias database unavailable";
+ return;
+ }
+ if (p == NULL)
+ return;
+
+ /*
+ ** Match on Alias.
+ ** Deliver to the target list.
+ */
+
+ if (tTd(27, 1))
+ printf("%s (%s, %s) aliased to %s\n",
+ a->q_paddr, a->q_host, a->q_user, p);
+ if (bitset(EF_VRFYONLY, e->e_flags))
+ {
+ a->q_flags |= QVERIFIED;
+ return;
+ }
+ message("aliased to %s", shortenstring(p, 203));
+#ifdef LOG
+ if (LogLevel > 9)
+ syslog(LOG_INFO, "%s: alias %.100s => %s",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ a->q_paddr, shortenstring(p, 203));
+#endif
+ a->q_flags &= ~QSELFREF;
+ if (tTd(27, 5))
+ {
+ printf("alias: QDONTSEND ");
+ printaddr(a, FALSE);
+ }
+ a->q_flags |= QDONTSEND;
+ naliases = sendtolist(p, a, sendq, aliaslevel + 1, e);
+ if (bitset(QSELFREF, a->q_flags))
+ 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, &stat, e);
+ if (owner == NULL)
+ return;
+
+ /* reflect owner into envelope sender */
+ if (strpbrk(owner, ",:/|\"") != NULL)
+ owner = obuf;
+ a->q_owner = newstr(owner);
+
+ /* announce delivery to this alias; NORECEIPT bit set later */
+ if (e->e_xfp != NULL)
+ fprintf(e->e_xfp, "Message delivered to mailing list %s\n",
+ a->q_paddr);
+ e->e_flags |= EF_SENDRECEIPT;
+ a->q_flags |= QDELIVERED|QEXPANDED;
+}
+ /*
+** ALIASLOOKUP -- look up a name in the alias file.
+**
+** Parameters:
+** name -- the name to look up.
+** pstat -- a pointer to a place to put the status.
+** e -- the current envelope.
+**
+** Returns:
+** the value of name.
+** NULL if unknown.
+**
+** Side Effects:
+** none.
+**
+** Warnings:
+** The return value will be trashed across calls.
+*/
+
+char *
+aliaslookup(name, pstat, e)
+ char *name;
+ int *pstat;
+ ENVELOPE *e;
+{
+ static MAP *map = NULL;
+
+ if (map == NULL)
+ {
+ STAB *s = stab("aliases", ST_MAP, ST_FIND);
+
+ if (s == NULL)
+ return NULL;
+ map = &s->s_map;
+ }
+ if (!bitset(MF_OPEN, map->map_mflags))
+ return NULL;
+ return (*map->map_class->map_lookup)(map, name, NULL, pstat);
+}
+ /*
+** SETALIAS -- set up an alias map
+**
+** Called when reading configuration file.
+**
+** Parameters:
+** spec -- the alias specification
+**
+** Returns:
+** none.
+*/
+
+void
+setalias(spec)
+ char *spec;
+{
+ register char *p;
+ register MAP *map;
+ char *class;
+ STAB *s;
+
+ if (tTd(27, 8))
+ printf("setalias(%s)\n", spec);
+
+ for (p = spec; p != NULL; )
+ {
+ char buf[50];
+
+ while (isspace(*p))
+ p++;
+ if (*p == '\0')
+ break;
+ spec = p;
+
+ if (NAliasFileMaps >= MAXMAPSTACK)
+ {
+ syserr("Too many alias databases defined, %d max",
+ MAXMAPSTACK);
+ return;
+ }
+ if (AliasFileMap == NULL)
+ {
+ strcpy(buf, "aliases.files sequence");
+ AliasFileMap = makemapentry(buf);
+ if (AliasFileMap == NULL)
+ {
+ syserr("setalias: cannot create aliases.files map");
+ return;
+ }
+ }
+ (void) sprintf(buf, "Alias%d", NAliasFileMaps);
+ s = stab(buf, ST_MAP, ST_ENTER);
+ map = &s->s_map;
+ bzero(map, sizeof *map);
+ map->map_mname = s->s_name;
+
+ 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';
+
+ if (tTd(27, 20))
+ printf(" map %s:%s %s\n", class, s->s_name, spec);
+
+ /* 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;
+ AliasFileMap->map_stack[NAliasFileMaps++] = map;
+ }
+ }
+ }
+}
+ /*
+** ALIASWAIT -- wait for distinguished @:@ token to appear.
+**
+** This can decide to reopen or rebuild the alias file
+**
+** Parameters:
+** map -- a pointer to the map descriptor for this alias file.
+** ext -- the filename extension (e.g., ".db") for the
+** database file.
+** isopen -- if set, the database is already open, and we
+** should check for validity; otherwise, we are
+** just checking to see if it should be created.
+**
+** Returns:
+** TRUE -- if the database is open when we return.
+** FALSE -- if the database is closed when we return.
+*/
+
+bool
+aliaswait(map, ext, isopen)
+ MAP *map;
+ char *ext;
+ int isopen;
+{
+ bool attimeout = FALSE;
+ time_t mtime;
+ struct stat stb;
+ char buf[MAXNAME + 1];
+
+ if (tTd(27, 3))
+ printf("aliaswait(%s:%s)\n",
+ map->map_class->map_cname, map->map_file);
+ if (bitset(MF_ALIASWAIT, map->map_mflags))
+ return isopen;
+ map->map_mflags |= MF_ALIASWAIT;
+
+ if (SafeAlias > 0)
+ {
+ auto int st;
+ time_t toolong = curtime() + SafeAlias;
+ unsigned int sleeptime = 2;
+
+ while (isopen &&
+ map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
+ {
+ if (curtime() > toolong)
+ {
+ /* we timed out */
+ attimeout = TRUE;
+ break;
+ }
+
+ /*
+ ** Close and re-open the alias database in case
+ ** the one is mv'ed instead of cp'ed in.
+ */
+
+ if (tTd(27, 2))
+ printf("aliaswait: sleeping for %d seconds\n",
+ sleeptime);
+
+ map->map_class->map_close(map);
+ map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ sleep(sleeptime);
+ sleeptime *= 2;
+ if (sleeptime > 60)
+ sleeptime = 60;
+ isopen = map->map_class->map_open(map, O_RDONLY);
+ }
+ }
+
+ /* see if we need to go into auto-rebuild mode */
+ if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
+ {
+ if (tTd(27, 3))
+ printf("aliaswait: not rebuildable\n");
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
+ }
+ if (stat(map->map_file, &stb) < 0)
+ {
+ if (tTd(27, 3))
+ printf("aliaswait: no source file\n");
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
+ }
+ 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 || attimeout)
+ {
+ /* database is out of date */
+ if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
+ {
+ bool oldSuprErrs;
+
+ message("auto-rebuilding alias database %s", buf);
+ oldSuprErrs = SuprErrs;
+ SuprErrs = TRUE;
+ if (isopen)
+ {
+ map->map_class->map_close(map);
+ map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ }
+ rebuildaliases(map, TRUE);
+ isopen = map->map_class->map_open(map, O_RDONLY);
+ SuprErrs = oldSuprErrs;
+ }
+ else
+ {
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_INFO, "alias database %s out of date",
+ buf);
+#endif /* LOG */
+ message("Warning: alias database %s out of date", buf);
+ }
+ }
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
+}
+ /*
+** REBUILDALIASES -- rebuild the alias database.
+**
+** Parameters:
+** map -- the database to rebuild.
+** automatic -- set if this was automatically generated.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Reads the text version of the database, builds the
+** DBM or DB version.
+*/
+
+void
+rebuildaliases(map, automatic)
+ register MAP *map;
+ bool automatic;
+{
+ FILE *af;
+ bool nolock = FALSE;
+ sigfunc_t oldsigint, oldsigquit;
+#ifdef SIGTSTP
+ sigfunc_t oldsigtstp;
+#endif
+
+ if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
+ return;
+
+ /* try to lock the source file */
+ if ((af = fopen(map->map_file, "r+")) == NULL)
+ {
+ struct stat stb;
+
+ if ((errno != EACCES && errno != EROFS) || automatic ||
+ (af = fopen(map->map_file, "r")) == NULL)
+ {
+ int saveerr = errno;
+
+ if (tTd(27, 1))
+ printf("Can't open %s: %s\n",
+ map->map_file, errstring(saveerr));
+ if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
+ message("newaliases: cannot open %s: %s",
+ map->map_file, errstring(saveerr));
+ errno = 0;
+ return;
+ }
+ nolock = TRUE;
+ if (tTd(27, 1) ||
+ fstat(fileno(af), &stb) < 0 ||
+ bitset(S_IWUSR|S_IWGRP|S_IWOTH, stb.st_mode))
+ message("warning: cannot lock %s: %s",
+ map->map_file, errstring(errno));
+ }
+
+ /* see if someone else is rebuilding the alias file */
+ if (!nolock &&
+ !lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB))
+ {
+ /* 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 */
+ (void) lockfile(fileno(af), map->map_file, NULL,
+ LOCK_EX);
+ }
+ (void) xfclose(af, "rebuildaliases1", map->map_file);
+ errno = 0;
+ return;
+ }
+
+ /* avoid denial-of-service attacks */
+ resetlimits();
+ oldsigint = setsignal(SIGINT, SIG_IGN);
+ oldsigquit = setsignal(SIGQUIT, SIG_IGN);
+#ifdef SIGTSTP
+ oldsigtstp = setsignal(SIGTSTP, SIG_IGN);
+#endif
+
+ if (map->map_class->map_open(map, O_RDWR))
+ {
+#ifdef LOG
+ if (LogLevel > 7)
+ {
+ syslog(LOG_NOTICE, "alias database %s %srebuilt by %s",
+ map->map_file, automatic ? "auto" : "",
+ username());
+ }
+#endif /* LOG */
+ map->map_mflags |= MF_OPEN|MF_WRITABLE;
+ readaliases(map, af, !automatic, TRUE);
+ }
+ 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 */
+ xfclose(af, "rebuildaliases2", map->map_file);
+
+ /* add distinguished entries and close the database */
+ if (bitset(MF_OPEN, map->map_mflags))
+ {
+ map->map_class->map_close(map);
+ map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ }
+
+ /* restore the old signals */
+ (void) setsignal(SIGINT, oldsigint);
+ (void) setsignal(SIGQUIT, oldsigquit);
+#ifdef SIGTSTP
+ (void) setsignal(SIGTSTP, oldsigtstp);
+#endif
+}
+ /*
+** 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.
+** announcestats -- anounce statistics regarding number of
+** aliases, longest alias, etc.
+** logstats -- lot the same info.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Reads aliasfile into the symbol table.
+** Optionally, builds the .dir & .pag files.
+*/
+
+void
+readaliases(map, af, announcestats, logstats)
+ register MAP *map;
+ FILE *af;
+ bool announcestats;
+ bool logstats;
+{
+ register char *p;
+ char *rhs;
+ bool skipping;
+ long naliases, bytes, longest;
+ ADDRESS al, bl;
+ char line[BUFSIZ];
+
+ /*
+ ** Read and interpret lines
+ */
+
+ FileName = map->map_file;
+ LineNumber = 0;
+ naliases = bytes = longest = 0;
+ skipping = FALSE;
+ while (fgets(line, sizeof (line), af) != NULL)
+ {
+ int lhssize, rhssize;
+
+ LineNumber++;
+ p = strchr(line, '\n');
+ if (p != NULL)
+ *p = '\0';
+ switch (line[0])
+ {
+ case '#':
+ case '\0':
+ skipping = FALSE;
+ continue;
+
+ case ' ':
+ case '\t':
+ if (!skipping)
+ syserr("554 Non-continuation line starts with space");
+ skipping = TRUE;
+ continue;
+ }
+ skipping = FALSE;
+
+ /*
+ ** Process the LHS
+ ** 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
+ ** detection).
+ */
+
+ for (p = line; *p != '\0' && *p != ':' && *p != '\n'; p++)
+ continue;
+ if (*p++ != ':')
+ {
+ syserr("554 missing colon");
+ continue;
+ }
+ if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL)
+ {
+ syserr("554 %.40s... illegal alias name", line);
+ continue;
+ }
+
+ /*
+ ** Process the RHS.
+ ** 'al' is the internal form of the LHS address.
+ ** 'p' points to the text of the RHS.
+ */
+
+ while (isascii(*p) && isspace(*p))
+ p++;
+ rhs = p;
+ for (;;)
+ {
+ register char c;
+ register char *nlp;
+
+ nlp = &p[strlen(p)];
+ if (nlp[-1] == '\n')
+ *--nlp = '\0';
+
+ if (CheckAliases)
+ {
+ /* do parsing & compression of addresses */
+ while (*p != '\0')
+ {
+ auto char *delimptr;
+
+ while ((isascii(*p) && isspace(*p)) ||
+ *p == ',')
+ p++;
+ if (*p == '\0')
+ break;
+ if (parseaddr(p, &bl, RF_COPYNONE, ',',
+ &delimptr, CurEnv) == NULL)
+ usrerr("553 %s... bad address", p);
+ p = delimptr;
+ }
+ }
+ else
+ {
+ p = nlp;
+ }
+
+ /* see if there should be a continuation line */
+ c = getc(af);
+ if (!feof(af))
+ (void) ungetc(c, af);
+ if (c != ' ' && c != '\t')
+ break;
+
+ /* read continuation line */
+ 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 (!bitnset(M_ALIASABLE, al.q_mailer->m_flags))
+ {
+ syserr("554 %s... cannot alias non-local names",
+ al.q_paddr);
+ continue;
+ }
+
+ /*
+ ** Insert alias into symbol table or DBM file
+ */
+
+ if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags))
+ makelower(al.q_user);
+
+ lhssize = strlen(al.q_user);
+ rhssize = strlen(rhs);
+ map->map_class->map_store(map, al.q_user, 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++;
+ bytes += lhssize + rhssize;
+ if (rhssize > longest)
+ longest = rhssize;
+ }
+
+ CurEnv->e_to = NULL;
+ FileName = NULL;
+ if (Verbose || announcestats)
+ message("%s: %d aliases, longest %d bytes, %d bytes total",
+ map->map_file, naliases, longest, bytes);
+# ifdef LOG
+ if (LogLevel > 7 && logstats)
+ syslog(LOG_INFO, "%s: %d aliases, longest %d bytes, %d bytes total",
+ map->map_file, naliases, longest, bytes);
+# endif /* LOG */
+}
+ /*
+** FORWARD -- Try to forward mail
+**
+** This is similar but not identical to aliasing.
+**
+** Parameters:
+** user -- the name of the user who's mail we would like
+** to forward to. It must have been verified --
+** i.e., the q_home field must have been filled
+** in.
+** sendq -- a pointer to the head of the send queue to
+** put this user's aliases in.
+** aliaslevel -- the current alias nesting depth.
+** e -- the current envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** New names are added to send queues.
+*/
+
+void
+forward(user, sendq, aliaslevel, e)
+ ADDRESS *user;
+ ADDRESS **sendq;
+ int aliaslevel;
+ register ENVELOPE *e;
+{
+ char *pp;
+ char *ep;
+
+ if (tTd(27, 1))
+ printf("forward(%s)\n", user->q_paddr);
+
+ if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) ||
+ bitset(QBADADDR, user->q_flags))
+ return;
+ if (user->q_home == NULL)
+ {
+ syserr("554 forward: no home");
+ user->q_home = "/nosuchdirectory";
+ }
+
+ /* good address -- look for .forward file in home */
+ 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");
+
+ for (pp = ForwardPath; pp != NULL; pp = ep)
+ {
+ int err;
+ char buf[MAXPATHLEN+1];
+ extern int include();
+
+ ep = strchr(pp, ':');
+ if (ep != NULL)
+ *ep = '\0';
+ expand(pp, buf, sizeof buf, e);
+ if (ep != NULL)
+ *ep++ = ':';
+ if (tTd(27, 3))
+ printf("forward: trying %s\n", buf);
+
+ err = include(buf, TRUE, user, sendq, aliaslevel, e);
+ if (err == 0)
+ break;
+ else 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 == NULL ? "NOQUEUE" : e->e_id,
+ buf, errstring(err));
+#endif
+ message("%s: %s: message queued", buf, errstring(err));
+ user->q_flags |= QQUEUEUP;
+ return;
+ }
+ }
+}
diff --git a/usr.sbin/sendmail/src/arpadate.c b/usr.sbin/sendmail/src/arpadate.c
new file mode 100644
index 000000000000..f6764704db07
--- /dev/null
+++ b/usr.sbin/sendmail/src/arpadate.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)arpadate.c 8.4 (Berkeley) 4/21/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** ARPADATE -- Create date in ARPANET format
+**
+** Parameters:
+** ud -- unix style date string. if NULL, one is created.
+**
+** Returns:
+** pointer to an ARPANET date field
+**
+** Side Effects:
+** none
+**
+** WARNING:
+** date is stored in a local buffer -- subsequent
+** calls will overwrite.
+**
+** Bugs:
+** Timezone is computed from local time, rather than
+** from whereever (and whenever) the message was sent.
+** To do better is very hard.
+**
+** Some sites are now inserting the timezone into the
+** local date. This routine should figure out what
+** the format is and work appropriately.
+*/
+
+#ifndef TZNAME_MAX
+# define TZNAME_MAX 50 /* max size of timezone */
+#endif
+
+/* values for TZ_TYPE */
+#define TZ_NONE 0 /* no character timezone support */
+#define TZ_TM_NAME 1 /* use tm->tm_name */
+#define TZ_TM_ZONE 2 /* use tm->tm_zone */
+#define TZ_TZNAME 3 /* use tzname[] */
+#define TZ_TIMEZONE 4 /* use timezone() */
+
+char *
+arpadate(ud)
+ register char *ud;
+{
+ register char *p;
+ register char *q;
+ register int off;
+ register int i;
+ register struct tm *lt;
+ time_t t;
+ struct tm gmt;
+ char *tz;
+ static char b[43 + TZNAME_MAX];
+
+ /*
+ ** Get current time.
+ ** This will be used if a null argument is passed and
+ ** to resolve the timezone.
+ */
+
+ (void) time(&t);
+ if (ud == NULL)
+ ud = ctime(&t);
+
+ /*
+ ** Crack the UNIX date line in a singularly unoriginal way.
+ */
+
+ q = b;
+
+ p = &ud[0]; /* Mon */
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = ',';
+ *q++ = ' ';
+
+ p = &ud[8]; /* 16 */
+ if (*p == ' ')
+ p++;
+ else
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = ' ';
+
+ p = &ud[4]; /* Sep */
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = ' ';
+
+ p = &ud[20]; /* 1979 */
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = *p++;
+ *q++ = ' ';
+
+ p = &ud[11]; /* 01:03:52 */
+ for (i = 8; i > 0; i--)
+ *q++ = *p++;
+
+ /*
+ * should really get the timezone from the time in "ud" (which
+ * is only different if a non-null arg was passed which is different
+ * from the current time), but for all practical purposes, returning
+ * the current local zone will do (its all that is ever needed).
+ */
+ gmt = *gmtime(&t);
+ lt = localtime(&t);
+
+ off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
+
+ /* assume that offset isn't more than a day ... */
+ if (lt->tm_year < gmt.tm_year)
+ off -= 24 * 60;
+ else if (lt->tm_year > gmt.tm_year)
+ off += 24 * 60;
+ else if (lt->tm_yday < gmt.tm_yday)
+ off -= 24 * 60;
+ else if (lt->tm_yday > gmt.tm_yday)
+ off += 24 * 60;
+
+ *q++ = ' ';
+ if (off == 0)
+ {
+ *q++ = 'G';
+ *q++ = 'M';
+ *q++ = 'T';
+ }
+ else
+ {
+ tz = NULL;
+#if TZ_TYPE == TZ_TM_NAME
+ tz = lt->tm_name;
+#endif
+#if TZ_TYPE == TZ_TM_ZONE
+ tz = lt->tm_zone;
+#endif
+#if TZ_TYPE == TZ_TZNAME
+ {
+ extern char *tzname[];
+
+ tz = tzname[lt->tm_isdst];
+ }
+#endif
+#if TZ_TYPE == TZ_TIMEZONE
+ {
+ extern char *timezone();
+
+ tz = timezone(off, lt->tm_isdst);
+ }
+#endif
+ if (off < 0)
+ {
+ off = -off;
+ *q++ = '-';
+ }
+ else
+ *q++ = '+';
+
+ if (off >= 24*60) /* should be impossible */
+ off = 23*60+59; /* if not, insert silly value */
+
+ *q++ = (off / 600) + '0';
+ *q++ = (off / 60) % 10 + '0';
+ off %= 60;
+ *q++ = (off / 10) + '0';
+ *q++ = (off % 10) + '0';
+ if (tz != NULL && *tz != '\0')
+ {
+ *q++ = ' ';
+ *q++ = '(';
+ while (*tz != '\0')
+ *q++ = *tz++;
+ *q++ = ')';
+ }
+ }
+ *q = '\0';
+
+ return (b);
+}
diff --git a/usr.sbin/sendmail/src/clock.c b/usr.sbin/sendmail/src/clock.c
new file mode 100644
index 000000000000..1490137170e2
--- /dev/null
+++ b/usr.sbin/sendmail/src/clock.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)clock.c 8.12 (Berkeley) 5/23/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+# ifndef sigmask
+# define sigmask(s) (1 << ((s) - 1))
+# endif
+
+/*
+** SETEVENT -- set an event to happen at a specific time.
+**
+** Events are stored in a sorted list for fast processing.
+** An event only applies to the process that set it.
+**
+** Parameters:
+** intvl -- intvl until next event occurs.
+** func -- function to call on event.
+** arg -- argument to func on event.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+static void tick __P((int));
+
+EVENT *
+setevent(intvl, func, arg)
+ time_t intvl;
+ void (*func)();
+ int arg;
+{
+ register EVENT **evp;
+ register EVENT *ev;
+ auto time_t now;
+
+ if (intvl <= 0)
+ {
+ syserr("554 setevent: intvl=%ld\n", intvl);
+ return (NULL);
+ }
+
+ (void) setsignal(SIGALRM, SIG_IGN);
+ (void) time(&now);
+
+ /* search event queue for correct position */
+ for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
+ {
+ if (ev->ev_time >= now + intvl)
+ break;
+ }
+
+ /* insert new event */
+ ev = (EVENT *) xalloc(sizeof *ev);
+ ev->ev_time = now + intvl;
+ ev->ev_func = func;
+ ev->ev_arg = arg;
+ ev->ev_pid = getpid();
+ ev->ev_link = *evp;
+ *evp = ev;
+
+ if (tTd(5, 5))
+ printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
+ intvl, now + intvl, func, arg, ev);
+
+ tick(0);
+ return (ev);
+}
+ /*
+** CLREVENT -- remove an event from the event queue.
+**
+** Parameters:
+** ev -- pointer to event to remove.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** arranges for event ev to not happen.
+*/
+
+void
+clrevent(ev)
+ register EVENT *ev;
+{
+ register EVENT **evp;
+
+ if (tTd(5, 5))
+ printf("clrevent: ev=%x\n", ev);
+ if (ev == NULL)
+ return;
+
+ /* find the parent event */
+ (void) setsignal(SIGALRM, SIG_IGN);
+ for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
+ {
+ if (*evp == ev)
+ break;
+ }
+
+ /* now remove it */
+ if (*evp != NULL)
+ {
+ *evp = ev->ev_link;
+ free((char *) ev);
+ }
+
+ /* restore clocks and pick up anything spare */
+ tick(0);
+}
+ /*
+** TICK -- take a clock tick
+**
+** Called by the alarm clock. This routine runs events as needed.
+**
+** Parameters:
+** One that is ignored; for compatibility with signal handlers.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** calls the next function in EventQueue.
+*/
+
+static void
+tick(arg)
+ int arg;
+{
+ register time_t now;
+ register EVENT *ev;
+ int mypid = getpid();
+ int olderrno = errno;
+#ifdef SIG_UNBLOCK
+ sigset_t ss;
+#endif
+
+ (void) setsignal(SIGALRM, SIG_IGN);
+ (void) alarm(0);
+ now = curtime();
+
+ if (tTd(5, 4))
+ printf("tick: now=%ld\n", now);
+
+ while ((ev = EventQueue) != NULL &&
+ (ev->ev_time <= now || ev->ev_pid != mypid))
+ {
+ void (*f)();
+ int arg;
+ int pid;
+
+ /* process the event on the top of the queue */
+ ev = EventQueue;
+ EventQueue = EventQueue->ev_link;
+ if (tTd(5, 6))
+ printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
+ ev->ev_func, ev->ev_arg, ev->ev_pid);
+
+ /* we must be careful in here because ev_func may not return */
+ f = ev->ev_func;
+ arg = ev->ev_arg;
+ pid = ev->ev_pid;
+ free((char *) ev);
+ if (pid != getpid())
+ continue;
+ if (EventQueue != NULL)
+ {
+ if (EventQueue->ev_time > now)
+ (void) alarm((unsigned) (EventQueue->ev_time - now));
+ else
+ (void) alarm(3);
+ }
+
+ /* restore signals so that we can take ticks while in ev_func */
+ (void) setsignal(SIGALRM, tick);
+#ifdef SIG_UNBLOCK
+ /* unblock SIGALRM signal */
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &ss, NULL);
+#else
+#if HASSIGSETMASK
+ /* reset 4.2bsd signal mask to allow future alarms */
+ (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
+#endif /* HASSIGSETMASK */
+#endif /* SIG_UNBLOCK */
+
+ /* call ev_func */
+ errno = olderrno;
+ (*f)(arg);
+ (void) alarm(0);
+ now = curtime();
+ }
+ (void) setsignal(SIGALRM, tick);
+ if (EventQueue != NULL)
+ (void) alarm((unsigned) (EventQueue->ev_time - now));
+ errno = olderrno;
+}
+ /*
+** SLEEP -- a version of sleep that works with this stuff
+**
+** Because sleep uses the alarm facility, I must reimplement
+** it here.
+**
+** Parameters:
+** intvl -- time to sleep.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** waits for intvl time. However, other events can
+** be run during that interval.
+*/
+
+static bool SleepDone;
+static void endsleep();
+
+#ifndef SLEEP_T
+# define SLEEP_T unsigned int
+#endif
+
+SLEEP_T
+sleep(intvl)
+ unsigned int intvl;
+{
+ if (intvl == 0)
+ return (SLEEP_T) 0;
+ SleepDone = FALSE;
+ (void) setevent((time_t) intvl, endsleep, 0);
+ while (!SleepDone)
+ pause();
+ return (SLEEP_T) 0;
+}
+
+static void
+endsleep()
+{
+ SleepDone = TRUE;
+}
diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c
new file mode 100644
index 000000000000..7e43c5f5ffa2
--- /dev/null
+++ b/usr.sbin/sendmail/src/collect.c
@@ -0,0 +1,743 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)collect.c 8.49 (Berkeley) 10/29/95";
+#endif /* not lint */
+
+# include <errno.h>
+# include "sendmail.h"
+
+/*
+** COLLECT -- read & parse message header & make temp file.
+**
+** Creates a temporary file name and copies the standard
+** input to that file. Leading UNIX-style "From" lines are
+** stripped off (after important information is extracted).
+**
+** Parameters:
+** fp -- file to read.
+** 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.
+** hdrp -- the location to stash the header.
+** e -- the current envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Temp file is created and filled.
+** The from person may be set.
+*/
+
+static jmp_buf CtxCollectTimeout;
+static void collecttimeout();
+static bool CollectProgress;
+static EVENT *CollectTimeout;
+
+/* values for input state machine */
+#define IS_NORM 0 /* middle of line */
+#define IS_BOL 1 /* beginning of line */
+#define IS_DOT 2 /* read a dot at beginning of line */
+#define IS_DOTCR 3 /* read ".\r" at beginning of line */
+#define IS_CR 4 /* read a carriage return */
+
+/* values for message state machine */
+#define MS_UFROM 0 /* reading Unix from line */
+#define MS_HEADER 1 /* reading message header */
+#define MS_BODY 2 /* reading message body */
+
+void
+collect(fp, smtpmode, requeueflag, hdrp, e)
+ FILE *fp;
+ bool smtpmode;
+ bool requeueflag;
+ HDR **hdrp;
+ register ENVELOPE *e;
+{
+ register FILE *tf;
+ bool ignrdot = smtpmode ? FALSE : IgnrDot;
+ time_t dbto = smtpmode ? TimeOuts.to_datablock : 0;
+ register char *bp;
+ int c = '\0';
+ bool inputerr = FALSE;
+ bool headeronly;
+ char *buf;
+ int buflen;
+ int istate;
+ int mstate;
+ char *pbp;
+ char peekbuf[8];
+ char dfname[20];
+ char bufbuf[MAXLINE];
+ extern bool isheader();
+ extern void eatheader();
+ extern void tferror();
+
+ headeronly = hdrp != NULL;
+
+ /*
+ ** Create the temp file name and create the file.
+ */
+
+ if (!headeronly)
+ {
+ struct stat stbuf;
+
+ strcpy(dfname, queuename(e, 'd'));
+ if ((tf = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL)
+ {
+ syserr("Cannot create %s", dfname);
+ e->e_flags |= EF_NO_BODY_RETN;
+ finis();
+ }
+ if (fstat(fileno(tf), &stbuf) < 0)
+ e->e_dfino = -1;
+ else
+ {
+ e->e_dfdev = stbuf.st_dev;
+ e->e_dfino = stbuf.st_ino;
+ }
+ HasEightBits = FALSE;
+ e->e_msgsize = 0;
+ e->e_flags |= EF_HAS_DF;
+ }
+
+ /*
+ ** Tell ARPANET to go ahead.
+ */
+
+ if (smtpmode)
+ message("354 Enter mail, end with \".\" on a line by itself");
+
+ if (tTd(30, 2))
+ printf("collect\n");
+
+ /*
+ ** Read the message.
+ **
+ ** This is done using two interleaved state machines.
+ ** The input state machine is looking for things like
+ ** hidden dots; the message state machine is handling
+ ** the larger picture (e.g., header versus body).
+ */
+
+ buf = bp = bufbuf;
+ buflen = sizeof bufbuf;
+ pbp = peekbuf;
+ istate = IS_BOL;
+ mstate = SaveFrom ? MS_HEADER : MS_UFROM;
+ CollectProgress = FALSE;
+
+ if (dbto != 0)
+ {
+ /* handle possible input timeout */
+ if (setjmp(CtxCollectTimeout) != 0)
+ {
+#ifdef LOG
+ syslog(LOG_NOTICE,
+ "timeout waiting for input from %s during message collect",
+ CurHostName ? CurHostName : "<local machine>");
+#endif
+ errno = 0;
+ usrerr("451 timeout waiting for input during message collect");
+ goto readerr;
+ }
+ CollectTimeout = setevent(dbto, collecttimeout, dbto);
+ }
+
+ for (;;)
+ {
+ if (tTd(30, 35))
+ printf("top, istate=%d, mstate=%d\n", istate, mstate);
+ for (;;)
+ {
+ if (pbp > peekbuf)
+ c = *--pbp;
+ else
+ {
+ while (!feof(fp) && !ferror(fp))
+ {
+ errno = 0;
+ c = getc(fp);
+ if (errno != EINTR)
+ break;
+ clearerr(fp);
+ }
+ CollectProgress = TRUE;
+ if (TrafficLogFile != NULL && !headeronly)
+ {
+ if (istate == IS_BOL)
+ fprintf(TrafficLogFile, "%05d <<< ",
+ getpid());
+ if (c == EOF)
+ fprintf(TrafficLogFile, "[EOF]\n");
+ else
+ putc(c, TrafficLogFile);
+ }
+ if (c == EOF)
+ goto readerr;
+ if (SevenBitInput)
+ c &= 0x7f;
+ else
+ HasEightBits |= bitset(0x80, c);
+ if (!headeronly)
+ e->e_msgsize++;
+ }
+ if (tTd(30, 94))
+ printf("istate=%d, c=%c (0x%x)\n",
+ istate, c, c);
+ switch (istate)
+ {
+ case IS_BOL:
+ if (c == '.')
+ {
+ istate = IS_DOT;
+ continue;
+ }
+ break;
+
+ case IS_DOT:
+ if (c == '\n' && !ignrdot &&
+ !bitset(EF_NL_NOT_EOL, e->e_flags))
+ goto readerr;
+ else if (c == '\r' &&
+ !bitset(EF_CRLF_NOT_EOL, e->e_flags))
+ {
+ istate = IS_DOTCR;
+ continue;
+ }
+ else if (c != '.' ||
+ (OpMode != MD_SMTP &&
+ OpMode != MD_DAEMON &&
+ OpMode != MD_ARPAFTP))
+ {
+ *pbp++ = c;
+ c = '.';
+ }
+ break;
+
+ case IS_DOTCR:
+ if (c == '\n')
+ goto readerr;
+ else
+ {
+ /* push back the ".\rx" */
+ *pbp++ = c;
+ *pbp++ = '\r';
+ c = '.';
+ }
+ break;
+
+ case IS_CR:
+ if (c == '\n')
+ istate = IS_BOL;
+ else
+ {
+ ungetc(c, fp);
+ c = '\r';
+ istate = IS_NORM;
+ }
+ goto bufferchar;
+ }
+
+ if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags))
+ {
+ istate = IS_CR;
+ continue;
+ }
+ else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags))
+ istate = IS_BOL;
+ else
+ istate = IS_NORM;
+
+bufferchar:
+ if (mstate == MS_BODY)
+ {
+ /* just put the character out */
+ if (MaxMessageSize <= 0 ||
+ e->e_msgsize <= MaxMessageSize)
+ putc(c, tf);
+ continue;
+ }
+
+ /* header -- buffer up */
+ if (bp >= &buf[buflen - 2])
+ {
+ char *obuf;
+
+ if (mstate != MS_HEADER)
+ break;
+
+ /* out of space for header */
+ obuf = buf;
+ if (buflen < MEMCHUNKSIZE)
+ buflen *= 2;
+ else
+ buflen += MEMCHUNKSIZE;
+ buf = xalloc(buflen);
+ bcopy(obuf, buf, bp - obuf);
+ bp = &buf[bp - obuf];
+ if (obuf != bufbuf)
+ free(obuf);
+ }
+ if (c != '\0')
+ *bp++ = c;
+ if (istate == IS_BOL)
+ break;
+ }
+ *bp = '\0';
+
+nextstate:
+ if (tTd(30, 35))
+ printf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n",
+ istate, mstate, buf);
+ switch (mstate)
+ {
+ extern int chompheader();
+
+ case MS_UFROM:
+ mstate = MS_HEADER;
+#ifndef NOTUNIX
+ if (strncmp(buf, "From ", 5) == 0)
+ {
+ extern void eatfrom();
+
+ bp = buf;
+ eatfrom(buf, e);
+ continue;
+ }
+#endif
+ /* fall through */
+
+ case MS_HEADER:
+ if (!isheader(buf))
+ {
+ mstate = MS_BODY;
+ goto nextstate;
+ }
+
+ /* check for possible continuation line */
+ do
+ {
+ clearerr(fp);
+ errno = 0;
+ c = getc(fp);
+ } while (errno == EINTR);
+ if (c != EOF)
+ ungetc(c, fp);
+ if (c == ' ' || c == '\t')
+ {
+ /* yep -- defer this */
+ continue;
+ }
+
+ /* trim off trailing CRLF or NL */
+ if (*--bp != '\n' || *--bp != '\r')
+ bp++;
+ *bp = '\0';
+ if (bitset(H_EOH, chompheader(buf, FALSE, hdrp, e)))
+ mstate = MS_BODY;
+ break;
+
+ case MS_BODY:
+ if (tTd(30, 1))
+ printf("EOH\n");
+ if (headeronly)
+ goto readerr;
+ bp = buf;
+
+ /* toss blank line */
+ if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) &&
+ bp[0] == '\r' && bp[1] == '\n') ||
+ (!bitset(EF_NL_NOT_EOL, e->e_flags) &&
+ bp[0] == '\n'))
+ {
+ break;
+ }
+
+ /* if not a blank separator, write it out */
+ if (MaxMessageSize <= 0 ||
+ e->e_msgsize <= MaxMessageSize)
+ {
+ while (*bp != '\0')
+ putc(*bp++, tf);
+ }
+ break;
+ }
+ bp = buf;
+ }
+
+readerr:
+ if ((feof(fp) && smtpmode) || ferror(fp))
+ {
+ const char *errmsg = errstring(errno);
+
+ if (tTd(30, 1))
+ printf("collect: premature EOM: %s\n", errmsg);
+#ifdef LOG
+ if (LogLevel >= 2)
+ syslog(LOG_WARNING, "collect: premature EOM: %s", errmsg);
+#endif
+ inputerr = TRUE;
+ }
+
+ /* reset global timer */
+ clrevent(CollectTimeout);
+
+ if (headeronly)
+ return;
+
+ if (tf != NULL &&
+ (fflush(tf) != 0 || ferror(tf) || fsync(fileno(tf)) < 0 ||
+ fclose(tf) < 0))
+ {
+ tferror(tf, e);
+ flush_errors(TRUE);
+ finis();
+ }
+
+ /* An EOF when running SMTP is an error */
+ if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
+ {
+ char *host;
+ char *problem;
+
+ host = RealHostName;
+ if (host == NULL)
+ host = "localhost";
+
+ if (feof(fp))
+ problem = "unexpected close";
+ else if (ferror(fp))
+ problem = "I/O error";
+ else
+ problem = "read timeout";
+# ifdef LOG
+ if (LogLevel > 0 && feof(fp))
+ syslog(LOG_NOTICE,
+ "collect: %s on connection from %.100s, sender=%s: %s",
+ problem, host,
+ shortenstring(e->e_from.q_paddr, 203),
+ errstring(errno));
+# endif
+ if (feof(fp))
+ usrerr("451 collect: %s on connection from %s, from=%s",
+ problem, host,
+ shortenstring(e->e_from.q_paddr, 203));
+ else
+ syserr("451 collect: %s on connection from %s, from=%s",
+ problem, host,
+ shortenstring(e->e_from.q_paddr, 203));
+
+ /* don't return an error indication */
+ e->e_to = NULL;
+ e->e_flags &= ~EF_FATALERRS;
+ e->e_flags |= EF_CLRQUEUE;
+
+ /* and don't try to deliver the partial message either */
+ if (InChild)
+ ExitStat = EX_QUIT;
+ finis();
+ }
+
+ /*
+ ** Find out some information from the headers.
+ ** Examples are who is the from person & the date.
+ */
+
+ eatheader(e, !requeueflag);
+
+ if (GrabTo && e->e_sendqueue == NULL)
+ usrerr("No recipient addresses found in header");
+
+ /* collect statistics */
+ if (OpMode != MD_VERIFY)
+ {
+ extern void markstats();
+
+ markstats(e, (ADDRESS *) NULL);
+ }
+
+ /*
+ ** Add an Apparently-To: line if we have no recipient lines.
+ */
+
+ if (hvalue("to", e->e_header) != NULL ||
+ hvalue("cc", e->e_header) != NULL ||
+ hvalue("apparently-to", e->e_header) != NULL)
+ {
+ /* have a valid recipient header -- delete Bcc: headers */
+ e->e_flags |= EF_DELETE_BCC;
+ }
+ else if (hvalue("bcc", e->e_header) == NULL)
+ {
+ /* no valid recipient headers */
+ register ADDRESS *q;
+ char *hdr = NULL;
+ extern void addheader();
+
+ /* create an Apparently-To: field */
+ /* that or reject the message.... */
+ switch (NoRecipientAction)
+ {
+ case NRA_ADD_APPARENTLY_TO:
+ hdr = "Apparently-To";
+ break;
+
+ case NRA_ADD_TO:
+ hdr = "To";
+ break;
+
+ case NRA_ADD_BCC:
+ addheader("Bcc", "", &e->e_header);
+ break;
+
+ case NRA_ADD_TO_UNDISCLOSED:
+ addheader("To", "undisclosed-recipients:;", &e->e_header);
+ break;
+ }
+
+ if (hdr != NULL)
+ {
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (q->q_alias != NULL)
+ continue;
+ if (tTd(30, 3))
+ printf("Adding %s: %s\n",
+ hdr, q->q_paddr);
+ addheader(hdr, q->q_paddr, &e->e_header);
+ }
+ }
+ }
+
+ /* check for message too large */
+ if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
+ {
+ e->e_status = "5.2.3";
+ usrerr("552 Message exceeds maximum fixed size (%ld)",
+ MaxMessageSize);
+# ifdef LOG
+ if (LogLevel > 6)
+ syslog(LOG_NOTICE, "%s: message size (%ld) exceeds maximum (%ld)",
+ e->e_id, e->e_msgsize, MaxMessageSize);
+# endif
+ }
+
+ /* check for illegal 8-bit data */
+ if (HasEightBits)
+ {
+ e->e_flags |= EF_HAS8BIT;
+ if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode))
+ {
+ e->e_status = "5.6.1";
+ usrerr("554 Eight bit data not allowed");
+ }
+ }
+ else
+ {
+ /* if it claimed to be 8 bits, well, it lied.... */
+ if (e->e_bodytype != NULL &&
+ strcasecmp(e->e_bodytype, "8BITMIME") == 0)
+ e->e_bodytype = "7BIT";
+ }
+
+ if ((e->e_dfp = fopen(dfname, "r")) == NULL)
+ {
+ /* we haven't acked receipt yet, so just chuck this */
+ syserr("Cannot reopen %s", dfname);
+ finis();
+ }
+}
+
+
+static void
+collecttimeout(timeout)
+ time_t timeout;
+{
+ /* if no progress was made, die now */
+ if (!CollectProgress)
+ longjmp(CtxCollectTimeout, 1);
+
+ /* otherwise reset the timeout */
+ CollectTimeout = setevent(timeout, collecttimeout, timeout);
+ CollectProgress = FALSE;
+}
+ /*
+** TFERROR -- signal error on writing the temporary file.
+**
+** Parameters:
+** tf -- the file pointer for the temporary file.
+** e -- the current envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Gives an error message.
+** Arranges for following output to go elsewhere.
+*/
+
+void
+tferror(tf, e)
+ FILE *tf;
+ register ENVELOPE *e;
+{
+ setstat(EX_IOERR);
+ if (errno == ENOSPC)
+ {
+ struct stat st;
+ long avail;
+ long bsize;
+
+ e->e_flags |= EF_NO_BODY_RETN;
+ if (fstat(fileno(tf), &st) < 0)
+ st.st_size = 0;
+ (void) freopen(queuename(e, 'd'), "w", tf);
+ if (st.st_size <= 0)
+ fprintf(tf, "\n*** Mail could not be accepted");
+ else if (sizeof st.st_size > sizeof (long))
+ fprintf(tf, "\n*** Mail of at least %qd bytes could not be accepted\n",
+ st.st_size);
+ else
+ fprintf(tf, "\n*** Mail of at least %ld bytes could not be accepted\n",
+ st.st_size);
+ fprintf(tf, "*** at %s due to lack of disk space for temp file.\n",
+ MyHostName);
+ avail = freediskspace(QueueDir, &bsize);
+ if (avail > 0)
+ {
+ if (bsize > 1024)
+ avail *= bsize / 1024;
+ else if (bsize < 1024)
+ avail /= 1024 / bsize;
+ fprintf(tf, "*** Currently, %ld kilobytes are available for mail temp files.\n",
+ avail);
+ }
+ e->e_status = "4.3.1";
+ usrerr("452 Out of disk space for temp file");
+ }
+ else
+ syserr("collect: Cannot write tf%s", e->e_id);
+ (void) freopen("/dev/null", "w", tf);
+}
+ /*
+** EATFROM -- chew up a UNIX style from line and process
+**
+** This does indeed make some assumptions about the format
+** of UNIX messages.
+**
+** Parameters:
+** fm -- the from line.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** extracts what information it can from the header,
+** such as the date.
+*/
+
+# ifndef NOTUNIX
+
+char *DowList[] =
+{
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL
+};
+
+char *MonthList[] =
+{
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+ NULL
+};
+
+void
+eatfrom(fm, e)
+ char *fm;
+ register ENVELOPE *e;
+{
+ register char *p;
+ register char **dt;
+
+ if (tTd(30, 2))
+ printf("eatfrom(%s)\n", fm);
+
+ /* find the date part */
+ p = fm;
+ while (*p != '\0')
+ {
+ /* skip a word */
+ while (*p != '\0' && *p != ' ')
+ p++;
+ while (*p == ' ')
+ p++;
+ if (!(isascii(*p) && isupper(*p)) ||
+ p[3] != ' ' || p[13] != ':' || p[16] != ':')
+ continue;
+
+ /* we have a possible date */
+ for (dt = DowList; *dt != NULL; dt++)
+ if (strncmp(*dt, p, 3) == 0)
+ break;
+ if (*dt == NULL)
+ continue;
+
+ for (dt = MonthList; *dt != NULL; dt++)
+ if (strncmp(*dt, &p[4], 3) == 0)
+ break;
+ if (*dt != NULL)
+ break;
+ }
+
+ if (*p != '\0')
+ {
+ char *q;
+ extern char *arpadate();
+
+ /* we have found a date */
+ q = xalloc(25);
+ (void) strncpy(q, p, 25);
+ q[24] = '\0';
+ q = arpadate(q);
+ define('a', newstr(q), e);
+ }
+}
+
+# endif /* NOTUNIX */
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
new file mode 100644
index 000000000000..ab6db9310027
--- /dev/null
+++ b/usr.sbin/sendmail/src/conf.c
@@ -0,0 +1,3755 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)conf.c 8.243 (Berkeley) 11/20/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+# include "pathnames.h"
+# include <sys/ioctl.h>
+# include <sys/param.h>
+
+/*
+** CONF.C -- Sendmail Configuration Tables.
+**
+** Defines the configuration of this installation.
+**
+** Configuration Variables:
+** HdrInfo -- a table describing well-known header fields.
+** Each entry has the field name and some flags,
+** which are described in sendmail.h.
+**
+** Notes:
+** I have tried to put almost all the reasonable
+** configuration information into the configuration
+** file read at runtime. My intent is that anything
+** here is a function of the version of UNIX you
+** are running, or is really static -- for example
+** the headers are a superset of widely used
+** protocols. If you find yourself playing with
+** this file too much, you may be making a mistake!
+*/
+
+
+
+
+/*
+** Header info table
+** Final (null) entry contains the flags used for any other field.
+**
+** Not all of these are actually handled specially by sendmail
+** at this time. They are included as placeholders, to let
+** you know that "someday" I intend to have sendmail do
+** something with them.
+*/
+
+struct hdrinfo HdrInfo[] =
+{
+ /* originator fields, most to least significant */
+ "resent-sender", H_FROM|H_RESENT,
+ "resent-from", H_FROM|H_RESENT,
+ "resent-reply-to", H_FROM|H_RESENT,
+ "sender", H_FROM,
+ "from", H_FROM,
+ "reply-to", H_FROM,
+ "full-name", H_ACHECK,
+ "return-receipt-to", H_FROM|H_RECEIPTTO,
+ "errors-to", H_FROM|H_ERRORSTO,
+
+ /* destination fields */
+ "to", H_RCPT,
+ "resent-to", H_RCPT|H_RESENT,
+ "cc", H_RCPT,
+ "resent-cc", H_RCPT|H_RESENT,
+ "bcc", H_RCPT|H_BCC,
+ "resent-bcc", H_RCPT|H_BCC|H_RESENT,
+ "apparently-to", H_RCPT,
+
+ /* 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,
+
+ /* trace fields */
+ "received", H_TRACE|H_FORCE,
+ "x400-received", H_TRACE|H_FORCE,
+ "via", H_TRACE|H_FORCE,
+ "mail-from", H_TRACE|H_FORCE,
+
+ /* miscellaneous fields */
+ "comments", H_FORCE,
+ "return-path", H_FORCE|H_ACHECK,
+ "content-transfer-encoding", H_CTE,
+ "content-type", H_CTYPE,
+ "content-length", H_ACHECK,
+
+ NULL, 0,
+};
+
+
+
+/*
+** Location of system files/databases/etc.
+*/
+
+char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */
+
+
+
+/*
+** Privacy values
+*/
+
+struct prival PrivacyValues[] =
+{
+ "public", PRIV_PUBLIC,
+ "needmailhelo", PRIV_NEEDMAILHELO,
+ "needexpnhelo", PRIV_NEEDEXPNHELO,
+ "needvrfyhelo", PRIV_NEEDVRFYHELO,
+ "noexpn", PRIV_NOEXPN,
+ "novrfy", PRIV_NOVRFY,
+ "restrictmailq", PRIV_RESTRICTMAILQ,
+ "restrictqrun", PRIV_RESTRICTQRUN,
+ "authwarnings", PRIV_AUTHWARNINGS,
+ "noreceipts", PRIV_NORECEIPTS,
+ "goaway", PRIV_GOAWAY,
+ NULL, 0,
+};
+
+
+
+/*
+** Miscellaneous stuff.
+*/
+
+int DtableSize = 50; /* max open files; reset in 4.2bsd */
+ /*
+** SETDEFAULTS -- set default values
+**
+** Because of the way freezing is done, these must be initialized
+** using direct code.
+**
+** Parameters:
+** e -- the default envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Initializes a bunch of global variables to their
+** default values.
+*/
+
+#define MINUTES * 60
+#define HOURS * 60 MINUTES
+#define DAYS * 24 HOURS
+
+#ifndef MAXRULERECURSION
+# define MAXRULERECURSION 50 /* max ruleset recursion depth */
+#endif
+
+void
+setdefaults(e)
+ register ENVELOPE *e;
+{
+ int i;
+ extern void inittimeouts();
+ extern void setdefuser();
+ extern void setupmaps();
+ extern void setupmailers();
+
+ 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 = (RealUid != 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 */
+ SevenBitInput = FALSE; /* option 7 */
+ MaxMciCache = 1; /* option k */
+ MciCacheTimeout = 5 MINUTES; /* option K */
+ LogLevel = 9; /* option L */
+ inittimeouts(NULL); /* option r */
+ PrivacyFlags = 0; /* option p */
+#if MIME8TO7
+ MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */
+#else
+ MimeMode = MM_PASS8BIT;
+#endif
+ for (i = 0; i < MAXTOCLASS; i++)
+ {
+ TimeOuts.to_q_return[i] = 5 DAYS; /* option T */
+ TimeOuts.to_q_warning[i] = 0; /* option T */
+ }
+ ServiceSwitchFile = "/etc/service.switch";
+ HostsFile = _PATH_HOSTS;
+ MustQuoteChars = "@,;:\\()[].'";
+ MciInfoTimeout = 30 MINUTES;
+ MaxRuleRecursion = MAXRULERECURSION;
+ MaxAliasRecursion = 10;
+ ColonOkInAddr = TRUE;
+ setdefuser();
+ setupmaps();
+ setupmailers();
+}
+
+
+/*
+** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
+*/
+
+void
+setdefuser()
+{
+ struct passwd *defpwent;
+ static char defuserbuf[40];
+
+ DefUser = defuserbuf;
+ if ((defpwent = sm_getpwuid(DefUid)) != NULL)
+ strcpy(defuserbuf, defpwent->pw_name);
+ else
+ strcpy(defuserbuf, "nobody");
+}
+ /*
+** HOST_MAP_INIT -- initialize host class structures
+*/
+
+bool host_map_init __P((MAP *map, char *args));
+
+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;
+}
+ /*
+** SETUPMAILERS -- initialize default mailers
+*/
+
+void
+setupmailers()
+{
+ char buf[100];
+ extern void makemailer();
+
+ strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=DNS/RFC822/X-Unix, A=sh -c \201u");
+ makemailer(buf);
+
+ strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=DNS/RFC822/X-Unix, A=FILE");
+ makemailer(buf);
+
+ strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE");
+ makemailer(buf);
+}
+ /*
+** 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; \
+ }
+
+void
+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, null_map_close,
+ nis_map_lookup, null_map_store);
+#endif
+
+#ifdef NISPLUS
+ MAPDEF("nisplus", NULL, MCF_ALIASOK,
+ map_parseargs, nisplus_map_open, null_map_close,
+ nisplus_map_lookup, null_map_store);
+#endif
+
+#ifdef HESIOD
+ MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
+ map_parseargs, hes_map_open, null_map_close,
+ hes_map_lookup, null_map_store);
+#endif
+
+#if NETINFO
+ MAPDEF("netinfo", NULL, MCF_ALIASOK,
+ map_parseargs, ni_map_open, null_map_close,
+ ni_map_lookup, null_map_store);
+#endif
+
+#if 0
+ MAPDEF("dns", NULL, 0,
+ dns_map_init, null_map_open, null_map_close,
+ dns_map_lookup, null_map_store);
+#endif
+
+#if NAMED_BIND
+ /* best MX DNS lookup */
+ MAPDEF("bestmx", NULL, MCF_OPTFILE,
+ map_parseargs, null_map_open, null_map_close,
+ bestmx_map_lookup, null_map_store);
+#endif
+
+ MAPDEF("host", NULL, 0,
+ host_map_init, null_map_open, null_map_close,
+ host_map_lookup, null_map_store);
+
+ MAPDEF("text", NULL, MCF_ALIASOK,
+ map_parseargs, text_map_open, null_map_close,
+ text_map_lookup, null_map_store);
+
+ MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
+ map_parseargs, stab_map_open, null_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);
+
+ /* access to system passwd file */
+ MAPDEF("user", NULL, MCF_OPTFILE,
+ map_parseargs, user_map_open, null_map_close,
+ user_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 USERDB
+ /* user database */
+ MAPDEF("userdb", ".db", 0,
+ map_parseargs, null_map_open, null_map_close,
+ udb_map_lookup, null_map_store);
+#endif
+
+ /* arbitrary programs */
+ MAPDEF("program", NULL, MCF_ALIASOK,
+ map_parseargs, null_map_open, null_map_close,
+ prog_map_lookup, null_map_store);
+
+ /* sequenced maps */
+ MAPDEF("sequence", NULL, MCF_ALIASOK,
+ seq_map_parse, null_map_open, null_map_close,
+ seq_map_lookup, seq_map_store);
+
+ /* switched interface to sequenced maps */
+ MAPDEF("switch", NULL, MCF_ALIASOK,
+ map_parseargs, switch_map_open, null_map_close,
+ seq_map_lookup, seq_map_store);
+
+ /* null map lookup -- really for internal use only */
+ MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
+ map_parseargs, null_map_open, null_map_close,
+ null_map_lookup, null_map_store);
+}
+
+#undef MAPDEF
+ /*
+** INITHOSTMAPS -- initial host-dependent maps
+**
+** This should act as an interface to any local service switch
+** provided by the host operating system.
+**
+** Parameters:
+** none
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Should define maps "host" and "users" as necessary
+** for this OS. If they are not defined, they will get
+** a default value later. It should check to make sure
+** they are not defined first, since it's possible that
+** the config file has provided an override.
+*/
+
+void
+inithostmaps()
+{
+ register int i;
+ int nmaps;
+ char *maptype[MAXMAPSTACK];
+ short mapreturn[MAXMAPACTIONS];
+ char buf[MAXLINE];
+
+ /*
+ ** Set up default hosts maps.
+ */
+
+#if 0
+ nmaps = switch_map_find("hosts", maptype, mapreturn);
+ for (i = 0; i < nmaps; i++)
+ {
+ if (strcmp(maptype[i], "files") == 0 &&
+ stab("hosts.files", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts");
+ (void) makemapentry(buf);
+ }
+#if NAMED_BIND
+ else if (strcmp(maptype[i], "dns") == 0 &&
+ stab("hosts.dns", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "hosts.dns dns A");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef NISPLUS
+ else if (strcmp(maptype[i], "nisplus") == 0 &&
+ stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef NIS
+ else if (strcmp(maptype[i], "nis") == 0 &&
+ stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname");
+ (void) makemapentry(buf);
+ }
+#endif
+#if NETINFO
+ else if (strcmp(maptype[i], "netinfo") == 0) &&
+ stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "hosts.netinfo netinfo -v name /machines");
+ (void) makemapentry(buf);
+ }
+#endif
+ }
+#endif
+
+ /*
+ ** Make sure we have a host map.
+ */
+
+ if (stab("host", ST_MAP, ST_FIND) == NULL)
+ {
+ /* user didn't initialize: set up host map */
+ strcpy(buf, "host host");
+#if NAMED_BIND
+ if (ConfigLevel >= 2)
+ strcat(buf, " -a.");
+#endif
+ (void) makemapentry(buf);
+ }
+
+ /*
+ ** Set up default aliases maps
+ */
+
+ nmaps = switch_map_find("aliases", maptype, mapreturn);
+ for (i = 0; i < nmaps; i++)
+ {
+ if (strcmp(maptype[i], "files") == 0 &&
+ stab("aliases.files", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases.files null");
+ (void) makemapentry(buf);
+ }
+#ifdef NISPLUS
+ else if (strcmp(maptype[i], "nisplus") == 0 &&
+ stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef NIS
+ else if (strcmp(maptype[i], "nis") == 0 &&
+ stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases.nis nis -d mail.aliases");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef NETINFO
+ else if (strcmp(maptype[i], "netinfo") == 0 &&
+ stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases.netinfo netinfo /aliases");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef HESIOD
+ else if (strcmp(maptype[i], "hesiod") == 0 &&
+ stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases.hesiod hesiod aliases");
+ (void) makemapentry(buf);
+ }
+#endif
+ }
+ if (stab("aliases", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "aliases switch aliases");
+ (void) makemapentry(buf);
+ }
+
+#if 0 /* "user" map class is a better choice */
+ /*
+ ** Set up default users maps.
+ */
+
+ nmaps = switch_map_find("passwd", maptype, mapreturn);
+ for (i = 0; i < nmaps; i++)
+ {
+ if (strcmp(maptype[i], "files") == 0 &&
+ stab("users.files", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd");
+ (void) makemapentry(buf);
+ }
+#ifdef NISPLUS
+ else if (strcmp(maptype[i], "nisplus") == 0 &&
+ stab("users.nisplus", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef NIS
+ else if (strcmp(maptype[i], "nis") == 0 &&
+ stab("users.nis", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "users.nis nis -m -d passwd.byname");
+ (void) makemapentry(buf);
+ }
+#endif
+#ifdef HESIOD
+ else if (strcmp(maptype[i], "hesiod") == 0) &&
+ stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "users.hesiod hesiod");
+ (void) makemapentry(buf);
+ }
+#endif
+ }
+ if (stab("users", ST_MAP, ST_FIND) == NULL)
+ {
+ strcpy(buf, "users switch -m passwd");
+ (void) makemapentry(buf);
+ }
+#endif
+}
+ /*
+** SWITCH_MAP_FIND -- find the list of types associated with a map
+**
+** This is the system-dependent interface to the service switch.
+**
+** Parameters:
+** service -- the name of the service of interest.
+** maptype -- an out-array of strings containing the types
+** of access to use for this service. There can
+** be at most MAXMAPSTACK types for a single service.
+** mapreturn -- an out-array of return information bitmaps
+** for the map.
+**
+** Returns:
+** The number of map types filled in, or -1 for failure.
+*/
+
+#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
+# define _USE_SUN_NSSWITCH_
+#endif
+
+#ifdef _USE_SUN_NSSWITCH_
+# include <nsswitch.h>
+#endif
+
+#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
+# define _USE_DEC_SVC_CONF_
+#endif
+
+#ifdef _USE_DEC_SVC_CONF_
+# include <sys/svcinfo.h>
+#endif
+
+int
+switch_map_find(service, maptype, mapreturn)
+ char *service;
+ char *maptype[MAXMAPSTACK];
+ short mapreturn[MAXMAPACTIONS];
+{
+ register FILE *fp;
+ int svcno;
+ static char buf[MAXLINE];
+
+#ifdef _USE_SUN_NSSWITCH_
+ struct __nsw_switchconfig *nsw_conf;
+ enum __nsw_parse_err pserr;
+ struct __nsw_lookup *lk;
+ int nsw_rc;
+ static struct __nsw_lookup lkp0 =
+ { "files", {1, 0, 0, 0}, NULL, NULL };
+ static struct __nsw_switchconfig lkp_default =
+ { 0, "sendmail", 3, &lkp0 };
+
+ for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
+ mapreturn[svcno] = 0;
+
+ if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
+ lk = lkp_default.lookups;
+ else
+ lk = nsw_conf->lookups;
+ svcno = 0;
+ while (lk != NULL)
+ {
+ maptype[svcno] = lk->service_name;
+ if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
+ mapreturn[MA_NOTFOUND] |= 1 << svcno;
+ if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
+ mapreturn[MA_TRYAGAIN] |= 1 << svcno;
+ if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
+ mapreturn[MA_TRYAGAIN] |= 1 << svcno;
+ svcno++;
+ lk = lk->next;
+ }
+ return svcno;
+#endif
+
+#ifdef _USE_DEC_SVC_CONF_
+ struct svcinfo *svcinfo;
+ int svc;
+
+ for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
+ mapreturn[svcno] = 0;
+
+ svcinfo = getsvc();
+ if (svcinfo == NULL)
+ goto punt;
+ if (strcmp(service, "hosts") == 0)
+ svc = SVC_HOSTS;
+ else if (strcmp(service, "aliases") == 0)
+ svc = SVC_ALIASES;
+ else if (strcmp(service, "passwd") == 0)
+ svc = SVC_PASSWD;
+ else
+ return -1;
+ for (svcno = 0; svcno < SVC_PATHSIZE; svcno++)
+ {
+ switch (svcinfo->svcpath[svc][svcno])
+ {
+ case SVC_LOCAL:
+ maptype[svcno] = "files";
+ break;
+
+ case SVC_YP:
+ maptype[svcno] = "nis";
+ break;
+
+ case SVC_BIND:
+ maptype[svcno] = "dns";
+ break;
+
+#ifdef SVC_HESIOD
+ case SVC_HESIOD:
+ maptype[svcno] = "hesiod";
+ break;
+#endif
+
+ case SVC_LAST:
+ return svcno;
+ }
+ }
+ return svcno;
+#endif
+
+#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
+ /*
+ ** Fall-back mechanism.
+ */
+
+ for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
+ mapreturn[svcno] = 0;
+
+ svcno = 0;
+ fp = fopen(ServiceSwitchFile, "r");
+ if (fp != NULL)
+ {
+ while (fgets(buf, sizeof buf, fp) != NULL)
+ {
+ register char *p;
+
+ p = strpbrk(buf, "#\n");
+ if (p != NULL)
+ *p = '\0';
+ p = strpbrk(buf, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ if (strcmp(buf, service) != 0)
+ continue;
+
+ /* got the right service -- extract data */
+ do
+ {
+ while (isspace(*p))
+ p++;
+ if (*p == '\0')
+ break;
+ maptype[svcno++] = p;
+ p = strpbrk(p, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ } while (p != NULL);
+ fclose(fp);
+ return svcno;
+ }
+
+ /* service was not found -- use compiled in default */
+ fclose(fp);
+ }
+#endif
+
+ /* if the service file doesn't work, use an absolute fallback */
+ punt:
+ for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
+ mapreturn[svcno] = 0;
+ svcno = 0;
+ if (strcmp(service, "aliases") == 0)
+ {
+ maptype[svcno++] = "files";
+#ifdef AUTO_NIS_ALIASES
+# ifdef NISPLUS
+ maptype[svcno++] = "nisplus";
+# endif
+# ifdef NIS
+ maptype[svcno++] = "nis";
+# endif
+#endif
+ return svcno;
+ }
+ if (strcmp(service, "hosts") == 0)
+ {
+# if NAMED_BIND
+ maptype[svcno++] = "dns";
+# else
+# if defined(sun) && !defined(BSD) && !defined(_USE_SUN_NSSWITCH_)
+ /* SunOS */
+ maptype[svcno++] = "nis";
+# endif
+# endif
+ maptype[svcno++] = "files";
+ return svcno;
+ }
+ return -1;
+}
+ /*
+** USERNAME -- return the user id of the logged in user.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** The login name of the logged in user.
+**
+** Side Effects:
+** none.
+**
+** Notes:
+** The return value is statically allocated.
+*/
+
+char *
+username()
+{
+ static char *myname = NULL;
+ extern char *getlogin();
+ register struct passwd *pw;
+
+ /* cache the result */
+ if (myname == NULL)
+ {
+ myname = getlogin();
+ if (myname == NULL || myname[0] == '\0')
+ {
+ pw = sm_getpwuid(RealUid);
+ if (pw != NULL)
+ myname = newstr(pw->pw_name);
+ }
+ else
+ {
+ uid_t uid = RealUid;
+
+ myname = newstr(myname);
+ if ((pw = sm_getpwnam(myname)) == NULL ||
+ (uid != 0 && uid != pw->pw_uid))
+ {
+ pw = sm_getpwuid(uid);
+ if (pw != NULL)
+ myname = newstr(pw->pw_name);
+ }
+ }
+ if (myname == NULL || myname[0] == '\0')
+ {
+ syserr("554 Who are you?");
+ myname = "postmaster";
+ }
+ }
+
+ return (myname);
+}
+ /*
+** TTYPATH -- Get the path of the user's tty
+**
+** Returns the pathname of the user's tty. Returns NULL if
+** the user is not logged in or if s/he has write permission
+** denied.
+**
+** Parameters:
+** none
+**
+** Returns:
+** pathname of the user's tty.
+** NULL if not logged in or write permission denied.
+**
+** Side Effects:
+** none.
+**
+** WARNING:
+** Return value is in a local buffer.
+**
+** Called By:
+** savemail
+*/
+
+char *
+ttypath()
+{
+ struct stat stbuf;
+ register char *pathn;
+ extern char *ttyname();
+ extern char *getlogin();
+
+ /* compute the pathname of the controlling tty */
+ if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
+ (pathn = ttyname(0)) == NULL)
+ {
+ errno = 0;
+ return (NULL);
+ }
+
+ /* see if we have write permission */
+ if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
+ {
+ errno = 0;
+ return (NULL);
+ }
+
+ /* see if the user is logged in */
+ if (getlogin() == NULL)
+ return (NULL);
+
+ /* looks good */
+ return (pathn);
+}
+ /*
+** CHECKCOMPAT -- check for From and To person compatible.
+**
+** This routine can be supplied on a per-installation basis
+** to determine whether a person is allowed to send a message.
+** This allows restriction of certain types of internet
+** forwarding or registration of users.
+**
+** If the hosts are found to be incompatible, an error
+** message should be given using "usrerr" and an EX_ code
+** should be returned. You can also set to->q_status to
+** a DSN-style status code.
+**
+** EF_NO_BODY_RETN can be set in e->e_flags to suppress the
+** body during the return-to-sender function; this should be done
+** on huge messages. This bit may already be set by the ESMTP
+** protocol.
+**
+** Parameters:
+** to -- the person being sent to.
+**
+** Returns:
+** an exit status
+**
+** Side Effects:
+** none (unless you include the usrerr stuff)
+*/
+
+int
+checkcompat(to, e)
+ register ADDRESS *to;
+ register ENVELOPE *e;
+{
+# ifdef lint
+ if (to == NULL)
+ to++;
+# endif /* lint */
+
+ if (tTd(49, 1))
+ printf("checkcompat(to=%s, from=%s)\n",
+ to->q_paddr, e->e_from.q_paddr);
+
+# ifdef EXAMPLE_CODE
+ /* this code is intended as an example only */
+ register STAB *s;
+
+ s = stab("arpa", ST_MAILER, ST_FIND);
+ if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
+ to->q_mailer == s->s_mailer)
+ {
+ usrerr("553 No ARPA mail through this machine: see your system administration");
+ /* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */
+ to->q_status = "5.7.1";
+ return (EX_UNAVAILABLE);
+ }
+# endif /* EXAMPLE_CODE */
+ return (EX_OK);
+}
+ /*
+** SETSIGNAL -- set a signal handler
+**
+** This is essentially old BSD "signal(3)".
+*/
+
+sigfunc_t
+setsignal(sig, handler)
+ int sig;
+ sigfunc_t handler;
+{
+#if defined(SYS5SIGNALS) || defined(BSD4_3)
+ return signal(sig, handler);
+#else
+ struct sigaction n, o;
+
+ bzero(&n, sizeof n);
+ n.sa_handler = handler;
+# ifdef SA_RESTART
+ n.sa_flags = SA_RESTART;
+# endif
+ if (sigaction(sig, &n, &o) < 0)
+ return SIG_ERR;
+ return o.sa_handler;
+#endif
+}
+ /*
+** RELEASESIGNAL -- release a held signal
+**
+** Parameters:
+** sig -- the signal to release.
+**
+** Returns:
+** 0 on success.
+** -1 on failure.
+*/
+
+int
+releasesignal(sig)
+ int sig;
+{
+#ifdef BSD4_3
+ return sigsetmask(sigblock(0) & ~(1 << sig));
+#else
+ sigset_t sset;
+
+ sigemptyset(&sset);
+ sigaddset(&sset, sig);
+ return sigprocmask(SIG_UNBLOCK, &sset, NULL);
+#endif
+}
+ /*
+** HOLDSIGS -- arrange to hold all signals
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Arranges that signals are held.
+*/
+
+void
+holdsigs()
+{
+}
+ /*
+** RLSESIGS -- arrange to release all signals
+**
+** This undoes the effect of holdsigs.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Arranges that signals are released.
+*/
+
+void
+rlsesigs()
+{
+}
+ /*
+** INIT_MD -- do machine dependent initializations
+**
+** Systems that have global modes that should be set should do
+** them here rather than in main.
+*/
+
+#ifdef _AUX_SOURCE
+# include <compat.h>
+#endif
+
+void
+init_md(argc, argv)
+ int argc;
+ char **argv;
+{
+#ifdef _AUX_SOURCE
+ setcompat(getcompat() | COMPAT_BSDPROT);
+#endif
+
+#ifdef VENDOR_DEFAULT
+ VendorCode = VENDOR_DEFAULT;
+#else
+ VendorCode = VENDOR_BERKELEY;
+#endif
+}
+ /*
+** INIT_VENDOR_MACROS -- vendor-dependent macro initializations
+**
+** Called once, on startup.
+**
+** Parameters:
+** e -- the global envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** vendor-dependent.
+*/
+
+void
+init_vendor_macros(e)
+ register ENVELOPE *e;
+{
+}
+ /*
+** GETLA -- get the current load average
+**
+** This code stolen from la.c.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** The current load average as an integer.
+**
+** Side Effects:
+** none.
+*/
+
+/* 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 long */
+#define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */
+#define LA_SUBR 4 /* call getloadavg */
+#define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
+#define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
+#define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
+#define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */
+#define LA_DGUX 9 /* special DGUX implementation */
+#define LA_HPUX 10 /* special HPUX implementation */
+
+/* do guesses based on general OS type */
+#ifndef LA_TYPE
+# define LA_TYPE LA_ZERO
+#endif
+
+#ifndef FSHIFT
+# if defined(unixpc)
+# define FSHIFT 5
+# endif
+
+# if defined(__alpha) || defined(IRIX)
+# define FSHIFT 10
+# endif
+
+# if defined(_AIX3)
+# define FSHIFT 16
+# endif
+#endif
+
+#ifndef FSHIFT
+# define FSHIFT 8
+#endif
+
+#ifndef FSCALE
+# define FSCALE (1 << FSHIFT)
+#endif
+
+#ifndef LA_AVENRUN
+# ifdef SYSTEM5
+# define LA_AVENRUN "avenrun"
+# else
+# define LA_AVENRUN "_avenrun"
+# endif
+#endif
+
+/* _PATH_KMEM should be defined in <paths.h> */
+#ifndef _PATH_KMEM
+# define _PATH_KMEM "/dev/kmem"
+#endif
+
+#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT)
+
+#include <nlist.h>
+
+#ifdef IRIX64
+# define nlist nlist64
+#endif
+
+/* _PATH_UNIX should be defined in <paths.h> */
+#ifndef _PATH_UNIX
+# if defined(SYSTEM5)
+# define _PATH_UNIX "/unix"
+# else
+# define _PATH_UNIX "/vmunix"
+# endif
+#endif
+
+#ifdef _AUX_SOURCE
+struct nlist Nl[2];
+#else
+struct nlist Nl[] =
+{
+ { LA_AVENRUN },
+ { 0 },
+};
+#endif
+#define X_AVENRUN 0
+
+getla()
+{
+ static int kmem = -1;
+#if LA_TYPE == LA_INT
+ long avenrun[3];
+#else
+# if LA_TYPE == LA_SHORT
+ short avenrun[3];
+# else
+ double avenrun[3];
+# endif
+#endif
+ extern int errno;
+ extern off_t lseek();
+
+ if (kmem < 0)
+ {
+ kmem = open(_PATH_KMEM, 0, 0);
+ if (kmem < 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: open(/dev/kmem): %s\n",
+ errstring(errno));
+ return (-1);
+ }
+ (void) fcntl(kmem, F_SETFD, 1);
+
+#ifdef _AUX_SOURCE
+ strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN);
+ Nl[1].n_name[0] = '\0';
+#endif
+
+#ifdef _AIX3
+ if (knlist(Nl, 1, sizeof Nl[0]) < 0)
+#else
+ if (nlist(_PATH_UNIX, Nl) < 0)
+#endif
+ {
+ if (tTd(3, 1))
+ printf("getla: nlist(%s): %s\n", _PATH_UNIX,
+ errstring(errno));
+ 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);
+ }
+#ifdef NAMELISTMASK
+ Nl[X_AVENRUN].n_value &= NAMELISTMASK;
+#endif
+ }
+ 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, SEEK_SET) == -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);
+ }
+# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
+ 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);
+# else /* LA_TYPE == LA_FLOAT */
+ 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
+}
+
+#endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */
+
+#if LA_TYPE == LA_READKSYM
+
+# include <sys/ksym.h>
+
+getla()
+{
+ static int kmem = -1;
+ long avenrun[3];
+ extern int errno;
+ struct mioc_rksym mirk;
+
+ 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);
+ }
+ (void) fcntl(kmem, F_SETFD, 1);
+ }
+ mirk.mirk_symname = LA_AVENRUN;
+ mirk.mirk_buf = avenrun;
+ mirk.mirk_buflen = sizeof(avenrun);
+ if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
+ errstring(errno));
+ return -1;
+ }
+ 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);
+}
+
+#endif /* LA_TYPE == LA_READKSYM */
+
+#if LA_TYPE == LA_DGUX
+
+# include <sys/dg_sys_info.h>
+
+int
+getla()
+{
+ struct dg_sys_info_load_info load_info;
+
+ dg_sys_info((long *)&load_info,
+ DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
+
+ if (tTd(3, 1))
+ printf("getla: %d\n", (int) (load_info.one_minute + 0.5));
+
+ return((int) (load_info.one_minute + 0.5));
+}
+
+#endif /* LA_TYPE == LA_DGUX */
+
+#if LA_TYPE == LA_HPUX
+
+/* forward declarations to keep gcc from complaining */
+struct pst_dynamic;
+struct pst_status;
+struct pst_static;
+struct pst_vminfo;
+struct pst_diskinfo;
+struct pst_processor;
+struct pst_lv;
+struct pst_swapinfo;
+
+# include <sys/param.h>
+# include <sys/pstat.h>
+
+int
+getla()
+{
+ struct pst_dynamic pstd;
+
+ if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
+ (size_t) 1, 0) == -1)
+ return 0;
+
+ if (tTd(3, 1))
+ printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
+
+ return (int) (pstd.psd_avg_1_min + 0.5);
+}
+
+#endif /* LA_TYPE == LA_HPUX */
+
+#if LA_TYPE == LA_SUBR
+
+int
+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));
+}
+
+#endif /* LA_TYPE == LA_SUBR */
+
+#if LA_TYPE == LA_MACH
+
+/*
+** This has been tested on NEXTSTEP release 2.1/3.X.
+*/
+
+#if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
+# include <mach/mach.h>
+#else
+# include <mach.h>
+#endif
+
+getla()
+{
+ processor_set_t default_set;
+ kern_return_t error;
+ unsigned int info_count;
+ struct processor_set_basic_info info;
+ host_t host;
+
+ error = processor_set_default(host_self(), &default_set);
+ if (error != KERN_SUCCESS)
+ return -1;
+ info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
+ if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
+ &host, (processor_set_info_t)&info,
+ &info_count) != KERN_SUCCESS)
+ {
+ return -1;
+ }
+ return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
+}
+
+#endif /* LA_TYPE == LA_MACH */
+
+#if LA_TYPE == LA_PROCSTR
+
+/*
+** Read /proc/loadavg for the load average. This is assumed to be
+** in a format like "0.15 0.12 0.06".
+**
+** Initially intended for Linux. This has been in the kernel
+** since at least 0.99.15.
+*/
+
+# ifndef _PATH_LOADAVG
+# define _PATH_LOADAVG "/proc/loadavg"
+# endif
+
+int
+getla()
+{
+ double avenrun;
+ register int result;
+ FILE *fp;
+
+ fp = fopen(_PATH_LOADAVG, "r");
+ if (fp == NULL)
+ {
+ if (tTd(3, 1))
+ printf("getla: fopen(%s): %s\n",
+ _PATH_LOADAVG, errstring(errno));
+ return -1;
+ }
+ result = fscanf(fp, "%lf", &avenrun);
+ fclose(fp);
+ if (result != 1)
+ {
+ if (tTd(3, 1))
+ printf("getla: fscanf() = %d: %s\n",
+ result, errstring(errno));
+ return -1;
+ }
+
+ if (tTd(3, 1))
+ printf("getla(): %.2f\n", avenrun);
+
+ return ((int) (avenrun + 0.5));
+}
+
+#endif /* LA_TYPE == LA_PROCSTR */
+
+#if LA_TYPE == LA_ZERO
+
+getla()
+{
+ if (tTd(3, 1))
+ printf("getla: ZERO\n");
+ return (0);
+}
+
+#endif /* LA_TYPE == LA_ZERO */
+
+
+/*
+ * Copyright 1989 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Many and varied...
+ */
+
+/* Non Apollo stuff removed by Don Lewis 11/15/93 */
+#ifndef lint
+static char rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
+#endif /* !lint */
+
+#ifdef apollo
+# undef volatile
+# include <apollo/base.h>
+
+/* ARGSUSED */
+int getloadavg( call_data )
+ caddr_t call_data; /* pointer to (double) return value */
+{
+ double *avenrun = (double *) call_data;
+ int i;
+ status_$t st;
+ long loadav[3];
+ proc1_$get_loadav(loadav, &st);
+ *avenrun = loadav[0] / (double) (1 << 16);
+ return(0);
+}
+# endif /* apollo */
+ /*
+** SHOULDQUEUE -- should this message be queued or sent?
+**
+** Compares the message cost to the load average to decide.
+**
+** 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
+** time being.
+** FALSE -- if the load is low enough to send this message.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+shouldqueue(pri, ctime)
+ long pri;
+ time_t ctime;
+{
+ bool rval;
+
+ if (tTd(3, 30))
+ printf("shouldqueue: CurrentLA=%d, pri=%d: ", CurrentLA, pri);
+ if (CurrentLA < QueueLA)
+ {
+ if (tTd(3, 30))
+ printf("FALSE (CurrentLA < QueueLA)\n");
+ return (FALSE);
+ }
+#if 0 /* this code is reported to cause oscillation around RefuseLA */
+ if (CurrentLA >= RefuseLA && QueueLA < RefuseLA)
+ {
+ if (tTd(3, 30))
+ printf("TRUE (CurrentLA >= RefuseLA)\n");
+ return (TRUE);
+ }
+#endif
+ rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
+ if (tTd(3, 30))
+ printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE");
+ return rval;
+}
+ /*
+** 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:
+** Sets process title when it is rejecting connections.
+*/
+
+bool
+refuseconnections()
+{
+ extern bool enoughdiskspace();
+ extern void setproctitle __P((const char *, ...));
+
+#ifdef XLA
+ if (!xla_smtp_ok())
+ return TRUE;
+#endif
+
+ if (CurrentLA >= RefuseLA)
+ {
+ setproctitle("rejecting connections: load average: %d",
+ CurrentLA);
+ }
+ else if (!enoughdiskspace(MinBlocksFree + 1))
+ {
+ setproctitle("rejecting connections: min free: %d",
+ MinBlocksFree);
+ }
+ else if (MaxChildren > 0 && CurChildren >= MaxChildren)
+ {
+ setproctitle("rejecting connections: maximum children: %d",
+ CurChildren);
+ }
+ else
+ return FALSE;
+ return TRUE;
+}
+ /*
+** SETPROCTITLE -- set process title for ps
+**
+** Parameters:
+** fmt -- a printf style format string.
+** a, b, c -- possible parameters to fmt.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Clobbers argv of our main procedure so ps(1) will
+** display the title.
+*/
+
+#define SPT_NONE 0 /* don't use it at all */
+#define SPT_REUSEARGV 1 /* cover argv with title information */
+#define SPT_BUILTIN 2 /* use libc builtin */
+#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
+#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
+#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
+#define SPT_SCO 6 /* write kernel u. area */
+
+#ifndef SPT_TYPE
+# define SPT_TYPE SPT_REUSEARGV
+#endif
+
+#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
+
+# if SPT_TYPE == SPT_PSTAT
+# include <sys/pstat.h>
+# endif
+# if SPT_TYPE == SPT_PSSTRINGS
+# include <machine/vmparam.h>
+# include <sys/exec.h>
+# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */
+# undef SPT_TYPE
+# define SPT_TYPE SPT_REUSEARGV
+# else
+# ifndef NKPDE /* FreeBSD 2.0 */
+# define NKPDE 63
+typedef unsigned int *pt_entry_t;
+# endif
+# endif
+# endif
+
+# if SPT_TYPE == SPT_PSSTRINGS
+# define SETPROC_STATIC static
+# else
+# define SETPROC_STATIC
+# endif
+
+# if SPT_TYPE == SPT_SYSMIPS
+# include <sys/sysmips.h>
+# include <sys/sysnews.h>
+# endif
+
+# if SPT_TYPE == SPT_SCO
+# include <sys/immu.h>
+# include <sys/dir.h>
+# include <sys/user.h>
+# include <sys/fs/s5param.h>
+# if PSARGSZ > MAXLINE
+# define SPT_BUFSIZE PSARGSZ
+# endif
+# endif
+
+# ifndef SPT_PADCHAR
+# define SPT_PADCHAR ' '
+# endif
+
+# ifndef SPT_BUFSIZE
+# define SPT_BUFSIZE MAXLINE
+# endif
+
+#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
+
+/*
+** Pointers for setproctitle.
+** This allows "ps" listings to give more useful information.
+*/
+
+char **Argv = NULL; /* pointer to argument vector */
+char *LastArgv = NULL; /* end of argv */
+
+void
+initsetproctitle(argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ register int i;
+ extern char **environ;
+
+ /*
+ ** Move the environment so setproctitle can use the space at
+ ** the top of memory.
+ */
+
+ for (i = 0; envp[i] != NULL; i++)
+ continue;
+ environ = (char **) xalloc(sizeof (char *) * (i + 1));
+ for (i = 0; envp[i] != NULL; i++)
+ environ[i] = newstr(envp[i]);
+ environ[i] = NULL;
+
+ /*
+ ** Save start and extent of argv for setproctitle.
+ */
+
+ Argv = argv;
+ if (i > 0)
+ LastArgv = envp[i - 1] + strlen(envp[i - 1]);
+ else
+ LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
+}
+
+#if SPT_TYPE != SPT_BUILTIN
+
+
+/*VARARGS1*/
+void
+# ifdef __STDC__
+setproctitle(const char *fmt, ...)
+# else
+setproctitle(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+# endif
+{
+# if SPT_TYPE != SPT_NONE
+ register char *p;
+ register int i;
+ SETPROC_STATIC char buf[SPT_BUFSIZE];
+ VA_LOCAL_DECL
+# if SPT_TYPE == SPT_PSTAT
+ union pstun pst;
+# endif
+# if SPT_TYPE == SPT_SCO
+ off_t seek_off;
+ static int kmem = -1;
+ static int kmempid = -1;
+ struct user u;
+# endif
+
+ p = buf;
+
+ /* print sendmail: heading for grep */
+ (void) strcpy(p, "sendmail: ");
+ p += strlen(p);
+
+ /* print the argument string */
+ VA_START(fmt);
+ (void) vsnprintf(p, sizeof buf - (p - buf), fmt, ap);
+ VA_END;
+
+ i = strlen(buf);
+
+# if SPT_TYPE == SPT_PSTAT
+ pst.pst_command = buf;
+ pstat(PSTAT_SETCMD, pst, i, 0, 0);
+# endif
+# if SPT_TYPE == SPT_PSSTRINGS
+ PS_STRINGS->ps_nargvstr = 1;
+ PS_STRINGS->ps_argvstr = buf;
+# endif
+# if SPT_TYPE == SPT_SYSMIPS
+ sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
+# endif
+# if SPT_TYPE == SPT_SCO
+ if (kmem < 0 || kmempid != getpid())
+ {
+ if (kmem >= 0)
+ close(kmem);
+ kmem = open(_PATH_KMEM, O_RDWR, 0);
+ if (kmem < 0)
+ return;
+ (void) fcntl(kmem, F_SETFD, 1);
+ kmempid = getpid();
+ }
+ buf[PSARGSZ - 1] = '\0';
+ seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
+ if (lseek(kmem, (char *) seek_off, SEEK_SET) == seek_off)
+ (void) write(kmem, buf, PSARGSZ);
+# endif
+# if SPT_TYPE == SPT_REUSEARGV
+ if (i > LastArgv - Argv[0] - 2)
+ {
+ i = LastArgv - Argv[0] - 2;
+ buf[i] = '\0';
+ }
+ (void) strcpy(Argv[0], buf);
+ p = &Argv[0][i];
+ while (p < LastArgv)
+ *p++ = SPT_PADCHAR;
+ Argv[1] = NULL;
+# endif
+# endif /* SPT_TYPE != SPT_NONE */
+}
+
+#endif /* SPT_TYPE != SPT_BUILTIN */
+ /*
+** REAPCHILD -- pick up the body of my child, lest it become a zombie
+**
+** Parameters:
+** sig -- the signal that got us here (unused).
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Picks up extant zombies.
+*/
+
+void
+reapchild(sig)
+ int sig;
+{
+ int olderrno = errno;
+# ifdef HASWAITPID
+ auto int status;
+ int count;
+ int pid;
+
+ count = 0;
+ while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+ {
+ if (count++ > 1000)
+ {
+#ifdef LOG
+ syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x",
+ pid, status);
+#endif
+ break;
+ }
+ CurChildren--;
+ }
+# else
+# ifdef WNOHANG
+ union wait status;
+
+ while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
+ CurChildren--;
+# else /* WNOHANG */
+ auto int status;
+
+ while (wait(&status) > 0)
+ CurChildren--;
+# endif /* WNOHANG */
+# endif
+# ifdef SYS5SIGNALS
+ (void) setsignal(SIGCHLD, reapchild);
+# endif
+ errno = olderrno;
+}
+ /*
+** PUTENV -- emulation of putenv() in terms of setenv()
+**
+** Not needed on Posix-compliant systems.
+** This doesn't have full Posix semantics, but it's good enough
+** for sendmail.
+**
+** Parameter:
+** env -- the environment to put.
+**
+** Returns:
+** none.
+*/
+
+#ifdef NEEDPUTENV
+
+# if NEEDPUTENV == 2 /* no setenv(3) call available */
+
+int
+putenv(str)
+ char *str;
+{
+ char **current;
+ int matchlen, envlen=0;
+ char *tmp;
+ char **newenv;
+ static int first=1;
+ extern char **environ;
+
+ /*
+ * find out how much of str to match when searching
+ * for a string to replace.
+ */
+ if ((tmp = index(str, '=')) == NULL || tmp == str)
+ matchlen = strlen(str);
+ else
+ matchlen = (int) (tmp - str);
+ ++matchlen;
+
+ /*
+ * Search for an existing string in the environment and find the
+ * length of environ. If found, replace and exit.
+ */
+ for (current=environ; *current; current++) {
+ ++envlen;
+
+ if (strncmp(str, *current, matchlen) == 0) {
+ /* found it, now insert the new version */
+ *current = (char *)str;
+ return(0);
+ }
+ }
+
+ /*
+ * There wasn't already a slot so add space for a new slot.
+ * If this is our first time through, use malloc(), else realloc().
+ */
+ if (first) {
+ newenv = (char **) malloc(sizeof(char *) * (envlen + 2));
+ if (newenv == NULL)
+ return(-1);
+
+ first=0;
+ (void) memcpy(newenv, environ, sizeof(char *) * envlen);
+ } else {
+ newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2));
+ if (newenv == NULL)
+ return(-1);
+ }
+
+ /* actually add in the new entry */
+ environ = newenv;
+ environ[envlen] = (char *)str;
+ environ[envlen+1] = NULL;
+
+ return(0);
+}
+
+#else /* implement putenv() in terms of setenv() */
+
+int
+putenv(env)
+ char *env;
+{
+ char *p;
+ int l;
+ char nbuf[100];
+
+ p = strchr(env, '=');
+ if (p == NULL)
+ return 0;
+ l = p - env;
+ if (l > sizeof nbuf - 1)
+ l = sizeof nbuf - 1;
+ bcopy(env, nbuf, l);
+ nbuf[l] = '\0';
+ return setenv(nbuf, ++p, 1);
+}
+
+# endif
+#endif
+ /*
+** 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.
+*/
+
+#ifndef HASUNSETENV
+
+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
+ /*
+** GETDTABLESIZE -- return number of file descriptors
+**
+** Only on non-BSD systems
+**
+** Parameters:
+** none
+**
+** Returns:
+** size of file descriptor table
+**
+** Side Effects:
+** none
+*/
+
+#ifdef SOLARIS
+# include <sys/resource.h>
+#endif
+
+int
+getdtsize()
+{
+#ifdef RLIMIT_NOFILE
+ struct rlimit rl;
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
+ return rl.rlim_cur;
+#endif
+
+# ifdef HASGETDTABLESIZE
+ return getdtablesize();
+# else
+# ifdef _SC_OPEN_MAX
+ return sysconf(_SC_OPEN_MAX);
+# else
+ return NOFILE;
+# endif
+# endif
+}
+ /*
+** 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 */
+ /*
+** INITGROUPS -- initialize groups
+**
+** Stub implementation for System V style systems
+*/
+
+#ifndef HASINITGROUPS
+
+initgroups(name, basegid)
+ char *name;
+ int basegid;
+{
+ return 0;
+}
+
+#endif
+ /*
+** SETSID -- set session id (for non-POSIX systems)
+*/
+
+#ifndef HASSETSID
+
+pid_t
+setsid __P ((void))
+{
+#ifdef TIOCNOTTY
+ int fd;
+
+ fd = open("/dev/tty", O_RDWR, 0);
+ if (fd >= 0)
+ {
+ (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
+ (void) close(fd);
+ }
+#endif /* TIOCNOTTY */
+# ifdef SYS5SETPGRP
+ return setpgrp();
+# else
+ return setpgid(0, getpid());
+# endif
+}
+
+#endif
+ /*
+** FSYNC -- dummy fsync
+*/
+
+#ifdef NEEDFSYNC
+
+fsync(fd)
+ int fd;
+{
+# ifdef O_SYNC
+ return fcntl(fd, F_SETFL, O_SYNC);
+# else
+ /* nothing we can do */
+ return 0;
+# endif
+}
+
+#endif
+ /*
+** DGUX_INET_ADDR -- inet_addr for DG/UX
+**
+** Data General DG/UX version of inet_addr returns a struct in_addr
+** instead of a long. This patches things. Only needed on versions
+** prior to 5.4.3.
+*/
+
+#ifdef DGUX_5_4_2
+
+#undef inet_addr
+
+long
+dgux_inet_addr(host)
+ char *host;
+{
+ struct in_addr haddr;
+
+ haddr = inet_addr(host);
+ return haddr.s_addr;
+}
+
+#endif
+ /*
+** GETOPT -- for old systems or systems with bogus implementations
+*/
+
+#ifdef NEEDGETOPT
+
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+
+/*
+** this version hacked to add `atend' flag to allow state machine
+** to reset if invoked by the program to scan args for a 2nd time
+*/
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * get option letter from argument vector
+ */
+#ifdef _CONVEX_SOURCE
+extern int optind, opterr, optopt;
+extern char *optarg;
+#else
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = 0; /* character checked for validity */
+char *optarg = NULL; /* argument associated with option */
+#endif
+
+#define BADCH (int)'?'
+#define EMSG ""
+#define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \
+ fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
+
+getopt(nargc,nargv,ostr)
+ int nargc;
+ char *const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ static char atend = 0;
+ register char *oli; /* option letter list index */
+
+ if (atend) {
+ atend = 0;
+ place = EMSG;
+ }
+ if(!*place) { /* update scanning pointer */
+ if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
+ atend++;
+ return(EOF);
+ }
+ if (*place == '-') { /* found "--" */
+ ++optind;
+ atend++;
+ return(EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
+ if (!*place) ++optind;
+ tell(": illegal option -- ");
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place) ++optind;
+ }
+ else { /* need an argument */
+ if (*place) optarg = place; /* no white space */
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ tell(": option requires an argument -- ");
+ }
+ else optarg = nargv[optind]; /* white space */
+ place = EMSG;
+ ++optind;
+ }
+ return(optopt); /* dump back option letter */
+}
+
+#endif
+ /*
+** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version
+*/
+
+#ifdef NEEDVPRINTF
+
+#define MAXARG 16
+
+vfprintf(fp, fmt, ap)
+ FILE *fp;
+ char *fmt;
+ char **ap;
+{
+ char *bp[MAXARG];
+ int i = 0;
+
+ while (*ap && i < MAXARG)
+ bp[i++] = *ap++;
+ fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3],
+ bp[4], bp[5], bp[6], bp[7],
+ bp[8], bp[9], bp[10], bp[11],
+ bp[12], bp[13], bp[14], bp[15]);
+}
+
+vsprintf(s, fmt, ap)
+ char *s;
+ char *fmt;
+ char **ap;
+{
+ char *bp[MAXARG];
+ int i = 0;
+
+ while (*ap && i < MAXARG)
+ bp[i++] = *ap++;
+ sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3],
+ bp[4], bp[5], bp[6], bp[7],
+ bp[8], bp[9], bp[10], bp[11],
+ bp[12], bp[13], bp[14], bp[15]);
+}
+
+#endif
+ /*
+** SNPRINTF, VSNPRINT -- counted versions of printf
+**
+** These are at best crude emulations.
+*/
+
+#if !HASSNPRINTF
+
+void
+# ifdef __STDC__
+snprintf(char *buf, size_t bufsize, const char *fmt, ...)
+# else
+snprintf(buf, bufsize, fmt, va_alist)
+ char *buf;
+ size_t bufsize;
+ const char *fmt;
+ va_dcl
+# endif
+{
+ VA_LOCAL_DECL
+
+ VA_START(fmt);
+ vsprintf(buf, fmt, ap);
+ VA_END;
+# if defined(XDEBUG) && defined(LOG)
+ if (strlen(buf) > bufsize)
+ syslog(LOG_ALERT, "INTERNAL ERROR: snprintf overflow: %s",
+ shortenstring(buf, 200));
+# endif
+}
+
+
+#ifndef luna2
+void
+vsnprintf(buf, bufsize, fmt, ap)
+ char *buf;
+ size_t bufsize;
+ const char *fmt;
+ va_list ap;
+{
+ vsprintf(buf, fmt, ap);
+# if defined(XDEBUG) && defined(LOG)
+ if (strlen(buf) > bufsize)
+ syslog(LOG_ALERT, "INTERNAL ERROR: vsnprintf overflow: %s",
+ shortenstring(buf, 200));
+# endif
+}
+#endif
+
+#endif
+ /*
+** USERSHELLOK -- tell if a user's shell is ok for unrestricted use
+**
+** Parameters:
+** user -- the name of the user we are checking.
+** shell -- the user's shell from /etc/passwd
+**
+** Returns:
+** TRUE -- if it is ok to use this for unrestricted access.
+** FALSE -- if the shell is restricted.
+*/
+
+#if !HASGETUSERSHELL
+
+# ifndef _PATH_SHELLS
+# define _PATH_SHELLS "/etc/shells"
+# endif
+
+# ifdef _AIX3
+# include <userconf.h>
+# include <usersec.h>
+# endif
+
+char *DefaultUserShells[] =
+{
+ "/bin/sh", /* standard shell */
+ "/usr/bin/sh",
+ "/bin/csh", /* C shell */
+ "/usr/bin/csh",
+#ifdef __hpux
+# ifdef V4FS
+ "/usr/bin/rsh", /* restricted Bourne shell */
+ "/usr/bin/ksh", /* Korn shell */
+ "/usr/bin/rksh", /* restricted Korn shell */
+ "/usr/bin/pam",
+ "/usr/bin/keysh", /* key shell (extended Korn shell) */
+ "/usr/bin/posix/sh",
+# else
+ "/bin/rsh", /* restricted Bourne shell */
+ "/bin/ksh", /* Korn shell */
+ "/bin/rksh", /* restricted Korn shell */
+ "/bin/pam",
+ "/usr/bin/keysh", /* key shell (extended Korn shell) */
+ "/bin/posix/sh",
+# endif
+#endif
+#ifdef _AIX3
+ "/bin/ksh", /* Korn shell */
+ "/usr/bin/ksh",
+ "/bin/tsh", /* trusted shell */
+ "/usr/bin/tsh",
+ "/bin/bsh", /* Bourne shell */
+ "/usr/bin/bsh",
+#endif
+#ifdef __svr4__
+ "/bin/ksh", /* Korn shell */
+ "/usr/bin/ksh",
+#endif
+ NULL
+};
+
+#endif
+
+#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
+
+bool
+usershellok(user, shell)
+ char *user;
+ char *shell;
+{
+#if HASGETUSERSHELL
+ register char *p;
+ extern char *getusershell();
+
+ if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
+ ConfigLevel <= 1)
+ return TRUE;
+
+ setusershell();
+ while ((p = getusershell()) != NULL)
+ if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
+ break;
+ endusershell();
+ return p != NULL;
+#else
+# if USEGETCONFATTR
+ auto char *v;
+# endif
+ register FILE *shellf;
+ char buf[MAXLINE];
+
+ if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't'))
+ return TRUE;
+
+# if USEGETCONFATTR
+ /*
+ ** Naturally IBM has a "better" idea.....
+ **
+ ** What a crock. This interface isn't documented, it is
+ ** considered part of the security library (-ls), and it
+ ** only works if you are running as root (since the list
+ ** of valid shells is obviously a source of great concern).
+ ** I recommend that you do NOT define USEGETCONFATTR,
+ ** especially since you are going to have to set up an
+ ** /etc/shells anyhow to handle the cases where getconfattr
+ ** fails.
+ */
+
+ if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
+ {
+ while (*v != '\0')
+ {
+ if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
+ return TRUE;
+ v += strlen(v) + 1;
+ }
+ return FALSE;
+ }
+# endif
+
+ shellf = fopen(_PATH_SHELLS, "r");
+ if (shellf == NULL)
+ {
+ /* no /etc/shells; see if it is one of the std shells */
+ char **d;
+
+ for (d = DefaultUserShells; *d != NULL; d++)
+ {
+ if (strcmp(shell, *d) == 0)
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ while (fgets(buf, sizeof buf, shellf) != NULL)
+ {
+ register char *p, *q;
+
+ p = buf;
+ while (*p != '\0' && *p != '#' && *p != '/')
+ p++;
+ if (*p == '#' || *p == '\0')
+ continue;
+ q = p;
+ while (*p != '\0' && *p != '#' && !isspace(*p))
+ p++;
+ *p = '\0';
+ if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
+ {
+ fclose(shellf);
+ return TRUE;
+ }
+ }
+ fclose(shellf);
+ return FALSE;
+#endif
+}
+ /*
+** FREEDISKSPACE -- see how much free space is on the queue filesystem
+**
+** Only implemented if you have statfs.
+**
+** Parameters:
+** dir -- the directory in question.
+** bsize -- a variable into which the filesystem
+** block size is stored.
+**
+** Returns:
+** The number of bytes free on the queue filesystem.
+** -1 if the statfs call fails.
+**
+** Side effects:
+** Puts the filesystem block size into bsize.
+*/
+
+/* statfs types */
+#define SFS_NONE 0 /* no statfs implementation */
+#define SFS_USTAT 1 /* use ustat */
+#define SFS_4ARGS 2 /* use four-argument statfs call */
+#define SFS_VFS 3 /* use <sys/vfs.h> implementation */
+#define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
+#define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
+#define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */
+
+#ifndef SFS_TYPE
+# define SFS_TYPE SFS_NONE
+#endif
+
+#if SFS_TYPE == SFS_USTAT
+# include <ustat.h>
+#endif
+#if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
+# include <sys/statfs.h>
+#endif
+#if SFS_TYPE == SFS_VFS
+# include <sys/vfs.h>
+#endif
+#if SFS_TYPE == SFS_MOUNT
+# include <sys/mount.h>
+#endif
+#if SFS_TYPE == SFS_STATVFS
+# include <sys/statvfs.h>
+#endif
+
+long
+freediskspace(dir, bsize)
+ char *dir;
+ long *bsize;
+{
+#if SFS_TYPE != SFS_NONE
+# if SFS_TYPE == SFS_USTAT
+ struct ustat fs;
+ struct stat statbuf;
+# define FSBLOCKSIZE DEV_BSIZE
+# define SFS_BAVAIL f_tfree
+# else
+# if defined(ultrix)
+ struct fs_data fs;
+# define SFS_BAVAIL fd_bfreen
+# define FSBLOCKSIZE 1024L
+# else
+# if SFS_TYPE == SFS_STATVFS
+ struct statvfs fs;
+# define FSBLOCKSIZE fs.f_frsize
+# else
+ struct statfs fs;
+# define FSBLOCKSIZE fs.f_bsize
+# endif
+# endif
+# endif
+# ifndef SFS_BAVAIL
+# define SFS_BAVAIL f_bavail
+# endif
+
+# if SFS_TYPE == SFS_USTAT
+ if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
+# else
+# if SFS_TYPE == SFS_4ARGS
+ if (statfs(dir, &fs, sizeof fs, 0) == 0)
+# else
+# if SFS_TYPE == SFS_STATVFS
+ if (statvfs(dir, &fs) == 0)
+# else
+# if defined(ultrix)
+ if (statfs(dir, &fs) > 0)
+# else
+ if (statfs(dir, &fs) == 0)
+# endif
+# endif
+# endif
+# endif
+ {
+ if (bsize != NULL)
+ *bsize = FSBLOCKSIZE;
+ if (fs.SFS_BAVAIL < 0)
+ return 0;
+ else
+ return fs.SFS_BAVAIL;
+ }
+#endif
+ return (-1);
+}
+ /*
+** ENOUGHDISKSPACE -- is there 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.
+*/
+
+bool
+enoughdiskspace(msize)
+ long msize;
+{
+ long bfree, bsize;
+
+ if (MinBlocksFree <= 0 && msize <= 0)
+ {
+ if (tTd(4, 80))
+ printf("enoughdiskspace: no threshold\n");
+ return TRUE;
+ }
+
+ if ((bfree = freediskspace(QueueDir, &bsize)) >= 0)
+ {
+ if (tTd(4, 80))
+ printf("enoughdiskspace: bavail=%ld, need=%ld\n",
+ bfree, msize);
+
+ /* convert msize to block count */
+ msize = msize / bsize + 1;
+ if (MinBlocksFree >= 0)
+ msize += MinBlocksFree;
+
+ if (bfree < msize)
+ {
+#ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT,
+ "%s: low on space (have %ld, %s needs %ld in %s)",
+ CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id,
+ bfree,
+ CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
+ msize, QueueDir);
+#endif
+ return FALSE;
+ }
+ }
+ else if (tTd(4, 80))
+ printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n",
+ MinBlocksFree, msize, errstring(errno));
+ return TRUE;
+}
+ /*
+** 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 ETXTBSY
+ case ETXTBSY: /* (Apollo) file locked */
+#endif
+#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
+ case ENOSR: /* Out of streams resources */
+#endif
+ case EOPENTIMEOUT: /* PSEUDO: open timed out */
+ return TRUE;
+ }
+
+ /* nope, must be permanent */
+ return FALSE;
+}
+ /*
+** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
+**
+** Parameters:
+** fd -- the file descriptor of the file.
+** filename -- the file name (for error messages).
+** ext -- the filename extension.
+** 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, ext, type)
+ int fd;
+ char *filename;
+ char *ext;
+ int type;
+{
+# if !HASFLOCK
+ int action;
+ struct flock lfd;
+
+ if (ext == NULL)
+ ext = "";
+
+ bzero(&lfd, sizeof 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;
+
+ if (tTd(55, 60))
+ printf("lockfile(%s%s, action=%d, type=%d): ",
+ filename, ext, action, lfd.l_type);
+
+ if (fcntl(fd, action, &lfd) >= 0)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
+ return TRUE;
+ }
+
+ if (tTd(55, 60))
+ printf("(%s) ", errstring(errno));
+
+ /*
+ ** On SunOS, if you are testing using -oQ/tmp/mqueue or
+ ** -oA/tmp/aliases or anything like that, and /tmp is mounted
+ ** as type "tmp" (that is, served from swap space), the
+ ** previous fcntl will fail with "Invalid argument" errors.
+ ** Since this is fairly common during testing, we will assume
+ ** that this indicates that the lock is successfully grabbed.
+ */
+
+ if (errno == EINVAL)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
+ return TRUE;
+ }
+
+ if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN))
+ {
+ int omode = -1;
+# ifdef F_GETFL
+ int oerrno = errno;
+
+ (void) fcntl(fd, F_GETFL, &omode);
+ errno = oerrno;
+# endif
+ syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
+ filename, ext, fd, type, omode, geteuid());
+ }
+# else
+ if (ext == NULL)
+ ext = "";
+
+ if (tTd(55, 60))
+ printf("lockfile(%s%s, type=%o): ", filename, ext, type);
+
+ if (flock(fd, type) >= 0)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
+ return TRUE;
+ }
+
+ if (tTd(55, 60))
+ printf("(%s) ", errstring(errno));
+
+ if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK)
+ {
+ int omode = -1;
+# ifdef F_GETFL
+ int oerrno = errno;
+
+ (void) fcntl(fd, F_GETFL, &omode);
+ errno = oerrno;
+# endif
+ syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
+ filename, ext, fd, type, omode, geteuid());
+ }
+# endif
+ if (tTd(55, 60))
+ printf("FAIL\n");
+ return FALSE;
+}
+ /*
+** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
+**
+** Parameters:
+** fd -- the file descriptor to check.
+**
+** Returns:
+** TRUE -- if only root can chown the file to an arbitrary
+** user.
+** FALSE -- if an arbitrary user can give away a file.
+*/
+
+bool
+chownsafe(fd)
+ int fd;
+{
+#ifdef __hpux
+ char *s;
+ int tfd;
+ uid_t o_uid, o_euid;
+ gid_t o_gid, o_egid;
+ bool rval;
+ struct stat stbuf;
+
+ o_uid = getuid();
+ o_euid = geteuid();
+ o_gid = getgid();
+ o_egid = getegid();
+ fstat(fd, &stbuf);
+ setresuid(stbuf.st_uid, stbuf.st_uid, -1);
+ setresgid(stbuf.st_gid, stbuf.st_gid, -1);
+ s = tmpnam(NULL);
+ tfd = open(s, O_RDONLY|O_CREAT, 0600);
+ rval = fchown(tfd, DefUid, DefGid) != 0;
+ close(tfd);
+ unlink(s);
+ setresuid(o_uid, o_euid, -1);
+ setresgid(o_gid, o_egid, -1);
+ return rval;
+#else
+# ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED == -1
+ return FALSE;
+# else
+ return TRUE;
+# endif
+# else
+# ifdef _PC_CHOWN_RESTRICTED
+ int rval;
+
+ /*
+ ** Some systems (e.g., SunOS) seem to have the call and the
+ ** #define _PC_CHOWN_RESTRICTED, but don't actually implement
+ ** the call. This heuristic checks for that.
+ */
+
+ errno = 0;
+ rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
+ if (errno == 0)
+ return rval > 0;
+# endif
+# ifdef BSD
+ return TRUE;
+# else
+ return FALSE;
+# endif
+# endif
+#endif
+}
+ /*
+** RESETLIMITS -- reset system controlled resource limits
+**
+** This is to avoid denial-of-service attacks
+**
+** Parameters:
+** none
+**
+** Returns:
+** none
+*/
+
+#if HASSETRLIMIT
+# ifdef apollo
+# include <sys/time.h>
+# endif
+# include <sys/resource.h>
+#endif
+
+void
+resetlimits()
+{
+#if HASSETRLIMIT
+ struct rlimit lim;
+
+ lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
+ (void) setrlimit(RLIMIT_CPU, &lim);
+ (void) setrlimit(RLIMIT_FSIZE, &lim);
+#else
+# if HASULIMIT
+ (void) ulimit(2, 0x3fffff);
+# endif
+#endif
+}
+ /*
+** GETCFNAME -- return the name of the .cf file.
+**
+** Some systems (e.g., NeXT) determine this dynamically.
+*/
+
+char *
+getcfname()
+{
+
+ if (ConfFile != NULL)
+ return ConfFile;
+#if NETINFO
+ {
+ extern char *ni_propval();
+ char *cflocation;
+
+ cflocation = ni_propval("/locations", NULL, "sendmail",
+ "sendmail.cf", '\0');
+ if (cflocation != NULL)
+ return cflocation;
+ }
+#endif
+
+ return _PATH_SENDMAILCF;
+}
+ /*
+** SETVENDOR -- process vendor code from V configuration line
+**
+** Parameters:
+** vendor -- string representation of vendor.
+**
+** Returns:
+** TRUE -- if ok.
+** FALSE -- if vendor code could not be processed.
+**
+** Side Effects:
+** It is reasonable to set mode flags here to tweak
+** processing in other parts of the code if necessary.
+** For example, if you are a vendor that uses $%y to
+** indicate YP lookups, you could enable that here.
+*/
+
+bool
+setvendor(vendor)
+ char *vendor;
+{
+ if (strcasecmp(vendor, "Berkeley") == 0)
+ {
+ VendorCode = VENDOR_BERKELEY;
+ return TRUE;
+ }
+
+ /* add vendor extensions here */
+
+#ifdef SUN_EXTENSIONS
+ if (strcasecmp(vendor, "Sun") == 0)
+ {
+ VendorCode = VENDOR_SUN;
+ return TRUE;
+ }
+#endif
+
+ return FALSE;
+}
+ /*
+** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
+**
+** Vendor_pre_defaults is called before reading the configuration
+** file; vendor_post_defaults is called immediately after.
+**
+** Parameters:
+** e -- the global environment to initialize.
+**
+** Returns:
+** none.
+*/
+
+void
+vendor_pre_defaults(e)
+ ENVELOPE *e;
+{
+}
+
+
+void
+vendor_post_defaults(e)
+ ENVELOPE *e;
+{
+}
+ /*
+** STRTOL -- convert string to long integer
+**
+** For systems that don't have it in the C library.
+**
+** This is taken verbatim from the 4.4-Lite C library.
+*/
+
+#ifdef NEEDSTRTOL
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+
+long
+strtol(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+
+#endif
+ /*
+** STRSTR -- find first substring in string
+**
+** Parameters:
+** big -- the big (full) string.
+** little -- the little (sub) string.
+**
+** Returns:
+** A pointer to the first instance of little in big.
+** big if little is the null string.
+** NULL if little is not contained in big.
+*/
+
+#ifdef NEEDSTRSTR
+
+char *
+strstr(big, little)
+ char *big;
+ char *little;
+{
+ register char *p = big;
+ int l;
+
+ if (*little == '\0')
+ return big;
+ l = strlen(little);
+
+ while ((p = strchr(p, *little)) != NULL)
+ {
+ if (strncmp(p, little, l) == 0)
+ return p;
+ p++;
+ }
+ return NULL;
+}
+
+#endif
+ /*
+** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
+**
+** Some operating systems have wierd problems with the gethostbyXXX
+** routines. For example, Solaris versions at least through 2.3
+** don't properly deliver a canonical h_name field. This tries to
+** work around these problems.
+*/
+
+struct hostent *
+sm_gethostbyname(name)
+ char *name;
+{
+ struct hostent *h;
+#if defined(SOLARIS) && SOLARIS < 204 || defined(sony_news) && defined(__svr4)
+# if SOLARIS == 203
+ static struct hostent hp;
+ static char buf[1000];
+ extern struct hostent *_switch_gethostbyname_r();
+
+ if (tTd(61, 10))
+ printf("_switch_gethostbyname_r(%s)... ", name);
+ h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
+# else
+ extern struct hostent *__switch_gethostbyname();
+
+ if (tTd(61, 10))
+ printf("__switch_gethostbyname(%s)... ", name);
+ h = __switch_gethostbyname(name);
+# endif
+#else
+ int nmaps;
+ char *maptype[MAXMAPSTACK];
+ short mapreturn[MAXMAPACTIONS];
+ char hbuf[MAXNAME];
+
+ if (tTd(61, 10))
+ printf("gethostbyname(%s)... ", name);
+ h = gethostbyname(name);
+ if (h == NULL)
+ {
+ if (tTd(61, 10))
+ printf("failure\n");
+
+ nmaps = switch_map_find("hosts", maptype, mapreturn);
+ while (--nmaps >= 0)
+ if (strcmp(maptype[nmaps], "nis") == 0 ||
+ strcmp(maptype[nmaps], "files") == 0)
+ break;
+ if (nmaps >= 0)
+ {
+ /* try short name */
+ if (strlen(name) > sizeof hbuf - 1)
+ return NULL;
+ strcpy(hbuf, name);
+ shorten_hostname(hbuf);
+
+ /* if it hasn't been shortened, there's no point */
+ if (strcmp(hbuf, name) != 0)
+ {
+ if (tTd(61, 10))
+ printf("gethostbyname(%s)... ", hbuf);
+ h = gethostbyname(hbuf);
+ }
+ }
+ }
+#endif
+ if (tTd(61, 10))
+ {
+ if (h == NULL)
+ printf("failure\n");
+ else
+ printf("%s\n", h->h_name);
+ }
+ return h;
+}
+
+struct hostent *
+sm_gethostbyaddr(addr, len, type)
+ char *addr;
+ int len;
+ int type;
+{
+#if defined(SOLARIS) && SOLARIS < 204
+# if SOLARIS == 203
+ static struct hostent hp;
+ static char buf[1000];
+ extern struct hostent *_switch_gethostbyaddr_r();
+
+ return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno);
+# else
+ extern struct hostent *__switch_gethostbyaddr();
+
+ return __switch_gethostbyaddr(addr, len, type);
+# endif
+#else
+ return gethostbyaddr(addr, len, type);
+#endif
+}
+ /*
+** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
+*/
+
+struct passwd *
+sm_getpwnam(user)
+ char *user;
+{
+ return getpwnam(user);
+}
+
+struct passwd *
+sm_getpwuid(uid)
+ UID_T uid;
+{
+ return getpwuid(uid);
+}
+ /*
+** LOAD_IF_NAMES -- load interface-specific names into $=w
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Loads $=w with the names of all the interfaces.
+*/
+
+#ifdef SIOCGIFCONF
+struct rtentry;
+struct mbuf;
+# include <arpa/inet.h>
+# ifndef SUNOS403
+# include <sys/time.h>
+# endif
+# include <net/if.h>
+#endif
+
+void
+load_if_names()
+{
+#ifdef SIOCGIFCONF
+ int s;
+ int i;
+ struct ifconf ifc;
+ char interfacebuf[1024];
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1)
+ return;
+
+ /* get the list of known IP address from the kernel */
+ ifc.ifc_buf = interfacebuf;
+ ifc.ifc_len = sizeof interfacebuf;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
+ {
+ if (tTd(0, 4))
+ printf("SIOGIFCONF failed: %s\n", errstring(errno));
+ close(s);
+ return;
+ }
+ close(s);
+
+ /* scan the list of IP address */
+ if (tTd(0, 40))
+ printf("scanning for interface specific names, ifc_len=%d\n",
+ ifc.ifc_len);
+
+ for (i = 0; i < ifc.ifc_len; )
+ {
+ struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
+ struct sockaddr *sa = &ifr->ifr_addr;
+ struct in_addr ia;
+ struct hostent *hp;
+ char ip_addr[256];
+ extern char *inet_ntoa();
+ extern struct hostent *gethostbyaddr();
+
+#ifdef BSD4_4_SOCKADDR
+ if (sa->sa_len > sizeof ifr->ifr_addr)
+ i += sizeof ifr->ifr_name + sa->sa_len;
+ else
+#endif
+ i += sizeof *ifr;
+
+ if (tTd(0, 20))
+ printf("%s\n", anynet_ntoa((SOCKADDR *) sa));
+
+ /* for some reason gcc 2.3 pukes on || here */
+ if (!bitset(IFF_UP, ifr->ifr_flags))
+ continue;
+ if (ifr->ifr_addr.sa_family != AF_INET)
+ continue;
+
+ /* extract IP address from the list*/
+ ia = (((struct sockaddr_in *) sa)->sin_addr);
+
+ /* save IP address in text from */
+ (void) sprintf(ip_addr, "[%.*s]",
+ sizeof ip_addr - 3,
+ inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
+ if (!wordinclass(ip_addr, 'w'))
+ {
+ setclass('w', ip_addr);
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", ip_addr);
+ }
+
+ /* skip "loopback" interface "lo" */
+ if (strcmp("lo0", ifr->ifr_name) == 0)
+ continue;
+
+ /* lookup name with IP address */
+ hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET);
+ if (hp == NULL)
+ {
+ syslog(LOG_CRIT, "gethostbyaddr() failed for %.100s\n",
+ inet_ntoa(ia));
+ continue;
+ }
+
+ /* save its cname */
+ if (!wordinclass((char *) hp->h_name, 'w'))
+ {
+ setclass('w', (char *) hp->h_name);
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", hp->h_name);
+ }
+
+ /* save all it aliases name */
+ while (*hp->h_aliases)
+ {
+ if (!wordinclass(*hp->h_aliases, 'w'))
+ {
+ setclass('w', *hp->h_aliases);
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", *hp->h_aliases);
+ }
+ hp->h_aliases++;
+ }
+ }
+#endif
+}
+ /*
+** HARD_SYSLOG -- call syslog repeatedly until it works
+**
+** Needed on HP-UX, which apparently doesn't guarantee that
+** syslog succeeds during interrupt handlers.
+*/
+
+#ifdef __hpux
+
+# define MAXSYSLOGTRIES 100
+# undef syslog
+
+# ifdef __STDC__
+void
+hard_syslog(int pri, char *msg, ...)
+# else
+hard_syslog(pri, msg, va_alist)
+ int pri;
+ char *msg;
+ va_dcl
+# endif
+{
+ int i;
+ char buf[SYSLOG_BUFSIZE * 2];
+ VA_LOCAL_DECL;
+
+ VA_START(msg);
+ vsnprintf(buf, sizeof buf, msg, ap);
+ VA_END;
+
+ for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; )
+ continue;
+}
+
+#endif
+ /*
+** LOCAL_HOSTNAME_LENGTH
+**
+** This is required to get sendmail to compile against BIND 4.9.x
+** on Ultrix.
+*/
+
+#if defined(ultrix) && NAMED_BIND
+
+# include <resolv.h>
+# if __RES >= 19931104 && __RES < 19950621
+
+int
+local_hostname_length(hostname)
+ char *hostname;
+{
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return len_host - len_domain - 1;
+ else
+ return 0;
+}
+
+# endif
+#endif
+ /*
+** Compile-Time options
+*/
+
+char *CompileOptions[] =
+{
+#if HESIOD
+ "HESIOD",
+#endif
+#if HES_GETMAILHOST
+ "HES_GETMAILHOST",
+#endif
+#ifdef LOG
+ "LOG",
+#endif
+#if MATCHGECOS
+ "MATCHGECOS",
+#endif
+#if MIME8TO7
+ "MIME8TO7",
+#endif
+#if NAMED_BIND
+ "NAMED_BIND",
+#endif
+#if NDBM
+ "NDBM",
+#endif
+#if NETINET
+ "NETINET",
+#endif
+#if NETINFO
+ "NETINFO",
+#endif
+#if NETISO
+ "NETISO",
+#endif
+#if NETNS
+ "NETNS",
+#endif
+#if NETUNIX
+ "NETUNIX",
+#endif
+#if NETX25
+ "NETX25",
+#endif
+#if NEWDB
+ "NEWDB",
+#endif
+#if NIS
+ "NIS",
+#endif
+#if NISPLUS
+ "NISPLUS",
+#endif
+#if SCANF
+ "SCANF",
+#endif
+#if SUID_ROOT_FILES_OK
+ "SUID_ROOT_FILES_OK",
+#endif
+#if USERDB
+ "USERDB",
+#endif
+#if XDEBUG
+ "XDEBUG",
+#endif
+#if XLA
+ "XLA",
+#endif
+ NULL
+};
+
+
+/*
+** OS compile options.
+*/
+
+char *OsCompileOptions[] =
+{
+#if HASFCHMOD
+ "HASFCHMOD",
+#endif
+#if HASFLOCK
+ "HASFLOCK",
+#endif
+#if HASGETUSERSHELL
+ "HASGETUSERSHELL",
+#endif
+#if HASINITGROUPS
+ "HASINITGROUPS",
+#endif
+#if HASLSTAT
+ "HASLSTAT",
+#endif
+#if HASSETREUID
+ "HASSETREUID",
+#endif
+#if HASSETSID
+ "HASSETSID",
+#endif
+#if HASSETVBUF
+ "HASSETVBUF",
+#endif
+#if HASSNPRINTF
+ "HASSNPRINTF",
+#endif
+#if HASUNAME
+ "HASUNAME",
+#endif
+#if IDENTPROTO
+ "IDENTPROTO",
+#endif
+#if IP_SRCROUTE
+ "IP_SRCROUTE",
+#endif
+#if NEEDFSYNC
+ "NEEDFSYNC",
+#endif
+#if NOFTRUNCATE
+ "NOFTRUNCATE",
+#endif
+#if SYS5SETPGRP
+ "SYS5SETPGRP",
+#endif
+#if SYSTEM5
+ "SYSTEM5",
+#endif
+#if USESETEUID
+ "USESETEUID",
+#endif
+ NULL
+};
diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h
new file mode 100644
index 000000000000..30bb9d1e2e6b
--- /dev/null
+++ b/usr.sbin/sendmail/src/conf.h
@@ -0,0 +1,1807 @@
+/*
+ * Copyright (c) 1983, 1995 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.
+ *
+ * @(#)conf.h 8.219 (Berkeley) 11/11/95
+ */
+
+/*
+** CONF.H -- All user-configurable parameters for sendmail
+**
+** Send updates to sendmail@Sendmail.ORG so they will be
+** included in the next release.
+*/
+
+struct rusage; /* forward declaration to get gcc to shut up in wait.h */
+
+# include <sys/param.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/file.h>
+# include <sys/wait.h>
+# include <limits.h>
+# include <fcntl.h>
+# include <signal.h>
+# include <netdb.h>
+# include <pwd.h>
+
+/**********************************************************************
+** Table sizes, etc....
+** There shouldn't be much need to change these....
+**********************************************************************/
+
+# define MAXLINE 2048 /* max line length */
+# define MAXNAME 256 /* max length of a name */
+# define MAXPV 40 /* max # of parms to mailers */
+# define MAXATOM 200 /* max atoms per address */
+# define MAXMAILERS 25 /* maximum mailers known to system */
+# define MAXRWSETS 200 /* max # of sets of rewriting rules */
+# define MAXPRIORITIES 25 /* max values for Precedence: field */
+# 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 MAXALIASDB 12 /* max # of alias databases */
+# define MAXMAPSTACK 12 /* max # of stacked or sequenced maps */
+# define MAXTOCLASS 8 /* max # of message timeout classes */
+# define MAXMIMEARGS 20 /* max args in Content-Type: */
+# define MAXMIMENESTING 20 /* max MIME multipart nesting */
+# define QUEUESEGSIZE 1000 /* increment for queue size */
+
+/**********************************************************************
+** Compilation options.
+** #define these to 1 if they are available;
+** #define them to 0 otherwise.
+** All can be overridden from Makefile.
+**********************************************************************/
+
+# ifndef NETINET
+# define NETINET 1 /* include internet support */
+# endif
+
+# ifndef NETISO
+# define NETISO 0 /* do not include ISO socket support */
+# endif
+
+# ifndef NAMED_BIND
+# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */
+# endif
+
+# ifndef XDEBUG
+# define XDEBUG 1 /* enable extended debugging */
+# endif
+
+# ifndef MATCHGECOS
+# define MATCHGECOS 1 /* match user names from gecos field */
+# endif
+
+# ifndef DSN
+# define DSN 1 /* include delivery status notification code */
+# endif
+
+# if !defined(USERDB) && (defined(NEWDB) || defined(HESIOD))
+# define USERDB 1 /* look in user database */
+# endif
+
+# ifndef MIME8TO7
+# define MIME8TO7 1 /* 8->7 bit MIME conversions */
+# endif
+
+# ifndef MIME7TO8
+# define MIME7TO8 1 /* 7->8 bit MIME conversions */
+# endif
+
+/**********************************************************************
+** "Hard" compilation options.
+** #define these if they are available; comment them out otherwise.
+** These cannot be overridden from the Makefile, and should really not
+** be turned off unless absolutely necessary.
+**********************************************************************/
+
+# define LOG /* enable logging -- don't turn off */
+
+/**********************************************************************
+** End of site-specific configuration.
+**********************************************************************/
+ /*
+** General "standard C" defines.
+**
+** These may be undone later, to cope with systems that claim to
+** be Standard C but aren't. Gcc is the biggest offender -- it
+** doesn't realize that the library is part of the language.
+**
+** Life would be much easier if we could get rid of this sort
+** of bozo problems.
+*/
+
+#ifdef __STDC__
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+#endif
+
+/*
+** Assume you have standard calls; can be #undefed below if necessary.
+*/
+
+# define HASLSTAT 1 /* has lstat(2) call */
+ /**********************************************************************
+** Operating system configuration.
+**
+** Unless you are porting to a new OS, you shouldn't have to
+** change these.
+**********************************************************************/
+
+/*
+** HP-UX -- tested for 8.07, 9.00, and 9.01.
+**
+** If V4FS is defined, compile for HP-UX 10.0.
+*/
+
+#ifdef __hpux
+ /* common definitions for HP-UX 9.x and 10.x */
+# undef m_flags /* conflict between db.h & sys/sysmacros.h on HP 300 */
+# define SYSTEM5 1 /* include all the System V defines */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define seteuid(e) setresuid(-1, e, -1)
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# define LA_TYPE LA_HPUX
+# define SPT_TYPE SPT_PSTAT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define GIDSET_T gid_t
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
+# endif
+# define syslog hard_syslog
+# ifdef __STDC__
+extern void hard_syslog(int, char *, ...);
+# endif
+
+# ifdef V4FS
+ /* HP-UX 10.x */
+# define _PATH_UNIX "/stand/vmunix"
+# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# endif
+# ifndef IDENTPROTO
+# define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */
+# endif
+
+# else
+ /* HP-UX 9.x */
+# define _PATH_UNIX "/hp-ux"
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# endif
+
+#endif
+
+
+/*
+** IBM AIX 3.x -- actually tested for 3.2.3
+*/
+
+#ifdef _AIX3
+# include <paths.h>
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
+# define FORK fork /* no vfork primitive available */
+# define GIDSET_T gid_t
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# define SPT_PADCHAR '\0' /* pad process title with nulls */
+# define LA_TYPE LA_INT
+# define LA_AVENRUN "avenrun"
+#endif
+
+
+/*
+** Silicon Graphics IRIX
+**
+** Compiles on 4.0.1.
+**
+** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0).
+** Use IRIX5 instead of IRIX for IRIX 5.x.
+**
+** IRIX64 changes from Mark R. Levinson <ml@cvdev.rochester.edu>.
+** IRIX5 changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>.
+*/
+
+#if defined(IRIX64) || defined(IRIX5)
+# define IRIX
+#endif
+
+#ifdef IRIX
+# define SYSTEM5 1 /* this is a System-V derived system */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# define FORK fork /* no vfork primitive available */
+# define setpgid BSDsetpgrp
+# define GIDSET_T gid_t
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define LA_TYPE LA_INT
+# ifdef IRIX64
+# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */
+# else
+# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
+# endif
+# if defined(IRIX64) || defined(IRIX5)
+# define ARGV_T char *const *
+# define HASSETRLIMIT 1 /* has setrlimit(2) syscall */
+# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */
+# else
+# define ARGV_T const char **
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# endif
+#endif
+
+
+/*
+** SunOS and Solaris
+**
+** Tested on SunOS 4.1.x (a.k.a. Solaris 1.1.x) and
+** Solaris 2.4 (a.k.a. SunOS 5.4).
+*/
+
+#if defined(sun) && !defined(BSD)
+
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# define LA_TYPE LA_INT
+
+# ifdef SOLARIS_2_3
+# define SOLARIS 203 /* for back compat only -- use -DSOLARIS=203 */
+# endif
+
+# ifdef SOLARIS
+ /* Solaris 2.x (a.k.a. SunOS 5.x) */
+# ifndef __svr4__
+# define __svr4__ /* use all System V Releae 4 defines below */
+# endif
+# include <sys/time.h>
+# define GIDSET_T gid_t
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/dev/ksyms"
+# endif
+# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# endif
+# ifndef _PATH_HOSTS
+# define _PATH_HOSTS "/etc/inet/hosts"
+# endif
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
+# endif
+
+# else
+ /* SunOS 4.0.3 or 4.1.x */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */
+# include <vfork.h>
+
+# ifdef SUNOS403
+ /* special tweaking for SunOS 4.0.3 */
+# include <malloc.h>
+# define BSD4_3 1 /* 4.3 BSD-based */
+# define NEEDSTRSTR 1 /* need emulation of strstr(3) routine */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# undef WIFEXITED
+# undef WEXITSTATUS
+# undef HASUNAME
+# define setpgid setpgrp
+typedef int pid_t;
+extern char *getenv();
+
+# else
+ /* 4.1.x specifics */
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+
+# endif
+# endif
+#endif
+
+/*
+** DG/UX
+**
+** Tested on 5.4.2 and 5.4.3. Use DGUX_5_4_2 to get the
+** older support.
+** 5.4.3 changes from Mark T. Robinson <mtr@ornl.gov>.
+*/
+
+#ifdef DGUX_5_4_2
+# define DGUX 1
+#endif
+
+#ifdef DGUX
+# define SYSTEM5 1
+# define LA_TYPE LA_DGUX
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define IP_SRCROUTE 0 /* does not have <netinet/ip_var.h> */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# define SPT_TYPE SPT_NONE /* don't use setproctitle */
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+
+/* these include files must be included early on DG/UX */
+# include <netinet/in.h>
+# include <arpa/inet.h>
+
+/* compiler doesn't understand const? */
+# define const
+
+# ifdef DGUX_5_4_2
+# define inet_addr dgux_inet_addr
+extern long dgux_inet_addr();
+# endif
+#endif
+
+
+/*
+** Digital Ultrix 4.2A or 4.3
+**
+** Apparently, fcntl locking is broken on 4.2A, in that locks are
+** not dropped when the process exits. This causes major problems,
+** so flock is the only alternative.
+*/
+
+#ifdef ultrix
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# ifndef BROKEN_RES_SEARCH
+# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */
+# endif
+# ifdef vax
+# define LA_TYPE LA_FLOAT
+# else
+# define LA_TYPE LA_INT
+# define LA_AVENRUN "avenrun"
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */
+# endif
+#endif
+
+
+/*
+** OSF/1 for KSR.
+**
+** Contributed by Todd C. Miller <Todd.Miller@cs.colorado.edu>
+*/
+
+#ifdef __ksr__
+# define __osf__ 1 /* get OSF/1 defines below */
+# define FORK fork /* no vfork primitive available */
+# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
+# endif
+#endif
+
+
+/*
+** OSF/1 for Intel Paragon.
+**
+** Contributed by Jeff A. Earickson <jeff@ssd.intel.com>
+** of Intel Scalable Systems Divison.
+*/
+
+#ifdef __PARAGON__
+# define __osf__ 1 /* get OSF/1 defines below */
+# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
+#endif
+
+
+/*
+** OSF/1 (tested on Alpha)
+*/
+
+#ifdef __osf__
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define LA_TYPE LA_INT
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** NeXTstep
+*/
+
+#ifdef NeXT
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define NEEDPUTENV 2 /* need putenv(3) call; no setenv(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define UID_T int /* compiler gripes on uid_t */
+# define sleep sleepX
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_MACH
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# ifndef _POSIX_SOURCE
+typedef int pid_t;
+# undef WEXITSTATUS
+# undef WIFEXITED
+# endif
+# define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** 4.4 BSD
+**
+** See also BSD defines.
+*/
+
+#if defined(BSD4_4) && !defined(__bsdi__)
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# include <sys/cdefs.h>
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define BSD4_4_SOCKADDR /* has sa_len */
+# define NETLINK 1 /* supports AF_LINK */
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */
+#endif
+
+
+/*
+** BSD/386 (all versions)
+** From Tony Sanders, BSDI
+*/
+
+#ifdef __bsdi__
+# define HASUNSETENV 1 /* has the unsetenv(3) call */
+# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# define HASUNAME 1 /* has uname(2) syscall */
+# include <sys/cdefs.h>
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define BSD4_4_SOCKADDR /* has sa_len */
+# define NETLINK 1 /* supports AF_LINK */
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
+# define GIDSET_T gid_t
+# if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312
+ /* version 1.1 or later */
+# undef SPT_TYPE
+# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */
+# else
+ /* version 1.0 or earlier */
+# ifndef OLD_NEWDB
+# define OLD_NEWDB 1 /* old version of newdb library */
+# endif
+# define SPT_PADCHAR '\0' /* pad process title with nulls */
+# endif
+#endif
+
+
+
+/*
+** FreeBSD / NetBSD (all architectures, all versions)
+**
+** 4.3BSD clone, closer to 4.4BSD for FreeBSD 1.x and NetBSD 0.9x
+** 4.4BSD-Lite based for FreeBSD 2.x and NetBSD 1.x
+**
+** See also BSD defines.
+*/
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# define HASUNAME 1 /* has uname(2) syscall */
+# include <sys/cdefs.h>
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define BSD4_4_SOCKADDR /* has sa_len */
+# define NETLINK 1 /* supports AF_LINK */
+# define GIDSET_T gid_t
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1)
+# undef SPT_TYPE
+# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */
+# define setreuid __setreuid
+# endif
+#endif
+
+
+/*
+** Mach386
+**
+** For mt Xinu's Mach386 system.
+*/
+
+#if defined(MACH) && defined(i386)
+# define MACH386 1
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define NEEDSTRTOL 1 /* need the strtol() function */
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_FLOAT
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# undef HASSETVBUF /* don't actually have setvbuf(3) */
+# undef WEXITSTATUS
+# undef WIFEXITED
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** 4.3 BSD -- this is for very old systems
+**
+** Should work for mt Xinu MORE/BSD and Mips UMIPS-BSD 2.1.
+**
+** You'll also have to install a new resolver library.
+** I don't guarantee that support for this environment is complete.
+*/
+
+#if defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd)
+# define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define ARBPTR_T char *
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_FLOAT
+# endif
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# undef WEXITSTATUS
+# undef WIFEXITED
+typedef short pid_t;
+extern int errno;
+#endif
+
+
+/*
+** SCO Unix
+**
+** This includes two parts -- the first is for SCO Open Server 3.2v4
+** (contributed by Philippe Brand <phb@colombo.telesys-innov.fr>).
+** The second is, I believe, for an older version.
+*/
+
+#ifdef _SCO_unix_4_2
+# define _SCO_unix_
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define _PATH_UNIX "/unix"
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+#ifdef _SCO_unix_
+# include <sys/stream.h> /* needed for IP_SRCROUTE */
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
+# define FORK fork
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_SHORT
+# define SFS_TYPE SFS_4ARGS /* use <sys/statfs.h> 4-arg impl */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define SPT_TYPE SPT_SCO /* write kernel u. area */
+# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
+# define NETUNIX 0 /* no unix domain socket support */
+#endif
+
+
+/*
+** ISC (SunSoft) Unix.
+**
+** Contributed by J.J. Bailey <jjb@jagware.bcc.com>
+*/
+
+#ifdef ISC_UNIX
+# include <net/errno.h>
+# include <sys/stream.h> /* needed for IP_SRCROUTE */
+# include <sys/bsdtypes.h>
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
+# define NETUNIX 0 /* no unix domain socket support */
+# define FORK fork
+# define MAXPATHLEN 1024
+# define LA_TYPE LA_SHORT
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define _PATH_UNIX "/unix"
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+
+#endif
+
+
+/*
+** Altos System V.
+** Contributed by Tim Rice <timr@crl.com>.
+*/
+
+#ifdef ALTOS_SYS_V
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define NEEDFSYNC 1 /* no fsync(2) in system library */
+# define FORK fork
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_SHORT
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
+# define NETUNIX 0 /* no unix domain socket support */
+# undef WIFEXITED
+# undef WEXITSTATUS
+# define strtoul strtol /* gcc library bogosity */
+
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+typedef short pid_t;
+#endif
+
+
+/*
+** ConvexOS 11.0 and later
+**
+** "Todd C. Miller" <millert@mroe.cs.colorado.edu> claims this
+** works on 9.1 as well.
+*/
+
+#ifdef _CONVEX_SOURCE
+# define BSD 1 /* include all the BSD defines */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define NEEDGETOPT 1 /* need replacement for getopt(3) */
+# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
+# define LA_TYPE LA_FLOAT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef S_IREAD
+# define S_IREAD _S_IREAD
+# define S_IWRITE _S_IWRITE
+# define S_IEXEC _S_IEXEC
+# define S_IFMT _S_IFMT
+# define S_IFCHR _S_IFCHR
+# define S_IFBLK _S_IFBLK
+# endif
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+#endif
+
+
+/*
+** RISC/os 4.52
+**
+** Gives a ton of warning messages, but otherwise compiles.
+*/
+
+#ifdef RISCOS
+
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define NEEDPUTENV 1 /* need putenv(3) call */
+# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define LA_TYPE LA_INT
+# define LA_AVENRUN "avenrun"
+# define _PATH_UNIX "/unix"
+# undef WIFEXITED
+
+# define setpgid setpgrp
+
+extern int errno;
+typedef int pid_t;
+#define SIGFUNC_DEFINED
+typedef int (*sigfunc_t)();
+extern char *getenv();
+extern void *malloc();
+
+# include <sys/time.h>
+
+#endif
+
+
+/*
+** Linux 0.99pl10 and above...
+**
+** Thanks to, in reverse order of contact:
+**
+** John Kennedy <warlock@csuchico.edu>
+** Andrew Pam <avatar@aus.xanadu.com>
+** Florian La Roche <rzsfl@rz.uni-sb.de>
+** Karl London <karl@borg.demon.co.uk>
+**
+** Last compiled against: [09/06/95 @ 10:20:58 AM (Wednesday)]
+** sendmail 8.7-b14 named 4.9.3-beta17 db-1.85
+** gcc 2.7.0 libc-5.2.7 linux 1.2.13
+*/
+
+#ifdef __linux__
+# define BSD 1 /* include BSD defines */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# ifndef HASSNPRINTF
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# endif
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define GIDSET_T gid_t /* from <linux/types.h> */
+# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */
+# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */
+# ifndef HASFLOCK
+# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */
+# endif
+# ifndef LA_TYPE
+# define LA_TYPE LA_PROCSTR
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() impl */
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
+# endif
+# define TZ_TYPE TZ_TNAME
+# include <sys/sysmacros.h>
+# undef atol /* wounded in <stdlib.h> */
+#endif
+
+
+/*
+** DELL SVR4 Issue 2.2, and others
+** From Kimmo Suominen <kim@grendel.lut.fi>
+**
+** It's on #ifdef DELL_SVR4 because Solaris also gets __svr4__
+** defined, and the definitions conflict.
+**
+** Peter Wemm <peter@perth.DIALix.oz.au> claims that the setreuid
+** trick works on DELL 2.2 (SVR4.0/386 version 4.0) and ESIX 4.0.3A
+** (SVR4.0/386 version 3.0).
+*/
+
+#ifdef DELL_SVR4
+ /* no changes necessary */
+ /* see general __svr4__ defines below */
+#endif
+
+
+/*
+** Apple A/UX 3.0
+*/
+
+#ifdef _AUX_SOURCE
+# include <sys/sysmacros.h>
+# define BSD /* has BSD routines */
+# define HASSETRLIMIT 0 /* ... but not setrlimit(2) */
+# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASFCHMOD 1 /* has fchmod(2) syscall */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# define SIGFUNC_DEFINED /* sigfunc_t already defined */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# define FORK fork
+# ifndef LA_TYPE
+# define LA_TYPE LA_INT
+# define FSHIFT 16
+# endif
+# define LA_AVENRUN "avenrun"
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define TZ_TYPE TZ_TZNAME
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/unix" /* should be in <paths.h> */
+# endif
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Encore UMAX V
+**
+** Not extensively tested.
+*/
+
+#ifdef UMAXV
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
+# define FORK fork /* no vfork(2) primitive available */
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define MAXPATHLEN PATH_MAX
+extern struct passwd *getpwent(), *getpwnam(), *getpwuid();
+extern struct group *getgrent(), *getgrnam(), *getgrgid();
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Stardent Titan 3000 running TitanOS 4.2.
+**
+** Must be compiled in "cc -43" mode.
+**
+** From Kate Hedstrom <kate@ahab.rutgers.edu>.
+**
+** Note the tweaking below after the BSD defines are set.
+*/
+
+#ifdef titan
+# define setpgid setpgrp
+typedef int pid_t;
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Sequent DYNIX 3.2.0
+**
+** From Jim Davis <jdavis@cs.arizona.edu>.
+*/
+
+#ifdef sequent
+
+# define BSD 1
+# define HASUNSETENV 1
+# define BSD4_3 1 /* to get signal() in conf.c */
+# define WAITUNION 1
+# define LA_TYPE LA_FLOAT
+# ifdef _POSIX_VERSION
+# undef _POSIX_VERSION /* set in <unistd.h> */
+# endif
+# undef HASSETVBUF /* don't actually have setvbuf(3) */
+# define setpgid setpgrp
+
+/* Have to redefine WIFEXITED to take an int, to work with waitfor() */
+# undef WIFEXITED
+# define WIFEXITED(s) (((union wait*)&(s))->w_stopval != WSTOPPED && \
+ ((union wait*)&(s))->w_termsig == 0)
+# define WEXITSTATUS(s) (((union wait*)&(s))->w_retcode)
+typedef int pid_t;
+# define isgraph(c) (isprint(c) && (c != ' '))
+
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/dynix"
+# endif
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+
+#endif
+
+
+/*
+** Sequent DYNIX/ptx v2.0 (and higher)
+**
+** For DYNIX/ptx v1.x, undefine HASSETREUID.
+**
+** From Tim Wright <timw@sequent.com>.
+*/
+
+#ifdef _SEQUENT_
+# define SYSTEM5 1 /* include all the System V defines */
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define GIDSET_T gid_t
+# define LA_TYPE LA_INT
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# define SPT_TYPE SPT_NONE /* don't use setproctitle */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** Cray Unicos
+**
+** Ported by David L. Kensiski, Sterling Sofware <kensiski@nas.nasa.gov>
+*/
+
+#ifdef UNICOS
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_ZERO
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+#endif
+
+
+/*
+** Apollo DomainOS
+**
+** From Todd Martin <tmartint@tus.ssi1.com> & Don Lewis <gdonl@gv.ssi1.com>
+**
+** 15 Jan 1994; updated 2 Aug 1995
+**
+*/
+
+#ifdef apollo
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(2) call */
+# define IP_SRCROUTE 0 /* does not have <netinet/ip_var.h> */
+# define SPT_TYPE SPT_NONE /* don't use setproctitle */
+# define LA_TYPE LA_SUBR /* use getloadavg.c */
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define TZ_TYPE TZ_TZNAME
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+# undef S_IFSOCK /* S_IFSOCK and S_IFIFO are the same */
+# undef S_IFIFO
+# define S_IFIFO 0010000
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+#endif
+
+
+/*
+** UnixWare 2.x
+*/
+
+#ifdef UNIXWARE2
+# define UNIXWARE 1
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+#endif
+
+
+/*
+** UnixWare 1.1.2.
+**
+** Updated by Petr Lampa <lampa@fee.vutbr.cz>.
+** From Evan Champion <evanc@spatial.synapse.org>.
+*/
+
+#ifdef UNIXWARE
+# include <sys/mkdev.h>
+# define SYSTEM5 1
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define HASSETREUID 1
+# define HASSETSID 1
+# define HASINITGROUPS 1
+# define GIDSET_T gid_t
+# define SLEEP_T unsigned
+# define SFS_TYPE SFS_STATVFS
+# define LA_TYPE LA_ZERO
+# undef WIFEXITED
+# undef WEXITSTATUS
+# define _PATH_UNIX "/unix"
+# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid"
+# endif
+# define SYSLOG_BUFSIZE 128
+#endif
+
+
+/*
+** Intergraph CLIX 3.1
+**
+** From Paul Southworth <pauls@locust.cic.net>
+*/
+
+#ifdef CLIX
+# define SYSTEM5 1 /* looks like System V */
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# endif
+# define DEV_BSIZE 512 /* device block size not defined */
+# define GIDSET_T gid_t
+# undef LOG /* syslog not available */
+# define NEEDFSYNC 1 /* no fsync in system library */
+# define GETSHORT _getshort
+#endif
+
+
+/*
+** NCR 3000 Series (SysVr4)
+**
+** From Kevin Darcy <kevin@tech.mis.cfc.com>.
+*/
+
+#ifdef NCR3000
+# include <sys/sockio.h>
+# define __svr4__
+# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
+# undef BSD
+# define LA_AVENRUN "avenrun"
+# define SYSLOG_BUFSIZE 1024
+#endif
+
+
+/*
+** Tandem NonStop-UX SVR4
+**
+** From Rick McCarty <mccarty@mpd.tandem.com>.
+*/
+
+#ifdef NonStop_UX_BXX
+# define __svr4__
+#endif
+
+
+/*
+** Hitachi 3050R & 3050RX Workstations running HI-UX/WE2.
+**
+** Tested for 1.04 and 1.03
+** From Akihiro Hashimoto ("Hash") <hash@dominic.ipc.chiba-u.ac.jp>.
+*/
+
+#ifdef __H3050R
+# define SYSTEM5 1 /* include all the System V defines */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define setreuid(r, e) setresuid(r, e, -1)
+# define LA_TYPE LA_FLOAT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define HASSETVBUF /* HI-UX has no setlinebuf */
+# ifndef GIDSET_T
+# define GIDSET_T gid_t
+# endif
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/HI-UX"
+# endif
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
+# endif
+
+/* avoid m_flags conflict between db.h & sys/sysmacros.h on HIUX 3050 */
+# undef m_flags
+
+# ifdef __STDC__
+extern int syslog(int, char *, ...);
+# endif
+
+#endif
+
+
+/*
+** Amdahl UTS System V 2.1.5 (SVr3-based)
+**
+** From: Janet Jackson <janet@dialix.oz.au>.
+*/
+
+#ifdef _UTS
+# include <sys/sysmacros.h>
+# undef HASLSTAT /* has symlinks, but they cause problems */
+# define NEEDFSYNC 1 /* system fsync(2) fails on non-EFS filesys */
+# define SYS5SIGNALS 1 /* System V signal semantics */
+# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASINITGROUPS 1 /* has initgroups(3) function */
+# define HASSETVBUF 1 /* has setvbuf(3) function */
+# define HASSIGSETMASK 0 /* does not have sigsetmask(2) function */
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) function */
+# endif
+# define GIDSET_T gid_t /* type of 2nd arg to getgroups(2) isn't int */
+# define LA_TYPE LA_ZERO /* doesn't have load average */
+# define SFS_TYPE SFS_4ARGS /* use 4-arg statfs() */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define _PATH_UNIX "/unix"
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+#endif
+
+/*
+** Cray Computer Corporation's CSOS
+**
+** From Scott Bolte <scott@craycos.com>.
+*/
+
+#ifdef _CRAYCOM
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define NEEDFSYNC 1 /* no fsync in system library */
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_ZERO
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define SFS_BAVAIL f_bfree /* alternate field name */
+# define _POSIX_CHOWN_RESTRICTED -1
+extern struct group *getgrent(), *getgrnam(), *getgrgid();
+#endif
+
+
+/*
+** Sony NEWS-OS 4.2.1R and 6.0.3
+**
+** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>.
+*/
+
+#ifdef sony_news
+# ifndef __svr4
+ /* NEWS-OS 4.2.1R */
+# ifndef BSD
+# define BSD /* has BSD routines */
+# endif
+# define HASUNSETENV 1 /* has unsetenv(2) call */
+# undef HASSETVBUF /* don't actually have setvbuf(3) */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define LA_TYPE LA_INT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define setpgid setpgrp
+# undef WIFEXITED
+# undef WEXITSTATUS
+typedef int pid_t;
+typedef int (*sigfunc_t)();
+# define SIGFUNC_DEFINED
+
+# else
+ /* NEWS-OS 6.0.3 with /bin/cc */
+# ifndef __svr4__
+# define __svr4__ /* use all System V Releae 4 defines below */
+# endif
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
+# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */
+# ifndef SPT_TYPE
+# define SPT_TYPE SPT_SYSMIPS /* use sysmips() (OS 6.0.2 or later) */
+# endif
+# define GIDSET_T gid_t
+# undef WIFEXITED
+# undef WEXITSTATUS
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024
+# endif
+# define _PATH_UNIX "/stand/unix"
+# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# endif
+
+# endif
+#endif
+
+
+/*
+** Omron LUNA/UNIOS-B 3.0, LUNA2/Mach and LUNA88K Mach
+**
+** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>.
+*/
+
+#ifdef luna
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# define HASUNSETENV 1 /* has unsetenv(2) call */
+# define NEEDPUTENV 1 /* need putenv(3) call */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# ifdef uniosb
+# include <sys/time.h>
+# define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */
+# define LA_TYPE LA_INT
+# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */
+# endif
+# ifdef luna2
+# define LA_TYPE LA_SUBR
+# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */
+# endif
+# ifdef luna88k
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# define LA_TYPE LA_INT
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define setpgid setpgrp
+# undef WIFEXITED
+# undef WEXITSTATUS
+typedef int pid_t;
+typedef int (*sigfunc_t)();
+# define SIGFUNC_DEFINED
+extern char *getenv();
+extern int errno;
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+#endif
+
+
+/*
+** NEC EWS-UX/V 4.2 (with /usr/ucb/cc)
+**
+** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>.
+*/
+
+#if defined(nec_ews_svr4) || defined(_nec_ews_svr4)
+# ifndef __svr4__
+# define __svr4__ /* use all System V Releae 4 defines below */
+# endif
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define LA_TYPE LA_READKSYM /* use MIOC_READSYM ioctl */
+# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */
+# define GIDSET_T gid_t
+# undef WIFEXITED
+# undef WEXITSTATUS
+# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
+# endif
+#endif
+
+
+/*
+** Fujitsu/ICL UXP/DS (For the DS/90 Series)
+**
+** From Diego R. Lopez <drlopez@cica.es>.
+*/
+
+#ifdef UXPDS
+# define __svr4__
+# define HASGETUSERSHELL 1
+# define HASFLOCK 0
+# define _PATH_UNIX "/stand/unix"
+# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# endif
+#endif
+
+
+
+/**********************************************************************
+** End of Per-Operating System defines
+**********************************************************************/
+ /**********************************************************************
+** More general defines
+**********************************************************************/
+
+/* general BSD defines */
+#ifdef BSD
+# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# ifndef IP_SRCROUTE
+# define IP_SRCROUTE 1 /* can check IP source routing */
+# endif
+# ifndef HASSETRLIMIT
+# define HASSETRLIMIT 1 /* has setrlimit(2) call */
+# endif
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */
+# endif
+#endif
+
+/* general System V Release 4 defines */
+#ifdef __svr4__
+# define SYSTEM5 1
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define BSD_COMP 1 /* get BSD ioctl calls */
+# ifndef HASSETRLIMIT
+# define HASSETRLIMIT 1 /* has setrlimit(2) call */
+# endif
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# endif
+
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/unix"
+# endif
+# ifndef _PATH_VENDOR_CF
+# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid"
+# endif
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 128
+# endif
+# ifndef SFS_TYPE
+# define SFS_TYPE SFS_STATVFS
+# endif
+
+# define jmp_buf sigjmp_buf
+# define setjmp(env) sigsetjmp(env, 1)
+# define longjmp(env, val) siglongjmp(env, val)
+#endif
+
+/* general System V defines */
+#ifdef SYSTEM5
+# include <sys/sysmacros.h>
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# ifndef HASULIMIT
+# define HASULIMIT 1 /* has the ulimit(2) syscall */
+# endif
+# ifndef LA_TYPE
+# ifdef MIOC_READKSYM
+# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */
+# else
+# define LA_TYPE LA_INT /* assume integer load average */
+# endif
+# endif
+# ifndef SFS_TYPE
+# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */
+# endif
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
+# endif
+# define bcopy(s, d, l) (memmove((d), (s), (l)))
+# define bzero(d, l) (memset((d), '\0', (l)))
+# define bcmp(s, d, l) (memcmp((s), (d), (l)))
+#endif
+
+/* general POSIX defines */
+#ifdef _POSIX_VERSION
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASWAITPID 1 /* has Posix waitpid(2) call */
+# if _POSIX_VERSION >= 199500 && !defined(USESETEUID)
+# define USESETEUID 1 /* has useable seteuid(2) call */
+# endif
+#endif
+ /*
+** Tweaking for systems that (for example) claim to be BSD or POSIX
+** but don't have all the standard BSD or POSIX routines (boo hiss).
+*/
+
+#ifdef titan
+# undef HASINITGROUPS /* doesn't have initgroups(3) call */
+#endif
+
+#ifdef _CRAYCOM
+# undef HASSETSID /* despite POSIX claim, doesn't have setsid */
+#endif
+
+#ifdef ISC_UNIX
+# undef bcopy /* despite SystemV claim, uses BSD bcopy */
+#endif
+
+#ifdef ALTOS_SYS_V
+# undef bcopy /* despite SystemV claim, uses BSD bcopy */
+# undef bzero /* despite SystemV claim, uses BSD bzero */
+# undef bcmp /* despite SystemV claim, uses BSD bcmp */
+#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
+** not explicitly set to zero above, default it on.
+*/
+
+#ifndef IDENTPROTO
+# define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */
+#endif
+
+#ifndef IP_SRCROUTE
+# define IP_SRCROUTE 1 /* Detect IP source routing */
+#endif
+
+#ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 1 /* libc has getusershell(3) call */
+#endif
+
+#ifndef NETUNIX
+# define NETUNIX 1 /* include unix domain support */
+#endif
+
+#ifndef HASFLOCK
+# define HASFLOCK 0 /* assume no flock(2) support */
+#endif
+
+#ifndef HASSETREUID
+# define HASSETREUID 0 /* assume no setreuid(2) call */
+#endif
+
+#ifndef HASFCHMOD
+# define HASFCHMOD 0 /* assume no fchmod(2) syscall */
+#endif
+
+#ifndef USESETEUID
+# define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */
+#endif
+
+#ifndef HASSETRLIMIT
+# define HASSETRLIMIT 0 /* assume no setrlimit(2) support */
+#endif
+
+#ifndef HASULIMIT
+# define HASULIMIT 0 /* assume no ulimit(2) support */
+#endif
+
+#ifndef OLD_NEWDB
+# define OLD_NEWDB 0 /* assume newer version of newdb */
+#endif
+
+/* heuristic setting of HASSETSIGMASK; can override above */
+#ifndef HASSIGSETMASK
+# ifdef SIGVTALRM
+# define HASSETSIGMASK 1
+# else
+# define HASSETSIGMASK 0
+# endif
+#endif
+
+/*
+** If no type for argument two of getgroups call is defined, assume
+** it's an integer -- unfortunately, there seem to be several choices
+** here.
+*/
+
+#ifndef GIDSET_T
+# define GIDSET_T int
+#endif
+
+#ifndef UID_T
+# define UID_T uid_t
+#endif
+
+#ifndef SIZE_T
+# define SIZE_T size_t
+#endif
+
+#ifndef ARGV_T
+# define ARGV_T char **
+#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_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK)
+#endif
+#ifndef S_IWUSR
+# define S_IWUSR 0200
+#endif
+#ifndef S_IWGRP
+# define S_IWGRP 0020
+#endif
+#ifndef S_IWOTH
+# define S_IWOTH 0002
+#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
+
+/* pseudo-code used in server SMTP */
+# define EX_QUIT 22 /* drop out of server immediately */
+
+
+/*
+** These are used in a few cases where we need some special
+** error codes, but where the system doesn't provide something
+** reasonable. They are printed in errstring.
+*/
+
+#ifndef E_PSEUDOBASE
+# define E_PSEUDOBASE 256
+#endif
+
+#define EOPENTIMEOUT (E_PSEUDOBASE + 0) /* timeout on open */
+#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */
+
+/* type of arbitrary pointer */
+#ifndef ARBPTR_T
+# define ARBPTR_T void *
+#endif
+
+#ifndef __P
+# include "cdefs.h"
+#endif
+
+#if NAMED_BIND
+# include <arpa/nameser.h>
+# ifdef __svr4__
+# ifdef NOERROR
+# undef NOERROR /* avoid compiler conflict with stream.h */
+# endif
+# endif
+# ifndef __ksr__
+extern int h_errno;
+# endif
+#endif
+
+/*
+** The size of an IP address -- can't use sizeof because of problems
+** on Crays, where everything is 64 bits. This will break if/when
+** IP addresses are expanded to eight bytes.
+*/
+
+#ifndef INADDRSZ
+# define INADDRSZ 4
+#endif
+
+/*
+** The size of various known types -- for reading network protocols.
+** Again, we can't use sizeof because of compiler randomness.
+*/
+
+#ifndef INT16SZ
+# define INT16SZ 2
+#endif
+#ifndef INT32SZ
+# define INT32SZ 4
+#endif
+
+/*
+** Do some required dependencies
+*/
+
+#if NETINET || 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 */
+
+#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYS_V)
+# 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
+
+#ifndef LOCK_SH
+# define LOCK_SH 0x01 /* shared lock */
+# define LOCK_EX 0x02 /* exclusive lock */
+# define LOCK_NB 0x04 /* non-blocking lock */
+# define LOCK_UN 0x08 /* unlock */
+#endif
+
+#ifndef SEEK_SET
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+
+#ifndef SIG_ERR
+# define SIG_ERR ((void (*)()) -1)
+#endif
+
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(st) (((st) >> 8) & 0377)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(st) (((st) & 0377) == 0)
+#endif
+
+#ifndef SIGFUNC_DEFINED
+typedef void (*sigfunc_t) __P((int));
+#endif
+
+/* size of syslog buffer */
+#ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024
+#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
+# if (SYSLOG_BUFSIZE) > 768
+# define TOBUFSIZE (SYSLOG_BUFSIZE - 512)
+# else
+# define TOBUFSIZE 256
+# endif
+#endif
+
+/* TOBUFSIZE must never be permitted to exceed MAXLINE - 128 */
+#if TOBUFSIZE > (MAXLINE - 128)
+# undef TOBUFSIZE
+# define TOBUFSIZE (MAXLINE - 128)
+#endif
+
+/*
+** Size of prescan buffer.
+** Despite comments in the _sendmail_ book, this probably should
+** not be changed; there are some hard-to-define dependencies.
+*/
+
+# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */
+/* fork routine -- set above using #ifdef _osname_ or in Makefile */
+# ifndef FORK
+# define FORK vfork /* function to call to fork mailer */
+# endif
+
+/*
+** Default to using scanf in readcf.
+*/
+
+#ifndef SCANF
+# define SCANF 1
+#endif
diff --git a/usr.sbin/sendmail/src/convtime.c b/usr.sbin/sendmail/src/convtime.c
new file mode 100644
index 000000000000..f978e92f15ed
--- /dev/null
+++ b/usr.sbin/sendmail/src/convtime.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)convtime.c 8.4 (Berkeley) 5/19/95";
+#endif /* not lint */
+
+# include <ctype.h>
+# include <string.h>
+# include "useful.h"
+
+/*
+** CONVTIME -- convert time
+**
+** Takes a time as an ascii string with a trailing character
+** giving units:
+** s -- seconds
+** m -- minutes
+** h -- hours
+** d -- days (default)
+** w -- weeks
+** For example, "3d12h" is three and a half days.
+**
+** Parameters:
+** p -- pointer to ascii time.
+** units -- default units if none specified.
+**
+** Returns:
+** time in seconds.
+**
+** Side Effects:
+** none.
+*/
+
+time_t
+convtime(p, units)
+ char *p;
+ char units;
+{
+ register time_t t, r;
+ register char c;
+
+ r = 0;
+ while (*p != '\0')
+ {
+ t = 0;
+ while ((c = *p++) != '\0' && isascii(c) && isdigit(c))
+ t = t * 10 + (c - '0');
+ if (c == '\0')
+ {
+ c = units;
+ p--;
+ }
+ else if (strchr("wdhms", c) == NULL)
+ {
+ usrerr("Invalid time unit `%c'", c);
+ c = units;
+ }
+ switch (c)
+ {
+ case 'w': /* weeks */
+ t *= 7;
+
+ case 'd': /* days */
+ default:
+ t *= 24;
+
+ case 'h': /* hours */
+ t *= 60;
+
+ case 'm': /* minutes */
+ t *= 60;
+
+ case 's': /* seconds */
+ break;
+ }
+ r += t;
+ }
+
+ return (r);
+}
+ /*
+** PINTVL -- produce printable version of a time interval
+**
+** Parameters:
+** intvl -- the interval to be converted
+** brief -- if TRUE, print this in an extremely compact form
+** (basically used for logging).
+**
+** Returns:
+** A pointer to a string version of intvl suitable for
+** printing or framing.
+**
+** Side Effects:
+** none.
+**
+** Warning:
+** The string returned is in a static buffer.
+*/
+
+# define PLURAL(n) ((n) == 1 ? "" : "s")
+
+char *
+pintvl(intvl, brief)
+ time_t intvl;
+ bool brief;
+{
+ static char buf[256];
+ register char *p;
+ int wk, dy, hr, mi, se;
+
+ if (intvl == 0 && !brief)
+ return ("zero seconds");
+
+ /* decode the interval into weeks, days, hours, minutes, seconds */
+ se = intvl % 60;
+ intvl /= 60;
+ mi = intvl % 60;
+ intvl /= 60;
+ hr = intvl % 24;
+ intvl /= 24;
+ if (brief)
+ dy = intvl;
+ else
+ {
+ dy = intvl % 7;
+ intvl /= 7;
+ wk = intvl;
+ }
+
+ /* now turn it into a sexy form */
+ p = buf;
+ if (brief)
+ {
+ if (dy > 0)
+ {
+ (void) sprintf(p, "%d+", dy);
+ p += strlen(p);
+ }
+ (void) sprintf(p, "%02d:%02d:%02d", hr, mi, se);
+ return (buf);
+ }
+
+ /* use the verbose form */
+ if (wk > 0)
+ {
+ (void) sprintf(p, ", %d week%s", wk, PLURAL(wk));
+ p += strlen(p);
+ }
+ if (dy > 0)
+ {
+ (void) sprintf(p, ", %d day%s", dy, PLURAL(dy));
+ p += strlen(p);
+ }
+ if (hr > 0)
+ {
+ (void) sprintf(p, ", %d hour%s", hr, PLURAL(hr));
+ p += strlen(p);
+ }
+ if (mi > 0)
+ {
+ (void) sprintf(p, ", %d minute%s", mi, PLURAL(mi));
+ p += strlen(p);
+ }
+ if (se > 0)
+ {
+ (void) sprintf(p, ", %d second%s", se, PLURAL(se));
+ p += strlen(p);
+ }
+
+ return (buf + 2);
+}
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
new file mode 100644
index 000000000000..c2f5327b1e34
--- /dev/null
+++ b/usr.sbin/sendmail/src/daemon.c
@@ -0,0 +1,1736 @@
+/*
+ * Copyright (c) 1983, 1995 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 <errno.h>
+#include "sendmail.h"
+
+#ifndef lint
+#ifdef DAEMON
+static char sccsid[] = "@(#)daemon.c 8.118 (Berkeley) 10/8/95 (with daemon mode)";
+#else
+static char sccsid[] = "@(#)daemon.c 8.118 (Berkeley) 10/8/95 (without daemon mode)";
+#endif
+#endif /* not lint */
+
+#ifdef DAEMON
+
+# include <arpa/inet.h>
+
+#if NAMED_BIND
+# include <resolv.h>
+# ifndef NO_DATA
+# define NO_DATA NO_ADDRESS
+# endif
+#endif
+
+#if IP_SRCROUTE
+# include <netinet/in_systm.h>
+# include <netinet/ip.h>
+# include <netinet/ip_var.h>
+#endif
+
+/*
+** DAEMON.C -- routines to use when running as a daemon.
+**
+** This entire file is highly dependent on the 4.2 BSD
+** interprocess communication primitives. No attempt has
+** been made to make this file portable to Version 7,
+** Version 6, MPX files, etc. If you should try such a
+** thing yourself, I recommend chucking the entire file
+** and starting from scratch. Basic semantics are:
+**
+** getrequests()
+** Opens a port and initiates a connection.
+** Returns in a child. Must set InChannel and
+** OutChannel appropriately.
+** clrdaemon()
+** Close any open files associated with getting
+** the connection; this is used when running the queue,
+** 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, 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.
+** host_map_lookup(map, hbuf, avp, pstat)
+** Convert the entry in hbuf into a canonical form.
+*/
+ /*
+** GETREQUESTS -- open mail IPC port and get requests.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Waits until some interesting activity occurs. When
+** it does, a child is created to process it, and the
+** parent waits for completion. Return from this
+** routine is always in the child. The file pointers
+** "InChannel" and "OutChannel" should be set to point
+** to the communication channel.
+*/
+
+int DaemonSocket = -1; /* fd describing socket */
+SOCKADDR DaemonAddr; /* socket for incoming */
+int ListenQueueSize = 10; /* size of listen queue */
+int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
+int TcpSndBufferSize = 0; /* size of TCP send buffer */
+
+void
+getrequests()
+{
+ int t;
+ bool refusingconnections = TRUE;
+ FILE *pidf;
+ int socksize;
+#if XDEBUG
+ bool j_has_dot;
+#endif
+ extern void reapchild();
+
+ /*
+ ** Set up the address for the mailer.
+ */
+
+ 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)
+ {
+ register struct servent *sp;
+
+ sp = getservbyname("smtp", "tcp");
+ if (sp == NULL)
+ {
+ syserr("554 service \"smtp\" unknown");
+ DaemonAddr.sin.sin_port = htons(25);
+ }
+ else
+ DaemonAddr.sin.sin_port = sp->s_port;
+ }
+
+ /*
+ ** Try to actually open the connection.
+ */
+
+ if (tTd(15, 1))
+ printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port);
+
+ /* get a socket for the SMTP connection */
+ socksize = opendaemonsocket(TRUE);
+
+ (void) setsignal(SIGCHLD, reapchild);
+
+ /* write the pid to the log file for posterity */
+ pidf = fopen(PidFile, "w");
+ if (pidf != NULL)
+ {
+ extern char *CommandLineArgs;
+
+ /* write the process id on line 1 */
+ fprintf(pidf, "%d\n", getpid());
+
+ /* line 2 contains all command line flags */
+ fprintf(pidf, "%s\n", CommandLineArgs);
+
+ /* flush and close */
+ fclose(pidf);
+ }
+
+#if XDEBUG
+ {
+ char jbuf[MAXHOSTNAMELEN];
+
+ expand("\201j", jbuf, sizeof jbuf, CurEnv);
+ j_has_dot = strchr(jbuf, '.') != NULL;
+ }
+#endif
+
+ if (tTd(15, 1))
+ printf("getrequests: %d\n", DaemonSocket);
+
+ for (;;)
+ {
+ register int pid;
+ auto int lotherend;
+ extern bool refuseconnections();
+ extern int getla();
+
+ /* see if we are rejecting connections */
+ CurrentLA = getla();
+ if (refuseconnections())
+ {
+ if (DaemonSocket >= 0)
+ {
+ /* close socket so peer will fail quickly */
+ (void) close(DaemonSocket);
+ DaemonSocket = -1;
+ }
+ refusingconnections = TRUE;
+ sleep(15);
+ continue;
+ }
+
+ /* arrange to (re)open the socket if necessary */
+ if (refusingconnections)
+ {
+ (void) opendaemonsocket(FALSE);
+ refusingconnections = FALSE;
+ }
+
+#if XDEBUG
+ /* check for disaster */
+ {
+ char jbuf[MAXHOSTNAMELEN];
+
+ expand("\201j", jbuf, sizeof jbuf, CurEnv);
+ if (!wordinclass(jbuf, 'w'))
+ {
+ dumpstate("daemon lost $j");
+ syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog");
+ abort();
+ }
+ else if (j_has_dot && strchr(jbuf, '.') == NULL)
+ {
+ dumpstate("daemon $j lost dot");
+ syslog(LOG_ALERT, "daemon process $j lost dot; see syslog");
+ abort();
+ }
+ }
+#endif
+
+ /* wait for a connection */
+ setproctitle("accepting connections");
+ do
+ {
+ errno = 0;
+ lotherend = socksize;
+ t = accept(DaemonSocket,
+ (struct sockaddr *)&RealHostAddr, &lotherend);
+ } while (t < 0 && errno == EINTR);
+ if (t < 0)
+ {
+ syserr("getrequests: accept");
+
+ /* arrange to re-open the socket next time around */
+ (void) close(DaemonSocket);
+ DaemonSocket = -1;
+ refusingconnections = TRUE;
+ sleep(5);
+ continue;
+ }
+
+ /*
+ ** Create a subprocess to process the mail.
+ */
+
+ if (tTd(15, 2))
+ printf("getrequests: forking (fd = %d)\n", t);
+
+ pid = fork();
+ if (pid < 0)
+ {
+ syserr("daemon: cannot fork");
+ sleep(10);
+ (void) close(t);
+ continue;
+ }
+
+ if (pid == 0)
+ {
+ char *p;
+ extern char *hostnamebyanyaddr();
+ extern void intsig();
+ FILE *inchannel, *outchannel;
+
+ /*
+ ** CHILD -- return to caller.
+ ** Collect verified idea of sending host.
+ ** Verify calling user id if possible here.
+ */
+
+ (void) setsignal(SIGCHLD, SIG_DFL);
+ (void) setsignal(SIGHUP, intsig);
+ (void) close(DaemonSocket);
+
+ setproctitle("startup with %s",
+ anynet_ntoa(&RealHostAddr));
+
+ /* determine host name */
+ p = hostnamebyanyaddr(&RealHostAddr);
+ if (strlen(p) > MAXNAME)
+ p[MAXNAME] = '\0';
+ RealHostName = newstr(p);
+ setproctitle("startup with %s", p);
+
+ if ((inchannel = fdopen(t, "r")) == NULL ||
+ (t = dup(t)) < 0 ||
+ (outchannel = fdopen(t, "w")) == NULL)
+ {
+ syserr("cannot open SMTP server channel, fd=%d", t);
+ exit(0);
+ }
+
+ InChannel = inchannel;
+ OutChannel = outchannel;
+ DisConnected = FALSE;
+
+ /* 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");
+ return;
+ }
+
+ CurChildren++;
+
+ /* close the port so that others will hang (for a while) */
+ (void) close(t);
+ }
+ /*NOTREACHED*/
+}
+ /*
+** OPENDAEMONSOCKET -- open the SMTP socket
+**
+** Deals with setting all appropriate options. DaemonAddr must
+** be set up in advance.
+**
+** Parameters:
+** firsttime -- set if this is the initial open.
+**
+** Returns:
+** Size in bytes of the daemon socket addr.
+**
+** Side Effects:
+** Leaves DaemonSocket set to the open socket.
+** Exits if the socket cannot be created.
+*/
+
+#define MAXOPENTRIES 10 /* maximum number of tries to open connection */
+
+int
+opendaemonsocket(firsttime)
+ bool firsttime;
+{
+ int on = 1;
+ int socksize = 0;
+ int ntries = 0;
+ int saveerrno;
+
+ if (tTd(15, 2))
+ printf("opendaemonsocket()\n");
+
+ do
+ {
+ if (ntries > 0)
+ sleep(5);
+ if (firsttime || DaemonSocket < 0)
+ {
+ DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0);
+ if (DaemonSocket < 0)
+ {
+ saveerrno = errno;
+ syserr("opendaemonsocket: can't create server SMTP socket");
+ severe:
+# ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT, "problem creating SMTP socket");
+# endif /* LOG */
+ DaemonSocket = -1;
+ continue;
+ }
+
+ /* turn on network debugging? */
+ 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);
+
+#ifdef SO_RCVBUF
+ if (TcpRcvBufferSize > 0)
+ {
+ if (setsockopt(DaemonSocket, SOL_SOCKET,
+ SO_RCVBUF,
+ (char *) &TcpRcvBufferSize,
+ sizeof(TcpRcvBufferSize)) < 0)
+ syserr("opendaemonsocket: setsockopt(SO_RCVBUF)");
+ }
+#endif
+
+ switch (DaemonAddr.sa.sa_family)
+ {
+# if NETINET
+ case AF_INET:
+ socksize = sizeof DaemonAddr.sin;
+ break;
+# endif
+
+# if NETISO
+ case AF_ISO:
+ socksize = sizeof DaemonAddr.siso;
+ break;
+# endif
+
+ default:
+ socksize = sizeof DaemonAddr;
+ break;
+ }
+
+ if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0)
+ {
+ /* probably another daemon already */
+ saveerrno = errno;
+ syserr("opendaemonsocket: cannot bind");
+ (void) close(DaemonSocket);
+ goto severe;
+ }
+ }
+ if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0)
+ {
+ saveerrno = errno;
+ syserr("opendaemonsocket: cannot listen");
+ (void) close(DaemonSocket);
+ goto severe;
+ }
+ return socksize;
+ } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno));
+ syserr("!opendaemonsocket: server SMTP socket wedged: exiting");
+ finis();
+}
+ /*
+** CLRDAEMON -- reset the daemon connection
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** releases any resources used by the passive daemon.
+*/
+
+void
+clrdaemon()
+{
+ if (DaemonSocket >= 0)
+ (void) close(DaemonSocket);
+ DaemonSocket = -1;
+}
+ /*
+** SETDAEMONOPTIONS -- set options for running the daemon
+**
+** Parameters:
+** p -- the options line.
+**
+** Returns:
+** none.
+*/
+
+void
+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;
+ if (isascii(*f) && islower(*f))
+ *f = toupper(*f);
+
+ switch (*f)
+ {
+ case 'F': /* address family */
+ if (isascii(*v) && isdigit(*v))
+ DaemonAddr.sa.sa_family = atoi(v);
+#if NETINET
+ else if (strcasecmp(v, "inet") == 0)
+ DaemonAddr.sa.sa_family = AF_INET;
+#endif
+#if NETISO
+ else if (strcasecmp(v, "iso") == 0)
+ DaemonAddr.sa.sa_family = AF_ISO;
+#endif
+#if NETNS
+ else if (strcasecmp(v, "ns") == 0)
+ DaemonAddr.sa.sa_family = AF_NS;
+#endif
+#if 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)
+ {
+#if NETINET
+ case AF_INET:
+ if (isascii(*v) && isdigit(*v))
+ DaemonAddr.sin.sin_addr.s_addr = htonl(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;
+
+#if NETINET
+ case AF_INET:
+ if (isascii(*v) && isdigit(*v))
+ DaemonAddr.sin.sin_port = htons(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
+
+#if NETISO
+ case AF_ISO:
+ /* assume two byte transport selector */
+ if (isascii(*v) && isdigit(*v))
+ port = htons(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;
+
+ case 'S': /* send buffer size */
+ TcpSndBufferSize = atoi(v);
+ break;
+
+ case 'R': /* receive buffer size */
+ TcpRcvBufferSize = atoi(v);
+ break;
+
+ default:
+ syserr("554 DaemonPortOptions parameter \"%s\" unknown", 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.
+** 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
+** made and if not why not.
+**
+** Side Effects:
+** none.
+*/
+
+static jmp_buf CtxConnectTimeout;
+
+static void
+connecttimeout()
+{
+ errno = ETIMEDOUT;
+ longjmp(CtxConnectTimeout, 1);
+}
+
+SOCKADDR CurHostAddr; /* address of current host */
+
+int
+makeconnection(host, port, mci, usesecureport)
+ char *host;
+ u_short port;
+ register MCI *mci;
+ bool usesecureport;
+{
+ register int i = 0;
+ register int s;
+ register struct hostent *hp = (struct hostent *)NULL;
+ SOCKADDR addr;
+ int sav_errno;
+ int addrlen;
+ bool firstconnect;
+ EVENT *ev;
+
+ /*
+ ** Set up the address for the mailer.
+ ** Accept "[a.b.c.d]" syntax for host name.
+ */
+
+#if NAMED_BIND
+ h_errno = 0;
+#endif
+ errno = 0;
+ bzero(&CurHostAddr, sizeof CurHostAddr);
+ SmtpPhase = mci->mci_phase = "initial connection";
+ CurHostName = host;
+
+ if (host[0] == '[')
+ {
+ long hid;
+ register char *p = strchr(host, ']');
+
+ if (p != NULL)
+ {
+ *p = '\0';
+#if NETINET
+ hid = inet_addr(&host[1]);
+ if (hid == -1)
+#endif
+ {
+ /* try it as a host name (avoid MX lookup) */
+ hp = sm_gethostbyname(&host[1]);
+ if (hp == NULL && p[-1] == '.')
+ {
+#if NAMED_BIND
+ int oldopts = _res.options;
+
+ _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
+#endif
+ p[-1] = '\0';
+ hp = sm_gethostbyname(&host[1]);
+ p[-1] = '.';
+#if NAMED_BIND
+ _res.options = oldopts;
+#endif
+ }
+ *p = ']';
+ goto gothostent;
+ }
+ *p = ']';
+ }
+ if (p == NULL)
+ {
+ usrerr("553 Invalid numeric domain spec \"%s\"", host);
+ mci->mci_status = "5.1.2";
+ return (EX_NOHOST);
+ }
+#if NETINET
+ addr.sin.sin_family = AF_INET; /*XXX*/
+ addr.sin.sin_addr.s_addr = hid;
+#endif
+ }
+ else
+ {
+ register char *p = &host[strlen(host) - 1];
+
+ hp = sm_gethostbyname(host);
+ if (hp == NULL && *p == '.')
+ {
+#if NAMED_BIND
+ int oldopts = _res.options;
+
+ _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
+#endif
+ *p = '\0';
+ hp = sm_gethostbyname(host);
+ *p = '.';
+#if NAMED_BIND
+ _res.options = oldopts;
+#endif
+ }
+gothostent:
+ if (hp == NULL)
+ {
+#if NAMED_BIND
+ /* check for name server timeouts */
+ if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
+ (errno == ECONNREFUSED && UseNameServer))
+ {
+ mci->mci_status = "4.4.3";
+ return (EX_TEMPFAIL);
+ }
+#endif
+ return (EX_NOHOST);
+ }
+ addr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype)
+ {
+#if NETINET
+ case AF_INET:
+ bcopy(hp->h_addr,
+ &addr.sin.sin_addr,
+ INADDRSZ);
+ break;
+#endif
+
+ default:
+ bcopy(hp->h_addr,
+ addr.sa.sa_data,
+ hp->h_length);
+ break;
+ }
+ i = 1;
+ }
+
+ /*
+ ** Determine the port number.
+ */
+
+ if (port == 0)
+ {
+ register struct servent *sp = getservbyname("smtp", "tcp");
+
+ if (sp == NULL)
+ {
+#ifdef LOG
+ if (LogLevel > 2)
+ syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown");
+#endif
+ port = htons(25);
+ }
+ else
+ port = sp->s_port;
+ }
+
+ switch (addr.sa.sa_family)
+ {
+#if NETINET
+ case AF_INET:
+ addr.sin.sin_port = port;
+ addrlen = sizeof (struct sockaddr_in);
+ break;
+#endif
+
+#if 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.
+ */
+
+#ifdef XLA
+ /* if too many connections, don't bother trying */
+ if (!xla_noqueue_ok(host))
+ return EX_TEMPFAIL;
+#endif
+
+ firstconnect = TRUE;
+ for (;;)
+ {
+ if (tTd(16, 1))
+ printf("makeconnection (%s [%s])\n",
+ host, anynet_ntoa(&addr));
+
+ /* save for logging */
+ CurHostAddr = addr;
+
+ 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: cannot create socket");
+ goto failure;
+ }
+
+#ifdef SO_SNDBUF
+ if (TcpSndBufferSize > 0)
+ {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ (char *) &TcpSndBufferSize,
+ sizeof(TcpSndBufferSize)) < 0)
+ syserr("makeconnection: setsockopt(SO_SNDBUF)");
+ }
+#endif
+
+ if (tTd(16, 1))
+ printf("makeconnection: fd=%d\n", s);
+
+ /* turn on network debugging? */
+ if (tTd(16, 101))
+ {
+ int on = 1;
+ (void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ (char *)&on, sizeof on);
+ }
+ if (CurEnv->e_xfp != NULL)
+ (void) fflush(CurEnv->e_xfp); /* for debugging */
+ errno = 0; /* for debugging */
+
+ /*
+ ** Linux seems to hang in connect for 90 minutes (!!!).
+ ** Time out the connect to avoid this problem.
+ */
+
+ if (setjmp(CtxConnectTimeout) == 0)
+ {
+ if (TimeOuts.to_connect == 0)
+ ev = NULL;
+ else
+ ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
+ if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
+ {
+ if (ev != NULL)
+ clrevent(ev);
+ break;
+ }
+ }
+ sav_errno = errno;
+ if (ev != NULL)
+ clrevent(ev);
+
+ /* if running demand-dialed connection, try again */
+ if (DialDelay > 0 && firstconnect)
+ {
+ if (tTd(16, 1))
+ printf("Connect failed (%s); trying again...\n",
+ errstring(sav_errno));
+ firstconnect = FALSE;
+ sleep(DialDelay);
+ continue;
+ }
+
+ /* couldn't connect.... figure out why */
+ (void) close(s);
+ if (hp != NULL && hp->h_addr_list[i])
+ {
+ if (tTd(16, 1))
+ printf("Connect failed (%s); trying new address....\n",
+ errstring(sav_errno));
+ switch (addr.sa.sa_family)
+ {
+#if NETINET
+ case AF_INET:
+ bcopy(hp->h_addr_list[i++],
+ &addr.sin.sin_addr,
+ INADDRSZ);
+ 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:
+#ifdef XLA
+ xla_host_end(host);
+#endif
+ if (transienterror(sav_errno))
+ return EX_TEMPFAIL;
+ else
+ {
+ message("%s", errstring(sav_errno));
+ return (EX_UNAVAILABLE);
+ }
+ }
+
+ /* connection ok, put it into canonical form */
+ if ((mci->mci_out = fdopen(s, "w")) == NULL ||
+ (s = dup(s)) < 0 ||
+ (mci->mci_in = fdopen(s, "r")) == NULL)
+ {
+ syserr("cannot open SMTP client channel, fd=%d", s);
+ return EX_TEMPFAIL;
+ }
+
+ return (EX_OK);
+}
+ /*
+** MYHOSTNAME -- return the name of this host.
+**
+** Parameters:
+** hostbuf -- a place to return the name of this host.
+** size -- the size of hostbuf.
+**
+** Returns:
+** A list of aliases for this host.
+**
+** Side Effects:
+** Adds numeric codes to $=w.
+*/
+
+struct hostent *
+myhostname(hostbuf, size)
+ char hostbuf[];
+ int size;
+{
+ register struct hostent *hp;
+ extern bool getcanonname();
+
+ if (gethostname(hostbuf, size) < 0)
+ {
+ (void) strcpy(hostbuf, "localhost");
+ }
+ hp = sm_gethostbyname(hostbuf);
+ if (hp == NULL)
+ return NULL;
+ if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL)
+ {
+ (void) strncpy(hostbuf, hp->h_name, size - 1);
+ hostbuf[size - 1] = '\0';
+ }
+
+ /*
+ ** If there is still no dot in the name, try looking for a
+ ** dotted alias.
+ */
+
+ if (strchr(hostbuf, '.') == NULL)
+ {
+ char **ha;
+
+ for (ha = hp->h_aliases; *ha != NULL; ha++)
+ {
+ if (strchr(*ha, '.') != NULL)
+ {
+ (void) strncpy(hostbuf, *ha, size - 1);
+ hostbuf[size - 1] = '\0';
+ break;
+ }
+ }
+ }
+
+ /*
+ ** If _still_ no dot, wait for a while and try again -- it is
+ ** possible that some service is starting up. This can result
+ ** in excessive delays if the system is badly configured, but
+ ** there really isn't a way around that, particularly given that
+ ** the config file hasn't been read at this point.
+ ** All in all, a bit of a mess.
+ */
+
+ if (strchr(hostbuf, '.') == NULL &&
+ !getcanonname(hostbuf, size, TRUE))
+ {
+#ifdef LOG
+ syslog(LOG_CRIT, "My unqualifed host name (%s) unknown; sleeping for retry",
+ hostbuf);
+#endif
+ message("My unqualifed host name (%s) unknown; sleeping for retry",
+ hostbuf);
+ sleep(60);
+ if (!getcanonname(hostbuf, size, TRUE))
+ {
+#ifdef LOG
+ syslog(LOG_ALERT, "unable to qualify my own domain name (%s) -- using short name",
+ hostbuf);
+#endif
+ message("WARNING: unable to qualify my own domain name (%s) -- using short name",
+ hostbuf);
+ }
+ }
+ return (hp);
+}
+ /*
+** 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.
+*/
+
+static jmp_buf CtxAuthTimeout;
+
+static void
+authtimeout()
+{
+ longjmp(CtxAuthTimeout, 1);
+}
+
+char *
+getauthinfo(fd)
+ int fd;
+{
+ int falen;
+ register char *p;
+ SOCKADDR la;
+ int lalen;
+ register struct servent *sp;
+ volatile int s;
+ int i;
+ EVENT *ev;
+ int nleft;
+ char ibuf[MAXNAME + 1];
+ static char hbuf[MAXNAME * 2 + 2];
+ extern char *hostnamebyanyaddr();
+
+ falen = sizeof RealHostAddr;
+ if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 ||
+ falen <= 0 || RealHostAddr.sa.sa_family == 0)
+ {
+ (void) sprintf(hbuf, "%s@localhost", RealUserName);
+ if (tTd(9, 1))
+ printf("getauthinfo: %s\n", hbuf);
+ return hbuf;
+ }
+
+ if (RealHostName == NULL)
+ {
+ /* translate that to a host name */
+ RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
+ }
+
+ if (TimeOuts.to_ident == 0)
+ goto noident;
+
+ lalen = sizeof la;
+ if (RealHostAddr.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(ibuf, "%d,%d\r\n",
+ ntohs(RealHostAddr.sin.sin_port), ntohs(la.sin.sin_port));
+
+ /* create local address */
+ la.sin.sin_port = 0;
+
+ /* create foreign address */
+ sp = getservbyname("auth", "tcp");
+ if (sp != NULL)
+ RealHostAddr.sin.sin_port = sp->s_port;
+ else
+ RealHostAddr.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(TimeOuts.to_ident, authtimeout, 0);
+
+ /* connect to foreign IDENT server using same address as SMTP socket */
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ clrevent(ev);
+ goto noident;
+ }
+ if (bind(s, &la.sa, sizeof la.sin) < 0 ||
+ connect(s, &RealHostAddr.sa, sizeof RealHostAddr.sin) < 0)
+ {
+ goto closeident;
+ }
+
+ if (tTd(9, 10))
+ printf("getauthinfo: sent %s", ibuf);
+
+ /* send query */
+ if (write(s, ibuf, strlen(ibuf)) < 0)
+ goto closeident;
+
+ /* get result */
+ p = &ibuf[0];
+ nleft = sizeof ibuf - 1;
+ while ((i = read(s, p, nleft)) > 0)
+ {
+ p += i;
+ nleft -= i;
+ }
+ (void) close(s);
+ clrevent(ev);
+ if (i < 0 || p == &ibuf[0])
+ goto noident;
+
+ if (*--p == '\n' && *--p == '\r')
+ p--;
+ *++p = '\0';
+
+ if (tTd(9, 3))
+ printf("getauthinfo: got %s\n", ibuf);
+
+ /* parse result */
+ p = strchr(ibuf, ':');
+ 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 */
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (strncasecmp(p, "other", 5) == 0 &&
+ (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0'))
+ {
+ /* not useful information */
+ goto noident;
+ }
+ 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 -- copy carefully */
+ cleanstrcpy(hbuf, p, MAXNAME);
+ i = strlen(hbuf);
+ hbuf[i++] = '@';
+ strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName);
+ goto postident;
+
+closeident:
+ (void) close(s);
+ clrevent(ev);
+
+noident:
+ if (RealHostName == NULL)
+ {
+ if (tTd(9, 1))
+ printf("getauthinfo: NULL\n");
+ return NULL;
+ }
+ (void) strcpy(hbuf, RealHostName);
+
+postident:
+#if IP_SRCROUTE
+ /*
+ ** Extract IP source routing information.
+ **
+ ** Format of output for a connection from site a through b
+ ** through c to d:
+ ** loose: @site-c@site-b:site-a
+ ** strict: !@site-c@site-b:site-a
+ **
+ ** o - pointer within ipopt_list structure.
+ ** q - pointer within ls/ss rr route data
+ ** p - pointer to hbuf
+ */
+
+ if (RealHostAddr.sa.sa_family == AF_INET)
+ {
+ int ipoptlen, j;
+ u_char *q;
+ u_char *o;
+ struct in_addr addr;
+ struct ipoption ipopt;
+
+ ipoptlen = sizeof ipopt;
+ if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS,
+ (char *) &ipopt, &ipoptlen) < 0)
+ goto noipsr;
+ if (ipoptlen == 0)
+ goto noipsr;
+ o = (u_char *) ipopt.ipopt_list;
+ while (o != NULL && o < (u_char *) &ipopt + ipoptlen)
+ {
+ switch (*o)
+ {
+ case IPOPT_EOL:
+ o = NULL;
+ break;
+
+ case IPOPT_NOP:
+ o++;
+ break;
+
+ case IPOPT_SSRR:
+ case IPOPT_LSRR:
+ p = &hbuf[strlen(hbuf)];
+ sprintf(p, " [%s@%.120s",
+ *o == IPOPT_SSRR ? "!" : "",
+ inet_ntoa(ipopt.ipopt_dst));
+ p += strlen(p);
+
+ /* o[1] is option length */
+ j = *++o / sizeof(struct in_addr) - 1;
+
+ /* q skips length and router pointer to data */
+ q = o + 2;
+ for ( ; j >= 0; j--)
+ {
+ memcpy(&addr, q, sizeof(addr));
+ sprintf(p, "%c%.120s",
+ j ? '@' : ':',
+ inet_ntoa(addr));
+ p += strlen(p);
+ q += sizeof(struct in_addr);
+ }
+ o += *o;
+ break;
+
+ default:
+ /* Skip over option */
+ o += o[1];
+ break;
+ }
+ }
+ strcat(hbuf,"]");
+ goto postipsr;
+ }
+#endif
+
+noipsr:
+ if (RealHostName != NULL && RealHostName[0] != '[')
+ {
+ p = &hbuf[strlen(hbuf)];
+ (void) sprintf(p, " [%.100s]", anynet_ntoa(&RealHostAddr));
+ }
+
+postipsr:
+ if (tTd(9, 1))
+ printf("getauthinfo: %s\n", hbuf);
+ return hbuf;
+}
+ /*
+** 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;
+ struct in_addr in_addr;
+ char *cp;
+ register STAB *s;
+ char hbuf[MAXNAME + 1];
+
+ /*
+ ** 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 == NULL
+ ? "NULL"
+ : s->s_namecanon.nc_cname);
+ errno = s->s_namecanon.nc_errno;
+#if NAMED_BIND
+ h_errno = s->s_namecanon.nc_herrno;
+#endif
+ *statp = s->s_namecanon.nc_stat;
+ if (*statp == EX_TEMPFAIL)
+ {
+ CurEnv->e_status = "4.4.3";
+ message("851 %s: Name server timeout",
+ shortenstring(name, 33));
+ }
+ return s->s_namecanon.nc_cname;
+ }
+
+ /*
+ ** If we are running without a regular network connection (usually
+ ** dial-on-demand) and we are just queueing, we want to avoid DNS
+ ** lookups because those could try to connect to a server.
+ */
+
+ if (CurEnv->e_sendmode == SM_DEFER)
+ {
+ if (tTd(9, 1))
+ printf("host_map_lookup(%s) => DEFERRED\n", name);
+ *statp = EX_TEMPFAIL;
+ return NULL;
+ }
+
+ /*
+ ** 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 */
+ if (strlen(name) < sizeof hbuf)
+ (void) strcpy(hbuf, name);
+ else
+ {
+ bcopy(name, hbuf, sizeof hbuf - 1);
+ hbuf[sizeof hbuf - 1] = '\0';
+ }
+ if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
+ {
+ 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;
+
+ s->s_namecanon.nc_errno = errno;
+#if NAMED_BIND
+ s->s_namecanon.nc_herrno = h_errno;
+ if (tTd(9, 1))
+ printf("FAIL (%d)\n", h_errno);
+ switch (h_errno)
+ {
+ case TRY_AGAIN:
+ if (UseNameServer)
+ {
+ CurEnv->e_status = "4.4.3";
+ message("851 %s: Name server timeout",
+ shortenstring(name, 33));
+ }
+ *statp = EX_TEMPFAIL;
+ break;
+
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ *statp = EX_NOHOST;
+ break;
+
+ case NO_RECOVERY:
+ *statp = EX_SOFTWARE;
+ break;
+
+ default:
+ *statp = EX_UNAVAILABLE;
+ break;
+ }
+#else
+ if (tTd(9, 1))
+ printf("FAIL\n");
+ *statp = EX_NOHOST;
+#endif
+ s->s_namecanon.nc_stat = *statp;
+ return NULL;
+ }
+ }
+ if ((cp = strchr(name, ']')) == NULL)
+ return (NULL);
+ *cp = '\0';
+ in_addr.s_addr = inet_addr(&name[1]);
+
+ /* nope -- ask the name server */
+ hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET);
+ s->s_namecanon.nc_errno = errno;
+#if NAMED_BIND
+ s->s_namecanon.nc_herrno = h_errno;
+#endif
+ s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
+ if (hp == NULL)
+ {
+ s->s_namecanon.nc_stat = *statp = EX_NOHOST;
+ return (NULL);
+ }
+
+ /* found a match -- copy out */
+ cp = map_rewrite(map, (char *) 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;
+}
+ /*
+** ANYNET_NTOA -- convert a network address to printable form.
+**
+** Parameters:
+** sap -- a pointer to a sockaddr structure.
+**
+** Returns:
+** A printable version of that sockaddr.
+*/
+
+#if NETLINK
+# include <net/if_dl.h>
+#endif
+
+char *
+anynet_ntoa(sap)
+ register SOCKADDR *sap;
+{
+ register char *bp;
+ register char *ap;
+ int l;
+ static char buf[100];
+
+ /* check for null/zero family */
+ if (sap == NULL)
+ return "NULLADDR";
+ if (sap->sa.sa_family == 0)
+ return "0";
+
+ switch (sap->sa.sa_family)
+ {
+#if NETUNIX
+ case AF_UNIX:
+ if (sap->sunix.sun_path[0] != '\0')
+ sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path);
+ else
+ sprintf(buf, "[UNIX: localhost]");
+ return buf;
+#endif
+
+#if NETINET
+ case AF_INET:
+ return inet_ntoa(sap->sin.sin_addr);
+#endif
+
+#if NETLINK
+ case AF_LINK:
+ sprintf(buf, "[LINK: %s]",
+ link_ntoa((struct sockaddr_dl *) &sap->sa));
+ return buf;
+#endif
+ default:
+ /* this case is needed when nothing is #defined */
+ /* in order to keep the switch syntactically correct */
+ break;
+ }
+
+ /* 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;
+}
+ /*
+** 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;
+ int saveretry;
+
+#if NAMED_BIND
+ /* shorten name server timeout to avoid higher level timeouts */
+ saveretry = _res.retry;
+ _res.retry = 3;
+#endif /* NAMED_BIND */
+
+ switch (sap->sa.sa_family)
+ {
+#if NETINET
+ case AF_INET:
+ hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr,
+ INADDRSZ,
+ AF_INET);
+ break;
+#endif
+
+#if NETISO
+ case AF_ISO:
+ hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr,
+ sizeof sap->siso.siso_addr,
+ AF_ISO);
+ break;
+#endif
+
+ case AF_UNIX:
+ hp = NULL;
+ break;
+
+ default:
+ hp = sm_gethostbyaddr(sap->sa.sa_data,
+ sizeof sap->sa.sa_data,
+ sap->sa.sa_family);
+ break;
+ }
+
+#if NAMED_BIND
+ _res.retry = saveretry;
+#endif /* NAMED_BIND */
+
+ if (hp != NULL)
+ return (char *) hp->h_name;
+ else
+ {
+ /* produce a dotted quad */
+ static char buf[203];
+
+ (void) sprintf(buf, "[%.200s]", anynet_ntoa(sap));
+ return buf;
+ }
+}
+
+# else /* DAEMON */
+/* code for systems without sophisticated networking */
+
+/*
+** MYHOSTNAME -- stub version for case of no daemon code.
+**
+** Can't convert to upper case here because might be a UUCP name.
+**
+** Mark, you can change this to be anything you want......
+*/
+
+char **
+myhostname(hostbuf, size)
+ char hostbuf[];
+ int size;
+{
+ register FILE *f;
+
+ hostbuf[0] = '\0';
+ f = fopen("/usr/include/whoami", "r");
+ if (f != NULL)
+ {
+ (void) fgets(hostbuf, size, f);
+ fixcrlf(hostbuf, TRUE);
+ (void) fclose(f);
+ }
+ return (NULL);
+}
+ /*
+** 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;
+}
+ /*
+** MAPHOSTNAME -- turn a hostname into canonical form
+**
+** Parameters:
+** 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:
+** mapped host name
+** FALSE otherwise.
+**
+** Side Effects:
+** 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*/
+char *
+host_map_lookup(map, name, avp, statp)
+ MAP *map;
+ char *name;
+ char **avp;
+ char *statp;
+{
+ register struct hostent *hp;
+
+ hp = sm_gethostbyname(name);
+ if (hp != NULL)
+ return hp->h_name;
+ *statp = EX_NOHOST;
+ return NULL;
+}
+
+#endif /* DAEMON */
diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c
new file mode 100644
index 000000000000..2435f0477836
--- /dev/null
+++ b/usr.sbin/sendmail/src/deliver.c
@@ -0,0 +1,3016 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)deliver.c 8.185 (Berkeley) 11/18/95";
+#endif /* not lint */
+
+#include "sendmail.h"
+#include <errno.h>
+#if NAMED_BIND
+#include <resolv.h>
+
+extern int h_errno;
+#endif
+
+#ifdef SMTP
+extern char SmtpError[];
+#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.
+*/
+
+void
+sendall(e, mode)
+ ENVELOPE *e;
+ char mode;
+{
+ register ADDRESS *q;
+ char *owner;
+ int otherowners;
+ register ENVELOPE *ee;
+ ENVELOPE *splitenv = NULL;
+ bool oldverbose = Verbose;
+ bool somedeliveries = FALSE;
+ int pid;
+ extern void sendenvelope();
+
+ /*
+ ** If we have had global, fatal errors, don't bother sending
+ ** the message at all if we are in SMTP mode. Local errors
+ ** (e.g., a single address failing) will still cause the other
+ ** addresses to be sent.
+ */
+
+ if (bitset(EF_FATALERRS, e->e_flags) &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON))
+ {
+ e->e_flags |= EF_CLRQUEUE;
+ return;
+ }
+
+ /* determine actual delivery mode */
+ CurrentLA = getla();
+ if (mode == SM_DEFAULT)
+ {
+ mode = e->e_sendmode;
+ if (mode != SM_VERIFY && mode != SM_DEFER &&
+ shouldqueue(e->e_msgpriority, e->e_ctime))
+ mode = SM_QUEUE;
+ }
+
+ if (tTd(13, 1))
+ {
+ extern void printenvflags();
+
+ printf("\n===== SENDALL: mode %c, id %s, e_from ",
+ mode, e->e_id);
+ printaddr(&e->e_from, FALSE);
+ printf("\te_flags = ");
+ printenvflags(e);
+ 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;
+#ifdef QUEUE
+ queueup(e, mode == SM_QUEUE || mode == SM_DEFER);
+#endif
+ e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE;
+ syserr("554 Too many hops %d (%d max): from %s via %s, to %s",
+ e->e_hopcount, MaxHopCount, e->e_from.q_paddr,
+ RealHostName == NULL ? "localhost" : RealHostName,
+ e->e_sendqueue->q_paddr);
+ e->e_sendqueue->q_status = "5.4.6";
+ 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 (!bitset(EF_METOO, e->e_flags) &&
+ !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, 0, 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 (tTd(13, 30))
+ {
+ printf("Checking ");
+ printaddr(q, FALSE);
+ }
+ if (bitset(QDONTSEND, q->q_flags))
+ {
+ if (tTd(13, 30))
+ printf(" ... QDONTSEND\n");
+ 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 this mailer is expensive, and if we don't
+ ** want to make connections now, just mark these
+ ** addresses and return. This is useful if we
+ ** want to batch connections to reduce load. This
+ ** will cause the messages to be queued up, and a
+ ** daemon will come along to send the messages later.
+ */
+
+ if (bitset(QBADADDR|QQUEUEUP, q->q_flags))
+ {
+ if (tTd(13, 30))
+ printf(" ... QBADADDR|QQUEUEUP\n");
+ continue;
+ }
+ if (NoConnect && !Verbose &&
+ bitnset(M_EXPENSIVE, q->q_mailer->m_flags))
+ {
+ if (tTd(13, 30))
+ printf(" ... expensive\n");
+ q->q_flags |= QQUEUEUP;
+ }
+ else
+ {
+ if (tTd(13, 30))
+ printf(" ... deliverable\n");
+ somedeliveries = TRUE;
+ }
+ }
+
+ 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|EF_SENDRECEIPT|EF_RET_PARAM);
+ ee->e_flags |= EF_NORECEIPT;
+ 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_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;
+ q->q_flags &= ~QQUEUEUP;
+ }
+ }
+ for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (q->q_owner != owner)
+ {
+ q->q_flags |= QDONTSEND;
+ q->q_flags &= ~QQUEUEUP;
+ }
+ else
+ {
+ /* clear DSN parameters */
+ q->q_flags &= ~(QHASNOTIFY|QPINGONSUCCESS);
+ q->q_flags |= QPINGONFAILURE|QPINGONDELAY;
+ }
+ }
+
+ if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags))
+ {
+ char df1buf[20], df2buf[20];
+
+ ee->e_dfp = NULL;
+ strcpy(df1buf, queuename(e, 'd'));
+ strcpy(df2buf, queuename(ee, 'd'));
+ if (link(df1buf, df2buf) < 0)
+ {
+ int saverrno = errno;
+
+ syserr("sendall: link(%s, %s)",
+ df1buf, df2buf);
+ if (saverrno == EEXIST)
+ {
+ if (unlink(df2buf) < 0)
+ {
+ syserr("!sendall: unlink(%s): permanent",
+ df2buf);
+ /*NOTREACHED*/
+ }
+ if (link(df1buf, df2buf) < 0)
+ {
+ syserr("!sendall: link(%s, %s): permanent",
+ df1buf, df2buf);
+ /*NOTREACHED*/
+ }
+ }
+ }
+ }
+#ifdef LOG
+ if (LogLevel > 4)
+ syslog(LOG_INFO, "%s: clone %s, owner=%s",
+ ee->e_id, e->e_id, owner);
+#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;
+ e->e_flags |= EF_NORECEIPT;
+ }
+
+ /* if nothing to be delivered, just queue up everything */
+ if (!somedeliveries && mode != SM_QUEUE && mode != SM_DEFER &&
+ mode != SM_VERIFY)
+ {
+ if (tTd(13, 29))
+ printf("No deliveries: auto-queuing\n");
+ mode = SM_QUEUE;
+ }
+
+# ifdef QUEUE
+ if ((mode == SM_QUEUE || mode == SM_DEFER || mode == SM_FORK ||
+ (mode != SM_VERIFY && SuperSafe)) &&
+ !bitset(EF_INQUEUE, e->e_flags))
+ {
+ /* be sure everything is instantiated in the queue */
+ queueup(e, mode == SM_QUEUE || mode == SM_DEFER);
+ for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
+ queueup(ee, mode == SM_QUEUE || mode == SM_DEFER);
+ }
+#endif /* QUEUE */
+
+ /*
+ ** If we belong in background, fork now.
+ */
+
+ if (tTd(13, 20))
+ printf("sendall: final mode = %c\n", mode);
+ switch (mode)
+ {
+ case SM_VERIFY:
+ Verbose = TRUE;
+ break;
+
+ case SM_QUEUE:
+ case SM_DEFER:
+ queueonly:
+ if (e->e_nrcpts > 0)
+ e->e_flags |= EF_INQUEUE;
+ return;
+
+ case SM_FORK:
+ if (e->e_xfp != NULL)
+ (void) fflush(e->e_xfp);
+
+# if !HASFLOCK
+ /*
+ ** Since fcntl locking has the interesting semantic that
+ ** the lock is owned by a process, not by an open file
+ ** descriptor, we have to flush this to the queue, and
+ ** then restart from scratch in the child.
+ */
+
+ {
+ /* save id for future use */
+ char *qid = e->e_id;
+
+ /* now drop the envelope in the parent */
+ e->e_flags |= EF_INQUEUE;
+ dropenvelope(e);
+
+ /* and reacquire in the child */
+ (void) dowork(qid, TRUE, FALSE, e);
+ }
+
+ return;
+
+# else /* HASFLOCK */
+
+ pid = fork();
+ if (pid < 0)
+ {
+ goto queueonly;
+ }
+ else if (pid > 0)
+ {
+ /* be sure we leave the temp files to our child */
+ /* can't call unlockqueue to avoid unlink of xfp */
+ if (e->e_lockfp != NULL)
+ (void) xfclose(e->e_lockfp, "sendenvelope lockfp", e->e_id);
+ e->e_lockfp = NULL;
+
+ /* close any random open files in the envelope */
+ closexscript(e);
+ if (e->e_dfp != NULL)
+ (void) xfclose(e->e_dfp, "sendenvelope dfp", e->e_id);
+ e->e_dfp = NULL;
+ e->e_id = NULL;
+ e->e_flags &= ~EF_HAS_DF;
+
+ /* catch intermediate zombie */
+ (void) waitfor(pid);
+ return;
+ }
+
+ /* double fork to avoid zombies */
+ pid = fork();
+ if (pid > 0)
+ exit(EX_OK);
+
+ /* be sure we are immune from the terminal */
+ disconnect(1, e);
+
+ /* prevent parent from waiting if there was an error */
+ if (pid < 0)
+ {
+ e->e_flags |= EF_INQUEUE;
+ finis();
+ }
+
+ /*
+ ** 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);
+
+# endif /* HASFLOCK */
+
+ break;
+ }
+
+ if (splitenv != NULL)
+ {
+ if (tTd(13, 2))
+ {
+ printf("\nsendall: Split queue; remaining queue:\n");
+ printaddr(e->e_sendqueue, TRUE);
+ }
+
+ for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
+ {
+ CurEnv = ee;
+ if (mode != SM_VERIFY)
+ openxscript(ee);
+ sendenvelope(ee, mode);
+ dropenvelope(ee);
+ }
+
+ CurEnv = e;
+ }
+ sendenvelope(e, mode);
+ Verbose = oldverbose;
+ if (mode == SM_FORK)
+ finis();
+}
+
+void
+sendenvelope(e, mode)
+ register ENVELOPE *e;
+ char mode;
+{
+ register ADDRESS *q;
+ bool didany;
+
+ if (tTd(13, 10))
+ printf("sendenvelope(%s) e_flags=0x%x\n",
+ e->e_id == NULL ? "[NOQUEUE]" : e->e_id,
+ e->e_flags);
+#ifdef LOG
+ if (LogLevel > 80)
+ syslog(LOG_DEBUG, "%s: sendenvelope, flags=0x%x",
+ e->e_id == NULL ? "[NOQUEUE]" : e->e_id,
+ e->e_flags);
+#endif
+
+ /*
+ ** If we have had global, fatal errors, don't bother sending
+ ** the message at all if we are in SMTP mode. Local errors
+ ** (e.g., a single address failing) will still cause the other
+ ** addresses to be sent.
+ */
+
+ if (bitset(EF_FATALERRS, e->e_flags) &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON))
+ {
+ e->e_flags |= EF_CLRQUEUE;
+ return;
+ }
+
+ /*
+ ** Run through the list and send everything.
+ **
+ ** Set EF_GLOBALERRS so that error messages during delivery
+ ** result in returned mail.
+ */
+
+ e->e_nsent = 0;
+ e->e_flags |= EF_GLOBALERRS;
+ didany = FALSE;
+
+ /* now run through the queue */
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+#if XDEBUG
+ char wbuf[MAXNAME + 20];
+
+ (void) sprintf(wbuf, "sendall(%.*s)", MAXNAME, q->q_paddr);
+ checkfd012(wbuf);
+#endif
+ if (mode == SM_VERIFY)
+ {
+ e->e_to = q->q_paddr;
+ if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
+ {
+ if (q->q_host != NULL && q->q_host[0] != '\0')
+ message("deliverable: mailer %s, host %s, user %s",
+ q->q_mailer->m_name,
+ q->q_host,
+ q->q_user);
+ else
+ message("deliverable: mailer %s, user %s",
+ q->q_mailer->m_name,
+ 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, FALSE);
+ e->e_nsent = 0;
+ }
+# endif /* QUEUE */
+ (void) deliver(e, q);
+ didany = TRUE;
+ }
+ }
+ if (didany)
+ {
+ e->e_dtime = curtime();
+ e->e_ntries++;
+ }
+
+#if XDEBUG
+ checkfd012("end of sendenvelope");
+#endif
+}
+ /*
+** 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);\
+ }\
+}
+ /*
+** 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.
+*/
+
+int
+dofork()
+{
+ register int pid = -1;
+
+ DOFORK(fork);
+ return (pid);
+}
+ /*
+** DELIVER -- Deliver a message to a list of addresses.
+**
+** This routine delivers to everyone on the same host as the
+** user on the head of the list. It is clever about mailers
+** that don't handle multiple users. It is NOT guaranteed
+** that it will deliver to all these addresses however -- so
+** deliver should be called once for each address on the
+** list.
+**
+** Parameters:
+** e -- the envelope to deliver.
+** firstto -- head of the address list to deliver to.
+**
+** Returns:
+** zero -- successfully delivered.
+** else -- some failure, see ExitStat for more info.
+**
+** Side Effects:
+** The standard input is passed off to someone.
+*/
+
+int
+deliver(e, firstto)
+ register ENVELOPE *e;
+ ADDRESS *firstto;
+{
+ char *host; /* host being sent to */
+ char *user; /* user being sent to */
+ char **pvp;
+ register char **mvp;
+ register char *p;
+ register MAILER *m; /* mailer for this recipient */
+ ADDRESS *volatile ctladdr;
+ register MCI *volatile mci;
+ register ADDRESS *to = firstto;
+ volatile bool clever = FALSE; /* running user smtp to this mailer */
+ ADDRESS *volatile tochain = NULL; /* users chain in this mailer call */
+ int rcode; /* response code */
+ char *firstsig; /* signature of firstto */
+ int pid = -1;
+ char *volatile curhost;
+ time_t xstart;
+ int mpvect[2];
+ int rpvect[2];
+ char *pv[MAXPV+1];
+ char tobuf[TOBUFSIZE]; /* text line of to people */
+ char buf[MAXNAME + 1];
+ char rpathbuf[MAXNAME + 1]; /* translated return path */
+ extern int checkcompat();
+ extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int));
+
+ errno = 0;
+ if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags))
+ return (0);
+
+#if NAMED_BIND
+ /* unless interactive, try twice, over a minute */
+ if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
+ {
+ _res.retrans = 30;
+ _res.retry = 2;
+ }
+#endif
+
+ m = to->q_mailer;
+ host = to->q_host;
+ CurEnv = e; /* just in case */
+ e->e_statmsg = NULL;
+#ifdef SMTP
+ SmtpError[0] = '\0';
+#endif
+ xstart = curtime();
+
+ if (tTd(10, 1))
+ printf("\n--deliver, id=%s, mailer=%s, host=`%s', first user=`%s'\n",
+ e->e_id, m->m_name, host, to->q_user);
+ if (tTd(10, 100))
+ printopenfds(FALSE);
+
+ /*
+ ** Do initial argv setup.
+ ** Insert the mailer name. Notice that $x expansion is
+ ** NOT done on the mailer name. Then, if the mailer has
+ ** a picky -f flag, we insert it as appropriate. This
+ ** code does not check for 'pv' overflow; this places a
+ ** manifest lower limit of 4 for MAXPV.
+ ** The from address rewrite is expected to make
+ ** the address relative to the other end.
+ */
+
+ /* rewrite from address, using rewriting rules */
+ rcode = EX_OK;
+ if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
+ p = e->e_sender;
+ else
+ p = e->e_from.q_paddr;
+ (void) strcpy(rpathbuf, remotename(p, m,
+ RF_SENDERADDR|RF_CANONICAL,
+ &rcode, e));
+ define('g', rpathbuf, e); /* translated return path */
+ define('h', host, e); /* to host */
+ Errors = 0;
+ pvp = pv;
+ *pvp++ = m->m_argv[0];
+
+ /* insert -f or -r flag as appropriate */
+ if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags)))
+ {
+ if (bitnset(M_FOPT, m->m_flags))
+ *pvp++ = "-f";
+ else
+ *pvp++ = "-r";
+ *pvp++ = newstr(rpathbuf);
+ }
+
+ /*
+ ** Append the other fixed parts of the argv. These run
+ ** up to the first entry containing "$u". There can only
+ ** be one of these, and there are only a few more slots
+ ** in the pv after it.
+ */
+
+ for (mvp = m->m_argv; (p = *++mvp) != 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 */
+ expand(*mvp, buf, sizeof buf, e);
+ *pvp++ = newstr(buf);
+ if (pvp >= &pv[MAXPV - 3])
+ {
+ syserr("554 Too many parameters to %s before $u", pv[0]);
+ return (-1);
+ }
+ }
+
+ /*
+ ** If we have no substitution for the user name in the argument
+ ** list, we know that we must supply the names otherwise -- and
+ ** SMTP is the answer!!
+ */
+
+ if (*mvp == NULL)
+ {
+ /* running SMTP */
+# ifdef SMTP
+ clever = TRUE;
+ *pvp = NULL;
+# else /* SMTP */
+ /* oops! we don't implement SMTP */
+ syserr("554 SMTP style mailer not implemented");
+ return (EX_SOFTWARE);
+# endif /* SMTP */
+ }
+
+ /*
+ ** At this point *mvp points to the argument with $u. We
+ ** run through our address list and append all the addresses
+ ** we can. If we run out of space, do not fret! We can
+ ** always send another copy later.
+ */
+
+ 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 */
+ if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags))
+ break;
+
+ /* if already sent or not for this host, don't send */
+ 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 */
+ if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2))
+ break;
+
+ if (tTd(10, 1))
+ {
+ printf("\nsend to ");
+ printaddr(to, FALSE);
+ }
+
+ /* compute effective uid/gid when sending */
+ if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags))
+ ctladdr = getctladdr(to);
+
+ if (tTd(10, 2))
+ {
+ printf("ctladdr=");
+ printaddr(ctladdr, FALSE);
+ }
+
+ user = to->q_user;
+ e->e_to = to->q_paddr;
+ if (tTd(10, 5))
+ {
+ printf("deliver: QDONTSEND ");
+ printaddr(to, FALSE);
+ }
+ to->q_flags |= QDONTSEND;
+
+ /*
+ ** Check to see that these people are allowed to
+ ** talk to each other.
+ */
+
+ if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
+ {
+ e->e_flags |= EF_NO_BODY_RETN;
+ to->q_status = "5.2.3";
+ usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
+ giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e);
+ continue;
+ }
+#if NAMED_BIND
+ h_errno = 0;
+#endif
+ rcode = checkcompat(to, e);
+ if (rcode != EX_OK)
+ {
+ markfailure(e, to, NULL, rcode);
+ giveresponse(rcode, m, NULL, ctladdr, xstart, e);
+ continue;
+ }
+
+ /*
+ ** Strip quote bits from names if the mailer is dumb
+ ** about them.
+ */
+
+ if (bitnset(M_STRIPQ, m->m_flags))
+ {
+ stripquotes(user);
+ stripquotes(host);
+ }
+
+ /* hack attack -- delivermail compatibility */
+ if (m == ProgMailer && *user == '|')
+ user++;
+
+ /*
+ ** If an error message has already been given, don't
+ ** bother to send to this address.
+ **
+ ** >>>>>>>>>> This clause assumes that the local mailer
+ ** >> NOTE >> cannot do any further aliasing; that
+ ** >>>>>>>>>> function is subsumed by sendmail.
+ */
+
+ if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
+ continue;
+
+ /* save statistics.... */
+ markstats(e, to);
+
+ /*
+ ** See if this user name is "special".
+ ** If the user name has a slash in it, assume that this
+ ** is a file -- send it off without further ado. Note
+ ** that this type of addresses is not processed along
+ ** with the others, so we fudge on the To person.
+ */
+
+ if (strcmp(m->m_mailer, "[FILE]") == 0)
+ {
+ rcode = mailfile(user, ctladdr, SFF_CREAT, e);
+ giveresponse(rcode, m, NULL, ctladdr, xstart, e);
+ e->e_nsent++;
+ if (rcode == EX_OK)
+ {
+ to->q_flags |= QSENT;
+ if (bitnset(M_LOCALMAILER, m->m_flags) &&
+ (e->e_receiptto != NULL ||
+ bitset(QPINGONSUCCESS, to->q_flags)))
+ {
+ to->q_flags |= QDELIVERED;
+ to->q_status = "2.1.5";
+ fprintf(e->e_xfp, "%s... Successfully delivered\n",
+ to->q_paddr);
+ }
+ }
+ to->q_statdate = curtime();
+ continue;
+ }
+
+ /*
+ ** Address is verified -- add this user to mailer
+ ** argv, and add it to the print list of recipients.
+ */
+
+ /* link together the chain of recipients */
+ to->q_tchain = tochain;
+ tochain = to;
+
+ /* create list of users for error messages */
+ (void) strcat(tobuf, ",");
+ (void) strcat(tobuf, to->q_paddr);
+ define('u', user, e); /* to user */
+ p = to->q_home;
+ if (p == NULL && ctladdr != NULL)
+ p = ctladdr->q_home;
+ define('z', p, e); /* user's home */
+
+ /*
+ ** Expand out this user into argument list.
+ */
+
+ if (!clever)
+ {
+ expand(*mvp, buf, sizeof buf, e);
+ *pvp++ = newstr(buf);
+ if (pvp >= &pv[MAXPV - 2])
+ {
+ /* allow some space for trailing parms */
+ break;
+ }
+ }
+ }
+
+ /* see if any addresses still exist */
+ if (tobuf[0] == '\0')
+ {
+ define('g', (char *) NULL, e);
+ return (0);
+ }
+
+ /* print out messages as full list */
+ e->e_to = tobuf + 1;
+
+ /*
+ ** Fill out any parameters after the $u parameter.
+ */
+
+ while (!clever && *++mvp != NULL)
+ {
+ expand(*mvp, buf, sizeof buf, e);
+ *pvp++ = newstr(buf);
+ if (pvp >= &pv[MAXPV])
+ 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.
+ */
+
+ /*XXX this seems a bit wierd */
+ if (ctladdr == NULL && m != ProgMailer && m != FileMailer &&
+ bitset(QGOODUID, e->e_from.q_flags))
+ ctladdr = &e->e_from;
+
+#if NAMED_BIND
+ if (ConfigLevel < 2)
+ _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */
+#endif
+
+ if (tTd(11, 1))
+ {
+ printf("openmailer:");
+ printav(pv);
+ }
+ errno = 0;
+#if NAMED_BIND
+ h_errno = 0;
+#endif
+
+ CurHostName = NULL;
+
+ /*
+ ** 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;
+ SmtpPhase = NULL;
+ mci = NULL;
+
+#if XDEBUG
+ {
+ char wbuf[MAXLINE];
+
+ /* make absolutely certain 0, 1, and 2 are in use */
+ sprintf(wbuf, "%s... openmailer(%s)",
+ shortenstring(e->e_to, 203), m->m_name);
+ checkfd012(wbuf);
+ }
+#endif
+
+ /* check for 8-bit available */
+ if (bitset(EF_HAS8BIT, e->e_flags) &&
+ bitnset(M_7BITS, m->m_flags) &&
+ (bitset(EF_DONT_MIME, e->e_flags) ||
+ !(bitset(MM_MIME8BIT, MimeMode) ||
+ (bitset(EF_IS_MIME, e->e_flags) &&
+ bitset(MM_CVTMIME, MimeMode)))))
+ {
+ usrerr("554 Cannot send 8-bit data to 7-bit destination");
+ rcode = EX_DATAERR;
+ e->e_status = "5.6.3";
+ goto give_up;
+ }
+
+ /* 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 volatile u_short port = 0;
+
+ if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0')
+ {
+ syserr("null host name for %s mailer", m->m_mailer);
+ rcode = EX_CONFIG;
+ goto give_up;
+ }
+
+ CurHostName = pv[1];
+ curhost = hostsignature(m, pv[1], e);
+
+ if (curhost == NULL || curhost[0] == '\0')
+ {
+ syserr("null host signature for %s", pv[1]);
+ rcode = EX_CONFIG;
+ goto give_up;
+ }
+
+ if (!clever)
+ {
+ syserr("554 non-clever IPC");
+ rcode = EX_CONFIG;
+ goto give_up;
+ }
+ if (pv[2] != NULL)
+ {
+ port = htons(atoi(pv[2]));
+ if (port == 0)
+ {
+ struct servent *sp = getservbyname(pv[2], "tcp");
+
+ if (sp == NULL)
+ syserr("Service %s unknown", pv[2]);
+ else
+ port = sp->s_port;
+ }
+ }
+tryhost:
+ while (*curhost != '\0')
+ {
+ register char *p;
+ static char hostbuf[MAXNAME + 1];
+
+ /* pull the next host from the signature */
+ p = strchr(curhost, ':');
+ if (p == NULL)
+ p = &curhost[strlen(curhost)];
+ if (p == curhost)
+ {
+ syserr("deliver: null host name in signature");
+ curhost++;
+ continue;
+ }
+ 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, FALSE);
+ }
+ CurHostName = mci->mci_host;
+ message("Using cached %sSMTP connection to %s via %s...",
+ bitset(MCIF_ESMTP, mci->mci_flags) ? "E" : "",
+ hostbuf, m->m_name);
+ 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 via %s...",
+ hostbuf, m->m_name);
+ i = makeconnection(hostbuf, port, mci,
+ bitnset(M_SECURE_PORT, m->m_flags));
+ mci->mci_lastuse = curtime();
+ mci->mci_exitstat = i;
+ mci->mci_errno = errno;
+#if NAMED_BIND
+ mci->mci_herrno = h_errno;
+#endif
+ if (i == EX_OK)
+ {
+ mci->mci_state = MCIS_OPENING;
+ mci_cache(mci);
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d == CONNECT %s\n",
+ getpid(), hostbuf);
+ break;
+ }
+ else if (tTd(11, 1))
+ printf("openmailer: makeconnection => stat=%d, errno=%d\n",
+ i, errno);
+
+ /* enter status of this host */
+ setstat(i);
+
+ /* should print some message here for -v mode */
+ }
+ if (mci == NULL)
+ {
+ syserr("deliver: no host name");
+ rcode = EX_OSERR;
+ goto give_up;
+ }
+ mci->mci_pid = 0;
+#else /* no DAEMON */
+ syserr("554 openmailer: no IPC");
+ if (tTd(11, 1))
+ printf("openmailer: NULL\n");
+ rcode = EX_UNAVAILABLE;
+ goto give_up;
+#endif /* DAEMON */
+ }
+ else
+ {
+ /* flush any expired connections */
+ (void) mci_scan(NULL);
+
+ /* announce the connection to verbose listeners */
+ if (host == NULL || host[0] == '\0')
+ message("Connecting to %s...", m->m_name);
+ else
+ message("Connecting to %s via %s...", host, m->m_name);
+ if (TrafficLogFile != NULL)
+ {
+ char **av;
+
+ fprintf(TrafficLogFile, "%05d === EXEC", getpid());
+ for (av = pv; *av != NULL; av++)
+ fprintf(TrafficLogFile, " %s", *av);
+ fprintf(TrafficLogFile, "\n");
+ }
+
+ /* create a pipe to shove the mail through */
+ if (pipe(mpvect) < 0)
+ {
+ syserr("%s... openmailer(%s): pipe (to mailer)",
+ shortenstring(e->e_to, 203), 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 */
+#ifdef SMTP
+ if (clever && pipe(rpvect) < 0)
+ {
+ syserr("%s... openmailer(%s): pipe (from mailer)",
+ shortenstring(e->e_to, 203), 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;
+ }
+#endif
+
+ /*
+ ** 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) setsignal(SIGCHLD, SIG_DFL);
+# endif /* SIGCHLD */
+ DOFORK(FORK);
+ /* pid is set by DOFORK */
+ if (pid < 0)
+ {
+ /* failure */
+ syserr("%s... openmailer(%s): cannot fork",
+ shortenstring(e->e_to, 203), m->m_name);
+ (void) close(mpvect[0]);
+ (void) close(mpvect[1]);
+#ifdef SMTP
+ if (clever)
+ {
+ (void) close(rpvect[0]);
+ (void) close(rpvect[1]);
+ }
+#endif
+ if (tTd(11, 1))
+ printf("openmailer: NULL\n");
+ rcode = EX_OSERR;
+ goto give_up;
+ }
+ else if (pid == 0)
+ {
+ int i;
+ int saveerrno;
+ struct stat stb;
+ extern int DtableSize;
+
+ if (e->e_lockfp != NULL)
+ (void) close(fileno(e->e_lockfp));
+
+ /* child -- set up input & exec mailer */
+ (void) setsignal(SIGINT, SIG_IGN);
+ (void) setsignal(SIGHUP, SIG_IGN);
+ (void) setsignal(SIGTERM, SIG_DFL);
+
+ if (m != FileMailer || stat(tochain->q_user, &stb) < 0)
+ stb.st_mode = 0;
+
+ /* tweak niceness */
+ if (m->m_nice != 0)
+ nice(m->m_nice);
+
+ /* reset group id */
+ if (bitnset(M_SPECIFIC_UID, m->m_flags))
+ (void) setgid(m->m_gid);
+ else if (bitset(S_ISGID, stb.st_mode))
+ (void) setgid(stb.st_gid);
+ else if (ctladdr != NULL && ctladdr->q_gid != 0)
+ {
+ if (!DontInitGroups)
+ (void) initgroups(ctladdr->q_ruser != NULL ?
+ ctladdr->q_ruser : ctladdr->q_user,
+ ctladdr->q_gid);
+ (void) setgid(ctladdr->q_gid);
+ }
+ else
+ {
+ if (!DontInitGroups)
+ (void) initgroups(DefUser, DefGid);
+ if (m->m_gid == 0)
+ (void) setgid(DefGid);
+ else
+ (void) setgid(m->m_gid);
+ }
+
+ /* reset user id */
+ endpwent();
+ if (bitnset(M_SPECIFIC_UID, m->m_flags))
+ {
+#if USESETEUID
+ (void) seteuid(m->m_uid);
+#else
+# if HASSETREUID
+ (void) setreuid(-1, m->m_uid);
+# else
+ if (m->m_uid != geteuid())
+ (void) setuid(m->m_uid);
+# endif
+#endif
+ }
+ else if (bitset(S_ISUID, stb.st_mode))
+ (void) setuid(stb.st_uid);
+ else if (ctladdr != NULL && ctladdr->q_uid != 0)
+ (void) setuid(ctladdr->q_uid);
+ else
+ {
+ if (m->m_uid == 0)
+ (void) setuid(DefUid);
+ else
+ (void) setuid(m->m_uid);
+ }
+
+ if (tTd(11, 2))
+ printf("openmailer: running as r/euid=%d/%d\n",
+ getuid(), geteuid());
+
+ /* move into some "safe" directory */
+ if (m->m_execdir != NULL)
+ {
+ char *p, *q;
+ char buf[MAXLINE + 1];
+
+ for (p = m->m_execdir; p != NULL; p = q)
+ {
+ q = strchr(p, ':');
+ if (q != NULL)
+ *q = '\0';
+ expand(p, buf, sizeof buf, 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 */
+#ifdef SMTP
+ if (clever)
+ {
+ (void) close(rpvect[0]);
+ if (dup2(rpvect[1], STDOUT_FILENO) < 0)
+ {
+ syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",
+ shortenstring(e->e_to, 203),
+ m->m_name, rpvect[1]);
+ _exit(EX_OSERR);
+ }
+ (void) close(rpvect[1]);
+ }
+ else if (OpMode == MD_SMTP || OpMode == MD_DAEMON ||
+ HoldErrs || DisConnected)
+ {
+ /* put mailer output in transcript */
+ if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0)
+ {
+ syserr("%s... openmailer(%s): cannot dup xscript %d for stdout",
+ shortenstring(e->e_to, 203),
+ m->m_name, fileno(e->e_xfp));
+ _exit(EX_OSERR);
+ }
+ }
+#endif
+ if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
+ {
+ syserr("%s... openmailer(%s): cannot dup stdout for stderr",
+ shortenstring(e->e_to, 203), 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",
+ shortenstring(e->e_to, 203),
+ m->m_name, mpvect[0]);
+ _exit(EX_OSERR);
+ }
+ (void) close(mpvect[0]);
+
+ /* 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);
+ }
+
+ /* run disconnected from terminal */
+ (void) setsid();
+
+ /* try to execute the mailer */
+ execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) UserEnviron);
+ saveerrno = errno;
+ syserr("Cannot exec %s", m->m_mailer);
+ if (bitnset(M_LOCALMAILER, m->m_flags) ||
+ 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 (mci->mci_out == NULL)
+ {
+ syserr("deliver: cannot create mailer output channel, fd=%d",
+ mpvect[1]);
+ (void) close(mpvect[1]);
+#ifdef SMTP
+ if (clever)
+ {
+ (void) close(rpvect[0]);
+ (void) close(rpvect[1]);
+ }
+#endif
+ rcode = EX_OSERR;
+ goto give_up;
+ }
+#ifdef SMTP
+ if (clever)
+ {
+ (void) close(rpvect[1]);
+ mci->mci_in = fdopen(rpvect[0], "r");
+ if (mci->mci_in == NULL)
+ {
+ syserr("deliver: cannot create mailer input channel, fd=%d",
+ mpvect[1]);
+ (void) close(rpvect[0]);
+ fclose(mci->mci_out);
+ mci->mci_out = NULL;
+ rcode = EX_OSERR;
+ goto give_up;
+ }
+ }
+ else
+#endif
+ {
+ mci->mci_flags |= MCIF_TEMP;
+ mci->mci_in = NULL;
+ }
+ }
+
+ /*
+ ** If we are in SMTP opening state, send initial protocol.
+ */
+
+ if (bitnset(M_7BITS, m->m_flags) &&
+ (!clever || mci->mci_state == MCIS_CLOSED))
+ mci->mci_flags |= MCIF_7BIT;
+#ifdef SMTP
+ if (clever && mci->mci_state != MCIS_CLOSED)
+ smtpinit(m, mci, e);
+#endif
+
+ if (bitset(EF_HAS8BIT, e->e_flags) &&
+ !bitset(EF_DONT_MIME, e->e_flags) &&
+ bitnset(M_7BITS, m->m_flags))
+ mci->mci_flags |= MCIF_CVT8TO7;
+ else
+ mci->mci_flags &= ~MCIF_CVT8TO7;
+
+ if (tTd(11, 1))
+ {
+ printf("openmailer: ");
+ mci_dump(mci, FALSE);
+ }
+
+ if (mci->mci_state != MCIS_OPEN)
+ {
+ /* couldn't open the mailer */
+ rcode = mci->mci_exitstat;
+ errno = mci->mci_errno;
+#if NAMED_BIND
+ h_errno = mci->mci_herrno;
+#endif
+ if (rcode == EX_OK)
+ {
+ /* shouldn't happen */
+ syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s",
+ rcode, mci->mci_state, firstsig);
+ rcode = EX_SOFTWARE;
+ }
+#ifdef DAEMON
+ else if (curhost != NULL && *curhost != '\0')
+ {
+ /* try next MX site */
+ goto tryhost;
+ }
+#endif
+ }
+ else if (!clever)
+ {
+ /*
+ ** Format and send message.
+ */
+
+ putfromline(mci, e);
+ (*e->e_puthdr)(mci, e->e_header, e);
+ (*e->e_putbody)(mci, 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)
+ {
+ register char *t = tobuf;
+ register int i;
+
+ /* 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, mci, i);
+ giveresponse(i, m, mci, ctladdr, xstart, e);
+ }
+ else
+ {
+ *t++ = ',';
+ for (p = to->q_paddr; *p; *t++ = *p++)
+ continue;
+ *t = '\0';
+ }
+ }
+
+ /* 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 != NULL && *curhost != '\0')
+ {
+ /* try next MX site */
+ goto tryhost;
+ }
+ }
+#else /* not SMTP */
+ {
+ syserr("554 deliver: need SMTP compiled to use clever mailer");
+ rcode = EX_CONFIG;
+ goto give_up;
+ }
+#endif /* SMTP */
+#if NAMED_BIND
+ if (ConfigLevel < 2)
+ _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */
+#endif
+
+ /* arrange a return receipt if requested */
+ if (rcode == EX_OK && 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.
+ ** If we got a temporary failure, arrange to queue the
+ ** addressees.
+ */
+
+ give_up:
+ if (tobuf[0] != '\0')
+ giveresponse(rcode, m, mci, ctladdr, xstart, e);
+ for (to = tochain; to != NULL; to = to->q_tchain)
+ {
+ /* see if address already marked */
+ if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
+ continue;
+
+ /* mark bad addresses */
+ if (rcode != EX_OK)
+ {
+ markfailure(e, to, mci, rcode);
+ continue;
+ }
+
+ /* successful delivery */
+ to->q_flags |= QSENT;
+ to->q_statdate = curtime();
+ e->e_nsent++;
+ if (bitnset(M_LOCALMAILER, m->m_flags) &&
+ (e->e_receiptto != NULL ||
+ bitset(QPINGONSUCCESS, to->q_flags)))
+ {
+ to->q_flags |= QDELIVERED;
+ to->q_status = "2.1.5";
+ fprintf(e->e_xfp, "%s... Successfully delivered\n",
+ to->q_paddr);
+ }
+ else if (bitset(QPINGONSUCCESS, to->q_flags) &&
+ bitset(QPRIMARY, to->q_flags) &&
+ !bitset(MCIF_DSN, mci->mci_flags))
+ {
+ to->q_flags |= QRELAYED;
+ fprintf(e->e_xfp, "%s... relayed; expect no further notifications\n",
+ to->q_paddr);
+ }
+ }
+
+ /*
+ ** Restore state and return.
+ */
+
+#if XDEBUG
+ {
+ char wbuf[MAXLINE];
+
+ /* make absolutely certain 0, 1, and 2 are in use */
+ sprintf(wbuf, "%s... end of deliver(%s)",
+ e->e_to == NULL ? "NO-TO-LIST"
+ : shortenstring(e->e_to, 203),
+ m->m_name);
+ checkfd012(wbuf);
+ }
+#endif
+
+ errno = 0;
+ define('g', (char *) NULL, e);
+ return (rcode);
+}
+ /*
+** MARKFAILURE -- mark a failure on a specific address.
+**
+** Parameters:
+** e -- the envelope we are sending.
+** q -- the address to mark.
+** mci -- mailer connection information.
+** rcode -- the code signifying the particular failure.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** marks the address (and possibly the envelope) with the
+** failure so that an error will be returned or
+** the message will be queued, as appropriate.
+*/
+
+void
+markfailure(e, q, mci, rcode)
+ register ENVELOPE *e;
+ register ADDRESS *q;
+ register MCI *mci;
+ int rcode;
+{
+ char *stat = NULL;
+
+ switch (rcode)
+ {
+ case EX_OK:
+ break;
+
+ case EX_TEMPFAIL:
+ case EX_IOERR:
+ case EX_OSERR:
+ q->q_flags |= QQUEUEUP;
+ break;
+
+ default:
+ q->q_flags |= QBADADDR;
+ break;
+ }
+
+ /* find most specific error code possible */
+ if (q->q_status == NULL && mci != NULL)
+ q->q_status = mci->mci_status;
+ if (q->q_status == NULL)
+ q->q_status = e->e_status;
+ if (q->q_status == NULL)
+ {
+ switch (rcode)
+ {
+ case EX_USAGE:
+ stat = "5.5.4";
+ break;
+
+ case EX_DATAERR:
+ stat = "5.5.2";
+ break;
+
+ case EX_NOUSER:
+ stat = "5.1.1";
+ break;
+
+ case EX_NOHOST:
+ stat = "5.1.2";
+ break;
+
+ case EX_NOINPUT:
+ case EX_CANTCREAT:
+ case EX_NOPERM:
+ stat = "5.3.0";
+ break;
+
+ case EX_UNAVAILABLE:
+ case EX_SOFTWARE:
+ case EX_OSFILE:
+ case EX_PROTOCOL:
+ case EX_CONFIG:
+ stat = "5.5.0";
+ break;
+
+ case EX_OSERR:
+ case EX_IOERR:
+ stat = "4.5.0";
+ break;
+
+ case EX_TEMPFAIL:
+ stat = "4.2.0";
+ break;
+ }
+ if (stat != NULL)
+ q->q_status = stat;
+ }
+
+ q->q_statdate = curtime();
+ if (CurHostName != NULL && CurHostName[0] != '\0')
+ q->q_statmta = newstr(CurHostName);
+ if (rcode != EX_OK && q->q_rstatus == NULL &&
+ q->q_mailer != NULL && q->q_mailer->m_diagtype != NULL &&
+ strcasecmp(q->q_mailer->m_diagtype, "UNIX") == 0)
+ {
+ char buf[30];
+
+ (void) sprintf(buf, "%d", rcode);
+ q->q_rstatus = newstr(buf);
+ }
+}
+ /*
+** ENDMAILER -- Wait for mailer to terminate.
+**
+** We should never get fatal errors (e.g., segmentation
+** violation), so we report those specially. For other
+** errors, we choose a status message (into statmsg),
+** and if it represents an error, we print it.
+**
+** Parameters:
+** pid -- pid of mailer.
+** e -- the current envelope.
+** pv -- the parameter vector that invoked the mailer
+** (for error messages).
+**
+** Returns:
+** exit code of mailer.
+**
+** Side Effects:
+** none.
+*/
+
+int
+endmailer(mci, e, pv)
+ register MCI *mci;
+ register ENVELOPE *e;
+ char **pv;
+{
+ int st;
+
+ /* close any connections */
+ if (mci->mci_in != NULL)
+ (void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in");
+ if (mci->mci_out != NULL)
+ (void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out");
+ mci->mci_in = mci->mci_out = NULL;
+ mci->mci_state = MCIS_CLOSED;
+
+ /* in the IPC case there is nothing to wait for */
+ if (mci->mci_pid == 0)
+ return (EX_OK);
+
+ /* wait for the mailer process to die and collect status */
+ st = waitfor(mci->mci_pid);
+ if (st == -1)
+ {
+ syserr("endmailer %s: wait", pv[0]);
+ return (EX_SOFTWARE);
+ }
+
+ if (WIFEXITED(st))
+ {
+ /* normal death -- return status */
+ return (WEXITSTATUS(st));
+ }
+
+ /* it died a horrid death */
+ syserr("451 mailer %s died with signal %o",
+ mci->mci_mailer->m_name, st);
+
+ /* log the arguments */
+ if (pv != NULL && e->e_xfp != NULL)
+ {
+ register char **av;
+
+ fprintf(e->e_xfp, "Arguments:");
+ for (av = pv; *av != NULL; av++)
+ fprintf(e->e_xfp, " %s", *av);
+ fprintf(e->e_xfp, "\n");
+ }
+
+ ExitStat = EX_TEMPFAIL;
+ return (EX_TEMPFAIL);
+}
+ /*
+** GIVERESPONSE -- Interpret an error response from a mailer
+**
+** Parameters:
+** stat -- the status code from the mailer (high byte
+** only; core dumps must have been taken care of
+** already).
+** 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.
+** ctladdr -- the controlling address for the recipient
+** address(es).
+** xstart -- the transaction start time, for computing
+** transaction delays.
+** e -- the current envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Errors may be incremented.
+** ExitStat may be set.
+*/
+
+void
+giveresponse(stat, m, mci, ctladdr, xstart, e)
+ int stat;
+ register MAILER *m;
+ register MCI *mci;
+ ADDRESS *ctladdr;
+ time_t xstart;
+ ENVELOPE *e;
+{
+ register const char *statmsg;
+ extern char *SysExMsg[];
+ register int i;
+ extern int N_SysEx;
+ char buf[MAXLINE];
+
+ /*
+ ** Compute status message from code.
+ */
+
+ i = stat - EX__BASE;
+ if (stat == 0)
+ {
+ statmsg = "250 Sent";
+ if (e->e_statmsg != NULL)
+ {
+ (void) sprintf(buf, "%s (%s)",
+ statmsg, shortenstring(e->e_statmsg, 403));
+ statmsg = buf;
+ }
+ }
+ else if (i < 0 || i > N_SysEx)
+ {
+ (void) sprintf(buf, "554 unknown mailer error %d", stat);
+ stat = EX_UNAVAILABLE;
+ statmsg = buf;
+ }
+ else if (stat == EX_TEMPFAIL)
+ {
+ (void) strcpy(buf, SysExMsg[i] + 1);
+#if NAMED_BIND
+ if (h_errno == TRY_AGAIN)
+ statmsg = errstring(h_errno+E_DNSBASE);
+ else
+#endif
+ {
+ if (errno != 0)
+ statmsg = errstring(errno);
+ else
+ {
+#ifdef SMTP
+ statmsg = SmtpError;
+#else /* SMTP */
+ statmsg = NULL;
+#endif /* SMTP */
+ }
+ }
+ if (statmsg != NULL && statmsg[0] != '\0')
+ {
+ (void) strcat(buf, ": ");
+ (void) strcat(buf, statmsg);
+ }
+ statmsg = buf;
+ }
+#if NAMED_BIND
+ else if (stat == EX_NOHOST && h_errno != 0)
+ {
+ statmsg = errstring(h_errno + E_DNSBASE);
+ (void) sprintf(buf, "%s (%s)", SysExMsg[i] + 1, statmsg);
+ statmsg = buf;
+ }
+#endif
+ else
+ {
+ statmsg = SysExMsg[i];
+ if (*statmsg++ == ':')
+ {
+ (void) sprintf(buf, "%s: %s", statmsg, errstring(errno));
+ statmsg = buf;
+ }
+ }
+
+ /*
+ ** Print the message as appropriate
+ */
+
+ if (stat == EX_OK || stat == EX_TEMPFAIL)
+ {
+ extern char MsgBuf[];
+
+ message("%s", &statmsg[4]);
+ if (stat == EX_TEMPFAIL && e->e_xfp != NULL)
+ fprintf(e->e_xfp, "%s\n", &MsgBuf[4]);
+ }
+ else
+ {
+ char mbuf[8];
+
+ Errors++;
+ sprintf(mbuf, "%.3s %%s", statmsg);
+ usrerr(mbuf, &statmsg[4]);
+ }
+
+ /*
+ ** Final cleanup.
+ ** Log a record of the transaction. Compute the new
+ ** ExitStat -- if we already had an error, stick with
+ ** that.
+ */
+
+ if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
+ logdelivery(m, mci, &statmsg[4], ctladdr, xstart, e);
+
+ if (tTd(11, 2))
+ printf("giveresponse: stat=%d, e->e_message=%s\n",
+ stat, e->e_message == NULL ? "<NULL>" : e->e_message);
+
+ if (stat != EX_TEMPFAIL)
+ setstat(stat);
+ if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL))
+ {
+ if (e->e_message != NULL)
+ free(e->e_message);
+ e->e_message = newstr(&statmsg[4]);
+ }
+ errno = 0;
+#if NAMED_BIND
+ h_errno = 0;
+#endif
+}
+ /*
+** LOGDELIVERY -- log the delivery in the system log
+**
+** Care is taken to avoid logging lines that are too long, because
+** some versions of syslog have an unfortunate proclivity for core
+** dumping. This is a hack, to be sure, that is at best empirical.
+**
+** Parameters:
+** 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.
+** ctladdr -- the controlling address for the to list.
+** xstart -- the transaction start time, used for
+** computing transaction delay.
+** e -- the current envelope.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** none
+*/
+
+#define SPACELEFT(bp) (sizeof buf - ((bp) - buf))
+
+void
+logdelivery(m, mci, stat, ctladdr, xstart, e)
+ MAILER *m;
+ register MCI *mci;
+ const char *stat;
+ ADDRESS *ctladdr;
+ time_t xstart;
+ register ENVELOPE *e;
+{
+# ifdef LOG
+ register char *bp;
+ register char *p;
+ int l;
+ char buf[1024];
+
+# if (SYSLOG_BUFSIZE) >= 256
+ /* ctladdr: max 106 bytes */
+ bp = buf;
+ if (ctladdr != NULL)
+ {
+ strcpy(bp, ", ctladdr=");
+ strcat(bp, shortenstring(ctladdr->q_paddr, 83));
+ bp += strlen(bp);
+ if (bitset(QGOODUID, ctladdr->q_flags))
+ {
+ (void) snprintf(bp, SPACELEFT(bp), " (%d/%d)",
+ ctladdr->q_uid, ctladdr->q_gid);
+ bp += strlen(bp);
+ }
+ }
+
+ /* delay & xdelay: max 41 bytes */
+ snprintf(bp, SPACELEFT(bp), ", delay=%s",
+ pintvl(curtime() - e->e_ctime, TRUE));
+ bp += strlen(bp);
+
+ if (xstart != (time_t) 0)
+ {
+ snprintf(bp, SPACELEFT(bp), ", xdelay=%s",
+ pintvl(curtime() - xstart, TRUE));
+ bp += strlen(bp);
+ }
+
+ /* mailer: assume about 19 bytes (max 10 byte mailer name) */
+ if (m != NULL)
+ {
+ snprintf(bp, SPACELEFT(bp), ", mailer=%s", m->m_name);
+ bp += strlen(bp);
+ }
+
+ /* relay: max 66 bytes for IPv4 addresses */
+ if (mci != NULL && mci->mci_host != NULL)
+ {
+# ifdef DAEMON
+ extern SOCKADDR CurHostAddr;
+# endif
+
+ snprintf(bp, SPACELEFT(bp), ", relay=%s",
+ shortenstring(mci->mci_host, 40));
+ bp += strlen(bp);
+
+# ifdef DAEMON
+ if (CurHostAddr.sa.sa_family != 0)
+ {
+ snprintf(bp, SPACELEFT(bp), " [%s]",
+ anynet_ntoa(&CurHostAddr));
+ }
+# endif
+ }
+ else if (strcmp(stat, "queued") != 0)
+ {
+ char *p = macvalue('h', e);
+
+ if (p != NULL && p[0] != '\0')
+ {
+ snprintf(bp, SPACELEFT(bp), ", relay=%s",
+ shortenstring(p, 40));
+ }
+ }
+ bp += strlen(bp);
+
+#define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4)
+#if (STATLEN) < 63
+# undef STATLEN
+# define STATLEN 63
+#endif
+#if (STATLEN) > 203
+# undef STATLEN
+# define STATLEN 203
+#endif
+
+ /* stat: max 210 bytes */
+ if ((bp - buf) > (sizeof buf - ((STATLEN) + 20)))
+ {
+ /* desperation move -- truncate data */
+ bp = buf + sizeof buf - ((STATLEN) + 17);
+ strcpy(bp, "...");
+ bp += 3;
+ }
+
+ (void) strcpy(bp, ", stat=");
+ bp += strlen(bp);
+
+ (void) strcpy(bp, shortenstring(stat, (STATLEN)));
+
+ /* id, to: max 13 + TOBUFSIZE bytes */
+ l = SYSLOG_BUFSIZE - 100 - strlen(buf);
+ p = e->e_to;
+ while (strlen(p) >= (SIZE_T) l)
+ {
+ register char *q = strchr(p + l, ',');
+
+ if (q == NULL)
+ break;
+ syslog(LOG_INFO, "%s: to=%.*s [more]%s",
+ e->e_id, ++q - p, p, buf);
+ p = q;
+ }
+ syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf);
+
+# else /* we have a very short log buffer size */
+
+ l = SYSLOG_BUFSIZE - 85;
+ p = e->e_to;
+ while (strlen(p) >= l)
+ {
+ register char *q = strchr(p + l, ',');
+
+ if (q == NULL)
+ break;
+ syslog(LOG_INFO, "%s: to=%.*s [more]",
+ e->e_id, ++q - p, p);
+ p = q;
+ }
+ syslog(LOG_INFO, "%s: to=%s", e->e_id, p);
+
+ if (ctladdr != NULL)
+ {
+ bp = buf;
+ strcpy(buf, "ctladdr=");
+ bp += strlen(buf);
+ strcpy(bp, shortenstring(ctladdr->q_paddr, 83));
+ bp += strlen(buf);
+ if (bitset(QGOODUID, ctladdr->q_flags))
+ {
+ (void) sprintf(bp, " (%d/%d)",
+ ctladdr->q_uid, ctladdr->q_gid);
+ bp += strlen(bp);
+ }
+ syslog(LOG_INFO, "%s: %s", e->e_id, buf);
+ }
+ bp = buf;
+ sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+ bp += strlen(bp);
+ if (xstart != (time_t) 0)
+ {
+ sprintf(bp, ", xdelay=%s", pintvl(curtime() - xstart, TRUE));
+ bp += strlen(bp);
+ }
+
+ if (m != NULL)
+ {
+ sprintf(bp, ", mailer=%s", m->m_name);
+ bp += strlen(bp);
+ }
+ syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf);
+
+ buf[0] = '\0';
+ if (mci != NULL && mci->mci_host != NULL)
+ {
+# ifdef DAEMON
+ extern SOCKADDR CurHostAddr;
+# endif
+
+ sprintf(buf, "relay=%.100s", mci->mci_host);
+
+# ifdef DAEMON
+ if (CurHostAddr.sa.sa_family != 0)
+ sprintf(bp, " [%.100s]", anynet_ntoa(&CurHostAddr));
+# endif
+ }
+ else if (strcmp(stat, "queued") != 0)
+ {
+ char *p = macvalue('h', e);
+
+ if (p != NULL && p[0] != '\0')
+ sprintf(buf, "relay=%.100s", p);
+ }
+ if (buf[0] != '\0')
+ syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf);
+
+ syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63));
+# endif /* short log buffer */
+# endif /* LOG */
+}
+
+#undef SPACELEFT
+ /*
+** PUTFROMLINE -- output a UNIX-style from line (or whatever)
+**
+** This can be made an arbitrary message separator by changing $l
+**
+** One of the ugliest hacks seen by human eyes is contained herein:
+** UUCP wants those stupid "remote from <host>" lines. Why oh why
+** does a well-meaning programmer such as myself have to deal with
+** this kind of antique garbage????
+**
+** Parameters:
+** mci -- the connection information.
+** e -- the envelope.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** outputs some text to fp.
+*/
+
+void
+putfromline(mci, e)
+ register MCI *mci;
+ ENVELOPE *e;
+{
+ char *template = UnixFromLine;
+ char buf[MAXLINE];
+
+ if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
+ return;
+
+ if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
+ {
+ char *bang;
+ char xbuf[MAXLINE];
+
+ expand("\201g", buf, sizeof buf, e);
+ bang = strchr(buf, '!');
+ if (bang == NULL)
+ {
+ errno = 0;
+ syserr("554 No ! in UUCP From address! (%s given)", buf);
+ }
+ else
+ {
+ *bang++ = '\0';
+ (void) sprintf(xbuf, "From %.800s \201d remote from %.100s\n",
+ bang, buf);
+ template = xbuf;
+ }
+ }
+ expand(template, buf, sizeof buf, e);
+ putxline(buf, mci, PXLF_NOTHINGSPECIAL);
+}
+ /*
+** PUTBODY -- put the body of a message.
+**
+** Parameters:
+** mci -- the connection information.
+** e -- the envelope to put out.
+** separator -- if non-NULL, a message separator that must
+** not be permitted in the resulting message.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** The message is written onto fp.
+*/
+
+/* values for output state variable */
+#define OS_HEAD 0 /* at beginning of line */
+#define OS_CR 1 /* read a carriage return */
+#define OS_INLINE 2 /* putting rest of line */
+
+void
+putbody(mci, e, separator)
+ register MCI *mci;
+ register ENVELOPE *e;
+ char *separator;
+{
+ char buf[MAXLINE];
+
+ /*
+ ** Output the body of the message
+ */
+
+ if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags))
+ {
+ char *df = queuename(e, 'd');
+
+ e->e_dfp = fopen(df, "r");
+ if (e->e_dfp == NULL)
+ syserr("putbody: Cannot open %s for %s from %s",
+ df, e->e_to, e->e_from.q_paddr);
+ }
+ if (e->e_dfp == NULL)
+ {
+ if (bitset(MCIF_INHEADER, mci->mci_flags))
+ {
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ }
+ putline("<<< No Message Collected >>>", mci);
+ goto endofmessage;
+ }
+ if (e->e_dfino == (ino_t) 0)
+ {
+ struct stat stbuf;
+
+ if (fstat(fileno(e->e_dfp), &stbuf) < 0)
+ e->e_dfino = -1;
+ else
+ {
+ e->e_dfdev = stbuf.st_dev;
+ e->e_dfino = stbuf.st_ino;
+ }
+ }
+ rewind(e->e_dfp);
+
+#if MIME8TO7
+ if (bitset(MCIF_CVT8TO7, mci->mci_flags))
+ {
+ char *boundaries[MAXMIMENESTING + 1];
+
+ /*
+ ** Do 8 to 7 bit MIME conversion.
+ */
+
+ /* make sure it looks like a MIME message */
+ if (hvalue("MIME-Version", e->e_header) == NULL)
+ putline("MIME-Version: 1.0", mci);
+
+ if (hvalue("Content-Type", e->e_header) == NULL)
+ {
+ sprintf(buf, "Content-Type: text/plain; charset=%s",
+ defcharset(e));
+ putline(buf, mci);
+ }
+
+ /* now do the hard work */
+ boundaries[0] = NULL;
+ mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
+ }
+ else
+#endif
+ {
+ int ostate;
+ register char *bp;
+ register char *pbp;
+ register int c;
+ int padc;
+ char *buflim;
+ int pos = 0;
+ char peekbuf[10];
+
+ /* we can pass it through unmodified */
+ if (bitset(MCIF_INHEADER, mci->mci_flags))
+ {
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ }
+
+ /* determine end of buffer; allow for short mailer lines */
+ buflim = &buf[sizeof buf - 1];
+ if (mci->mci_mailer->m_linelimit > 0 &&
+ mci->mci_mailer->m_linelimit < sizeof buf - 1)
+ buflim = &buf[mci->mci_mailer->m_linelimit - 1];
+
+ /* copy temp file to output with mapping */
+ ostate = OS_HEAD;
+ bp = buf;
+ pbp = peekbuf;
+ while (!ferror(mci->mci_out))
+ {
+ register char *xp;
+
+ if (pbp > peekbuf)
+ c = *--pbp;
+ else if ((c = getc(e->e_dfp)) == EOF)
+ break;
+ if (bitset(MCIF_7BIT, mci->mci_flags))
+ c &= 0x7f;
+ switch (ostate)
+ {
+ case OS_HEAD:
+ if (c != '\r' && c != '\n' && bp < buflim)
+ {
+ *bp++ = c;
+ break;
+ }
+
+ /* check beginning of line for special cases */
+ *bp = '\0';
+ pos = 0;
+ padc = EOF;
+ if (buf[0] == 'F' &&
+ bitnset(M_ESCFROM, mci->mci_mailer->m_flags) &&
+ strncmp(buf, "From ", 5) == 0)
+ {
+ padc = '>';
+ }
+ if (buf[0] == '-' && buf[1] == '-' &&
+ separator != NULL)
+ {
+ /* possible separator */
+ int sl = strlen(separator);
+
+ if (strncmp(&buf[2], separator, sl) == 0)
+ padc = ' ';
+ }
+ if (buf[0] == '.' &&
+ bitnset(M_XDOT, mci->mci_mailer->m_flags))
+ {
+ padc = '.';
+ }
+
+ /* now copy out saved line */
+ if (TrafficLogFile != NULL)
+ {
+ fprintf(TrafficLogFile, "%05d >>> ", getpid());
+ if (padc != EOF)
+ putc(padc, TrafficLogFile);
+ for (xp = buf; xp < bp; xp++)
+ putc(*xp, TrafficLogFile);
+ if (c == '\n')
+ fputs(mci->mci_mailer->m_eol,
+ TrafficLogFile);
+ }
+ if (padc != EOF)
+ {
+ putc(padc, mci->mci_out);
+ pos++;
+ }
+ for (xp = buf; xp < bp; xp++)
+ putc(*xp, mci->mci_out);
+ if (c == '\n')
+ {
+ fputs(mci->mci_mailer->m_eol,
+ mci->mci_out);
+ pos = 0;
+ }
+ else
+ {
+ pos += bp - buf;
+ if (c != '\r')
+ *pbp++ = c;
+ }
+ bp = buf;
+
+ /* determine next state */
+ if (c == '\n')
+ ostate = OS_HEAD;
+ else if (c == '\r')
+ ostate = OS_CR;
+ else
+ ostate = OS_INLINE;
+ continue;
+
+ case OS_CR:
+ if (c == '\n')
+ {
+ /* got CRLF */
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ if (TrafficLogFile != NULL)
+ {
+ fputs(mci->mci_mailer->m_eol,
+ TrafficLogFile);
+ }
+ ostate = OS_HEAD;
+ continue;
+ }
+
+ /* had a naked carriage return */
+ *pbp++ = c;
+ c = '\r';
+ goto putch;
+
+ case OS_INLINE:
+ if (c == '\r')
+ {
+ ostate = OS_CR;
+ continue;
+ }
+putch:
+ if (mci->mci_mailer->m_linelimit > 0 &&
+ pos > mci->mci_mailer->m_linelimit &&
+ c != '\n')
+ {
+ putc('!', mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ if (TrafficLogFile != NULL)
+ {
+ fprintf(TrafficLogFile, "!%s",
+ mci->mci_mailer->m_eol);
+ }
+ ostate = OS_HEAD;
+ *pbp++ = c;
+ continue;
+ }
+ if (TrafficLogFile != NULL)
+ putc(c, TrafficLogFile);
+ putc(c, mci->mci_out);
+ pos++;
+ ostate = c == '\n' ? OS_HEAD : OS_INLINE;
+ break;
+ }
+ }
+
+ /* make sure we are at the beginning of a line */
+ if (bp > buf)
+ {
+ *bp = '\0';
+ fputs(buf, mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ }
+ }
+
+ if (ferror(e->e_dfp))
+ {
+ syserr("putbody: df%s: read error", e->e_id);
+ ExitStat = EX_IOERR;
+ }
+
+endofmessage:
+ /* some mailers want extra blank line at end of message */
+ if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) &&
+ buf[0] != '\0' && buf[0] != '\n')
+ putline("", mci);
+
+ (void) fflush(mci->mci_out);
+ if (ferror(mci->mci_out) && errno != EPIPE)
+ {
+ syserr("putbody: write error");
+ ExitStat = EX_IOERR;
+ }
+ errno = 0;
+}
+ /*
+** MAILFILE -- Send a message to a file.
+**
+** If the file has the setuid/setgid bits set, but NO execute
+** bits, sendmail will try to become the owner of that file
+** rather than the real user. Obviously, this only works if
+** sendmail runs as root.
+**
+** This could be done as a subordinate mailer, except that it
+** is used implicitly to save messages in ~/dead.letter. We
+** view this as being sufficiently important as to include it
+** here. For example, if the system is dying, we shouldn't have
+** to create another process plus some pipes to save the message.
+**
+** Parameters:
+** filename -- the name of the file to send to.
+** ctladdr -- the controlling address header -- includes
+** the userid/groupid to be when sending.
+** sfflags -- flags for opening.
+** e -- the current envelope.
+**
+** Returns:
+** The exit code associated with the operation.
+**
+** Side Effects:
+** none.
+*/
+
+int
+mailfile(filename, ctladdr, sfflags, e)
+ char *filename;
+ ADDRESS *ctladdr;
+ int sfflags;
+ register ENVELOPE *e;
+{
+ register FILE *f;
+ register int pid = -1;
+ int mode;
+
+ if (tTd(11, 1))
+ {
+ printf("mailfile %s\n ctladdr=", filename);
+ printaddr(ctladdr, FALSE);
+ }
+
+ if (e->e_xfp != NULL)
+ fflush(e->e_xfp);
+
+ /*
+ ** Fork so we can change permissions here.
+ ** Note that we MUST use fork, not vfork, because of
+ ** the complications of calling subroutines, etc.
+ */
+
+ DOFORK(fork);
+
+ if (pid < 0)
+ return (EX_OSERR);
+ else if (pid == 0)
+ {
+ /* child -- actually write to file */
+ struct stat stb;
+ struct stat fsb;
+ MCI mcibuf;
+ int oflags = O_WRONLY|O_APPEND;
+
+ if (e->e_lockfp != NULL)
+ (void) close(fileno(e->e_lockfp));
+
+ (void) setsignal(SIGINT, SIG_DFL);
+ (void) setsignal(SIGHUP, SIG_DFL);
+ (void) setsignal(SIGTERM, SIG_DFL);
+ (void) umask(OldUmask);
+ e->e_to = filename;
+ ExitStat = EX_OK;
+
+#ifdef HASLSTAT
+ if ((SafeFileEnv != NULL ? lstat(filename, &stb)
+ : stat(filename, &stb)) < 0)
+#else
+ if (stat(filename, &stb) < 0)
+#endif
+ {
+ stb.st_mode = FileMode;
+ oflags |= O_CREAT|O_EXCL;
+ }
+ else if (bitset(0111, stb.st_mode) || stb.st_nlink != 1 ||
+ (SafeFileEnv != NULL && !S_ISREG(stb.st_mode)))
+ exit(EX_CANTCREAT);
+ mode = stb.st_mode;
+
+ /* limit the errors to those actually caused in the child */
+ errno = 0;
+ ExitStat = EX_OK;
+
+ if (ctladdr != NULL || bitset(SFF_RUNASREALUID, sfflags))
+ {
+ /* ignore setuid and setgid bits */
+ mode &= ~(S_ISGID|S_ISUID);
+ }
+
+ /* we have to open the dfile BEFORE setuid */
+ if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags))
+ {
+ char *df = queuename(e, 'd');
+
+ e->e_dfp = fopen(df, "r");
+ if (e->e_dfp == NULL)
+ {
+ syserr("mailfile: Cannot open %s for %s from %s",
+ df, e->e_to, e->e_from.q_paddr);
+ }
+ }
+
+ /* select a new user to run as */
+ if (!bitset(SFF_RUNASREALUID, sfflags))
+ {
+ if (bitset(S_ISUID, mode))
+ {
+ RealUserName = NULL;
+ RealUid = stb.st_uid;
+ }
+ else if (ctladdr != NULL && ctladdr->q_uid != 0)
+ {
+ if (ctladdr->q_ruser != NULL)
+ RealUserName = ctladdr->q_ruser;
+ else
+ RealUserName = ctladdr->q_user;
+ RealUid = ctladdr->q_uid;
+ }
+ else if (FileMailer != NULL && FileMailer->m_uid != 0)
+ {
+ RealUserName = DefUser;
+ RealUid = FileMailer->m_uid;
+ }
+ else
+ {
+ RealUserName = DefUser;
+ RealUid = DefUid;
+ }
+
+ /* select a new group to run as */
+ if (bitset(S_ISGID, mode))
+ RealGid = stb.st_gid;
+ else if (ctladdr != NULL && ctladdr->q_uid != 0)
+ RealGid = ctladdr->q_gid;
+ else if (FileMailer != NULL && FileMailer->m_gid != 0)
+ RealGid = FileMailer->m_gid;
+ else
+ RealGid = DefGid;
+ }
+
+ /* last ditch */
+ if (!bitset(SFF_ROOTOK, sfflags))
+ {
+ if (RealUid == 0)
+ RealUid = DefUid;
+ if (RealGid == 0)
+ RealGid = DefGid;
+ }
+
+ /* now set the group and user ids */
+ endpwent();
+ if (RealUserName != NULL && !DontInitGroups)
+ (void) initgroups(RealUserName, RealGid);
+ (void) setgid(RealGid);
+ (void) setuid(RealUid);
+
+ /* if you have a safe environment, go into it */
+ if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0')
+ {
+ int i;
+
+ if (chroot(SafeFileEnv) < 0)
+ {
+ syserr("mailfile: Cannot chroot(%s)",
+ SafeFileEnv);
+ exit(EX_CANTCREAT);
+ }
+ i = strlen(SafeFileEnv);
+ if (strncmp(SafeFileEnv, filename, i) == 0)
+ filename += i;
+ }
+ if (chdir("/") < 0)
+ syserr("mailfile: cannot chdir(/)");
+
+ sfflags |= SFF_NOPATHCHECK;
+ sfflags &= ~SFF_OPENASROOT;
+ f = safefopen(filename, oflags, FileMode, sfflags);
+ if (f == NULL)
+ {
+ message("554 cannot open: %s", errstring(errno));
+ exit(EX_CANTCREAT);
+ }
+ if (fstat(fileno(f), &stb) < 0)
+ {
+ message("554 cannot fstat %s", errstring(errno));
+ exit(EX_CANTCREAT);
+ }
+
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_mailer = FileMailer;
+ mcibuf.mci_out = f;
+ if (bitnset(M_7BITS, FileMailer->m_flags))
+ mcibuf.mci_flags |= MCIF_7BIT;
+
+ putfromline(&mcibuf, e);
+ (*e->e_puthdr)(&mcibuf, e->e_header, e);
+ (*e->e_putbody)(&mcibuf, e, NULL);
+ putline("\n", &mcibuf);
+ if (fflush(f) < 0 || ferror(f))
+ {
+ message("451 I/O error: %s", errstring(errno));
+ setstat(EX_IOERR);
+ }
+
+ /* reset ISUID & ISGID bits for paranoid systems */
+#if HASFCHMOD
+ (void) fchmod(fileno(f), (int) stb.st_mode);
+#else
+ (void) chmod(filename, (int) stb.st_mode);
+#endif
+ (void) xfclose(f, "mailfile", filename);
+ (void) fflush(stdout);
+ exit(ExitStat);
+ /*NOTREACHED*/
+ }
+ else
+ {
+ /* parent -- wait for exit status */
+ int st;
+
+ st = waitfor(pid);
+ if (WIFEXITED(st))
+ return (WEXITSTATUS(st));
+ else
+ {
+ syserr("child died on signal %d", st);
+ return (EX_UNAVAILABLE);
+ }
+ /*NOTREACHED*/
+ }
+}
+ /*
+** 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:
+** m -- the mailer describing this host.
+** host -- the host name.
+** e -- the current envelope.
+**
+** Returns:
+** The signature for this host.
+**
+** Side Effects:
+** Can tweak the symbol table.
+*/
+
+char *
+hostsignature(m, host, e)
+ register MAILER *m;
+ char *host;
+ ENVELOPE *e;
+{
+ register char *p;
+ register STAB *s;
+ int i;
+ int len;
+#if NAMED_BIND
+ int nmx;
+ auto int rcode;
+ char *hp;
+ char *endp;
+ int oldoptions = _res.options;
+ char *mxhosts[MAXMXHOSTS + 1];
+#endif
+
+ /*
+ ** Check to see if this uses IPC -- if not, it can't have MX records.
+ */
+
+ p = m->m_mailer;
+ if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0)
+ {
+ /* just an ordinary mailer */
+ return host;
+ }
+
+ /*
+ ** Look it up in the symbol table.
+ */
+
+ s = stab(host, ST_HOSTSIG, ST_ENTER);
+ if (s->s_hostsig != NULL)
+ return s->s_hostsig;
+
+ /*
+ ** Not already there -- create a signature.
+ */
+
+#if NAMED_BIND
+ if (ConfigLevel < 2)
+ _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */
+
+ for (hp = host; hp != NULL; hp = endp)
+ {
+ endp = strchr(hp, ':');
+ if (endp != NULL)
+ *endp = '\0';
+
+ nmx = getmxrr(hp, mxhosts, TRUE, &rcode);
+
+ if (nmx <= 0)
+ {
+ register MCI *mci;
+
+ /* update the connection info for this host */
+ mci = mci_get(hp, m);
+ mci->mci_lastuse = curtime();
+ mci->mci_exitstat = rcode;
+ mci->mci_errno = errno;
+ mci->mci_herrno = h_errno;
+
+ /* and return the original host name as the signature */
+ nmx = 1;
+ mxhosts[0] = hp;
+ }
+
+ 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++ = ':';
+ }
+ 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;
+}
diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c
new file mode 100644
index 000000000000..2f94508da1ea
--- /dev/null
+++ b/usr.sbin/sendmail/src/domain.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 1986, 1995 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
+#if NAMED_BIND
+static char sccsid[] = "@(#)domain.c 8.54 (Berkeley) 9/28/95 (with name server)";
+#else
+static char sccsid[] = "@(#)domain.c 8.54 (Berkeley) 9/28/95 (without name server)";
+#endif
+#endif /* not lint */
+
+#if NAMED_BIND
+
+#include <errno.h>
+#include <resolv.h>
+
+typedef union
+{
+ HEADER qb1;
+ u_char qb2[PACKETSZ];
+} querybuf;
+
+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
+
+#ifndef NO_DATA
+# define NO_DATA NO_ADDRESS
+#endif
+
+#ifndef HFIXEDSZ
+# define HFIXEDSZ 12 /* sizeof(HEADER) */
+#endif
+
+#define MAXCNAMEDEPTH 10 /* maximum depth of CNAME recursion */
+
+#if defined(__RES) && (__RES >= 19940415)
+# define RES_UNC_T char *
+#else
+# define RES_UNC_T u_char *
+#endif
+ /*
+** 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.
+*/
+
+int
+getmxrr(host, mxhosts, droplocalhost, rcode)
+ char *host;
+ char **mxhosts;
+ bool droplocalhost;
+ int *rcode;
+{
+ register u_char *eom, *cp;
+ register int i, j, n;
+ int nmx = 0;
+ register char *bp;
+ HEADER *hp;
+ querybuf answer;
+ int ancount, qdcount, buflen;
+ bool seenlocal = FALSE;
+ u_short pref, type;
+ u_short localpref = 256;
+ char *fallbackMX = FallBackMX;
+ static bool firsttime = TRUE;
+ bool trycanon = FALSE;
+ int (*resfunc)();
+ extern int res_query(), res_search();
+ u_short prefer[MAXMXHOSTS];
+ int weight[MAXMXHOSTS];
+ extern bool getcanonname();
+
+ if (tTd(8, 2))
+ printf("getmxrr(%s, droplocalhost=%d)\n", host, droplocalhost);
+
+ if (fallbackMX != NULL)
+ {
+ if (firsttime &&
+ res_query(FallBackMX, C_IN, T_A,
+ (u_char *) &answer, sizeof answer) < 0)
+ {
+ /* this entry is bogus */
+ fallbackMX = FallBackMX = NULL;
+ }
+ else if (droplocalhost && wordinclass(fallbackMX, 'w'))
+ {
+ /* don't use fallback for this pass */
+ fallbackMX = NULL;
+ }
+ firsttime = FALSE;
+ }
+
+ *rcode = EX_OK;
+
+ /* efficiency hack -- numeric or non-MX lookups */
+ if (host[0] == '[')
+ goto punt;
+
+ /*
+ ** If we don't have MX records in our host switch, don't
+ ** try for MX records. Note that this really isn't "right",
+ ** since we might be set up to try NIS first and then DNS;
+ ** if the host is found in NIS we really shouldn't be doing
+ ** MX lookups. However, that should be a degenerate case.
+ */
+
+ if (!UseNameServer)
+ goto punt;
+ if (HasWildcardMX && ConfigLevel >= 6)
+ resfunc = res_query;
+ else
+ resfunc = res_search;
+
+ errno = 0;
+ n = (*resfunc)(host, C_IN, T_MX, (u_char *) &answer, sizeof(answer));
+ if (n < 0)
+ {
+ if (tTd(8, 1))
+ 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:
+ trycanon = TRUE;
+ /* fall through */
+
+ case NO_RECOVERY:
+ /* no MX data on this host */
+ goto punt;
+
+ case HOST_NOT_FOUND:
+#if BROKEN_RES_SEARCH
+ case 0: /* Ultrix resolver retns failure w/ h_errno=0 */
+#endif
+ /* host doesn't exist in DNS; might be in /etc/hosts */
+ trycanon = TRUE;
+ *rcode = EX_NOHOST;
+ goto punt;
+
+ case TRY_AGAIN:
+ /* couldn't connect to the name server */
+ if (fallbackMX != NULL)
+ {
+ /* name server is hosed -- push to fallback */
+ mxhosts[nmx++] = fallbackMX;
+ return nmx;
+ }
+ /* it might come up later; better queue it up */
+ *rcode = EX_TEMPFAIL;
+ break;
+
+ default:
+ syserr("getmxrr: res_search (%s) failed with impossible h_errno (%d)\n",
+ host, h_errno);
+ *rcode = EX_OSERR;
+ break;
+ }
+
+ /* irreconcilable differences */
+ return (-1);
+ }
+
+ /* find first satisfactory answer */
+ hp = (HEADER *)&answer;
+ cp = (u_char *)&answer + HFIXEDSZ;
+ eom = (u_char *)&answer + n;
+ for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
+ if ((n = dn_skipname(cp, eom)) < 0)
+ goto punt;
+ buflen = sizeof(MXHostBuf) - 1;
+ bp = MXHostBuf;
+ ancount = ntohs(hp->ancount);
+ while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1)
+ {
+ if ((n = dn_expand((u_char *)&answer,
+ eom, cp, (RES_UNC_T) bp, buflen)) < 0)
+ break;
+ cp += n;
+ GETSHORT(type, cp);
+ cp += INT16SZ + INT32SZ;
+ GETSHORT(n, cp);
+ 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);
+ if ((n = dn_expand((u_char *)&answer, eom, cp,
+ (RES_UNC_T) bp, buflen)) < 0)
+ break;
+ cp += n;
+ if (wordinclass(bp, 'w'))
+ {
+ if (tTd(8, 3))
+ printf("found localhost (%s) in MX list, pref=%d\n",
+ bp, pref);
+ if (droplocalhost)
+ {
+ if (!seenlocal || pref < localpref)
+ localpref = pref;
+ seenlocal = TRUE;
+ continue;
+ }
+ weight[nmx] = 0;
+ }
+ else
+ weight[nmx] = mxrand(bp);
+ prefer[nmx] = pref;
+ mxhosts[nmx++] = bp;
+ n = strlen(bp);
+ bp += n;
+ if (bp[-1] != '.')
+ {
+ *bp++ = '.';
+ n++;
+ }
+ *bp++ = '\0';
+ buflen -= n + 1;
+ }
+
+ /* 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;
+
+ 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 preference part of list */
+ nmx = i;
+ }
+ }
+
+ /* delete duplicates from list (yes, some bozos have duplicates) */
+ for (i = 0; i < nmx - 1; )
+ {
+ if (strcasecmp(mxhosts[i], mxhosts[i + 1]) != 0)
+ i++;
+ else
+ {
+ /* compress out duplicate */
+ for (j = i + 1; j < nmx; j++)
+ mxhosts[j] = mxhosts[j + 1];
+ nmx--;
+ }
+ }
+
+ if (nmx == 0)
+ {
+punt:
+ if (seenlocal &&
+ (!TryNullMXList || sm_gethostbyname(host) == NULL))
+ {
+ /*
+ ** If we have deleted all MX entries, this is
+ ** an error -- we should NEVER send to a host that
+ ** has an MX, and this should have been caught
+ ** earlier in the config file.
+ **
+ ** Some sites prefer to go ahead and try the
+ ** A record anyway; that case is handled by
+ ** setting TryNullMXList. I believe this is a
+ ** bad idea, but it's up to you....
+ */
+
+ *rcode = EX_CONFIG;
+ syserr("MX list for %s points back to %s",
+ host, MyHostName);
+ return -1;
+ }
+ strcpy(MXHostBuf, host);
+ mxhosts[0] = MXHostBuf;
+ if (host[0] == '[')
+ {
+ register char *p;
+
+ /* this may be an MX suppression-style address */
+ p = strchr(MXHostBuf, ']');
+ if (p != NULL)
+ {
+ *p = '\0';
+ if (inet_addr(&MXHostBuf[1]) != -1)
+ *p = ']';
+ else
+ {
+ trycanon = TRUE;
+ mxhosts[0]++;
+ }
+ }
+ }
+ if (trycanon &&
+ getcanonname(mxhosts[0], sizeof MXHostBuf - 2, FALSE))
+ {
+ bp = &MXHostBuf[strlen(MXHostBuf)];
+ if (bp[-1] != '.')
+ {
+ *bp++ = '.';
+ *bp = '\0';
+ }
+ nmx = 1;
+ }
+ }
+
+ /* if we have a default lowest preference, include that */
+ if (fallbackMX != NULL && !seenlocal)
+ mxhosts[nmx++] = fallbackMX;
+
+ return (nmx);
+}
+ /*
+** 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.
+*/
+
+int
+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;
+ hfunc++;
+
+ if (tTd(17, 9))
+ printf(" = %d\n", hfunc);
+ return hfunc;
+}
+ /*
+** BESTMX -- find the best MX for a name
+**
+** This is really a hack, but I don't see any obvious way
+** to generalize it at the moment.
+*/
+
+char *
+bestmx_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ int nmx;
+ auto int rcode;
+ int saveopts = _res.options;
+ char *mxhosts[MAXMXHOSTS + 1];
+
+ _res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
+ nmx = getmxrr(name, mxhosts, FALSE, &rcode);
+ _res.options = saveopts;
+ if (nmx <= 0)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av);
+}
+ /*
+** DNS_GETCANONNAME -- get the canonical name for named host using DNS
+**
+** 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.
+** trymx -- if set, try MX records as well as A and CNAME.
+** statp -- pointer to place to store status.
+**
+** Returns:
+** TRUE -- if the host matched.
+** FALSE -- otherwise.
+*/
+
+bool
+dns_getcanonname(host, hbsize, trymx, statp)
+ char *host;
+ int hbsize;
+ bool trymx;
+ int *statp;
+{
+ register u_char *eom, *ap;
+ register char *cp;
+ register int n;
+ HEADER *hp;
+ querybuf answer;
+ int ancount, qdcount;
+ int ret;
+ char **domain;
+ int type;
+ char **dp;
+ char *mxmatch;
+ bool amatch;
+ bool gotmx = FALSE;
+ int qtype;
+ int loopcnt;
+ char *xp;
+ char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
+ char *searchlist[MAXDNSRCH+2];
+ extern char *gethostalias();
+
+ if (tTd(8, 2))
+ printf("dns_getcanonname(%s, trymx=%d)\n", host, trymx);
+
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+
+ /*
+ ** 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.
+ */
+
+ loopcnt = 0;
+cnameloop:
+ /* Check for dots in the name */
+ for (cp = host, n = 0; *cp != '\0'; cp++)
+ if (*cp == '.')
+ n++;
+
+ /*
+ ** If this is a simple name, determine whether it matches an
+ ** alias in the file defined by the environment variable HOSTALIASES.
+ */
+ if (n == 0 && (xp = gethostalias(host)) != NULL)
+ {
+ if (loopcnt++ > MAXCNAMEDEPTH)
+ {
+ syserr("loop in ${HOSTALIASES} file");
+ }
+ else
+ {
+ strncpy(host, xp, hbsize);
+ host[hbsize - 1] = '\0';
+ goto cnameloop;
+ }
+ }
+
+ /*
+ ** Build the search list.
+ ** If there is at least one dot in name, start with a null
+ ** domain to search the unmodified name first.
+ ** If name does not end with a dot and search up local domain
+ ** tree desired, append each local domain component to the
+ ** search list; if name contains no dots and default domain
+ ** name is desired, append default domain name to search list;
+ ** else if name ends in a dot, remove that dot.
+ */
+
+ dp = searchlist;
+ if (n > 0)
+ *dp++ = "";
+ if (n >= 0 && *--cp != '.' && bitset(RES_DNSRCH, _res.options))
+ {
+ for (domain = _res.dnsrch; *domain != NULL; )
+ *dp++ = *domain++;
+ }
+ else if (n == 0 && bitset(RES_DEFNAMES, _res.options))
+ {
+ *dp++ = _res.defdname;
+ }
+ else if (*cp == '.')
+ {
+ *cp = '\0';
+ }
+ *dp = NULL;
+
+ /*
+ ** Now loop through the search list, appending each domain in turn
+ ** name and searching for a match.
+ */
+
+ mxmatch = NULL;
+ qtype = T_ANY;
+
+ for (dp = searchlist; *dp != NULL; )
+ {
+ if (qtype == T_ANY)
+ gotmx = FALSE;
+ if (tTd(8, 5))
+ printf("dns_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.qb2, sizeof(answer.qb2));
+ 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;
+ *statp = EX_TEMPFAIL;
+ 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 && trymx)
+ {
+ qtype = T_MX;
+ continue;
+ }
+ }
+
+ /* definite no -- try the next domain */
+ dp++;
+ qtype = T_ANY;
+ continue;
+ }
+ else if (tTd(8, 7))
+ printf("\tYES\n");
+
+ /*
+ ** Appear to have a match. Confirm it by searching for A or
+ ** CNAME records. If we don't have a local domain
+ ** wild card MX record, we will accept MX as well.
+ */
+
+ hp = (HEADER *) &answer;
+ ap = (u_char *) &answer + HFIXEDSZ;
+ 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));
+ *statp = EX_SOFTWARE;
+ return FALSE; /* ???XXX??? */
+ }
+ }
+
+ amatch = FALSE;
+ for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom;
+ ap += n)
+ {
+ n = dn_expand((u_char *) &answer, eom, ap,
+ (RES_UNC_T) nbuf, sizeof nbuf);
+ if (n < 0)
+ break;
+ ap += n;
+ GETSHORT(type, ap);
+ ap += INT16SZ + INT32SZ;
+ GETSHORT(n, ap);
+ switch (type)
+ {
+ case T_MX:
+ gotmx = TRUE;
+ if (**dp != '\0' && HasWildcardMX)
+ {
+ /*
+ ** If we are using MX matches and have
+ ** not yet gotten one, save this one
+ ** but keep searching for an A or
+ ** CNAME match.
+ */
+
+ if (trymx && mxmatch == NULL)
+ mxmatch = *dp;
+ continue;
+ }
+
+ /*
+ ** If we did not append a domain name, this
+ ** must have been a canonical name to start
+ ** with. Even if we did append a domain name,
+ ** in the absence of a wildcard MX this must
+ ** still be a real MX match.
+ ** Such MX matches are as good as an A match,
+ ** fall through.
+ */
+
+ case T_A:
+ /* Flag that a good match was found */
+ amatch = TRUE;
+
+ /* continue in case a CNAME also exists */
+ continue;
+
+ case T_CNAME:
+ if (DontExpandCnames)
+ {
+ /* got CNAME -- guaranteed canonical */
+ amatch = TRUE;
+ break;
+ }
+
+ if (loopcnt++ > MAXCNAMEDEPTH)
+ {
+ /*XXX should notify postmaster XXX*/
+ message("DNS failure: CNAME loop for %s",
+ host);
+ if (CurEnv->e_message == NULL)
+ {
+ char ebuf[MAXLINE];
+
+ sprintf(ebuf, "Deferred: DNS failure: CNAME loop for %.100s",
+ host);
+ CurEnv->e_message = newstr(ebuf);
+ }
+ h_errno = NO_RECOVERY;
+ *statp = EX_CONFIG;
+ return FALSE;
+ }
+
+ /* value points at name */
+ if ((ret = dn_expand((u_char *)&answer,
+ eom, ap, (RES_UNC_T) 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 a good match -- either an A, CNAME, or an
+ ** exact MX record. Save it and get out of here.
+ */
+
+ mxmatch = *dp;
+ break;
+ }
+
+ /*
+ ** Nothing definitive yet.
+ ** If this was a T_ANY query, we don't really know what
+ ** was returned -- it might have been a T_NS,
+ ** for example. Try T_A to be more specific
+ ** during the next pass.
+ ** If this was a T_A query and we haven't yet found a MX
+ ** match, try T_MX if allowed to do so.
+ ** Otherwise, try the next domain.
+ */
+
+ if (qtype == T_ANY)
+ qtype = T_A;
+ else if (qtype == T_A && !gotmx && trymx)
+ qtype = T_MX;
+ else
+ {
+ qtype = T_ANY;
+ dp++;
+ }
+ }
+
+ /* if nothing was found, we are done */
+ if (mxmatch == NULL)
+ {
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+
+ /*
+ ** Create canonical name and return.
+ ** If saved domain name is null, name was already canonical.
+ ** Otherwise append the saved domain name.
+ */
+
+ (void) sprintf(nbuf, "%.*s%s%.*s", MAXDNAME, host,
+ *mxmatch == '\0' ? "" : ".",
+ MAXDNAME, mxmatch);
+ strncpy(host, nbuf, hbsize);
+ host[hbsize - 1] = '\0';
+ if (tTd(8, 5))
+ printf("dns_getcanonname: %s\n", host);
+ *statp = EX_OK;
+ return TRUE;
+}
+
+
+
+char *
+gethostalias(host)
+ char *host;
+{
+ char *fname;
+ FILE *fp;
+ register char *p = NULL;
+ char buf[MAXLINE];
+ static char hbuf[MAXDNAME];
+
+ fname = getenv("HOSTALIASES");
+ if (fname == NULL ||
+ (fp = safefopen(fname, O_RDONLY, 0, SFF_REGONLY)) == NULL)
+ return NULL;
+ while (fgets(buf, sizeof buf, fp) != NULL)
+ {
+ for (p = buf; p != '\0' && !(isascii(*p) && isspace(*p)); p++)
+ continue;
+ if (*p == 0)
+ {
+ /* syntax error */
+ continue;
+ }
+ *p++ = '\0';
+ if (strcasecmp(buf, host) == 0)
+ break;
+ }
+
+ if (feof(fp))
+ {
+ /* no match */
+ fclose(fp);
+ return NULL;
+ }
+
+ /* got a match; extract the equivalent name */
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ host = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ *p = '\0';
+ strncpy(hbuf, host, sizeof hbuf - 1);
+ hbuf[sizeof hbuf - 1] = '\0';
+ return hbuf;
+}
+
+#endif /* NAMED_BIND */
diff --git a/usr.sbin/sendmail/src/envelope.c b/usr.sbin/sendmail/src/envelope.c
new file mode 100644
index 000000000000..4bf7ac231ddf
--- /dev/null
+++ b/usr.sbin/sendmail/src/envelope.c
@@ -0,0 +1,924 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)envelope.c 8.76 (Berkeley) 11/11/95";
+#endif /* not lint */
+
+#include "sendmail.h"
+
+/*
+** NEWENVELOPE -- allocate a new envelope
+**
+** Supports inheritance.
+**
+** Parameters:
+** e -- the new envelope to fill in.
+** parent -- the envelope to be the parent of e.
+**
+** Returns:
+** e.
+**
+** Side Effects:
+** none.
+*/
+
+ENVELOPE *
+newenvelope(e, parent)
+ register ENVELOPE *e;
+ register ENVELOPE *parent;
+{
+ if (e == parent && e->e_parent != NULL)
+ parent = e->e_parent;
+ clearenvelope(e, TRUE);
+ if (e == CurEnv)
+ bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
+ else
+ bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
+ e->e_parent = parent;
+ e->e_ctime = curtime();
+ if (parent != NULL)
+ e->e_msgpriority = parent->e_msgsize;
+ e->e_puthdr = putheader;
+ e->e_putbody = putbody;
+ if (CurEnv->e_xfp != NULL)
+ (void) fflush(CurEnv->e_xfp);
+
+ return (e);
+}
+ /*
+** DROPENVELOPE -- deallocate an envelope.
+**
+** Parameters:
+** e -- the envelope to deallocate.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** housekeeping necessary to dispose of an envelope.
+** Unlocks this queue file.
+*/
+
+void
+dropenvelope(e)
+ register ENVELOPE *e;
+{
+ bool queueit = FALSE;
+ bool failure_return = FALSE;
+ bool success_return = FALSE;
+ register ADDRESS *q;
+ char *id = e->e_id;
+ char buf[MAXLINE];
+
+ if (tTd(50, 1))
+ {
+ extern void printenvflags();
+
+ printf("dropenvelope %x: id=", e);
+ xputs(e->e_id);
+ printf(", flags=");
+ printenvflags(e);
+ if (tTd(50, 10))
+ {
+ printf("sendq=");
+ printaddr(e->e_sendqueue, TRUE);
+ }
+ }
+
+#ifdef LOG
+ if (LogLevel > 84)
+ syslog(LOG_DEBUG, "%s: dropenvelope, e_flags=0x%x, OpMode=%c, pid=%d",
+ id == NULL ? "[NOQUEUE]" : id,
+ e->e_flags, OpMode, getpid());
+#endif
+
+ /* we must have an id to remove disk files */
+ if (id == NULL)
+ return;
+
+ /* if verify-only mode, we can skip most of this */
+ if (OpMode == MD_VERIFY)
+ goto simpledrop;
+
+ if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
+ logsender(e, NULL);
+ e->e_flags &= ~EF_LOGSENDER;
+
+ /* post statistics */
+ poststats(StatFile);
+
+ /*
+ ** Extract state information from dregs of send list.
+ */
+
+ e->e_flags &= ~EF_QUEUERUN;
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags) ||
+ bitset(QQUEUEUP, q->q_flags))
+ queueit = TRUE;
+
+ /* see if a notification is needed */
+ if (bitset(QBADADDR, q->q_flags) &&
+ bitset(QPINGONFAILURE, q->q_flags))
+ {
+ failure_return = TRUE;
+ if (q->q_owner == NULL && !emptyaddr(&e->e_from))
+ (void) sendtolist(e->e_from.q_paddr, NULL,
+ &e->e_errorqueue, 0, e);
+ }
+ else if (bitset(QPINGONSUCCESS, q->q_flags) &&
+ ((bitset(QSENT, q->q_flags) &&
+ bitnset(M_LOCALMAILER, q->q_mailer->m_flags)) ||
+ bitset(QRELAYED|QEXPANDED|QDELIVERED, q->q_flags)))
+ {
+ success_return = TRUE;
+ }
+ }
+
+ if (e->e_class < 0)
+ e->e_flags |= EF_NO_BODY_RETN;
+
+ /*
+ ** See if the message timed out.
+ */
+
+ if (!queueit)
+ /* nothing to do */ ;
+ else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
+ {
+ (void) sprintf(buf, "Cannot send message for %s",
+ pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ if (e->e_message != NULL)
+ free(e->e_message);
+ e->e_message = newstr(buf);
+ message(buf);
+ e->e_flags |= EF_CLRQUEUE;
+ failure_return = TRUE;
+ fprintf(e->e_xfp, "Message could not be delivered for %s\n",
+ pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ fprintf(e->e_xfp, "Message will be deleted from queue\n");
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QQUEUEUP, q->q_flags) ||
+ !bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
+ {
+ q->q_flags |= QBADADDR;
+ q->q_status = "4.4.7";
+ }
+ }
+ }
+ else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
+ curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
+ {
+ bool delay_return = FALSE;
+
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QQUEUEUP, q->q_flags) &&
+ bitset(QPINGONDELAY, q->q_flags))
+ {
+ q->q_flags |= QDELAYED;
+ delay_return = TRUE;
+ }
+ }
+ if (delay_return &&
+ !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
+ e->e_class >= 0 &&
+ e->e_from.q_paddr != NULL &&
+ strcmp(e->e_from.q_paddr, "<>") != 0 &&
+ strncasecmp(e->e_from.q_paddr, "owner-", 6) != 0 &&
+ (strlen(e->e_from.q_paddr) <= (SIZE_T) 8 ||
+ strcasecmp(&e->e_from.q_paddr[strlen(e->e_from.q_paddr) - 8], "-request") != 0))
+ {
+ (void) sprintf(buf,
+ "Warning: could not send message for past %s",
+ pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
+ if (e->e_message != NULL)
+ free(e->e_message);
+ e->e_message = newstr(buf);
+ message(buf);
+ e->e_flags |= EF_WARNING;
+ failure_return = TRUE;
+ }
+ fprintf(e->e_xfp,
+ "Warning: message still undelivered after %s\n",
+ pintvl(TimeOuts.to_q_warning[e->e_timeoutclass], FALSE));
+ fprintf(e->e_xfp, "Will keep trying until message is %s old\n",
+ pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
+ }
+
+ if (tTd(50, 2))
+ printf("failure_return=%d success_return=%d queueit=%d\n",
+ failure_return, success_return, queueit);
+
+ /*
+ ** If we had some fatal error, but no addresses are marked as
+ ** bad, mark them _all_ as bad.
+ */
+
+ if (bitset(EF_FATALERRS, e->e_flags) && !failure_return)
+ {
+ failure_return = TRUE;
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (!bitset(QDONTSEND, q->q_flags))
+ q->q_flags |= QBADADDR;
+ }
+ }
+
+ /*
+ ** Send back return receipts as requested.
+ */
+
+/*
+ if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)
+ && !bitset(PRIV_NORECEIPTS, PrivacyFlags))
+*/
+ if (e->e_receiptto == NULL)
+ e->e_receiptto = e->e_from.q_paddr;
+ if (success_return && !failure_return &&
+ !bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
+ strcmp(e->e_receiptto, "<>") != 0)
+ {
+ auto ADDRESS *rlist = NULL;
+
+ e->e_flags |= EF_SENDRECEIPT;
+ (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e);
+ (void) returntosender("Return receipt", rlist, FALSE, e);
+ }
+ e->e_flags &= ~EF_SENDRECEIPT;
+
+ /*
+ ** Arrange to send error messages if there are fatal errors.
+ */
+
+ if (failure_return && e->e_errormode != EM_QUIET)
+ savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
+
+ /*
+ ** Arrange to send warning messages to postmaster as requested.
+ */
+
+ if ((failure_return || bitset(EF_PM_NOTIFY, e->e_flags)) &&
+ PostMasterCopy != NULL &&
+ !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0)
+ {
+ auto ADDRESS *rlist = NULL;
+
+ (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
+ (void) returntosender(e->e_message, rlist, FALSE, e);
+ }
+
+ /*
+ ** Instantiate or deinstantiate the queue.
+ */
+
+simpledrop:
+ if (!queueit || bitset(EF_CLRQUEUE, e->e_flags))
+ {
+ if (tTd(50, 1))
+ {
+ extern void printenvflags();
+
+ printf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=",
+ e->e_id, queueit);
+ printenvflags(e);
+ }
+ xunlink(queuename(e, 'd'));
+ xunlink(queuename(e, 'q'));
+
+#ifdef LOG
+ if (LogLevel > 10)
+ syslog(LOG_INFO, "%s: done", id);
+#endif
+ }
+ else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
+ {
+#ifdef QUEUE
+ queueup(e, FALSE);
+#else /* QUEUE */
+ syserr("554 dropenvelope: queueup");
+#endif /* QUEUE */
+ }
+
+ /* now unlock the job */
+ closexscript(e);
+ unlockqueue(e);
+
+ /* make sure that this envelope is marked unused */
+ if (e->e_dfp != NULL)
+ (void) xfclose(e->e_dfp, "dropenvelope df", e->e_id);
+ e->e_dfp = NULL;
+ e->e_id = NULL;
+ e->e_flags &= ~EF_HAS_DF;
+}
+ /*
+** CLEARENVELOPE -- clear an envelope without unlocking
+**
+** This is normally used by a child process to get a clean
+** envelope without disturbing the parent.
+**
+** Parameters:
+** e -- the envelope to clear.
+** fullclear - if set, the current envelope is total
+** garbage and should be ignored; otherwise,
+** release any resources it may indicate.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Closes files associated with the envelope.
+** Marks the envelope as unallocated.
+*/
+
+void
+clearenvelope(e, fullclear)
+ register ENVELOPE *e;
+ bool fullclear;
+{
+ register HDR *bh;
+ register HDR **nhp;
+ extern ENVELOPE BlankEnvelope;
+
+ if (!fullclear)
+ {
+ /* clear out any file information */
+ if (e->e_xfp != NULL)
+ (void) xfclose(e->e_xfp, "clearenvelope xfp", e->e_id);
+ if (e->e_dfp != NULL)
+ (void) xfclose(e->e_dfp, "clearenvelope dfp", e->e_id);
+ e->e_xfp = e->e_dfp = NULL;
+ }
+
+ /* 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)
+ {
+ *nhp = (HDR *) xalloc(sizeof *bh);
+ bcopy((char *) bh, (char *) *nhp, sizeof *bh);
+ bh = bh->h_link;
+ nhp = &(*nhp)->h_link;
+ }
+}
+ /*
+** INITSYS -- initialize instantiation of system
+**
+** In Daemon mode, this is done in the child.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Initializes the system macros, some global variables,
+** etc. In particular, the current time in various
+** forms is set.
+*/
+
+void
+initsys(e)
+ register ENVELOPE *e;
+{
+ char cbuf[5]; /* holds hop count */
+ char pbuf[10]; /* holds pid */
+#ifdef TTYNAME
+ static char ybuf[60]; /* holds tty id */
+ register char *p;
+#endif /* TTYNAME */
+ extern char *ttyname();
+ extern void settime();
+
+ /*
+ ** Give this envelope a reality.
+ ** I.e., an id, a transcript, and a creation time.
+ */
+
+ openxscript(e);
+ e->e_ctime = curtime();
+
+ /*
+ ** Set OutChannel to something useful if stdout isn't it.
+ ** This arranges that any extra stuff the mailer produces
+ ** gets sent back to the user on error (because it is
+ ** tucked away in the transcript).
+ */
+
+ if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
+ e->e_xfp != NULL)
+ OutChannel = e->e_xfp;
+
+ /*
+ ** Set up some basic system macros.
+ */
+
+ /* process id */
+ (void) sprintf(pbuf, "%d", getpid());
+ define('p', newstr(pbuf), e);
+
+ /* hop count */
+ (void) sprintf(cbuf, "%d", e->e_hopcount);
+ define('c', newstr(cbuf), e);
+
+ /* time as integer, unix time, arpa time */
+ settime(e);
+
+#ifdef TTYNAME
+ /* tty name */
+ if (macvalue('y', e) == NULL)
+ {
+ p = ttyname(2);
+ if (p != NULL)
+ {
+ if (strrchr(p, '/') != NULL)
+ p = strrchr(p, '/') + 1;
+ (void) strcpy(ybuf, p);
+ define('y', ybuf, e);
+ }
+ }
+#endif /* TTYNAME */
+}
+ /*
+** SETTIME -- set the current time.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Sets the various time macros -- $a, $b, $d, $t.
+*/
+
+void
+settime(e)
+ register ENVELOPE *e;
+{
+ register char *p;
+ auto time_t now;
+ char tbuf[20]; /* holds "current" time */
+ char dbuf[30]; /* holds ctime(tbuf) */
+ register struct tm *tm;
+ extern char *arpadate();
+ extern struct tm *gmtime();
+
+ now = curtime();
+ tm = gmtime(&now);
+ (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', newstr(tbuf), e);
+ (void) strcpy(dbuf, ctime(&now));
+ p = strchr(dbuf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ define('d', newstr(dbuf), e);
+ p = arpadate(dbuf);
+ p = newstr(p);
+ if (macvalue('a', e) == NULL)
+ define('a', p, e);
+ define('b', p, e);
+}
+ /*
+** OPENXSCRIPT -- Open transcript file
+**
+** Creates a transcript file for possible eventual mailing or
+** sending back.
+**
+** Parameters:
+** e -- the envelope to create the transcript in/for.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Creates the transcript file.
+*/
+
+#ifndef O_APPEND
+#define O_APPEND 0
+#endif
+
+void
+openxscript(e)
+ register ENVELOPE *e;
+{
+ register char *p;
+ int fd;
+
+ if (e->e_xfp != NULL)
+ return;
+ p = queuename(e, 'x');
+ fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ if (fd < 0)
+ {
+ syserr("Can't create transcript file %s", p);
+ fd = open("/dev/null", O_WRONLY, 0644);
+ if (fd < 0)
+ syserr("!Can't open /dev/null");
+ }
+ e->e_xfp = fdopen(fd, "a");
+ if (e->e_xfp == NULL)
+ syserr("!Can't create transcript stream %s", p);
+#ifdef HASSETVBUF
+ setvbuf(e->e_xfp, NULL, _IOLBF, 0);
+#else
+ setlinebuf(e->e_xfp);
+#endif
+ if (tTd(46, 9))
+ {
+ printf("openxscript(%s):\n ", p);
+ dumpfd(fileno(e->e_xfp), TRUE, FALSE);
+ }
+}
+ /*
+** CLOSEXSCRIPT -- close the transcript file.
+**
+** Parameters:
+** e -- the envelope containing the transcript to close.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+void
+closexscript(e)
+ register ENVELOPE *e;
+{
+ if (e->e_xfp == NULL)
+ return;
+ (void) xfclose(e->e_xfp, "closexscript", e->e_id);
+ e->e_xfp = NULL;
+}
+ /*
+** SETSENDER -- set the person who this message is from
+**
+** Under certain circumstances allow the user to say who
+** s/he is (using -f or -r). These are:
+** 1. The user's uid is zero (root).
+** 2. The user's login name is in an approved list (typically
+** from a network server).
+** 3. The address the user is trying to claim has a
+** "!" character in it (since #2 doesn't do it for
+** us if we are dialing out for UUCP).
+** A better check to replace #3 would be if the
+** effective uid is "UUCP" -- this would require me
+** to rewrite getpwent to "grab" uucp as it went by,
+** make getname more nasty, do another passwd file
+** scan, or compile the UID of "UUCP" into the code,
+** all of which are reprehensible.
+**
+** Assuming all of these fail, we figure out something
+** ourselves.
+**
+** 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.
+**
+** Side Effects:
+** sets sendmail's notion of who the from person is.
+*/
+
+void
+setsender(from, e, delimptr, internal)
+ char *from;
+ register ENVELOPE *e;
+ char **delimptr;
+ bool internal;
+{
+ register char **pvp;
+ char *realname = NULL;
+ register struct passwd *pw;
+ char delimchar;
+ char *bp;
+ char buf[MAXNAME + 2];
+ char pvpbuf[PSBUFSIZE];
+ extern char *FullName;
+
+ if (tTd(45, 1))
+ printf("setsender(%s)\n", from == NULL ? "" : from);
+
+ /*
+ ** Figure out the real user executing us.
+ ** Username can return errno != 0 on non-errors.
+ */
+
+ if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
+ OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
+ realname = from;
+ if (realname == NULL || realname[0] == '\0')
+ realname = username();
+
+ if (ConfigLevel < 2)
+ SuprErrs = TRUE;
+
+ delimchar = internal ? '\0' : ' ';
+ e->e_from.q_flags = QBADADDR;
+ if (from == NULL ||
+ parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
+ delimchar, delimptr, e) == NULL ||
+ bitset(QBADADDR, e->e_from.q_flags) ||
+ e->e_from.q_mailer == ProgMailer ||
+ e->e_from.q_mailer == FileMailer ||
+ e->e_from.q_mailer == InclMailer)
+ {
+ /* log garbage addresses for traceback */
+# ifdef 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",
+ MAXNAME, realname,
+ MAXNAME, host);
+ p = ebuf;
+ }
+ syslog(LOG_NOTICE,
+ "setsender: %s: invalid or unparseable, received from %s",
+ shortenstring(from, 83), p);
+ }
+# endif /* LOG */
+ if (from != NULL)
+ {
+ if (!bitset(QBADADDR, e->e_from.q_flags))
+ {
+ /* it was a bogus mailer in the from addr */
+ e->e_status = "5.1.7";
+ usrerr("553 Invalid sender address");
+ }
+ SuprErrs = TRUE;
+ }
+ if (from == realname ||
+ parseaddr(from = newstr(realname), &e->e_from,
+ RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
+ {
+ char nbuf[100];
+
+ SuprErrs = TRUE;
+ expand("\201n", nbuf, sizeof nbuf, e);
+ if (parseaddr(from = newstr(nbuf), &e->e_from,
+ RF_COPYALL, ' ', NULL, e) == NULL &&
+ parseaddr(from = "postmaster", &e->e_from,
+ RF_COPYALL, ' ', NULL, e) == NULL)
+ syserr("553 setsender: can't even parse postmaster!");
+ }
+ }
+ else
+ FromFlag = TRUE;
+ e->e_from.q_flags |= QDONTSEND;
+ if (tTd(45, 5))
+ {
+ printf("setsender: QDONTSEND ");
+ printaddr(&e->e_from, FALSE);
+ }
+ SuprErrs = FALSE;
+
+# if USERDB
+ if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags))
+ {
+ register char *p;
+ extern char *udbsender();
+
+ p = udbsender(e->e_from.q_user);
+ if (p != NULL)
+ from = p;
+ }
+# endif /* USERDB */
+
+ if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
+ {
+ if (!internal)
+ {
+ /* if the user already given fullname don't redefine */
+ if (FullName == NULL)
+ FullName = macvalue('x', e);
+ if (FullName != NULL && FullName[0] == '\0')
+ FullName = NULL;
+ }
+
+ if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL)
+ {
+ /*
+ ** Process passwd file entry.
+ */
+
+ /* extract home directory */
+ if (strcmp(pw->pw_dir, "/") == 0)
+ e->e_from.q_home = newstr("");
+ else
+ 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;
+ e->e_from.q_flags |= QGOODUID;
+
+ /* 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 && !internal)
+ define('x', FullName, e);
+ }
+ else if (!internal && OpMode != MD_DAEMON)
+ {
+ if (e->e_from.q_home == NULL)
+ {
+ e->e_from.q_home = getenv("HOME");
+ if (e->e_from.q_home != NULL &&
+ strcmp(e->e_from.q_home, "/") == 0)
+ e->e_from.q_home++;
+ }
+ e->e_from.q_uid = RealUid;
+ e->e_from.q_gid = RealGid;
+ e->e_from.q_flags |= QGOODUID;
+ }
+
+ /*
+ ** Rewrite the from person to dispose of possible implicit
+ ** links in the net.
+ */
+
+ pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL, NULL);
+ if (pvp == NULL)
+ {
+ /* don't need to give error -- prescan did that already */
+# ifdef LOG
+ if (LogLevel > 2)
+ syslog(LOG_NOTICE, "cannot prescan from (%s)",
+ shortenstring(from, 203));
+# endif
+ finis();
+ }
+ (void) rewrite(pvp, 3, 0, e);
+ (void) rewrite(pvp, 1, 0, e);
+ (void) rewrite(pvp, 4, 0, e);
+ bp = buf + 1;
+ cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
+ if (*bp == '@' && !bitnset(M_NOBRACKET, e->e_from.q_mailer->m_flags))
+ {
+ /* heuristic: route-addr: add angle brackets */
+ strcat(bp, ">");
+ *--bp = '<';
+ }
+ e->e_sender = newstr(bp);
+ define('f', e->e_sender, e);
+
+ /* save the domain spec if this mailer wants it */
+ if (e->e_from.q_mailer != NULL &&
+ bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
+ {
+ char **lastat;
+ extern char **copyplist();
+
+ /* get rid of any pesky angle brackets */
+ (void) rewrite(pvp, 3, 0, e);
+ (void) rewrite(pvp, 1, 0, e);
+ (void) rewrite(pvp, 4, 0, e);
+
+ /* strip off to the last "@" sign */
+ for (lastat = NULL; *pvp != NULL; pvp++)
+ if (strcmp(*pvp, "@") == 0)
+ lastat = pvp;
+ if (lastat != NULL)
+ {
+ e->e_fromdomain = copyplist(lastat, TRUE);
+ if (tTd(45, 3))
+ {
+ printf("Saving from domain: ");
+ printav(e->e_fromdomain);
+ }
+ }
+ }
+}
+ /*
+** PRINTENVFLAGS -- print envelope flags for debugging
+**
+** Parameters:
+** e -- the envelope with the flags to be printed.
+**
+** Returns:
+** none.
+*/
+
+struct eflags
+{
+ char *ef_name;
+ u_long ef_bit;
+};
+
+struct eflags EnvelopeFlags[] =
+{
+ "OLDSTYLE", EF_OLDSTYLE,
+ "INQUEUE", EF_INQUEUE,
+ "NO_BODY_RETN", EF_NO_BODY_RETN,
+ "CLRQUEUE", EF_CLRQUEUE,
+ "SENDRECEIPT", EF_SENDRECEIPT,
+ "FATALERRS", EF_FATALERRS,
+ "DELETE_BCC", EF_DELETE_BCC,
+ "RESPONSE", EF_RESPONSE,
+ "RESENT", EF_RESENT,
+ "VRFYONLY", EF_VRFYONLY,
+ "WARNING", EF_WARNING,
+ "QUEUERUN", EF_QUEUERUN,
+ "GLOBALERRS", EF_GLOBALERRS,
+ "PM_NOTIFY", EF_PM_NOTIFY,
+ "METOO", EF_METOO,
+ "LOGSENDER", EF_LOGSENDER,
+ "NORECEIPT", EF_NORECEIPT,
+ "HAS8BIT", EF_HAS8BIT,
+ "NL_NOT_EOL", EF_NL_NOT_EOL,
+ "CRLF_NOT_EOL", EF_CRLF_NOT_EOL,
+ "RET_PARAM", EF_RET_PARAM,
+ "HAS_DF", EF_HAS_DF,
+ "IS_MIME", EF_IS_MIME,
+ "DONT_MIME", EF_DONT_MIME,
+ NULL
+};
+
+void
+printenvflags(e)
+ register ENVELOPE *e;
+{
+ register struct eflags *ef;
+ bool first = TRUE;
+
+ printf("%lx", e->e_flags);
+ for (ef = EnvelopeFlags; ef->ef_name != NULL; ef++)
+ {
+ if (!bitset(ef->ef_bit, e->e_flags))
+ continue;
+ if (first)
+ printf("<%s", ef->ef_name);
+ else
+ printf(",%s", ef->ef_name);
+ first = FALSE;
+ }
+ if (!first)
+ printf(">\n");
+}
diff --git a/usr.sbin/sendmail/src/err.c b/usr.sbin/sendmail/src/err.c
new file mode 100644
index 000000000000..6acb8fbeed27
--- /dev/null
+++ b/usr.sbin/sendmail/src/err.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)err.c 8.41 (Berkeley) 10/8/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+# include <errno.h>
+
+/*
+** SYSERR -- Print error message.
+**
+** 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:
+** fmt -- the format string. If it does not begin with
+** a three-digit SMTP reply code, either 554 or
+** 451 is assumed depending on whether errno
+** is set.
+** (others) -- parameters
+**
+** Returns:
+** none
+** Through TopFrame if QuickAbort is set.
+**
+** Side Effects:
+** increments Errors.
+** sets ExitStat.
+*/
+
+char MsgBuf[BUFSIZ*2]; /* text of most recent message */
+char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */
+
+extern void putoutmsg __P((char *, bool, bool));
+extern void puterrmsg __P((char *));
+static void fmtmsg __P((char *, const char *, const char *, int, const char *, va_list));
+
+#if NAMED_BIND && !defined(NO_DATA)
+# define NO_DATA NO_ADDRESS
+#endif
+
+void
+/*VARARGS1*/
+#ifdef __STDC__
+syserr(const char *fmt, ...)
+#else
+syserr(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ register char *p;
+ int olderrno = errno;
+ bool panic;
+#ifdef LOG
+ char *uname;
+ struct passwd *pw;
+ char ubuf[80];
+#endif
+ VA_LOCAL_DECL
+
+ panic = *fmt == '!';
+ if (panic)
+ fmt++;
+
+ /* format and output the error message */
+ if (olderrno == 0)
+ p = "554";
+ else
+ p = "451";
+ VA_START(fmt);
+ fmtmsg(MsgBuf, (char *) NULL, p, olderrno, fmt, ap);
+ VA_END;
+ puterrmsg(MsgBuf);
+
+ /* save this message for mailq printing */
+ if (!panic)
+ {
+ if (CurEnv->e_message != NULL)
+ free(CurEnv->e_message);
+ CurEnv->e_message = newstr(MsgBuf + 4);
+ }
+
+ /* determine exit status if not already set */
+ if (ExitStat == EX_OK)
+ {
+ if (olderrno == 0)
+ ExitStat = EX_SOFTWARE;
+ else
+ ExitStat = EX_OSERR;
+ if (tTd(54, 1))
+ printf("syserr: ExitStat = %d\n", ExitStat);
+ }
+
+# ifdef LOG
+ pw = sm_getpwuid(getuid());
+ if (pw != NULL)
+ uname = pw->pw_name;
+ else
+ {
+ uname = ubuf;
+ sprintf(ubuf, "UID%d", getuid());
+ }
+
+ if (LogLevel > 0)
+ syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR(%s): %.900s",
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ uname, &MsgBuf[4]);
+# endif /* LOG */
+ if (olderrno == EMFILE)
+ {
+ printopenfds(TRUE);
+ mci_dump_all(TRUE);
+ }
+ if (panic)
+ {
+#ifdef XLA
+ xla_all_end();
+#endif
+ if (tTd(0, 1))
+ abort();
+ exit(EX_OSERR);
+ }
+ errno = 0;
+ if (QuickAbort)
+ longjmp(TopFrame, 2);
+}
+ /*
+** USRERR -- Signal user error.
+**
+** This is much like syserr except it is for user errors.
+**
+** Parameters:
+** fmt -- the format string. If it does not begin with
+** a three-digit SMTP reply code, 501 is assumed.
+** (others) -- printf strings
+**
+** Returns:
+** none
+** Through TopFrame if QuickAbort is set.
+**
+** Side Effects:
+** increments Errors.
+*/
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+usrerr(const char *fmt, ...)
+#else
+usrerr(fmt, va_alist)
+ const char *fmt;
+ va_dcl
+#endif
+{
+ VA_LOCAL_DECL
+
+ if (SuprErrs)
+ return;
+
+ VA_START(fmt);
+ fmtmsg(MsgBuf, CurEnv->e_to, "501", 0, fmt, ap);
+ VA_END;
+
+ /* save this message for mailq printing */
+ switch (MsgBuf[0])
+ {
+ case '4':
+ case '8':
+ if (CurEnv->e_message != NULL)
+ break;
+
+ /* fall through.... */
+
+ case '5':
+ case '6':
+ if (CurEnv->e_message != NULL)
+ free(CurEnv->e_message);
+ if (MsgBuf[0] == '6')
+ {
+ char buf[MAXLINE];
+
+ sprintf(buf, "Postmaster warning: %.*s",
+ sizeof buf - 22, MsgBuf + 4);
+ CurEnv->e_message = newstr(buf);
+ }
+ else
+ {
+ CurEnv->e_message = newstr(MsgBuf + 4);
+ }
+ break;
+ }
+
+ puterrmsg(MsgBuf);
+
+# ifdef LOG
+ if (LogLevel > 3 && LogUsrErrs)
+ syslog(LOG_NOTICE, "%s: %.900s",
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ &MsgBuf[4]);
+# endif /* LOG */
+
+ if (QuickAbort)
+ longjmp(TopFrame, 1);
+}
+ /*
+** MESSAGE -- print message (not necessarily an error)
+**
+** Parameters:
+** msg -- the message (printf fmt) -- it can begin with
+** an SMTP reply code. If not, 050 is assumed.
+** (others) -- printf arguments
+**
+** Returns:
+** none
+**
+** Side Effects:
+** none.
+*/
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+message(const char *msg, ...)
+#else
+message(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ VA_LOCAL_DECL
+
+ errno = 0;
+ VA_START(msg);
+ fmtmsg(MsgBuf, CurEnv->e_to, "050", 0, msg, ap);
+ VA_END;
+ putoutmsg(MsgBuf, FALSE, FALSE);
+
+ /* save this message for mailq printing */
+ switch (MsgBuf[0])
+ {
+ case '4':
+ case '8':
+ if (CurEnv->e_message != NULL)
+ break;
+ /* fall through.... */
+
+ case '5':
+ if (CurEnv->e_message != NULL)
+ free(CurEnv->e_message);
+ CurEnv->e_message = newstr(MsgBuf + 4);
+ break;
+ }
+}
+ /*
+** NMESSAGE -- print message (not necessarily an error)
+**
+** Just like "message" except it never puts the to... tag on.
+**
+** Parameters:
+** msg -- the message (printf fmt) -- if it begins
+** with a three digit SMTP reply code, that is used,
+** otherwise 050 is assumed.
+** (others) -- printf arguments
+**
+** Returns:
+** none
+**
+** Side Effects:
+** none.
+*/
+
+/*VARARGS2*/
+void
+#ifdef __STDC__
+nmessage(const char *msg, ...)
+#else
+nmessage(msg, va_alist)
+ const char *msg;
+ va_dcl
+#endif
+{
+ VA_LOCAL_DECL
+
+ errno = 0;
+ VA_START(msg);
+ fmtmsg(MsgBuf, (char *) NULL, "050", 0, msg, ap);
+ VA_END;
+ putoutmsg(MsgBuf, FALSE, FALSE);
+
+ /* save this message for mailq printing */
+ switch (MsgBuf[0])
+ {
+ case '4':
+ case '8':
+ if (CurEnv->e_message != NULL)
+ break;
+ /* fall through.... */
+
+ case '5':
+ if (CurEnv->e_message != NULL)
+ free(CurEnv->e_message);
+ CurEnv->e_message = newstr(MsgBuf + 4);
+ break;
+ }
+}
+ /*
+** PUTOUTMSG -- output error message to transcript and channel
+**
+** Parameters:
+** msg -- message to output (in SMTP format).
+** holdmsg -- if TRUE, don't output a copy of the message to
+** our output channel.
+** heldmsg -- if TRUE, this is a previously held message;
+** don't log it to the transcript file.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Outputs msg to the transcript.
+** If appropriate, outputs it to the channel.
+** Deletes SMTP reply code number as appropriate.
+*/
+
+void
+putoutmsg(msg, holdmsg, heldmsg)
+ char *msg;
+ bool holdmsg;
+ bool heldmsg;
+{
+ char msgcode = msg[0];
+
+ /* display for debugging */
+ if (tTd(54, 8))
+ printf("--- %s%s%s\n", msg, holdmsg ? " (hold)" : "",
+ heldmsg ? " (held)" : "");
+
+ /* map warnings to something SMTP can handle */
+ if (msgcode == '6')
+ msg[0] = '5';
+ else if (msgcode == '8')
+ msg[0] = '4';
+
+ /* output to transcript if serious */
+ if (!heldmsg && CurEnv->e_xfp != NULL && strchr("45", msg[0]) != NULL)
+ fprintf(CurEnv->e_xfp, "%s\n", msg);
+
+ if (msgcode == '8')
+ msg[0] == '0';
+
+ /* output to channel if appropriate */
+ if (!Verbose && msg[0] == '0')
+ return;
+ if (holdmsg)
+ {
+ /* save for possible future display */
+ msg[0] = msgcode;
+ strcpy(HeldMessageBuf, msg);
+ return;
+ }
+
+ (void) fflush(stdout);
+
+ /* if DisConnected, OutChannel now points to the transcript */
+ if (!DisConnected &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
+ fprintf(OutChannel, "%s\r\n", msg);
+ else
+ fprintf(OutChannel, "%s\n", &msg[4]);
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(),
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
+ if (msg[3] == ' ')
+ (void) fflush(OutChannel);
+ if (!ferror(OutChannel) || DisConnected)
+ return;
+
+ /*
+ ** Error on output -- if reporting lost channel, just ignore it.
+ ** Also, ignore errors from QUIT response (221 message) -- some
+ ** rude servers don't read result.
+ */
+
+ if (feof(InChannel) || ferror(InChannel) || strncmp(msg, "221", 3) == 0)
+ return;
+
+ /* can't call syserr, 'cause we are using MsgBuf */
+ HoldErrs = TRUE;
+#ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_CRIT,
+ "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s",
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ CurHostName == NULL ? "NO-HOST" : CurHostName,
+ shortenstring(msg, 203), errstring(errno));
+#endif
+}
+ /*
+** PUTERRMSG -- like putoutmsg, but does special processing for error messages
+**
+** Parameters:
+** msg -- the message to output.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Sets the fatal error bit in the envelope as appropriate.
+*/
+
+void
+puterrmsg(msg)
+ char *msg;
+{
+ char msgcode = msg[0];
+
+ /* output the message as usual */
+ putoutmsg(msg, HoldErrs, FALSE);
+
+ /* signal the error */
+ Errors++;
+ if (msgcode == '6')
+ {
+ /* notify the postmaster */
+ CurEnv->e_flags |= EF_PM_NOTIFY;
+ }
+ else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
+ {
+ /* mark long-term fatal errors */
+ CurEnv->e_flags |= EF_FATALERRS;
+ }
+}
+ /*
+** FMTMSG -- format a message into buffer.
+**
+** Parameters:
+** eb -- error buffer to get result.
+** to -- the recipient tag for this message.
+** num -- arpanet error number.
+** en -- the error number to display.
+** fmt -- format of string.
+** a, b, c, d, e -- arguments.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+static void
+fmtmsg(eb, to, num, eno, fmt, ap)
+ register char *eb;
+ const char *to;
+ const char *num;
+ int eno;
+ const char *fmt;
+ va_list ap;
+{
+ char del;
+ char *meb;
+ int l;
+ int spaceleft = sizeof MsgBuf;
+
+ /* output the reply code */
+ if (isdigit(fmt[0]) && isdigit(fmt[1]) && isdigit(fmt[2]))
+ {
+ num = fmt;
+ fmt += 4;
+ }
+ if (num[3] == '-')
+ del = '-';
+ else
+ del = ' ';
+ (void) sprintf(eb, "%3.3s%c", num, del);
+ eb += 4;
+ spaceleft -= 4;
+
+ /* output the file name and line number */
+ if (FileName != NULL)
+ {
+ (void) snprintf(eb, spaceleft, "%s: line %d: ",
+ shortenstring(FileName, 83), LineNumber);
+ eb += (l = strlen(eb));
+ spaceleft -= l;
+ }
+
+ /* output the "to" person */
+ if (to != NULL && to[0] != '\0')
+ {
+ (void) snprintf(eb, spaceleft, "%s... ",
+ shortenstring(to, 203));
+ spaceleft -= strlen(eb);
+ while (*eb != '\0')
+ *eb++ &= 0177;
+ }
+
+ meb = eb;
+
+ /* output the message */
+ (void) vsnprintf(eb, spaceleft, fmt, ap);
+ spaceleft -= strlen(eb);
+ while (*eb != '\0')
+ *eb++ &= 0177;
+
+ /* output the error code, if any */
+ if (eno != 0)
+ (void) snprintf(eb, spaceleft, ": %s", errstring(eno));
+}
+ /*
+** BUFFER_ERRORS -- arrange to buffer future error messages
+**
+** Parameters:
+** none
+**
+** Returns:
+** none.
+*/
+
+void
+buffer_errors()
+{
+ HeldMessageBuf[0] = '\0';
+ HoldErrs = TRUE;
+}
+ /*
+** FLUSH_ERRORS -- flush the held error message buffer
+**
+** Parameters:
+** print -- if set, print the message, otherwise just
+** delete it.
+**
+** Returns:
+** none.
+*/
+
+void
+flush_errors(print)
+ bool print;
+{
+ if (print && HeldMessageBuf[0] != '\0')
+ putoutmsg(HeldMessageBuf, FALSE, TRUE);
+ HeldMessageBuf[0] = '\0';
+ HoldErrs = FALSE;
+}
+ /*
+** ERRSTRING -- return string description of error code
+**
+** Parameters:
+** errnum -- the error number to translate
+**
+** Returns:
+** A string description of errnum.
+**
+** Side Effects:
+** none.
+*/
+
+const char *
+errstring(errnum)
+ int errnum;
+{
+ char *dnsmsg;
+ static char buf[MAXLINE];
+# ifndef ERRLIST_PREDEFINED
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+# endif
+# ifdef SMTP
+ extern char *SmtpPhase;
+# endif /* SMTP */
+
+ /*
+ ** Handle special network error codes.
+ **
+ ** These are 4.2/4.3bsd specific; they should be in daemon.c.
+ */
+
+ dnsmsg = NULL;
+ switch (errnum)
+ {
+# if defined(DAEMON) && defined(ETIMEDOUT)
+ case ETIMEDOUT:
+ case ECONNRESET:
+ (void) strcpy(buf, sys_errlist[errnum]);
+ if (SmtpPhase != NULL)
+ {
+ (void) strcat(buf, " during ");
+ (void) strcat(buf, SmtpPhase);
+ }
+ if (CurHostName != NULL)
+ {
+ (void) strcat(buf, " with ");
+ (void) strcat(buf, CurHostName);
+ }
+ return (buf);
+
+ case EHOSTDOWN:
+ if (CurHostName == NULL)
+ break;
+ (void) sprintf(buf, "Host %s is down",
+ shortenstring(CurHostName, 203));
+ return (buf);
+
+ case ECONNREFUSED:
+ if (CurHostName == NULL)
+ break;
+ (void) sprintf(buf, "Connection refused by %s",
+ shortenstring(CurHostName, 203));
+ return (buf);
+# endif
+
+ case EOPENTIMEOUT:
+ return "Timeout on file open";
+
+# if NAMED_BIND
+ case HOST_NOT_FOUND + E_DNSBASE:
+ dnsmsg = "host not found";
+ break;
+
+ case TRY_AGAIN + E_DNSBASE:
+ dnsmsg = "host name lookup failure";
+ break;
+
+ case NO_RECOVERY + E_DNSBASE:
+ dnsmsg = "non-recoverable error";
+ break;
+
+ case NO_DATA + E_DNSBASE:
+ dnsmsg = "no data known";
+ break;
+# endif
+
+ case EPERM:
+ /* SunOS gives "Not owner" -- this is the POSIX message */
+ return "Operation not permitted";
+ }
+
+ if (dnsmsg != NULL)
+ {
+ (void) strcpy(buf, "Name server: ");
+ if (CurHostName != NULL)
+ {
+ (void) strcat(buf, CurHostName);
+ (void) strcat(buf, ": ");
+ }
+ (void) strcat(buf, dnsmsg);
+ return buf;
+ }
+
+ if (errnum > 0 && errnum < sys_nerr)
+ return (sys_errlist[errnum]);
+
+ (void) sprintf(buf, "Error %d", errnum);
+ return (buf);
+}
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
new file mode 100644
index 000000000000..ae242b1e258a
--- /dev/null
+++ b/usr.sbin/sendmail/src/headers.c
@@ -0,0 +1,1477 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)headers.c 8.82 (Berkeley) 10/28/95";
+#endif /* not lint */
+
+# include <errno.h>
+# include "sendmail.h"
+
+/*
+** CHOMPHEADER -- process and save a header line.
+**
+** Called by collect and by readcf to deal with header lines.
+**
+** Parameters:
+** line -- header as a text line.
+** def -- if set, this is a default value.
+** hdrp -- a pointer to the place to save the header.
+** e -- the envelope including this header.
+**
+** Returns:
+** flags for this header.
+**
+** Side Effects:
+** The header is saved on the header list.
+** Contents of 'line' are destroyed.
+*/
+
+int
+chompheader(line, def, hdrp, e)
+ char *line;
+ bool def;
+ HDR **hdrp;
+ register ENVELOPE *e;
+{
+ register char *p;
+ register HDR *h;
+ HDR **hp;
+ char *fname;
+ char *fvalue;
+ struct hdrinfo *hi;
+ bool cond = FALSE;
+ bool headeronly;
+ BITMAP mopts;
+ char buf[MAXNAME + 1];
+
+ if (tTd(31, 6))
+ {
+ printf("chompheader: ");
+ xputs(line);
+ printf("\n");
+ }
+
+ headeronly = hdrp != NULL;
+ if (!headeronly)
+ hdrp = &e->e_header;
+
+ /* strip off options */
+ clrbitmap(mopts);
+ p = line;
+ if (*p == '?')
+ {
+ /* have some */
+ register char *q = strchr(p + 1, *p);
+
+ if (q != NULL)
+ {
+ *q++ = '\0';
+ while (*++p != '\0')
+ setbitn(*p, mopts);
+ p = q;
+ }
+ else
+ syserr("553 header syntax error, line \"%s\"", line);
+ cond = TRUE;
+ }
+
+ /* find canonical name */
+ fname = p;
+ while (isascii(*p) && isgraph(*p) && *p != ':')
+ p++;
+ fvalue = p;
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p++ != ':' || fname == fvalue)
+ {
+ syserr("553 header syntax error, line \"%s\"", line);
+ return (0);
+ }
+ *fvalue = '\0';
+ fvalue = p;
+
+ /* strip field value on front */
+ if (*fvalue == ' ')
+ fvalue++;
+
+ /* security scan: long field names are end-of-header */
+ if (strlen(fname) > 100)
+ return H_EOH;
+
+ /* see if it is a known type */
+ for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+ {
+ if (strcasecmp(hi->hi_field, fname) == 0)
+ break;
+ }
+
+ if (tTd(31, 9))
+ {
+ if (hi->hi_field == NULL)
+ printf("no header match\n");
+ else
+ printf("header match, hi_flags=%x\n", hi->hi_flags);
+ }
+
+ /* see if this is a resent message */
+ if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags))
+ e->e_flags |= EF_RESENT;
+
+ /* if this is an Errors-To: header keep track of it now */
+ if (UseErrorsTo && !def && !headeronly &&
+ bitset(H_ERRORSTO, hi->hi_flags))
+ (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e);
+
+ /* if this means "end of header" quit now */
+ if (bitset(H_EOH, hi->hi_flags))
+ return (hi->hi_flags);
+
+#ifdef LOTUS_NOTES_HACK
+ /*
+ ** Horrible hack to work around problem with Lotus Notes SMTP
+ ** mail gateway, which generates From: headers with newlines in
+ ** them and the <address> on the second line. Although this is
+ ** legal RFC 822, many MUAs don't handle this properly and thus
+ ** never find the actual address.
+ */
+
+ if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader)
+ {
+ while ((p = strchr(fvalue, '\n')) != NULL)
+ *p = ' ';
+ }
+#endif
+
+ /*
+ ** Drop explicit From: if same as what we would generate.
+ ** This is to make MH (which doesn't always give a full name)
+ ** insert the full name information in all circumstances.
+ */
+
+ p = "resent-from";
+ if (!bitset(EF_RESENT, e->e_flags))
+ p += 7;
+ if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) &&
+ strcasecmp(fname, p) == 0)
+ {
+ if (tTd(31, 2))
+ {
+ printf("comparing header from (%s) against default (%s or %s)\n",
+ fvalue, e->e_from.q_paddr, e->e_from.q_user);
+ }
+ if (e->e_from.q_paddr != NULL &&
+ (strcmp(fvalue, e->e_from.q_paddr) == 0 ||
+ strcmp(fvalue, e->e_from.q_user) == 0))
+ return (hi->hi_flags);
+#ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
+#if USERDB
+ else
+ {
+ auto ADDRESS a;
+ char *fancy;
+ bool oldSuprErrs = SuprErrs;
+ extern char *crackaddr();
+ extern char *udbsender();
+
+ /*
+ ** Try doing USERDB rewriting even on fully commented
+ ** names; this saves the "comment" information (such
+ ** as full name) and rewrites the electronic part.
+ **
+ ** XXX This code doesn't belong here -- parsing should
+ ** XXX not be done during collect() phase because
+ ** XXX error messages can confuse the SMTP phase.
+ ** XXX Setting SuprErrs is a crude hack around this
+ ** XXX problem.
+ */
+
+ if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
+ SuprErrs = TRUE;
+ fancy = crackaddr(fvalue);
+ if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
+ bitnset(M_CHECKUDB, a.q_mailer->m_flags) &&
+ (p = udbsender(a.q_user)) != NULL)
+ {
+ char *oldg = macvalue('g', e);
+
+ define('g', p, e);
+ expand(fancy, buf, sizeof buf, e);
+ define('g', oldg, e);
+ fvalue = buf;
+ }
+ SuprErrs = oldSuprErrs;
+ }
+#endif
+#endif
+ }
+
+ /* delete default value for this header */
+ for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link)
+ {
+ if (strcasecmp(fname, h->h_field) == 0 &&
+ bitset(H_DEFAULT, h->h_flags) &&
+ !bitset(H_FORCE, h->h_flags))
+ {
+ h->h_value = NULL;
+ if (!cond)
+ {
+ /* copy conditions from default case */
+ bcopy((char *)h->h_mflags, (char *)mopts,
+ sizeof mopts);
+ }
+ }
+ }
+
+ /* create a new node */
+ h = (HDR *) xalloc(sizeof *h);
+ h->h_field = newstr(fname);
+ h->h_value = newstr(fvalue);
+ h->h_link = NULL;
+ bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
+ *hp = h;
+ h->h_flags = hi->hi_flags;
+ if (def)
+ h->h_flags |= H_DEFAULT;
+ if (cond)
+ h->h_flags |= H_CHECK;
+
+ /* hack to see if this is a new format message */
+ if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) &&
+ (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL ||
+ strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL))
+ {
+ e->e_flags &= ~EF_OLDSTYLE;
+ }
+
+ return (h->h_flags);
+}
+ /*
+** ADDHEADER -- add a header entry to the end of the queue.
+**
+** This bypasses the special checking of chompheader.
+**
+** Parameters:
+** field -- the name of the header field.
+** value -- the value of the field.
+** hp -- an indirect pointer to the header structure list.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** adds the field on the list of headers for this envelope.
+*/
+
+void
+addheader(field, value, hdrlist)
+ char *field;
+ char *value;
+ HDR **hdrlist;
+{
+ register HDR *h;
+ register struct hdrinfo *hi;
+ HDR **hp;
+
+ /* find info struct */
+ for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+ {
+ if (strcasecmp(field, hi->hi_field) == 0)
+ break;
+ }
+
+ /* find current place in list -- keep back pointer? */
+ for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link)
+ {
+ if (strcasecmp(field, h->h_field) == 0)
+ break;
+ }
+
+ /* allocate space for new header */
+ h = (HDR *) xalloc(sizeof *h);
+ h->h_field = field;
+ h->h_value = newstr(value);
+ h->h_link = *hp;
+ h->h_flags = hi->hi_flags | H_DEFAULT;
+ clrbitmap(h->h_mflags);
+ *hp = h;
+}
+ /*
+** HVALUE -- return value of a header.
+**
+** Only "real" fields (i.e., ones that have not been supplied
+** as a default) are used.
+**
+** Parameters:
+** field -- the field name.
+** header -- the header list.
+**
+** Returns:
+** pointer to the value part.
+** NULL if not found.
+**
+** Side Effects:
+** none.
+*/
+
+char *
+hvalue(field, header)
+ char *field;
+ HDR *header;
+{
+ register HDR *h;
+
+ for (h = header; h != NULL; h = h->h_link)
+ {
+ if (!bitset(H_DEFAULT, h->h_flags) &&
+ strcasecmp(h->h_field, field) == 0)
+ return (h->h_value);
+ }
+ return (NULL);
+}
+ /*
+** ISHEADER -- predicate telling if argument is a header.
+**
+** A line is a header if it has a single word followed by
+** optional white space followed by a colon.
+**
+** Header fields beginning with two dashes, although technically
+** permitted by RFC822, are automatically rejected in order
+** to make MIME work out. Without this we could have a technically
+** legal header such as ``--"foo:bar"'' that would also be a legal
+** MIME separator.
+**
+** Parameters:
+** h -- string to check for possible headerness.
+**
+** Returns:
+** TRUE if h is a header.
+** FALSE otherwise.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+isheader(h)
+ char *h;
+{
+ register char *s = h;
+
+ if (s[0] == '-' && s[1] == '-')
+ return FALSE;
+
+ while (*s > ' ' && *s != ':' && *s != '\0')
+ s++;
+
+ if (h == s)
+ return FALSE;
+
+ /* following technically violates RFC822 */
+ while (isascii(*s) && isspace(*s))
+ s++;
+
+ return (*s == ':');
+}
+ /*
+** EATHEADER -- run through the stored header and extract info.
+**
+** Parameters:
+** e -- the envelope to process.
+** full -- if set, do full processing (e.g., compute
+** message priority). This should not be set
+** when reading a queue file because some info
+** needed to compute the priority is wrong.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Sets a bunch of global variables from information
+** in the collected header.
+** Aborts the message if the hop count is exceeded.
+*/
+
+void
+eatheader(e, full)
+ register ENVELOPE *e;
+ bool full;
+{
+ 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 (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
+ define('u', e->e_origrcpt, e);
+ else
+ define('u', NULL, e);
+
+ /* full name of from person */
+ p = hvalue("full-name", e->e_header);
+ if (p != NULL)
+ define('x', p, e);
+
+ if (tTd(32, 1))
+ printf("----- collected header -----\n");
+ msgid = NULL;
+ for (h = e->e_header; h != NULL; h = h->h_link)
+ {
+ if (tTd(32, 1))
+ printf("%s: ", h->h_field);
+ if (h->h_value == NULL)
+ {
+ if (tTd(32, 1))
+ printf("<NULL>\n");
+ continue;
+ }
+
+ /* do early binding */
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ if (tTd(32, 1))
+ {
+ printf("(");
+ xputs(h->h_value);
+ printf(") ");
+ }
+ expand(h->h_value, buf, sizeof buf, e);
+ if (buf[0] != '\0')
+ {
+ if (bitset(H_FROM, h->h_flags))
+ {
+ extern char *crackaddr();
+
+ expand(crackaddr(buf), buf, sizeof buf, e);
+ }
+ h->h_value = newstr(buf);
+ h->h_flags &= ~H_DEFAULT;
+ }
+ }
+
+ if (tTd(32, 1))
+ {
+ xputs(h->h_value);
+ printf("\n");
+ }
+
+ /* count the number of times it has been processed */
+ if (bitset(H_TRACE, h->h_flags))
+ hopcnt++;
+
+ /* 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, e->e_flags) || bitset(H_RESENT, h->h_flags)))
+ {
+ int saveflags = e->e_flags;
+
+ (void) sendtolist(h->h_value, NULLADDR,
+ &e->e_sendqueue, 0, e);
+
+ /* delete fatal errors generated by this address */
+ if (!GrabTo && !bitset(EF_FATALERRS, saveflags))
+ e->e_flags &= ~EF_FATALERRS;
+ }
+
+ /* save the message-id for logging */
+ p = "resent-message-id";
+ if (!bitset(EF_RESENT, e->e_flags))
+ p += 7;
+ if (strcasecmp(h->h_field, p) == 0)
+ {
+ msgid = h->h_value;
+ while (isascii(*msgid) && isspace(*msgid))
+ msgid++;
+ }
+
+ /* see if this is a return-receipt header */
+ if (bitset(H_RECEIPTTO, h->h_flags))
+ e->e_receiptto = h->h_value;
+ }
+ 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 */
+ p = hvalue("precedence", e->e_header);
+ if (p != NULL)
+ e->e_class = priencode(p);
+ if (e->e_class < 0)
+ e->e_timeoutclass = TOC_NONURGENT;
+ else if (e->e_class > 0)
+ e->e_timeoutclass = TOC_URGENT;
+ if (full)
+ {
+ e->e_msgpriority = e->e_msgsize
+ - e->e_class * WkClassFact
+ + e->e_nrcpts * WkRecipFact;
+ }
+
+ /* message timeout priority */
+ p = hvalue("priority", e->e_header);
+ if (p != NULL)
+ {
+ /* (this should be in the configuration file) */
+ if (strcasecmp(p, "urgent"))
+ e->e_timeoutclass = TOC_URGENT;
+ else if (strcasecmp(p, "normal"))
+ e->e_timeoutclass = TOC_NORMAL;
+ else if (strcasecmp(p, "non-urgent"))
+ e->e_timeoutclass = TOC_NONURGENT;
+ }
+
+ /* date message originated */
+ p = hvalue("posted-date", e->e_header);
+ if (p == NULL)
+ p = hvalue("date", e->e_header);
+ if (p != NULL)
+ define('a', p, e);
+
+ /* check to see if this is a MIME message */
+ if ((e->e_bodytype != NULL &&
+ strcasecmp(e->e_bodytype, "8BITMIME") == 0) ||
+ hvalue("MIME-Version", e->e_header) != NULL)
+ {
+ e->e_flags |= EF_IS_MIME;
+ if (HasEightBits)
+ e->e_bodytype = "8BITMIME";
+ }
+ else if ((p = hvalue("Content-Type", e->e_header)) != NULL)
+ {
+ /* this may be an RFC 1049 message */
+ p = strpbrk(p, ";/");
+ if (p == NULL || *p == ';')
+ {
+ /* yep, it is */
+ e->e_flags |= EF_DONT_MIME;
+ }
+ }
+
+ /*
+ ** From person in antiquated ARPANET mode
+ ** required by UK Grey Book e-mail gateways (sigh)
+ */
+
+ if (OpMode == MD_ARPAFTP)
+ {
+ register struct hdrinfo *hi;
+
+ for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+ {
+ if (bitset(H_FROM, hi->hi_flags) &&
+ (!bitset(H_RESENT, hi->hi_flags) ||
+ bitset(EF_RESENT, e->e_flags)) &&
+ (p = hvalue(hi->hi_field, e->e_header)) != NULL)
+ break;
+ }
+ if (hi->hi_field != NULL)
+ {
+ if (tTd(32, 2))
+ printf("eatheader: setsender(*%s == %s)\n",
+ hi->hi_field, p);
+ setsender(p, e, NULL, TRUE);
+ }
+ }
+
+ /*
+ ** Log collection information.
+ */
+
+# ifdef LOG
+ if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4)
+ logsender(e, msgid);
+# endif /* LOG */
+ e->e_flags &= ~EF_LOGSENDER;
+}
+ /*
+** LOGSENDER -- log sender information
+**
+** Parameters:
+** e -- the envelope to log
+** msgid -- the message id
+**
+** Returns:
+** none
+*/
+
+void
+logsender(e, msgid)
+ register ENVELOPE *e;
+ char *msgid;
+{
+# ifdef LOG
+ char *name;
+ register char *sbp;
+ register char *p;
+ int l;
+ char hbuf[MAXNAME + 1];
+ char sbuf[MAXLINE + 1];
+ char mbuf[MAXNAME + 1];
+
+ /* don't allow newlines in the message-id */
+ if (msgid != NULL)
+ {
+ l = strlen(msgid);
+ if (l > sizeof mbuf - 1)
+ l = sizeof mbuf - 1;
+ bcopy(msgid, mbuf, l);
+ mbuf[l] = '\0';
+ p = mbuf;
+ while ((p = strchr(p, '\n')) != NULL)
+ *p++ = ' ';
+ }
+
+ if (bitset(EF_RESPONSE, e->e_flags))
+ name = "[RESPONSE]";
+ else if ((name = macvalue('_', e)) != NULL)
+ ;
+ else if (RealHostName == NULL)
+ name = "localhost";
+ else if (RealHostName[0] == '[')
+ name = RealHostName;
+ else
+ {
+ name = hbuf;
+ (void) sprintf(hbuf, "%.80s", RealHostName);
+ if (RealHostAddr.sa.sa_family != 0)
+ {
+ p = &hbuf[strlen(hbuf)];
+ (void) sprintf(p, " (%.100s)",
+ anynet_ntoa(&RealHostAddr));
+ }
+ }
+
+ /* some versions of syslog only take 5 printf args */
+# if (SYSLOG_BUFSIZE) >= 256
+ sbp = sbuf;
+ sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d",
+ e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr,
+ e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts);
+ sbp += strlen(sbp);
+ if (msgid != NULL)
+ {
+ sprintf(sbp, ", msgid=%.100s", mbuf);
+ 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: %.850s, relay=%.100s",
+ e->e_id, sbuf, name);
+
+# else /* short syslog buffer */
+
+ syslog(LOG_INFO, "%s: from=%s",
+ e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" :
+ shortenstring(e->e_from.q_paddr, 83));
+ syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
+ e->e_id, e->e_msgsize, e->e_class,
+ e->e_msgpriority, e->e_nrcpts);
+ if (msgid != NULL)
+ syslog(LOG_INFO, "%s: msgid=%s",
+ e->e_id, shortenstring(mbuf, 83));
+ sbp = sbuf;
+ sprintf(sbp, "%s:", e->e_id);
+ sbp += strlen(sbp);
+ if (e->e_bodytype != NULL)
+ {
+ sprintf(sbp, " bodytype=%.20s,", e->e_bodytype);
+ sbp += strlen(sbp);
+ }
+ p = macvalue('r', e);
+ if (p != NULL)
+ {
+ sprintf(sbp, " proto=%.20s,", p);
+ sbp += strlen(sbp);
+ }
+ syslog(LOG_INFO, "%.400s relay=%.100s", sbuf, name);
+# endif
+# endif
+}
+ /*
+** PRIENCODE -- encode external priority names into internal values.
+**
+** Parameters:
+** p -- priority in ascii.
+**
+** Returns:
+** priority as a numeric level.
+**
+** Side Effects:
+** none.
+*/
+
+int
+priencode(p)
+ char *p;
+{
+ register int i;
+
+ for (i = 0; i < NumPriorities; i++)
+ {
+ if (!strcasecmp(p, Priorities[i].pri_name))
+ return (Priorities[i].pri_val);
+ }
+
+ /* unknown priority */
+ return (0);
+}
+ /*
+** CRACKADDR -- parse an address and turn it into a macro
+**
+** This doesn't actually parse the address -- it just extracts
+** it and replaces it with "$g". The parse is totally ad hoc
+** and isn't even guaranteed to leave something syntactically
+** identical to what it started with. However, it does leave
+** something semantically identical.
+**
+** 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.
+**
+** Returns:
+** a pointer to the new version.
+**
+** Side Effects:
+** none.
+**
+** Warning:
+** The return value is saved in local storage and should
+** be copied if it is to be reused.
+*/
+
+char *
+crackaddr(addr)
+ register char *addr;
+{
+ register char *p;
+ register char c;
+ int cmtlev;
+ int realcmtlev;
+ int anglelev, realanglelev;
+ int copylev;
+ bool qmode;
+ bool realqmode;
+ bool skipping;
+ bool putgmac = FALSE;
+ bool quoteit = FALSE;
+ bool gotangle = FALSE;
+ bool gotcolon = FALSE;
+ register char *bp;
+ char *buflim;
+ char *bufhead;
+ char *addrhead;
+ static char buf[MAXNAME + 1];
+
+ if (tTd(33, 1))
+ printf("crackaddr(%s)\n", addr);
+
+ /* strip leading spaces */
+ while (*addr != '\0' && isascii(*addr) && isspace(*addr))
+ addr++;
+
+ /*
+ ** Start by assuming we have no angle brackets. This will be
+ ** adjusted later if we find them.
+ */
+
+ bp = bufhead = buf;
+ buflim = &buf[sizeof buf - 5];
+ p = addrhead = addr;
+ copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
+ qmode = realqmode = FALSE;
+
+ while ((c = *p++) != '\0')
+ {
+ /*
+ ** If the buffer is overful, go into a special "skipping"
+ ** mode that tries to keep legal syntax but doesn't actually
+ ** output things.
+ */
+
+ skipping = bp >= buflim;
+
+ if (copylev > 0 && !skipping)
+ *bp++ = c;
+
+ /* check for backslash escapes */
+ if (c == '\\')
+ {
+ /* arrange to quote the address */
+ if (cmtlev <= 0 && !qmode)
+ quoteit = TRUE;
+
+ if ((c = *p++) == '\0')
+ {
+ /* too far */
+ p--;
+ goto putg;
+ }
+ if (copylev > 0 && !skipping)
+ *bp++ = c;
+ goto putg;
+ }
+
+ /* check for quoted strings */
+ if (c == '"' && cmtlev <= 0)
+ {
+ qmode = !qmode;
+ if (copylev > 0 && !skipping)
+ realqmode = !realqmode;
+ continue;
+ }
+ if (qmode)
+ goto putg;
+
+ /* check for comments */
+ if (c == '(')
+ {
+ cmtlev++;
+
+ /* allow space for closing paren */
+ if (!skipping)
+ {
+ buflim--;
+ realcmtlev++;
+ if (copylev++ <= 0)
+ {
+ *bp++ = ' ';
+ *bp++ = c;
+ }
+ }
+ }
+ if (cmtlev > 0)
+ {
+ if (c == ')')
+ {
+ cmtlev--;
+ copylev--;
+ if (!skipping)
+ {
+ realcmtlev--;
+ buflim++;
+ }
+ }
+ continue;
+ }
+ else if (c == ')')
+ {
+ /* syntax error: unmatched ) */
+ if (copylev > 0 && !skipping)
+ bp--;
+ }
+
+ /* check for group: list; syntax */
+ if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr)
+ {
+ register char *q;
+
+ if (*p == ':')
+ {
+ /* special case -- :: syntax */
+ if (cmtlev <= 0 && !qmode)
+ quoteit = TRUE;
+ if (copylev > 0 && !skipping)
+ {
+ *bp++ = c;
+ *bp++ = c;
+ }
+ p++;
+ goto putg;
+ }
+
+ gotcolon = TRUE;
+
+ bp = bufhead;
+ if (quoteit)
+ {
+ *bp++ = '"';
+
+ /* back up over the ':' and any spaces */
+ --p;
+ while (isascii(*--p) && isspace(*p))
+ continue;
+ p++;
+ }
+ for (q = addrhead; q < p; )
+ {
+ c = *q++;
+ if (bp < buflim)
+ {
+ if (quoteit && c == '"')
+ *bp++ = '\\';
+ *bp++ = c;
+ }
+ }
+ if (quoteit)
+ {
+ if (bp == &bufhead[1])
+ bp--;
+ else
+ *bp++ = '"';
+ while ((c = *p++) != ':')
+ {
+ if (bp < buflim)
+ *bp++ = c;
+ }
+ *bp++ = c;
+ }
+
+ /* any trailing white space is part of group: */
+ while (isascii(*p) && isspace(*p) && bp < buflim)
+ *bp++ = *p++;
+ copylev = 0;
+ putgmac = quoteit = FALSE;
+ bufhead = bp;
+ addrhead = p;
+ continue;
+ }
+
+ if (c == ';' && copylev <= 0 && !ColonOkInAddr)
+ {
+ if (bp < buflim)
+ *bp++ = c;
+ }
+
+ /* check for characters that may have to be quoted */
+ if (strchr(MustQuoteChars, c) != NULL)
+ {
+ /*
+ ** 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;
+ }
+
+ /* check for angle brackets */
+ if (c == '<')
+ {
+ register char *q;
+
+ /* assume first of two angles is bogus */
+ if (gotangle)
+ quoteit = TRUE;
+ gotangle = TRUE;
+
+ /* oops -- have to change our mind */
+ anglelev = 1;
+ if (!skipping)
+ realanglelev = 1;
+
+ bp = bufhead;
+ if (quoteit)
+ {
+ *bp++ = '"';
+
+ /* back up over the '<' and any spaces */
+ --p;
+ while (isascii(*--p) && isspace(*p))
+ continue;
+ p++;
+ }
+ for (q = addrhead; q < p; )
+ {
+ c = *q++;
+ if (bp < buflim)
+ {
+ if (quoteit && c == '"')
+ *bp++ = '\\';
+ *bp++ = c;
+ }
+ }
+ if (quoteit)
+ {
+ if (bp == &buf[1])
+ bp--;
+ else
+ *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--;
+ quoteit = TRUE;
+ 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);
+
+ return (buf);
+}
+ /*
+** PUTHEADER -- put the header part of a message from the in-core copy
+**
+** Parameters:
+** mci -- the connection information.
+** h -- the header to put.
+** e -- envelope to use.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** 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
+
+void
+putheader(mci, h, e)
+ register MCI *mci;
+ register HDR *h;
+ register ENVELOPE *e;
+{
+ char buf[MAX(MAXLINE,BUFSIZ)];
+ char obuf[MAXLINE];
+
+ if (tTd(34, 1))
+ printf("--- putheader, mailer = %s ---\n",
+ mci->mci_mailer->m_name);
+
+ mci->mci_flags |= MCIF_INHEADER;
+ for (; h != NULL; h = h->h_link)
+ {
+ register char *p = h->h_value;
+ extern bool bitintersect();
+
+ if (tTd(34, 11))
+ {
+ printf(" %s: ", h->h_field);
+ xputs(p);
+ }
+
+ /* suppress Content-Transfer-Encoding: if we are MIMEing */
+ if (bitset(H_CTE, h->h_flags) &&
+ bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags))
+ {
+ if (tTd(34, 11))
+ printf(" (skipped (content-transfer-encoding))\n");
+ continue;
+ }
+
+ if (bitset(MCIF_INMIME, mci->mci_flags))
+ {
+ if (tTd(34, 11))
+ printf("\n");
+ goto vanilla;
+ }
+
+ if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
+ !bitintersect(h->h_mflags, mci->mci_mailer->m_flags))
+ {
+ if (tTd(34, 11))
+ printf(" (skipped)\n");
+ continue;
+ }
+
+ /* 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;
+ }
+
+ /* suppress return receipts if requested */
+ if (bitset(H_RECEIPTTO, h->h_flags) &&
+ bitset(EF_NORECEIPT, e->e_flags))
+ {
+ if (tTd(34, 11))
+ printf(" (skipped (receipt))\n");
+ continue;
+ }
+
+ /* macro expand value if generated internally */
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ expand(p, buf, sizeof buf, e);
+ p = buf;
+ if (p == NULL || *p == '\0')
+ {
+ if (tTd(34, 11))
+ printf(" (skipped -- null value)\n");
+ continue;
+ }
+ }
+
+ if (bitset(H_BCC, h->h_flags))
+ {
+ /* Bcc: field -- either truncate or delete */
+ if (bitset(EF_DELETE_BCC, e->e_flags))
+ {
+ if (tTd(34, 11))
+ printf(" (skipped -- bcc)\n");
+ }
+ else
+ {
+ /* no other recipient headers: truncate value */
+ (void) sprintf(obuf, "%s:", h->h_field);
+ putline(obuf, mci);
+ }
+ continue;
+ }
+
+ if (tTd(34, 11))
+ printf("\n");
+
+ if (bitset(H_FROM|H_RCPT, h->h_flags))
+ {
+ /* address field */
+ bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+
+ if (bitset(H_FROM, h->h_flags))
+ oldstyle = FALSE;
+ commaize(h, p, oldstyle, mci, e);
+ }
+ else
+ {
+ /* vanilla header line */
+ register char *nlp;
+ register char *obp;
+
+vanilla:
+ (void) sprintf(obuf, "%.200s: ", h->h_field);
+ obp = obuf + strlen(obuf);
+ while ((nlp = strchr(p, '\n')) != NULL)
+ {
+
+ *nlp = '\0';
+ sprintf(obp, "%.*s",
+ sizeof obuf - (obp - obuf) - 1, p);
+ *nlp = '\n';
+ putline(obuf, mci);
+ p = ++nlp;
+ obp = obuf;
+ }
+ sprintf(obp, "%.*s", sizeof obuf - (obp - obuf) - 1, p);
+ putline(obuf, mci);
+ }
+ }
+
+ /*
+ ** If we are converting this to a MIME message, add the
+ ** MIME headers.
+ */
+
+#if MIME8TO7
+ if (bitset(MM_MIME8BIT, MimeMode) &&
+ bitset(EF_HAS8BIT, e->e_flags) &&
+ !bitset(EF_DONT_MIME, e->e_flags) &&
+ !bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
+ !bitset(MCIF_CVT8TO7, mci->mci_flags))
+ {
+ if (hvalue("MIME-Version", e->e_header) == NULL)
+ putline("MIME-Version: 1.0", mci);
+ if (hvalue("Content-Type", e->e_header) == NULL)
+ {
+ sprintf(obuf, "Content-Type: text/plain; charset=%s",
+ defcharset(e));
+ putline(obuf, mci);
+ }
+ if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL)
+ putline("Content-Transfer-Encoding: 8bit", mci);
+ }
+#endif
+}
+ /*
+** COMMAIZE -- output a header field, making a comma-translated list.
+**
+** Parameters:
+** h -- the header field to output.
+** p -- the value to put in it.
+** oldstyle -- TRUE if this is an old style header.
+** mci -- the connection information.
+** e -- the envelope containing the message.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** outputs "p" to file "fp".
+*/
+
+void
+commaize(h, p, oldstyle, mci, e)
+ register HDR *h;
+ register char *p;
+ bool oldstyle;
+ register MCI *mci;
+ register ENVELOPE *e;
+{
+ register char *obp;
+ int opos;
+ int omax;
+ bool firstone = TRUE;
+ char obuf[MAXLINE + 3];
+
+ /*
+ ** Output the address list translated by the
+ ** mailer and with commas.
+ */
+
+ if (tTd(14, 2))
+ printf("commaize(%s: %s)\n", h->h_field, p);
+
+ obp = obuf;
+ (void) sprintf(obp, "%.200s: ", h->h_field);
+ opos = strlen(h->h_field) + 2;
+ obp += opos;
+ omax = mci->mci_mailer->m_linelimit - 2;
+ if (omax < 0 || omax > 78)
+ omax = 78;
+
+ /*
+ ** Run through the list of values.
+ */
+
+ while (*p != '\0')
+ {
+ register char *name;
+ register int c;
+ char savechar;
+ int flags;
+ auto int stat;
+
+ /*
+ ** Find the end of the name. New style names
+ ** end with a comma, old style names end with
+ ** a space character. However, spaces do not
+ ** necessarily delimit an old-style name -- at
+ ** signs mean keep going.
+ */
+
+ /* find end of name */
+ while ((isascii(*p) && isspace(*p)) || *p == ',')
+ p++;
+ name = p;
+ for (;;)
+ {
+ auto char *oldp;
+ char pvpbuf[PSBUFSIZE];
+
+ (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
+ sizeof pvpbuf, &oldp, NULL);
+ p = oldp;
+
+ /* look to see if we have an at sign */
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+
+ if (*p != '@')
+ {
+ p = oldp;
+ break;
+ }
+ p += *p == '@' ? 1 : 2;
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ }
+ /* at the end of one complete name */
+
+ /* strip off trailing white space */
+ while (p >= name &&
+ ((isascii(*p) && isspace(*p)) || *p == ',' || *p == '\0'))
+ p--;
+ if (++p == name)
+ continue;
+ savechar = *p;
+ *p = '\0';
+
+ /* translate the name to be relative */
+ flags = RF_HEADERADDR|RF_ADDDOMAIN;
+ if (bitset(H_FROM, h->h_flags))
+ flags |= RF_SENDERADDR;
+#if USERDB
+ else if (e->e_from.q_mailer != NULL &&
+ bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags))
+ {
+ extern char *udbsender();
+ char *q;
+
+ q = udbsender(name);
+ if (q != NULL)
+ name = q;
+ }
+#endif
+ stat = EX_OK;
+ name = remotename(name, mci->mci_mailer, flags, &stat, e);
+ if (*name == '\0')
+ {
+ *p = savechar;
+ continue;
+ }
+
+ /* output the name with nice formatting */
+ opos += strlen(name);
+ if (!firstone)
+ opos += 2;
+ if (opos > omax && !firstone)
+ {
+ (void) strcpy(obp, ",\n");
+ putline(obuf, mci);
+ obp = obuf;
+ (void) strcpy(obp, " ");
+ opos = strlen(obp);
+ obp += opos;
+ opos += strlen(name);
+ }
+ else if (!firstone)
+ {
+ (void) strcpy(obp, ", ");
+ obp += 2;
+ }
+
+ while ((c = *name++) != '\0' && obp < &obuf[MAXLINE])
+ *obp++ = c;
+ firstone = FALSE;
+ *p = savechar;
+ }
+ (void) strcpy(obp, "\n");
+ putline(obuf, mci);
+}
+ /*
+** COPYHEADER -- copy header list
+**
+** This routine is the equivalent of newstr for header lists
+**
+** Parameters:
+** header -- list of header structures to copy.
+**
+** Returns:
+** a copy of 'header'.
+**
+** Side Effects:
+** none.
+*/
+
+HDR *
+copyheader(header)
+ register HDR *header;
+{
+ register HDR *newhdr;
+ HDR *ret;
+ register HDR **tail = &ret;
+
+ 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;
+}
diff --git a/usr.sbin/sendmail/src/macro.c b/usr.sbin/sendmail/src/macro.c
new file mode 100644
index 000000000000..94ef834bb082
--- /dev/null
+++ b/usr.sbin/sendmail/src/macro.c
@@ -0,0 +1,441 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)macro.c 8.13 (Berkeley) 7/10/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+char *MacroName[256]; /* macro id to name table */
+int NextMacroId = 0240; /* codes for long named macros */
+
+
+/*
+** EXPAND -- macro expand a string using $x escapes.
+**
+** Parameters:
+** s -- the string to expand.
+** buf -- the place to put the expansion.
+** bufsize -- the size of the buffer.
+** e -- envelope in which to work.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+void
+expand(s, buf, bufsize, e)
+ register char *s;
+ register char *buf;
+ size_t bufsize;
+ register ENVELOPE *e;
+{
+ register char *xp;
+ register char *q;
+ bool skipping; /* set if conditionally skipping output */
+ bool recurse = FALSE; /* set if recursion required */
+ int i;
+ int iflev; /* if nesting level */
+ char xbuf[BUFSIZ];
+
+ if (tTd(35, 24))
+ {
+ printf("expand(");
+ xputs(s);
+ printf(")\n");
+ }
+
+ skipping = FALSE;
+ iflev = 0;
+ if (s == NULL)
+ s = "";
+ for (xp = xbuf; *s != '\0'; s++)
+ {
+ int c;
+
+ /*
+ ** Check for non-ordinary (special?) character.
+ ** 'q' will be the interpolated quantity.
+ */
+
+ q = NULL;
+ c = *s;
+ switch (c & 0377)
+ {
+ case CONDIF: /* see if var set */
+ c = *++s;
+ if (skipping)
+ iflev++;
+ else
+ skipping = macvalue(c, e) == NULL;
+ continue;
+
+ case CONDELSE: /* change state of skipping */
+ if (iflev == 0)
+ skipping = !skipping;
+ continue;
+
+ case CONDFI: /* stop skipping */
+ if (iflev == 0)
+ skipping = FALSE;
+ if (skipping)
+ iflev--;
+ continue;
+
+ case MACROEXPAND: /* macro interpolation */
+ c = *++s & 0377;
+ if (c != '\0')
+ q = macvalue(c, e);
+ else
+ {
+ s--;
+ q = NULL;
+ }
+ if (q == NULL)
+ continue;
+ break;
+ }
+
+ /*
+ ** Interpolate q or output one character
+ */
+
+ if (skipping || xp >= &xbuf[sizeof xbuf])
+ continue;
+ if (q == NULL)
+ *xp++ = c;
+ else
+ {
+ /* copy to end of q or max space remaining in buf */
+ while ((c = *q++) != '\0' && xp < &xbuf[sizeof xbuf - 1])
+ {
+ /* check for any sendmail metacharacters */
+ if ((c & 0340) == 0200)
+ recurse = TRUE;
+ *xp++ = c;
+ }
+ }
+ }
+ *xp = '\0';
+
+ if (tTd(35, 24))
+ {
+ printf("expand ==> ");
+ xputs(xbuf);
+ printf("\n");
+ }
+
+ /* recurse as appropriate */
+ if (recurse)
+ {
+ expand(xbuf, buf, bufsize, e);
+ return;
+ }
+
+ /* copy results out */
+ i = xp - xbuf;
+ if (i >= bufsize)
+ i = bufsize - 1;
+ bcopy(xbuf, buf, i);
+ buf[i] = '\0';
+}
+ /*
+** DEFINE -- define a macro.
+**
+** this would be better done using a #define macro.
+**
+** Parameters:
+** n -- the macro name.
+** v -- the macro value.
+** e -- the envelope to store the definition in.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** e->e_macro[n] is defined.
+**
+** Notes:
+** There is one macro for each ASCII character,
+** although they are not all used. The currently
+** defined macros are:
+**
+** $a date in ARPANET format (preferring the Date: line
+** of the message)
+** $b the current date (as opposed to the date as found
+** the message) in ARPANET format
+** $c hop count
+** $d (current) date in UNIX (ctime) format
+** $e the SMTP entry message+
+** $f raw from address
+** $g translated from address
+** $h to host
+** $i queue id
+** $j official SMTP hostname, used in messages+
+** $k UUCP node name
+** $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+
+** $p my process id in decimal
+** $q the string that becomes an address -- this is
+** normally used to combine $g & $x.
+** $r protocol used to talk to sender
+** $s sender's host name
+** $t the current time in seconds since 1/1/1970
+** $u to user
+** $v version number of sendmail
+** $w our host name (if it can be determined)
+** $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
+** are not set.
+**
+** There are also some macros that can be used
+** arbitrarily to make the configuration file
+** cleaner. In general all upper-case letters
+** are available.
+*/
+
+void
+define(n, v, e)
+ int n;
+ char *v;
+ register ENVELOPE *e;
+{
+ if (tTd(35, 9))
+ {
+ printf("%sdefine(%s as ",
+ (e->e_macro[n & 0377] == NULL) ? "" : "re", macname(n));
+ xputs(v);
+ printf(")\n");
+ }
+ e->e_macro[n & 0377] = v;
+}
+ /*
+** MACVALUE -- return uninterpreted value of a macro.
+**
+** Parameters:
+** n -- the name of the macro.
+**
+** Returns:
+** The value of n.
+**
+** Side Effects:
+** none.
+*/
+
+char *
+macvalue(n, e)
+ int n;
+ register ENVELOPE *e;
+{
+ n &= 0377;
+ while (e != NULL)
+ {
+ register char *p = e->e_macro[n];
+
+ if (p != NULL)
+ return (p);
+ e = e->e_parent;
+ }
+ return (NULL);
+}
+ /*
+** MACNAME -- return the name of a macro given its internal id
+**
+** Parameter:
+** n -- the id of the macro
+**
+** Returns:
+** The name of n.
+**
+** Side Effects:
+** none.
+*/
+
+char *
+macname(n)
+ int n;
+{
+ static char mbuf[2];
+
+ n &= 0377;
+ if (bitset(0200, n))
+ {
+ char *p = MacroName[n];
+
+ if (p != NULL)
+ return p;
+ return "***UNDEFINED MACRO***";
+ }
+ mbuf[0] = n;
+ mbuf[1] = '\0';
+ return mbuf;
+}
+ /*
+** MACID -- return id of macro identified by its name
+**
+** Parameters:
+** p -- pointer to name string -- either a single
+** character or {name}.
+** ep -- filled in with the pointer to the byte
+** after the name.
+**
+** Returns:
+** The internal id code for this macro. This will
+** fit into a single byte.
+**
+** Side Effects:
+** If this is a new macro name, a new id is allocated.
+*/
+
+int
+macid(p, ep)
+ register char *p;
+ char **ep;
+{
+ int mid;
+ register char *bp;
+ char mbuf[21];
+
+ if (tTd(35, 14))
+ {
+ printf("macid(");
+ xputs(p);
+ printf(") => ");
+ }
+
+ if (*p == '\0' || (p[0] == '{' && p[1] == '}'))
+ {
+ syserr("Name required for macro/class");
+ if (ep != NULL)
+ *ep = p;
+ if (tTd(35, 14))
+ printf("NULL\n");
+ return '\0';
+ }
+ if (*p != '{')
+ {
+ /* the macro is its own code */
+ if (ep != NULL)
+ *ep = p + 1;
+ if (tTd(35, 14))
+ printf("%c\n", *p);
+ return *p;
+ }
+ bp = mbuf;
+ while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf])
+ {
+ if (isascii(*p) && (isalnum(*p) || *p == '_'))
+ *bp++ = *p;
+ else
+ syserr("Invalid macro/class character %c", *p);
+ }
+ *bp = '\0';
+ mid = -1;
+ if (*p == '\0')
+ {
+ syserr("Unbalanced { on %s", mbuf); /* missing } */
+ }
+ else if (*p != '}')
+ {
+ syserr("Macro/class name ({%s}) too long (%d chars max)",
+ mbuf, sizeof mbuf - 1);
+ }
+ else if (mbuf[1] == '\0')
+ {
+ /* ${x} == $x */
+ mid = mbuf[0];
+ p++;
+ }
+ else
+ {
+ register STAB *s;
+
+ s = stab(mbuf, ST_MACRO, ST_ENTER);
+ if (s->s_macro != 0)
+ mid = s->s_macro;
+ else
+ {
+ if (NextMacroId > 0377)
+ {
+ syserr("Macro/class {%s}: too many long names", mbuf);
+ s->s_macro = -1;
+ }
+ else
+ {
+ MacroName[NextMacroId] = s->s_name;
+ s->s_macro = mid = NextMacroId++;
+ }
+ }
+ p++;
+ }
+ if (ep != NULL)
+ *ep = p;
+ if (tTd(35, 14))
+ printf("0x%x\n", mid);
+ return mid;
+}
+ /*
+** WORDINCLASS -- tell if a word is in a specific class
+**
+** Parameters:
+** str -- the name of the word to look up.
+** cl -- the class name.
+**
+** Returns:
+** TRUE if str can be found in cl.
+** FALSE otherwise.
+*/
+
+bool
+wordinclass(str, cl)
+ char *str;
+ int cl;
+{
+ register STAB *s;
+
+ s = stab(str, ST_CLASS, ST_FIND);
+ return s != NULL && bitnset(cl & 0xff, s->s_class);
+}
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
new file mode 100644
index 000000000000..5e352f2b9fba
--- /dev/null
+++ b/usr.sbin/sendmail/src/main.c
@@ -0,0 +1,2113 @@
+/*
+ * Copyright (c) 1983, 1995 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 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[] = "@(#)main.c 8.162 (Berkeley) 11/18/95";
+#endif /* not lint */
+
+#define _DEFINE
+
+#include "sendmail.h"
+#if NAMED_BIND
+#include <resolv.h>
+#endif
+
+# ifdef lint
+char edata, end;
+# endif /* lint */
+
+/*
+** SENDMAIL -- Post mail to a set of destinations.
+**
+** This is the basic mail router. All user mail programs should
+** call this routine to actually deliver mail. Sendmail in
+** turn calls a bunch of mail servers that do the real work of
+** delivering the mail.
+**
+** Sendmail is driven by tables read in from /usr/lib/sendmail.cf
+** (read by readcf.c). Some more static configuration info,
+** including some code that you may want to tailor for your
+** installation, is in conf.c. You may also want to touch
+** daemon.c (if you have some other IPC mechanism), acct.c
+** (to change your accounting), names.c (to adjust the name
+** server mechanism).
+**
+** Usage:
+** /usr/lib/sendmail [flags] addr ...
+**
+** See the associated documentation for details.
+**
+** Author:
+** 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
+** my involvement in this project.
+*/
+
+
+int NextMailer; /* "free" index into Mailer struct */
+char *FullName; /* sender's full name */
+ENVELOPE BlankEnvelope; /* a "blank" envelope */
+ENVELOPE MainEnvelope; /* the envelope around the basic letter */
+ADDRESS NullAddress = /* a null address */
+ { "", "", NULL, "" };
+char *CommandLineArgs; /* command line args for pid file */
+bool Warn_Q_option = FALSE; /* warn about Q option use */
+char **SaveArgv; /* argument vector for re-execing */
+
+static void obsolete();
+
+#ifdef DAEMON
+#ifndef SMTP
+ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
+#endif /* SMTP */
+#endif /* DAEMON */
+
+#define MAXCONFIGLEVEL 6 /* highest config version level known */
+
+int
+main(argc, argv, envp)
+ int argc;
+ char **argv;
+ char **envp;
+{
+ register char *p;
+ char **av;
+ extern char Version[];
+ char *ep, *from;
+ typedef int (*fnptr)();
+ STAB *st;
+ register int i;
+ int j;
+ bool queuemode = FALSE; /* process queue requests */
+ bool safecf = TRUE;
+ bool warn_C_flag = FALSE;
+ char warn_f_flag = '\0';
+ static bool reenter = FALSE;
+ struct passwd *pw;
+ struct stat stb;
+ struct hostent *hp;
+ char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */
+ static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ extern int DtableSize;
+ extern int optind;
+ extern int opterr;
+ extern time_t convtime();
+ extern void intsig();
+ extern struct hostent *myhostname();
+ extern char *arpadate();
+ extern char *getauthinfo();
+ extern char *getcfname();
+ extern char *optarg;
+ extern char **environ;
+ extern void sigusr1();
+ extern void sighup();
+ extern void initmacros __P((ENVELOPE *));
+
+ /*
+ ** Check to see if we reentered.
+ ** This would normally happen if e_putheader or e_putbody
+ ** were NULL when invoked.
+ */
+
+ if (reenter)
+ {
+ syserr("main: reentered!");
+ abort();
+ }
+ reenter = TRUE;
+
+ /* do machine-dependent initializations */
+ init_md(argc, argv);
+
+#ifdef SIGUSR1
+ /* arrange to dump state on user-1 signal */
+ setsignal(SIGUSR1, sigusr1);
+#endif
+
+ /* in 4.4BSD, the table can be huge; impose a reasonable limit */
+ DtableSize = getdtsize();
+ if (DtableSize > 256)
+ DtableSize = 256;
+
+ /*
+ ** Be sure we have enough file descriptors.
+ ** But also be sure that 0, 1, & 2 are open.
+ */
+
+ i = open("/dev/null", O_RDWR, 0);
+ if (fstat(STDIN_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
+ (void) dup2(i, STDIN_FILENO);
+ if (fstat(STDOUT_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
+ (void) dup2(i, STDOUT_FILENO);
+ if (fstat(STDERR_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
+ (void) dup2(i, STDERR_FILENO);
+ if (i != STDIN_FILENO && i != STDOUT_FILENO && 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
+# ifdef LOG_MAIL
+ openlog("sendmail", LOG_PID, LOG_MAIL);
+# else
+ openlog("sendmail", LOG_PID);
+# endif
+#endif
+
+ tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+
+ /* set up the blank envelope */
+ BlankEnvelope.e_puthdr = putheader;
+ BlankEnvelope.e_putbody = putbody;
+ BlankEnvelope.e_xfp = NULL;
+ STRUCTCOPY(NullAddress, BlankEnvelope.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 = sm_getpwuid(RealUid);
+ if (pw != NULL)
+ (void) strcpy(rnamebuf, pw->pw_name);
+ else
+ (void) sprintf(rnamebuf, "Unknown UID %d", RealUid);
+ RealUserName = rnamebuf;
+
+ /* save command line arguments */
+ i = 0;
+ for (av = argv; *av != NULL; )
+ i += strlen(*av++) + 1;
+ SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1));
+ CommandLineArgs = xalloc(i);
+ p = CommandLineArgs;
+ for (av = argv, i = 0; *av != NULL; )
+ {
+ SaveArgv[i++] = newstr(*av);
+ if (av != argv)
+ *p++ = ' ';
+ strcpy(p, *av++);
+ p += strlen(p);
+ }
+ SaveArgv[i] = NULL;
+
+ /* Handle any non-getoptable constructions. */
+ obsolete(argv);
+
+ /*
+ ** Do a quick prescan of the argument list.
+ */
+
+#if defined(__osf__) || defined(_AIX3)
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x"
+#endif
+#if defined(sony_news)
+# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mnO:o:p:q:r:sTtvX:"
+#endif
+#ifndef OPTIONS
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:"
+#endif
+ opterr = 0;
+ while ((j = getopt(argc, argv, OPTIONS)) != EOF)
+ {
+ switch (j)
+ {
+ case 'd':
+ tTflag(optarg);
+ setbuf(stdout, (char *) NULL);
+ break;
+ }
+ }
+ opterr = 1;
+
+ if (tTd(0, 1))
+ {
+ int ll;
+ extern char *CompileOptions[];
+
+ printf("Version %s\n Compiled with:", Version);
+ av = CompileOptions;
+ ll = 7;
+ while (*av != NULL)
+ {
+ if (ll + strlen(*av) > 63)
+ {
+ putchar('\n');
+ ll = 0;
+ }
+ if (ll == 0)
+ {
+ putchar('\t');
+ putchar('\t');
+ }
+ else
+ putchar(' ');
+ printf("%s", *av);
+ ll += strlen(*av++) + 1;
+ }
+ putchar('\n');
+ }
+ if (tTd(0, 10))
+ {
+ int ll;
+ extern char *OsCompileOptions[];
+
+ printf(" OS Defines:", Version);
+ av = OsCompileOptions;
+ ll = 7;
+ while (*av != NULL)
+ {
+ if (ll + strlen(*av) > 63)
+ {
+ putchar('\n');
+ ll = 0;
+ }
+ if (ll == 0)
+ {
+ putchar('\t');
+ putchar('\t');
+ }
+ else
+ putchar(' ');
+ printf("%s", *av);
+ ll += strlen(*av++) + 1;
+ }
+ putchar('\n');
+#ifdef _PATH_UNIX
+ printf("Kernel symbols:\t%s\n", _PATH_UNIX);
+#endif
+ printf(" Config file:\t%s\n", getcfname());
+ printf(" Pid file:\t%s\n", PidFile);
+ }
+
+ InChannel = stdin;
+ OutChannel = stdout;
+
+ /* initialize for setproctitle */
+ initsetproctitle(argc, argv, envp);
+
+ /* prime the child environment */
+ setuserenv("AGENT", "sendmail");
+
+ if (setsignal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void) setsignal(SIGINT, intsig);
+ (void) setsignal(SIGTERM, intsig);
+ (void) setsignal(SIGPIPE, SIG_IGN);
+ OldUmask = umask(022);
+ OpMode = MD_DELIVER;
+ FullName = getenv("NAME");
+
+#if NAMED_BIND
+ if (tTd(8, 8))
+ {
+ res_init();
+ _res.options |= RES_DEBUG;
+ }
+#endif
+
+ errno = 0;
+ from = NULL;
+
+ /* initialize some macros, etc. */
+ initmacros(CurEnv);
+ init_vendor_macros(CurEnv);
+
+ /* version */
+ define('v', Version, CurEnv);
+
+ /* hostname */
+ hp = myhostname(jbuf, sizeof jbuf);
+ if (jbuf[0] != '\0')
+ {
+ struct utsname utsname;
+
+ if (tTd(0, 4))
+ printf("canonical name: %s\n", jbuf);
+ define('w', newstr(jbuf), CurEnv); /* must be new string */
+ define('j', newstr(jbuf), CurEnv);
+ setclass('w', jbuf);
+
+ p = strchr(jbuf, '.');
+ if (p != NULL)
+ {
+ if (p[1] != '\0')
+ {
+ define('m', newstr(&p[1]), CurEnv);
+ }
+ while (p != NULL && strchr(&p[1], '.') != NULL)
+ {
+ *p = '\0';
+ setclass('w', jbuf);
+ *p++ = '.';
+ p = strchr(p, '.');
+ }
+ }
+
+ if (uname(&utsname) >= 0)
+ p = utsname.nodename;
+ else
+ {
+ if (tTd(0, 22))
+ printf("uname failed (%s)\n", errstring(errno));
+ makelower(jbuf);
+ p = jbuf;
+ }
+ if (tTd(0, 4))
+ printf(" UUCP nodename: %s\n", p);
+ p = newstr(p);
+ define('k', p, CurEnv);
+ setclass('k', p);
+ setclass('w', p);
+ }
+ if (hp != NULL)
+ {
+ for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
+ {
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", *av);
+ setclass('w', *av);
+ }
+#if NETINET
+ if (hp->h_addrtype == AF_INET && hp->h_length == INADDRSZ)
+ {
+ register int i;
+
+ for (i = 0; hp->h_addr_list[i] != NULL; i++)
+ {
+ char ipbuf[103];
+
+ sprintf(ipbuf, "[%.100s]",
+ inet_ntoa(*((struct in_addr *) hp->h_addr_list[i])));
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", ipbuf);
+ setclass('w', ipbuf);
+ }
+ }
+#endif
+ }
+
+ /* probe interfaces and locate any additional names */
+ load_if_names();
+
+ /* 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;
+ p = strrchr(*av, '/');
+ if (p++ == NULL)
+ p = *av;
+ if (strcmp(p, "newaliases") == 0)
+ OpMode = MD_INITALIAS;
+ else if (strcmp(p, "mailq") == 0)
+ OpMode = MD_PRINT;
+ else if (strcmp(p, "smtpd") == 0)
+ OpMode = MD_DAEMON;
+
+ optind = 1;
+ while ((j = getopt(argc, argv, OPTIONS)) != EOF)
+ {
+ switch (j)
+ {
+ case 'b': /* operations mode */
+ switch (j = *optarg)
+ {
+ case MD_DAEMON:
+# ifdef DAEMON
+ if (RealUid != 0) {
+ usrerr("Permission denied");
+ exit (EX_USAGE);
+ }
+ (void) unsetenv("HOSTALIASES");
+# else
+ usrerr("Daemon mode not implemented");
+ ExitStat = EX_USAGE;
+ break;
+# endif /* DAEMON */
+ case MD_SMTP:
+# ifndef SMTP
+ usrerr("I don't speak SMTP");
+ ExitStat = EX_USAGE;
+ break;
+# endif /* SMTP */
+ case MD_DELIVER:
+ case MD_VERIFY:
+ case MD_TEST:
+ case MD_INITALIAS:
+ case MD_PRINT:
+ case MD_ARPAFTP:
+ OpMode = j;
+ break;
+
+ case MD_FREEZE:
+ usrerr("Frozen configurations unsupported");
+ ExitStat = EX_USAGE;
+ break;
+
+ default:
+ usrerr("Invalid operation mode %c", j);
+ ExitStat = EX_USAGE;
+ break;
+ }
+ break;
+
+ case 'B': /* body type */
+ CurEnv->e_bodytype = optarg;
+ break;
+
+ case 'C': /* select configuration file (already done) */
+ if (RealUid != 0)
+ warn_C_flag = TRUE;
+ ConfFile = optarg;
+ endpwent();
+ (void) setgid(RealGid);
+ (void) setuid(RealUid);
+ safecf = FALSE;
+ break;
+
+ case 'd': /* debugging -- already done */
+ break;
+
+ case 'f': /* from address */
+ case 'r': /* obsolete -f flag */
+ if (from != NULL)
+ {
+ usrerr("More than one \"from\" person");
+ ExitStat = EX_USAGE;
+ break;
+ }
+ from = newstr(denlstring(optarg, TRUE, TRUE));
+ if (strcmp(RealUserName, from) != 0)
+ warn_f_flag = j;
+ break;
+
+ case 'F': /* set full name */
+ FullName = newstr(optarg);
+ break;
+
+ case 'h': /* hop count */
+ CurEnv->e_hopcount = strtol(optarg, &ep, 10);
+ if (*ep)
+ {
+ usrerr("Bad hop count (%s)", optarg);
+ ExitStat = EX_USAGE;
+ break;
+ }
+ break;
+
+ case 'n': /* don't alias */
+ NoAlias = TRUE;
+ break;
+
+ case 'o': /* set option */
+ setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
+ break;
+
+ case 'O': /* set option (long form) */
+ setoption(' ', optarg, FALSE, TRUE, CurEnv);
+ break;
+
+ case 'p': /* set protocol */
+ p = strchr(optarg, ':');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ if (*p != '\0')
+ {
+ ep = xalloc(strlen(p) + 1);
+ cleanstrcpy(ep, p, MAXNAME);
+ define('s', ep, CurEnv);
+ }
+ }
+ if (*optarg != '\0')
+ {
+ ep = xalloc(strlen(optarg) + 1);
+ cleanstrcpy(ep, optarg, MAXNAME);
+ define('r', ep, CurEnv);
+ }
+ break;
+
+ case 'q': /* run queue files at intervals */
+# ifdef QUEUE
+ (void) unsetenv("HOSTALIASES");
+ FullName = NULL;
+ queuemode = TRUE;
+ 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;
+# endif /* QUEUE */
+ break;
+
+ case 't': /* read recipients from message */
+ GrabTo = TRUE;
+ break;
+
+ case 'X': /* traffic log file */
+ endpwent();
+ setgid(RealGid);
+ setuid(RealUid);
+ TrafficLogFile = fopen(optarg, "a");
+ if (TrafficLogFile == NULL)
+ {
+ syserr("cannot open %s", optarg);
+ break;
+ }
+#ifdef HASSETVBUF
+ setvbuf(TrafficLogFile, NULL, _IOLBF, 0);
+#else
+ setlinebuf(TrafficLogFile);
+#endif
+ break;
+
+ /* compatibility flags */
+ case 'c': /* connect to non-local mailers */
+ 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(j, "T", FALSE, TRUE, CurEnv);
+ break;
+
+ case 'e': /* error message disposition */
+ case 'M': /* define macro */
+ setoption(j, optarg, FALSE, TRUE, CurEnv);
+ break;
+
+ case 's': /* save From lines in headers */
+ setoption('f', "T", FALSE, TRUE, CurEnv);
+ break;
+
+# ifdef DBM
+ case 'I': /* initialize alias DBM file */
+ OpMode = MD_INITALIAS;
+ break;
+# endif /* DBM */
+
+# if defined(__osf__) || defined(_AIX3)
+ case 'x': /* random flag that OSF/1 & AIX mailx passes */
+ break;
+# endif
+# if defined(sony_news)
+ case 'E':
+ case 'J': /* ignore flags for Japanese code conversion
+ impremented on Sony NEWS */
+ break;
+# endif
+
+ default:
+ ExitStat = EX_USAGE;
+ finis();
+ break;
+ }
+ }
+ av += optind;
+
+ /*
+ ** Do basic initialization.
+ ** Read system control file.
+ ** Extract special fields for local use.
+ */
+
+ /* set up ${opMode} for use in config file */
+ {
+ char mbuf[2];
+
+ mbuf[0] = OpMode;
+ mbuf[1] = '\0';
+ define(MID_OPMODE, newstr(mbuf), CurEnv);
+ }
+
+#if XDEBUG
+ checkfd012("before readcf");
+#endif
+ vendor_pre_defaults(CurEnv);
+ readcf(getcfname(), safecf, CurEnv);
+ vendor_post_defaults(CurEnv);
+
+ /* suppress error printing if errors mailed back or whatever */
+ if (CurEnv->e_errormode != EM_PRINT)
+ HoldErrs = TRUE;
+
+ /* set up the $=m class now, after .cf has a chance to redefine $m */
+ expand("\201m", jbuf, sizeof jbuf, CurEnv);
+ setclass('m', jbuf);
+
+ if (tTd(0, 1))
+ {
+ printf("\n============ SYSTEM IDENTITY (after readcf) ============");
+ printf("\n (short domain name) $w = ");
+ xputs(macvalue('w', CurEnv));
+ printf("\n (canonical domain name) $j = ");
+ xputs(macvalue('j', CurEnv));
+ printf("\n (subdomain name) $m = ");
+ xputs(macvalue('m', CurEnv));
+ printf("\n (node name) $k = ");
+ xputs(macvalue('k', CurEnv));
+ printf("\n========================================================\n\n");
+ }
+
+ /*
+ ** Initialize name server if it is going to be used.
+ */
+
+#if NAMED_BIND
+ if (UseNameServer && !bitset(RES_INIT, _res.options))
+ res_init();
+# ifdef RES_NOALIASES
+ _res.options |= RES_NOALIASES;
+# endif
+#endif
+
+ /*
+ ** Do more command line checking -- these are things that
+ ** have to modify the results of reading the config file.
+ */
+
+ /* process authorization warnings from command line */
+ if (warn_C_flag)
+ auth_warning(CurEnv, "Processed by %s with -C %s",
+ RealUserName, ConfFile);
+ if (Warn_Q_option)
+ auth_warning(CurEnv, "Processed from queue %s", QueueDir);
+
+ /* check body type for legality */
+ if (CurEnv->e_bodytype == NULL)
+ /* nothing */ ;
+ else if (strcasecmp(CurEnv->e_bodytype, "7BIT") == 0)
+ SevenBitInput = TRUE;
+ else if (strcasecmp(CurEnv->e_bodytype, "8BITMIME") == 0)
+ SevenBitInput = FALSE;
+ else
+ {
+ usrerr("Illegal body type %s", CurEnv->e_bodytype);
+ CurEnv->e_bodytype = NULL;
+ }
+
+ /* Enforce use of local time (null string overrides this) */
+ if (TimeZoneSpec == NULL)
+ unsetenv("TZ");
+ else if (TimeZoneSpec[0] != '\0')
+ setuserenv("TZ", TimeZoneSpec);
+ else
+ setuserenv("TZ", NULL);
+ tzset();
+
+ /* check for sane configuration level */
+ if (ConfigLevel > MAXCONFIGLEVEL)
+ {
+ syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
+ ConfigLevel, MAXCONFIGLEVEL);
+ }
+
+ if (MeToo)
+ BlankEnvelope.e_flags |= EF_METOO;
+
+ switch (OpMode)
+ {
+ case MD_DAEMON:
+ /* remove things that don't make sense in daemon mode */
+ FullName = NULL;
+ GrabTo = FALSE;
+
+ /* arrange to restart on hangup signal */
+ setsignal(SIGHUP, sighup);
+ break;
+
+ case MD_INITALIAS:
+ Verbose = TRUE;
+ /* fall through... */
+
+ default:
+ /* arrange to exit cleanly on hangup signal */
+ setsignal(SIGHUP, intsig);
+ break;
+ }
+
+ /* full names can't have newlines */
+ if (FullName != NULL && strchr(FullName, '\n') != NULL)
+ FullName = newstr(denlstring(FullName, TRUE, TRUE));
+
+ /* do heuristic mode adjustment */
+ if (Verbose)
+ {
+ /* turn off noconnect option */
+ setoption('c', "F", TRUE, FALSE, CurEnv);
+
+ /* turn on interactive delivery */
+ setoption('d', "", TRUE, FALSE, CurEnv);
+ }
+
+ if (ConfigLevel < 3)
+ {
+ UseErrorsTo = TRUE;
+ }
+
+ /* set options that were previous macros */
+ if (SmtpGreeting == NULL)
+ {
+ if (ConfigLevel < 7 && (p = macvalue('e', CurEnv)) != NULL)
+ SmtpGreeting = newstr(p);
+ else
+ SmtpGreeting = "\201j Sendmail \201v ready at \201b";
+ }
+ if (UnixFromLine == NULL)
+ {
+ if (ConfigLevel < 7 && (p = macvalue('l', CurEnv)) != NULL)
+ UnixFromLine = newstr(p);
+ else
+ UnixFromLine = "From \201g \201d";
+ }
+
+ /* our name for SMTP codes */
+ expand("\201j", jbuf, sizeof jbuf, CurEnv);
+ MyHostName = jbuf;
+ if (strchr(jbuf, '.') == NULL)
+ message("WARNING: local host name (%s) is not qualified; fix $j in config file",
+ jbuf);
+
+ /* make certain that this name is part of the $=w class */
+ setclass('w', MyHostName);
+
+ /* the indices of built-in mailers */
+ st = stab("local", ST_MAILER, ST_FIND);
+ if (st != NULL)
+ LocalMailer = st->s_mailer;
+ else if (OpMode != MD_TEST || !warn_C_flag)
+ syserr("No local mailer defined");
+
+ st = stab("prog", ST_MAILER, ST_FIND);
+ if (st == NULL)
+ syserr("No prog mailer defined");
+ else
+ {
+ ProgMailer = st->s_mailer;
+ clrbitn(M_MUSER, ProgMailer->m_flags);
+ }
+
+ st = stab("*file*", ST_MAILER, ST_FIND);
+ if (st == NULL)
+ syserr("No *file* mailer defined");
+ else
+ {
+ FileMailer = st->s_mailer;
+ clrbitn(M_MUSER, FileMailer->m_flags);
+ }
+
+ st = stab("*include*", ST_MAILER, ST_FIND);
+ if (st == NULL)
+ syserr("No *include* mailer defined");
+ else
+ InclMailer = st->s_mailer;
+
+ if (ConfigLevel < 6)
+ {
+ /* heuristic tweaking of local mailer for back compat */
+ if (LocalMailer != NULL)
+ {
+ setbitn(M_ALIASABLE, LocalMailer->m_flags);
+ setbitn(M_HASPWENT, LocalMailer->m_flags);
+ setbitn(M_TRYRULESET5, LocalMailer->m_flags);
+ setbitn(M_CHECKINCLUDE, LocalMailer->m_flags);
+ setbitn(M_CHECKPROG, LocalMailer->m_flags);
+ setbitn(M_CHECKFILE, LocalMailer->m_flags);
+ setbitn(M_CHECKUDB, LocalMailer->m_flags);
+ }
+ if (ProgMailer != NULL)
+ setbitn(M_RUNASRCPT, ProgMailer->m_flags);
+ if (FileMailer != NULL)
+ setbitn(M_RUNASRCPT, FileMailer->m_flags);
+
+ /* propogate some envariables into children */
+ setuserenv("ISP", NULL);
+ setuserenv("SYSTYPE", NULL);
+ }
+
+ /* MIME Content-Types that cannot be transfer encoded */
+ setclass('n', "multipart/signed");
+
+ /* MIME message/* subtypes that can be treated as messages */
+ setclass('s', "rfc822");
+
+ /* MIME Content-Transfer-Encodings that can be encoded */
+ setclass('e', "7bit");
+ setclass('e', "8bit");
+ setclass('e', "binary");
+
+ /* operate in queue directory */
+ if (OpMode != MD_TEST && chdir(QueueDir) < 0)
+ {
+ syserr("cannot chdir(%s)", QueueDir);
+ ExitStat = EX_SOFTWARE;
+ }
+
+# ifdef QUEUE
+ if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
+ {
+ struct stat stbuf;
+
+ /* check to see if we own the queue directory */
+ if (stat(".", &stbuf) < 0)
+ syserr("main: cannot stat %s", QueueDir);
+ if (stbuf.st_uid != RealUid)
+ {
+ /* nope, really a botch */
+ usrerr("You do not have permission to process the queue");
+ exit (EX_NOPERM);
+ }
+ }
+# endif /* QUEUE */
+
+ /* if we've had errors so far, exit now */
+ if (ExitStat != EX_OK && OpMode != MD_TEST)
+ {
+ endpwent();
+ setuid(RealUid);
+ exit(ExitStat);
+ }
+
+#if XDEBUG
+ checkfd012("before main() initmaps");
+#endif
+
+ /*
+ ** Do operation-mode-dependent initialization.
+ */
+
+ switch (OpMode)
+ {
+ case MD_PRINT:
+ /* print the queue */
+#ifdef QUEUE
+ dropenvelope(CurEnv);
+ printqueue();
+ endpwent();
+ setuid(RealUid);
+ exit(EX_OK);
+#else /* QUEUE */
+ usrerr("No queue to print");
+ finis();
+#endif /* QUEUE */
+
+ case MD_INITALIAS:
+ /* initialize alias database */
+ initmaps(TRUE, CurEnv);
+ endpwent();
+ setuid(RealUid);
+ exit(EX_OK);
+
+ case MD_DAEMON:
+ case MD_SMTP:
+ /* don't open alias database -- done in srvrsmtp */
+ break;
+
+ default:
+ /* open the alias database */
+ initmaps(FALSE, CurEnv);
+ break;
+ }
+
+ if (tTd(0, 15))
+ {
+ /* print configuration table (or at least part of it) */
+ if (tTd(0, 90))
+ printrules();
+ for (i = 0; i < MAXMAILERS; i++)
+ {
+ if (Mailer[i] != NULL)
+ printmailer(Mailer[i]);
+ }
+ }
+
+ /*
+ ** Switch to the main envelope.
+ */
+
+ CurEnv = newenvelope(&MainEnvelope, CurEnv);
+ MainEnvelope.e_flags = BlankEnvelope.e_flags;
+
+ /*
+ ** If test mode, read addresses from stdin and process.
+ */
+
+ if (OpMode == MD_TEST)
+ {
+ char buf[MAXLINE];
+ void intindebug();
+
+ if (isatty(fileno(stdin)))
+ Verbose = TRUE;
+
+ if (Verbose)
+ {
+ printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n");
+ printf("Enter <ruleset> <address>\n");
+ }
+ if (setjmp(TopFrame) > 0)
+ printf("\n");
+ (void) setsignal(SIGINT, intindebug);
+ for (;;)
+ {
+ extern void testmodeline __P((char *, ENVELOPE *));
+
+ if (Verbose)
+ printf("> ");
+ (void) fflush(stdout);
+ if (fgets(buf, sizeof buf, stdin) == NULL)
+ finis();
+ p = strchr(buf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ if (!Verbose)
+ printf("> %s\n", buf);
+ testmodeline(buf, CurEnv);
+ }
+ }
+
+# ifdef QUEUE
+ /*
+ ** If collecting stuff from the queue, go start doing that.
+ */
+
+ if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
+ {
+ (void) unsetenv("HOSTALIASES");
+ runqueue(FALSE);
+ finis();
+ }
+# endif /* QUEUE */
+
+ /*
+ ** If a daemon, wait for a request.
+ ** getrequests will always return in a child.
+ ** If we should also be processing the queue, start
+ ** doing it in background.
+ ** We check for any errors that might have happened
+ ** during startup.
+ */
+
+ if (OpMode == MD_DAEMON || QueueIntvl != 0)
+ {
+ char dtype[200];
+
+ if (!tTd(99, 100))
+ {
+ /* put us in background */
+ i = fork();
+ if (i < 0)
+ syserr("daemon: cannot fork");
+ if (i != 0)
+ exit(0);
+
+ /* disconnect from our controlling tty */
+ disconnect(2, 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");
+
+#ifdef LOG
+ syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);
+#endif
+#ifdef XLA
+ xla_create_file();
+#endif
+
+# ifdef QUEUE
+ if (queuemode)
+ {
+ runqueue(TRUE);
+ if (OpMode != MD_DAEMON)
+ for (;;)
+ pause();
+ }
+# endif /* QUEUE */
+ dropenvelope(CurEnv);
+
+#ifdef DAEMON
+ getrequests();
+
+ /* at this point we are in a child: reset state */
+ (void) newenvelope(CurEnv, CurEnv);
+
+ /*
+ ** Get authentication data
+ */
+
+ p = getauthinfo(fileno(InChannel));
+ define('_', p, CurEnv);
+
+#endif /* DAEMON */
+ }
+
+# ifdef SMTP
+ /*
+ ** If running SMTP protocol, start collecting and executing
+ ** commands. This will never return.
+ */
+
+ if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
+ smtp(CurEnv);
+# endif /* SMTP */
+
+ if (OpMode == MD_VERIFY)
+ {
+ CurEnv->e_sendmode = SM_VERIFY;
+ CurEnv->e_errormode = EM_QUIET;
+ PostMasterCopy = NULL;
+ }
+ else
+ {
+ /* interactive -- all errors are global */
+ CurEnv->e_flags |= EF_GLOBALERRS|EF_LOGSENDER;
+ }
+
+ /*
+ ** Do basic system initialization and set the sender
+ */
+
+ initsys(CurEnv);
+ if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't'))
+ auth_warning(CurEnv, "%s set sender to %s using -%c",
+ RealUserName, from, warn_f_flag);
+ setsender(from, CurEnv, NULL, FALSE);
+ if (macvalue('s', CurEnv) == NULL)
+ define('s', RealHostName, CurEnv);
+
+ if (*av == NULL && !GrabTo)
+ {
+ CurEnv->e_flags |= EF_GLOBALERRS;
+ usrerr("Recipient names must be specified");
+
+ /* collect body for UUCP return */
+ if (OpMode != MD_VERIFY)
+ collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ finis();
+ }
+
+ /*
+ ** Scan argv and deliver the message to everyone.
+ */
+
+ sendtoargv(av, CurEnv);
+
+ /* if we have had errors sofar, arrange a meaningful exit stat */
+ if (Errors > 0 && ExitStat == EX_OK)
+ ExitStat = EX_USAGE;
+
+ /*
+ ** Read the input mail.
+ */
+
+ CurEnv->e_to = NULL;
+ if (OpMode != MD_VERIFY || GrabTo)
+ {
+ CurEnv->e_flags |= EF_GLOBALERRS;
+ collect(InChannel, FALSE, FALSE, NULL, CurEnv);
+ }
+ errno = 0;
+
+ if (tTd(1, 1))
+ printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
+
+ /*
+ ** Actually send everything.
+ ** If verifying, just ack.
+ */
+
+ 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);
+
+ /*
+ ** All done.
+ ** Don't send return error message if in VERIFY mode.
+ */
+
+ finis();
+}
+
+
+void
+intindebug()
+{
+ longjmp(TopFrame, 1);
+}
+
+
+ /*
+** FINIS -- Clean up and exit.
+**
+** Parameters:
+** none
+**
+** Returns:
+** never
+**
+** Side Effects:
+** exits sendmail
+*/
+
+void
+finis()
+{
+ if (tTd(2, 1))
+ {
+ extern void printenvflags();
+
+ printf("\n====finis: stat %d e_id=%s e_flags=",
+ ExitStat,
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
+ printenvflags(CurEnv);
+ }
+ if (tTd(2, 9))
+ printopenfds(FALSE);
+
+ /* clean up temp files */
+ CurEnv->e_to = NULL;
+ dropenvelope(CurEnv);
+
+ /* flush any cached connections */
+ mci_flush(TRUE, NULL);
+
+# ifdef XLA
+ /* clean up extended load average stuff */
+ xla_all_end();
+# endif
+
+ /* and exit */
+# ifdef LOG
+ if (LogLevel > 78)
+ syslog(LOG_DEBUG, "finis, pid=%d", getpid());
+# endif /* LOG */
+ if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET)
+ ExitStat = EX_OK;
+
+ /* reset uid for process accounting */
+ endpwent();
+ setuid(RealUid);
+
+ exit(ExitStat);
+}
+ /*
+** INTSIG -- clean up on interrupt
+**
+** This just arranges to exit. It pessimises in that it
+** may resend a message.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Unlocks the current job.
+*/
+
+void
+intsig()
+{
+ FileName = NULL;
+ unlockqueue(CurEnv);
+#ifdef XLA
+ xla_all_end();
+#endif
+
+ /* reset uid for process accounting */
+ endpwent();
+ setuid(RealUid);
+
+ exit(EX_OK);
+}
+ /*
+** INITMACROS -- initialize the macro system
+**
+** This just involves defining some macros that are actually
+** used internally as metasymbols to be themselves.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** initializes several macros to be themselves.
+*/
+
+struct metamac MetaMacros[] =
+{
+ /* LHS pattern matching characters */
+ '*', MATCHZANY, '+', MATCHANY, '-', MATCHONE,
+ '=', MATCHCLASS, '~', MATCHNCLASS,
+
+ /* these are RHS metasymbols */
+ '#', CANONNET, '@', CANONHOST, ':', CANONUSER,
+ '>', CALLSUBR,
+
+ /* the conditional operations */
+ '?', CONDIF, '|', CONDELSE, '.', CONDFI,
+
+ /* the hostname lookup characters */
+ '[', HOSTBEGIN, ']', HOSTEND,
+ '(', LOOKUPBEGIN, ')', LOOKUPEND,
+
+ /* miscellaneous control characters */
+ '&', MACRODEXPAND,
+
+ '\0'
+};
+
+#define MACBINDING(name, mid) \
+ stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \
+ MacroName[mid] = name;
+
+void
+initmacros(e)
+ register ENVELOPE *e;
+{
+ register struct metamac *m;
+ register int c;
+ char buf[5];
+ extern char *MacroName[256];
+
+ for (m = MetaMacros; m->metaname != '\0'; m++)
+ {
+ buf[0] = m->metaval;
+ buf[1] = '\0';
+ define(m->metaname, newstr(buf), e);
+ }
+ buf[0] = MATCHREPL;
+ buf[2] = '\0';
+ for (c = '0'; c <= '9'; c++)
+ {
+ buf[1] = c;
+ define(c, newstr(buf), e);
+ }
+
+ /* set defaults for some macros sendmail will use later */
+ define('n', "MAILER-DAEMON", e);
+
+ /* set up external names for some internal macros */
+ MACBINDING("opMode", MID_OPMODE);
+ /*XXX should probably add equivalents for all short macros here XXX*/
+}
+ /*
+** DISCONNECT -- remove our connection with any foreground process
+**
+** Parameters:
+** droplev -- how "deeply" we should drop the line.
+** 0 -- ignore signals, mail back errors, make sure
+** output goes to stdout.
+** 1 -- also, make stdout go to transcript.
+** 2 -- also, disconnect from controlling terminal
+** (only for daemon mode).
+** e -- the current envelope.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Trys to insure that we are immune to vagaries of
+** the controlling tty.
+*/
+
+void
+disconnect(droplev, e)
+ int droplev;
+ register ENVELOPE *e;
+{
+ int fd;
+
+ if (tTd(52, 1))
+ printf("disconnect: In %d Out %d, e=%x\n",
+ fileno(InChannel), fileno(OutChannel), e);
+ if (tTd(52, 100))
+ {
+ printf("don't\n");
+ return;
+ }
+
+ /* be sure we don't get nasty signals */
+ (void) setsignal(SIGINT, SIG_IGN);
+ (void) setsignal(SIGQUIT, SIG_IGN);
+
+ /* we can't communicate with our caller, so.... */
+ HoldErrs = TRUE;
+ CurEnv->e_errormode = EM_MAIL;
+ Verbose = FALSE;
+ DisConnected = TRUE;
+
+ /* all input from /dev/null */
+ if (InChannel != stdin)
+ {
+ (void) fclose(InChannel);
+ InChannel = stdin;
+ }
+ (void) freopen("/dev/null", "r", stdin);
+
+ /* output to the transcript */
+ if (OutChannel != stdout)
+ {
+ (void) fclose(OutChannel);
+ OutChannel = stdout;
+ }
+ if (droplev > 0)
+ {
+ if (e->e_xfp == NULL)
+ fd = open("/dev/null", O_WRONLY, 0666);
+ else
+ fd = fileno(e->e_xfp);
+ (void) fflush(stdout);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (e->e_xfp == NULL)
+ close(fd);
+ }
+
+ /* drop our controlling TTY completely if possible */
+ if (droplev > 1)
+ {
+ (void) setsid();
+ errno = 0;
+ }
+
+#if XDEBUG
+ checkfd012("disconnect");
+#endif
+
+# ifdef LOG
+ if (LogLevel > 71)
+ syslog(LOG_DEBUG, "in background, pid=%d", getpid());
+# endif /* LOG */
+
+ errno = 0;
+}
+
+static void
+obsolete(argv)
+ char *argv[];
+{
+ register char *ap;
+ register char *op;
+
+ while ((ap = *++argv) != NULL)
+ {
+ /* Return if "--" or not an option of any form. */
+ if (ap[0] != '-' || ap[1] == '-')
+ return;
+
+ /* skip over options that do have a value */
+ op = strchr(OPTIONS, ap[1]);
+ if (op != NULL && *++op == ':' && ap[2] == '\0' &&
+ ap[1] != 'd' &&
+#if defined(sony_news)
+ ap[1] != 'E' && ap[1] != 'J' &&
+#endif
+ argv[1] != NULL && argv[1][0] != '-')
+ {
+ argv++;
+ continue;
+ }
+
+ /* If -C doesn't have an argument, use sendmail.cf. */
+#define __DEFPATH "sendmail.cf"
+ if (ap[1] == 'C' && ap[2] == '\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 = "-q0";
+
+ /* if -d doesn't have an argument, use 0-99.1 */
+ if (ap[1] == 'd' && ap[2] == '\0')
+ *argv = "-d0-99.1";
+
+# if defined(sony_news)
+ /* if -E doesn't have an argument, use -EC */
+ if (ap[1] == 'E' && ap[2] == '\0')
+ *argv = "-EC";
+
+ /* if -J doesn't have an argument, use -JJ */
+ if (ap[1] == 'J' && ap[2] == '\0')
+ *argv = "-JJ";
+# endif
+ }
+}
+ /*
+** 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 struct hostent *myhostname();
+
+ if (hostbuf[0] == '\0')
+ (void) myhostname(hostbuf, sizeof hostbuf);
+
+ (void) sprintf(buf, "%s: ", hostbuf);
+ p = &buf[strlen(buf)];
+ VA_START(msg);
+ vsnprintf(p, sizeof buf - (p - buf), msg, ap);
+ VA_END;
+ addheader("X-Authentication-Warning", buf, &e->e_header);
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_INFO, "%s: Authentication-Warning: %.400s",
+ e->e_id == NULL ? "[NOQUEUE]" : e->e_id, buf);
+#endif
+ }
+}
+ /*
+** SETUSERENV -- set an environment in the propogated environment
+**
+** Parameters:
+** envar -- the name of the environment variable.
+** value -- the value to which it should be set. If
+** null, this is extracted from the incoming
+** environment. If that is not set, the call
+** to setuserenv is ignored.
+**
+** Returns:
+** none.
+*/
+
+void
+setuserenv(envar, value)
+ const char *envar;
+ const char *value;
+{
+ int i;
+ char **evp = UserEnviron;
+ char *p;
+
+ if (value == NULL)
+ {
+ value = getenv(envar);
+ if (value == NULL)
+ return;
+ }
+
+ i = strlen(envar);
+ p = (char *) xalloc(strlen(value) + i + 2);
+ strcpy(p, envar);
+ p[i++] = '=';
+ strcpy(&p[i], value);
+
+ while (*evp != NULL && strncmp(*evp, p, i) != 0)
+ evp++;
+ if (*evp != NULL)
+ {
+ *evp++ = p;
+ }
+ else if (evp < &UserEnviron[MAXUSERENVIRON])
+ {
+ *evp++ = p;
+ *evp = NULL;
+ }
+
+ /* make sure it is in our environment as well */
+ if (putenv(p) < 0)
+ syserr("setuserenv: putenv(%s) failed", p);
+}
+ /*
+** DUMPSTATE -- dump state
+**
+** For debugging.
+*/
+
+void
+dumpstate(when)
+ char *when;
+{
+#ifdef LOG
+ register char *j = macvalue('j', CurEnv);
+
+ syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
+ when,
+ j == NULL ? "<NULL>" : j);
+ if (j != NULL)
+ {
+ if (!wordinclass(j, 'w'))
+ syslog(LOG_DEBUG, "*** $j not in $=w ***");
+ }
+ syslog(LOG_DEBUG, "CurChildren = %d", CurChildren);
+ syslog(LOG_DEBUG, "--- open file descriptors: ---");
+ printopenfds(TRUE);
+ syslog(LOG_DEBUG, "--- connection cache: ---");
+ mci_dump_all(TRUE);
+ if (RewriteRules[89] != NULL)
+ {
+ int stat;
+ register char **pvp;
+ char *pv[MAXATOM + 1];
+
+ pv[0] = NULL;
+ stat = rewrite(pv, 89, 0, CurEnv);
+ syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
+ stat);
+ for (pvp = pv; *pvp != NULL; pvp++)
+ syslog(LOG_DEBUG, "%s", *pvp);
+ }
+ syslog(LOG_DEBUG, "--- end of state dump ---");
+#endif
+}
+
+
+void
+sigusr1()
+{
+ dumpstate("user signal");
+}
+
+
+void
+sighup()
+{
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
+#endif
+ releasesignal(SIGHUP);
+ execv(SaveArgv[0], (ARGV_T) SaveArgv);
+#ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]);
+#endif
+ exit(EX_OSFILE);
+}
+ /*
+** TESTMODELINE -- process a test mode input line
+**
+** Parameters:
+** line -- the input line.
+** e -- the current environment.
+** Syntax:
+** # a comment
+** .X process X as a configuration line
+** =X dump a configuration item (such as mailers)
+** $X dump a macro or class
+** /X try an activity
+** X normal process through rule set X
+*/
+
+void
+testmodeline(line, e)
+ char *line;
+ ENVELOPE *e;
+{
+ register char *p;
+ char *q;
+ auto char *delimptr;
+ int mid;
+ int i, rs;
+ STAB *map;
+ char **s;
+ struct rewrite *rw;
+ ADDRESS a;
+ static int tryflags = RF_COPYNONE;
+ char exbuf[MAXLINE];
+ extern bool invalidaddr __P((char *, char *));
+ extern char *crackaddr __P((char *));
+ extern void dump_class __P((STAB *, int));
+ extern void translate_dollars __P((char *));
+
+ switch (line[0])
+ {
+ case '#':
+ case 0:
+ return;
+
+ case '?':
+ help("-bt");
+ return;
+
+ case '.': /* config-style settings */
+ switch (line[1])
+ {
+ case 'D':
+ mid = macid(&line[2], &delimptr);
+ if (mid == '\0')
+ return;
+ translate_dollars(delimptr);
+ define(mid, newstr(delimptr), e);
+ break;
+
+ case 'C':
+ if (line[2] == '\0') /* not to call syserr() */
+ return;
+
+ mid = macid(&line[2], &delimptr);
+ if (mid == '\0')
+ return;
+ translate_dollars(delimptr);
+ expand(delimptr, exbuf, sizeof exbuf, e);
+ p = exbuf;
+ while (*p != '\0')
+ {
+ register char *wd;
+ char delim;
+
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ wd = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ delim = *p;
+ *p = '\0';
+ if (wd[0] != '\0')
+ setclass(mid, wd);
+ *p = delim;
+ }
+ break;
+
+ case '\0':
+ printf("Usage: .[DC]macro value(s)\n");
+ break;
+
+ default:
+ printf("Unknown \".\" command %s\n", line);
+ break;
+ }
+ return;
+
+ case '=': /* config-style settings */
+ switch (line[1])
+ {
+ case 'S': /* dump rule set */
+ rs = strtorwset(&line[2], NULL, ST_FIND);
+ if (rs < 0)
+ return;
+ rw = RewriteRules[rs];
+ if (rw == NULL)
+ return;
+ do
+ {
+ putchar('R');
+ s = rw->r_lhs;
+ while (*s != NULL)
+ {
+ xputs(*s++);
+ putchar(' ');
+ }
+ putchar('\t');
+ putchar('\t');
+ s = rw->r_rhs;
+ while (*s != NULL)
+ {
+ xputs(*s++);
+ putchar(' ');
+ }
+ putchar('\n');
+ } while (rw = rw->r_next);
+ break;
+
+ case 'M':
+ for (i = 0; i < MAXMAILERS; i++)
+ {
+ if (Mailer[i] != NULL)
+ printmailer(Mailer[i]);
+ }
+ break;
+
+ case '\0':
+ printf("Usage: =Sruleset or =M\n");
+ break;
+
+ default:
+ printf("Unknown \"=\" command %s\n", line);
+ break;
+ }
+ return;
+
+ case '-': /* set command-line-like opts */
+ switch (line[1])
+ {
+ case 'd':
+ tTflag(&line[2]);
+ break;
+
+ case '\0':
+ printf("Usage: -d{debug arguments}\n");
+ break;
+
+ default:
+ printf("Unknown \"-\" command %s\n", line);
+ break;
+ }
+ return;
+
+ case '$':
+ if (line[1] == '=')
+ {
+ mid = macid(&line[2], NULL);
+ if (mid != '\0')
+ stabapply(dump_class, mid);
+ return;
+ }
+ mid = macid(&line[1], NULL);
+ if (mid == '\0')
+ return;
+ p = macvalue(mid, e);
+ if (p == NULL)
+ printf("Undefined\n");
+ else
+ {
+ xputs(p);
+ printf("\n");
+ }
+ return;
+
+ case '/': /* miscellaneous commands */
+ p = &line[strlen(line)];
+ while (--p >= line && isascii(*p) && isspace(*p))
+ *p = '\0';
+ p = strpbrk(line, " \t");
+ if (p != NULL)
+ {
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ }
+ else
+ p = "";
+ if (line[1] == '\0')
+ {
+ printf("Usage: /[canon|map|mx|parse|try|tryflags]\n");
+ return;
+ }
+ if (strcasecmp(&line[1], "mx") == 0)
+ {
+#if NAMED_BIND
+ /* look up MX records */
+ int nmx;
+ auto int rcode;
+ char *mxhosts[MAXMXHOSTS + 1];
+
+ if (*p == '\0')
+ {
+ printf("Usage: /mx address\n");
+ return;
+ }
+ nmx = getmxrr(p, mxhosts, FALSE, &rcode);
+ printf("getmxrr(%s) returns %d value(s):\n", p, nmx);
+ for (i = 0; i < nmx; i++)
+ printf("\t%s\n", mxhosts[i]);
+#else
+ printf("No MX code compiled in\n");
+#endif
+ }
+ else if (strcasecmp(&line[1], "canon") == 0)
+ {
+ auto int rcode = EX_OK;
+ char host[MAXHOSTNAMELEN];
+
+ if (*p == '\0')
+ {
+ printf("Usage: /canon address\n");
+ return;
+ }
+ strcpy(host, p);
+ getcanonname(host, sizeof(host), HasWildcardMX, &rcode);
+ printf("getcanonname(%s) returns %s (%d)\n",
+ p, host, rcode);
+ }
+ else if (strcasecmp(&line[1], "map") == 0)
+ {
+ auto int rcode = EX_OK;
+
+ if (*p == '\0')
+ {
+ printf("Usage: /map mapname key\n");
+ return;
+ }
+ for (q = p; *q != '\0' && !isspace(*q); q++)
+ continue;
+ if (*q == '\0')
+ {
+ printf("No key specified\n");
+ return;
+ }
+ *q++ = '\0';
+ map = stab(p, ST_MAP, ST_FIND);
+ if (map == NULL)
+ {
+ printf("Map named \"%s\" not found\n", p);
+ return;
+ }
+ printf("map_lookup: %s (%s) ", p, q);
+ p = (*map->s_map.map_class->map_lookup)
+ (&map->s_map, q, NULL, &rcode);
+ if (p == NULL)
+ printf("no match (%d)\n", rcode);
+ else
+ printf("returns %s (%d)\n", p, rcode);
+ }
+ else if (strcasecmp(&line[1], "try") == 0)
+ {
+ MAILER *m;
+ STAB *s;
+ auto int rcode = EX_OK;
+
+ q = strpbrk(p, " \t");
+ if (q != NULL)
+ {
+ while (isascii(*q) && isspace(*q))
+ *q++ = '\0';
+ }
+ if (q == NULL || *q == '\0')
+ {
+ printf("Usage: /try mailer address\n");
+ return;
+ }
+ s = stab(p, ST_MAILER, ST_FIND);
+ if (s == NULL)
+ {
+ printf("Unknown mailer %s\n", p);
+ return;
+ }
+ m = s->s_mailer;
+ printf("Trying %s %s address %s for mailer %s\n",
+ bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope",
+ bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient",
+ q, p);
+ p = remotename(q, m, tryflags, &rcode, CurEnv);
+ printf("Rcode = %d, addr = %s\n",
+ rcode, p == NULL ? "<NULL>" : p);
+ }
+ else if (strcasecmp(&line[1], "tryflags") == 0)
+ {
+ if (*p == '\0')
+ {
+ printf("Usage: /tryflags [Hh|Ee][Ss|Rr]\n");
+ return;
+ }
+ for (; *p != '\0'; p++)
+ {
+ switch (*p)
+ {
+ case 'H':
+ case 'h':
+ tryflags |= RF_HEADERADDR;
+ break;
+
+ case 'E':
+ case 'e':
+ tryflags &= ~RF_HEADERADDR;
+ break;
+
+ case 'S':
+ case 's':
+ tryflags |= RF_SENDERADDR;
+ break;
+
+ case 'R':
+ case 'r':
+ tryflags &= ~RF_SENDERADDR;
+ break;
+ }
+ }
+ }
+ else if (strcasecmp(&line[1], "parse") == 0)
+ {
+ if (*p == '\0')
+ {
+ printf("Usage: /parse address\n");
+ return;
+ }
+ q = crackaddr(p);
+ printf("Cracked address = ");
+ xputs(q);
+ printf("\nParsing %s %s address\n",
+ bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope",
+ bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient");
+ if (parseaddr(p, &a, tryflags, '\0', NULL, e) == NULL)
+ printf("Cannot parse\n");
+ else if (a.q_host != NULL && a.q_host[0] != '\0')
+ printf("mailer %s, host %s, user %s\n",
+ a.q_mailer->m_name, a.q_host, a.q_user);
+ else
+ printf("mailer %s, user %s\n",
+ a.q_mailer->m_name, a.q_user);
+ }
+ else
+ {
+ printf("Unknown \"/\" command %s\n", line);
+ }
+ return;
+ }
+
+ for (p = line; isascii(*p) && isspace(*p); p++)
+ continue;
+ q = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p == '\0')
+ {
+ printf("No address!\n");
+ return;
+ }
+ *p = '\0';
+ if (invalidaddr(p + 1, NULL))
+ return;
+ do
+ {
+ register char **pvp;
+ char pvpbuf[PSBUFSIZE];
+
+ pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
+ &delimptr, NULL);
+ if (pvp == NULL)
+ continue;
+ p = q;
+ while (*p != '\0')
+ {
+ int stat;
+ int rs = strtorwset(p, NULL, ST_FIND);
+
+ if (rs < 0)
+ break;
+ stat = rewrite(pvp, rs, 0, e);
+ if (stat != EX_OK)
+ printf("== Ruleset %s (%d) status %d\n",
+ p, rs, stat);
+ while (*p != '\0' && *p++ != ',')
+ continue;
+ }
+ } while (*(p = delimptr) != '\0');
+}
+
+
+void
+dump_class(s, id)
+ register STAB *s;
+ int id;
+{
+ if (s->s_type != ST_CLASS)
+ return;
+ if (bitnset(id & 0xff, s->s_class))
+ printf("%s\n", s->s_name);
+}
diff --git a/usr.sbin/sendmail/src/makesendmail b/usr.sbin/sendmail/src/makesendmail
new file mode 100644
index 000000000000..df202e9163e2
--- /dev/null
+++ b/usr.sbin/sendmail/src/makesendmail
@@ -0,0 +1,282 @@
+#!/bin/sh
+
+# Copyright (c) 1993 Eric P. Allman
+# Copyright (c) 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.
+#
+# @(#)makesendmail 8.29 (Berkeley) 8/1/95
+#
+
+#
+# A quick-and-dirty script to compile sendmail in the presence of
+# multiple architectures and Makefiles.
+#
+
+if [ "x${1-""}" = "x-m" ]
+then
+ # show Makefile name only
+ mflag=1
+else
+ mflag=""
+fi
+
+#
+# Do heuristic guesses !ONLY! for machines that do not have uname
+#
+if [ -d /LocalApps -a ! -f /bin/uname -a ! -f /usr/bin/uname ]
+then
+ # probably a NeXT box
+ arch=NeXT
+ os=Mach
+ rel=`strings /mach | grep 'Mach.*:' | sed -e 's/.* Mach //' -e 's/:.*//'`
+elif [ -f /usr/sony/bin/machine -a -f /etc/osversion ]
+then
+ # probably a Sony NEWS 4.x
+ os=NEWS-OS
+ rel=`awk '{ print $3}' /etc/osversion`
+ arch=`/usr/sony/bin/machine`
+elif [ -d /usr/omron -a -f /bin/luna ]
+then
+ # probably a Omron LUNA
+ os=LUNA
+ if [ -f /bin/luna1 ] && /bin/luna1
+ then
+ rel=unios-b
+ arch=luna1
+ elif [ -f /bin/luna2 ] && /bin/luna2
+ then
+ rel=Mach
+ arch=luna2
+ elif [ -f /bin/luna88k ] && /bin/luna88k
+ then
+ rel=Mach
+ arch=luna88k
+ fi
+fi
+
+if [ ! "$arch" -a ! "$os" -a ! "$rel" ]
+then
+ arch=`uname -m | sed -e 's/ //g'`
+ os=`uname -s | sed 's/\//-/g'`
+ rel=`uname -r`
+fi
+
+#
+# Tweak the values we have already got. PLEASE LIMIT THESE to
+# tweaks that are absolutely necessary because your system uname
+# routine doesn't return something sufficiently unique. Don't do
+# it just because you don't like the name that is returned. You
+# can combine the architecture name with the os name to create a
+# unique Makefile name.
+#
+
+# tweak machine architecture
+case $arch
+in
+ sun4*) arch=sun4;;
+
+ 9000/*) arch=`echo $arch | sed -e 's/9000.//' -e 's/..$/xx/'`;;
+esac
+
+# tweak operating system type and release
+case $os
+in
+ DYNIX-ptx) os=PTX;;
+ Paragon*) os=Paragon;;
+ HP-UX) rel=`echo $rel | sed -e 's/^[^.]*\.0*//'`;;
+ AIX) rel=`uname -v`;;
+ BSD-386) os=BSD-OS;;
+esac
+
+# get "base part" of operating system release
+rbase=`echo $rel | sed -e 's/\..*//'`
+
+# heuristic tweaks to clean up names -- PLEASE LIMIT THESE!
+if [ "$os" = "unix" ]
+then
+ # might be Altos System V
+ case $rel
+ in
+ 5.3*) os=Altos;;
+ esac
+elif [ -r /unix -a -r /usr/lib/libseq.a -a -r /lib/cpp ]
+then
+ # might be a DYNIX/ptx 2.x system, which has a broken uname
+ if strings /lib/cpp | grep _SEQUENT_ > /dev/null
+ then
+ os=PTX
+ fi
+elif [ -d /usr/nec ]
+then
+ # NEC machine -- what is it running?
+ if [ "$os" = "UNIX_System_V" ]
+ then
+ os=EWS-UX_V
+ elif [ "$os" = "UNIX_SV" ]
+ then
+ os=UX4800
+ fi
+elif [ "$arch" = "mips" ]
+then
+ case $rel
+ in
+ 4_*)
+ if [ `uname -v` = "UMIPS" ]
+ then
+ os=RISCos
+ fi;;
+ esac
+fi
+
+# see if there is a "user suffix" specified
+if [ "${SENDMAIL_SUFFIX-}x" = "x" ]
+then
+ sfx=""
+else
+ sfx=".${SENDMAIL_SUFFIX}"
+fi
+
+echo "Configuration: os=$os, rel=$rel, rbase=$rbase, arch=$arch, sfx=$sfx"
+
+# now try to find a reasonable object directory
+if [ -r obj.$os.$rel.$arch$sfx ]; then
+ obj=obj.$os.$rel.$arch$sfx
+elif [ -r obj.$os.$rbase.x.$arch$sfx ]; then
+ obj=obj.$os.$rbase.x.$arch$sfx
+elif [ -r obj.$os.$rel$sfx ]; then
+ obj=obj.$os.$rel$sfx
+elif [ -r obj.$os.$rbase.x$sfx ]; then
+ obj=obj.$os.$rbase.x$sfx
+elif [ -r obj.$os.$arch$sfx ]; then
+ obj=obj.$os.$arch$sfx
+elif [ -r obj.$rel.$arch$sfx ]; then
+ obj=obj.$rel.$arch$sfx
+elif [ -r obj.$rbase.x.$arch$sfx ]; then
+ obj=obj.$rbase.x.$arch$sfx
+elif [ -r obj.$os$sfx ]; then
+ obj=obj.$os$sfx
+elif [ -r obj.$arch$sfx ]; then
+ obj=obj.$arch$sfx
+elif [ -r obj.$rel$sfx ]; then
+ obj=obj.$rel$sfx
+elif [ -r obj$sfx ]; then
+ obj=obj$sfx
+else
+ # no existing obj directory -- try to create one if Makefile found
+ obj=obj.$os.$rel.$arch$sfx
+ if [ -r Makefiles/Makefile.$os.$rel.$arch$sfx ]; then
+ makefile=Makefile.$os.$rel.$arch$sfx
+ elif [ -r Makefiles/Makefile.$os.$rel.$arch ]; then
+ makefile=Makefile.$os.$rel.$arch
+ elif [ -r Makefiles/Makefile.$os.$rbase.x.$arch$sfx ]; then
+ makefile=Makefile.$os.$rbase.x.$arch$sfx
+ elif [ -r Makefiles/Makefile.$os.$rbase.x.$arch ]; then
+ makefile=Makefile.$os.$rbase.x.$arch
+ elif [ -r Makefiles/Makefile.$os.$rel$sfx ]; then
+ makefile=Makefile.$os.$rel$sfx
+ elif [ -r Makefiles/Makefile.$os.$rel ]; then
+ makefile=Makefile.$os.$rel
+ elif [ -r Makefiles/Makefile.$os.$rbase.x$sfx ]; then
+ makefile=Makefile.$os.$rbase.x$sfx
+ elif [ -r Makefiles/Makefile.$os.$rbase.x ]; then
+ makefile=Makefile.$os.$rbase.x
+ elif [ -r Makefiles/Makefile.$os.$arch$sfx ]; then
+ makefile=Makefile.$os.$arch$sfx
+ elif [ -r Makefiles/Makefile.$os.$arch ]; then
+ makefile=Makefile.$os.$arch
+ elif [ -r Makefiles/Makefile.$rel.$arch$sfx ]; then
+ makefile=Makefile.$rel.$arch$sfx
+ elif [ -r Makefiles/Makefile.$rel.$arch ]; then
+ makefile=Makefile.$rel.$arch
+ elif [ -r Makefiles/Makefile.$rbase.x.$arch$sfx ]; then
+ makefile=Makefile.$rbase.x.$arch$sfx
+ elif [ -r Makefiles/Makefile.$rbase.x.$arch ]; then
+ makefile=Makefile.$rbase.x.$arch
+ elif [ -r Makefiles/Makefile.$os$sfx ]; then
+ makefile=Makefile.$os$sfx
+ elif [ -r Makefiles/Makefile.$os ]; then
+ makefile=Makefile.$os
+ elif [ -r Makefiles/Makefile.$arch$sfx ]; then
+ makefile=Makefile.$arch$sfx
+ elif [ -r Makefiles/Makefile.$arch ]; then
+ makefile=Makefile.$arch
+ elif [ -r Makefiles/Makefile.$rel$sfx ]; then
+ makefile=Makefile.$rel$sfx
+ elif [ -r Makefiles/Makefile.$rel ]; then
+ makefile=Makefile.$rel
+ elif [ -r Makefiles/Makefile.$rel$sfx ]; then
+ makefile=Makefile.$rel$sfx
+ else
+ echo "Cannot determine how to support $arch.$os.$rel"
+ exit 1
+ fi
+ if [ "$mflag" ]
+ then
+ echo "Will run in virgin $obj using $makefile"
+ exit 0
+ fi
+ echo "Creating $obj using $makefile"
+ mkdir $obj
+ (cd $obj; ln -s ../*.[ch158] ../sendmail.hf .; ln -s ../Makefiles/$makefile Makefile)
+ echo "Making dependencies in $obj"
+ (cd $obj; ${MAKE-make} depend)
+fi
+
+if [ "$mflag" ]
+then
+ makefile=`ls -l $obj/Makefile | sed 's/.* //'`
+ if [ -z "$makefile" ]
+ then
+ echo "ERROR: $obj exists but has no Makefile"
+ exit 1
+ fi
+ case $makefile
+ in
+ ../Makefiles/*)
+ makefile=`echo $makefile | sed 's/...Makefiles.//'`
+ echo "Will run in existing $obj using $makefile"
+ ;;
+
+ *)
+ echo "Will run in existing $obj using custom $makefile"
+ ;;
+ esac
+ exit 0
+fi
+
+echo "Making in $obj"
+cd $obj
+if [ $# = 0 ]
+then
+ exec ${MAKE-make}
+else
+ exec ${MAKE-make} "$@"
+fi
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c
new file mode 100644
index 000000000000..b8ea903fb3de
--- /dev/null
+++ b/usr.sbin/sendmail/src/map.c
@@ -0,0 +1,3330 @@
+/*
+ * Copyright (c) 1992, 1995 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.107 (Berkeley) 11/20/95";
+#endif /* not lint */
+
+#include "sendmail.h"
+
+#ifdef NDBM
+# include <ndbm.h>
+#endif
+#ifdef NEWDB
+# ifdef R_FIRST
+ ERROR README: You are running the Berkeley DB version of ndbm.h. See
+ ERROR README: the READ_ME file about tweaking Berkeley DB so it can
+ ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile.
+# endif
+# include <db.h>
+#endif
+#ifdef NIS
+ struct dom_binding; /* forward reference needed on IRIX */
+# 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.
+**
+** This file also includes the implementation for getcanonname.
+** It is currently implemented in a pretty ad-hoc manner; it ought
+** to be more properly integrated into the map structure.
+*/
+
+#define DBMMODE 0644
+
+#define EX_NOTFOUND EX_NOHOST
+
+extern bool aliaswait __P((MAP *, char *, int));
+extern bool extract_canonname __P((char *, char *, char[]));
+
+#if defined(O_EXLOCK) && HASFLOCK
+# define LOCK_ON_OPEN 1 /* we can open/create a locked file */
+#else
+# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */
+#endif
+ /*
+** 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;
+
+ map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
+ for (;;)
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ switch (*++p)
+ {
+ case 'N':
+ map->map_mflags |= MF_INCLNULL;
+ map->map_mflags &= ~MF_TRY0NULL;
+ break;
+
+ case 'O':
+ map->map_mflags &= ~MF_TRY1NULL;
+ 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_mflags |= MF_APPEND;
+ break;
+
+ case 'q':
+ map->map_mflags |= MF_KEEPQUOTES;
+ break;
+
+ case 'a':
+ map->map_app = ++p;
+ break;
+
+ case 'k':
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ map->map_keycolnm = p;
+ break;
+
+ case 'v':
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ map->map_valcolnm = p;
+ break;
+
+ case 'z':
+ if (*++p != '\\')
+ map->map_coldelim = *p;
+ else
+ {
+ switch (*++p)
+ {
+ case 'n':
+ map->map_coldelim = '\n';
+ break;
+
+ case 't':
+ map->map_coldelim = '\t';
+ break;
+
+ default:
+ map->map_coldelim = '\\';
+ }
+ }
+ break;
+#ifdef RESERVED_FOR_SUN
+ case 'd':
+ map->map_mflags |= MF_DOMAIN_WIDE;
+ break;
+
+ case 's':
+ /* info type */
+ break;
+#endif
+ }
+ 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 (map->map_keycolnm != NULL)
+ map->map_keycolnm = newstr(map->map_keycolnm);
+ if (map->map_valcolnm != NULL)
+ map->map_valcolnm = newstr(map->map_valcolnm);
+
+ 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 &&
+ !bitset(MCF_OPTFILE, map->map_class->map_cflags))
+ {
+ syserr("No file name for %s map %s",
+ map->map_class->map_cname, map->map_mname);
+ return FALSE;
+ }
+ return TRUE;
+}
+ /*
+** 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. This is static data that
+** should be copied if it is to be saved!
+**
+** Side Effects:
+** none.
+*/
+
+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;
+ int i;
+ int len;
+ static int buflen = -1;
+ static char *buf = NULL;
+
+ 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");
+ }
+
+ /* 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;
+ 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 (buflen < ++len)
+ {
+ /* need to malloc additional space */
+ buflen = len;
+ if (buf != NULL)
+ free(buf);
+ buf = xalloc(buflen);
+ }
+
+ bp = 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;
+ }
+ 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", buf);
+ return buf;
+}
+ /*
+** 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.
+*/
+
+void
+initmaps(rebuild, e)
+ bool rebuild;
+ register ENVELOPE *e;
+{
+ extern void map_init();
+
+#if XDEBUG
+ checkfd012("entering initmaps");
+#endif
+ CurEnv = e;
+ if (rebuild)
+ {
+ stabapply(map_init, 1);
+ stabapply(map_init, 2);
+ }
+ else
+ {
+ stabapply(map_init, 0);
+ }
+#if XDEBUG
+ checkfd012("exiting initmaps");
+#endif
+}
+
+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, %s, %d)\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_mname == NULL ? "NULL" : map->map_mname,
+ map->map_file == NULL ? "NULL" : map->map_file,
+ rebuild);
+
+ if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
+ bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
+ {
+ if (tTd(38, 3))
+ printf("\twrong pass\n");
+ return;
+ }
+
+ /* 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 == 2)
+ {
+ rebuildaliases(map, FALSE);
+ }
+ else
+ {
+ if (map->map_class->map_open(map, O_RDONLY))
+ {
+ if (tTd(38, 4))
+ printf("\t%s:%s %s: valid\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_mname == NULL ? "NULL" :
+ map->map_mname,
+ map->map_file == NULL ? "NULL" :
+ map->map_file);
+ map->map_mflags |= MF_OPEN;
+ }
+ else
+ {
+ if (tTd(38, 4))
+ printf("\t%s:%s %s: invalid: %s\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_mname == NULL ? "NULL" :
+ map->map_mname,
+ map->map_file == NULL ? "NULL" :
+ map->map_file,
+ errstring(errno));
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ extern MAPCLASS BogusMapClass;
+
+ map->map_class = &BogusMapClass;
+ map->map_mflags |= MF_OPEN;
+ }
+ }
+ }
+}
+ /*
+** GETCANONNAME -- look up name using service switch
+**
+** Parameters:
+** host -- the host name to look up.
+** hbsize -- the size of the host buffer.
+** trymx -- if set, try MX records.
+**
+** Returns:
+** TRUE -- if the host was found.
+** FALSE -- otherwise.
+*/
+
+bool
+getcanonname(host, hbsize, trymx)
+ char *host;
+ int hbsize;
+ bool trymx;
+{
+ int nmaps;
+ int mapno;
+ bool found = FALSE;
+ bool got_tempfail = FALSE;
+ auto int stat;
+ char *maptype[MAXMAPSTACK];
+ short mapreturn[MAXMAPACTIONS];
+
+ nmaps = switch_map_find("hosts", maptype, mapreturn);
+ for (mapno = 0; mapno < nmaps; mapno++)
+ {
+ int i;
+
+ if (tTd(38, 20))
+ printf("getcanonname(%s), trying %s\n",
+ host, maptype[mapno]);
+ if (strcmp("files", maptype[mapno]) == 0)
+ {
+ extern bool text_getcanonname __P((char *, int, int *));
+
+ found = text_getcanonname(host, hbsize, &stat);
+ }
+#ifdef NIS
+ else if (strcmp("nis", maptype[mapno]) == 0)
+ {
+ extern bool nis_getcanonname __P((char *, int, int *));
+
+ found = nis_getcanonname(host, hbsize, &stat);
+ }
+#endif
+#ifdef NISPLUS
+ else if (strcmp("nisplus", maptype[mapno]) == 0)
+ {
+ extern bool nisplus_getcanonname __P((char *, int, int *));
+
+ found = nisplus_getcanonname(host, hbsize, &stat);
+ }
+#endif
+#if NAMED_BIND
+ else if (strcmp("dns", maptype[mapno]) == 0)
+ {
+ extern bool dns_getcanonname __P((char *, int, bool, int *));
+
+ found = dns_getcanonname(host, hbsize, trymx, &stat);
+ }
+#endif
+#if NETINFO
+ else if (strcmp("netinfo", maptype[mapno]) == 0)
+ {
+ extern bool ni_getcanonname __P((char *, int, int *));
+
+ found = ni_getcanonname(host, hbsize, &stat);
+ }
+#endif
+ else
+ {
+ found = FALSE;
+ stat = EX_UNAVAILABLE;
+ }
+
+ /*
+ ** Heuristic: if $m is not set, we are running during system
+ ** startup. In this case, when a name is apparently found
+ ** but has no dot, treat is as not found. This avoids
+ ** problems if /etc/hosts has no FQDN but is listed first
+ ** in the service switch.
+ */
+
+ if (found &&
+ (macvalue('m', CurEnv) != NULL || strchr(host, '.') != NULL))
+ break;
+
+ /* see if we should continue */
+ if (stat == EX_TEMPFAIL)
+ {
+ i = MA_TRYAGAIN;
+ got_tempfail = TRUE;
+ }
+ else if (stat == EX_NOTFOUND)
+ i = MA_NOTFOUND;
+ else
+ i = MA_UNAVAIL;
+ if (bitset(1 << mapno, mapreturn[i]))
+ break;
+ }
+
+ if (found)
+ {
+ char *d;
+
+ if (tTd(38, 20))
+ printf("getcanonname(%s), found\n", host);
+
+ /*
+ ** If returned name is still single token, compensate
+ ** by tagging on $m. This is because some sites set
+ ** up their DNS or NIS databases wrong.
+ */
+
+ if ((d = strchr(host, '.')) == NULL || d[1] == '\0')
+ {
+ d = macvalue('m', CurEnv);
+ if (d != NULL &&
+ hbsize > (int) (strlen(host) + strlen(d) + 1))
+ {
+ if (host[strlen(host) - 1] != '.')
+ strcat(host, ".");
+ strcat(host, d);
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+
+ if (tTd(38, 20))
+ printf("getcanonname(%s), failed, stat=%d\n", host, stat);
+
+#if NAMED_BIND
+ if (stat == EX_NOHOST && !got_tempfail)
+ h_errno = HOST_NOT_FOUND;
+ else
+ h_errno = TRY_AGAIN;
+#endif
+
+ return FALSE;
+}
+ /*
+** EXTRACT_CANONNAME -- extract canonical name from /etc/hosts entry
+**
+** Parameters:
+** name -- the name against which to match.
+** line -- the /etc/hosts line.
+** cbuf -- the location to store the result.
+**
+** Returns:
+** TRUE -- if the line matched the desired name.
+** FALSE -- otherwise.
+*/
+
+bool
+extract_canonname(name, line, cbuf)
+ char *name;
+ char *line;
+ char cbuf[];
+{
+ int i;
+ char *p;
+ bool found = FALSE;
+ extern char *get_column();
+
+ cbuf[0] = '\0';
+ if (line[0] == '#')
+ return FALSE;
+
+ for (i = 1; ; i++)
+ {
+ char nbuf[MAXNAME + 1];
+
+ p = get_column(line, i, '\0', nbuf);
+ if (p == NULL)
+ break;
+ if (cbuf[0] == '\0' ||
+ (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
+ strcpy(cbuf, p);
+ if (strcasecmp(name, p) == 0)
+ found = TRUE;
+ }
+ if (found && strchr(cbuf, '.') == NULL)
+ {
+ /* try to add a domain on the end of the name */
+ char *domain = macvalue('m', CurEnv);
+
+ if (domain != NULL &&
+ strlen(domain) + strlen(cbuf) + 1 < MAXNAME)
+ {
+ p = &cbuf[strlen(cbuf)];
+ *p++ = '.';
+ strcpy(p, domain);
+ }
+ }
+ return found;
+}
+ /*
+** NDBM modules
+*/
+
+#ifdef NDBM
+
+/*
+** DBM_MAP_OPEN -- DBM-style map open
+*/
+
+bool
+ndbm_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ register DBM *dbm;
+ struct stat st;
+ int fd;
+
+ if (tTd(38, 2))
+ printf("ndbm_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+#if LOCK_ON_OPEN
+ if (mode == O_RDONLY)
+ mode |= O_SHLOCK;
+ else
+ mode |= O_CREAT|O_TRUNC|O_EXLOCK;
+#else
+ if (mode == O_RDWR)
+ {
+# ifdef NOFTRUNCATE
+ /*
+ ** Warning: race condition. Try to lock the file as
+ ** quickly as possible after opening it.
+ */
+
+ mode |= O_CREAT|O_TRUNC;
+# else
+ /*
+ ** This ugly code opens the map without truncating it,
+ ** locks the file, then truncates it. Necessary to
+ ** avoid race conditions.
+ */
+
+ int dirfd;
+ int pagfd;
+ char dirfile[MAXNAME + 1];
+ char pagfile[MAXNAME + 1];
+
+ sprintf(dirfile, "%s.dir", map->map_file);
+ sprintf(pagfile, "%s.pag", map->map_file);
+ dirfd = open(dirfile, mode|O_CREAT, DBMMODE);
+ pagfd = open(pagfile, mode|O_CREAT, DBMMODE);
+
+ if (dirfd < 0 || pagfd < 0)
+ {
+ syserr("ndbm_map_open: cannot create database %s",
+ map->map_file);
+ close(dirfd);
+ close(pagfd);
+ return FALSE;
+ }
+ if (!lockfile(dirfd, map->map_file, ".dir", LOCK_EX))
+ syserr("ndbm_map_open: cannot lock %s.dir",
+ map->map_file);
+ if (ftruncate(dirfd, 0) < 0)
+ syserr("ndbm_map_open: cannot truncate %s.dir",
+ map->map_file);
+ if (ftruncate(pagfd, 0) < 0)
+ syserr("ndbm_map_open: cannot truncate %s.pag",
+ map->map_file);
+
+ /* we can safely unlock because others will wait for @:@ */
+ close(dirfd);
+ close(pagfd);
+# endif
+ }
+#endif
+
+ /* open the database */
+ dbm = dbm_open(map->map_file, mode, DBMMODE);
+ if (dbm == NULL)
+ {
+ if (bitset(MF_ALIAS, map->map_mflags) &&
+ aliaswait(map, ".pag", FALSE))
+ return TRUE;
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("Cannot open DBM database %s", map->map_file);
+ return FALSE;
+ }
+ map->map_db1 = (void *) dbm;
+ fd = dbm_dirfno((DBM *) map->map_db1);
+ if (mode == O_RDONLY)
+ {
+#if LOCK_ON_OPEN
+ if (fd >= 0)
+ (void) lockfile(fd, map->map_file, ".pag", LOCK_UN);
+#endif
+ if (bitset(MF_ALIAS, map->map_mflags) &&
+ !aliaswait(map, ".pag", TRUE))
+ return FALSE;
+ }
+ else
+ {
+ /* exclusive lock for duration of rebuild */
+#if !LOCK_ON_OPEN
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
+ lockfile(fd, map->map_file, ".dir", LOCK_EX))
+#endif
+ map->map_mflags |= MF_LOCKED;
+ }
+ if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
+ map->map_mtime = st.st_mtime;
+ 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;
+ int fd;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(38, 20))
+ printf("ndbm_map_lookup(%s, %s)\n",
+ map->map_mname, 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;
+ }
+ fd = dbm_dirfno((DBM *) map->map_db1);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
+ val.dptr = NULL;
+ if (bitset(MF_TRY0NULL, map->map_mflags))
+ {
+ val = dbm_fetch((DBM *) map->map_db1, key);
+ if (val.dptr != NULL)
+ map->map_mflags &= ~MF_TRY1NULL;
+ }
+ if (val.dptr == NULL && bitset(MF_TRY1NULL, map->map_mflags))
+ {
+ key.dsize++;
+ val = dbm_fetch((DBM *) map->map_db1, key);
+ if (val.dptr != NULL)
+ map->map_mflags &= ~MF_TRY0NULL;
+ }
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
+ if (val.dptr == NULL)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ 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, %s)\n",
+ map->map_mname, 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)
+ {
+ if (!bitset(MF_APPEND, map->map_mflags))
+ usrerr("050 Warning: duplicate alias name %s", lhs);
+ else
+ {
+ static char *buf = NULL;
+ static int bufsiz = 0;
+ auto int xstat;
+ datum old;
+
+ old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
+ if (old.dptr != NULL && *old.dptr != '\0')
+ {
+ old.dsize = strlen(old.dptr);
+ if (data.dsize + old.dsize + 2 > bufsiz)
+ {
+ if (buf != NULL)
+ (void) free(buf);
+ bufsiz = data.dsize + old.dsize + 2;
+ buf = xalloc(bufsiz);
+ }
+ sprintf(buf, "%s,%s", data.dptr, old.dptr);
+ data.dsize = data.dsize + old.dsize + 1;
+ data.dptr = buf;
+ if (tTd(38, 9))
+ printf("ndbm_map_store append=%s\n", data.dptr);
+ }
+ }
+ 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 (tTd(38, 9))
+ printf("ndbm_map_close(%s, %s, %x)\n",
+ map->map_mname, map->map_file, map->map_mflags);
+
+ if (bitset(MF_WRITABLE, map->map_mflags))
+ {
+#ifdef NIS
+ bool inclnull;
+ char buf[200];
+
+ inclnull = bitset(MF_INCLNULL, map->map_mflags);
+ map->map_mflags &= ~MF_INCLNULL;
+
+ if (strstr(map->map_file, "/yp/") != NULL)
+ {
+ (void) sprintf(buf, "%010ld", curtime());
+ ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
+
+ (void) gethostname(buf, sizeof buf);
+ ndbm_map_store(map, "YP_MASTER_NAME", buf);
+ }
+
+ if (inclnull)
+ map->map_mflags |= MF_INCLNULL;
+#endif
+
+ /* write out the distinguished alias */
+ ndbm_map_store(map, "@", "@");
+ }
+ dbm_close((DBM *) map->map_db1);
+}
+
+#endif
+ /*
+** 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;
+{
+ if (tTd(38, 2))
+ printf("bt_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+ return db_map_open(map, mode, DB_BTREE);
+}
+
+bool
+hash_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ if (tTd(38, 2))
+ printf("hash_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+ return db_map_open(map, mode, DB_HASH);
+}
+
+bool
+db_map_open(map, mode, dbtype)
+ MAP *map;
+ int mode;
+ DBTYPE dbtype;
+{
+ DB *db;
+ int i;
+ int omode;
+ int fd;
+ int saveerrno;
+ struct stat st;
+ char buf[MAXNAME + 1];
+
+ (void) strcpy(buf, map->map_file);
+ i = strlen(buf);
+ if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
+ (void) strcat(buf, ".db");
+
+ omode = mode;
+
+#if LOCK_ON_OPEN
+ if (mode == O_RDWR)
+ omode |= O_CREAT|O_TRUNC|O_EXLOCK;
+# if !OLD_NEWDB
+ else
+ omode |= O_SHLOCK;
+# endif
+#else
+ if (mode == O_RDWR)
+ omode |= O_CREAT;
+
+ /*
+ ** Pre-lock the file to avoid race conditions. In particular,
+ ** since dbopen returns NULL if the file is zero length, we
+ ** must have a locked instance around the dbopen.
+ */
+
+ fd = open(buf, omode, DBMMODE);
+
+ if (fd < 0)
+ {
+ syserr("db_map_open: cannot pre-open database %s",
+ buf);
+ close(fd);
+ return FALSE;
+ }
+ if (!lockfile(fd, map->map_file, ".db",
+ mode == O_RDONLY ? LOCK_SH : LOCK_EX))
+ syserr("db_map_open: cannot lock %s", buf);
+ if (mode == O_RDWR)
+ omode |= O_TRUNC;
+#endif
+
+ db = dbopen(buf, omode, DBMMODE, dbtype, NULL);
+ saveerrno = errno;
+
+#if !LOCK_ON_OPEN
+ /* we can safely unlock now because others will wait for @:@ */
+ close(fd);
+#endif
+
+ if (db == NULL)
+ {
+ if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
+ aliaswait(map, ".db", FALSE))
+ return TRUE;
+ errno = saveerrno;
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("Cannot open DB database %s", map->map_file);
+ return FALSE;
+ }
+#if !OLD_NEWDB
+ fd = db->fd(db);
+# if LOCK_ON_OPEN
+ if (fd >= 0)
+ {
+ if (mode == O_RDONLY)
+ (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
+ else
+ map->map_mflags |= MF_LOCKED;
+ }
+# else
+ if (mode == O_RDWR && fd >= 0)
+ {
+ if (lockfile(fd, map->map_file, ".db", LOCK_EX))
+ map->map_mflags |= MF_LOCKED;
+ }
+# endif
+#endif
+
+ /* try to make sure that at least the database header is on disk */
+ if (mode == O_RDWR)
+#if OLD_NEWDB
+ (void) db->sync(db);
+#else
+ (void) db->sync(db, 0);
+
+ if (fd >= 0 && fstat(fd, &st) >= 0)
+ map->map_mtime = st.st_mtime;
+#endif
+
+ map->map_db2 = (void *) db;
+ if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
+ !aliaswait(map, ".db", TRUE))
+ return FALSE;
+ 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;
+ int fd;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(38, 20))
+ printf("db_map_lookup(%s, %s)\n",
+ map->map_mname, 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 !OLD_NEWDB
+ fd = db->fd(db);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
+#endif
+ st = 1;
+ if (bitset(MF_TRY0NULL, map->map_mflags))
+ {
+ st = db->get(db, &key, &val, 0);
+ if (st == 0)
+ map->map_mflags &= ~MF_TRY1NULL;
+ }
+ if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags))
+ {
+ key.size++;
+ st = db->get(db, &key, &val, 0);
+ if (st == 0)
+ map->map_mflags &= ~MF_TRY0NULL;
+ }
+ saveerrno = errno;
+#if !OLD_NEWDB
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".db", 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))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ 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, 12))
+ printf("db_map_store(%s, %s, %s)\n",
+ map->map_mname, 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)
+ {
+ if (!bitset(MF_APPEND, map->map_mflags))
+ usrerr("050 Warning: duplicate alias name %s", lhs);
+ else
+ {
+ static char *buf = NULL;
+ static int bufsiz = 0;
+ DBT old;
+
+ old.data = db_map_lookup(map, key.data, NULL, &stat);
+ if (old.data != NULL)
+ {
+ old.size = strlen(old.data);
+ if (data.size + old.size + 2 > bufsiz)
+ {
+ if (buf != NULL)
+ (void) free(buf);
+ bufsiz = data.size + old.size + 2;
+ buf = xalloc(bufsiz);
+ }
+ sprintf(buf, "%s,%s", data.data, old.data);
+ data.size = data.size + old.size + 1;
+ data.data = buf;
+ if (tTd(38, 9))
+ printf("db_map_store append=%s\n", data.data);
+ }
+ }
+ 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, %s, %x)\n",
+ map->map_mname, 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
+ /*
+** NIS Modules
+*/
+
+# ifdef NIS
+
+# ifndef YPERR_BUSY
+# define YPERR_BUSY 16
+# endif
+
+/*
+** 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;
+
+ if (tTd(38, 2))
+ printf("nis_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (mode != O_RDONLY)
+ {
+ /* issue a pseudo-error message */
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+# ifdef EFTYPE
+ errno = EFTYPE;
+# else
+ errno = ENXIO;
+# endif
+#endif
+ return FALSE;
+ }
+
+ p = strchr(map->map_file, '@');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ if (*p != '\0')
+ map->map_domain = p;
+ }
+
+ if (*map->map_file == '\0')
+ map->map_file = "mail.aliases";
+
+ if (map->map_domain == NULL)
+ {
+ yperr = yp_get_default_domain(&map->map_domain);
+ if (yperr != 0)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("421 NIS map %s specified, but NIS not running\n",
+ map->map_file);
+ return FALSE;
+ }
+ }
+
+ /* 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)
+ {
+ /*
+ ** We ought to be calling aliaswait() here if this is an
+ ** alias file, but powerful HP-UX NIS servers apparently
+ ** don't insert the @:@ token into the alias map when it
+ ** is rebuilt, so aliaswait() just hangs. I hate HP-UX.
+ */
+
+#if 0
+ if (!bitset(MF_ALIAS, map->map_mflags) ||
+ aliaswait(map, NULL, TRUE))
+#endif
+ return TRUE;
+ }
+
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ syserr("421 Cannot bind to map %s in domain %s: %s",
+ map->map_file, 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, %s)\n",
+ map->map_mname, 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);
+ yperr = YPERR_KEY;
+ if (bitset(MF_TRY0NULL, map->map_mflags))
+ {
+ yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+ &vp, &vsize);
+ if (yperr == 0)
+ map->map_mflags &= ~MF_TRY1NULL;
+ }
+ if (yperr == YPERR_KEY && bitset(MF_TRY1NULL, map->map_mflags))
+ {
+ buflen++;
+ yperr = yp_match(map->map_domain, map->map_file, keybuf, buflen,
+ &vp, &vsize);
+ if (yperr == 0)
+ map->map_mflags &= ~MF_TRY0NULL;
+ }
+ 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))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, vp, vsize, av);
+}
+
+
+/*
+** NIS_GETCANONNAME -- look up canonical name in NIS
+*/
+
+bool
+nis_getcanonname(name, hbsize, statp)
+ char *name;
+ int hbsize;
+ int *statp;
+{
+ char *vp;
+ auto int vsize;
+ int keylen;
+ int yperr;
+ static bool try0null = TRUE;
+ static bool try1null = TRUE;
+ static char *yp_domain = NULL;
+ char host_record[MAXLINE];
+ char cbuf[MAXNAME];
+ char nbuf[MAXNAME + 1];
+
+ if (tTd(38, 20))
+ printf("nis_getcanonname(%s)\n", name);
+
+ if (strlen(name) >= sizeof nbuf)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ (void) strcpy(nbuf, name);
+ shorten_hostname(nbuf);
+ keylen = strlen(nbuf);
+
+ if (yp_domain == NULL)
+ yp_get_default_domain(&yp_domain);
+ makelower(nbuf);
+ yperr = YPERR_KEY;
+ if (try0null)
+ {
+ yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
+ &vp, &vsize);
+ if (yperr == 0)
+ try1null = FALSE;
+ }
+ if (yperr == YPERR_KEY && try1null)
+ {
+ keylen++;
+ yperr = yp_match(yp_domain, "hosts.byname", nbuf, keylen,
+ &vp, &vsize);
+ if (yperr == 0)
+ try0null = FALSE;
+ }
+ if (yperr != 0)
+ {
+ if (yperr == YPERR_KEY)
+ *statp = EX_NOHOST;
+ else if (yperr == YPERR_BUSY)
+ *statp = EX_TEMPFAIL;
+ else
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ strncpy(host_record, vp, vsize);
+ host_record[vsize] = '\0';
+ if (tTd(38, 44))
+ printf("got record `%s'\n", host_record);
+ if (!extract_canonname(nbuf, host_record, cbuf))
+ {
+ /* this should not happen, but.... */
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+ if (hbsize < strlen(cbuf))
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ strcpy(name, cbuf);
+ *statp = EX_OK;
+ return TRUE;
+}
+
+#endif
+ /*
+** NISPLUS Modules
+**
+** This code donated by Sun Microsystems.
+*/
+
+#ifdef NISPLUS
+
+#undef NIS /* symbol conflict in nis.h */
+#include <rpcsvc/nis.h>
+#include <rpcsvc/nislib.h>
+
+#define EN_col(col) zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val
+#define COL_NAME(res,i) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_val)[i].tc_name
+#define COL_MAX(res) ((res->objects.objects_val)->TA_data.ta_cols.ta_cols_len)
+#define PARTIAL_NAME(x) ((x)[strlen(x) - 1] != '.')
+
+/*
+** NISPLUS_MAP_OPEN -- open nisplus table
+*/
+
+bool
+nisplus_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ register char *p;
+ char qbuf[MAXLINE + NIS_MAXNAMELEN];
+ nis_result *res = NULL;
+ u_int objs_len;
+ nis_object *obj_ptr;
+ int retry_cnt, max_col, i;
+
+ if (tTd(38, 2))
+ printf("nisplus_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (mode != O_RDONLY)
+ {
+ errno = ENODEV;
+ return FALSE;
+ }
+
+ if (*map->map_file == '\0')
+ map->map_file = "mail_aliases.org_dir";
+
+ if (PARTIAL_NAME(map->map_file) && map->map_domain == NULL)
+ {
+ /* set default NISPLUS Domain to $m */
+ extern char *nisplus_default_domain();
+
+ map->map_domain = newstr(nisplus_default_domain());
+ if (tTd(38, 2))
+ printf("nisplus_map_open(%s): using domain %s\n",
+ map->map_file, map->map_domain);
+ }
+ if (!PARTIAL_NAME(map->map_file))
+ map->map_domain = newstr("");
+
+ /* check to see if this map actually exists */
+ if (PARTIAL_NAME(map->map_file))
+ sprintf(qbuf, "%s.%s", map->map_file, map->map_domain);
+ else
+ strcpy(qbuf, map->map_file);
+
+ retry_cnt = 0;
+ while (res == NULL || res->status != NIS_SUCCESS)
+ {
+ res = nis_lookup(qbuf, FOLLOW_LINKS);
+ switch (res->status)
+ {
+ case NIS_SUCCESS:
+ break;
+
+ case NIS_TRYAGAIN:
+ case NIS_RPCERROR:
+ case NIS_NAMEUNREACHABLE:
+ if (retry_cnt++ > 4)
+ {
+ errno = EBADR;
+ return FALSE;
+ }
+ /* try not to overwhelm hosed server */
+ sleep(2);
+ break;
+
+ default: /* all other nisplus errors */
+#if 0
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("421 Cannot find table %s.%s: %s",
+ map->map_file, map->map_domain,
+ nis_sperrno(res->status));
+#endif
+ errno = EBADR;
+ return FALSE;
+ }
+ }
+
+ if (NIS_RES_NUMOBJ(res) != 1 ||
+ (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ))
+ {
+ if (tTd(38, 10))
+ printf("nisplus_map_open: %s is not a table\n", qbuf);
+#if 0
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("421 %s.%s: %s is not a table",
+ map->map_file, map->map_domain,
+ nis_sperrno(res->status));
+#endif
+ errno = EBADR;
+ return FALSE;
+ }
+ /* default key column is column 0 */
+ if (map->map_keycolnm == NULL)
+ map->map_keycolnm = newstr(COL_NAME(res,0));
+
+ max_col = COL_MAX(res);
+
+ /* verify the key column exist */
+ for (i=0; i< max_col; i++)
+ {
+ if (!strcmp(map->map_keycolnm, COL_NAME(res,i)))
+ break;
+ }
+ if (i == max_col)
+ {
+ if (tTd(38, 2))
+ printf("nisplus_map_open(%s): can not find key column %s\n",
+ map->map_file, map->map_keycolnm);
+ errno = EBADR;
+ return FALSE;
+ }
+
+ /* default value column is the last column */
+ if (map->map_valcolnm == NULL)
+ {
+ map->map_valcolno = max_col - 1;
+ return TRUE;
+ }
+
+ for (i=0; i< max_col; i++)
+ {
+ if (strcmp(map->map_valcolnm, COL_NAME(res,i)) == 0)
+ {
+ map->map_valcolno = i;
+ return TRUE;
+ }
+ }
+
+ if (tTd(38, 2))
+ printf("nisplus_map_open(%s): can not find column %s\n",
+ map->map_file, map->map_keycolnm);
+ errno = EBADR;
+ return FALSE;
+}
+
+
+/*
+** NISPLUS_MAP_LOOKUP -- look up a datum in a NISPLUS table
+*/
+
+char *
+nisplus_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char *vp;
+ auto int vsize;
+ int buflen;
+ char search_key[MAXNAME + 1];
+ char qbuf[MAXLINE + NIS_MAXNAMELEN];
+ nis_result *result;
+
+ if (tTd(38, 20))
+ printf("nisplus_map_lookup(%s, %s)\n",
+ map->map_mname, name);
+
+ if (!bitset(MF_OPEN, map->map_mflags))
+ {
+ if (nisplus_map_open(map, O_RDONLY))
+ map->map_mflags |= MF_OPEN;
+ else
+ {
+ *statp = EX_UNAVAILABLE;
+ return NULL;
+ }
+ }
+
+ buflen = strlen(name);
+ if (buflen > sizeof search_key - 1)
+ buflen = sizeof search_key - 1;
+ bcopy(name, search_key, buflen + 1);
+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+ makelower(search_key);
+
+ /* construct the query */
+ if (PARTIAL_NAME(map->map_file))
+ sprintf(qbuf, "[%s=%s],%s.%s", map->map_keycolnm,
+ search_key, map->map_file, map->map_domain);
+ else
+ sprintf(qbuf, "[%s=%s],%s", map->map_keycolnm,
+ search_key, map->map_file);
+
+ if (tTd(38, 20))
+ printf("qbuf=%s\n", qbuf);
+ result = nis_list(qbuf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
+ if (result->status == NIS_SUCCESS)
+ {
+ int count;
+ char *str;
+
+ if ((count = NIS_RES_NUMOBJ(result)) != 1)
+ {
+ if (LogLevel > 10)
+ syslog(LOG_WARNING,
+ "%s: lookup error, expected 1 entry, got %d",
+ map->map_file, count);
+
+ /* ignore second entry */
+ if (tTd(38, 20))
+ printf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n",
+ name, count);
+ }
+
+ vp = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno));
+ /* set the length of the result */
+ if (vp == NULL)
+ vp = "";
+ vsize = strlen(vp);
+ if (tTd(38, 20))
+ printf("nisplus_map_lookup(%s), found %s\n",
+ name, vp);
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ str = map_rewrite(map, name, strlen(name), NULL);
+ else
+ str = map_rewrite(map, vp, vsize, av);
+ nis_freeresult(result);
+ *statp = EX_OK;
+ return str;
+ }
+ else
+ {
+ if (result->status == NIS_NOTFOUND)
+ *statp = EX_NOTFOUND;
+ else if (result->status == NIS_TRYAGAIN)
+ *statp = EX_TEMPFAIL;
+ else
+ {
+ *statp = EX_UNAVAILABLE;
+ map->map_mflags &= ~(MF_VALID|MF_OPEN);
+ }
+ }
+ if (tTd(38, 20))
+ printf("nisplus_map_lookup(%s), failed\n", name);
+ nis_freeresult(result);
+ return NULL;
+}
+
+
+
+/*
+** NISPLUS_GETCANONNAME -- look up canonical name in NIS+
+*/
+
+bool
+nisplus_getcanonname(name, hbsize, statp)
+ char *name;
+ int hbsize;
+ int *statp;
+{
+ char *vp;
+ auto int vsize;
+ nis_result *result;
+ char *p;
+ char nbuf[MAXNAME + 1];
+ char qbuf[MAXLINE + NIS_MAXNAMELEN];
+
+ if (strlen(name) >= sizeof nbuf)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ (void) strcpy(nbuf, name);
+ shorten_hostname(nbuf);
+
+ p = strchr(nbuf, '.');
+ if (p == NULL)
+ {
+ /* single token */
+ sprintf(qbuf, "[name=%s],hosts.org_dir", nbuf);
+ }
+ else if (p[1] != '\0')
+ {
+ /* multi token -- take only first token in nbuf */
+ *p = '\0';
+ sprintf(qbuf, "[name=%s],hosts.org_dir.%s", nbuf, &p[1]);
+ }
+ else
+ {
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+
+ if (tTd(38, 20))
+ printf("\nnisplus_getcanoname(%s), qbuf=%s\n",
+ name, qbuf);
+
+ result = nis_list(qbuf, EXPAND_NAME|FOLLOW_LINKS|FOLLOW_PATH,
+ NULL, NULL);
+
+ if (result->status == NIS_SUCCESS)
+ {
+ int count;
+ char *str;
+ char *domain;
+
+ if ((count = NIS_RES_NUMOBJ(result)) != 1)
+ {
+#ifdef LOG
+ if (LogLevel > 10)
+ syslog(LOG_WARNING,
+ "nisplus_getcanonname: lookup error, expected 1 entry, got %d",
+ count);
+#endif
+
+ /* ignore second entry */
+ if (tTd(38, 20))
+ printf("nisplus_getcanoname(%s), got %d entries, addtional entries ignores\n", name);
+ }
+
+ if (tTd(38, 20))
+ printf("nisplus_getcanoname(%s), found in directory \"%s\"\n",
+ name, (NIS_RES_OBJECT(result))->zo_domain);
+
+
+ vp = ((NIS_RES_OBJECT(result))->EN_col(0));
+ vsize = strlen(vp);
+ if (tTd(38, 20))
+ printf("nisplus_getcanonname(%s), found %s\n",
+ name, vp);
+ if (strchr(vp, '.') != NULL)
+ {
+ domain = "";
+ }
+ else
+ {
+ domain = macvalue('m', CurEnv);
+ if (domain == NULL)
+ domain = "";
+ }
+ if (hbsize > vsize + (int) strlen(domain) + 1)
+ {
+ if (domain[0] == '\0')
+ strcpy(name, vp);
+ else
+ sprintf(name, "%s.%s", vp, domain);
+ *statp = EX_OK;
+ }
+ else
+ *statp = EX_NOHOST;
+ nis_freeresult(result);
+ return TRUE;
+ }
+ else
+ {
+ if (result->status == NIS_NOTFOUND)
+ *statp = EX_NOHOST;
+ else if (result->status == NIS_TRYAGAIN)
+ *statp = EX_TEMPFAIL;
+ else
+ *statp = EX_UNAVAILABLE;
+ }
+ if (tTd(38, 20))
+ printf("nisplus_getcanonname(%s), failed, status=%d, nsw_stat=%d\n",
+ name, result->status, *statp);
+ nis_freeresult(result);
+ return FALSE;
+}
+
+
+char *
+nisplus_default_domain()
+{
+ static char default_domain[MAXNAME + 1] = "";
+ char *p;
+
+ if (default_domain[0] != '\0')
+ return(default_domain);
+
+ p = nis_local_directory();
+ strcpy(default_domain, p);
+ return default_domain;
+}
+
+#endif /* NISPLUS */
+ /*
+** HESIOD Modules
+*/
+
+#ifdef HESIOD
+
+#include <hesiod.h>
+
+bool
+hes_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ if (tTd(38, 2))
+ printf("hes_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (mode != O_RDONLY)
+ {
+ /* issue a pseudo-error message */
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+# ifdef EFTYPE
+ errno = EFTYPE;
+# else
+ errno = ENXIO;
+# endif
+#endif
+ return FALSE;
+ }
+
+ if (hes_error() == HES_ER_UNINIT)
+ hes_init();
+ switch (hes_error())
+ {
+ case HES_ER_OK:
+ case HES_ER_NOTFOUND:
+ return TRUE;
+ }
+
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("421 cannot initialize Hesiod map (%d)", hes_error());
+
+ return FALSE;
+}
+
+char *
+hes_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char **hp;
+
+ if (tTd(38, 20))
+ printf("hes_map_lookup(%s, %s)\n", map->map_file, name);
+
+ if (name[0] == '\\')
+ {
+ char *np;
+ int nl;
+ char nbuf[MAXNAME];
+
+ nl = strlen(name);
+ if (nl < sizeof nbuf - 1)
+ np = nbuf;
+ else
+ np = xalloc(strlen(name) + 2);
+ np[0] = '\\';
+ strcpy(&np[1], name);
+ hp = hes_resolve(np, map->map_file);
+ if (np != nbuf)
+ free(np);
+ }
+ else
+ {
+ hp = hes_resolve(name, map->map_file);
+ }
+ if (hp == NULL || hp[0] == NULL)
+ {
+ switch (hes_error())
+ {
+ case HES_ER_OK:
+ *statp = EX_OK;
+ break;
+
+ case HES_ER_NOTFOUND:
+ *statp = EX_NOTFOUND;
+ break;
+
+ case HES_ER_CONFIG:
+ *statp = EX_UNAVAILABLE;
+ break;
+
+ case HES_ER_NET:
+ *statp = EX_TEMPFAIL;
+ break;
+ }
+ return NULL;
+ }
+
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, hp[0], strlen(hp[0]), av);
+}
+
+#endif
+ /*
+** NeXT NETINFO Modules
+*/
+
+#if NETINFO
+
+# define NETINFO_DEFAULT_DIR "/aliases"
+# define NETINFO_DEFAULT_PROPERTY "members"
+
+extern char *ni_propval __P((char *, char *, char *, char *, int));
+
+
+/*
+** NI_MAP_OPEN -- open NetInfo Aliases
+*/
+
+bool
+ni_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ char *p;
+
+ if (tTd(38, 20))
+ printf("ni_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (*map->map_file == '\0')
+ map->map_file = NETINFO_DEFAULT_DIR;
+
+ if (map->map_valcolnm == NULL)
+ map->map_valcolnm = NETINFO_DEFAULT_PROPERTY;
+
+ if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags))
+ map->map_coldelim = ',';
+
+ return TRUE;
+}
+
+
+/*
+** NI_MAP_LOOKUP -- look up a datum in NetInfo
+*/
+
+char *
+ni_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char *res;
+ char *propval;
+
+ if (tTd(38, 20))
+ printf("ni_map_lookup(%s, %s)\n", map->map_mname, name);
+
+ propval = ni_propval(map->map_file, map->map_keycolnm, name,
+ map->map_valcolnm, map->map_coldelim);
+
+ if (propval == NULL)
+ return NULL;
+
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ res = map_rewrite(map, name, strlen(name), NULL);
+ else
+ res = map_rewrite(map, propval, strlen(propval), av);
+ free(propval);
+ return res;
+}
+
+
+bool
+ni_getcanonname(name, hbsize, statp)
+ char *name;
+ int hbsize;
+ int *statp;
+{
+ char *vptr;
+ char nbuf[MAXNAME + 1];
+
+ if (tTd(38, 20))
+ printf("ni_getcanonname(%s)\n", name);
+
+ if (strlen(name) >= sizeof nbuf)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ (void) strcpy(nbuf, name);
+ shorten_hostname(nbuf);
+
+ /* we only accept single token search key */
+ if (strchr(nbuf, '.'))
+ {
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+
+ /* Do the search */
+ vptr = ni_propval("/machines", NULL, nbuf, "name", '\0');
+
+ if (vptr == NULL)
+ {
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+
+ if (hbsize >= strlen(vptr))
+ {
+ strcpy(name, vptr);
+ *statp = EX_OK;
+ return TRUE;
+ }
+ *statp = EX_UNAVAILABLE;
+ free(vptr);
+ return FALSE;
+}
+
+
+/*
+** NI_PROPVAL -- NetInfo property value lookup routine
+**
+** Parameters:
+** keydir -- the NetInfo directory name in which to search
+** for the key.
+** keyprop -- the name of the property in which to find the
+** property we are interested. Defaults to "name".
+** keyval -- the value for which we are really searching.
+** valprop -- the property name for the value in which we
+** are interested.
+** sepchar -- if non-nil, this can be multiple-valued, and
+** we should return a string separated by this
+** character.
+**
+** Returns:
+** NULL -- if:
+** 1. the directory is not found
+** 2. the property name is not found
+** 3. the property contains multiple values
+** 4. some error occured
+** else -- the value of the lookup.
+**
+** Example:
+** To search for an alias value, use:
+** ni_propval("/aliases", "name", aliasname, "members", ',')
+**
+** Notes:
+** Caller should free the return value of ni_proval
+*/
+
+# include <netinfo/ni.h>
+
+# define LOCAL_NETINFO_DOMAIN "."
+# define PARENT_NETINFO_DOMAIN ".."
+# define MAX_NI_LEVELS 256
+
+char *
+ni_propval(keydir, keyprop, keyval, valprop, sepchar)
+ char *keydir;
+ char *keyprop;
+ char *keyval;
+ char *valprop;
+ int sepchar;
+{
+ char *propval = NULL;
+ int i;
+ int j, alen;
+ void *ni = NULL;
+ void *lastni = NULL;
+ ni_status nis;
+ ni_id nid;
+ ni_namelist ninl;
+ register char *p;
+ char keybuf[1024];
+
+ /*
+ ** Create the full key from the two parts.
+ **
+ ** Note that directory can end with, e.g., "name=" to specify
+ ** an alternate search property.
+ */
+
+ i = strlen(keydir) + strlen(keyval) + 2;
+ if (keyprop != NULL)
+ i += strlen(keyprop) + 1;
+ if (i > sizeof keybuf)
+ return NULL;
+ strcpy(keybuf, keydir);
+ strcat(keybuf, "/");
+ if (keyprop != NULL)
+ {
+ strcat(keybuf, keyprop);
+ strcat(keybuf, "=");
+ }
+ strcat(keybuf, keyval);
+
+ /*
+ ** If the passed directory and property name are found
+ ** in one of netinfo domains we need to search (starting
+ ** from the local domain moving all the way back to the
+ ** root domain) set propval to the property's value
+ ** and return it.
+ */
+
+ for (i = 0; i < MAX_NI_LEVELS; ++i)
+ {
+ if (i == 0)
+ {
+ nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
+ }
+ else
+ {
+ if (lastni != NULL)
+ ni_free(lastni);
+ lastni = ni;
+ nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
+ }
+
+ /*
+ ** Don't bother if we didn't get a handle on a
+ ** proper domain. This is not necessarily an error.
+ ** We would get a positive ni_status if, for instance
+ ** we never found the directory or property and tried
+ ** to open the parent of the root domain!
+ */
+
+ if (nis != 0)
+ break;
+
+ /*
+ ** Find the path to the server information.
+ */
+
+ if (ni_pathsearch(ni, &nid, keybuf) != 0)
+ continue;
+
+ /*
+ ** Find associated value information.
+ */
+
+ if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
+ continue;
+
+ /*
+ ** See if we have an acceptable number of values.
+ */
+
+ if (ninl.ni_namelist_len <= 0)
+ continue;
+
+ if (sepchar == '\0' && ninl.ni_namelist_len > 1)
+ {
+ ni_namelist_free(&ninl);
+ continue;
+ }
+
+ /*
+ ** Calculate number of bytes needed and build result
+ */
+
+ alen = 1;
+ for (j = 0; j < ninl.ni_namelist_len; j++)
+ alen += strlen(ninl.ni_namelist_val[j]) + 1;
+ propval = p = xalloc(alen);
+ for (j = 0; j < ninl.ni_namelist_len; j++)
+ {
+ strcpy(p, ninl.ni_namelist_val[j]);
+ p += strlen(p);
+ *p++ = sepchar;
+ }
+ *--p = '\0';
+
+ ni_namelist_free(&ninl);
+ }
+
+ /*
+ ** Clean up.
+ */
+
+ if (ni != NULL)
+ ni_free(ni);
+ if (lastni != NULL && ni != lastni)
+ ni_free(lastni);
+
+ return propval;
+}
+
+#endif
+ /*
+** TEXT (unindexed text file) Modules
+**
+** This code donated by Sun Microsystems.
+*/
+
+
+/*
+** TEXT_MAP_OPEN -- open text table
+*/
+
+bool
+text_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ struct stat sbuf;
+
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (mode != O_RDONLY)
+ {
+ errno = ENODEV;
+ return FALSE;
+ }
+
+ if (*map->map_file == '\0')
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s): file name required\n",
+ map->map_mname);
+ return FALSE;
+ }
+
+ if (map->map_file[0] != '/')
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s): file name must be fully qualified\n",
+ map->map_mname, map->map_file);
+ return FALSE;
+ }
+ /* check to see if this map actually accessable */
+ if (access(map->map_file, R_OK) <0)
+ return FALSE;
+
+ /* check to see if this map actually exist */
+ if (stat(map->map_file, &sbuf) <0)
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s): cannot stat\n",
+ map->map_mname, map->map_file);
+ return FALSE;
+ }
+
+ if (!S_ISREG(sbuf.st_mode))
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s): %s is not a regular file\n",
+ map->map_mname, map->map_file);
+ return FALSE;
+ }
+
+ if (map->map_keycolnm == NULL)
+ map->map_keycolno = 0;
+ else
+ {
+ if (!isdigit(*map->map_keycolnm))
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s): -k should specify a number, not %s\n",
+ map->map_mname, map->map_file,
+ map->map_keycolnm);
+ return FALSE;
+ }
+ map->map_keycolno = atoi(map->map_keycolnm);
+ }
+
+ if (map->map_valcolnm == NULL)
+ map->map_valcolno = 0;
+ else
+ {
+ if (!isdigit(*map->map_valcolnm))
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s): -v should specify a number, not %s\n",
+ map->map_mname, map->map_file,
+ map->map_valcolnm);
+ return FALSE;
+ }
+ map->map_valcolno = atoi(map->map_valcolnm);
+ }
+
+ if (tTd(38, 2))
+ {
+ printf("text_map_open(%s, %s): delimiter = ",
+ map->map_mname, map->map_file);
+ if (map->map_coldelim == '\0')
+ printf("(white space)\n");
+ else
+ printf("%c\n", map->map_coldelim);
+ }
+
+ return TRUE;
+}
+
+
+/*
+** TEXT_MAP_LOOKUP -- look up a datum in a TEXT table
+*/
+
+char *
+text_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char *vp;
+ auto int vsize;
+ int buflen;
+ char search_key[MAXNAME + 1];
+ char linebuf[MAXLINE];
+ FILE *f;
+ char buf[MAXNAME + 1];
+ char delim;
+ int key_idx;
+ bool found_it;
+ extern char *get_column();
+
+
+ found_it = FALSE;
+ if (tTd(38, 20))
+ printf("text_map_lookup(%s, %s)\n", map->map_mname, name);
+
+ buflen = strlen(name);
+ if (buflen > sizeof search_key - 1)
+ buflen = sizeof search_key - 1;
+ bcopy(name, search_key, buflen + 1);
+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+ makelower(search_key);
+
+ f = fopen(map->map_file, "r");
+ if (f == NULL)
+ {
+ map->map_mflags &= ~(MF_VALID|MF_OPEN);
+ *statp = EX_UNAVAILABLE;
+ return NULL;
+ }
+ key_idx = map->map_keycolno;
+ delim = map->map_coldelim;
+ while (fgets(linebuf, MAXLINE, f) != NULL)
+ {
+ char *p;
+
+ /* skip comment line */
+ if (linebuf[0] == '#')
+ continue;
+ p = strchr(linebuf, '\n');
+ if (p != NULL)
+ *p = '\0';
+ p = get_column(linebuf, key_idx, delim, buf);
+ if (p != NULL && strcasecmp(search_key, p) == 0)
+ {
+ found_it = TRUE;
+ break;
+ }
+ }
+ fclose(f);
+ if (!found_it)
+ {
+ *statp = EX_NOTFOUND;
+ return NULL;
+ }
+ vp = get_column(linebuf, map->map_valcolno, delim, buf);
+ vsize = strlen(vp);
+ *statp = EX_OK;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, vp, vsize, av);
+}
+
+
+/*
+** TEXT_GETCANONNAME -- look up canonical name in hosts file
+*/
+
+bool
+text_getcanonname(name, hbsize, statp)
+ char *name;
+ int hbsize;
+ int *statp;
+{
+ int key_idx;
+ bool found;
+ FILE *f;
+ char linebuf[MAXLINE];
+ char cbuf[MAXNAME + 1];
+ char fbuf[MAXNAME + 1];
+ char nbuf[MAXNAME + 1];
+ extern char *get_column();
+
+ if (tTd(38, 20))
+ printf("text_getcanonname(%s)\n", name);
+
+ if (strlen(name) >= sizeof nbuf)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ (void) strcpy(nbuf, name);
+ shorten_hostname(nbuf);
+
+ f = fopen(HostsFile, "r");
+ if (f == NULL)
+ {
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+ }
+ found = FALSE;
+ while (!found && fgets(linebuf, MAXLINE, f) != NULL)
+ {
+ char *p = strpbrk(linebuf, "#\n");
+
+ if (p != NULL)
+ *p = '\0';
+ if (linebuf[0] != '\0')
+ found = extract_canonname(nbuf, linebuf, cbuf);
+ }
+ fclose(f);
+ if (!found)
+ {
+ *statp = EX_NOHOST;
+ return FALSE;
+ }
+
+ if (hbsize >= strlen(cbuf))
+ {
+ strcpy(name, cbuf);
+ *statp = EX_OK;
+ return TRUE;
+ }
+ *statp = EX_UNAVAILABLE;
+ return FALSE;
+}
+ /*
+** 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, %s)\n",
+ map->map_mname, 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;
+{
+ FILE *af;
+ struct stat st;
+
+ if (tTd(38, 2))
+ printf("stab_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ if (mode != O_RDONLY)
+ {
+ errno = ENODEV;
+ return FALSE;
+ }
+
+ af = fopen(map->map_file, "r");
+ if (af == NULL)
+ return FALSE;
+ readaliases(map, af, FALSE, FALSE);
+
+ if (fstat(fileno(af), &st) >= 0)
+ map->map_mtime = st.st_mtime;
+ fclose(af);
+
+ return TRUE;
+}
+ /*
+** 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, %s)\n",
+ map->map_mname, 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;
+{
+ if (tTd(38, 12))
+ printf("impl_map_store(%s, %s, %s)\n",
+ map->map_mname, lhs, 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;
+{
+ if (tTd(38, 2))
+ printf("impl_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+#ifdef NEWDB
+ map->map_mflags |= MF_IMPL_HASH;
+ if (hash_map_open(map, mode))
+ {
+#if defined(NDBM) && defined(NIS)
+ if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
+#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);
+#else
+ if (mode != O_RDONLY)
+ usrerr("Cannot rebuild aliases: no database format defined");
+#endif
+
+ return stab_map_open(map, mode);
+}
+
+
+/*
+** IMPL_MAP_CLOSE -- close any open database(s)
+*/
+
+void
+impl_map_close(map)
+ MAP *map;
+{
+ if (tTd(38, 9))
+ printf("impl_map_close(%s, %s, %x)\n",
+ map->map_mname, map->map_file, map->map_mflags);
+#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
+}
+ /*
+** User map class.
+**
+** Provides access to the system password file.
+*/
+
+/*
+** USER_MAP_OPEN -- open user map
+**
+** Really just binds field names to field numbers.
+*/
+
+bool
+user_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ if (tTd(38, 2))
+ printf("user_map_open(%s, %d)\n",
+ map->map_mname, mode);
+
+ if (mode != O_RDONLY)
+ {
+ /* issue a pseudo-error message */
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+# ifdef EFTYPE
+ errno = EFTYPE;
+# else
+ errno = ENXIO;
+# endif
+#endif
+ return FALSE;
+ }
+ if (map->map_valcolnm == NULL)
+ /* nothing */ ;
+ else if (strcasecmp(map->map_valcolnm, "name") == 0)
+ map->map_valcolno = 1;
+ else if (strcasecmp(map->map_valcolnm, "passwd") == 0)
+ map->map_valcolno = 2;
+ else if (strcasecmp(map->map_valcolnm, "uid") == 0)
+ map->map_valcolno = 3;
+ else if (strcasecmp(map->map_valcolnm, "gid") == 0)
+ map->map_valcolno = 4;
+ else if (strcasecmp(map->map_valcolnm, "gecos") == 0)
+ map->map_valcolno = 5;
+ else if (strcasecmp(map->map_valcolnm, "dir") == 0)
+ map->map_valcolno = 6;
+ else if (strcasecmp(map->map_valcolnm, "shell") == 0)
+ map->map_valcolno = 7;
+ else
+ {
+ syserr("User map %s: unknown column name %s",
+ map->map_mname, map->map_valcolnm);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*
+** USER_MAP_LOOKUP -- look up a user in the passwd file.
+*/
+
+char *
+user_map_lookup(map, key, av, statp)
+ MAP *map;
+ char *key;
+ char **av;
+ int *statp;
+{
+ struct passwd *pw;
+
+ if (tTd(38, 20))
+ printf("user_map_lookup(%s, %s)\n",
+ map->map_mname, key);
+
+ pw = sm_getpwnam(key);
+ if (pw == NULL)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, key, strlen(key), NULL);
+ else
+ {
+ char *rwval = NULL;
+ char buf[30];
+
+ switch (map->map_valcolno)
+ {
+ case 0:
+ case 1:
+ rwval = pw->pw_name;
+ break;
+
+ case 2:
+ rwval = pw->pw_passwd;
+ break;
+
+ case 3:
+ sprintf(buf, "%d", pw->pw_uid);
+ rwval = buf;
+ break;
+
+ case 4:
+ sprintf(buf, "%d", pw->pw_gid);
+ rwval = buf;
+ break;
+
+ case 5:
+ rwval = pw->pw_gecos;
+ break;
+
+ case 6:
+ rwval = pw->pw_dir;
+ break;
+
+ case 7:
+ rwval = pw->pw_shell;
+ break;
+ }
+ return map_rewrite(map, rwval, strlen(rwval), av);
+ }
+}
+ /*
+** Program map type.
+**
+** This provides access to arbitrary programs. It should be used
+** only very sparingly, since there is no way to bound the cost
+** of invoking an arbitrary program.
+*/
+
+char *
+prog_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ int i;
+ register char *p;
+ int fd;
+ auto pid_t pid;
+ char *rval;
+ int stat;
+ char *argv[MAXPV + 1];
+ char buf[MAXLINE];
+
+ if (tTd(38, 20))
+ printf("prog_map_lookup(%s, %s) %s\n",
+ map->map_mname, name, map->map_file);
+
+ i = 0;
+ argv[i++] = map->map_file;
+ if (map->map_rebuild != NULL)
+ {
+ strcpy(buf, map->map_rebuild);
+ for (p = strtok(buf, " \t"); p != NULL; p = strtok(NULL, " \t"))
+ {
+ if (i >= MAXPV - 1)
+ break;
+ argv[i++] = p;
+ }
+ }
+ argv[i++] = name;
+ argv[i] = NULL;
+ if (tTd(38, 21))
+ {
+ printf("prog_open:");
+ for (i = 0; argv[i] != NULL; i++)
+ printf(" %s", argv[i]);
+ printf("\n");
+ }
+ pid = prog_open(argv, &fd, CurEnv);
+ if (pid < 0)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("prog_map_lookup(%s) failed (%s) -- closing",
+ map->map_mname, errstring(errno));
+ else if (tTd(38, 9))
+ printf("prog_map_lookup(%s) failed (%s) -- closing",
+ map->map_mname, errstring(errno));
+ map->map_mflags &= ~(MF_VALID|MF_OPEN);
+ *statp = EX_OSFILE;
+ return NULL;
+ }
+ i = read(fd, buf, sizeof buf - 1);
+ if (i < 0)
+ {
+ syserr("prog_map_lookup(%s): read error %s\n",
+ map->map_mname, errstring(errno));
+ rval = NULL;
+ }
+ else if (i == 0 && tTd(38, 20))
+ {
+ printf("prog_map_lookup(%s): empty answer\n",
+ map->map_mname);
+ rval = NULL;
+ }
+ if (i > 0)
+ {
+ buf[i] = '\0';
+ p = strchr(buf, '\n');
+ if (p != NULL)
+ *p = '\0';
+
+ /* collect the return value */
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ rval = map_rewrite(map, name, strlen(name), NULL);
+ else
+ rval = map_rewrite(map, buf, strlen(buf), NULL);
+
+ /* now flush any additional output */
+ while ((i = read(fd, buf, sizeof buf)) > 0)
+ continue;
+ }
+
+ /* wait for the process to terminate */
+ close(fd);
+ stat = waitfor(pid);
+
+ if (stat == -1)
+ {
+ syserr("prog_map_lookup(%s): wait error %s\n",
+ map->map_mname, errstring(errno));
+ *statp = EX_SOFTWARE;
+ rval = NULL;
+ }
+ else if (WIFEXITED(stat))
+ {
+ if ((*statp = WEXITSTATUS(stat)) != EX_OK)
+ rval = NULL;
+ }
+ else
+ {
+ syserr("prog_map_lookup(%s): child died on signal %d",
+ map->map_mname, stat);
+ *statp = EX_UNAVAILABLE;
+ rval = NULL;
+ }
+ return rval;
+}
+ /*
+** Sequenced map type.
+**
+** Tries each map in order until something matches, much like
+** implicit. Stores go to the first map in the list that can
+** support storing.
+**
+** This is slightly unusual in that there are two interfaces.
+** The "sequence" interface lets you stack maps arbitrarily.
+** The "switch" interface builds a sequence map by looking
+** at a system-dependent configuration file such as
+** /etc/nsswitch.conf on Solaris or /etc/svc.conf on Ultrix.
+**
+** We don't need an explicit open, since all maps are
+** opened during startup, including underlying maps.
+*/
+
+/*
+** SEQ_MAP_PARSE -- Sequenced map parsing
+*/
+
+bool
+seq_map_parse(map, ap)
+ MAP *map;
+ char *ap;
+{
+ int maxmap;
+
+ if (tTd(38, 2))
+ printf("seq_map_parse(%s, %s)\n", map->map_mname, ap);
+ maxmap = 0;
+ while (*ap != '\0')
+ {
+ register char *p;
+ STAB *s;
+
+ /* find beginning of map name */
+ while (isascii(*ap) && isspace(*ap))
+ ap++;
+ for (p = ap; isascii(*p) && isalnum(*p); p++)
+ continue;
+ if (*p != '\0')
+ *p++ = '\0';
+ while (*p != '\0' && (!isascii(*p) || !isalnum(*p)))
+ p++;
+ if (*ap == '\0')
+ {
+ ap = p;
+ continue;
+ }
+ s = stab(ap, ST_MAP, ST_FIND);
+ if (s == NULL)
+ {
+ syserr("Sequence map %s: unknown member map %s",
+ map->map_mname, ap);
+ }
+ else if (maxmap == MAXMAPSTACK)
+ {
+ syserr("Sequence map %s: too many member maps (%d max)",
+ map->map_mname, MAXMAPSTACK);
+ maxmap++;
+ }
+ else if (maxmap < MAXMAPSTACK)
+ {
+ map->map_stack[maxmap++] = &s->s_map;
+ }
+ ap = p;
+ }
+ return TRUE;
+}
+
+
+/*
+** SWITCH_MAP_OPEN -- open a switched map
+**
+** This looks at the system-dependent configuration and builds
+** a sequence map that does the same thing.
+**
+** Every system must define a switch_map_find routine in conf.c
+** that will return the list of service types associated with a
+** given service class.
+*/
+
+bool
+switch_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ int mapno;
+ int nmaps;
+ char *maptype[MAXMAPSTACK];
+
+ if (tTd(38, 2))
+ printf("switch_map_open(%s, %s, %d)\n",
+ map->map_mname, map->map_file, mode);
+
+ nmaps = switch_map_find(map->map_file, maptype, map->map_return);
+ if (tTd(38, 19))
+ {
+ printf("\tswitch_map_find => %d\n", nmaps);
+ for (mapno = 0; mapno < nmaps; mapno++)
+ printf("\t\t%s\n", maptype[mapno]);
+ }
+ if (nmaps <= 0 || nmaps > MAXMAPSTACK)
+ return FALSE;
+
+ for (mapno = 0; mapno < nmaps; mapno++)
+ {
+ register STAB *s;
+ char nbuf[MAXNAME + 1];
+
+ if (maptype[mapno] == NULL)
+ continue;
+ (void) sprintf(nbuf, "%s.%s", map->map_mname, maptype[mapno]);
+ s = stab(nbuf, ST_MAP, ST_FIND);
+ if (s == NULL)
+ {
+ syserr("Switch map %s: unknown member map %s",
+ map->map_mname, nbuf);
+ }
+ else
+ {
+ map->map_stack[mapno] = &s->s_map;
+ if (tTd(38, 4))
+ printf("\tmap_stack[%d] = %s:%s\n",
+ mapno, s->s_map.map_class->map_cname,
+ nbuf);
+ }
+ }
+ return TRUE;
+}
+
+
+/*
+** SEQ_MAP_CLOSE -- close all underlying maps
+*/
+
+void
+seq_map_close(map)
+ MAP *map;
+{
+ int mapno;
+
+ if (tTd(38, 9))
+ printf("seq_map_close(%s)\n", map->map_mname);
+
+ for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
+ {
+ MAP *mm = map->map_stack[mapno];
+
+ if (mm == NULL || !bitset(MF_OPEN, mm->map_mflags))
+ continue;
+ mm->map_class->map_close(mm);
+ mm->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
+ }
+}
+
+
+/*
+** SEQ_MAP_LOOKUP -- sequenced map lookup
+*/
+
+char *
+seq_map_lookup(map, key, args, pstat)
+ MAP *map;
+ char *key;
+ char **args;
+ int *pstat;
+{
+ int mapno;
+ int mapbit = 0x01;
+ bool tempfail = FALSE;
+
+ if (tTd(38, 20))
+ printf("seq_map_lookup(%s, %s)\n", map->map_mname, key);
+
+ for (mapno = 0; mapno < MAXMAPSTACK; mapbit <<= 1, mapno++)
+ {
+ MAP *mm = map->map_stack[mapno];
+ char *rv;
+
+ if (mm == NULL)
+ continue;
+ if (!bitset(MF_OPEN, mm->map_mflags))
+ {
+ if (bitset(mapbit, map->map_return[MA_UNAVAIL]))
+ {
+ *pstat = EX_UNAVAILABLE;
+ return NULL;
+ }
+ continue;
+ }
+ *pstat = EX_OK;
+ rv = mm->map_class->map_lookup(mm, key, args, pstat);
+ if (rv != NULL)
+ return rv;
+ if (*pstat == EX_TEMPFAIL)
+ {
+ if (bitset(mapbit, map->map_return[MA_TRYAGAIN]))
+ return NULL;
+ tempfail = TRUE;
+ }
+ else if (bitset(mapbit, map->map_return[MA_NOTFOUND]))
+ break;
+ }
+ if (tempfail)
+ *pstat = EX_TEMPFAIL;
+ else if (*pstat == EX_OK)
+ *pstat = EX_NOTFOUND;
+ return NULL;
+}
+
+
+/*
+** SEQ_MAP_STORE -- sequenced map store
+*/
+
+void
+seq_map_store(map, key, val)
+ MAP *map;
+ char *key;
+ char *val;
+{
+ int mapno;
+
+ if (tTd(38, 12))
+ printf("seq_map_store(%s, %s, %s)\n",
+ map->map_mname, key, val);
+
+ for (mapno = 0; mapno < MAXMAPSTACK; mapno++)
+ {
+ MAP *mm = map->map_stack[mapno];
+
+ if (mm == NULL || !bitset(MF_WRITABLE, mm->map_mflags))
+ continue;
+
+ mm->map_class->map_store(mm, key, val);
+ return;
+ }
+ syserr("seq_map_store(%s, %s, %s): no writable map",
+ map->map_mname, key, val);
+}
+ /*
+** NULL stubs
+*/
+
+bool
+null_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ return TRUE;
+}
+
+void
+null_map_close(map)
+ MAP *map;
+{
+ return;
+}
+
+char *
+null_map_lookup(map, key, args, pstat)
+ MAP *map;
+ char *key;
+ char **args;
+ int *pstat;
+{
+ *pstat = EX_NOTFOUND;
+ return NULL;
+}
+
+void
+null_map_store(map, key, val)
+ MAP *map;
+ char *key;
+ char *val;
+{
+ return;
+}
+
+
+/*
+** BOGUS stubs
+*/
+
+char *
+bogus_map_lookup(map, key, args, pstat)
+ MAP *map;
+ char *key;
+ char **args;
+ int *pstat;
+{
+ *pstat = EX_TEMPFAIL;
+ return NULL;
+}
+
+MAPCLASS BogusMapClass =
+{
+ "bogus-map", NULL, 0,
+ NULL, bogus_map_lookup, null_map_store,
+ null_map_open, null_map_close,
+};
diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c
new file mode 100644
index 000000000000..ee0da2d1f324
--- /dev/null
+++ b/usr.sbin/sendmail/src/mci.c
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 1995 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.22 (Berkeley) 11/18/95";
+#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 */
+
+extern void mci_uncache __P((MCI **, bool));
+ /*
+** 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.
+*/
+
+void
+mci_cache(mci)
+ register MCI *mci;
+{
+ register MCI **mcislot;
+ extern MCI **mci_scan();
+
+ /*
+ ** Find the best slot. This may cause expired connections
+ ** to be closed.
+ */
+
+ mcislot = mci_scan(mci);
+ if (mcislot == NULL)
+ {
+ /* we don't support caching */
+ return;
+ }
+
+ /* 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);
+
+ if (tTd(42, 5))
+ printf("mci_cache: caching %x (%s) in slot %d\n",
+ mci, mci->mci_host, mcislot - MciCache);
+#ifdef LOG
+ if (tTd(91, 100))
+ syslog(LOG_DEBUG, "%s: mci_cache: caching %x (%.100s) in slot %d",
+ CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ mci, mci->mci_host, mcislot - MciCache);
+#endif
+
+ *mcislot = mci;
+ mci->mci_flags |= MCIF_CACHED;
+}
+ /*
+** 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 (MaxMciCache <= 0)
+ {
+ /* we don't support caching */
+ return NULL;
+ }
+
+ 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;
+}
+ /*
+** 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.
+*/
+
+void
+mci_uncache(mcislot, doquit)
+ register MCI **mcislot;
+ bool doquit;
+{
+ register MCI *mci;
+ extern ENVELOPE BlankEnvelope;
+
+ mci = *mcislot;
+ if (mci == NULL)
+ return;
+ *mcislot = NULL;
+
+ if (tTd(42, 5))
+ printf("mci_uncache: uncaching %x (%s) from slot %d (%d)\n",
+ mci, mci->mci_host, mcislot - MciCache, doquit);
+#ifdef LOG
+ if (tTd(91, 100))
+ syslog(LOG_DEBUG, "%s: mci_uncache: uncaching %x (%.100s) from slot %d (%d)",
+ CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ mci, mci->mci_host, mcislot - MciCache, doquit);
+#endif
+
+#ifdef SMTP
+ 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
+#endif
+ {
+ 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;
+ }
+}
+ /*
+** 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.
+*/
+
+void
+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);
+}
+ /*
+** MCI_GET -- get information about a particular host
+*/
+
+MCI *
+mci_get(host, m)
+ char *host;
+ MAILER *m;
+{
+ register MCI *mci;
+ register STAB *s;
+ extern MCI **mci_scan();
+
+#ifdef DAEMON
+ extern SOCKADDR CurHostAddr;
+
+ /* clear CurHostAddr so we don't get a bogus address with this name */
+ bzero(&CurHostAddr, sizeof CurHostAddr);
+#endif
+
+ /* clear out any expired connections */
+ (void) mci_scan(NULL);
+
+ if (m->m_mno < 0)
+ syserr("negative mno %d (%s)", m->m_mno, m->m_name);
+ 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);
+ }
+
+#ifdef SMTP
+ 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;
+ }
+# ifdef DAEMON
+ else
+ {
+ /* get peer host address for logging reasons only */
+ /* (this should really be in the mci struct) */
+ int socksize = sizeof CurHostAddr;
+
+ (void) getpeername(fileno(mci->mci_in),
+ (struct sockaddr *) &CurHostAddr, &socksize);
+ }
+# endif
+ }
+#endif
+#ifdef MAYBE_NEXT_RELEASE
+ if (mci->mci_state == MCIS_CLOSED)
+ {
+ time_t now = curtime();
+
+ /* if this info is stale, ignore it */
+ if (now > mci->mci_lastuse + MciInfoTimeout)
+ {
+ mci->mci_lastuse = now;
+ mci->mci_errno = 0;
+ mci->mci_exitstat = EX_OK;
+ }
+ }
+#endif
+
+ return mci;
+}
+ /*
+** MCI_DUMP -- dump the contents of an MCI structure.
+**
+** Parameters:
+** mci -- the MCI structure to dump.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+void
+mci_dump(mci, logit)
+ register MCI *mci;
+ bool logit;
+{
+ register char *p;
+ char *sep;
+ char buf[4000];
+ extern char *ctime();
+
+ sep = logit ? " " : "\n\t";
+ p = buf;
+ sprintf(p, "MCI@%x: ", mci);
+ p += strlen(p);
+ if (mci == NULL)
+ {
+ sprintf(p, "NULL");
+ goto printit;
+ }
+ sprintf(p, "flags=%x, errno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
+ mci->mci_flags, mci->mci_errno, mci->mci_herrno,
+ mci->mci_exitstat, mci->mci_state, mci->mci_pid, sep);
+ p += strlen(p);
+ sprintf(p, "maxsize=%ld, phase=%s, mailer=%s,%s",
+ mci->mci_maxsize,
+ mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
+ mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name,
+ sep);
+ p += strlen(p);
+ sprintf(p, "host=%s, lastuse=%s",
+ mci->mci_host == NULL ? "NULL" : mci->mci_host,
+ ctime(&mci->mci_lastuse));
+printit:
+#ifdef LOG
+ if (logit)
+ syslog(LOG_DEBUG, "%.1000s", buf);
+ else
+#endif
+ printf("%s\n", buf);
+}
+ /*
+** MCI_DUMP_ALL -- print the entire MCI cache
+**
+** Parameters:
+** logit -- if set, log the result instead of printing
+** to stdout.
+**
+** Returns:
+** none.
+*/
+
+void
+mci_dump_all(logit)
+ bool logit;
+{
+ register int i;
+
+ if (MciCache == NULL)
+ return;
+
+ for (i = 0; i < MaxMciCache; i++)
+ mci_dump(MciCache[i], logit);
+}
diff --git a/usr.sbin/sendmail/src/mime.c b/usr.sbin/sendmail/src/mime.c
new file mode 100644
index 000000000000..acbc04ca617f
--- /dev/null
+++ b/usr.sbin/sendmail/src/mime.c
@@ -0,0 +1,866 @@
+/*
+ * Copyright (c) 1994 Eric P. Allman
+ * Copyright (c) 1994
+ * 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"
+# include <string.h>
+
+#ifndef lint
+static char sccsid[] = "@(#)mime.c 8.30 (Berkeley) 10/31/95";
+#endif /* not lint */
+
+/*
+** MIME support.
+**
+** I am indebted to John Beck of Hewlett-Packard, who contributed
+** his code to me for inclusion. As it turns out, I did not use
+** his code since he used a "minimum change" approach that used
+** several temp files, and I wanted a "minimum impact" approach
+** that would avoid copying. However, looking over his code
+** helped me cement my understanding of the problem.
+**
+** I also looked at, but did not directly use, Nathaniel
+** Borenstein's "code.c" module. Again, it functioned as
+** a file-to-file translator, which did not fit within my
+** design bounds, but it was a useful base for understanding
+** the problem.
+*/
+
+#if MIME8TO7
+
+/* character set for hex and base64 encoding */
+char Base16Code[] = "0123456789ABCDEF";
+char Base64Code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* types of MIME boundaries */
+#define MBT_SYNTAX 0 /* syntax error */
+#define MBT_NOTSEP 1 /* not a boundary */
+#define MBT_INTERMED 2 /* intermediate boundary (no trailing --) */
+#define MBT_FINAL 3 /* final boundary (trailing -- included) */
+
+static char *MimeBoundaryNames[] =
+{
+ "SYNTAX", "NOTSEP", "INTERMED", "FINAL"
+};
+ /*
+** MIME8TO7 -- output 8 bit body in 7 bit format
+**
+** The header has already been output -- this has to do the
+** 8 to 7 bit conversion. It would be easy if we didn't have
+** to deal with nested formats (multipart/xxx and message/rfc822).
+**
+** We won't be called if we don't have to do a conversion, and
+** appropriate MIME-Version: and Content-Type: fields have been
+** output. Any Content-Transfer-Encoding: field has not been
+** output, and we can add it here.
+**
+** Parameters:
+** mci -- mailer connection information.
+** header -- the header for this body part.
+** e -- envelope.
+** boundaries -- the currently pending message boundaries.
+** NULL if we are processing the outer portion.
+** flags -- to tweak processing.
+**
+** Returns:
+** An indicator of what terminated the message part:
+** MBT_FINAL -- the final boundary
+** MBT_INTERMED -- an intermediate boundary
+** MBT_NOTSEP -- an end of file
+*/
+
+struct args
+{
+ char *field; /* name of field */
+ char *value; /* value of that field */
+};
+
+int
+mime8to7(mci, header, e, boundaries, flags)
+ register MCI *mci;
+ HDR *header;
+ register ENVELOPE *e;
+ char **boundaries;
+ int flags;
+{
+ register char *p;
+ int linelen;
+ int bt;
+ off_t offset;
+ size_t sectionsize, sectionhighbits;
+ int i;
+ char *type;
+ char *subtype;
+ char *cte;
+ char **pvp;
+ int argc = 0;
+ char *bp;
+ struct args argv[MAXMIMEARGS];
+ char bbuf[128];
+ char buf[MAXLINE];
+ char pvpbuf[MAXLINE];
+ extern u_char MimeTokenTab[256];
+
+ if (tTd(43, 1))
+ {
+ printf("mime8to7: flags = %x, boundaries =", flags);
+ if (boundaries[0] == NULL)
+ printf(" <none>");
+ else
+ {
+ for (i = 0; boundaries[i] != NULL; i++)
+ printf(" %s", boundaries[i]);
+ }
+ printf("\n");
+ }
+ p = hvalue("Content-Transfer-Encoding", header);
+ if (p == NULL ||
+ (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ MimeTokenTab)) == NULL ||
+ pvp[0] == NULL)
+ {
+ cte = NULL;
+ }
+ else
+ {
+ cataddr(pvp, NULL, buf, sizeof buf, '\0');
+ cte = newstr(buf);
+ }
+
+ type = subtype = NULL;
+ p = hvalue("Content-Type", header);
+ if (p == NULL)
+ {
+ if (bitset(M87F_DIGEST, flags))
+ p = "message/rfc822";
+ else
+ p = "text/plain";
+ }
+ if (p != NULL &&
+ (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
+ MimeTokenTab)) != NULL &&
+ pvp[0] != NULL)
+ {
+ if (tTd(43, 40))
+ {
+ for (i = 0; pvp[i] != NULL; i++)
+ printf("pvp[%d] = \"%s\"\n", i, pvp[i]);
+ }
+ type = *pvp++;
+ if (*pvp != NULL && strcmp(*pvp, "/") == 0 &&
+ *++pvp != NULL)
+ {
+ subtype = *pvp++;
+ }
+
+ /* break out parameters */
+ while (*pvp != NULL && argc < MAXMIMEARGS)
+ {
+ /* skip to semicolon separator */
+ while (*pvp != NULL && strcmp(*pvp, ";") != 0)
+ pvp++;
+ if (*pvp++ == NULL || *pvp == NULL)
+ break;
+
+ /* extract field name */
+ argv[argc].field = *pvp++;
+
+ /* see if there is a value */
+ if (*pvp != NULL && strcmp(*pvp, "=") == 0 &&
+ (*++pvp == NULL || strcmp(*pvp, ";") != 0))
+ {
+ argv[argc].value = *pvp;
+ argc++;
+ }
+ }
+ }
+
+ /* check for disaster cases */
+ if (type == NULL)
+ type = "-none-";
+ if (subtype == NULL)
+ subtype = "-none-";
+
+ /* don't propogate some flags more than one level into the message */
+ flags &= ~M87F_DIGEST;
+
+ /*
+ ** Check for cases that can not be encoded.
+ **
+ ** For example, you can't encode certain kinds of types
+ ** or already-encoded messages. If we find this case,
+ ** just copy it through.
+ */
+
+ sprintf(buf, "%.100s/%.100s", type, subtype);
+ if (wordinclass(buf, 'n') || (cte != NULL && !wordinclass(cte, 'e')))
+ flags |= M87F_NO8BIT;
+
+ /*
+ ** Multipart requires special processing.
+ **
+ ** Do a recursive descent into the message.
+ */
+
+ if (strcasecmp(type, "multipart") == 0 && !bitset(M87F_NO8BIT, flags))
+ {
+ int blen;
+
+ if (strcasecmp(subtype, "digest") == 0)
+ flags |= M87F_DIGEST;
+
+ for (i = 0; i < argc; i++)
+ {
+ if (strcasecmp(argv[i].field, "boundary") == 0)
+ break;
+ }
+ if (i >= argc)
+ {
+ syserr("mime8to7: Content-Type: %s missing boundary", p);
+ p = "---";
+ }
+ else
+ {
+ p = argv[i].value;
+ stripquotes(p);
+ }
+ blen = strlen(p);
+ if (blen > sizeof bbuf - 1)
+ {
+ syserr("mime8to7: multipart boundary \"%s\" too long",
+ p);
+ blen = sizeof bbuf - 1;
+ }
+ strncpy(bbuf, p, blen);
+ bbuf[blen] = '\0';
+ if (tTd(43, 1))
+ printf("mime8to7: multipart boundary \"%s\"\n", bbuf);
+ for (i = 0; i < MAXMIMENESTING; i++)
+ if (boundaries[i] == NULL)
+ break;
+ if (i >= MAXMIMENESTING)
+ syserr("mime8to7: multipart nesting boundary too deep");
+ else
+ {
+ boundaries[i] = bbuf;
+ boundaries[i + 1] = NULL;
+ }
+ mci->mci_flags |= MCIF_INMIME;
+
+ /* skip the early "comment" prologue */
+ putline("", mci);
+ while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ {
+ bt = mimeboundary(buf, boundaries);
+ if (bt != MBT_NOTSEP)
+ break;
+ putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
+ if (tTd(43, 99))
+ printf(" ...%s", buf);
+ }
+ if (feof(e->e_dfp))
+ bt = MBT_FINAL;
+ while (bt != MBT_FINAL)
+ {
+ auto HDR *hdr = NULL;
+
+ sprintf(buf, "--%s", bbuf);
+ putline(buf, mci);
+ if (tTd(43, 35))
+ printf(" ...%s\n", buf);
+ collect(e->e_dfp, FALSE, FALSE, &hdr, e);
+ if (tTd(43, 101))
+ putline("+++after collect", mci);
+ putheader(mci, hdr, e);
+ if (tTd(43, 101))
+ putline("+++after putheader", mci);
+ bt = mime8to7(mci, hdr, e, boundaries, flags);
+ }
+ sprintf(buf, "--%s--", bbuf);
+ putline(buf, mci);
+ if (tTd(43, 35))
+ printf(" ...%s\n", buf);
+ boundaries[i] = NULL;
+ mci->mci_flags &= ~MCIF_INMIME;
+
+ /* skip the late "comment" epilogue */
+ while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ {
+ bt = mimeboundary(buf, boundaries);
+ if (bt != MBT_NOTSEP)
+ break;
+ putxline(buf, mci, PXLF_MAPFROM|PXLF_STRIP8BIT);
+ if (tTd(43, 99))
+ printf(" ...%s", buf);
+ }
+ if (feof(e->e_dfp))
+ bt = MBT_FINAL;
+ if (tTd(43, 3))
+ printf("\t\t\tmime8to7=>%s (multipart)\n",
+ MimeBoundaryNames[bt]);
+ return bt;
+ }
+
+ /*
+ ** Message/* types -- recurse exactly once.
+ **
+ ** Class 's' is predefined to have "rfc822" only.
+ */
+
+ if (strcasecmp(type, "message") == 0)
+ {
+ if (!wordinclass(subtype, 's'))
+ {
+ flags |= M87F_NO8BIT;
+ }
+ else
+ {
+ auto HDR *hdr = NULL;
+
+ putline("", mci);
+
+ mci->mci_flags |= MCIF_INMIME;
+ collect(e->e_dfp, FALSE, FALSE, &hdr, e);
+ if (tTd(43, 101))
+ putline("+++after collect", mci);
+ putheader(mci, hdr, e);
+ if (tTd(43, 101))
+ putline("+++after putheader", mci);
+ if (hvalue("MIME-Version", hdr) == NULL)
+ putline("MIME-Version: 1.0", mci);
+ bt = mime8to7(mci, hdr, e, boundaries, flags);
+ mci->mci_flags &= ~MCIF_INMIME;
+ return bt;
+ }
+ }
+
+ /*
+ ** Non-compound body type
+ **
+ ** Compute the ratio of seven to eight bit characters;
+ ** use that as a heuristic to decide how to do the
+ ** encoding.
+ */
+
+ sectionsize = sectionhighbits = 0;
+ if (!bitset(M87F_NO8BIT, flags))
+ {
+ /* remember where we were */
+ offset = ftell(e->e_dfp);
+ if (offset == -1)
+ syserr("mime8to7: cannot ftell on df%s", e->e_id);
+
+ /* do a scan of this body type to count character types */
+ while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ {
+ if (mimeboundary(buf, boundaries) != MBT_NOTSEP)
+ break;
+ for (p = buf; *p != '\0'; p++)
+ {
+ /* count bytes with the high bit set */
+ sectionsize++;
+ if (bitset(0200, *p))
+ sectionhighbits++;
+ }
+
+ /*
+ ** Heuristic: if 1/4 of the first 4K bytes are 8-bit,
+ ** assume base64. This heuristic avoids double-reading
+ ** large graphics or video files.
+ */
+
+ if (sectionsize >= 4096 &&
+ sectionhighbits > sectionsize / 4)
+ break;
+ }
+
+ /* return to the original offset for processing */
+ /* XXX use relative seeks to handle >31 bit file sizes? */
+ if (fseek(e->e_dfp, offset, SEEK_SET) < 0)
+ syserr("mime8to7: cannot fseek on df%s", e->e_id);
+ else
+ clearerr(e->e_dfp);
+ }
+
+ /*
+ ** Heuristically determine encoding method.
+ ** If more than 1/8 of the total characters have the
+ ** eighth bit set, use base64; else use quoted-printable.
+ ** However, only encode binary encoded data as base64,
+ ** since otherwise the NL=>CRLF mapping will be a problem.
+ */
+
+ if (tTd(43, 8))
+ {
+ printf("mime8to7: %ld high bit(s) in %ld byte(s), cte=%s\n",
+ sectionhighbits, sectionsize,
+ cte == NULL ? "[none]" : cte);
+ }
+ if (cte != NULL && strcasecmp(cte, "binary") == 0)
+ sectionsize = sectionhighbits;
+ linelen = 0;
+ bp = buf;
+ if (sectionhighbits == 0)
+ {
+ /* no encoding necessary */
+ if (cte != NULL)
+ {
+ sprintf(buf, "Content-Transfer-Encoding: %.200s", cte);
+ putline(buf, mci);
+ if (tTd(43, 36))
+ printf(" ...%s\n", buf);
+ }
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ {
+ bt = mimeboundary(buf, boundaries);
+ if (bt != MBT_NOTSEP)
+ break;
+ putline(buf, mci);
+ }
+ if (feof(e->e_dfp))
+ bt = MBT_FINAL;
+ }
+ else if (sectionsize / 8 < sectionhighbits)
+ {
+ /* use base64 encoding */
+ int c1, c2;
+
+ putline("Content-Transfer-Encoding: base64", mci);
+ if (tTd(43, 36))
+ printf(" ...Content-Transfer-Encoding: base64\n");
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ while ((c1 = mime_getchar_crlf(e->e_dfp, boundaries, &bt)) != EOF)
+ {
+ if (linelen > 71)
+ {
+ *bp = '\0';
+ putline(buf, mci);
+ linelen = 0;
+ bp = buf;
+ }
+ linelen += 4;
+ *bp++ = Base64Code[(c1 >> 2)];
+ c1 = (c1 & 0x03) << 4;
+ c2 = mime_getchar_crlf(e->e_dfp, boundaries, &bt);
+ if (c2 == EOF)
+ {
+ *bp++ = Base64Code[c1];
+ *bp++ = '=';
+ *bp++ = '=';
+ break;
+ }
+ c1 |= (c2 >> 4) & 0x0f;
+ *bp++ = Base64Code[c1];
+ c1 = (c2 & 0x0f) << 2;
+ c2 = mime_getchar_crlf(e->e_dfp, boundaries, &bt);
+ if (c2 == EOF)
+ {
+ *bp++ = Base64Code[c1];
+ *bp++ = '=';
+ break;
+ }
+ c1 |= (c2 >> 6) & 0x03;
+ *bp++ = Base64Code[c1];
+ *bp++ = Base64Code[c2 & 0x3f];
+ }
+ *bp = '\0';
+ putline(buf, mci);
+ }
+ else
+ {
+ /* use quoted-printable encoding */
+ int c1, c2;
+ int fromstate;
+ BITMAP badchars;
+
+ /* set up map of characters that must be mapped */
+ clrbitmap(badchars);
+ for (c1 = 0x00; c1 < 0x20; c1++)
+ setbitn(c1, badchars);
+ clrbitn('\t', badchars);
+ for (c1 = 0x7f; c1 < 0x100; c1++)
+ setbitn(c1, badchars);
+ setbitn('=', badchars);
+ if (bitnset(M_EBCDIC, mci->mci_mailer->m_flags))
+ for (p = "!\"#$@[\\]^`{|}~"; *p != '\0'; p++)
+ setbitn(*p, badchars);
+
+ putline("Content-Transfer-Encoding: quoted-printable", mci);
+ if (tTd(43, 36))
+ printf(" ...Content-Transfer-Encoding: quoted-printable\n");
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ fromstate = 0;
+ c2 = '\n';
+ while ((c1 = mime_getchar(e->e_dfp, boundaries, &bt)) != EOF)
+ {
+ if (c1 == '\n')
+ {
+ if (c2 == ' ' || c2 == '\t')
+ {
+ *bp++ = '=';
+ *bp++ = Base16Code[(c2 >> 4) & 0x0f];
+ *bp++ = Base16Code[c2 & 0x0f];
+ }
+ if (buf[0] == '.' && bp == &buf[1])
+ {
+ buf[0] = '=';
+ *bp++ = Base16Code[('.' >> 4) & 0x0f];
+ *bp++ = Base16Code['.' & 0x0f];
+ }
+ *bp = '\0';
+ putline(buf, mci);
+ linelen = fromstate = 0;
+ bp = buf;
+ c2 = c1;
+ continue;
+ }
+ if (c2 == ' ' && linelen == 4 && fromstate == 4 &&
+ bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
+ {
+ *bp++ = '=';
+ *bp++ = '2';
+ *bp++ = '0';
+ linelen += 3;
+ }
+ else if (c2 == ' ' || c2 == '\t')
+ {
+ *bp++ = c2;
+ linelen++;
+ }
+ if (linelen > 72 &&
+ (linelen > 75 || c1 != '.' ||
+ (linelen > 73 && c2 == '.')))
+ {
+ if (linelen > 73 && c2 == '.')
+ bp--;
+ else
+ c2 = '\n';
+ *bp++ = '=';
+ *bp = '\0';
+ putline(buf, mci);
+ linelen = fromstate = 0;
+ bp = buf;
+ if (c2 == '.')
+ {
+ *bp++ = '.';
+ linelen++;
+ }
+ }
+ if (bitnset(c1 & 0xff, badchars))
+ {
+ *bp++ = '=';
+ *bp++ = Base16Code[(c1 >> 4) & 0x0f];
+ *bp++ = Base16Code[c1 & 0x0f];
+ linelen += 3;
+ }
+ else if (c1 != ' ' && c1 != '\t')
+ {
+ if (linelen < 4 && c1 == "From"[linelen])
+ fromstate++;
+ *bp++ = c1;
+ linelen++;
+ }
+ c2 = c1;
+ }
+
+ /* output any saved character */
+ if (c2 == ' ' || c2 == '\t')
+ {
+ *bp++ = '=';
+ *bp++ = Base16Code[(c2 >> 4) & 0x0f];
+ *bp++ = Base16Code[c2 & 0x0f];
+ linelen += 3;
+ }
+
+ if (linelen > 0 || boundaries[0] != NULL)
+ {
+ *bp = '\0';
+ putline(buf, mci);
+ }
+
+ }
+ if (tTd(43, 3))
+ printf("\t\t\tmime8to7=>%s (basic)\n", MimeBoundaryNames[bt]);
+ return bt;
+}
+ /*
+** MIME_GETCHAR -- get a character for MIME processing
+**
+** Treats boundaries as EOF.
+**
+** Parameters:
+** fp -- the input file.
+** boundaries -- the current MIME boundaries.
+** btp -- if the return value is EOF, *btp is set to
+** the type of the boundary.
+**
+** Returns:
+** The next character in the input stream.
+*/
+
+int
+mime_getchar(fp, boundaries, btp)
+ register FILE *fp;
+ char **boundaries;
+ int *btp;
+{
+ int c;
+ static u_char *bp = NULL;
+ static int buflen = 0;
+ static bool atbol = TRUE; /* at beginning of line */
+ static int bt = MBT_SYNTAX; /* boundary type of next EOF */
+ static u_char buf[128]; /* need not be a full line */
+
+ if (buflen > 0)
+ {
+ buflen--;
+ return *bp++;
+ }
+ bp = buf;
+ buflen = 0;
+ c = getc(fp);
+ if (c == '\n')
+ {
+ /* might be part of a MIME boundary */
+ *bp++ = c;
+ atbol = TRUE;
+ c = getc(fp);
+ if (c == '\n')
+ {
+ ungetc(c, fp);
+ return c;
+ }
+ }
+ if (c != EOF)
+ *bp++ = c;
+ else
+ bt = MBT_FINAL;
+ if (atbol && c == '-')
+ {
+ /* check for a message boundary */
+ c = getc(fp);
+ if (c != '-')
+ {
+ if (c != EOF)
+ *bp++ = c;
+ else
+ bt = MBT_FINAL;
+ buflen = bp - buf - 1;
+ bp = buf;
+ return *bp++;
+ }
+
+ /* got "--", now check for rest of separator */
+ *bp++ = '-';
+ while (bp < &buf[sizeof buf - 2] &&
+ (c = getc(fp)) != EOF && c != '\n')
+ {
+ *bp++ = c;
+ }
+ *bp = '\0';
+ bt = mimeboundary(&buf[1], boundaries);
+ switch (bt)
+ {
+ case MBT_FINAL:
+ case MBT_INTERMED:
+ /* we have a message boundary */
+ buflen = 0;
+ *btp = bt;
+ return EOF;
+ }
+
+ atbol = c == '\n';
+ if (c != EOF)
+ *bp++ = c;
+ }
+
+ buflen = bp - buf - 1;
+ if (buflen < 0)
+ {
+ *btp = bt;
+ return EOF;
+ }
+ bp = buf;
+ return *bp++;
+}
+ /*
+** MIME_GETCHAR_CRLF -- do mime_getchar, but translate NL => CRLF
+**
+** Parameters:
+** fp -- the input file.
+** boundaries -- the current MIME boundaries.
+** btp -- if the return value is EOF, *btp is set to
+** the type of the boundary.
+**
+** Returns:
+** The next character in the input stream.
+*/
+
+int
+mime_getchar_crlf(fp, boundaries, btp)
+ register FILE *fp;
+ char **boundaries;
+ int *btp;
+{
+ static bool sendlf = FALSE;
+ int c;
+
+ if (sendlf)
+ {
+ sendlf = FALSE;
+ return '\n';
+ }
+ c = mime_getchar(fp, boundaries, btp);
+ if (c == '\n')
+ {
+ sendlf = TRUE;
+ return '\r';
+ }
+ return c;
+}
+ /*
+** MIMEBOUNDARY -- determine if this line is a MIME boundary & its type
+**
+** Parameters:
+** line -- the input line.
+** boundaries -- the set of currently pending boundaries.
+**
+** Returns:
+** MBT_NOTSEP -- if this is not a separator line
+** MBT_INTERMED -- if this is an intermediate separator
+** MBT_FINAL -- if this is a final boundary
+** MBT_SYNTAX -- if this is a boundary for the wrong
+** enclosure -- i.e., a syntax error.
+*/
+
+int
+mimeboundary(line, boundaries)
+ register char *line;
+ char **boundaries;
+{
+ int type = MBT_NOTSEP;
+ int i;
+ int savec;
+
+ if (line[0] != '-' || line[1] != '-' || boundaries == NULL)
+ return MBT_NOTSEP;
+ i = strlen(line);
+ if (line[i - 1] == '\n')
+ i--;
+
+ /* strip off trailing whitespace */
+ while (line[i - 1] == ' ' || line[i - 1] == '\t')
+ i--;
+ savec = line[i];
+ line[i] = '\0';
+
+ if (tTd(43, 5))
+ printf("mimeboundary: line=\"%s\"... ", line);
+
+ /* check for this as an intermediate boundary */
+ if (isboundary(&line[2], boundaries) >= 0)
+ type = MBT_INTERMED;
+ else if (i > 2 && strncmp(&line[i - 2], "--", 2) == 0)
+ {
+ /* check for a final boundary */
+ line[i - 2] = '\0';
+ if (isboundary(&line[2], boundaries) >= 0)
+ type = MBT_FINAL;
+ line[i - 2] = '-';
+ }
+
+ line[i] = savec;
+ if (tTd(43, 5))
+ printf("%s\n", MimeBoundaryNames[type]);
+ return type;
+}
+ /*
+** DEFCHARSET -- return default character set for message
+**
+** The first choice for character set is for the mailer
+** corresponding to the envelope sender. If neither that
+** nor the global configuration file has a default character
+** set defined, return "unknown-8bit" as recommended by
+** RFC 1428 section 3.
+**
+** Parameters:
+** e -- the envelope for this message.
+**
+** Returns:
+** The default character set for that mailer.
+*/
+
+char *
+defcharset(e)
+ register ENVELOPE *e;
+{
+ if (e != NULL && e->e_from.q_mailer != NULL &&
+ e->e_from.q_mailer->m_defcharset != NULL)
+ return e->e_from.q_mailer->m_defcharset;
+ if (DefaultCharSet != NULL)
+ return DefaultCharSet;
+ return "unknown-8bit";
+}
+ /*
+** ISBOUNDARY -- is a given string a currently valid boundary?
+**
+** Parameters:
+** line -- the current input line.
+** boundaries -- the list of valid boundaries.
+**
+** Returns:
+** The index number in boundaries if the line is found.
+** -1 -- otherwise.
+**
+*/
+
+int
+isboundary(line, boundaries)
+ char *line;
+ char **boundaries;
+{
+ register int i;
+
+ for (i = 0; boundaries[i] != NULL; i++)
+ {
+ if (strcmp(line, boundaries[i]) == 0)
+ return i;
+ }
+ return -1;
+}
+
+#endif /* MIME */
diff --git a/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c
new file mode 100644
index 000000000000..e8bda9c4be58
--- /dev/null
+++ b/usr.sbin/sendmail/src/parseaddr.c
@@ -0,0 +1,2157 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)parseaddr.c 8.86 (Berkeley) 9/28/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** PARSEADDR -- Parse an address
+**
+** Parses an address and breaks it up into three parts: a
+** net to transmit the message on, the host to transmit it
+** to, and a user on that host. These are loaded into an
+** ADDRESS header with the values squirreled away if necessary.
+** The "user" part may not be a real user; the process may
+** just reoccur on that machine. For example, on a machine
+** with an arpanet connection, the address
+** csvax.bill@berkeley
+** will break up to a "user" of 'csvax.bill' and a host
+** of 'berkeley' -- to be transmitted over the arpanet.
+**
+** Parameters:
+** addr -- the address to parse.
+** a -- a pointer to the address descriptor buffer.
+** If NULL, a header will be created.
+** flags -- describe detail for parsing. See RF_ definitions
+** in sendmail.h.
+** 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
+** `a' is non-NULL).
+** NULL on error.
+**
+** Side Effects:
+** none
+*/
+
+/* following delimiters are inherent to the internal algorithms */
+# define DELIMCHARS "()<>,;\r\n" /* default word delimiters */
+
+ADDRESS *
+parseaddr(addr, a, flags, delim, delimptr, e)
+ char *addr;
+ register ADDRESS *a;
+ int flags;
+ int delim;
+ char **delimptr;
+ register ENVELOPE *e;
+{
+ register char **pvp;
+ auto char *delimptrbuf;
+ bool queueup;
+ char pvpbuf[PSBUFSIZE];
+ extern ADDRESS *buildaddr();
+ extern bool invalidaddr();
+ extern void allocaddr __P((ADDRESS *, int, char *));
+
+ /*
+ ** Initialize and prescan address.
+ */
+
+ e->e_to = addr;
+ if (tTd(20, 1))
+ printf("\n--parseaddr(%s)\n", addr);
+
+ if (delimptr == NULL)
+ delimptr = &delimptrbuf;
+
+ pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL);
+ if (pvp == NULL)
+ {
+ if (tTd(20, 1))
+ printf("parseaddr-->NULL\n");
+ return (NULL);
+ }
+
+ if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr))
+ {
+ if (tTd(20, 1))
+ printf("parseaddr-->bad address\n");
+ return NULL;
+ }
+
+ /*
+ ** Save addr if we are going to have to.
+ **
+ ** We have to do this early because there is a chance that
+ ** the map lookups in the rewriting rules could clobber
+ ** static memory somewhere.
+ */
+
+ if (bitset(RF_COPYPADDR, flags) && addr != NULL)
+ {
+ char savec = **delimptr;
+
+ if (savec != '\0')
+ **delimptr = '\0';
+ e->e_to = addr = newstr(addr);
+ if (savec != '\0')
+ **delimptr = savec;
+ }
+
+ /*
+ ** Apply rewriting rules.
+ ** Ruleset 0 does basic parsing. It must resolve.
+ */
+
+ queueup = FALSE;
+ if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
+ queueup = TRUE;
+ if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
+ queueup = TRUE;
+
+
+ /*
+ ** Build canonical address from pvp.
+ */
+
+ a = buildaddr(pvp, a, flags, e);
+
+ /*
+ ** Make local copies of the host & user and then
+ ** transport them out.
+ */
+
+ allocaddr(a, flags, addr);
+ if (bitset(QBADADDR, a->q_flags))
+ return a;
+
+ /*
+ ** If there was a parsing failure, mark it for queueing.
+ */
+
+ if (queueup)
+ {
+ char *msg = "Transient parse error -- message queued for future delivery";
+
+ if (e->e_sendmode == SM_DEFER)
+ msg = "Deferring message until queue run";
+ if (tTd(20, 1))
+ printf("parseaddr: queuing message\n");
+ message(msg);
+ if (e->e_message == NULL && e->e_sendmode != SM_DEFER)
+ e->e_message = newstr(msg);
+ a->q_flags |= QQUEUEUP;
+ a->q_status = "4.4.3";
+ }
+
+ /*
+ ** Compute return value.
+ */
+
+ if (tTd(20, 1))
+ {
+ printf("parseaddr-->");
+ printaddr(a, FALSE);
+ }
+
+ return (a);
+}
+ /*
+** INVALIDADDR -- check for address containing meta-characters
+**
+** Parameters:
+** addr -- the address to check.
+**
+** Returns:
+** TRUE -- if the address has any "wierd" characters
+** FALSE -- otherwise.
+*/
+
+bool
+invalidaddr(addr, delimptr)
+ register char *addr;
+ char *delimptr;
+{
+ char savedelim = '\0';
+
+ if (delimptr != NULL)
+ {
+ savedelim = *delimptr;
+ if (savedelim != '\0')
+ *delimptr = '\0';
+ }
+#if 0
+ /* for testing.... */
+ if (strcmp(addr, "INvalidADDR") == 0)
+ {
+ usrerr("553 INvalid ADDRess");
+ goto addrfailure;
+ }
+#endif
+ for (; *addr != '\0'; addr++)
+ {
+ if ((*addr & 0340) == 0200)
+ break;
+ }
+ if (*addr == '\0')
+ {
+ if (delimptr != NULL && savedelim != '\0')
+ *delimptr = savedelim;
+ return FALSE;
+ }
+ setstat(EX_USAGE);
+ usrerr("553 Address contained invalid control characters");
+ addrfailure:
+ if (delimptr != NULL && savedelim != '\0')
+ *delimptr = savedelim;
+ return TRUE;
+}
+ /*
+** ALLOCADDR -- do local allocations of address on demand.
+**
+** Also lowercases the host name if requested.
+**
+** Parameters:
+** a -- the address to reallocate.
+** flags -- the copy flag (see RF_ definitions in sendmail.h
+** for a description).
+** paddr -- the printname of the address.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Copies portions of a into local buffers as requested.
+*/
+
+void
+allocaddr(a, flags, paddr)
+ register ADDRESS *a;
+ int flags;
+ char *paddr;
+{
+ if (tTd(24, 4))
+ printf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr);
+
+ a->q_paddr = paddr;
+
+ if (a->q_user == NULL)
+ a->q_user = "";
+ if (a->q_host == NULL)
+ a->q_host = "";
+
+ if (bitset(RF_COPYPARSE, flags))
+ {
+ 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;
+}
+ /*
+** PRESCAN -- Prescan name and make it canonical
+**
+** Scans a name and turns it into a set of tokens. This process
+** deletes blanks and comments (in parentheses).
+**
+** This routine knows about quoted strings and angle brackets.
+**
+** There are certain subtleties to this routine. The one that
+** comes to mind now is that backslashes on the ends of names
+** are silently stripped off; this is intentional. The problem
+** is that some versions of sndmsg (like at LBL) set the kill
+** character to something other than @ when reading addresses;
+** so people type "csvax.eric\@berkeley" -- which screws up the
+** berknet mailer.
+**
+** Parameters:
+** addr -- the name to chomp.
+** delim -- the delimiter for the address, normally
+** '\0' or ','; \0 is accepted in any case.
+** If '\t' then we are reading the .cf file.
+** pvpbuf -- place to put the saved text -- note that
+** the pointers are static.
+** pvpbsize -- size of pvpbuf.
+** delimptr -- if non-NULL, set to the location of the
+** terminating delimiter.
+** toktab -- if set, a token table to use for parsing.
+** If NULL, use the default table.
+**
+** Returns:
+** A pointer to a vector of tokens.
+** NULL on error.
+*/
+
+/* states and character types */
+# define OPR 0 /* operator */
+# define ATM 1 /* atom */
+# define QST 2 /* in quoted string */
+# define SPC 3 /* chewing up spaces */
+# define ONE 4 /* pick up one character */
+# define ILL 5 /* illegal character */
+
+# define NSTATES 6 /* number of states */
+# define TYPE 017 /* mask to select state type */
+
+/* meta bits for table */
+# define M 020 /* meta character; don't pass through */
+# define B 040 /* cause a break */
+# define MB M|B /* meta-break */
+
+static short StateTab[NSTATES][NSTATES] =
+{
+ /* oldst chtype> OPR ATM QST SPC ONE ILL */
+ /*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB,
+ /*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB,
+ /*QST*/ QST, QST, OPR, QST, QST, QST,
+ /*SPC*/ OPR, ATM, QST, SPC|M, ONE, ILL|MB,
+ /*ONE*/ OPR, OPR, OPR, OPR, OPR, ILL|MB,
+ /*ILL*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M,
+};
+
+/* token type table -- it gets modified with $o characters */
+static u_char TokTypeTab[256] =
+{
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* @ A B C D E F G H I J K L M N O */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+};
+
+/* token type table for MIME parsing */
+u_char MimeTokenTab[256] =
+{
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,OPR,ATM,ATM,OPR,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,OPR,OPR,OPR,OPR,OPR,OPR,
+ /* @ A B C D E F G H I J K L M N O */
+ OPR,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,OPR,OPR,OPR,ATM,ATM,
+ /* ` a b c d e f g h i j k l m n o */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ /* p q r s t u v w x y z { | } ~ del */
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+
+ /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* sp ! " # $ % & ' ( ) * + , - . / */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* @ A B C D E F G H I J K L M N O */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* P Q R S T U V W X Y Z [ \ ] ^ _ */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* ` a b c d e f g h i j k l m n o */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+ /* p q r s t u v w x y z { | } ~ del */
+ ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL,
+};
+
+
+# define NOCHAR -1 /* signal nothing in lookahead token */
+
+char **
+prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
+ char *addr;
+ int delim;
+ char pvpbuf[];
+ int pvpbsize;
+ char **delimptr;
+ u_char *toktab;
+{
+ register char *p;
+ register char *q;
+ register int c;
+ char **avp;
+ bool bslashmode;
+ int cmntcnt;
+ int anglecnt;
+ char *tok;
+ int state;
+ int newstate;
+ char *saveto = CurEnv->e_to;
+ static char *av[MAXATOM+1];
+ static char firsttime = TRUE;
+ extern int errno;
+
+ if (firsttime)
+ {
+ /* initialize the token type table */
+ char obuf[50];
+
+ firsttime = FALSE;
+ if (OperatorChars == NULL)
+ {
+ if (ConfigLevel < 7)
+ OperatorChars = macvalue('o', CurEnv);
+ if (OperatorChars == NULL)
+ OperatorChars = ".:@[]";
+ }
+ expand(OperatorChars, obuf, sizeof obuf - sizeof DELIMCHARS, CurEnv);
+ strcat(obuf, DELIMCHARS);
+ for (p = obuf; *p != '\0'; p++)
+ {
+ if (TokTypeTab[*p & 0xff] == ATM)
+ TokTypeTab[*p & 0xff] = OPR;
+ }
+ }
+ if (toktab == NULL)
+ toktab = TokTypeTab;
+
+ /* make sure error messages don't have garbage on them */
+ errno = 0;
+
+ q = pvpbuf;
+ bslashmode = FALSE;
+ cmntcnt = 0;
+ anglecnt = 0;
+ avp = av;
+ state = ATM;
+ c = NOCHAR;
+ p = addr;
+ CurEnv->e_to = p;
+ if (tTd(22, 11))
+ {
+ printf("prescan: ");
+ xputs(p);
+ (void) putchar('\n');
+ }
+
+ do
+ {
+ /* read a token */
+ tok = q;
+ for (;;)
+ {
+ /* store away any old lookahead character */
+ if (c != NOCHAR && !bslashmode)
+ {
+ /* see if there is room */
+ if (q >= &pvpbuf[pvpbsize - 5])
+ {
+ usrerr("553 Address too long");
+ if (strlen(addr) > MAXNAME)
+ addr[MAXNAME] = '\0';
+ returnnull:
+ if (delimptr != NULL)
+ *delimptr = p;
+ CurEnv->e_to = saveto;
+ return (NULL);
+ }
+
+ /* squirrel it away */
+ *q++ = c;
+ }
+
+ /* read a new input character */
+ c = *p++;
+ if (c == '\0')
+ {
+ /* diagnose and patch up bad syntax */
+ if (state == QST)
+ {
+ usrerr("653 Unbalanced '\"'");
+ c = '"';
+ }
+ else if (cmntcnt > 0)
+ {
+ usrerr("653 Unbalanced '('");
+ c = ')';
+ }
+ else if (anglecnt > 0)
+ {
+ c = '>';
+ usrerr("653 Unbalanced '<'");
+ }
+ else
+ break;
+
+ p--;
+ }
+ else if (c == delim && anglecnt <= 0 &&
+ cmntcnt <= 0 && state != QST)
+ break;
+
+ if (tTd(22, 101))
+ printf("c=%c, s=%d; ", c, state);
+
+ /* chew up special characters */
+ *q = '\0';
+ if (bslashmode)
+ {
+ bslashmode = FALSE;
+
+ /* kludge \! for naive users */
+ if (cmntcnt > 0)
+ {
+ c = NOCHAR;
+ continue;
+ }
+ else if (c != '!' || state == QST)
+ {
+ *q++ = '\\';
+ continue;
+ }
+ }
+
+ if (c == '\\')
+ {
+ bslashmode = TRUE;
+ }
+ else if (state == QST)
+ {
+ /* do nothing, just avoid next clauses */
+ }
+ else if (c == '(')
+ {
+ cmntcnt++;
+ c = NOCHAR;
+ }
+ else if (c == ')')
+ {
+ if (cmntcnt <= 0)
+ {
+ usrerr("653 Unbalanced ')'");
+ c = NOCHAR;
+ }
+ else
+ cmntcnt--;
+ }
+ else if (cmntcnt > 0)
+ c = NOCHAR;
+ else if (c == '<')
+ anglecnt++;
+ else if (c == '>')
+ {
+ if (anglecnt <= 0)
+ {
+ usrerr("653 Unbalanced '>'");
+ c = NOCHAR;
+ }
+ else
+ anglecnt--;
+ }
+ else if (delim == ' ' && isascii(c) && isspace(c))
+ c = ' ';
+
+ if (c == NOCHAR)
+ continue;
+
+ /* see if this is end of input */
+ if (c == delim && anglecnt <= 0 && state != QST)
+ break;
+
+ newstate = StateTab[state][toktab[c & 0xff]];
+ if (tTd(22, 101))
+ printf("ns=%02o\n", newstate);
+ state = newstate & TYPE;
+ if (state == ILL)
+ {
+ if (isascii(c) && isprint(c))
+ usrerr("653 Illegal character %c", c);
+ else
+ usrerr("653 Illegal character 0x%02x", c);
+ }
+ if (bitset(M, newstate))
+ c = NOCHAR;
+ if (bitset(B, newstate))
+ break;
+ }
+
+ /* new token */
+ if (tok != q)
+ {
+ *q++ = '\0';
+ if (tTd(22, 36))
+ {
+ printf("tok=");
+ xputs(tok);
+ (void) putchar('\n');
+ }
+ if (avp >= &av[MAXATOM])
+ {
+ syserr("553 prescan: too many tokens");
+ goto returnnull;
+ }
+ if (q - tok > MAXNAME)
+ {
+ syserr("553 prescan: token too long");
+ goto returnnull;
+ }
+ *avp++ = tok;
+ }
+ } while (c != '\0' && (c != delim || anglecnt > 0));
+ *avp = NULL;
+ p--;
+ if (delimptr != NULL)
+ *delimptr = p;
+ if (tTd(22, 12))
+ {
+ printf("prescan==>");
+ printav(av);
+ }
+ CurEnv->e_to = saveto;
+ if (av[0] == NULL)
+ {
+ if (tTd(22, 1))
+ printf("prescan: null leading token\n");
+ return (NULL);
+ }
+ return (av);
+}
+ /*
+** REWRITE -- apply rewrite rules to token vector.
+**
+** This routine is an ordered production system. Each rewrite
+** rule has a LHS (called the pattern) and a RHS (called the
+** rewrite); 'rwr' points the the current rewrite rule.
+**
+** For each rewrite rule, 'avp' points the address vector we
+** are trying to match against, and 'pvp' points to the pattern.
+** If pvp points to a special match value (MATCHZANY, MATCHANY,
+** MATCHONE, MATCHCLASS, MATCHNCLASS) then the address in avp
+** matched is saved away in the match vector (pointed to by 'mvp').
+**
+** When a match between avp & pvp does not match, we try to
+** back out. If we back up over MATCHONE, MATCHCLASS, or MATCHNCLASS
+** we must also back out the match in mvp. If we reach a
+** MATCHANY or MATCHZANY we just extend the match and start
+** over again.
+**
+** When we finally match, we rewrite the address vector
+** and try over again.
+**
+** Parameters:
+** pvp -- pointer to token vector.
+** ruleset -- the ruleset to use for rewriting.
+** reclevel -- recursion level (to catch loops).
+** e -- the current envelope.
+**
+** Returns:
+** A status code. If EX_TEMPFAIL, higher level code should
+** attempt recovery.
+**
+** Side Effects:
+** pvp is modified.
+*/
+
+struct match
+{
+ char **first; /* first token matched */
+ char **last; /* last token matched */
+ char **pattern; /* pointer to pattern */
+};
+
+# define MAXMATCH 9 /* max params per rewrite */
+
+
+int
+rewrite(pvp, ruleset, reclevel, e)
+ char **pvp;
+ int ruleset;
+ int reclevel;
+ register ENVELOPE *e;
+{
+ register char *ap; /* address pointer */
+ register char *rp; /* rewrite pointer */
+ register char **avp; /* address vector pointer */
+ 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 */
+ int loopcount;
+ struct match mlist[MAXMATCH]; /* stores match on LHS */
+ char *npvp[MAXATOM+1]; /* temporary space for rebuild */
+
+ if (OpMode == MD_TEST || tTd(21, 1))
+ {
+ 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 (reclevel++ > MaxRuleRecursion)
+ {
+ syserr("rewrite: excessive recursion (max %d), ruleset %d",
+ MaxRuleRecursion, ruleset);
+ return EX_CONFIG;
+ }
+ if (pvp == NULL)
+ return EX_USAGE;
+
+ /*
+ ** Run through the list of rewrite rules, applying
+ ** any that match.
+ */
+
+ ruleno = 1;
+ loopcount = 0;
+ for (rwr = RewriteRules[ruleset]; rwr != NULL; )
+ {
+ if (tTd(21, 12))
+ {
+ printf("-----trying rule:");
+ printav(rwr->r_lhs);
+ }
+
+ /* try to match on this rule */
+ 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))
+ {
+ printf("ADVANCE rp=");
+ xputs(rp);
+ printf(", ap=");
+ xputs(ap);
+ printf("\n");
+ }
+ if (rp == NULL)
+ {
+ /* end-of-pattern before end-of-address */
+ goto backup;
+ }
+ if (ap == NULL && (*rp & 0377) != MATCHZANY &&
+ (*rp & 0377) != MATCHZERO)
+ {
+ /* end-of-input with patterns left */
+ goto backup;
+ }
+
+ switch (*rp & 0377)
+ {
+ char buf[MAXLINE];
+
+ case MATCHCLASS:
+ /* 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');
+ if (!wordinclass(buf, rp[1]))
+ {
+ if (tTd(21, 36))
+ {
+ printf("EXTEND rp=");
+ xputs(rp);
+ printf(", ap=");
+ xputs(ap);
+ printf("\n");
+ }
+ goto extendclass;
+ }
+ if (tTd(21, 36))
+ printf("CLMATCH\n");
+ mlp++;
+ break;
+
+ case MATCHNCLASS:
+ /* match any token not in a class */
+ if (wordinclass(ap, rp[1]))
+ goto backup;
+
+ /* fall through */
+
+ case MATCHONE:
+ case MATCHANY:
+ /* match exactly one token */
+ mlp->pattern = rvp;
+ mlp->first = avp;
+ mlp->last = avp++;
+ mlp++;
+ break;
+
+ case MATCHZANY:
+ /* match zero or more tokens */
+ mlp->pattern = rvp;
+ 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))
+ goto backup;
+ avp++;
+ break;
+ }
+
+ /* successful match on this token */
+ rvp++;
+ continue;
+
+ backup:
+ /* match failed -- back up */
+ while (--mlp >= mlist)
+ {
+ rvp = mlp->pattern;
+ rp = *rvp;
+ 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 */
+ mlp->last = avp++;
+ rvp++;
+ mlp++;
+ break;
+ }
+ if ((*rp & 0377) == MATCHCLASS)
+ {
+ /* extend binding and try again */
+ mlp->last = avp;
+ goto extendclass;
+ }
+ }
+
+ if (mlp < mlist)
+ {
+ /* total failure to match */
+ break;
+ }
+ }
+
+ /*
+ ** See if we successfully matched
+ */
+
+ if (mlp < mlist || *rvp != NULL)
+ {
+ if (tTd(21, 10))
+ printf("----- rule fails\n");
+ rwr = rwr->r_next;
+ ruleno++;
+ loopcount = 0;
+ continue;
+ }
+
+ rvp = rwr->r_rhs;
+ if (tTd(21, 12))
+ {
+ printf("-----rule matches:");
+ printav(rvp);
+ }
+
+ rp = *rvp;
+ if ((*rp & 0377) == CANONUSER)
+ {
+ rvp++;
+ rwr = rwr->r_next;
+ ruleno++;
+ loopcount = 0;
+ }
+ else if ((*rp & 0377) == CANONHOST)
+ {
+ rvp++;
+ rwr = NULL;
+ }
+ else if ((*rp & 0377) == CANONNET)
+ rwr = NULL;
+
+ /* substitute */
+ for (avp = npvp; *rvp != NULL; rvp++)
+ {
+ register struct match *m;
+ register char **pp;
+
+ rp = *rvp;
+ if ((*rp & 0377) == MATCHREPL)
+ {
+ /* substitute from LHS */
+ m = &mlist[rp[1] - '1'];
+ if (m < mlist || m >= mlp)
+ {
+ syserr("554 rewrite: ruleset %d: replacement $%c out of bounds",
+ ruleset, rp[1]);
+ return EX_CONFIG;
+ }
+ if (tTd(21, 15))
+ {
+ printf("$%c:", rp[1]);
+ pp = m->first;
+ while (pp <= m->last)
+ {
+ printf(" %x=\"", *pp);
+ (void) fflush(stdout);
+ printf("%s\"", *pp++);
+ }
+ printf("\n");
+ }
+ pp = m->first;
+ while (pp <= m->last)
+ {
+ if (avp >= &npvp[MAXATOM])
+ {
+ syserr("554 rewrite: expansion too long");
+ return EX_DATAERR;
+ }
+ *avp++ = *pp++;
+ }
+ }
+ else
+ {
+ /* vanilla replacement */
+ if (avp >= &npvp[MAXATOM])
+ {
+ toolong:
+ 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++ = NULL;
+
+ /*
+ ** Check for any hostname/keyword lookups.
+ */
+
+ for (rvp = npvp; *rvp != NULL; rvp++)
+ {
+ char **hbrvp;
+ char **xpvp;
+ int trsize;
+ 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 *argvect[10];
+ char pvpbuf[PSBUFSIZE];
+ char *nullpvp[1];
+
+ if ((**rvp & 0377) != HOSTBEGIN &&
+ (**rvp & 0377) != LOOKUPBEGIN)
+ continue;
+
+ /*
+ ** Got a hostname/keyword lookup.
+ **
+ ** 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 */
+ 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 (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 */
+ cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
+ argvect[0] = buf;
+ if (e->e_sendmode == SM_DEFER)
+ {
+ /* don't do any map lookups */
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) => DEFERRED\n",
+ mapname, buf);
+ replac = NULL;
+ rstat = EX_TEMPFAIL;
+ }
+ else if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
+ {
+ auto int stat = EX_OK;
+
+ if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
+ stripquotes(buf);
+
+ /* 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 = EX_TEMPFAIL;
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) tempfail: errno=%d\n",
+ mapname, buf, errno);
+ if (e->e_message == NULL)
+ {
+ char mbuf[300];
+
+ sprintf(mbuf, "%.80s map: lookup (%s): deferred",
+ mapname,
+ shortenstring(buf, 203));
+ e->e_message = newstr(mbuf);
+ }
+ }
+ }
+ 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 if (*replac == '\0')
+ {
+ /* null replacement */
+ nullpvp[0] = NULL;
+ xpvp = nullpvp;
+ }
+ else
+ {
+ /* scan the new replacement */
+ xpvp = prescan(replac, '\0', pvpbuf,
+ sizeof pvpbuf, NULL, NULL);
+ if (xpvp == NULL)
+ {
+ /* prescan already printed error */
+ return EX_DATAERR;
+ }
+ }
+
+ /* append it to the token list */
+ for (avp = hbrvp; *xpvp != NULL; xpvp++)
+ {
+ *avp++ = newstr(*xpvp);
+ if (avp >= &npvp[MAXATOM])
+ goto toolong;
+ }
+
+ /* restore the old trailing information */
+ for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; )
+ if (avp >= &npvp[MAXATOM])
+ goto toolong;
+
+ break;
+ }
+
+ /*
+ ** Check for subroutine calls.
+ */
+
+ if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
+ {
+ int stat;
+
+ if (npvp[1] == NULL)
+ {
+ syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
+ ruleset, ruleno);
+ *pvp = NULL;
+ }
+ else
+ {
+ int ruleset;
+ STAB *s;
+
+ bcopy((char *) &npvp[2], (char *) pvp,
+ (int) (avp - npvp - 2) * sizeof *avp);
+ if (tTd(21, 3))
+ printf("-----callsubr %s\n", npvp[1]);
+ ruleset = strtorwset(npvp[1], NULL, ST_FIND);
+ stat = rewrite(pvp, ruleset, reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
+ if (*pvp != NULL && (**pvp & 0377) == CANONNET)
+ rwr = NULL;
+ }
+ }
+ else
+ {
+ bcopy((char *) npvp, (char *) pvp,
+ (int) (avp - npvp) * sizeof *avp);
+ }
+ if (tTd(21, 4))
+ {
+ printf("rewritten as:");
+ printav(pvp);
+ }
+ }
+
+ if (OpMode == MD_TEST || tTd(21, 1))
+ {
+ printf("rewrite: ruleset %2d returns:", ruleset);
+ printav(pvp);
+ }
+
+ return rstat;
+}
+ /*
+** BUILDADDR -- build address from token vector.
+**
+** Parameters:
+** tv -- token vector.
+** a -- pointer to address descriptor to fill.
+** If NULL, one will be allocated.
+** flags -- info regarding whether this is a sender or
+** a recipient.
+** e -- the current envelope.
+**
+** Returns:
+** NULL if there was an error.
+** 'a' otherwise.
+**
+** Side Effects:
+** 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 *
+buildaddr(tv, a, flags, e)
+ register char **tv;
+ register ADDRESS *a;
+ int flags;
+ register ENVELOPE *e;
+{
+ struct mailer **mp;
+ register struct mailer *m;
+ register char *p;
+ char *mname;
+ char **hostp;
+ char hbuf[MAXNAME + 1];
+ static MAILER errormailer;
+ static char *errorargv[] = { "ERROR", NULL };
+ static char ubuf[MAXNAME + 1];
+
+ if (tTd(24, 5))
+ {
+ printf("buildaddr, flags=%x, tv=", flags);
+ printav(tv);
+ }
+
+ if (a == NULL)
+ a = (ADDRESS *) xalloc(sizeof *a);
+ bzero((char *) a, sizeof *a);
+
+ /* set up default error return flags */
+ a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
+
+ /* figure out what net/mailer to use */
+ if (*tv == NULL || (**tv & 0377) != CANONNET)
+ {
+ syserr("554 buildaddr: no mailer in parsed address");
+badaddr:
+ a->q_flags |= QBADADDR;
+ a->q_mailer = &errormailer;
+ if (errormailer.m_name == NULL)
+ {
+ /* initialize the bogus mailer */
+ errormailer.m_name = "*error*";
+ errormailer.m_mailer = "ERROR";
+ errormailer.m_argv = errorargv;
+ }
+ return a;
+ }
+ mname = *++tv;
+
+ /* extract host and user portions */
+ if ((**++tv & 0377) == CANONHOST)
+ hostp = ++tv;
+ else
+ hostp = NULL;
+ while (*tv != NULL && (**tv & 0377) != CANONUSER)
+ tv++;
+ if (*tv == NULL)
+ {
+ syserr("554 buildaddr: no user");
+ goto badaddr;
+ }
+ if (tv == hostp)
+ hostp = NULL;
+ else if (hostp != NULL)
+ cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0');
+ cataddr(++tv, NULL, ubuf, sizeof ubuf, ' ');
+
+ /* save away the host name */
+ if (strcasecmp(mname, "error") == 0)
+ {
+ if (hostp != NULL)
+ {
+ register struct errcodes *ep;
+
+ if (strchr(hbuf, '.') != NULL)
+ {
+ a->q_status = newstr(hbuf);
+ setstat(dsntoexitstat(hbuf));
+ }
+ else if (isascii(hbuf[0]) && isdigit(hbuf[0]))
+ {
+ setstat(atoi(hbuf));
+ }
+ else
+ {
+ for (ep = ErrorCodes; ep->ec_name != NULL; ep++)
+ if (strcasecmp(ep->ec_name, hbuf) == 0)
+ break;
+ setstat(ep->ec_code);
+ }
+ }
+ else
+ setstat(EX_UNAVAILABLE);
+ stripquotes(ubuf);
+ if (isascii(ubuf[0]) && isdigit(ubuf[0]) &&
+ isascii(ubuf[1]) && isdigit(ubuf[1]) &&
+ isascii(ubuf[2]) && isdigit(ubuf[2]) &&
+ ubuf[3] == ' ')
+ {
+ char fmt[10];
+
+ strncpy(fmt, ubuf, 3);
+ strcpy(&fmt[3], " %s");
+ usrerr(fmt, ubuf + 4);
+
+ /*
+ ** If this is a 4xx code and we aren't running
+ ** SMTP on our input, bounce this message;
+ ** otherwise it disappears without a trace.
+ */
+
+ if (fmt[0] == '4' && OpMode != MD_SMTP &&
+ OpMode != MD_DAEMON)
+ {
+ e->e_flags |= EF_FATALERRS;
+ }
+ }
+ else
+ {
+ usrerr("553 %s", ubuf);
+ }
+ goto badaddr;
+ }
+
+ for (mp = Mailer; (m = *mp++) != NULL; )
+ {
+ if (strcasecmp(m->m_name, mname) == 0)
+ break;
+ }
+ if (m == NULL)
+ {
+ syserr("554 buildaddr: unknown mailer %s", mname);
+ goto badaddr;
+ }
+ a->q_mailer = m;
+
+ /* figure out what host (if any) */
+ if (hostp == NULL)
+ {
+ if (!bitnset(M_LOCALMAILER, m->m_flags))
+ {
+ syserr("554 buildaddr: no host");
+ goto badaddr;
+ }
+ a->q_host = NULL;
+ }
+ else
+ a->q_host = newstr(hbuf);
+
+ /* figure out the user */
+ p = ubuf;
+ if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@')
+ {
+ p++;
+ tv++;
+ a->q_flags |= QNOTREMOTE;
+ }
+
+ /* do special mapping for local mailer */
+ if (*p == '"')
+ p++;
+ if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags))
+ a->q_mailer = m = ProgMailer;
+ else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags))
+ a->q_mailer = m = FileMailer;
+ else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags))
+ {
+ /* may be :include: */
+ stripquotes(ubuf);
+ if (strncasecmp(ubuf, ":include:", 9) == 0)
+ {
+ /* if :include:, don't need further rewriting */
+ a->q_mailer = m = InclMailer;
+ a->q_user = newstr(&ubuf[9]);
+ return a;
+ }
+ }
+
+ /* rewrite according recipient mailer rewriting rules */
+ define('h', a->q_host, e);
+ if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
+ {
+ /* sender addresses done later */
+ (void) rewrite(tv, 2, 0, e);
+ if (m->m_re_rwset > 0)
+ (void) rewrite(tv, m->m_re_rwset, 0, e);
+ }
+ (void) rewrite(tv, 4, 0, e);
+
+ /* save the result for the command line/RCPT argument */
+ cataddr(tv, NULL, ubuf, sizeof ubuf, '\0');
+ a->q_user = ubuf;
+
+ /*
+ ** 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);
+
+ if (tTd(24, 6))
+ {
+ printf("buildaddr => ");
+ printaddr(a, FALSE);
+ }
+ return a;
+}
+ /*
+** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)
+**
+** 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.
+** spacesub -- the space separator character; if null,
+** use SpaceSub.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Destroys buf.
+*/
+
+void
+cataddr(pvp, evp, buf, sz, spacesub)
+ char **pvp;
+ char **evp;
+ char *buf;
+ register int sz;
+ int spacesub;
+{
+ bool oatomtok = FALSE;
+ bool natomtok = FALSE;
+ register int i;
+ register char *p;
+
+ if (spacesub == '\0')
+ spacesub = SpaceSub;
+
+ if (pvp == NULL)
+ {
+ (void) strcpy(buf, "");
+ return;
+ }
+ p = buf;
+ sz -= 2;
+ while (*pvp != NULL && (i = strlen(*pvp)) < sz)
+ {
+ natomtok = (TokTypeTab[**pvp & 0xff] == ATM);
+ if (oatomtok && natomtok)
+ *p++ = spacesub;
+ (void) strcpy(p, *pvp);
+ oatomtok = natomtok;
+ p += i;
+ sz -= i + 1;
+ if (pvp++ == evp)
+ break;
+ }
+ *p = '\0';
+}
+ /*
+** SAMEADDR -- Determine if two addresses are the same
+**
+** This is not just a straight comparison -- if the mailer doesn't
+** care about the host we just ignore it, etc.
+**
+** Parameters:
+** a, b -- pointers to the internal forms to compare.
+**
+** Returns:
+** TRUE -- they represent the same mailbox.
+** FALSE -- they don't.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+sameaddr(a, b)
+ register ADDRESS *a;
+ register ADDRESS *b;
+{
+ register ADDRESS *ca, *cb;
+
+ /* if they don't have the same mailer, forget it */
+ if (a->q_mailer != b->q_mailer)
+ return (FALSE);
+
+ /* if the user isn't the same, we can drop out */
+ if (strcmp(a->q_user, b->q_user) != 0)
+ return (FALSE);
+
+ /* if we have good uids for both but they differ, these are different */
+ if (a->q_mailer == ProgMailer)
+ {
+ ca = getctladdr(a);
+ cb = getctladdr(b);
+ if (ca != NULL && cb != NULL &&
+ bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
+ ca->q_uid != cb->q_uid)
+ return (FALSE);
+ }
+
+ /* 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)
+ {
+ /* only one is a null pointer */
+ return (FALSE);
+ }
+ if (strcmp(a->q_host, b->q_host) != 0)
+ return (FALSE);
+
+ return (TRUE);
+}
+ /*
+** PRINTADDR -- print address (for debugging)
+**
+** Parameters:
+** a -- the address to print
+** follow -- follow the q_next chain.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+struct qflags
+{
+ char *qf_name;
+ u_long qf_bit;
+};
+
+struct qflags AddressFlags[] =
+{
+ "QDONTSEND", QDONTSEND,
+ "QBADADDR", QBADADDR,
+ "QGOODUID", QGOODUID,
+ "QPRIMARY", QPRIMARY,
+ "QQUEUEUP", QQUEUEUP,
+ "QSENT", QSENT,
+ "QNOTREMOTE", QNOTREMOTE,
+ "QSELFREF", QSELFREF,
+ "QVERIFIED", QVERIFIED,
+ "QBOGUSSHELL", QBOGUSSHELL,
+ "QUNSAFEADDR", QUNSAFEADDR,
+ "QPINGONSUCCESS", QPINGONSUCCESS,
+ "QPINGONFAILURE", QPINGONFAILURE,
+ "QPINGONDELAY", QPINGONDELAY,
+ "QHASNOTIFY", QHASNOTIFY,
+ "QRELAYED", QRELAYED,
+ "QEXPANDED", QEXPANDED,
+ "QDELIVERED", QDELIVERED,
+ "QDELAYED", QDELAYED,
+ "QTHISPASS", QTHISPASS,
+ NULL
+};
+
+void
+printaddr(a, follow)
+ register ADDRESS *a;
+ bool follow;
+{
+ register MAILER *m;
+ MAILER pseudomailer;
+ register struct qflags *qfp;
+ bool firstone;
+
+ if (a == NULL)
+ {
+ printf("[NULL]\n");
+ return;
+ }
+
+ while (a != NULL)
+ {
+ printf("%x=", a);
+ (void) fflush(stdout);
+
+ /* 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'\n",
+ a->q_paddr == NULL ? "<null>" : a->q_paddr,
+ m->m_mno, m->m_name,
+ a->q_host == NULL ? "<null>" : a->q_host);
+ printf("\tuser `%s', ruser `%s'\n",
+ a->q_user,
+ a->q_ruser == NULL ? "<null>" : a->q_ruser);
+ printf("\tnext=%x, alias %x, uid %d, gid %d\n",
+ a->q_next, a->q_alias, a->q_uid, a->q_gid);
+ printf("\tflags=%lx<", a->q_flags);
+ firstone = TRUE;
+ for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++)
+ {
+ if (!bitset(qfp->qf_bit, a->q_flags))
+ continue;
+ if (!firstone)
+ printf(",");
+ firstone = FALSE;
+ printf("%s", qfp->qf_name);
+ }
+ printf(">\n");
+ printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n",
+ a->q_owner == NULL ? "(none)" : a->q_owner,
+ a->q_home == NULL ? "(none)" : a->q_home,
+ a->q_fullname == NULL ? "(none)" : a->q_fullname);
+ printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n",
+ a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
+ a->q_statmta == NULL ? "(none)" : a->q_statmta,
+ a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
+
+ if (!follow)
+ return;
+ a = a->q_next;
+ }
+}
+ /*
+** EMPTYADDR -- return TRUE if this address is empty (``<>'')
+**
+** Parameters:
+** a -- pointer to the address
+**
+** Returns:
+** TRUE -- if this address is "empty" (i.e., no one should
+** ever generate replies to it.
+** FALSE -- if it is a "regular" (read: replyable) address.
+*/
+
+bool
+emptyaddr(a)
+ register ADDRESS *a;
+{
+ return a->q_paddr == NULL || strcmp(a->q_paddr, "<>") == 0 ||
+ a->q_user == NULL || strcmp(a->q_user, "<>") == 0;
+}
+ /*
+** REMOTENAME -- return the name relative to the current mailer
+**
+** Parameters:
+** name -- the name to translate.
+** m -- the mailer that we want to do rewriting relative
+** to.
+** flags -- fine tune operations.
+** pstat -- pointer to status word.
+** e -- the current envelope.
+**
+** Returns:
+** the text string representing this address relative to
+** the receiving mailer.
+**
+** Side Effects:
+** none.
+**
+** Warnings:
+** The text string returned is tucked away locally;
+** copy it if you intend to save it.
+*/
+
+char *
+remotename(name, m, flags, pstat, e)
+ char *name;
+ struct mailer *m;
+ int flags;
+ int *pstat;
+ register ENVELOPE *e;
+{
+ register char **pvp;
+ char *fancy;
+ char *oldg = macvalue('g', e);
+ int rwset;
+ static char buf[MAXNAME + 1];
+ char lbuf[MAXNAME + 1];
+ char pvpbuf[PSBUFSIZE];
+ extern char *crackaddr();
+
+ if (tTd(12, 1))
+ printf("remotename(%s)\n", name);
+
+ /* don't do anything if we are tagging it as special */
+ 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);
+
+ /*
+ ** Do a heuristic crack of this name to extract any comment info.
+ ** This will leave the name as a comment and a $g macro.
+ */
+
+ if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags))
+ fancy = "\201g";
+ else
+ fancy = crackaddr(name);
+
+ /*
+ ** Turn the name into canonical form.
+ ** Normally this will be RFC 822 style, i.e., "user@domain".
+ ** If this only resolves to "user", and the "C" flag is
+ ** specified in the sending mailer, then the sender's
+ ** domain will be appended.
+ */
+
+ pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
+ if (pvp == NULL)
+ return (name);
+ if (rewrite(pvp, 3, 0, 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;
+
+ /* see if there is an "@domain" in the current name */
+ while (*pxp != NULL && strcmp(*pxp, "@") != 0)
+ pxp++;
+ if (*pxp == NULL)
+ {
+ /* no.... append the "@domain" from the sender */
+ register char **qxq = e->e_fromdomain;
+
+ while ((*pxp++ = *qxq++) != NULL)
+ continue;
+ if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
+ }
+
+ /*
+ ** Do more specific rewriting.
+ ** Rewrite using ruleset 1 or 2 depending on whether this is
+ ** a sender address or not.
+ ** Then run it through any receiving-mailer-specific rulesets.
+ */
+
+ if (bitset(RF_SENDERADDR, flags))
+ {
+ if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
+ else
+ {
+ if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
+ if (rwset > 0)
+ {
+ if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+ }
+
+ /*
+ ** Do any final sanitation the address may require.
+ ** This will normally be used to turn internal forms
+ ** (e.g., user@host.LOCAL) into external form. This
+ ** may be used as a default to the above rules.
+ */
+
+ if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
+ *pstat = EX_TEMPFAIL;
+
+ /*
+ ** Now restore the comment information we had at the beginning.
+ */
+
+ cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
+ define('g', lbuf, e);
+
+ /* need to make sure route-addrs have <angle brackets> */
+ if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
+ expand("<\201g>", buf, sizeof buf, e);
+ else
+ expand(fancy, buf, sizeof buf, e);
+
+ define('g', oldg, e);
+
+ if (tTd(12, 1))
+ printf("remotename => `%s'\n", buf);
+ return (buf);
+}
+ /*
+** 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.
+** aliaslevel -- the alias nesting depth.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+maplocaluser(a, sendq, aliaslevel, e)
+ register ADDRESS *a;
+ ADDRESS **sendq;
+ int aliaslevel;
+ 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, sizeof pvpbuf, &delimptr, NULL);
+ if (pvp == NULL)
+ return;
+
+ (void) rewrite(pvp, 5, 0, e);
+ if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
+ return;
+
+ /* if non-null, mailer destination specified -- has it changed? */
+ a1 = buildaddr(pvp, NULL, 0, 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, RF_COPYALL, a->q_paddr);
+ (void) recipient(a1, sendq, aliaslevel, e);
+}
+ /*
+** 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;
+
+ map->map_mflags |= MF_KEEPQUOTES;
+ for (;;)
+ {
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p != '-')
+ break;
+ switch (*++p)
+ {
+ case 'a':
+ map->map_app = ++p;
+ break;
+
+ case 's':
+ map->map_coldelim = *++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;
+}
+ /*
+** 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 = 0;
+ int cmntcnt = 0;
+ int quotecnt = 0;
+ int spacecnt = 0;
+ bool quotemode = FALSE;
+ bool bslashmode = FALSE;
+ char spacesub = map->map_coldelim;
+
+ for (p = q = name; (c = *p++) != '\0'; )
+ {
+ if (bslashmode)
+ {
+ bslashmode = FALSE;
+ *q++ = c;
+ continue;
+ }
+
+ if (c == ' ' && spacesub != '\0')
+ c = spacesub;
+
+ 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;
+}
diff --git a/usr.sbin/sendmail/src/pathnames.h b/usr.sbin/sendmail/src/pathnames.h
new file mode 100644
index 000000000000..a364fbab33a7
--- /dev/null
+++ b/usr.sbin/sendmail/src/pathnames.h
@@ -0,0 +1,54 @@
+/*-
+ * 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
+ * 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.
+ *
+ * @(#)pathnames.h 8.4 (Berkeley) 6/19/95
+ */
+
+#ifndef _PATH_SENDMAILCF
+# if defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF)
+# define _PATH_SENDMAILCF _PATH_VENDOR_CF
+# else
+# define _PATH_SENDMAILCF "/etc/sendmail.cf"
+# endif
+#endif
+
+#ifndef _PATH_SENDMAILPID
+# ifdef BSD4_4
+# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
+# else
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+#ifndef _PATH_HOSTS
+# define _PATH_HOSTS "/etc/hosts"
+#endif
diff --git a/usr.sbin/sendmail/src/queue.c b/usr.sbin/sendmail/src/queue.c
new file mode 100644
index 000000000000..97bf36cd8086
--- /dev/null
+++ b/usr.sbin/sendmail/src/queue.c
@@ -0,0 +1,2071 @@
+/*
+ * Copyright (c) 1983, 1995 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 QUEUE
+static char sccsid[] = "@(#)queue.c 8.98 (Berkeley) 11/11/95 (with queueing)";
+#else
+static char sccsid[] = "@(#)queue.c 8.98 (Berkeley) 11/11/95 (without queueing)";
+#endif
+#endif /* not lint */
+
+# include <errno.h>
+# include <dirent.h>
+
+# ifdef QUEUE
+
+/*
+** Work queue.
+*/
+
+struct work
+{
+ char *w_name; /* name of control file */
+ char *w_host; /* name of recipient host */
+ bool w_lock; /* is message locked? */
+ bool w_tooyoung; /* is it too young to run? */
+ long w_pri; /* priority of message, see below */
+ time_t w_ctime; /* creation time of message */
+ struct work *w_next; /* next in queue */
+};
+
+typedef struct work WORK;
+
+WORK *WorkQ; /* queue of things to be done */
+
+#define QF_VERSION 1 /* version number of this queue format */
+
+#if !defined(NGROUPS_MAX) && defined(NGROUPS)
+# define NGROUPS_MAX NGROUPS /* POSIX naming convention */
+#endif
+ /*
+** QUEUEUP -- queue a message up for future transmission.
+**
+** Parameters:
+** e -- the envelope to queue up.
+** announce -- if TRUE, tell when you are queueing up.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** The current request are saved in a control file.
+** The queue file is left locked.
+*/
+
+void
+queueup(e, announce)
+ register ENVELOPE *e;
+ bool announce;
+{
+ char *qf;
+ register FILE *tfp;
+ register HDR *h;
+ register ADDRESS *q;
+ int fd;
+ int i;
+ bool newid;
+ register char *p;
+ MAILER nullmailer;
+ MCI mcibuf;
+ char buf[MAXLINE], tf[MAXLINE];
+ extern void printctladdr __P((ADDRESS *, FILE *));
+
+ /*
+ ** Create control file.
+ */
+
+ newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
+
+ /* if newid, queuename will create a locked qf file in e->lockfp */
+ strcpy(tf, queuename(e, 't'));
+ tfp = e->e_lockfp;
+ if (tfp == NULL)
+ newid = FALSE;
+
+ /* if newid, just write the qf file directly (instead of tf file) */
+ if (!newid)
+ {
+ /* get a locked tf file */
+ for (i = 0; i < 128; i++)
+ {
+ fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
+ if (fd < 0)
+ {
+ if (errno != EEXIST)
+ break;
+#ifdef LOG
+ if (LogLevel > 0 && (i % 32) == 0)
+ syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s",
+ tf, geteuid(), errstring(errno));
+#endif
+ }
+ else
+ {
+ if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
+ break;
+#ifdef LOG
+ else if (LogLevel > 0 && (i % 32) == 0)
+ syslog(LOG_ALERT, "queueup: cannot lock %s: %s",
+ tf, errstring(errno));
+#endif
+ close(fd);
+ }
+
+ if ((i % 32) == 31)
+ {
+ /* save the old temp file away */
+ (void) rename(tf, queuename(e, 'T'));
+ }
+ else
+ sleep(i % 32);
+ }
+ if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL)
+ {
+ printopenfds(TRUE);
+ syserr("!queueup: cannot create queue temp file %s, uid=%d",
+ tf, geteuid());
+ }
+ }
+
+ if (tTd(40, 1))
+ printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id,
+ newid ? " (new id)" : "");
+ if (tTd(40, 3))
+ {
+ extern void printenvflags();
+
+ printf(" e_flags=");
+ printenvflags(e);
+ }
+ if (tTd(40, 32))
+ {
+ printf(" sendq=");
+ printaddr(e->e_sendqueue, TRUE);
+ }
+ if (tTd(40, 9))
+ {
+ printf(" tfp=");
+ dumpfd(fileno(tfp), TRUE, FALSE);
+ printf(" lockfp=");
+ if (e->e_lockfp == NULL)
+ printf("NULL\n");
+ else
+ dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
+ }
+
+ /*
+ ** If there is no data file yet, create one.
+ */
+
+ if (!bitset(EF_HAS_DF, e->e_flags))
+ {
+ register FILE *dfp;
+ char dfname[20];
+ struct stat stbuf;
+
+ strcpy(dfname, queuename(e, 'd'));
+ fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode);
+ if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL)
+ syserr("!queueup: cannot create data temp file %s, uid=%d",
+ dfname, geteuid());
+ if (fstat(fd, &stbuf) < 0)
+ e->e_dfino = -1;
+ else
+ {
+ e->e_dfdev = stbuf.st_dev;
+ e->e_dfino = stbuf.st_ino;
+ }
+ e->e_flags |= EF_HAS_DF;
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_out = dfp;
+ mcibuf.mci_mailer = FileMailer;
+ (*e->e_putbody)(&mcibuf, e, NULL);
+ (void) xfclose(dfp, "queueup dfp", e->e_id);
+ e->e_putbody = putbody;
+ }
+
+ /*
+ ** Output future work requests.
+ ** Priority and creation time should be first, since
+ ** they are required by orderq.
+ */
+
+ /* output queue version number (must be first!) */
+ fprintf(tfp, "V%d\n", QF_VERSION);
+
+ /* output creation time */
+ fprintf(tfp, "T%ld\n", e->e_ctime);
+
+ /* output last delivery time */
+ fprintf(tfp, "K%ld\n", e->e_dtime);
+
+ /* output number of delivery attempts */
+ fprintf(tfp, "N%d\n", e->e_ntries);
+
+ /* output message priority */
+ fprintf(tfp, "P%ld\n", e->e_msgpriority);
+
+ /* output inode number of data file */
+ /* XXX should probably include device major/minor too */
+ if (e->e_dfino != -1)
+ fprintf(tfp, "I%d/%d/%ld\n",
+ major(e->e_dfdev), minor(e->e_dfdev), e->e_dfino);
+
+ /* output body type */
+ if (e->e_bodytype != NULL)
+ fprintf(tfp, "B%s\n", e->e_bodytype);
+
+ /* message from envelope, if it exists */
+ if (e->e_message != NULL)
+ fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
+
+ /* 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';
+ if (bitset(EF_HAS8BIT, e->e_flags))
+ *p++ = '8';
+ *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", denlstring(p, TRUE, FALSE));
+ if ((p = macvalue('s', e)) != NULL)
+ fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE));
+ if ((p = macvalue('_', e)) != NULL)
+ fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE));
+
+ /* output name of sender */
+ if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
+ p = e->e_sender;
+ else
+ p = e->e_from.q_paddr;
+ fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE));
+
+ /* output ESMTP-supplied "original" information */
+ if (e->e_envid != NULL)
+ fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE));
+
+ /* output list of recipient addresses */
+ printctladdr(NULL, NULL);
+ for (q = e->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QQUEUEUP, q->q_flags) ||
+ !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
+ {
+ printctladdr(q, tfp);
+ if (q->q_orcpt != NULL)
+ fprintf(tfp, "Q%s\n",
+ denlstring(q->q_orcpt, TRUE, FALSE));
+ putc('R', tfp);
+ if (bitset(QPRIMARY, q->q_flags))
+ putc('P', tfp);
+ if (bitset(QPINGONSUCCESS, q->q_flags))
+ putc('S', tfp);
+ if (bitset(QPINGONFAILURE, q->q_flags))
+ putc('F', tfp);
+ if (bitset(QPINGONDELAY, q->q_flags))
+ putc('D', tfp);
+ putc(':', tfp);
+ fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
+ if (announce)
+ {
+ e->e_to = q->q_paddr;
+ message("queued");
+ if (LogLevel > 8)
+ logdelivery(q->q_mailer, NULL, "queued",
+ NULL, (time_t) 0, e);
+ e->e_to = NULL;
+ }
+ if (tTd(40, 1))
+ {
+ printf("queueing ");
+ printaddr(q, FALSE);
+ }
+ }
+ }
+
+ /*
+ ** Output headers for this message.
+ ** Expand macros completely here. Queue run will deal with
+ ** everything as absolute headers.
+ ** All headers that must be relative to the recipient
+ ** can be cracked later.
+ ** We set up a "null mailer" -- i.e., a mailer that will have
+ ** no effect on the addresses as they are output.
+ */
+
+ bzero((char *) &nullmailer, sizeof nullmailer);
+ nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
+ nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
+ nullmailer.m_eol = "\n";
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_mailer = &nullmailer;
+ mcibuf.mci_out = tfp;
+
+ define('g', "\201f", e);
+ for (h = e->e_header; h != NULL; h = h->h_link)
+ {
+ extern bool bitzerop();
+
+ /* don't output null headers */
+ if (h->h_value == NULL || h->h_value[0] == '\0')
+ continue;
+
+ /* don't output resent headers on non-resent messages */
+ if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
+ continue;
+
+ /* expand macros; if null, don't output header at all */
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ (void) expand(h->h_value, buf, sizeof buf, e);
+ if (buf[0] == '\0')
+ continue;
+ }
+
+ /* output this header */
+ fprintf(tfp, "H");
+
+ /* if conditional, output the set of conditions */
+ if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags))
+ {
+ int j;
+
+ (void) putc('?', tfp);
+ for (j = '\0'; j <= '\177'; j++)
+ if (bitnset(j, h->h_mflags))
+ (void) putc(j, tfp);
+ (void) putc('?', tfp);
+ }
+
+ /* output the header: expand macros, convert addresses */
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ fprintf(tfp, "%s: %s\n", h->h_field, buf);
+ }
+ else if (bitset(H_FROM|H_RCPT, h->h_flags))
+ {
+ bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
+ FILE *savetrace = TrafficLogFile;
+
+ TrafficLogFile = NULL;
+
+ if (bitset(H_FROM, h->h_flags))
+ oldstyle = FALSE;
+
+ commaize(h, h->h_value, oldstyle, &mcibuf, e);
+
+ TrafficLogFile = savetrace;
+ }
+ else
+ fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);
+ }
+
+ /*
+ ** Clean up.
+ **
+ ** Write a terminator record -- this is to prevent
+ ** scurrilous crackers from appending any data.
+ */
+
+ fprintf(tfp, ".\n");
+
+ if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp))
+ {
+ if (newid)
+ syserr("!552 Error writing control file %s", tf);
+ else
+ syserr("!452 Error writing control file %s", tf);
+ }
+
+ if (!newid)
+ {
+ /* rename (locked) tf to be (locked) qf */
+ qf = queuename(e, 'q');
+ if (rename(tf, qf) < 0)
+ syserr("cannot rename(%s, %s), uid=%d",
+ tf, qf, geteuid());
+
+ /* close and unlock old (locked) qf */
+ if (e->e_lockfp != NULL)
+ (void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);
+ e->e_lockfp = tfp;
+ }
+ else
+ qf = tf;
+ errno = 0;
+ e->e_flags |= EF_INQUEUE;
+
+# ifdef LOG
+ /* save log info */
+ if (LogLevel > 79)
+ syslog(LOG_DEBUG, "%s: queueup, qf=%s", e->e_id, qf);
+# endif /* LOG */
+
+ if (tTd(40, 1))
+ printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
+ return;
+}
+
+void
+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 || a->q_alias == 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;
+ 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 = sm_getpwuid(uid)) == NULL)
+ uname = "";
+ else
+ uname = pw->pw_name;
+
+ fprintf(tfp, "C%s:%s\n", uname, denlstring(a->q_paddr, TRUE, FALSE));
+}
+ /*
+** RUNQUEUE -- run the jobs in the queue.
+**
+** Gets the stuff out of the queue in some presumably logical
+** order and processes them.
+**
+** Parameters:
+** forkflag -- TRUE if the queue scanning should be done in
+** a child process. We double-fork so it is not our
+** child and we don't have to clean up after it.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** runs things in the mail queue.
+*/
+
+ENVELOPE QueueEnvelope; /* the queue run envelope */
+
+void
+runqueue(forkflag)
+ bool forkflag;
+{
+ register ENVELOPE *e;
+ int njobs;
+ int sequenceno = 0;
+ extern ENVELOPE BlankEnvelope;
+
+ /*
+ ** If no work will ever be selected, don't even bother reading
+ ** the queue.
+ */
+
+ CurrentLA = getla(); /* get load average */
+
+ if (shouldqueue(0L, curtime()))
+ {
+ char *msg = "Skipping queue run -- load average too high";
+
+ if (Verbose)
+ printf("%s\n", msg);
+#ifdef LOG
+ if (LogLevel > 8)
+ syslog(LOG_INFO, "runqueue: %s", msg);
+#endif
+ if (forkflag && QueueIntvl != 0)
+ (void) setevent(QueueIntvl, runqueue, TRUE);
+ return;
+ }
+
+ /*
+ ** See if we want to go off and do other useful work.
+ */
+
+ if (forkflag)
+ {
+ int pid;
+ extern void intsig();
+#ifdef SIGCHLD
+ extern void reapchild();
+
+ (void) setsignal(SIGCHLD, reapchild);
+#endif
+
+ pid = dofork();
+ if (pid != 0)
+ {
+ /* parent -- pick up intermediate zombie */
+#ifndef SIGCHLD
+ (void) waitfor(pid);
+#else
+ CurChildren++;
+#endif /* SIGCHLD */
+ if (QueueIntvl != 0)
+ (void) setevent(QueueIntvl, runqueue, TRUE);
+ return;
+ }
+ /* child -- double fork and clean up signals */
+#ifndef SIGCHLD
+ if (fork() != 0)
+ exit(EX_OK);
+#else /* SIGCHLD */
+ (void) setsignal(SIGCHLD, SIG_DFL);
+#endif /* SIGCHLD */
+ (void) setsignal(SIGHUP, intsig);
+ }
+
+ setproctitle("running queue: %s", QueueDir);
+
+# ifdef 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.
+ */
+
+# ifdef DAEMON
+ clrdaemon();
+# endif /* DAEMON */
+
+ /* force it to run expensive jobs */
+ NoConnect = FALSE;
+
+ /*
+ ** Create ourselves an envelope
+ */
+
+ CurEnv = &QueueEnvelope;
+ e = newenvelope(&QueueEnvelope, CurEnv);
+ e->e_flags = BlankEnvelope.e_flags;
+
+ /*
+ ** Make sure the alias database is open.
+ */
+
+ initmaps(FALSE, e);
+
+ /*
+ ** Start making passes through the queue.
+ ** First, read and sort the entire queue.
+ ** Then, process the work in that order.
+ ** But if you take too long, start over.
+ */
+
+ /* order the existing work requests */
+ njobs = orderq(FALSE);
+
+ /* process them once at a time */
+ while (WorkQ != NULL)
+ {
+ WORK *w = WorkQ;
+
+ WorkQ = WorkQ->w_next;
+
+ /*
+ ** Ignore jobs that are too expensive for the moment.
+ */
+
+ sequenceno++;
+ if (shouldqueue(w->w_pri, w->w_ctime))
+ {
+ if (Verbose)
+ printf("\nSkipping %s (sequence %d of %d)\n",
+ w->w_name + 2, sequenceno, njobs);
+ }
+ else
+ {
+ pid_t pid;
+ extern pid_t dowork();
+
+ if (Verbose)
+ printf("\nRunning %s (sequence %d of %d)\n",
+ w->w_name + 2, sequenceno, njobs);
+ pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
+ errno = 0;
+ if (pid != 0)
+ (void) waitfor(pid);
+ }
+ free(w->w_name);
+ if (w->w_host)
+ free(w->w_host);
+ free((char *) w);
+ }
+
+ /* exit without the usual cleanup */
+ e->e_id = NULL;
+ finis();
+}
+ /*
+** ORDERQ -- order the work queue.
+**
+** Parameters:
+** doall -- if set, include everything in the queue (even
+** the jobs that cannot be run because the load
+** average is too high). Otherwise, exclude those
+** jobs.
+**
+** Returns:
+** The number of request in the queue (not necessarily
+** the number of requests in WorkQ however).
+**
+** Side Effects:
+** Sets WorkQ to the queue of available work, in order.
+*/
+
+# define NEED_P 001
+# define NEED_T 002
+# define NEED_R 004
+# define NEED_S 010
+
+static WORK *WorkList = NULL;
+static int WorkListSize = 0;
+
+int
+orderq(doall)
+ bool doall;
+{
+ register struct dirent *d;
+ register WORK *w;
+ DIR *f;
+ register int i;
+ int wn = -1;
+ int wc;
+
+ 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; )
+ {
+ register WORK *nw = w->w_next;
+
+ WorkQ = nw;
+ free(w->w_name);
+ if (w->w_host)
+ free(w->w_host);
+ free((char *) w);
+ w = nw;
+ }
+
+ /* open the queue directory */
+ f = opendir(".");
+ if (f == NULL)
+ {
+ syserr("orderq: cannot open \"%s\" as \".\"", QueueDir);
+ return (0);
+ }
+
+ /*
+ ** Read the work directory.
+ */
+
+ while ((d = readdir(f)) != NULL)
+ {
+ FILE *cf;
+ register char *p;
+ char lbuf[MAXNAME + 1];
+ extern bool strcontainedin();
+
+ if (tTd(41, 50))
+ printf("orderq: checking %s\n", d->d_name);
+
+ /* 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;
+
+#ifdef PICKY_QF_NAME_CHECK
+ /*
+ ** Check queue name for plausibility. This handles
+ ** both old and new type ids.
+ */
+
+ p = d->d_name + 2;
+ if (isupper(p[0]) && isupper(p[2]))
+ p += 3;
+ else if (isupper(p[1]))
+ p += 2;
+ else
+ p = d->d_name;
+ for (i = 0; isdigit(*p); p++)
+ i++;
+ if (i < 5 || *p != '\0')
+ {
+ if (Verbose)
+ printf("orderq: bogus qf name %s\n", d->d_name);
+# ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT, "orderq: bogus qf name %s",
+ d->d_name);
+# endif
+ if (strlen(d->d_name) > (SIZE_T) MAXNAME)
+ d->d_name[MAXNAME] = '\0';
+ strcpy(lbuf, d->d_name);
+ lbuf[0] = 'Q';
+ (void) rename(d->d_name, lbuf);
+ continue;
+ }
+#endif
+
+ /* open control file (if not too many files) */
+ if (++wn >= MaxQueueRun && MaxQueueRun > 0)
+ {
+# ifdef LOG
+ if (wn == MaxQueueRun && LogLevel > 0)
+ syslog(LOG_ALERT, "WorkList for %s maxed out at %d",
+ QueueDir, MaxQueueRun);
+# endif
+ continue;
+ }
+ if (wn >= WorkListSize)
+ {
+ extern void grow_wlist __P((void));
+
+ grow_wlist();
+ if (wn >= WorkListSize)
+ continue;
+ }
+
+ cf = fopen(d->d_name, "r");
+ if (cf == NULL)
+ {
+ /* this may be some random person sending hir msgs */
+ /* syserr("orderq: cannot open %s", cbuf); */
+ if (tTd(41, 2))
+ printf("orderq: cannot open %s: %s\n",
+ d->d_name, errstring(errno));
+ errno = 0;
+ wn--;
+ continue;
+ }
+ w = &WorkList[wn];
+ w->w_name = newstr(d->d_name);
+ w->w_host = NULL;
+ w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB);
+ w->w_tooyoung = FALSE;
+
+ /* make sure jobs in creation don't clog queue */
+ w->w_pri = 0x7fffffff;
+ w->w_ctime = 0;
+
+ /* extract useful information */
+ i = NEED_P | NEED_T;
+ if (QueueLimitSender != NULL)
+ i |= NEED_S;
+ if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL)
+ i |= NEED_R;
+ while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
+ {
+ extern bool strcontainedin();
+
+ switch (lbuf[0])
+ {
+ case 'P':
+ w->w_pri = atol(&lbuf[1]);
+ i &= ~NEED_P;
+ break;
+
+ case 'T':
+ w->w_ctime = atol(&lbuf[1]);
+ i &= ~NEED_T;
+ break;
+
+ case 'R':
+ if (w->w_host == NULL &&
+ (p = strrchr(&lbuf[1], '@')) != NULL)
+ w->w_host = newstr(&p[1]);
+ if (QueueLimitRecipient == NULL ||
+ strcontainedin(QueueLimitRecipient, &lbuf[1]))
+ i &= ~NEED_R;
+ break;
+
+ case 'S':
+ if (QueueLimitSender != NULL &&
+ strcontainedin(QueueLimitSender, &lbuf[1]))
+ i &= ~NEED_S;
+ break;
+
+ case 'K':
+ if ((curtime() - (time_t) atol(&lbuf[1])) < MinQueueAge)
+ w->w_tooyoung = TRUE;
+ break;
+
+ case 'N':
+ if (atol(&lbuf[1]) == 0)
+ w->w_tooyoung = FALSE;
+ break;
+ }
+ }
+ (void) fclose(cf);
+
+ if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
+ bitset(NEED_R|NEED_S, i))
+ {
+ /* don't even bother sorting this job in */
+ if (tTd(41, 49))
+ printf("skipping %s (%x)\n", w->w_name, i);
+ free(w->w_name);
+ if (w->w_host)
+ free(w->w_host);
+ wn--;
+ }
+ }
+ (void) closedir(f);
+ wn++;
+
+ wc = min(wn, WorkListSize);
+ if (wc > MaxQueueRun && MaxQueueRun > 0)
+ wc = MaxQueueRun;
+
+ if (QueueSortOrder == QS_BYHOST)
+ {
+ extern workcmpf1();
+ extern workcmpf2();
+
+ /*
+ ** Sort the work directory for the first time,
+ ** based on host name, lock status, and priority.
+ */
+
+ qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
+
+ /*
+ ** If one message to host is locked, "lock" all messages
+ ** to that host.
+ */
+
+ i = 0;
+ while (i < wc)
+ {
+ if (!WorkList[i].w_lock)
+ {
+ i++;
+ continue;
+ }
+ w = &WorkList[i];
+ while (++i < wc)
+ {
+ if (WorkList[i].w_host == NULL &&
+ w->w_host == NULL)
+ WorkList[i].w_lock = TRUE;
+ else if (WorkList[i].w_host != NULL &&
+ w->w_host != NULL &&
+ strcmp(WorkList[i].w_host, w->w_host) == 0)
+ WorkList[i].w_lock = TRUE;
+ else
+ break;
+ }
+ }
+
+ /*
+ ** Sort the work directory for the second time,
+ ** based on lock status, host name, and priority.
+ */
+
+ qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
+ }
+ else
+ {
+ extern workcmpf0();
+
+ /*
+ ** Simple sort based on queue priority only.
+ */
+
+ qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
+ }
+
+ /*
+ ** Convert the work list into canonical form.
+ ** Should be turning it into a list of envelopes here perhaps.
+ */
+
+ WorkQ = NULL;
+ for (i = wc; --i >= 0; )
+ {
+ w = (WORK *) xalloc(sizeof *w);
+ w->w_name = WorkList[i].w_name;
+ w->w_host = WorkList[i].w_host;
+ w->w_lock = WorkList[i].w_lock;
+ w->w_tooyoung = WorkList[i].w_tooyoung;
+ w->w_pri = WorkList[i].w_pri;
+ w->w_ctime = WorkList[i].w_ctime;
+ w->w_next = WorkQ;
+ WorkQ = w;
+ }
+ if (WorkList != NULL)
+ free(WorkList);
+ WorkList = NULL;
+
+ if (tTd(40, 1))
+ {
+ for (w = WorkQ; w != NULL; w = w->w_next)
+ printf("%32s: pri=%ld\n", w->w_name, w->w_pri);
+ }
+
+ return (wn);
+}
+ /*
+** GROW_WLIST -- make the work list larger
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Adds another QUEUESEGSIZE entries to WorkList if possible.
+** It can fail if there isn't enough memory, so WorkListSize
+** should be checked again upon return.
+*/
+
+void
+grow_wlist()
+{
+ if (tTd(41, 1))
+ printf("grow_wlist: WorkListSize=%d\n", WorkListSize);
+ if (WorkList == NULL)
+ {
+ WorkList = (WORK *) xalloc(sizeof(WORK) * (QUEUESEGSIZE + 1));
+ WorkListSize = QUEUESEGSIZE;
+ }
+ else
+ {
+ int newsize = WorkListSize + QUEUESEGSIZE;
+ WORK *newlist = (WORK *) realloc((char *)WorkList,
+ (unsigned)sizeof(WORK) * (newsize + 1));
+
+ if (newlist != NULL)
+ {
+ WorkListSize = newsize;
+ WorkList = newlist;
+# ifdef LOG
+ if (LogLevel > 1)
+ {
+ syslog(LOG_NOTICE, "grew WorkList for %s to %d",
+ QueueDir, WorkListSize);
+ }
+ }
+ else if (LogLevel > 0)
+ {
+ syslog(LOG_ALERT, "FAILED to grow WorkList for %s to %d",
+ QueueDir, newsize);
+# endif
+ }
+ }
+ if (tTd(41, 1))
+ printf("grow_wlist: WorkListSize now %d\n", WorkListSize);
+}
+ /*
+** WORKCMPF0 -- simple priority-only compare function.
+**
+** Parameters:
+** a -- the first argument.
+** b -- the second argument.
+**
+** Returns:
+** -1 if a < b
+** 0 if a == b
+** +1 if a > b
+**
+** Side Effects:
+** none.
+*/
+
+int
+workcmpf0(a, b)
+ register WORK *a;
+ register WORK *b;
+{
+ long pa = a->w_pri;
+ long pb = b->w_pri;
+
+ if (pa == pb)
+ return 0;
+ else if (pa > pb)
+ return 1;
+ else
+ return -1;
+}
+ /*
+** WORKCMPF1 -- first compare function for ordering work based on host name.
+**
+** Sorts on host name, lock status, and priority in that order.
+**
+** Parameters:
+** a -- the first argument.
+** b -- the second argument.
+**
+** Returns:
+** <0 if a < b
+** 0 if a == b
+** >0 if a > b
+**
+** Side Effects:
+** none.
+*/
+
+int
+workcmpf1(a, b)
+ register WORK *a;
+ register WORK *b;
+{
+ int i;
+
+ /* host name */
+ if (a->w_host != NULL && b->w_host == NULL)
+ return 1;
+ else if (a->w_host == NULL && b->w_host != NULL)
+ return -1;
+ if (a->w_host != NULL && b->w_host != NULL &&
+ (i = strcmp(a->w_host, b->w_host)))
+ return i;
+
+ /* lock status */
+ if (a->w_lock != b->w_lock)
+ return b->w_lock - a->w_lock;
+
+ /* job priority */
+ return a->w_pri - b->w_pri;
+}
+ /*
+** WORKCMPF2 -- second compare function for ordering work based on host name.
+**
+** Sorts on lock status, host name, and priority in that order.
+**
+** Parameters:
+** a -- the first argument.
+** b -- the second argument.
+**
+** Returns:
+** <0 if a < b
+** 0 if a == b
+** >0 if a > b
+**
+** Side Effects:
+** none.
+*/
+
+int
+workcmpf2(a, b)
+ register WORK *a;
+ register WORK *b;
+{
+ int i;
+
+ /* lock status */
+ if (a->w_lock != b->w_lock)
+ return a->w_lock - b->w_lock;
+
+ /* host name */
+ if (a->w_host != NULL && b->w_host == NULL)
+ return 1;
+ else if (a->w_host == NULL && b->w_host != NULL)
+ return -1;
+ if (a->w_host != NULL && b->w_host != NULL &&
+ (i = strcmp(a->w_host, b->w_host)))
+ return i;
+
+ /* job priority */
+ return a->w_pri - b->w_pri;
+}
+ /*
+** DOWORK -- do a work request.
+**
+** Parameters:
+** 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:
+** process id of process that is running the queue job.
+**
+** Side Effects:
+** The work request is satisfied if possible.
+*/
+
+pid_t
+dowork(id, forkflag, requeueflag, e)
+ char *id;
+ bool forkflag;
+ bool requeueflag;
+ register ENVELOPE *e;
+{
+ register pid_t pid;
+ extern bool readqf();
+
+ if (tTd(40, 1))
+ printf("dowork(%s)\n", id);
+
+ /*
+ ** Fork for work.
+ */
+
+ if (forkflag)
+ {
+ pid = fork();
+ if (pid < 0)
+ {
+ syserr("dowork: cannot fork");
+ return 0;
+ }
+ else if (pid > 0)
+ {
+ /* parent -- clean out connection cache */
+ mci_flush(FALSE, NULL);
+ }
+ }
+ else
+ {
+ pid = 0;
+ }
+
+ if (pid == 0)
+ {
+ /*
+ ** CHILD
+ ** Lock the control file to avoid duplicate deliveries.
+ ** Then run the file as though we had just read it.
+ ** We save an idea of the temporary name so we
+ ** can recover on interrupt.
+ */
+
+ /* set basic modes, etc. */
+ (void) alarm(0);
+ clearenvelope(e, FALSE);
+ e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
+ e->e_sendmode = SM_DELIVER;
+ e->e_errormode = EM_MAIL;
+ e->e_id = id;
+ GrabTo = UseErrorsTo = FALSE;
+ ExitStat = EX_OK;
+ if (forkflag)
+ {
+ disconnect(1, e);
+ OpMode = MD_DELIVER;
+ }
+# ifdef LOG
+ if (LogLevel > 76)
+ syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id,
+ getpid());
+# endif /* LOG */
+
+ /* don't use the headers from sendmail.cf... */
+ e->e_header = NULL;
+
+ /* read the queue control file -- return if locked */
+ if (!readqf(e))
+ {
+ if (tTd(40, 4))
+ printf("readqf(%s) failed\n", e->e_id);
+ if (forkflag)
+ exit(EX_OK);
+ else
+ return 0;
+ }
+
+ e->e_flags |= EF_INQUEUE;
+ eatheader(e, requeueflag);
+
+ if (requeueflag)
+ queueup(e, FALSE);
+
+ /* do the delivery */
+ sendall(e, SM_DELIVER);
+
+ /* finish up and exit */
+ if (forkflag)
+ finis();
+ else
+ dropenvelope(e);
+ }
+ e->e_id = NULL;
+ return pid;
+}
+ /*
+** READQF -- read queue file and set up environment.
+**
+** Parameters:
+** e -- the envelope of the job to run.
+**
+** Returns:
+** TRUE if it successfully read the queue file.
+** FALSE otherwise.
+**
+** Side Effects:
+** The queue file is returned locked.
+*/
+
+bool
+readqf(e)
+ register ENVELOPE *e;
+{
+ register FILE *qfp;
+ ADDRESS *ctladdr;
+ struct stat st;
+ char *bp;
+ int qfver = 0;
+ register char *p;
+ char *orcpt = NULL;
+ bool nomore = FALSE;
+ char qf[20];
+ char buf[MAXLINE];
+ extern ADDRESS *setctluser();
+ extern void loseqfile();
+
+ /*
+ ** Read and process the file.
+ */
+
+ strcpy(qf, queuename(e, 'q'));
+ qfp = fopen(qf, "r+");
+ 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);
+ return FALSE;
+ }
+
+ if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
+ {
+ /* being processed by another queuer */
+ if (Verbose || tTd(40, 8))
+ 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);
+ return FALSE;
+ }
+
+ /*
+ ** 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() || bitset(S_IWOTH|S_IWGRP, st.st_mode))
+ {
+# 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);
+ loseqfile(e, "bogus file uid in mqueue");
+ fclose(qfp);
+ return FALSE;
+ }
+
+ if (st.st_size == 0)
+ {
+ /* must be a bogus file -- just remove it */
+ (void) unlink(qf);
+ fclose(qfp);
+ return FALSE;
+ }
+
+ if (st.st_nlink == 0)
+ {
+ /*
+ ** Race condition -- we got a file just as it was being
+ ** unlinked. Just assume it is zero length.
+ */
+
+ fclose(qfp);
+ return FALSE;
+ }
+
+ /* good file -- save this lock */
+ e->e_lockfp = qfp;
+
+ /* do basic system initialization */
+ initsys(e);
+ define('i', e->e_id, e);
+
+ LineNumber = 0;
+ e->e_flags |= EF_GLOBALERRS;
+ OpMode = MD_DELIVER;
+ ctladdr = NULL;
+ e->e_dfino = -1;
+ e->e_msgsize = -1;
+ while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
+ {
+ register char *p;
+ u_long qflags;
+ ADDRESS *q;
+
+ if (tTd(40, 4))
+ printf("+++++ %s\n", bp);
+ if (nomore)
+ {
+ /* hack attack */
+ syserr("SECURITY ALERT: extra data in qf: %s", bp);
+ fclose(qfp);
+ loseqfile(e, "bogus queue line");
+ return FALSE;
+ }
+ switch (bp[0])
+ {
+ case 'V': /* queue file version number */
+ qfver = atoi(&bp[1]);
+ if (qfver > QF_VERSION)
+ {
+ syserr("Version number in qf (%d) greater than max (%d)",
+ qfver, QF_VERSION);
+ }
+ break;
+
+ case 'C': /* specify controlling user */
+ ctladdr = setctluser(&bp[1]);
+ break;
+
+ case 'Q': /* original recipient */
+ orcpt = newstr(&bp[1]);
+ break;
+
+ case 'R': /* specify recipient */
+ p = bp;
+ qflags = 0;
+ if (qfver >= 1)
+ {
+ /* get flag bits */
+ while (*++p != '\0' && *p != ':')
+ {
+ switch (*p)
+ {
+ case 'S':
+ qflags |= QPINGONSUCCESS;
+ break;
+
+ case 'F':
+ qflags |= QPINGONFAILURE;
+ break;
+
+ case 'D':
+ qflags |= QPINGONDELAY;
+ break;
+
+ case 'P':
+ qflags |= QPRIMARY;
+ break;
+ }
+ }
+ }
+ else
+ qflags |= QPRIMARY;
+ q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e);
+ if (q != NULL)
+ {
+ q->q_alias = ctladdr;
+ q->q_flags |= qflags;
+ q->q_orcpt = orcpt;
+ (void) recipient(q, &e->e_sendqueue, 0, e);
+ }
+ orcpt = NULL;
+ break;
+
+ case 'E': /* specify error recipient */
+ /* no longer used */
+ break;
+
+ case 'H': /* header */
+ (void) chompheader(&bp[1], FALSE, NULL, e);
+ break;
+
+ case 'M': /* message */
+ /* ignore this; we want a new message next time */
+ break;
+
+ case 'S': /* sender */
+ setsender(newstr(&bp[1]), e, NULL, TRUE);
+ break;
+
+ case 'B': /* body type */
+ e->e_bodytype = newstr(&bp[1]);
+ break;
+
+ case 'D': /* data file name */
+ /* obsolete -- ignore */
+ break;
+
+ case 'T': /* init time */
+ e->e_ctime = atol(&bp[1]);
+ break;
+
+ case 'I': /* data file's inode number */
+ if (e->e_dfino == -1)
+ e->e_dfino = atol(&buf[1]);
+ break;
+
+ case 'K': /* time of last deliver attempt */
+ e->e_dtime = atol(&buf[1]);
+ break;
+
+ case 'N': /* number of delivery attempts */
+ e->e_ntries = atoi(&buf[1]);
+ break;
+
+ case 'P': /* message priority */
+ e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
+ break;
+
+ case 'F': /* flag bits */
+ if (strncmp(bp, "From ", 5) == 0)
+ {
+ /* we are being spoofed! */
+ syserr("SECURITY ALERT: bogus qf line %s", bp);
+ fclose(qfp);
+ loseqfile(e, "bogus queue line");
+ return FALSE;
+ }
+ 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;
+
+ case '8': /* has 8 bit data */
+ e->e_flags |= EF_HAS8BIT;
+ break;
+ }
+ }
+ break;
+
+ case 'Z': /* original envelope id from ESMTP */
+ e->e_envid = newstr(&bp[1]);
+ break;
+
+ case '$': /* define macro */
+ define(bp[1], newstr(&bp[2]), e);
+ break;
+
+ case '.': /* terminate file */
+ nomore = TRUE;
+ break;
+
+ default:
+ syserr("readqf: %s: line %d: bad line \"%s\"",
+ qf, LineNumber, bp);
+ fclose(qfp);
+ loseqfile(e, "unrecognized line");
+ return FALSE;
+ }
+
+ if (bp != buf)
+ free(bp);
+ }
+
+ /*
+ ** If we haven't read any lines, this queue file is empty.
+ ** Arrange to remove it without referencing any null pointers.
+ */
+
+ if (LineNumber == 0)
+ {
+ errno = 0;
+ e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
+ return TRUE;
+ }
+
+ /* if this has been tried recently, let it be */
+ if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge)
+ {
+ char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
+ extern void unlockqueue();
+
+ if (Verbose || tTd(40, 8))
+ printf("%s: too young (%s)\n",
+ e->e_id, howlong);
+#ifdef LOG
+ if (LogLevel > 19)
+ syslog(LOG_DEBUG, "%s: too young (%s)",
+ e->e_id, howlong);
+#endif
+ e->e_id = NULL;
+ unlockqueue(e);
+ return FALSE;
+ }
+
+ /*
+ ** Arrange to read the data file.
+ */
+
+ p = queuename(e, 'd');
+ e->e_dfp = fopen(p, "r");
+ if (e->e_dfp == NULL)
+ {
+ syserr("readqf: cannot open %s", p);
+ }
+ else
+ {
+ e->e_flags |= EF_HAS_DF;
+ if (fstat(fileno(e->e_dfp), &st) >= 0)
+ {
+ e->e_msgsize = st.st_size;
+ e->e_dfdev = st.st_dev;
+ e->e_dfino = st.st_ino;
+ }
+ }
+
+ return TRUE;
+}
+ /*
+** PRINTQUEUE -- print out a representation of the mail queue
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Prints a listing of the mail queue on the standard output.
+*/
+
+void
+printqueue()
+{
+ register WORK *w;
+ FILE *f;
+ int nrequests;
+ char buf[MAXLINE];
+
+ /*
+ ** Check for permission to print the queue
+ */
+
+ if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
+ {
+ struct stat st;
+# ifdef NGROUPS_MAX
+ int n;
+ GIDSET_T gidset[NGROUPS_MAX];
+# endif
+
+ if (stat(QueueDir, &st) < 0)
+ {
+ syserr("Cannot stat %s", QueueDir);
+ return;
+ }
+# ifdef NGROUPS_MAX
+ n = getgroups(NGROUPS_MAX, gidset);
+ while (--n >= 0)
+ {
+ if (gidset[n] == st.st_gid)
+ break;
+ }
+ if (n < 0 && RealGid != st.st_gid)
+# else
+ if (RealGid != st.st_gid)
+# endif
+ {
+ usrerr("510 You are not permitted to see the queue");
+ setstat(EX_NOPERM);
+ return;
+ }
+ }
+
+ /*
+ ** Read and order the queue.
+ */
+
+ nrequests = orderq(TRUE);
+
+ /*
+ ** Print the work list that we have read.
+ */
+
+ /* first see if there is anything */
+ if (nrequests <= 0)
+ {
+ printf("Mail queue is empty\n");
+ return;
+ }
+
+ CurrentLA = getla(); /* get load average */
+
+ printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
+ if (nrequests > WorkListSize)
+ printf(", only %d printed", WorkListSize);
+ if (Verbose)
+ printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
+ else
+ 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;
+ int flags = 0;
+ int qfver;
+ char statmsg[MAXLINE];
+ char bodytype[MAXNAME + 1];
+
+ printf("%8s", w->w_name + 2);
+ f = fopen(w->w_name, "r");
+ if (f == NULL)
+ {
+ printf(" (job completed)\n");
+ errno = 0;
+ continue;
+ }
+ w->w_name[0] = 'd';
+ if (stat(w->w_name, &st) >= 0)
+ dfsize = st.st_size;
+ else
+ dfsize = -1;
+ if (w->w_lock)
+ printf("*");
+ else if (w->w_tooyoung)
+ printf("-");
+ else if (shouldqueue(w->w_pri, w->w_ctime))
+ printf("X");
+ else
+ printf(" ");
+ errno = 0;
+
+ statmsg[0] = bodytype[0] = '\0';
+ qfver = 0;
+ while (fgets(buf, sizeof buf, f) != NULL)
+ {
+ register int i;
+ register char *p;
+
+ fixcrlf(buf, TRUE);
+ switch (buf[0])
+ {
+ case 'V': /* queue file version */
+ qfver = atoi(&buf[1]);
+ break;
+
+ case 'M': /* error message */
+ if ((i = strlen(&buf[1])) >= sizeof statmsg)
+ i = sizeof statmsg - 1;
+ bcopy(&buf[1], statmsg, i);
+ statmsg[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)
+ 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]);
+ if (statmsg[0] != '\0' || bodytype[0] != '\0')
+ {
+ printf("\n %10.10s", bodytype);
+ if (statmsg[0] != '\0')
+ printf(" (%.60s)", statmsg);
+ }
+ break;
+
+ case 'C': /* controlling user */
+ if (Verbose)
+ printf("\n\t\t\t\t (---%.34s---)",
+ &buf[1]);
+ break;
+
+ case 'R': /* recipient name */
+ p = &buf[1];
+ if (qfver >= 1)
+ {
+ p = strchr(p, ':');
+ if (p == NULL)
+ break;
+ p++;
+ }
+ if (Verbose)
+ printf("\n\t\t\t\t\t %.38s", p);
+ else
+ printf("\n\t\t\t\t %.45s", p);
+ break;
+
+ case 'T': /* creation time */
+ submittime = atol(&buf[1]);
+ 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)
+ printf(" (no control file)");
+ printf("\n");
+ (void) fclose(f);
+ }
+}
+
+# endif /* QUEUE */
+ /*
+** QUEUENAME -- build a file name in the queue directory for this envelope.
+**
+** Assigns an id code if one does not already exist.
+** This code is very careful to avoid trashing existing files
+** under any circumstances.
+**
+** Parameters:
+** e -- envelope to build it in/from.
+** type -- the file type, used as the first character
+** of the file name.
+**
+** Returns:
+** a pointer to the new file name (in a static buffer).
+**
+** Side Effects:
+** 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;
+ int type;
+{
+ static int pid = -1;
+ static char c0;
+ static char c1;
+ static char c2;
+ time_t now;
+ struct tm *tm;
+ static char buf[MAXNAME + 1];
+
+ if (e->e_id == NULL)
+ {
+ char qf[20];
+
+ /* find a unique id */
+ if (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;
+ }
+ (void) sprintf(qf, "qf%cAA%05d", c0, pid);
+
+ while (c1 < '~' || c2 < 'Z')
+ {
+ int i;
+
+ if (c2 >= 'Z')
+ {
+ c1++;
+ c2 = 'A' - 1;
+ }
+ 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 (i < 0)
+ {
+ if (errno == EEXIST)
+ continue;
+ syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
+ qf, QueueDir, geteuid());
+ exit(EX_UNAVAILABLE);
+ }
+ if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB))
+ {
+ e->e_lockfp = fdopen(i, "w");
+ break;
+ }
+
+ /* a reader got the file; abandon it and try again */
+ (void) close(i);
+ }
+ if (c1 >= '~' && c2 >= 'Z')
+ {
+ syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
+ qf, QueueDir, geteuid());
+ exit(EX_OSERR);
+ }
+ e->e_id = newstr(&qf[2]);
+ define('i', e->e_id, e);
+ if (tTd(7, 1))
+ printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
+ if (tTd(7, 9))
+ {
+ printf(" lockfd=");
+ dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
+ }
+# ifdef LOG
+ if (LogLevel > 93)
+ syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
+# endif /* LOG */
+ }
+
+ if (type == '\0')
+ return (NULL);
+ (void) sprintf(buf, "%cf%s", type, e->e_id);
+ if (tTd(7, 2))
+ printf("queuename: %s\n", buf);
+ return (buf);
+}
+ /*
+** UNLOCKQUEUE -- unlock the queue entry for a specified envelope
+**
+** Parameters:
+** e -- the envelope to unlock.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** unlocks the queue for `e'.
+*/
+
+void
+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
+ if (LogLevel > 87)
+ syslog(LOG_DEBUG, "%s: unlock", e->e_id);
+# endif /* LOG */
+ if (!tTd(51, 104))
+ xunlink(queuename(e, 'x'));
+
+}
+ /*
+** SETCTLUSER -- create a controlling address
+**
+** Create a fake "address" given only a local login name; this is
+** used as a "controlling user" for future recipient addresses.
+**
+** Parameters:
+** user -- the user name of the controlling user.
+**
+** Returns:
+** An address descriptor for the controlling user.
+**
+** Side Effects:
+** none.
+*/
+
+ADDRESS *
+setctluser(user)
+ char *user;
+{
+ register ADDRESS *a;
+ struct passwd *pw;
+ char *p;
+
+ /*
+ ** See if this clears our concept of controlling user.
+ */
+
+ if (user == NULL || *user == '\0')
+ return NULL;
+
+ /*
+ ** Set up addr fields for controlling user.
+ */
+
+ a = (ADDRESS *) xalloc(sizeof *a);
+ bzero((char *) a, sizeof *a);
+
+ p = strchr(user, ':');
+ if (p != NULL)
+ *p++ = '\0';
+ if (*user != '\0' && (pw = sm_getpwnam(user)) != NULL)
+ {
+ if (strcmp(pw->pw_dir, "/") == 0)
+ a->q_home = "";
+ else
+ a->q_home = newstr(pw->pw_dir);
+ a->q_uid = pw->pw_uid;
+ a->q_gid = pw->pw_gid;
+ a->q_flags |= QGOODUID;
+ }
+
+ if (*user != '\0')
+ a->q_user = newstr(user);
+ else if (p != NULL)
+ a->q_user = newstr(p);
+ else
+ a->q_user = newstr(DefUser);
+
+ 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;
+}
+ /*
+** LOSEQFILE -- save the qf as Qf and try to let someone know
+**
+** Parameters:
+** e -- the envelope (e->e_id will be used).
+** why -- reported to whomever can hear.
+**
+** Returns:
+** none.
+*/
+
+void
+loseqfile(e, why)
+ register ENVELOPE *e;
+ char *why;
+{
+ char *p;
+ char buf[40];
+
+ if (e == NULL || e->e_id == NULL)
+ return;
+ if (strlen(e->e_id) > sizeof buf - 4)
+ return;
+ strcpy(buf, queuename(e, 'q'));
+ p = queuename(e, 'Q');
+ if (rename(buf, p) < 0)
+ syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
+#ifdef LOG
+ else if (LogLevel > 0)
+ syslog(LOG_ALERT, "Losing %s: %s", buf, why);
+#endif
+}
diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c
new file mode 100644
index 000000000000..c98d82c5054f
--- /dev/null
+++ b/usr.sbin/sendmail/src/readcf.c
@@ -0,0 +1,2554 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)readcf.c 8.138 (Berkeley) 11/20/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+# include <grp.h>
+#if NAMED_BIND
+# include <resolv.h>
+#endif
+
+/*
+** READCF -- read control file.
+**
+** This routine reads the control file and builds the internal
+** form.
+**
+** The file is formatted as a sequence of lines, each taken
+** atomically. The first character of each line describes how
+** the line is to be interpreted. The lines are:
+** Dxval Define macro x to have value val.
+** Cxword Put word into class x.
+** Fxfile [fmt] Read file for lines to put into
+** class x. Use scanf string 'fmt'
+** or "%s" if not present. Fmt should
+** only produce one string-valued result.
+** Hname: value Define header with field-name 'name'
+** and value as specified; this will be
+** macro expanded immediately before
+** use.
+** Sn Use rewriting set n.
+** Rlhs rhs Rewrite addresses that match lhs to
+** be rhs.
+** Mn arg=val... Define mailer. n is the internal name.
+** Args specify mailer parameters.
+** Oxvalue Set option x to value.
+** Pname=value Set precedence name to value.
+** Vversioncode[/vendorcode]
+** Version level/vendor name of
+** configuration syntax.
+** Kmapname mapclass arguments....
+** Define keyed lookup of a given class.
+** Arguments are class dependent.
+** Eenvar=value Set the environment value to the given value.
+**
+** Parameters:
+** cfname -- control file name.
+** safe -- TRUE if this is the system config file;
+** FALSE otherwise.
+** e -- the main envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Builds several internal tables.
+*/
+
+void
+readcf(cfname, safe, e)
+ char *cfname;
+ bool safe;
+ register ENVELOPE *e;
+{
+ FILE *cf;
+ int ruleset = 0;
+ char *q;
+ struct rewrite *rwp = NULL;
+ char *bp;
+ auto char *ep;
+ int nfuzzy;
+ char *file;
+ bool optional;
+ int mid;
+ char buf[MAXLINE];
+ register char *p;
+ extern char **copyplist();
+ struct stat statb;
+ char exbuf[MAXLINE];
+ char pvpbuf[MAXLINE + MAXATOM];
+ static char *null_list[1] = { NULL };
+ extern char *munchstring __P((char *, char **));
+ extern void fileclass __P((int, char *, char *, bool, bool));
+ extern void toomany __P((int, int));
+ extern void translate_dollars __P((char *));
+
+ FileName = cfname;
+ LineNumber = 0;
+
+ cf = fopen(cfname, "r");
+ if (cf == NULL)
+ {
+ syserr("cannot open");
+ exit(EX_OSFILE);
+ }
+
+ 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_INITALIAS)
+ 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)
+ {
+ if (bp[0] == '#')
+ {
+ if (bp != buf)
+ free(bp);
+ continue;
+ }
+
+ /* do macro expansion mappings */
+ translate_dollars(bp);
+
+ /* interpret this line */
+ errno = 0;
+ switch (bp[0])
+ {
+ case '\0':
+ case '#': /* comment */
+ break;
+
+ case 'R': /* rewriting rule */
+ for (p = &bp[1]; *p != '\0' && *p != '\t'; p++)
+ continue;
+
+ if (*p == '\0')
+ {
+ syserr("invalid rewrite line \"%s\" (tab expected)", bp);
+ break;
+ }
+
+ /* allocate space for the rule header */
+ if (rwp == NULL)
+ {
+ RewriteRules[ruleset] = rwp =
+ (struct rewrite *) xalloc(sizeof *rwp);
+ }
+ else
+ {
+ rwp->r_next = (struct rewrite *) xalloc(sizeof *rwp);
+ rwp = rwp->r_next;
+ }
+ rwp->r_next = NULL;
+
+ /* expand and save the LHS */
+ *p = '\0';
+ expand(&bp[1], exbuf, sizeof exbuf, e);
+ rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,
+ sizeof pvpbuf, NULL, NULL);
+ nfuzzy = 0;
+ if (rwp->r_lhs != NULL)
+ {
+ register char **ap;
+
+ 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");
+ rwp->r_lhs = null_list;
+ }
+
+ /* expand and save the RHS */
+ while (*++p == '\t')
+ continue;
+ q = p;
+ while (*p != '\0' && *p != '\t')
+ p++;
+ *p = '\0';
+ expand(q, exbuf, sizeof exbuf, e);
+ rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,
+ sizeof pvpbuf, NULL, NULL);
+ if (rwp->r_rhs != NULL)
+ {
+ register char **ap;
+
+ 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");
+ rwp->r_rhs = null_list;
+ }
+ break;
+
+ case 'S': /* select rewriting set */
+ expand(&bp[1], exbuf, sizeof exbuf, e);
+ ruleset = strtorwset(exbuf, NULL, ST_ENTER);
+ if (ruleset < 0)
+ break;
+ rwp = RewriteRules[ruleset];
+ if (rwp != NULL)
+ {
+ while (rwp->r_next != NULL)
+ rwp = rwp->r_next;
+ fprintf(stderr, "WARNING: Ruleset %s redefined\n",
+ &bp[1]);
+ }
+ break;
+
+ case 'D': /* macro definition */
+ mid = macid(&bp[1], &ep);
+ p = munchstring(ep, NULL);
+ define(mid, newstr(p), e);
+ break;
+
+ case 'H': /* required header line */
+ (void) chompheader(&bp[1], TRUE, NULL, e);
+ break;
+
+ case 'C': /* word class */
+ case 'T': /* trusted user (set class `t') */
+ if (bp[0] == 'C')
+ {
+ mid = macid(&bp[1], &ep);
+ expand(ep, exbuf, sizeof exbuf, e);
+ p = exbuf;
+ }
+ else
+ {
+ mid = 't';
+ p = &bp[1];
+ }
+ while (*p != '\0')
+ {
+ register char *wd;
+ char delim;
+
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ wd = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ delim = *p;
+ *p = '\0';
+ if (wd[0] != '\0')
+ setclass(mid, wd);
+ *p = delim;
+ }
+ break;
+
+ case 'F': /* word class from file */
+ mid = macid(&bp[1], &ep);
+ for (p = ep; isascii(*p) && isspace(*p); )
+ p++;
+ if (p[0] == '-' && p[1] == 'o')
+ {
+ optional = TRUE;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ while (isascii(*p) && isspace(*p))
+ p++;
+ }
+ else
+ optional = FALSE;
+ file = p;
+ if (*file == '|')
+ p = "%s";
+ else
+ {
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p == '\0')
+ p = "%s";
+ else
+ {
+ *p = '\0';
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ }
+ }
+ fileclass(mid, file, p, safe, optional);
+ break;
+
+#ifdef XLA
+ case 'L': /* extended load average description */
+ xla_init(&bp[1]);
+ break;
+#endif
+
+ case 'M': /* define mailer */
+ makemailer(&bp[1]);
+ break;
+
+ case 'O': /* set option */
+ setoption(bp[1], &bp[2], safe, FALSE, e);
+ break;
+
+ case 'P': /* set precedence */
+ if (NumPriorities >= MAXPRIORITIES)
+ {
+ toomany('P', MAXPRIORITIES);
+ break;
+ }
+ for (p = &bp[1]; *p != '\0' && *p != '='; p++)
+ continue;
+ if (*p == '\0')
+ goto badline;
+ *p = '\0';
+ Priorities[NumPriorities].pri_name = newstr(&bp[1]);
+ Priorities[NumPriorities].pri_val = atoi(++p);
+ NumPriorities++;
+ break;
+
+ case 'V': /* configuration syntax version */
+ for (p = &bp[1]; isascii(*p) && isspace(*p); p++)
+ continue;
+ if (!isascii(*p) || !isdigit(*p))
+ {
+ syserr("invalid argument to V line: \"%.20s\"",
+ &bp[1]);
+ break;
+ }
+ ConfigLevel = strtol(p, &ep, 10);
+
+ /*
+ ** Do heuristic tweaking for back compatibility.
+ */
+
+ if (ConfigLevel >= 5)
+ {
+ /* level 5 configs have short name in $w */
+ p = macvalue('w', e);
+ if (p != NULL && (p = strchr(p, '.')) != NULL)
+ *p = '\0';
+ define('w', macvalue('w', e), e);
+ }
+ if (ConfigLevel >= 6)
+ {
+ ColonOkInAddr = FALSE;
+ }
+
+ /*
+ ** Look for vendor code.
+ */
+
+ if (*ep++ == '/')
+ {
+ /* extract vendor code */
+ for (p = ep; isascii(*p) && isalpha(*p); )
+ p++;
+ *p = '\0';
+
+ if (!setvendor(ep))
+ syserr("invalid V line vendor code: \"%s\"",
+ ep);
+ }
+ break;
+
+ case 'K':
+ expand(&bp[1], exbuf, sizeof exbuf, e);
+ (void) makemapentry(exbuf);
+ break;
+
+ case 'E':
+ p = strchr(bp, '=');
+ if (p != NULL)
+ *p++ = '\0';
+ setuserenv(&bp[1], p);
+ break;
+
+ default:
+ badline:
+ syserr("unknown control line \"%s\"", bp);
+ }
+ if (bp != buf)
+ free(bp);
+ }
+ if (ferror(cf))
+ {
+ syserr("I/O read error");
+ exit(EX_OSFILE);
+ }
+ fclose(cf);
+ FileName = NULL;
+
+ /* initialize host maps from local service tables */
+ inithostmaps();
+
+ /* determine if we need to do special name-server frotz */
+ {
+ int nmaps;
+ char *maptype[MAXMAPSTACK];
+ short mapreturn[MAXMAPACTIONS];
+
+ nmaps = switch_map_find("hosts", maptype, mapreturn);
+ UseNameServer = FALSE;
+ if (nmaps > 0 && nmaps <= MAXMAPSTACK)
+ {
+ register int mapno;
+
+ for (mapno = 0; mapno < nmaps && !UseNameServer; mapno++)
+ {
+ if (strcmp(maptype[mapno], "dns") == 0)
+ UseNameServer = TRUE;
+ }
+ }
+
+#ifdef HESIOD
+ nmaps = switch_map_find("passwd", maptype, mapreturn);
+ UseHesiod = FALSE;
+ if (nmaps > 0 && nmaps <= MAXMAPSTACK)
+ {
+ register int mapno;
+
+ for (mapno = 0; mapno < nmaps && !UseHesiod; mapno++)
+ {
+ if (strcmp(maptype[mapno], "hesiod") == 0)
+ UseHesiod = TRUE;
+ }
+ }
+#endif
+ }
+}
+ /*
+** TRANSLATE_DOLLARS -- convert $x into internal form
+**
+** Actually does all appropriate pre-processing of a config line
+** to turn it into internal form.
+**
+** Parameters:
+** bp -- the buffer to translate.
+**
+** Returns:
+** None. The buffer is translated in place. Since the
+** translations always make the buffer shorter, this is
+** safe without a size parameter.
+*/
+
+void
+translate_dollars(bp)
+ char *bp;
+{
+ register char *p;
+ auto char *ep;
+
+ 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 != '\n' && p > bp)
+ p--;
+ if ((e = strchr(++p, '\n')) != NULL)
+ (void) strcpy(p, e);
+ else
+ *p-- = '\0';
+ break;
+ }
+ continue;
+ }
+
+ if (*p != '$' || p[1] == '\0')
+ continue;
+
+ if (p[1] == '$')
+ {
+ /* actual dollar sign.... */
+ (void) strcpy(p, p + 1);
+ continue;
+ }
+
+ /* convert to macro expansion character */
+ *p++ = MACROEXPAND;
+
+ /* special handling for $=, $~, $&, and $? */
+ if (*p == '=' || *p == '~' || *p == '&' || *p == '?')
+ p++;
+
+ /* convert macro name to code */
+ *p = macid(p, &ep);
+ if (ep != p)
+ strcpy(p + 1, ep);
+ }
+
+ /* strip trailing white space from the line */
+ while (--p > bp && isascii(*p) && isspace(*p))
+ *p = '\0';
+}
+ /*
+** TOOMANY -- signal too many of some option
+**
+** Parameters:
+** id -- the id of the error line
+** maxcnt -- the maximum possible values
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** gives a syserr.
+*/
+
+void
+toomany(id, maxcnt)
+ int id;
+ int maxcnt;
+{
+ syserr("too many %c lines, %d max", id, maxcnt);
+}
+ /*
+** FILECLASS -- read members of a class from a file
+**
+** Parameters:
+** class -- class to define.
+** filename -- name of file to read.
+** fmt -- scanf string to use for match.
+** safe -- if set, this is a safe read.
+** optional -- if set, it is not an error for the file to
+** not exist.
+**
+** Returns:
+** none
+**
+** Side Effects:
+**
+** puts all lines in filename that match a scanf into
+** the named class.
+*/
+
+void
+fileclass(class, filename, fmt, safe, optional)
+ int class;
+ char *filename;
+ char *fmt;
+ bool safe;
+ bool optional;
+{
+ FILE *f;
+ int sff;
+ int pid;
+ register char *p;
+ char buf[MAXLINE];
+
+ if (tTd(37, 2))
+ printf("fileclass(%s, fmt=%s)\n", filename, fmt);
+
+ if (filename[0] == '|')
+ {
+ auto int fd;
+ int i;
+ char *argv[MAXPV + 1];
+
+ i = 0;
+ for (p = strtok(&filename[1], " \t"); p != NULL; p = strtok(NULL, " \t"))
+ {
+ if (i >= MAXPV)
+ break;
+ argv[i++] = p;
+ }
+ argv[i] = NULL;
+ pid = prog_open(argv, &fd, CurEnv);
+ if (pid < 0)
+ f = NULL;
+ else
+ f = fdopen(fd, "r");
+ }
+ else
+ {
+ pid = -1;
+ sff = SFF_REGONLY;
+ if (safe)
+ sff |= SFF_OPENASROOT;
+ f = safefopen(filename, O_RDONLY, 0, sff);
+ }
+ if (f == NULL)
+ {
+ if (!optional)
+ syserr("fileclass: cannot open %s", filename);
+ return;
+ }
+
+ while (fgets(buf, sizeof buf, f) != NULL)
+ {
+ register char *p;
+# if SCANF
+ char wordbuf[MAXNAME+1];
+# endif
+
+ if (buf[0] == '#')
+ continue;
+# if SCANF
+ if (sscanf(buf, fmt, wordbuf) != 1)
+ continue;
+ p = wordbuf;
+# else /* SCANF */
+ p = buf;
+# endif /* SCANF */
+
+ /*
+ ** Break up the match into words.
+ */
+
+ while (*p != '\0')
+ {
+ register char *q;
+
+ /* strip leading spaces */
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p == '\0')
+ break;
+
+ /* find the end of the word */
+ q = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ if (*p != '\0')
+ *p++ = '\0';
+
+ /* enter the word in the symbol table */
+ setclass(class, q);
+ }
+ }
+
+ (void) fclose(f);
+ if (pid > 0)
+ (void) waitfor(pid);
+}
+ /*
+** MAKEMAILER -- define a new mailer.
+**
+** Parameters:
+** line -- description of mailer. This is in labeled
+** fields. The fields are:
+** A -- the argv for this mailer
+** C -- the character set for MIME conversions
+** D -- the directory to run in
+** E -- the eol string
+** F -- the flags associated with the mailer
+** L -- the maximum line length
+** M -- the maximum message size
+** N -- the niceness at which to run
+** P -- the path to the mailer
+** R -- the recipient rewriting set
+** S -- the sender rewriting set
+** T -- the mailer type (for DSNs)
+** U -- the uid to run as
+** The first word is the canonical name of the mailer.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** enters the mailer into the mailer table.
+*/
+
+void
+makemailer(line)
+ char *line;
+{
+ register char *p;
+ register struct mailer *m;
+ register STAB *s;
+ int i;
+ char fcode;
+ auto char *endp;
+ extern int NextMailer;
+ extern char **makeargv();
+ extern char *munchstring();
+
+ /* allocate a mailer and set up defaults */
+ m = (struct mailer *) xalloc(sizeof *m);
+ bzero((char *) m, sizeof *m);
+ m->m_eol = "\n";
+ m->m_uid = m->m_gid = 0;
+
+ /* collect the mailer name */
+ for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++)
+ continue;
+ if (*p != '\0')
+ *p++ = '\0';
+ if (line[0] == '\0')
+ syserr("name required for mailer");
+ m->m_name = newstr(line);
+
+ /* now scan through and assign info from the fields */
+ while (*p != '\0')
+ {
+ auto char *delimptr;
+
+ while (*p != '\0' && (*p == ',' || (isascii(*p) && isspace(*p))))
+ p++;
+
+ /* p now points to field code */
+ fcode = *p;
+ while (*p != '\0' && *p != '=' && *p != ',')
+ p++;
+ if (*p++ != '=')
+ {
+ syserr("mailer %s: `=' expected", m->m_name);
+ return;
+ }
+ while (isascii(*p) && isspace(*p))
+ p++;
+
+ /* p now points to the field body */
+ p = munchstring(p, &delimptr);
+
+ /* install the field into the mailer struct */
+ switch (fcode)
+ {
+ case 'P': /* pathname */
+ if (*p == '\0')
+ syserr("mailer %s: empty path name", m->m_name);
+ m->m_mailer = newstr(p);
+ break;
+
+ case 'F': /* flags */
+ for (; *p != '\0'; p++)
+ if (!(isascii(*p) && isspace(*p)))
+ setbitn(*p, m->m_flags);
+ break;
+
+ case 'S': /* sender rewriting ruleset */
+ case 'R': /* recipient rewriting ruleset */
+ i = strtorwset(p, &endp, ST_ENTER);
+ if (i < 0)
+ return;
+ if (fcode == 'S')
+ m->m_sh_rwset = m->m_se_rwset = i;
+ else
+ m->m_rh_rwset = m->m_re_rwset = i;
+
+ p = endp;
+ if (*p++ == '/')
+ {
+ i = strtorwset(p, NULL, ST_ENTER);
+ if (i < 0)
+ return;
+ if (fcode == 'S')
+ m->m_sh_rwset = i;
+ else
+ m->m_rh_rwset = i;
+ }
+ break;
+
+ case 'E': /* end of line string */
+ if (*p == '\0')
+ syserr("mailer %s: null end-of-line string",
+ m->m_name);
+ m->m_eol = newstr(p);
+ break;
+
+ case 'A': /* argument vector */
+ if (*p == '\0')
+ syserr("mailer %s: null argument vector",
+ m->m_name);
+ m->m_argv = makeargv(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 'N': /* run niceness */
+ m->m_nice = atoi(p);
+ break;
+
+ case 'D': /* working directory */
+ if (*p == '\0')
+ syserr("mailer %s: null working directory",
+ m->m_name);
+ m->m_execdir = newstr(p);
+ break;
+
+ case 'C': /* default charset */
+ if (*p == '\0')
+ syserr("mailer %s: null charset", m->m_name);
+ m->m_defcharset = newstr(p);
+ break;
+
+ case 'T': /* MTA-Name/Address/Diagnostic types */
+ /* extract MTA name type; default to "dns" */
+ m->m_mtatype = newstr(p);
+ p = strchr(m->m_mtatype, '/');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ if (*p == '\0')
+ p = NULL;
+ }
+ if (*m->m_mtatype == '\0')
+ m->m_mtatype = "dns";
+
+ /* extract address type; default to "rfc822" */
+ m->m_addrtype = p;
+ if (p != NULL)
+ p = strchr(p, '/');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ if (*p == '\0')
+ p = NULL;
+ }
+ if (m->m_addrtype == NULL || *m->m_addrtype == '\0')
+ m->m_addrtype = "rfc822";
+
+ /* extract diagnostic type; default to "smtp" */
+ m->m_diagtype = p;
+ if (m->m_diagtype == NULL || *m->m_diagtype == '\0')
+ m->m_diagtype = "smtp";
+ break;
+
+ case 'U': /* user id */
+ if (isascii(*p) && !isdigit(*p))
+ {
+ char *q = p;
+ struct passwd *pw;
+
+ while (*p != '\0' && isascii(*p) &&
+ (isalnum(*p) || strchr("-_", *p) != NULL))
+ p++;
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ if (*p != '\0')
+ *p++ = '\0';
+ if (*q == '\0')
+ syserr("mailer %s: null user name",
+ m->m_name);
+ pw = sm_getpwnam(q);
+ if (pw == NULL)
+ syserr("readcf: mailer U= flag: unknown user %s", q);
+ else
+ {
+ m->m_uid = pw->pw_uid;
+ m->m_gid = pw->pw_gid;
+ }
+ }
+ else
+ {
+ auto char *q;
+
+ m->m_uid = strtol(p, &q, 0);
+ p = q;
+ }
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p == '\0')
+ break;
+ if (isascii(*p) && !isdigit(*p))
+ {
+ char *q = p;
+ struct group *gr;
+
+ while (isascii(*p) && isalnum(*p))
+ p++;
+ *p++ = '\0';
+ if (*q == '\0')
+ syserr("mailer %s: null group name",
+ m->m_name);
+ gr = getgrnam(q);
+ if (gr == NULL)
+ syserr("readcf: mailer U= flag: unknown group %s", q);
+ else
+ m->m_gid = gr->gr_gid;
+ }
+ else
+ {
+ m->m_gid = strtol(p, NULL, 0);
+ }
+ break;
+ }
+
+ p = delimptr;
+ }
+
+ /* 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;
+ }
+
+ if (NextMailer >= MAXMAILERS)
+ {
+ syserr("too many mailers defined (%d max)", MAXMAILERS);
+ return;
+ }
+
+ /* 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);
+ }
+
+ if (strcmp(m->m_mailer, "[IPC]") == 0 ||
+ strcmp(m->m_mailer, "[TCP]") == 0)
+ {
+ if (m->m_mtatype == NULL)
+ m->m_mtatype = "dns";
+ if (m->m_addrtype == NULL)
+ m->m_addrtype = "rfc822";
+ if (m->m_diagtype == NULL)
+ m->m_diagtype = "smtp";
+ }
+
+ /* enter the mailer into the symbol table */
+ s = stab(m->m_name, ST_MAILER, ST_ENTER);
+ 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;
+}
+ /*
+** 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.
+*/
+
+char *
+munchstring(p, delimptr)
+ register char *p;
+ char **delimptr;
+{
+ register char *q;
+ bool backslash = FALSE;
+ bool quotemode = FALSE;
+ static char buf[MAXLINE];
+
+ for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++)
+ {
+ if (backslash)
+ {
+ /* everything is roughly literal */
+ backslash = FALSE;
+ switch (*p)
+ {
+ case 'r': /* carriage return */
+ *q++ = '\r';
+ continue;
+
+ case 'n': /* newline */
+ *q++ = '\n';
+ continue;
+
+ case 'f': /* form feed */
+ *q++ = '\f';
+ continue;
+
+ case 'b': /* backspace */
+ *q++ = '\b';
+ continue;
+ }
+ *q++ = *p;
+ }
+ else
+ {
+ if (*p == '\\')
+ backslash = TRUE;
+ else if (*p == '"')
+ quotemode = !quotemode;
+ else if (quotemode || *p != ',')
+ *q++ = *p;
+ else
+ break;
+ }
+ }
+
+ if (delimptr != NULL)
+ *delimptr = p;
+ *q++ = '\0';
+ return (buf);
+}
+ /*
+** MAKEARGV -- break up a string into words
+**
+** Parameters:
+** p -- the string to break up.
+**
+** Returns:
+** a char **argv (dynamically allocated)
+**
+** Side Effects:
+** munges p.
+*/
+
+char **
+makeargv(p)
+ register char *p;
+{
+ char *q;
+ int i;
+ char **avp;
+ char *argv[MAXPV + 1];
+
+ /* take apart the words */
+ i = 0;
+ while (*p != '\0' && i < MAXPV)
+ {
+ q = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ argv[i++] = newstr(q);
+ }
+ argv[i++] = NULL;
+
+ /* now make a copy of the argv */
+ avp = (char **) xalloc(sizeof *avp * i);
+ bcopy((char *) argv, (char *) avp, sizeof *avp * i);
+
+ return (avp);
+}
+ /*
+** PRINTRULES -- print rewrite rules (for debugging)
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** prints rewrite rules.
+*/
+
+void
+printrules()
+{
+ register struct rewrite *rwp;
+ register int ruleset;
+
+ for (ruleset = 0; ruleset < 10; ruleset++)
+ {
+ if (RewriteRules[ruleset] == NULL)
+ continue;
+ printf("\n----Rule Set %d:", ruleset);
+
+ for (rwp = RewriteRules[ruleset]; rwp != NULL; rwp = rwp->r_next)
+ {
+ printf("\nLHS:");
+ printav(rwp->r_lhs);
+ printf("RHS:");
+ printav(rwp->r_rhs);
+ }
+ }
+}
+ /*
+** PRINTMAILER -- print mailer structure (for debugging)
+**
+** Parameters:
+** m -- the mailer to print
+**
+** Returns:
+** none.
+*/
+
+void
+printmailer(m)
+ register MAILER *m;
+{
+ int j;
+
+ printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld U=%d:%d F=",
+ m->m_mno, 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,
+ m->m_uid, m->m_gid);
+ for (j = '\0'; j <= '\177'; j++)
+ if (bitnset(j, m->m_flags))
+ (void) putchar(j);
+ printf(" L=%d E=", m->m_linelimit);
+ xputs(m->m_eol);
+ if (m->m_defcharset != NULL)
+ printf(" C=%s", m->m_defcharset);
+ printf(" T=%s/%s/%s",
+ m->m_mtatype == NULL ? "<undefined>" : m->m_mtatype,
+ m->m_addrtype == NULL ? "<undefined>" : m->m_addrtype,
+ m->m_diagtype == NULL ? "<undefined>" : m->m_diagtype);
+ 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");
+}
+ /*
+** SETOPTION -- set global processing option
+**
+** Parameters:
+** opt -- option name.
+** val -- option value (as a text string).
+** safe -- set if this came from a configuration file.
+** Some options (if set from the command line) will
+** 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.
+**
+** Side Effects:
+** Sets options as implied by the arguments.
+*/
+
+static BITMAP StickyOpt; /* set if option is stuck */
+extern void settimeout __P((char *, char *));
+
+
+#if 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,
+ "true", 0, /* to avoid error on old syntax */
+ NULL, 0
+};
+
+#endif
+
+struct optioninfo
+{
+ char *o_name; /* long name of option */
+ u_char o_code; /* short name of option */
+ bool o_safe; /* safe for random people to use */
+} OptionTab[] =
+{
+ "SevenBitInput", '7', TRUE,
+#if MIME8TO7
+ "EightBitMode", '8', TRUE,
+#endif
+ "AliasFile", 'A', FALSE,
+ "AliasWait", 'a', FALSE,
+ "BlankSub", 'B', FALSE,
+ "MinFreeBlocks", 'b', TRUE,
+ "CheckpointInterval", 'C', TRUE,
+ "HoldExpensive", 'c', FALSE,
+ "AutoRebuildAliases", 'D', FALSE,
+ "DeliveryMode", 'd', TRUE,
+ "ErrorHeader", 'E', FALSE,
+ "ErrorMode", 'e', TRUE,
+ "TempFileMode", 'F', FALSE,
+ "SaveFromLine", 'f', FALSE,
+ "MatchGECOS", 'G', FALSE,
+ "HelpFile", 'H', FALSE,
+ "MaxHopCount", 'h', FALSE,
+ "ResolverOptions", 'I', FALSE,
+ "IgnoreDots", 'i', TRUE,
+ "ForwardPath", 'J', FALSE,
+ "SendMimeErrors", 'j', TRUE,
+ "ConnectionCacheSize", 'k', FALSE,
+ "ConnectionCacheTimeout", 'K', FALSE,
+ "UseErrorsTo", 'l', FALSE,
+ "LogLevel", 'L', FALSE,
+ "MeToo", 'm', TRUE,
+ "CheckAliases", 'n', FALSE,
+ "OldStyleHeaders", 'o', TRUE,
+ "DaemonPortOptions", 'O', FALSE,
+ "PrivacyOptions", 'p', TRUE,
+ "PostmasterCopy", 'P', FALSE,
+ "QueueFactor", 'q', FALSE,
+ "QueueDirectory", 'Q', FALSE,
+ "DontPruneRoutes", 'R', FALSE,
+ "Timeout", 'r', TRUE,
+ "StatusFile", 'S', FALSE,
+ "SuperSafe", 's', TRUE,
+ "QueueTimeout", 'T', FALSE,
+ "TimeZoneSpec", 't', FALSE,
+ "UserDatabaseSpec", 'U', FALSE,
+ "DefaultUser", 'u', FALSE,
+ "FallbackMXhost", 'V', FALSE,
+ "Verbose", 'v', TRUE,
+ "TryNullMXList", 'w', TRUE,
+ "QueueLA", 'x', FALSE,
+ "RefuseLA", 'X', FALSE,
+ "RecipientFactor", 'y', FALSE,
+ "ForkEachJob", 'Y', FALSE,
+ "ClassFactor", 'z', FALSE,
+ "RetryFactor", 'Z', FALSE,
+#define O_QUEUESORTORD 0x81
+ "QueueSortOrder", O_QUEUESORTORD, TRUE,
+#define O_HOSTSFILE 0x82
+ "HostsFile", O_HOSTSFILE, FALSE,
+#define O_MQA 0x83
+ "MinQueueAge", O_MQA, TRUE,
+#define O_MHSA 0x84
+/*
+ "MaxHostStatAge", O_MHSA, TRUE,
+*/
+#define O_DEFCHARSET 0x85
+ "DefaultCharSet", O_DEFCHARSET, TRUE,
+#define O_SSFILE 0x86
+ "ServiceSwitchFile", O_SSFILE, FALSE,
+#define O_DIALDELAY 0x87
+ "DialDelay", O_DIALDELAY, TRUE,
+#define O_NORCPTACTION 0x88
+ "NoRecipientAction", O_NORCPTACTION, TRUE,
+#define O_SAFEFILEENV 0x89
+ "SafeFileEnvironment", O_SAFEFILEENV, FALSE,
+#define O_MAXMSGSIZE 0x8a
+ "MaxMessageSize", O_MAXMSGSIZE, FALSE,
+#define O_COLONOKINADDR 0x8b
+ "ColonOkInAddr", O_COLONOKINADDR, TRUE,
+#define O_MAXQUEUERUN 0x8c
+ "MaxQueueRunSize", O_MAXQUEUERUN, TRUE,
+#define O_MAXCHILDREN 0x8d
+/*
+ "MaxDaemonChildren", O_MAXCHILDREN, FALSE,
+*/
+#define O_KEEPCNAMES 0x8e
+ "DontExpandCnames", O_KEEPCNAMES, FALSE,
+#define O_MUSTQUOTE 0x8f
+/*
+ "MustQuoteChars", O_MUSTQUOTE, FALSE,
+*/
+#define O_SMTPGREETING 0x90
+ "SmtpGreetingMessage", O_SMTPGREETING, FALSE,
+#define O_UNIXFROM 0x91
+ "UnixFromLine", O_UNIXFROM, FALSE,
+#define O_OPCHARS 0x92
+ "OperatorChars", O_OPCHARS, FALSE,
+#define O_DONTINITGRPS 0x93
+ "DontInitGroups", O_DONTINITGRPS, TRUE,
+#define O_SLFH 0x94
+#ifdef LOTUS_NOTES_HACK
+ "SingleLineFromHeader", O_SLFH, TRUE,
+#endif
+
+ NULL, '\0', FALSE,
+};
+
+
+
+void
+setoption(opt, val, safe, sticky, e)
+ int opt;
+ char *val;
+ bool safe;
+ bool sticky;
+ register ENVELOPE *e;
+{
+ register char *p;
+ register struct optioninfo *o;
+ char *subopt;
+ char buf[50];
+ extern bool atobool();
+ extern time_t convtime();
+ extern int QueueLA;
+ extern int RefuseLA;
+ extern bool Warn_Q_option;
+
+ errno = 0;
+ if (opt == ' ')
+ {
+ /* full word options */
+ struct optioninfo *sel;
+
+ p = strchr(val, '=');
+ if (p == NULL)
+ p = &val[strlen(val)];
+ while (*--p == ' ')
+ continue;
+ while (*++p == ' ')
+ *p = '\0';
+ if (p == val)
+ {
+ syserr("readcf: null option name");
+ return;
+ }
+ if (*p == '=')
+ *p++ = '\0';
+ while (*p == ' ')
+ p++;
+ subopt = strchr(val, '.');
+ if (subopt != NULL)
+ *subopt++ = '\0';
+ sel = NULL;
+ for (o = OptionTab; o->o_name != NULL; o++)
+ {
+ if (strncasecmp(o->o_name, val, strlen(val)) != 0)
+ continue;
+ if (strlen(o->o_name) == strlen(val))
+ {
+ /* completely specified -- this must be it */
+ sel = NULL;
+ break;
+ }
+ if (sel != NULL)
+ break;
+ sel = o;
+ }
+ if (sel != NULL && o->o_name == NULL)
+ o = sel;
+ else if (o->o_name == NULL)
+ {
+ syserr("readcf: unknown option name %s", val);
+ return;
+ }
+ else if (sel != NULL)
+ {
+ syserr("readcf: ambiguous option name %s (matches %s and %s)",
+ val, sel->o_name, o->o_name);
+ return;
+ }
+ if (strlen(val) != strlen(o->o_name))
+ {
+ bool oldVerbose = Verbose;
+
+ Verbose = TRUE;
+ message("Option %s used as abbreviation for %s",
+ val, o->o_name);
+ Verbose = oldVerbose;
+ }
+ opt = o->o_code;
+ val = p;
+ }
+ else
+ {
+ for (o = OptionTab; o->o_name != NULL; o++)
+ {
+ if (o->o_code == opt)
+ break;
+ }
+ subopt = NULL;
+ }
+
+ if (tTd(37, 1))
+ {
+ printf(isascii(opt) && isprint(opt) ?
+ "setoption %s (%c).%s=" :
+ "setoption %s (0x%x).%s=",
+ o->o_name == NULL ? "<unknown>" : o->o_name,
+ opt,
+ subopt == NULL ? "" : subopt);
+ xputs(val);
+ }
+
+ /*
+ ** See if this option is preset for us.
+ */
+
+ if (!sticky && bitnset(opt, StickyOpt))
+ {
+ if (tTd(37, 1))
+ printf(" (ignored)\n");
+ return;
+ }
+
+ /*
+ ** Check to see if this option can be specified by this user.
+ */
+
+ if (!safe && RealUid == 0)
+ safe = TRUE;
+ if (!safe && !o->o_safe)
+ {
+ if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
+ {
+ if (tTd(37, 1))
+ printf(" (unsafe)");
+ if (RealUid != geteuid())
+ {
+ if (tTd(37, 1))
+ printf("(Resetting uid)");
+ endpwent();
+ (void) setgid(RealGid);
+ (void) setuid(RealUid);
+ }
+ }
+ }
+ if (tTd(37, 1))
+ printf("\n");
+
+ switch (opt & 0xff)
+ {
+ case '7': /* force seven-bit input */
+ SevenBitInput = atobool(val);
+ break;
+
+#if MIME8TO7
+ case '8': /* handling of 8-bit input */
+ switch (*val)
+ {
+ case 'm': /* convert 8-bit, convert MIME */
+ MimeMode = MM_CVTMIME|MM_MIME8BIT;
+ break;
+
+ case 'p': /* pass 8 bit, convert MIME */
+ MimeMode = MM_CVTMIME|MM_PASS8BIT;
+ break;
+
+ case 's': /* strict adherence */
+ MimeMode = MM_CVTMIME;
+ break;
+
+#if 0
+ case 'r': /* reject 8-bit, don't convert MIME */
+ MimeMode = 0;
+ break;
+
+ case 'j': /* "just send 8" */
+ MimeMode = MM_PASS8BIT;
+ break;
+
+ case 'a': /* encode 8 bit if available */
+ MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME;
+ break;
+
+ case 'c': /* convert 8 bit to MIME, never 7 bit */
+ MimeMode = MM_MIME8BIT;
+ break;
+#endif
+
+ default:
+ syserr("Unknown 8-bit mode %c", *val);
+ exit(EX_USAGE);
+ }
+ break;
+#endif
+
+ case 'A': /* set default alias file */
+ if (val[0] == '\0')
+ setalias("aliases");
+ else
+ setalias(val);
+ break;
+
+ case 'a': /* look N minutes for "@:@" in alias file */
+ if (val[0] == '\0')
+ SafeAlias = 5 * 60; /* five minutes */
+ else
+ SafeAlias = convtime(val, 'm');
+ break;
+
+ case 'B': /* substitution for blank character */
+ SpaceSub = val[0];
+ if (SpaceSub == '\0')
+ 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': /* checkpoint every N addresses */
+ CheckpointInterval = atoi(val);
+ break;
+
+ case 'd': /* delivery mode */
+ switch (*val)
+ {
+ case '\0':
+ e->e_sendmode = SM_DELIVER;
+ break;
+
+ case SM_QUEUE: /* queue only */
+ case SM_DEFER: /* queue only and defer map lookups */
+#ifndef QUEUE
+ syserr("need QUEUE to set -odqueue or -oddefer");
+#endif /* QUEUE */
+ /* fall through..... */
+
+ case SM_DELIVER: /* do everything */
+ case SM_FORK: /* fork after verification */
+ e->e_sendmode = *val;
+ break;
+
+ default:
+ syserr("Unknown delivery mode %c", *val);
+ exit(EX_USAGE);
+ }
+ break;
+
+ case 'D': /* rebuild alias database as needed */
+ 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 EM_QUIET: /* be silent about it */
+ case EM_MAIL: /* mail back */
+ case EM_BERKNET: /* do berknet error processing */
+ case EM_WRITE: /* write back (or mail) */
+ case EM_PRINT: /* print errors normally (default) */
+ e->e_errormode = *val;
+ break;
+ }
+ break;
+
+ case 'F': /* file mode */
+ FileMode = atooct(val) & 0777;
+ break;
+
+ case 'f': /* save Unix-style From lines on front */
+ SaveFrom = atobool(val);
+ break;
+
+ case 'G': /* match recipients against GECOS field */
+ MatchGecos = atobool(val);
+ break;
+
+ case 'g': /* default gid */
+ g_opt:
+ if (isascii(*val) && isdigit(*val))
+ DefGid = atoi(val);
+ else
+ {
+ register struct group *gr;
+
+ DefGid = -1;
+ gr = getgrnam(val);
+ if (gr == NULL)
+ syserr("readcf: option %c: unknown group %s",
+ opt, val);
+ else
+ DefGid = gr->gr_gid;
+ }
+ break;
+
+ case 'H': /* help file */
+ if (val[0] == '\0')
+ HelpFile = "sendmail.hf";
+ else
+ HelpFile = newstr(val);
+ break;
+
+ case 'h': /* maximum hop count */
+ MaxHopCount = atoi(val);
+ break;
+
+ case 'I': /* use internet domain name server */
+#if NAMED_BIND
+ 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';
+ if (strcasecmp(q, "HasWildcardMX") == 0)
+ {
+ HasWildcardMX = !clearmode;
+ continue;
+ }
+ for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++)
+ {
+ if (strcasecmp(q, rfp->rf_name) == 0)
+ break;
+ }
+ if (rfp->rf_name == NULL)
+ syserr("readcf: I option value %s unrecognized", q);
+ else if (clearmode)
+ _res.options &= ~rfp->rf_bits;
+ else
+ _res.options |= rfp->rf_bits;
+ }
+ if (tTd(8, 2))
+ printf("_res.options = %x, HasWildcardMX = %d\n",
+ _res.options, HasWildcardMX);
+#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;
+
+ 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 */
+ if (safe || LogLevel < atoi(val))
+ LogLevel = atoi(val);
+ break;
+
+ case 'M': /* define macro */
+ p = newstr(&val[1]);
+ if (!safe)
+ cleanstrcpy(p, p, MAXNAME);
+ define(val[0], p, CurEnv);
+ sticky = FALSE;
+ break;
+
+ case 'm': /* send to me too */
+ MeToo = atobool(val);
+ break;
+
+ case 'n': /* validate RHS in newaliases */
+ CheckAliases = atobool(val);
+ break;
+
+ /* 'N' available -- was "net name" */
+
+ case 'O': /* daemon options */
+#ifdef DAEMON
+ setdaemonoptions(val);
+#else
+ syserr("DaemonPortOptions (O option) set but DAEMON not compiled in");
+#endif
+ break;
+
+ case 'o': /* assume old style headers */
+ if (atobool(val))
+ CurEnv->e_flags |= EF_OLDSTYLE;
+ else
+ 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;
+ }
+ sticky = FALSE;
+ break;
+
+ case 'P': /* postmaster copy address for returned mail */
+ PostMasterCopy = newstr(val);
+ break;
+
+ case 'q': /* slope of queue only function */
+ QueueFactor = atoi(val);
+ break;
+
+ case 'Q': /* queue directory */
+ if (val[0] == '\0')
+ QueueDir = "mqueue";
+ else
+ QueueDir = newstr(val);
+ if (RealUid != 0 && !safe)
+ Warn_Q_option = TRUE;
+ break;
+
+ case 'R': /* don't prune routes */
+ DontPruneRoutes = atobool(val);
+ break;
+
+ case 'r': /* read timeout */
+ if (subopt == NULL)
+ inittimeouts(val);
+ else
+ settimeout(subopt, val);
+ break;
+
+ case 'S': /* status file */
+ if (val[0] == '\0')
+ StatFile = "sendmail.st";
+ else
+ StatFile = newstr(val);
+ break;
+
+ case 's': /* be super safe, even if expensive */
+ SuperSafe = atobool(val);
+ break;
+
+ case 'T': /* queue timeout */
+ p = strchr(val, '/');
+ if (p != NULL)
+ {
+ *p++ = '\0';
+ settimeout("queuewarn", p);
+ }
+ settimeout("queuereturn", val);
+ break;
+
+ case 't': /* time zone name */
+ TimeZoneSpec = newstr(val);
+ break;
+
+ case 'U': /* location of user database */
+ UdbSpec = newstr(val);
+ break;
+
+ case 'u': /* set default uid */
+ for (p = val; *p != '\0'; p++)
+ {
+ if (*p == '.' || *p == '/' || *p == ':')
+ {
+ *p++ = '\0';
+ break;
+ }
+ }
+ if (isascii(*val) && isdigit(*val))
+ DefUid = atoi(val);
+ else
+ {
+ register struct passwd *pw;
+
+ DefUid = -1;
+ pw = sm_getpwnam(val);
+ if (pw == NULL)
+ syserr("readcf: option u: unknown user %s", val);
+ else
+ {
+ DefUid = pw->pw_uid;
+ DefGid = pw->pw_gid;
+ }
+ }
+ setdefuser();
+
+ /* handle the group if it is there */
+ if (*p == '\0')
+ break;
+ val = p;
+ goto g_opt;
+
+ case 'V': /* fallback MX host */
+ FallBackMX = newstr(val);
+ break;
+
+ case 'v': /* run in verbose mode */
+ Verbose = atobool(val);
+ break;
+
+ case 'w': /* if we are best MX, try host directly */
+ TryNullMXList = atobool(val);
+ break;
+
+ /* '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-reject connections */
+ RefuseLA = atoi(val);
+ break;
+
+ case 'y': /* work recipient factor */
+ WkRecipFact = atoi(val);
+ break;
+
+ case 'Y': /* fork jobs during queue runs */
+ ForkQueueRuns = atobool(val);
+ break;
+
+ case 'z': /* work message class factor */
+ WkClassFact = atoi(val);
+ break;
+
+ case 'Z': /* work time factor */
+ WkTimeFact = atoi(val);
+ break;
+
+ case O_QUEUESORTORD: /* queue sorting order */
+ switch (*val)
+ {
+ case 'h': /* Host first */
+ case 'H':
+ QueueSortOrder = QS_BYHOST;
+ break;
+
+ case 'p': /* Priority order */
+ case 'P':
+ QueueSortOrder = QS_BYPRIORITY;
+ break;
+
+ default:
+ syserr("Invalid queue sort order \"%s\"", val);
+ }
+ break;
+
+ case O_HOSTSFILE: /* pathname of /etc/hosts file */
+ HostsFile = newstr(val);
+ break;
+
+ case O_MQA: /* minimum queue age between deliveries */
+ MinQueueAge = convtime(val, 'm');
+ break;
+
+ case O_MHSA: /* maximum age of cached host status */
+ MaxHostStatAge = convtime(val, 'm');
+ break;
+
+ case O_DEFCHARSET: /* default character set for mimefying */
+ DefaultCharSet = newstr(denlstring(val, TRUE, TRUE));
+ break;
+
+ case O_SSFILE: /* service switch file */
+ ServiceSwitchFile = newstr(val);
+ break;
+
+ case O_DIALDELAY: /* delay for dial-on-demand operation */
+ DialDelay = convtime(val, 's');
+ break;
+
+ case O_NORCPTACTION: /* what to do if no recipient */
+ if (strcasecmp(val, "none") == 0)
+ NoRecipientAction = NRA_NO_ACTION;
+ else if (strcasecmp(val, "add-to") == 0)
+ NoRecipientAction = NRA_ADD_TO;
+ else if (strcasecmp(val, "add-apparently-to") == 0)
+ NoRecipientAction = NRA_ADD_APPARENTLY_TO;
+ else if (strcasecmp(val, "add-bcc") == 0)
+ NoRecipientAction = NRA_ADD_BCC;
+ else if (strcasecmp(val, "add-to-undisclosed") == 0)
+ NoRecipientAction = NRA_ADD_TO_UNDISCLOSED;
+ else
+ syserr("Invalid NoRecipientAction: %s", val);
+ break;
+
+ case O_SAFEFILEENV: /* chroot() environ for writing to files */
+ SafeFileEnv = newstr(val);
+ break;
+
+ case O_MAXMSGSIZE: /* maximum message size */
+ MaxMessageSize = atol(val);
+ break;
+
+ case O_COLONOKINADDR: /* old style handling of colon addresses */
+ ColonOkInAddr = atobool(val);
+ break;
+
+ case O_MAXQUEUERUN: /* max # of jobs in a single queue run */
+ MaxQueueRun = atol(val);
+ break;
+
+ case O_MAXCHILDREN: /* max # of children of daemon */
+ MaxChildren = atoi(val);
+ break;
+
+ case O_KEEPCNAMES: /* don't expand CNAME records */
+ DontExpandCnames = atobool(val);
+ break;
+
+ case O_MUSTQUOTE: /* must quote these characters in phrases */
+ strcpy(buf, "@,;:\\()[]");
+ if (strlen(val) < sizeof buf - 10)
+ strcat(buf, val);
+ MustQuoteChars = newstr(buf);
+ break;
+
+ case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */
+ SmtpGreeting = newstr(munchstring(val, NULL));
+ break;
+
+ case O_UNIXFROM: /* UNIX From_ line (old $l macro) */
+ UnixFromLine = newstr(munchstring(val, NULL));
+ break;
+
+ case O_OPCHARS: /* operator characters (old $o macro) */
+ OperatorChars = newstr(munchstring(val, NULL));
+ break;
+
+ case O_DONTINITGRPS: /* don't call initgroups(3) */
+ DontInitGroups = atobool(val);
+ break;
+
+ case O_SLFH: /* make sure from fits on one line */
+ SingleLineFromHeader = atobool(val);
+ break;
+
+ default:
+ if (tTd(37, 1))
+ {
+ if (isascii(opt) && isprint(opt))
+ printf("Warning: option %c unknown\n", opt);
+ else
+ printf("Warning: option 0x%x unknown\n", opt);
+ }
+ break;
+ }
+ if (sticky)
+ setbitn(opt, StickyOpt);
+}
+ /*
+** SETCLASS -- set a string into a class
+**
+** Parameters:
+** class -- the class to put the string in.
+** str -- the string to enter
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** puts the word into the symbol table.
+*/
+
+void
+setclass(class, str)
+ int class;
+ char *str;
+{
+ register STAB *s;
+
+ if (tTd(37, 8))
+ printf("setclass(%s, %s)\n", macname(class), str);
+ s = stab(str, ST_CLASS, ST_ENTER);
+ setbitn(class, s->s_class);
+}
+ /*
+** MAKEMAPENTRY -- create a map entry
+**
+** Parameters:
+** line -- the config file line
+**
+** Returns:
+** A pointer to the map that has been created.
+** NULL if there was a syntax error.
+**
+** Side Effects:
+** Enters the map into the dictionary.
+*/
+
+MAP *
+makemapentry(line)
+ char *line;
+{
+ register char *p;
+ char *mapname;
+ char *classname;
+ register STAB *s;
+ 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 NULL;
+ }
+
+ mapname = p;
+ while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *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 NULL;
+ }
+ 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 NULL;
+ }
+
+ /* enter the map */
+ s = stab(mapname, ST_MAP, ST_ENTER);
+ s->s_map.map_class = &class->s_mapclass;
+ s->s_map.map_mname = newstr(mapname);
+
+ if (class->s_mapclass.map_parse(&s->s_map, p))
+ s->s_map.map_mflags |= MF_VALID;
+
+ if (tTd(37, 5))
+ {
+ printf("map %s, class %s, flags %x, file %s,\n",
+ s->s_map.map_mname, s->s_map.map_class->map_cname,
+ s->s_map.map_mflags,
+ s->s_map.map_file == NULL ? "(null)" : s->s_map.map_file);
+ printf("\tapp %s, domain %s, rebuild %s\n",
+ s->s_map.map_app == NULL ? "(null)" : s->s_map.map_app,
+ s->s_map.map_domain == NULL ? "(null)" : s->s_map.map_domain,
+ s->s_map.map_rebuild == NULL ? "(null)" : s->s_map.map_rebuild);
+ }
+
+ return &s->s_map;
+}
+ /*
+** STRTORWSET -- convert string to rewriting set number
+**
+** Parameters:
+** p -- the pointer to the string to decode.
+** endp -- if set, store the trailing delimiter here.
+** stabmode -- ST_ENTER to create this entry, ST_FIND if
+** it must already exist.
+**
+** Returns:
+** The appropriate ruleset number.
+** -1 if it is not valid (error already printed)
+*/
+
+int
+strtorwset(p, endp, stabmode)
+ char *p;
+ char **endp;
+ int stabmode;
+{
+ int ruleset;
+ static int nextruleset = MAXRWSETS;
+
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (!isascii(*p))
+ {
+ syserr("invalid ruleset name: \"%.20s\"", p);
+ return -1;
+ }
+ if (isdigit(*p))
+ {
+ ruleset = strtol(p, endp, 10);
+ if (ruleset >= MAXRWSETS / 2 || ruleset < 0)
+ {
+ syserr("bad ruleset %d (%d max)",
+ ruleset, MAXRWSETS / 2);
+ ruleset = -1;
+ }
+ }
+ else
+ {
+ STAB *s;
+ char delim;
+ char *q;
+
+ q = p;
+ while (*p != '\0' && isascii(*p) &&
+ (isalnum(*p) || *p == '_'))
+ p++;
+ if (q == p || !isalpha(*q))
+ {
+ /* no valid characters */
+ syserr("invalid ruleset name: \"%.20s\"", q);
+ return -1;
+ }
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ delim = *p;
+ if (delim != '\0')
+ *p = '\0';
+ s = stab(q, ST_RULESET, stabmode);
+ if (delim != '\0')
+ *p = delim;
+
+ if (s == NULL)
+ {
+ syserr("unknown ruleset %s", q);
+ return -1;
+ }
+
+ if (stabmode == ST_ENTER && delim == '=')
+ {
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ if (!isdigit(*p))
+ {
+ syserr("bad ruleset definition \"%s\" (number required after `=')", q);
+ ruleset = -1;
+ }
+ else
+ {
+ ruleset = strtol(p, endp, 10);
+ if (ruleset >= MAXRWSETS / 2 || ruleset < 0)
+ {
+ syserr("bad ruleset number %d in \"%s\" (%d max)",
+ ruleset, q, MAXRWSETS / 2);
+ ruleset = -1;
+ }
+ }
+ }
+ else
+ {
+ if (endp != NULL)
+ *endp = p;
+ if (s->s_ruleset > 0)
+ ruleset = s->s_ruleset;
+ else if ((ruleset = --nextruleset) < MAXRWSETS / 2)
+ {
+ syserr("%s: too many named rulesets (%d max)",
+ q, MAXRWSETS / 2);
+ ruleset = -1;
+ }
+ }
+ if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset)
+ {
+ syserr("%s: ruleset changed value (old %d, new %d)",
+ q, ruleset, s->s_ruleset);
+ ruleset = s->s_ruleset;
+ }
+ else if (ruleset > 0)
+ {
+ s->s_ruleset = ruleset;
+ }
+ }
+ return ruleset;
+}
+ /*
+** INITTIMEOUTS -- 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 SECONDS
+#define MINUTES * 60
+#define HOUR * 3600
+
+void
+inittimeouts(val)
+ register char *val;
+{
+ register char *p;
+ extern time_t convtime();
+
+ if (val == NULL)
+ {
+ TimeOuts.to_connect = (time_t) 0 SECONDS;
+ 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;
+#if IDENTPROTO
+ TimeOuts.to_ident = (time_t) 30 SECONDS;
+#else
+ TimeOuts.to_ident = (time_t) 0 SECONDS;
+#endif
+ TimeOuts.to_fileopen = (time_t) 60 SECONDS;
+ 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, ':');
+
+ if (q == NULL && (q = strchr(val, '=')) == NULL)
+ {
+ /* syntax error */
+ continue;
+ }
+ *q++ = '\0';
+ settimeout(val, q);
+ }
+ }
+}
+ /*
+** SETTIMEOUT -- set an individual timeout
+**
+** Parameters:
+** name -- the name of the timeout.
+** val -- the value of the timeout.
+**
+** Returns:
+** none.
+*/
+
+void
+settimeout(name, val)
+ char *name;
+ char *val;
+{
+ register char *p;
+ time_t to;
+ extern time_t convtime();
+
+ to = convtime(val, 'm');
+ p = strchr(name, '.');
+ if (p != NULL)
+ *p++ = '\0';
+
+ if (strcasecmp(name, "initial") == 0)
+ TimeOuts.to_initial = to;
+ else if (strcasecmp(name, "mail") == 0)
+ TimeOuts.to_mail = to;
+ else if (strcasecmp(name, "rcpt") == 0)
+ TimeOuts.to_rcpt = to;
+ else if (strcasecmp(name, "datainit") == 0)
+ TimeOuts.to_datainit = to;
+ else if (strcasecmp(name, "datablock") == 0)
+ TimeOuts.to_datablock = to;
+ else if (strcasecmp(name, "datafinal") == 0)
+ TimeOuts.to_datafinal = to;
+ else if (strcasecmp(name, "command") == 0)
+ TimeOuts.to_nextcommand = to;
+ else if (strcasecmp(name, "rset") == 0)
+ TimeOuts.to_rset = to;
+ else if (strcasecmp(name, "helo") == 0)
+ TimeOuts.to_helo = to;
+ else if (strcasecmp(name, "quit") == 0)
+ TimeOuts.to_quit = to;
+ else if (strcasecmp(name, "misc") == 0)
+ TimeOuts.to_miscshort = to;
+ else if (strcasecmp(name, "ident") == 0)
+ TimeOuts.to_ident = to;
+ else if (strcasecmp(name, "fileopen") == 0)
+ TimeOuts.to_fileopen = to;
+ else if (strcasecmp(name, "connect") == 0)
+ TimeOuts.to_connect = to;
+ else if (strcasecmp(name, "queuewarn") == 0)
+ {
+ to = convtime(val, 'h');
+ if (p == NULL || strcmp(p, "*") == 0)
+ {
+ TimeOuts.to_q_warning[TOC_NORMAL] = to;
+ TimeOuts.to_q_warning[TOC_URGENT] = to;
+ TimeOuts.to_q_warning[TOC_NONURGENT] = to;
+ }
+ else if (strcasecmp(p, "normal") == 0)
+ TimeOuts.to_q_warning[TOC_NORMAL] = to;
+ else if (strcasecmp(p, "urgent") == 0)
+ TimeOuts.to_q_warning[TOC_URGENT] = to;
+ else if (strcasecmp(p, "non-urgent") == 0)
+ TimeOuts.to_q_warning[TOC_NONURGENT] = to;
+ else
+ syserr("settimeout: invalid queuewarn subtimeout %s", p);
+ }
+ else if (strcasecmp(name, "queuereturn") == 0)
+ {
+ to = convtime(val, 'd');
+ if (p == NULL || strcmp(p, "*") == 0)
+ {
+ TimeOuts.to_q_return[TOC_NORMAL] = to;
+ TimeOuts.to_q_return[TOC_URGENT] = to;
+ TimeOuts.to_q_return[TOC_NONURGENT] = to;
+ }
+ else if (strcasecmp(p, "normal") == 0)
+ TimeOuts.to_q_return[TOC_NORMAL] = to;
+ else if (strcasecmp(p, "urgent") == 0)
+ TimeOuts.to_q_return[TOC_URGENT] = to;
+ else if (strcasecmp(p, "non-urgent") == 0)
+ TimeOuts.to_q_return[TOC_NONURGENT] = to;
+ else
+ syserr("settimeout: invalid queuereturn subtimeout %s", p);
+ }
+ else
+ syserr("settimeout: invalid timeout %s", name);
+}
diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c
new file mode 100644
index 000000000000..79126e9ccc5d
--- /dev/null
+++ b/usr.sbin/sendmail/src/recipient.c
@@ -0,0 +1,1349 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)recipient.c 8.108 (Berkeley) 10/30/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** SENDTOLIST -- Designate a send list.
+**
+** The parameter is a comma-separated list of people to send to.
+** This routine arranges to send to all of them.
+**
+** Parameters:
+** list -- the send list.
+** ctladdr -- the address template for the person to
+** send to -- effective uid/gid are important.
+** This is typically the alias that caused this
+** expansion.
+** sendq -- a pointer to the head of a queue to put
+** these people into.
+** aliaslevel -- the current alias nesting depth -- to
+** diagnose loops.
+** e -- the envelope in which to add these recipients.
+**
+** Returns:
+** The number of addresses actually on the list.
+**
+** Side Effects:
+** none.
+*/
+
+/* q_flags bits inherited from ctladdr */
+#define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY)
+
+int
+sendtolist(list, ctladdr, sendq, aliaslevel, e)
+ char *list;
+ ADDRESS *ctladdr;
+ ADDRESS **sendq;
+ int aliaslevel;
+ register ENVELOPE *e;
+{
+ register char *p;
+ register ADDRESS *al; /* list of addresses to send to */
+ bool firstone; /* set on first address sent */
+ char delimiter; /* the address delimiter */
+ int naddrs;
+ int i;
+ char *oldto = e->e_to;
+ char *bufp;
+ char buf[MAXNAME + 1];
+
+ if (list == NULL)
+ {
+ syserr("sendtolist: null list");
+ return 0;
+ }
+
+ if (tTd(25, 1))
+ {
+ printf("sendto: %s\n ctladdr=", list);
+ printaddr(ctladdr, FALSE);
+ }
+
+ /* heuristic to determine old versus new style addresses */
+ if (ctladdr == NULL &&
+ (strchr(list, ',') != NULL || strchr(list, ';') != NULL ||
+ strchr(list, '<') != NULL || strchr(list, '(') != NULL))
+ e->e_flags &= ~EF_OLDSTYLE;
+ delimiter = ' ';
+ if (!bitset(EF_OLDSTYLE, e->e_flags) || ctladdr != NULL)
+ delimiter = ',';
+
+ firstone = TRUE;
+ al = NULL;
+ naddrs = 0;
+
+ /* make sure we have enough space to copy the string */
+ i = strlen(list) + 1;
+ if (i <= sizeof buf)
+ bufp = buf;
+ else
+ bufp = xalloc(i);
+ strcpy(bufp, denlstring(list, FALSE, TRUE));
+
+ for (p = bufp; *p != '\0'; )
+ {
+ auto char *delimptr;
+ register ADDRESS *a;
+
+ /* parse the address */
+ while ((isascii(*p) && isspace(*p)) || *p == ',')
+ p++;
+ a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
+ p = delimptr;
+ if (a == NULL)
+ continue;
+ a->q_next = al;
+ a->q_alias = ctladdr;
+
+ /* arrange to inherit attributes from parent */
+ if (ctladdr != NULL)
+ {
+ ADDRESS *b;
+ extern ADDRESS *self_reference();
+
+ /* self reference test */
+ if (sameaddr(ctladdr, a))
+ {
+ if (tTd(27, 5))
+ {
+ printf("sendtolist: QSELFREF ");
+ printaddr(ctladdr, FALSE);
+ }
+ ctladdr->q_flags |= QSELFREF;
+ }
+
+ /* check for address loops */
+ b = self_reference(a, e);
+ if (b != NULL)
+ {
+ b->q_flags |= QSELFREF;
+ if (tTd(27, 5))
+ {
+ printf("sendtolist: QSELFREF ");
+ printaddr(b, FALSE);
+ }
+ if (a != b)
+ {
+ if (tTd(27, 5))
+ {
+ printf("sendtolist: QDONTSEND ");
+ printaddr(a, FALSE);
+ }
+ a->q_flags |= QDONTSEND;
+ b->q_flags |= a->q_flags & QNOTREMOTE;
+ continue;
+ }
+ }
+
+ /* full name */
+ if (a->q_fullname == NULL)
+ a->q_fullname = ctladdr->q_fullname;
+
+ /* various flag bits */
+ a->q_flags &= ~QINHERITEDBITS;
+ a->q_flags |= ctladdr->q_flags & QINHERITEDBITS;
+
+ /* original recipient information */
+ a->q_orcpt = ctladdr->q_orcpt;
+ }
+
+ al = a;
+ firstone = FALSE;
+ }
+
+ /* arrange to send to everyone on the local send list */
+ while (al != NULL)
+ {
+ register ADDRESS *a = al;
+
+ al = a->q_next;
+ a = recipient(a, sendq, aliaslevel, e);
+ naddrs++;
+ }
+
+ e->e_to = oldto;
+ if (bufp != buf)
+ free(bufp);
+ return (naddrs);
+}
+ /*
+** RECIPIENT -- Designate a message recipient
+**
+** Saves the named person for future mailing.
+**
+** Parameters:
+** a -- the (preparsed) address header for the recipient.
+** sendq -- a pointer to the head of a queue to put the
+** recipient in. Duplicate supression is done
+** in this queue.
+** aliaslevel -- the current alias nesting depth.
+** e -- the current envelope.
+**
+** Returns:
+** The actual address in the queue. This will be "a" if
+** the address is not a duplicate, else the original address.
+**
+** Side Effects:
+** none.
+*/
+
+ADDRESS *
+recipient(a, sendq, aliaslevel, e)
+ register ADDRESS *a;
+ register ADDRESS **sendq;
+ int aliaslevel;
+ 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 */
+ int findusercount = 0;
+ bool initialdontsend = bitset(QDONTSEND, a->q_flags);
+ int i;
+ char *buf;
+ char buf0[MAXNAME + 1]; /* unquoted image of the user name */
+ extern int safefile();
+
+ e->e_to = a->q_paddr;
+ m = a->q_mailer;
+ errno = 0;
+ if (aliaslevel == 0)
+ a->q_flags |= QPRIMARY;
+ if (tTd(26, 1))
+ {
+ printf("\nrecipient (%d): ", aliaslevel);
+ printaddr(a, FALSE);
+ }
+
+ /* if this is primary, add it to the original recipient list */
+ if (a->q_alias == NULL)
+ {
+ if (e->e_origrcpt == NULL)
+ e->e_origrcpt = a->q_paddr;
+ else if (e->e_origrcpt != a->q_paddr)
+ e->e_origrcpt = "";
+ }
+
+ /* break aliasing loops */
+ if (aliaslevel > MaxAliasRecursion)
+ {
+ a->q_status = "5.4.6";
+ usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max",
+ aliaslevel, MaxAliasRecursion);
+ return (a);
+ }
+
+ /*
+ ** Finish setting up address structure.
+ */
+
+ /* get unquoted user for file, program or user.name check */
+ i = strlen(a->q_user);
+ if (i >= sizeof buf0)
+ buf = xalloc(i + 1);
+ else
+ buf = buf0;
+ (void) strcpy(buf, a->q_user);
+ for (p = buf; *p != '\0' && !quoted; p++)
+ {
+ if (*p == '\\')
+ quoted = TRUE;
+ }
+ stripquotes(buf);
+
+ /* check for direct mailing to restricted mailers */
+ if (m == ProgMailer)
+ {
+ if (a->q_alias == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 Cannot mail directly to programs");
+ }
+ else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
+ a->q_alias->q_ruser, MyHostName);
+ }
+ else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 Address %s is unsafe for mailing to programs",
+ a->q_alias->q_paddr);
+ }
+ }
+
+ /*
+ ** Look up this person in the recipient list.
+ ** If they are there already, return, otherwise continue.
+ ** If the list is empty, just add it. Notice the cute
+ ** hack to make from addresses suppress things correctly:
+ ** the QDONTSEND bit will be set in the send list.
+ ** [Please note: the emphasis is on "hack."]
+ */
+
+ for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next)
+ {
+ if (sameaddr(q, a))
+ {
+ if (tTd(26, 1))
+ {
+ printf("%s in sendq: ", a->q_paddr);
+ printaddr(q, FALSE);
+ }
+ if (!bitset(QPRIMARY, q->q_flags))
+ {
+ if (!bitset(QDONTSEND, a->q_flags))
+ message("duplicate suppressed");
+ q->q_flags |= a->q_flags;
+ }
+ else if (bitset(QSELFREF, q->q_flags))
+ q->q_flags |= a->q_flags & ~QDONTSEND;
+ a = q;
+ goto done;
+ }
+ }
+
+ /* add address on list */
+ *pq = a;
+ a->q_next = NULL;
+
+ /*
+ ** Alias the name and handle special mailer types.
+ */
+
+ trylocaluser:
+ if (tTd(29, 7))
+ printf("at trylocaluser %s\n", a->q_user);
+
+ if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
+ goto testselfdestruct;
+
+ if (m == InclMailer)
+ {
+ a->q_flags |= QDONTSEND;
+ if (a->q_alias == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ 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, aliaslevel, e);
+ if (transienterror(ret))
+ {
+#ifdef LOG
+ if (LogLevel > 2)
+ syslog(LOG_ERR, "%s: include %s: transient error: %s",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ shortenstring(a->q_user, 203),
+ errstring(ret));
+#endif
+ a->q_flags |= QQUEUEUP;
+ a->q_flags &= ~QDONTSEND;
+ usrerr("451 Cannot open %s: %s",
+ shortenstring(a->q_user, 203),
+ errstring(ret));
+ }
+ else if (ret != 0)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.2.4";
+ usrerr("550 Cannot open %s: %s",
+ shortenstring(a->q_user, 203),
+ errstring(ret));
+ }
+ }
+ }
+ else if (m == FileMailer)
+ {
+ extern bool writable();
+
+ /* check if writable or creatable */
+ if (a->q_alias == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 Cannot mail directly to files");
+ }
+ else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
+ a->q_alias->q_ruser, MyHostName);
+ }
+ else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.7.1";
+ usrerr("550 Address %s is unsafe for mailing to files",
+ a->q_alias->q_paddr);
+ }
+ else if (!writable(buf, a->q_alias, SFF_CREAT))
+ {
+ a->q_flags |= QBADADDR;
+ giveresponse(EX_CANTCREAT, m, NULL, a->q_alias,
+ (time_t) 0, e);
+ }
+ }
+
+ /* try aliasing */
+ if (!quoted && !bitset(QDONTSEND, a->q_flags) &&
+ bitnset(M_ALIASABLE, m->m_flags))
+ alias(a, sendq, aliaslevel, e);
+
+# if USERDB
+ /* if not aliased, look it up in the user database */
+ if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) &&
+ bitnset(M_CHECKUDB, m->m_flags))
+ {
+ extern int udbexpand();
+
+ if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL)
+ {
+ a->q_flags |= QQUEUEUP;
+ 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 == NULL ? "NOQUEUE" : e->e_id,
+ errstring(errno));
+# endif
+ message("queued (user database error): %s",
+ errstring(errno));
+ e->e_nrcpts++;
+ goto testselfdestruct;
+ }
+ }
+# endif
+
+ /*
+ ** 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 (tTd(29, 5))
+ {
+ printf("recipient: testing local? cl=%d, rr5=%x\n\t",
+ ConfigLevel, RewriteRules[5]);
+ printaddr(a, FALSE);
+ }
+ if (!bitset(QNOTREMOTE|QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
+ ConfigLevel >= 2 && RewriteRules[5] != NULL &&
+ bitnset(M_TRYRULESET5, m->m_flags))
+ {
+ maplocaluser(a, sendq, aliaslevel + 1, e);
+ }
+
+ /*
+ ** If it didn't get rewritten to another mailer, go ahead
+ ** and deliver it.
+ */
+
+ if (!bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) &&
+ bitnset(M_HASPWENT, m->m_flags))
+ {
+ auto bool fuzzy;
+ register struct passwd *pw;
+ extern struct passwd *finduser();
+
+ /* warning -- finduser may trash buf */
+ pw = finduser(buf, &fuzzy);
+ if (pw == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.1.1";
+ giveresponse(EX_NOUSER, m, NULL, a->q_alias,
+ (time_t) 0, e);
+ }
+ else
+ {
+ char nbuf[MAXNAME + 1];
+
+ if (fuzzy)
+ {
+ /* name was a fuzzy match */
+ a->q_user = newstr(pw->pw_name);
+ if (findusercount++ > 3)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.4.6";
+ usrerr("554 aliasing/forwarding loop for %s broken",
+ pw->pw_name);
+ goto done;
+ }
+
+ /* see if it aliases */
+ (void) strcpy(buf, pw->pw_name);
+ goto trylocaluser;
+ }
+ if (strcmp(pw->pw_dir, "/") == 0)
+ a->q_home = "";
+ else
+ 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 (!usershellok(pw->pw_name, pw->pw_shell))
+ {
+ a->q_flags |= QBOGUSSHELL;
+ }
+ if (bitset(EF_VRFYONLY, e->e_flags))
+ {
+ /* don't do any more now */
+ a->q_flags |= QVERIFIED;
+ }
+ else if (!quoted)
+ forward(a, sendq, aliaslevel, e);
+ }
+ }
+ if (!bitset(QDONTSEND, a->q_flags))
+ e->e_nrcpts++;
+
+ testselfdestruct:
+ a->q_flags |= QTHISPASS;
+ if (tTd(26, 8))
+ {
+ printf("testselfdestruct: ");
+ printaddr(a, FALSE);
+ if (tTd(26, 10))
+ {
+ printf("SENDQ:\n");
+ printaddr(*sendq, TRUE);
+ printf("----\n");
+ }
+ }
+ if (a->q_alias == NULL && a != &e->e_from &&
+ bitset(QDONTSEND, a->q_flags))
+ {
+ for (q = *sendq; q != NULL; q = q->q_next)
+ {
+ if (!bitset(QDONTSEND, q->q_flags))
+ break;
+ }
+ if (q == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ a->q_status = "5.4.6";
+ usrerr("554 aliasing/forwarding loop broken");
+ }
+ }
+
+ done:
+ a->q_flags |= QTHISPASS;
+ if (buf != buf0)
+ free(buf);
+
+ /*
+ ** If we are at the top level, check to see if this has
+ ** expanded to exactly one address. If so, it can inherit
+ ** the primaryness of the address.
+ **
+ ** While we're at it, clear the QTHISPASS bits.
+ */
+
+ if (aliaslevel == 0)
+ {
+ int nrcpts = 0;
+ ADDRESS *only;
+
+ for (q = *sendq; q != NULL; q = q->q_next)
+ {
+ if (bitset(QTHISPASS, q->q_flags) &&
+ !bitset(QDONTSEND|QBADADDR, q->q_flags))
+ {
+ nrcpts++;
+ only = q;
+ }
+ q->q_flags &= ~QTHISPASS;
+ }
+ if (nrcpts == 1)
+ {
+ /* check to see if this actually got a new owner */
+ q = only;
+ while ((q = q->q_alias) != NULL)
+ {
+ if (q->q_owner != NULL)
+ break;
+ }
+ if (q == NULL)
+ only->q_flags |= QPRIMARY;
+ }
+ else if (!initialdontsend && nrcpts > 0)
+ {
+ /* arrange for return receipt */
+ e->e_flags |= EF_SENDRECEIPT;
+ a->q_flags |= QEXPANDED;
+ if (e->e_xfp != NULL && bitset(QPINGONSUCCESS, a->q_flags))
+ fprintf(e->e_xfp,
+ "%s... expanded to multiple addresses\n",
+ a->q_paddr);
+ }
+ }
+
+ return (a);
+}
+ /*
+** FINDUSER -- find the password entry for a user.
+**
+** This looks a lot like getpwnam, except that it may want to
+** do some fancier pattern matching in /etc/passwd.
+**
+** This routine contains most of the time of many sendmail runs.
+** It deserves to be optimized.
+**
+** 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.
+** NULL if name is unknown or ambiguous.
+**
+** Side Effects:
+** may modify name.
+*/
+
+struct passwd *
+finduser(name, fuzzyp)
+ char *name;
+ bool *fuzzyp;
+{
+ register struct passwd *pw;
+ register char *p;
+ bool tryagain;
+
+ if (tTd(29, 4))
+ printf("finduser(%s): ", name);
+
+ *fuzzyp = FALSE;
+
+#ifdef HESIOD
+ /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
+ for (p = name; *p != '\0'; p++)
+ if (!isascii(*p) || !isdigit(*p))
+ break;
+ if (*p == '\0')
+ {
+ if (tTd(29, 4))
+ printf("failed (numeric input)\n");
+ return NULL;
+ }
+#endif
+
+ /* look up this login name using fast path */
+ if ((pw = sm_getpwnam(name)) != NULL)
+ {
+ if (tTd(29, 4))
+ printf("found (non-fuzzy)\n");
+ return (pw);
+ }
+
+ /* try mapping it to lower case */
+ tryagain = FALSE;
+ for (p = name; *p != '\0'; p++)
+ {
+ if (isascii(*p) && isupper(*p))
+ {
+ *p = tolower(*p);
+ tryagain = TRUE;
+ }
+ }
+ if (tryagain && (pw = sm_getpwnam(name)) != NULL)
+ {
+ if (tTd(29, 4))
+ printf("found (lower case)\n");
+ *fuzzyp = TRUE;
+ return pw;
+ }
+
+#if 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++)
+ {
+ if (*p == (SpaceSub & 0177) || *p == '_')
+ *p = ' ';
+ }
+ (void) setpwent();
+ while ((pw = getpwent()) != NULL)
+ {
+ char buf[MAXNAME + 1];
+
+# if 0
+ if (strcasecmp(pw->pw_name, name) == 0)
+ {
+ if (tTd(29, 4))
+ printf("found (case wrapped)\n");
+ *fuzzyp = TRUE;
+ return pw;
+ }
+# endif
+
+ buildfname(pw->pw_gecos, pw->pw_name, buf);
+ if (strchr(buf, ' ') != NULL && !strcasecmp(buf, 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);
+ }
+ }
+ if (tTd(29, 4))
+ printf("no fuzzy match found\n");
+#else
+ if (tTd(29, 4))
+ printf("not found (fuzzy disabled)\n");
+#endif
+ return (NULL);
+}
+ /*
+** WRITABLE -- predicate returning if the file is writable.
+**
+** This routine must duplicate the algorithm in sys/fio.c.
+** Unfortunately, we cannot use the access call since we
+** won't necessarily be the real uid when we try to
+** actually open the file.
+**
+** Notice that ANY file with ANY execute bit is automatically
+** not writable. This is also enforced by mailfile.
+**
+** Parameters:
+** filename -- the file name to check.
+** ctladdr -- the controlling address for this file.
+** flags -- SFF_* flags to control the function.
+**
+** Returns:
+** TRUE -- if we will be able to write this file.
+** FALSE -- if we cannot write this file.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+writable(filename, ctladdr, flags)
+ char *filename;
+ ADDRESS *ctladdr;
+ int flags;
+{
+ uid_t euid;
+ gid_t egid;
+ char *uname;
+
+ if (tTd(44, 5))
+ printf("writable(%s, 0x%x)\n", filename, flags);
+
+ /*
+ ** File does exist -- check that it is writable.
+ */
+
+ if (ctladdr != NULL && geteuid() == 0)
+ {
+ euid = ctladdr->q_uid;
+ egid = ctladdr->q_gid;
+ uname = ctladdr->q_user;
+ }
+ else if (bitset(SFF_RUNASREALUID, flags))
+ {
+ euid = RealUid;
+ egid = RealGid;
+ uname = RealUserName;
+ }
+ else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags))
+ {
+ euid = FileMailer->m_uid;
+ egid = FileMailer->m_gid;
+ uname = NULL;
+ }
+ else
+ {
+ euid = egid = 0;
+ uname = NULL;
+ }
+ if (!bitset(SFF_ROOTOK, flags))
+ {
+ if (euid == 0)
+ {
+ euid = DefUid;
+ uname = DefUser;
+ }
+ if (egid == 0)
+ egid = DefGid;
+ }
+ if (geteuid() == 0 &&
+ (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags)))
+ flags |= SFF_SETUIDOK;
+
+ errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL);
+ return errno == 0;
+}
+ /*
+** INCLUDE -- handle :include: specification.
+**
+** Parameters:
+** fname -- filename to include.
+** 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.
+** sendq -- a pointer to the head of the send queue
+** to put these addresses in.
+** aliaslevel -- the alias nesting depth.
+** e -- the current envelope.
+**
+** Returns:
+** open error status
+**
+** Side Effects:
+** reads the :include: file and sends to everyone
+** listed in that file.
+**
+** Security Note:
+** If you have restricted chown (that is, you can't
+** give a file away), it is reasonable to allow programs
+** and files called from this :include: file to be to be
+** run as the owner of the :include: file. This is bogus
+** if there is any chance of someone giving away a file.
+** We assume that pre-POSIX systems can give away files.
+**
+** There is an additional restriction that if you
+** forward to a :include: file, it will not take on
+** the ownership of the :include: file. This may not
+** be necessary, but shouldn't hurt.
+*/
+
+static jmp_buf CtxIncludeTimeout;
+static void includetimeout();
+
+int
+include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
+ char *fname;
+ bool forwarding;
+ ADDRESS *ctladdr;
+ ADDRESS **sendq;
+ int aliaslevel;
+ ENVELOPE *e;
+{
+ FILE *volatile fp = NULL;
+ char *oldto = e->e_to;
+ char *oldfilename = FileName;
+ int oldlinenumber = LineNumber;
+ register EVENT *ev = NULL;
+ int nincludes;
+ register ADDRESS *ca;
+ volatile uid_t saveduid, uid;
+ volatile gid_t savedgid, gid;
+ char *volatile uname;
+ int rval = 0;
+ int sfflags = SFF_REGONLY;
+ struct stat st;
+ char buf[MAXLINE];
+#ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED == -1
+# define safechown FALSE
+# else
+# define safechown TRUE
+# endif
+#else
+# ifdef _PC_CHOWN_RESTRICTED
+ bool safechown;
+# else
+# ifdef BSD
+# define safechown TRUE
+# else
+# define safechown FALSE
+# endif
+# endif
+#endif
+ extern bool chownsafe();
+
+ if (tTd(27, 2))
+ printf("include(%s)\n", fname);
+ if (tTd(27, 4))
+ printf(" ruid=%d euid=%d\n", getuid(), geteuid());
+ if (tTd(27, 14))
+ {
+ printf("ctladdr ");
+ printaddr(ctladdr, FALSE);
+ }
+
+ if (tTd(27, 9))
+ printf("include: old uid = %d/%d\n", getuid(), geteuid());
+
+ if (forwarding)
+ sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOSLINK;
+
+ ca = getctladdr(ctladdr);
+ if (ca == NULL)
+ {
+ uid = DefUid;
+ gid = DefGid;
+ uname = DefUser;
+ }
+ else
+ {
+ uid = ca->q_uid;
+ gid = ca->q_gid;
+ uname = ca->q_user;
+ }
+#if HASSETREUID || USESETEUID
+ saveduid = geteuid();
+ savedgid = getegid();
+ if (saveduid == 0)
+ {
+ if (!DontInitGroups)
+ initgroups(uname, gid);
+ if (gid != 0)
+ (void) setgid(gid);
+ if (uid != 0)
+ {
+# if USESETEUID
+ if (seteuid(uid) < 0)
+ syserr("seteuid(%d) failure (real=%d, eff=%d)",
+ uid, getuid(), geteuid());
+# else
+ if (setreuid(0, uid) < 0)
+ syserr("setreuid(0, %d) failure (real=%d, eff=%d)",
+ uid, getuid(), geteuid());
+# endif
+ else
+ sfflags |= SFF_NOPATHCHECK;
+ }
+ }
+#endif
+
+ if (tTd(27, 9))
+ printf("include: new uid = %d/%d\n", getuid(), geteuid());
+
+ /*
+ ** If home directory is remote mounted but server is down,
+ ** this can hang or give errors; use a timeout to avoid this
+ */
+
+ if (setjmp(CtxIncludeTimeout) != 0)
+ {
+ ctladdr->q_flags |= QQUEUEUP;
+ errno = 0;
+
+ /* return pseudo-error code */
+ rval = EOPENTIMEOUT;
+ goto resetuid;
+ }
+ if (TimeOuts.to_fileopen > 0)
+ ev = setevent(TimeOuts.to_fileopen, includetimeout, 0);
+ else
+ ev = NULL;
+
+ /* the input file must be marked safe */
+ rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, NULL);
+ if (rval != 0)
+ {
+ /* don't use this :include: file */
+ if (tTd(27, 4))
+ printf("include: not safe (uid=%d): %s\n",
+ uid, errstring(rval));
+ }
+ else
+ {
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ {
+ rval = errno;
+ if (tTd(27, 4))
+ printf("include: open: %s\n", errstring(rval));
+ }
+ }
+ if (ev != NULL)
+ clrevent(ev);
+
+resetuid:
+
+#if HASSETREUID || USESETEUID
+ if (saveduid == 0)
+ {
+ if (uid != 0)
+ {
+# if USESETEUID
+ if (seteuid(0) < 0)
+ syserr("seteuid(0) failure (real=%d, eff=%d)",
+ getuid(), geteuid());
+# else
+ if (setreuid(-1, 0) < 0)
+ syserr("setreuid(-1, 0) failure (real=%d, eff=%d)",
+ getuid(), geteuid());
+ if (setreuid(RealUid, 0) < 0)
+ syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
+ RealUid, getuid(), geteuid());
+# endif
+ }
+ setgid(savedgid);
+ }
+#endif
+
+ if (tTd(27, 9))
+ printf("include: reset uid = %d/%d\n", getuid(), geteuid());
+
+ if (rval == EOPENTIMEOUT)
+ usrerr("451 open timeout on %s", fname);
+
+ if (fp == NULL)
+ return rval;
+
+ if (fstat(fileno(fp), &st) < 0)
+ {
+ rval = errno;
+ syserr("Cannot fstat %s!", fname);
+ return rval;
+ }
+
+#ifndef safechown
+ safechown = chownsafe(fileno(fp));
+#endif
+ if (ca == NULL && safechown)
+ {
+ ctladdr->q_uid = st.st_uid;
+ ctladdr->q_gid = st.st_gid;
+ ctladdr->q_flags |= QGOODUID;
+ }
+ if (ca != NULL && ca->q_uid == st.st_uid)
+ {
+ /* optimization -- avoid getpwuid if we already have info */
+ ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL;
+ ctladdr->q_ruser = ca->q_ruser;
+ }
+ else
+ {
+ register struct passwd *pw;
+
+ pw = sm_getpwuid(st.st_uid);
+ if (pw == NULL)
+ ctladdr->q_flags |= QBOGUSSHELL;
+ else
+ {
+ char *sh;
+
+ ctladdr->q_ruser = newstr(pw->pw_name);
+ if (safechown)
+ sh = pw->pw_shell;
+ else
+ sh = "/SENDMAIL/ANY/SHELL/";
+ if (!usershellok(pw->pw_name, sh))
+ {
+#ifdef LOG
+ if (LogLevel >= 12)
+ syslog(LOG_INFO, "%s: user %s has bad shell %s, marked %s",
+ shortenstring(fname, 203),
+ pw->pw_name, sh,
+ safechown ? "bogus" : "unsafe");
+#endif
+ if (safechown)
+ ctladdr->q_flags |= QBOGUSSHELL;
+ else
+ ctladdr->q_flags |= QUNSAFEADDR;
+ }
+ }
+ }
+
+ 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 rval;
+ }
+
+ /*
+ ** Check to see if some bad guy can write this file
+ **
+ ** This should really do something clever with group
+ ** permissions; currently we just view world writable
+ ** as unsafe. Also, we don't check for writable
+ ** directories in the path. We've got to leave
+ ** something for the local sysad to do.
+ */
+
+ if (bitset(S_IWOTH, st.st_mode))
+ {
+#ifdef LOG
+ if (LogLevel >= 12)
+ syslog(LOG_INFO, "%s: world writable %s file, marked unsafe",
+ shortenstring(fname, 203),
+ forwarding ? "forward" : ":include:");
+#endif
+ ctladdr->q_flags |= QUNSAFEADDR;
+ }
+
+ /* 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)
+ {
+ register char *p = strchr(buf, '\n');
+
+ LineNumber++;
+ if (p != NULL)
+ *p = '\0';
+ if (buf[0] == '#' || buf[0] == '\0')
+ continue;
+
+ /* <sp>#@# introduces a comment anywhere */
+ /* for Japanese character sets */
+ for (p = buf; (p = strchr(++p, '#')) != NULL; )
+ {
+ if (p[1] == '@' && p[2] == '#' &&
+ isascii(p[-1]) && isspace(p[-1]) &&
+ (p[3] == '\0' || (isascii(p[3]) && isspace(p[3]))))
+ {
+ p[-1] = '\0';
+ break;
+ }
+ }
+ if (buf[0] == '\0')
+ continue;
+
+ e->e_to = NULL;
+ message("%s to %s",
+ forwarding ? "forwarding" : "sending", buf);
+#ifdef LOG
+ if (forwarding && LogLevel > 9)
+ syslog(LOG_INFO, "%s: forward %.200s => %s",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ oldto, shortenstring(buf, 203));
+#endif
+
+ nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e);
+ }
+
+ if (ferror(fp) && tTd(27, 3))
+ printf("include: read error: %s\n", errstring(errno));
+ if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
+ {
+ if (tTd(27, 5))
+ {
+ printf("include: QDONTSEND ");
+ printaddr(ctladdr, FALSE);
+ }
+ ctladdr->q_flags |= QDONTSEND;
+ }
+
+ (void) xfclose(fp, "include", fname);
+ FileName = oldfilename;
+ LineNumber = oldlinenumber;
+ e->e_to = oldto;
+ return rval;
+}
+
+static void
+includetimeout()
+{
+ longjmp(CtxIncludeTimeout, 1);
+}
+ /*
+** SENDTOARGV -- send to an argument vector.
+**
+** Parameters:
+** argv -- argument vector to send to.
+** e -- the current envelope.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** puts all addresses on the argument vector onto the
+** send queue.
+*/
+
+void
+sendtoargv(argv, e)
+ register char **argv;
+ register ENVELOPE *e;
+{
+ register char *p;
+
+ while ((p = *argv++) != NULL)
+ {
+ (void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e);
+ }
+}
+ /*
+** GETCTLADDR -- get controlling address from an address header.
+**
+** If none, get one corresponding to the effective userid.
+**
+** Parameters:
+** a -- the address to find the controller of.
+**
+** Returns:
+** the controlling address.
+**
+** Side Effects:
+** none.
+*/
+
+ADDRESS *
+getctladdr(a)
+ register ADDRESS *a;
+{
+ while (a != NULL && !bitset(QGOODUID, a->q_flags))
+ a = a->q_alias;
+ return (a);
+}
+ /*
+** SELF_REFERENCE -- check to see if an address references itself
+**
+** The check is done through a chain of aliases. If it is part of
+** a loop, break the loop at the "best" address, that is, the one
+** that exists as a real user.
+**
+** This is to handle the case of:
+** awc: Andrew.Chang
+** Andrew.Chang: awc@mail.server
+** which is a problem only on mail.server.
+**
+** Parameters:
+** a -- the address to check.
+** e -- the current envelope.
+**
+** Returns:
+** The address that should be retained.
+*/
+
+ADDRESS *
+self_reference(a, e)
+ ADDRESS *a;
+ ENVELOPE *e;
+{
+ ADDRESS *b; /* top entry in self ref loop */
+ ADDRESS *c; /* entry that point to a real mail box */
+
+ if (tTd(27, 1))
+ printf("self_reference(%s)\n", a->q_paddr);
+
+ for (b = a->q_alias; b != NULL; b = b->q_alias)
+ {
+ if (sameaddr(a, b))
+ break;
+ }
+
+ if (b == NULL)
+ {
+ if (tTd(27, 1))
+ printf("\t... no self ref\n");
+ return NULL;
+ }
+
+ /*
+ ** Pick the first address that resolved to a real mail box
+ ** i.e has a pw entry. The returned value will be marked
+ ** QSELFREF in recipient(), which in turn will disable alias()
+ ** from marking it QDONTSEND, which mean it will be used
+ ** as a deliverable address.
+ **
+ ** The 2 key thing to note here are:
+ ** 1) we are in a recursive call sequence:
+ ** alias->sentolist->recipient->alias
+ ** 2) normally, when we return back to alias(), the address
+ ** will be marked QDONTSEND, since alias() assumes the
+ ** expanded form will be used instead of the current address.
+ ** This behaviour is turned off if the address is marked
+ ** QSELFREF We set QSELFREF when we return to recipient().
+ */
+
+ c = a;
+ while (c != NULL)
+ {
+ if (bitnset(M_HASPWENT, c->q_mailer->m_flags))
+ {
+ if (tTd(27, 2))
+ printf("\t... getpwnam(%s)... ", c->q_user);
+ if (sm_getpwnam(c->q_user) != NULL)
+ {
+ if (tTd(27, 2))
+ printf("found\n");
+
+ /* ought to cache results here */
+ if (sameaddr(b, c))
+ return b;
+ else
+ return c;
+ }
+ if (tTd(27, 2))
+ printf("failed\n");
+ }
+ c = c->q_alias;
+ }
+
+ if (tTd(27, 1))
+ printf("\t... cannot break loop for \"%s\"\n", a->q_paddr);
+
+ return NULL;
+}
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c
new file mode 100644
index 000000000000..78c9149980b2
--- /dev/null
+++ b/usr.sbin/sendmail/src/savemail.c
@@ -0,0 +1,1388 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)savemail.c 8.87 (Berkeley) 10/28/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** SAVEMAIL -- Save mail on error
+**
+** If mailing back errors, mail it back to the originator
+** together with an error message; otherwise, just put it in
+** dead.letter in the user's home directory (if he exists on
+** this machine).
+**
+** Parameters:
+** e -- the envelope containing the message in error.
+** sendbody -- if TRUE, also send back the body of the
+** message; otherwise just send the header.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Saves the letter, by writing or mailing it back to the
+** sender, or by putting it in dead.letter in her home
+** directory.
+*/
+
+/* defines for state machine */
+# define ESM_REPORT 0 /* report to sender's terminal */
+# define ESM_MAIL 1 /* mail back to sender */
+# define ESM_QUIET 2 /* messages have already been returned */
+# define ESM_DEADLETTER 3 /* save in ~/dead.letter */
+# define ESM_POSTMASTER 4 /* return to postmaster */
+# define ESM_USRTMP 5 /* save in /usr/tmp/dead.letter */
+# define ESM_PANIC 6 /* leave the locked queue/transcript files */
+# define ESM_DONE 7 /* the message is successfully delivered */
+
+# ifndef _PATH_VARTMP
+# define _PATH_VARTMP "/usr/tmp/"
+# endif
+
+
+void
+savemail(e, sendbody)
+ register ENVELOPE *e;
+ bool sendbody;
+{
+ register struct passwd *pw;
+ register FILE *fp;
+ int state;
+ auto ADDRESS *q = NULL;
+ register char *p;
+ MCI mcibuf;
+ int sfflags;
+ char buf[MAXLINE+1];
+ extern char *ttypath();
+ typedef int (*fnptr)();
+ extern bool writable();
+
+ if (tTd(6, 1))
+ {
+ printf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=",
+ e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id,
+ ExitStat);
+ printaddr(&e->e_from, FALSE);
+ }
+
+ if (e->e_id == NULL)
+ {
+ /* can't return a message with no id */
+ return;
+ }
+
+ /*
+ ** In the unhappy event we don't know who to return the mail
+ ** to, make someone up.
+ */
+
+ if (e->e_from.q_paddr == NULL)
+ {
+ e->e_sender = "Postmaster";
+ if (parseaddr(e->e_sender, &e->e_from,
+ RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL)
+ {
+ syserr("553 Cannot parse Postmaster!");
+ ExitStat = EX_SOFTWARE;
+ finis();
+ }
+ }
+ e->e_to = NULL;
+
+ /*
+ ** Basic state machine.
+ **
+ ** This machine runs through the following states:
+ **
+ ** ESM_QUIET Errors have already been printed iff the
+ ** sender is local.
+ ** ESM_REPORT Report directly to the sender's terminal.
+ ** ESM_MAIL Mail response to the sender.
+ ** ESM_DEADLETTER Save response in ~/dead.letter.
+ ** ESM_POSTMASTER Mail response to the postmaster.
+ ** ESM_PANIC Save response anywhere possible.
+ */
+
+ /* determine starting state */
+ switch (e->e_errormode)
+ {
+ case EM_WRITE:
+ state = ESM_REPORT;
+ break;
+
+ case EM_BERKNET:
+ case EM_MAIL:
+ state = ESM_MAIL;
+ break;
+
+ case EM_PRINT:
+ case '\0':
+ state = ESM_QUIET;
+ break;
+
+ case EM_QUIET:
+ /* no need to return anything at all */
+ return;
+
+ default:
+ syserr("554 savemail: bogus errormode x%x\n", e->e_errormode);
+ 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))
+ printf(" state %d\n", state);
+
+ switch (state)
+ {
+ case ESM_QUIET:
+ if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags))
+ state = ESM_DEADLETTER;
+ else
+ state = ESM_MAIL;
+ break;
+
+ case ESM_REPORT:
+
+ /*
+ ** If the user is still logged in on the same terminal,
+ ** then write the error messages back to hir (sic).
+ */
+
+ p = ttypath();
+ if (p == NULL || freopen(p, "w", stdout) == NULL)
+ {
+ state = ESM_MAIL;
+ break;
+ }
+
+ expand("\201n", buf, sizeof buf, e);
+ printf("\r\nMessage from %s...\r\n", buf);
+ printf("Errors occurred while sending mail.\r\n");
+ if (e->e_xfp != NULL)
+ {
+ (void) fflush(e->e_xfp);
+ fp = fopen(queuename(e, 'x'), "r");
+ }
+ else
+ fp = NULL;
+ if (fp == NULL)
+ {
+ syserr("Cannot open %s", queuename(e, 'x'));
+ printf("Transcript of session is unavailable.\r\n");
+ }
+ else
+ {
+ printf("Transcript follows:\r\n");
+ while (fgets(buf, sizeof buf, fp) != NULL &&
+ !ferror(stdout))
+ fputs(buf, stdout);
+ (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:
+ /*
+ ** If mailing back, do it.
+ ** Throw away all further output. Don't alias,
+ ** since this could cause loops, e.g., if joe
+ ** mails to joe@x, and for some reason the network
+ ** for @x is down, then the response gets sent to
+ ** joe@x, which gives a response, etc. Also force
+ ** the mail to be delivered even if a version of
+ ** it has already been sent to the sender.
+ **
+ ** If this is a configuration or local software
+ ** error, send to the local postmaster as well,
+ ** since the originator can't do anything
+ ** about it anyway. Note that this is a full
+ ** copy of the message (intentionally) so that
+ ** the Postmaster can forward things along.
+ */
+
+ if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE)
+ {
+ (void) sendtolist("postmaster",
+ NULLADDR, &e->e_errorqueue, 0, e);
+ }
+ if (!emptyaddr(&e->e_from))
+ {
+ (void) sendtolist(e->e_from.q_paddr,
+ NULLADDR, &e->e_errorqueue, 0, e);
+ }
+
+ /*
+ ** Deliver a non-delivery report to the
+ ** Postmaster-designate (not necessarily
+ ** Postmaster). This does not include the
+ ** body of the message, for privacy reasons.
+ ** You really shouldn't need this.
+ */
+
+ e->e_flags |= EF_PM_NOTIFY;
+
+ /* check to see if there are any good addresses */
+ for (q = e->e_errorqueue; q != NULL; q = q->q_next)
+ if (!bitset(QBADADDR|QDONTSEND, q->q_flags))
+ break;
+ if (q == NULL)
+ {
+ /* this is an error-error */
+ state = ESM_POSTMASTER;
+ break;
+ }
+ if (returntosender(e->e_message, e->e_errorqueue,
+ sendbody, e) == 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ /* 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, 0, e) <= 0)
+ {
+ syserr("553 cannot parse postmaster!");
+ ExitStat = EX_SOFTWARE;
+ state = ESM_USRTMP;
+ break;
+ }
+ if (returntosender(e->e_message, q, sendbody, e) == 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ /* didn't work -- last resort */
+ state = ESM_USRTMP;
+ break;
+
+ case ESM_DEADLETTER:
+ /*
+ ** Save the message in dead.letter.
+ ** If we weren't mailing back, and the user is
+ ** local, we should save the message in
+ ** ~/dead.letter so that the poor person doesn't
+ ** have to type it over again -- and we all know
+ ** what poor typists UNIX users are.
+ */
+
+ p = NULL;
+ if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags))
+ {
+ if (e->e_from.q_home != NULL)
+ p = e->e_from.q_home;
+ else if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL)
+ p = pw->pw_dir;
+ }
+ if (p == NULL || e->e_dfp == NULL)
+ {
+ /* no local directory or no data file */
+ state = ESM_MAIL;
+ break;
+ }
+
+ /* we have a home directory; write dead.letter */
+ define('z', p, e);
+ expand("\201z/dead.letter", buf, sizeof buf, e);
+ sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
+ e->e_to = buf;
+ if (mailfile(buf, NULL, sfflags, e) == EX_OK)
+ {
+ bool oldverb = Verbose;
+
+ Verbose = TRUE;
+ message("Saved message in %s", buf);
+ Verbose = oldverb;
+ state = ESM_DONE;
+ break;
+ }
+ state = ESM_MAIL;
+ break;
+
+ case ESM_USRTMP:
+ /*
+ ** Log the mail in /usr/tmp/dead.letter.
+ */
+
+ if (e->e_class < 0)
+ {
+ state = ESM_DONE;
+ break;
+ }
+
+ if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0')
+ {
+ state = ESM_PANIC;
+ break;
+ }
+
+ strcpy(buf, _PATH_VARTMP);
+ strcat(buf, "dead.letter");
+
+ sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
+ if (!writable(buf, NULL, sfflags) ||
+ (fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND,
+ FileMode, sfflags)) == NULL)
+ {
+ state = ESM_PANIC;
+ break;
+ }
+
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_out = fp;
+ mcibuf.mci_mailer = FileMailer;
+ if (bitnset(M_7BITS, FileMailer->m_flags))
+ mcibuf.mci_flags |= MCIF_7BIT;
+
+ putfromline(&mcibuf, e);
+ (*e->e_puthdr)(&mcibuf, e->e_header, e);
+ (*e->e_putbody)(&mcibuf, e, NULL);
+ putline("\n", &mcibuf);
+ (void) fflush(fp);
+ if (!ferror(fp))
+ {
+ bool oldverb = Verbose;
+
+ Verbose = TRUE;
+ message("Saved message in %s", buf);
+ Verbose = oldverb;
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_NOTICE, "Saved message in %s", buf);
+#endif
+ state = ESM_DONE;
+ break;
+ }
+ state = ESM_PANIC;
+ (void) xfclose(fp, "savemail", buf);
+ break;
+
+ default:
+ syserr("554 savemail: unknown state %d", state);
+
+ /* fall through ... */
+
+ case ESM_PANIC:
+ /* leave the locked queue & transcript files around */
+ loseqfile(e, "savemail panic");
+ syserr("!554 savemail: cannot save rejected email anywhere");
+ }
+ }
+}
+ /*
+** RETURNTOSENDER -- return a message to the sender with an error.
+**
+** Parameters:
+** msg -- the explanatory message.
+** 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.
+** else -- some error.
+**
+** Side Effects:
+** Returns the current message to the sender via
+** mail.
+*/
+
+#define MAXRETURNS 6 /* max depth of returning messages */
+#define ERRORFUDGE 100 /* nominal size of error message text */
+
+int
+returntosender(msg, returnq, sendbody, e)
+ char *msg;
+ ADDRESS *returnq;
+ bool sendbody;
+ register ENVELOPE *e;
+{
+ register ENVELOPE *ee;
+ ENVELOPE *oldcur = CurEnv;
+ ENVELOPE errenvelope;
+ static int returndepth;
+ register ADDRESS *q;
+ char *p;
+ char buf[MAXNAME + 1];
+ extern void errbody __P((MCI *, ENVELOPE *, char *));
+
+ if (returnq == NULL)
+ return (-1);
+
+ if (msg == NULL)
+ msg = "Unable to deliver mail";
+
+ if (tTd(6, 1))
+ {
+ printf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%x, returnq=",
+ msg, returndepth, e);
+ printaddr(returnq, TRUE);
+ if (tTd(6, 20))
+ {
+ printf("Sendq=");
+ printaddr(e->e_sendqueue, TRUE);
+ }
+ }
+
+ if (++returndepth >= MAXRETURNS)
+ {
+ if (returndepth != MAXRETURNS)
+ syserr("554 returntosender: infinite recursion on %s", returnq->q_paddr);
+ /* don't "unrecurse" and fake a clean exit */
+ /* returndepth--; */
+ return (0);
+ }
+
+ define('g', e->e_from.q_paddr, e);
+ define('u', NULL, e);
+
+ /* initialize error envelope */
+ 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|EF_METOO;
+ if (!bitset(EF_OLDSTYLE, e->e_flags))
+ ee->e_flags &= ~EF_OLDSTYLE;
+ ee->e_sendqueue = returnq;
+ ee->e_msgsize = ERRORFUDGE;
+ if (sendbody)
+ ee->e_msgsize += e->e_msgsize;
+ else
+ ee->e_flags |= EF_NO_BODY_RETN;
+ initsys(ee);
+ for (q = returnq; q != NULL; q = q->q_next)
+ {
+ if (bitset(QBADADDR, q->q_flags))
+ continue;
+
+ if (!DontPruneRoutes && pruneroute(q->q_paddr))
+ {
+ register ADDRESS *p;
+
+ parseaddr(q->q_paddr, q, RF_COPYPARSE, '\0', NULL, e);
+ for (p = returnq; p != NULL; p = p->q_next)
+ {
+ if (p != q && sameaddr(p, q))
+ q->q_flags |= QDONTSEND;
+ }
+ }
+
+ if (!bitset(QDONTSEND, q->q_flags))
+ ee->e_nrcpts++;
+
+ if (q->q_alias == NULL)
+ addheader("To", q->q_paddr, &ee->e_header);
+ }
+
+# ifdef LOG
+ if (LogLevel > 5)
+ {
+ if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags))
+ p = "return to sender";
+ else
+ p = "postmaster notify";
+ syslog(LOG_INFO, "%s: %s: %s: %s",
+ e->e_id, ee->e_id, p, shortenstring(msg, 203));
+ }
+# endif
+
+ if (SendMIMEErrors)
+ {
+ addheader("MIME-Version", "1.0", &ee->e_header);
+
+ (void) sprintf(buf, "%s.%ld/%.100s",
+ ee->e_id, curtime(), MyHostName);
+ ee->e_msgboundary = newstr(buf);
+ (void) sprintf(buf,
+#if DSN
+ "multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"",
+#else
+ "multipart/mixed; boundary=\"%s\"",
+#endif
+ ee->e_msgboundary);
+ addheader("Content-Type", buf, &ee->e_header);
+
+ p = hvalue("Content-Transfer-Encoding", e->e_header);
+ if (p != NULL && strcasecmp(p, "binary") != 0)
+ p = NULL;
+ if (p == NULL && bitset(EF_HAS8BIT, e->e_flags))
+ p = "8bit";
+ if (p != NULL)
+ addheader("Content-Transfer-Encoding", p, &ee->e_header);
+ }
+ if (strncmp(msg, "Warning:", 8) == 0)
+ {
+ addheader("Subject", msg, &ee->e_header);
+ p = "warning-timeout";
+ }
+ else if (strncmp(msg, "Postmaster warning:", 19) == 0)
+ {
+ addheader("Subject", msg, &ee->e_header);
+ p = "postmaster-warning";
+ }
+ else if (strcmp(msg, "Return receipt") == 0)
+ {
+ addheader("Subject", msg, &ee->e_header);
+ p = "return-receipt";
+ }
+ else
+ {
+ sprintf(buf, "Returned mail: %.*s", sizeof buf - 20, msg);
+ addheader("Subject", buf, &ee->e_header);
+ p = "failure";
+ }
+ (void) sprintf(buf, "auto-generated (%s)", p);
+ addheader("Auto-Submitted", buf, &ee->e_header);
+
+ /* fake up an address header for the from person */
+ expand("\201n", buf, sizeof buf, e);
+ if (parseaddr(buf, &ee->e_from, RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL)
+ {
+ syserr("553 Can't parse myself!");
+ ExitStat = EX_SOFTWARE;
+ returndepth--;
+ return (-1);
+ }
+ ee->e_sender = ee->e_from.q_paddr;
+
+ /* push state into submessage */
+ CurEnv = ee;
+ define('f', "\201n", ee);
+ define('x', "Mail Delivery Subsystem", ee);
+ eatheader(ee, TRUE);
+
+ /* mark statistics */
+ markstats(ee, NULLADDR);
+
+ /* actually deliver the error message */
+ sendall(ee, SM_DEFAULT);
+
+ /* restore state */
+ dropenvelope(ee);
+ CurEnv = oldcur;
+ returndepth--;
+
+ /* check for delivery errors */
+ if (ee->e_parent == NULL || !bitset(EF_RESPONSE, ee->e_parent->e_flags))
+ return 0;
+ for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QSENT, q->q_flags))
+ return 0;
+ }
+ return -1;
+}
+ /*
+** ERRBODY -- output the body of an error message.
+**
+** Typically this is a copy of the transcript plus a copy of the
+** original offending message.
+**
+** Parameters:
+** mci -- the mailer connection information.
+** e -- the envelope we are working in.
+** separator -- any possible MIME separator.
+** flags -- to modify the behaviour.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** Outputs the body of an error message.
+*/
+
+void
+errbody(mci, e, separator)
+ register MCI *mci;
+ register ENVELOPE *e;
+ char *separator;
+{
+ register FILE *xfile;
+ char *p;
+ register ADDRESS *q;
+ bool printheader;
+ bool sendbody;
+ char buf[MAXLINE];
+ extern char *xuntextify();
+
+ if (bitset(MCIF_INHEADER, mci->mci_flags))
+ {
+ putline("", mci);
+ mci->mci_flags &= ~MCIF_INHEADER;
+ }
+ if (e->e_parent == NULL)
+ {
+ syserr("errbody: null parent");
+ putline(" ----- Original message lost -----\n", mci);
+ return;
+ }
+
+ /*
+ ** Output MIME header.
+ */
+
+ if (e->e_msgboundary != NULL)
+ {
+ putline("This is a MIME-encapsulated message", mci);
+ putline("", mci);
+ (void) sprintf(buf, "--%s", e->e_msgboundary);
+ putline(buf, mci);
+ putline("", mci);
+ }
+
+ /*
+ ** Output introductory information.
+ */
+
+ for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+ if (bitset(QBADADDR, q->q_flags))
+ break;
+ if (q == NULL &&
+ !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
+ {
+ putline(" **********************************************",
+ mci);
+ putline(" ** THIS IS A WARNING MESSAGE ONLY **",
+ mci);
+ putline(" ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **",
+ mci);
+ putline(" **********************************************",
+ mci);
+ putline("", mci);
+ }
+ sprintf(buf, "The original message was received at %s",
+ arpadate(ctime(&e->e_parent->e_ctime)));
+ putline(buf, mci);
+ expand("from \201_", buf, sizeof buf, e->e_parent);
+ putline(buf, mci);
+ putline("", mci);
+
+ /*
+ ** Output error message header (if specified and available).
+ */
+
+ if (ErrMsgFile != NULL && !bitset(EF_SENDRECEIPT, e->e_parent->e_flags))
+ {
+ if (*ErrMsgFile == '/')
+ {
+ xfile = fopen(ErrMsgFile, "r");
+ if (xfile != NULL)
+ {
+ while (fgets(buf, sizeof buf, xfile) != NULL)
+ {
+ expand(buf, buf, sizeof buf, e);
+ putline(buf, mci);
+ }
+ (void) fclose(xfile);
+ putline("\n", mci);
+ }
+ }
+ else
+ {
+ expand(ErrMsgFile, buf, sizeof buf, e);
+ putline(buf, mci);
+ putline("", mci);
+ }
+ }
+
+ /*
+ ** 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 (!bitset(QPINGONFAILURE, q->q_flags))
+ continue;
+ p = "unrecoverable error";
+ }
+ else if (!bitset(QPRIMARY, q->q_flags))
+ continue;
+ else if (bitset(QDELAYED, q->q_flags))
+ p = "transient failure";
+ else if (!bitset(QPINGONSUCCESS, q->q_flags))
+ continue;
+ else if (bitset(QRELAYED, q->q_flags))
+ p = "relayed to non-DSN-aware mailer";
+ else if (bitset(QDELIVERED, q->q_flags))
+ {
+ if (bitset(QEXPANDED, q->q_flags))
+ p = "successfully delivered to mailing list";
+ else
+ p = "successfully delivered to mailbox";
+ }
+ else if (bitset(QEXPANDED, q->q_flags))
+ p = "expanded by alias";
+ else
+ continue;
+
+ if (printheader)
+ {
+ putline(" ----- The following addresses have delivery notifications -----",
+ mci);
+ printheader = FALSE;
+ }
+
+ sprintf(buf, "%s (%s)", shortenstring(q->q_paddr, 203), p);
+ putline(buf, mci);
+ if (q->q_alias != NULL)
+ {
+ sprintf(buf, " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr, 203));
+ putline(buf, mci);
+ }
+ }
+ if (!printheader)
+ putline("\n", mci);
+
+ /*
+ ** Output transcript of errors
+ */
+
+ (void) fflush(stdout);
+ p = queuename(e->e_parent, 'x');
+ if ((xfile = fopen(p, "r")) == NULL)
+ {
+ syserr("Cannot open %s", p);
+ putline(" ----- Transcript of session is unavailable -----\n", mci);
+ }
+ else
+ {
+ printheader = TRUE;
+ if (e->e_xfp != NULL)
+ (void) fflush(e->e_xfp);
+ while (fgets(buf, sizeof buf, xfile) != NULL)
+ {
+ if (printheader)
+ putline(" ----- Transcript of session follows -----\n", mci);
+ printheader = FALSE;
+ putline(buf, mci);
+ }
+ (void) xfclose(xfile, "errbody xscript", p);
+ }
+ errno = 0;
+
+#if DSN
+ /*
+ ** Output machine-readable version.
+ */
+
+ if (e->e_msgboundary != NULL)
+ {
+ putline("", mci);
+ (void) sprintf(buf, "--%s", e->e_msgboundary);
+ putline(buf, mci);
+ putline("Content-Type: message/delivery-status", mci);
+ putline("", mci);
+
+ /*
+ ** Output per-message information.
+ */
+
+ /* original envelope id from MAIL FROM: line */
+ if (e->e_parent->e_envid != NULL)
+ {
+ (void) sprintf(buf, "Original-Envelope-Id: %.800s",
+ xuntextify(e->e_parent->e_envid));
+ putline(buf, mci);
+ }
+
+ /* Reporting-MTA: is us (required) */
+ (void) sprintf(buf, "Reporting-MTA: dns; %.800s", MyHostName);
+ putline(buf, mci);
+
+ /* DSN-Gateway: not relevant since we are not translating */
+
+ /* Received-From-MTA: shows where we got this message from */
+ if (RealHostName != NULL)
+ {
+ /* XXX use $s for type? */
+ if (e->e_parent->e_from.q_mailer == NULL ||
+ (p = e->e_parent->e_from.q_mailer->m_mtatype) == NULL)
+ p = "dns";
+ (void) sprintf(buf, "Received-From-MTA: %s; %.800s",
+ p, RealHostName);
+ putline(buf, mci);
+ }
+
+ /* Arrival-Date: -- when it arrived here */
+ (void) sprintf(buf, "Arrival-Date: %s",
+ arpadate(ctime(&e->e_parent->e_ctime)));
+ putline(buf, mci);
+
+ /*
+ ** Output per-address information.
+ */
+
+ for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ register ADDRESS *r;
+ char *action;
+
+ if (bitset(QBADADDR, q->q_flags))
+ action = "failed";
+ else if (!bitset(QPRIMARY, q->q_flags))
+ continue;
+ else if (bitset(QDELIVERED, q->q_flags))
+ {
+ if (bitset(QEXPANDED, q->q_flags))
+ action = "delivered (to mailing list)";
+ else
+ action = "delivered (to mailbox)";
+ }
+ else if (bitset(QRELAYED, q->q_flags))
+ action = "relayed (to non-DSN-aware mailer)";
+ else if (bitset(QEXPANDED, q->q_flags))
+ action = "expanded (to multi-recipient alias)";
+ else if (bitset(QDELAYED, q->q_flags))
+ action = "delayed";
+ else
+ continue;
+
+ putline("", mci);
+
+ /* Original-Recipient: -- passed from on high */
+ if (q->q_orcpt != NULL)
+ {
+ (void) sprintf(buf, "Original-Recipient: %.800s",
+ q->q_orcpt);
+ putline(buf, mci);
+ }
+
+ /* Final-Recipient: -- the name from the RCPT command */
+ p = e->e_parent->e_from.q_mailer->m_addrtype;
+ if (p == NULL)
+ p = "rfc822";
+ for (r = q; r->q_alias != NULL; r = r->q_alias)
+ continue;
+ if (strchr(r->q_user, '@') == NULL)
+ {
+ (void) sprintf(buf, "Final-Recipient: %s; %.700s@%.100s",
+ p, r->q_user, MyHostName);
+ }
+ else
+ {
+ (void) sprintf(buf, "Final-Recipient: %s; %.800s",
+ p, r->q_user);
+ }
+ putline(buf, mci);
+
+ /* X-Actual-Recipient: -- the real problem address */
+ if (r != q && q->q_user[0] != '\0')
+ {
+ if (strchr(q->q_user, '@') == NULL)
+ {
+ (void) sprintf(buf, "X-Actual-Recipient: %s; %.700s@%.100s",
+ p, q->q_user, MyHostName);
+ }
+ else
+ {
+ (void) sprintf(buf, "X-Actual-Recipient: %s; %.800s",
+ p, q->q_user);
+ }
+ putline(buf, mci);
+ }
+
+ /* Action: -- what happened? */
+ sprintf(buf, "Action: %s", action);
+ putline(buf, mci);
+
+ /* Status: -- what _really_ happened? */
+ strcpy(buf, "Status: ");
+ if (q->q_status != NULL)
+ strcat(buf, q->q_status);
+ else if (bitset(QBADADDR, q->q_flags))
+ strcat(buf, "5.0.0");
+ else if (bitset(QQUEUEUP, q->q_flags))
+ strcat(buf, "4.0.0");
+ else
+ strcat(buf, "2.0.0");
+ putline(buf, mci);
+
+ /* Remote-MTA: -- who was I talking to? */
+ if (q->q_statmta != NULL)
+ {
+ if (q->q_mailer == NULL ||
+ (p = q->q_mailer->m_mtatype) == NULL)
+ p = "dns";
+ (void) sprintf(buf, "Remote-MTA: %s; %.800s",
+ p, q->q_statmta);
+ p = &buf[strlen(buf) - 1];
+ if (*p == '.')
+ *p = '\0';
+ putline(buf, mci);
+ }
+
+ /* Diagnostic-Code: -- actual result from other end */
+ if (q->q_rstatus != NULL)
+ {
+ p = q->q_mailer->m_diagtype;
+ if (p == NULL)
+ p = "smtp";
+ (void) sprintf(buf, "Diagnostic-Code: %s; %.800s",
+ p, q->q_rstatus);
+ putline(buf, mci);
+ }
+
+ /* Last-Attempt-Date: -- fine granularity */
+ if (q->q_statdate == (time_t) 0L)
+ q->q_statdate = curtime();
+ (void) sprintf(buf, "Last-Attempt-Date: %s",
+ arpadate(ctime(&q->q_statdate)));
+ putline(buf, mci);
+
+ /* Will-Retry-Until: -- for delayed messages only */
+ if (bitset(QQUEUEUP, q->q_flags) &&
+ !bitset(QBADADDR, q->q_flags))
+ {
+ time_t xdate;
+
+ xdate = e->e_parent->e_ctime +
+ TimeOuts.to_q_return[e->e_parent->e_timeoutclass];
+ sprintf(buf, "Will-Retry-Until: %s",
+ arpadate(ctime(&xdate)));
+ putline(buf, mci);
+ }
+ }
+ }
+#endif
+
+ /*
+ ** Output text of original message
+ */
+
+ putline("", mci);
+ if (bitset(EF_HAS_DF, e->e_parent->e_flags))
+ {
+ sendbody = !bitset(EF_NO_BODY_RETN, e->e_parent->e_flags) &&
+ !bitset(EF_NO_BODY_RETN, e->e_flags);
+
+ if (e->e_msgboundary == NULL)
+ {
+ if (sendbody)
+ putline(" ----- Original message follows -----\n", mci);
+ else
+ putline(" ----- Message header follows -----\n", mci);
+ (void) fflush(mci->mci_out);
+ }
+ else
+ {
+ (void) sprintf(buf, "--%s", e->e_msgboundary);
+
+ putline(buf, mci);
+ (void) sprintf(buf, "Content-Type: %s",
+ sendbody ? "message/rfc822"
+ : "text/rfc822-headers");
+ putline(buf, mci);
+
+ p = hvalue("Content-Transfer-Encoding", e->e_parent->e_header);
+ if (p != NULL && strcasecmp(p, "binary") != 0)
+ p = NULL;
+ if (p == NULL && bitset(EF_HAS8BIT, e->e_parent->e_flags))
+ p = "8bit";
+ if (p != NULL)
+ {
+ (void) sprintf(buf, "Content-Transfer-Encoding: %s",
+ p);
+ putline(buf, mci);
+ }
+ }
+ putline("", mci);
+ putheader(mci, e->e_parent->e_header, e->e_parent);
+ if (sendbody)
+ putbody(mci, e->e_parent, e->e_msgboundary);
+ else if (e->e_msgboundary == NULL)
+ {
+ putline("", mci);
+ putline(" ----- Message body suppressed -----", mci);
+ }
+ }
+ else if (e->e_msgboundary == NULL)
+ {
+ putline(" ----- No message was collected -----\n", mci);
+ }
+
+ if (e->e_msgboundary != NULL)
+ {
+ putline("", mci);
+ (void) sprintf(buf, "--%s--", e->e_msgboundary);
+ putline(buf, mci);
+ }
+ putline("", mci);
+
+ /*
+ ** Cleanup and exit
+ */
+
+ if (errno != 0)
+ syserr("errbody: I/O error");
+}
+ /*
+** SMTPTODSN -- convert SMTP to DSN status code
+**
+** Parameters:
+** smtpstat -- the smtp status code (e.g., 550).
+**
+** Returns:
+** The DSN version of the status code.
+*/
+
+char *
+smtptodsn(smtpstat)
+ int smtpstat;
+{
+ if (smtpstat < 0)
+ return "4.4.2";
+
+ switch (smtpstat)
+ {
+ case 450: /* Req mail action not taken: mailbox unavailable */
+ return "4.2.0";
+
+ case 451: /* Req action aborted: local error in processing */
+ return "4.3.0";
+
+ case 452: /* Req action not taken: insufficient sys storage */
+ return "4.3.1";
+
+ case 500: /* Syntax error, command unrecognized */
+ return "5.5.2";
+
+ case 501: /* Syntax error in parameters or arguments */
+ return "5.5.4";
+
+ case 502: /* Command not implemented */
+ return "5.5.1";
+
+ case 503: /* Bad sequence of commands */
+ return "5.5.1";
+
+ case 504: /* Command parameter not implemented */
+ return "5.5.4";
+
+ case 550: /* Req mail action not taken: mailbox unavailable */
+ return "5.2.0";
+
+ case 551: /* User not local; please try <...> */
+ return "5.1.6";
+
+ case 552: /* Req mail action aborted: exceeded storage alloc */
+ return "5.2.2";
+
+ case 553: /* Req action not taken: mailbox name not allowed */
+ return "5.1.3";
+
+ case 554: /* Transaction failed */
+ return "5.0.0";
+ }
+
+ if ((smtpstat / 100) == 2)
+ return "2.0.0";
+ if ((smtpstat / 100) == 4)
+ return "4.0.0";
+ return "5.0.0";
+}
+ /*
+** XTEXTIFY -- take regular text and turn it into DSN-style xtext
+**
+** Parameters:
+** t -- the text to convert.
+**
+** Returns:
+** The xtext-ified version of the same string.
+*/
+
+char *
+xtextify(t)
+ register char *t;
+{
+ register char *p;
+ int l;
+ int nbogus;
+ static char *bp = NULL;
+ static int bplen = 0;
+
+ /* figure out how long this xtext will have to be */
+ nbogus = l = 0;
+ for (p = t; *p != '\0'; p++)
+ {
+ register int c = (*p & 0xff);
+
+ /* ASCII dependence here -- this is the way the spec words it */
+ if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
+ nbogus++;
+ l++;
+ }
+ if (nbogus == 0)
+ return t;
+ l += nbogus * 2 + 1;
+
+ /* now allocate space if necessary for the new string */
+ if (l > bplen)
+ {
+ if (bp != NULL)
+ free(bp);
+ bp = xalloc(l);
+ bplen = l;
+ }
+
+ /* ok, copy the text with byte expansion */
+ for (p = bp; *t != '\0'; )
+ {
+ register int c = (*t++ & 0xff);
+
+ /* ASCII dependence here -- this is the way the spec words it */
+ if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
+ {
+ *p++ = '+';
+ *p++ = "0123456789abcdef"[c >> 4];
+ *p++ = "0123456789abcdef"[c & 0xf];
+ }
+ else
+ *p++ = c;
+ }
+ *p = '\0';
+ return bp;
+}
+ /*
+** XUNTEXTIFY -- take xtext and turn it into plain text
+**
+** Parameters:
+** t -- the xtextified text.
+**
+** Returns:
+** The decoded text. No attempt is made to deal with
+** null strings in the resulting text.
+*/
+
+char *
+xuntextify(t)
+ register char *t;
+{
+ register char *p;
+ int l;
+ static char *bp = NULL;
+ static int bplen = 0;
+
+ /* heuristic -- if no plus sign, just return the input */
+ if (strchr(t, '+') == NULL)
+ return t;
+
+ /* xtext is always longer than decoded text */
+ l = strlen(t);
+ if (l > bplen)
+ {
+ if (bp != NULL)
+ free(bp);
+ bp = xalloc(l);
+ bplen = l;
+ }
+
+ /* ok, copy the text with byte compression */
+ for (p = bp; *t != '\0'; t++)
+ {
+ register int c = *t & 0xff;
+
+ if (c != '+')
+ {
+ *p++ = c;
+ continue;
+ }
+
+ c = *++t & 0xff;
+ if (!isascii(c) || !isxdigit(c))
+ {
+ /* error -- first digit is not hex */
+ usrerr("bogus xtext: +%c", c);
+ t--;
+ continue;
+ }
+ if (isdigit(c))
+ c -= '0';
+ else if (isupper(c))
+ c -= 'A' - 10;
+ else
+ c -= 'a' - 10;
+ *p = c << 4;
+
+ c = *++t & 0xff;
+ if (!isascii(c) || !isxdigit(c))
+ {
+ /* error -- second digit is not hex */
+ usrerr("bogus xtext: +%x%c", *p >> 4, c);
+ t--;
+ continue;
+ }
+ if (isdigit(c))
+ c -= '0';
+ else if (isupper(c))
+ c -= 'A' - 10;
+ else
+ c -= 'a' - 10;
+ *p++ |= c;
+ }
+ return bp;
+}
+ /*
+** XTEXTOK -- check if a string is legal xtext
+**
+** Xtext is used in Delivery Status Notifications. The spec was
+** taken from draft-ietf-notary-mime-delivery-04.txt.
+**
+** Parameters:
+** s -- the string to check.
+**
+** Returns:
+** TRUE -- if 's' is legal xtext.
+** FALSE -- if it has any illegal characters in it.
+*/
+
+bool
+xtextok(s)
+ char *s;
+{
+ int c;
+
+ while ((c = *s++) != '\0')
+ {
+ if (c == '+')
+ {
+ c = *s++;
+ if (!isascii(c) || !isxdigit(c))
+ return FALSE;
+ c = *s++;
+ if (!isascii(c) || !isxdigit(c))
+ return FALSE;
+ }
+ else if (c < '!' || c > '~' || c == '=')
+ return FALSE;
+ }
+ return TRUE;
+}
+ /*
+** 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
+*/
+
+bool
+pruneroute(addr)
+ char *addr;
+{
+#if 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;
+}
diff --git a/usr.sbin/sendmail/src/sendmail.8 b/usr.sbin/sendmail/src/sendmail.8
new file mode 100644
index 000000000000..3397b8f947da
--- /dev/null
+++ b/usr.sbin/sendmail/src/sendmail.8
@@ -0,0 +1,514 @@
+.\" 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.
+.\"
+.\" @(#)sendmail.8 8.6 (Berkeley) 5/27/95
+.\"
+.Dd May 27, 1995
+.Dt SENDMAIL 8
+.Os BSD 4
+.Sh NAME
+.Nm sendmail
+.Nd send mail over the internet
+.Sh SYNOPSIS
+.Nm sendmail
+.Op Ar flags
+.Op Ar address ...
+.Nm newaliases
+.Nm mailq
+.Op Fl v
+.Sh DESCRIPTION
+.Nm Sendmail
+sends a message to one or more
+.Em recipients ,
+routing the message over whatever networks
+are necessary.
+.Nm Sendmail
+does internetwork forwarding as necessary
+to deliver the message to the correct place.
+.Pp
+.Nm Sendmail
+is not intended as a user interface routine;
+other programs provide user-friendly
+front ends;
+.Nm sendmail
+is used only to deliver pre-formatted messages.
+.Pp
+With no flags,
+.Nm sendmail
+reads its standard input
+up to an end-of-file
+or a line consisting only of a single dot
+and sends a copy of the message found there
+to all of the addresses listed.
+It determines the network(s) to use
+based on the syntax and contents of the addresses.
+.Pp
+Local addresses are looked up in a file
+and aliased appropriately.
+Aliasing can be prevented by preceding the address
+with a backslash.
+Normally the sender is not included in any alias
+expansions, e.g.,
+if `john' sends to `group',
+and `group' includes `john' in the expansion,
+then the letter will not be delivered to `john'.
+.Ss Parameters
+.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
+mode.
+All input lines must end with a CR-LF,
+and all messages will be generated with a CR-LF at the end.
+Also,
+the ``From:'' and ``Sender:''
+fields are examined for the name of the sender.
+.It Fl bd
+Run as a daemon. This requires Berkeley
+.Tn IPC .
+.Nm Sendmail
+will fork and run in background
+listening on socket 25 for incoming
+.Tn SMTP
+connections.
+This is normally run from
+.Pa /etc/rc .
+.It Fl bi
+Initialize the alias database.
+.It Fl bm
+Deliver mail in the usual way (default).
+.It Fl bp
+Print a listing of the queue.
+.It Fl bs
+Use the
+.Tn SMTP
+protocol as described in
+.Tn RFC821
+on standard input and output.
+This flag implies all the operations of the
+.Fl ba
+flag that are compatible with
+.Tn SMTP .
+.It Fl bt
+Run in address test mode.
+This mode reads addresses and shows the steps in parsing;
+it is used for debugging configuration tables.
+.It Fl bv
+Verify names only \- do not try to collect or deliver a message.
+Verify mode is normally used for validating
+users or mailing lists.
+.It Fl C Ns Ar file
+Use alternate configuration file.
+.Nm Sendmail
+refuses to run as root if an alternate configuration file is specified.
+.It Fl d Ns Ar X
+Set debugging value to
+.Ar X .
+.ne 1i
+.It Fl F Ns Ar fullname
+Set the full name of the sender.
+.It Fl f Ns Ar name
+Sets the name of the ``from'' person
+(i.e., the sender of the mail).
+.Fl f
+can only be used
+by ``trusted'' users
+(normally
+.Em root ,
+.Em daemon ,
+and
+.Em network )
+or if the person you are trying to become
+is the same as the person you are.
+.It Fl h Ns Ar N
+Set the hop count to
+.Ar N .
+The hop count is incremented every time the mail is
+processed.
+When it reaches a limit,
+the mail is returned with an error message,
+the victim of an aliasing loop.
+If not specified,
+``Received:'' lines in the message are counted.
+.It Fl n
+Don't do aliasing.
+.It Fl o Ns Ar x Em value
+Set option
+.Ar x
+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
+.Ar time
+is omitted,
+process the queue once.
+.Xr Time
+is given as a tagged number,
+with
+.Ql s
+being seconds,
+.Ql m
+being minutes,
+.Ql h
+being hours,
+.Ql d
+being days,
+and
+.Ql w
+being weeks.
+For example,
+.Ql \-q1h30m
+or
+.Ql \-q90m
+would both set the timeout to one hour thirty minutes.
+If
+.Ar time
+is specified,
+.Nm sendmail
+will run in background.
+This option can be used safely with
+.Fl bd .
+.It Fl qI Ns Ar substr
+Limit processed jobs to those containing
+.Ar substr
+as a substring of the queue id.
+.It Fl qR Ns Ar substr
+Limit processed jobs to those containing
+.Ar substr
+as a substring of one of the recipients.
+.It Fl qS Ns Ar substr
+Limit processed jobs to those containing
+.Ar substr
+as a substring of the sender.
+.It Fl r Ns Ar name
+An alternate and obsolete form of the
+.Fl f
+flag.
+.It Fl t
+Read message for recipients.
+To:, Cc:, and Bcc: lines will be scanned for recipient addresses.
+The Bcc: line will be deleted before transmission.
+Any addresses in the argument list will be suppressed,
+that is,
+they will
+.Em not
+receive copies even if listed in the message header.
+.It Fl v
+Go into verbose mode.
+Alias expansions will be announced, etc.
+.It Fl X Ar logfile
+Log all traffic in and out of mailers in the indicated log file.
+This should only be used as a last resort
+for debugging mailer bugs.
+It will log a lot of data very quickly.
+.El
+.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
+using the
+.Fl o
+flag
+or in the configuration file.
+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.
+.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 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.
+.ne 1i
+.It Li d Ns Ar x
+Set the delivery mode to
+.Ar x .
+Delivery modes are
+.Ql i
+for interactive (synchronous) delivery,
+.Ql b
+for background (asynchronous) delivery,
+and
+.Ql q
+for queue only \- i.e.,
+actual delivery is done the next time the queue is run.
+.It Li D
+Try to automatically rebuild the alias database
+if necessary.
+.It Li e Ns Ar x
+Set error processing to mode
+.Ar x .
+Valid modes are
+.Ql m
+to mail back the error message,
+.Ql w
+to ``write'' back the error message
+(or mail it back if the sender is not logged in),
+.Ql p
+to print the errors on the terminal
+(default),
+.Ql q
+to throw away error messages
+(only exit status is returned),
+and
+.Ql e
+to do special processing for the BerkNet.
+If the text of the message is not mailed back
+by
+modes
+.Ql m
+or
+.Ql w
+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.
+.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 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 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
+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 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.
+If not set,
+this message is guaranteed to have new style headers
+(i.e., commas instead of spaces between addresses).
+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.
+.It Li S Ns Ar file
+Save statistics in the named file.
+.It Li s
+Always instantiate the queue file,
+even under circumstances where it is not strictly necessary.
+This provides safety against system crashes during delivery.
+.It Li T Ns Ar time
+Set the timeout on undelivered messages in the queue to the specified time.
+After delivery has failed
+(e.g., because of a host being down)
+for this amount of time,
+failed messages will be returned to the sender.
+The default is three days.
+.It Li t Ns Ar stz , Ar dtz
+Set the name of the time zone.
+.It Li U Ns Ar userdatabase
+If set, a user database is consulted to get forwarding information.
+You can consider this an adjunct to the aliasing mechanism,
+except that the database is intended to be distributed;
+aliases are local to a particular host.
+This may not be available if your sendmail does not have the
+.Dv USERDB
+option compiled in.
+.It Li u Ns Ar N
+Set the default user id for mailers.
+.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,
+the first character of a name may be
+a vertical bar to cause interpretation of
+the rest of the name as a command
+to pipe the mail to.
+It may be necessary to quote the name
+to keep
+.Nm sendmail
+from suppressing the blanks from between arguments.
+For example, a common alias is:
+.Pp
+.Bd -literal -offset indent -compact
+msgs: "|/usr/bin/msgs -s"
+.Ed
+.Pp
+Aliases may also have the syntax
+.Dq :include: Ns Ar filename
+to ask
+.Xr sendmail
+to read the named file for a list of recipients.
+For example, an alias such as:
+.Pp
+.Bd -literal -offset indent -compact
+poets: ":include:/usr/local/lib/poets.list"
+.Ed
+.Pp
+would read
+.Pa /usr/local/lib/poets.list
+for the list of addresses making up the group.
+.Pp
+.Nm Sendmail
+returns an exit status
+describing what it did.
+The codes are defined in
+.Aq Pa sysexits.h :
+.Bl -tag -width EX_UNAVAILABLE -compact -offset indent
+.It Dv EX_OK
+Successful completion on all addresses.
+.It Dv EX_NOUSER
+User name not recognized.
+.It Dv EX_UNAVAILABLE
+Catchall meaning necessary resources
+were not available.
+.It Dv EX_SYNTAX
+Syntax error in address.
+.It Dv EX_SOFTWARE
+Internal software error,
+including bad arguments.
+.It Dv EX_OSERR
+Temporary operating system error,
+such as
+.Dq cannot fork .
+.It Dv EX_NOHOST
+Host name not recognized.
+.It Dv EX_TEMPFAIL
+Message could not be sent immediately,
+but was queued.
+.El
+.Pp
+If invoked as
+.Nm newaliases ,
+.Nm sendmail
+will rebuild the alias database.
+If invoked as
+.Nm mailq ,
+.Nm sendmail
+will print the contents of the mail queue.
+.Sh FILES
+Except for the file
+.Pa /etc/sendmail.cf
+itself,
+the following pathnames are all specified in
+.Pa /etc/sendmail.cf.
+Thus,
+these values are only approximations.
+.Pp
+.Bl -tag -width /usr/lib/sendmail.fc -compact
+.It Pa /etc/aliases
+raw data for alias names
+.It Pa /etc/aliases.db
+data base of alias names
+.It Pa /etc/sendmail.cf
+configuration file
+.It Pa /etc/sendmail.hf
+help file
+.It Pa /var/log/sendmail.st
+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 ,
+.Xr mail 1 ,
+.Xr rmail 1 ,
+.Xr syslog 3 ,
+.Xr aliases 5 ,
+.Xr mailaddr 7 ,
+.Xr rc 8 ;
+.Pp
+DARPA
+Internet Request For Comments
+.%T RFC819 ,
+.%T RFC821 ,
+.%T RFC822 .
+.Rs
+.%T "Sendmail \- An Internetwork Mail Router"
+.%V SMM
+.%N \&No. 9
+.Re
+.Rs
+.%T "Sendmail Installation and Operation Guide"
+.%V SMM
+.%N \&No. 8
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/usr.sbin/sendmail/src/sendmail.h b/usr.sbin/sendmail/src/sendmail.h
new file mode 100644
index 000000000000..9de20ca4b23d
--- /dev/null
+++ b/usr.sbin/sendmail/src/sendmail.h
@@ -0,0 +1,1237 @@
+/*
+ * Copyright (c) 1983, 1995 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.h 8.159 (Berkeley) 11/18/95
+ */
+
+/*
+** SENDMAIL.H -- Global definitions for sendmail.
+*/
+
+# ifdef _DEFINE
+# define EXTERN
+# ifndef lint
+static char SmailSccsId[] = "@(#)sendmail.h 8.159 11/18/95";
+# endif
+# else /* _DEFINE */
+# define EXTERN extern
+# endif /* _DEFINE */
+
+# include <unistd.h>
+# include <stddef.h>
+# include <stdlib.h>
+# include <stdio.h>
+# include <ctype.h>
+# include <setjmp.h>
+# include <string.h>
+# include <time.h>
+# include <errno.h>
+# ifdef EX_OK
+# undef EX_OK /* for SVr4.2 SMP */
+# endif
+# include <sysexits.h>
+
+# include "conf.h"
+# include "useful.h"
+
+# ifdef LOG
+# include <syslog.h>
+# endif /* LOG */
+
+# ifdef DAEMON
+# include <sys/socket.h>
+# endif
+# if NETUNIX
+# include <sys/un.h>
+# endif
+# if NETINET
+# include <netinet/in.h>
+# endif
+# if NETISO
+# include <netiso/iso.h>
+# endif
+# if NETNS
+# include <netns/ns.h>
+# endif
+# if NETX25
+# include <netccitt/x25.h>
+# endif
+
+
+
+/* forward references for prototypes */
+typedef struct envelope ENVELOPE;
+typedef struct mailer MAILER;
+
+
+/*
+** Data structure for bit maps.
+**
+** Each bit in this map can be referenced by an ascii character.
+** This is 256 possible bits, or 32 8-bit bytes.
+*/
+
+#define BITMAPBYTES 32 /* number of bytes in a bit map */
+#define BYTEBITS 8 /* number of bits in a byte */
+
+/* internal macros */
+#define _BITWORD(bit) ((bit) / (BYTEBITS * sizeof (int)))
+#define _BITBIT(bit) (1 << ((bit) % (BYTEBITS * sizeof (int))))
+
+typedef int BITMAP[BITMAPBYTES / sizeof (int)];
+
+/* test bit number N */
+#define bitnset(bit, map) ((map)[_BITWORD(bit)] & _BITBIT(bit))
+
+/* set bit number N */
+#define setbitn(bit, map) (map)[_BITWORD(bit)] |= _BITBIT(bit)
+
+/* clear bit number N */
+#define clrbitn(bit, map) (map)[_BITWORD(bit)] &= ~_BITBIT(bit)
+
+/* clear an entire bit map */
+#define clrbitmap(map) bzero((char *) map, BITMAPBYTES)
+ /*
+** Address structure.
+** Addresses are stored internally in this structure.
+*/
+
+struct address
+{
+ char *q_paddr; /* the printname for the address */
+ char *q_user; /* user name */
+ char *q_ruser; /* real user name, or NULL if q_user */
+ char *q_host; /* host name */
+ struct mailer *q_mailer; /* mailer to use */
+ u_long q_flags; /* status flags, see below */
+ 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_owner; /* owner of q_alias */
+ struct address *q_tchain; /* temporary use chain */
+ char *q_orcpt; /* ORCPT parameter from RCPT TO: line */
+ char *q_status; /* status code for DSNs */
+ char *q_rstatus; /* remote status message for DSNs */
+ time_t q_statdate; /* date of status messages */
+ char *q_statmta; /* MTA generating q_rstatus */
+ short q_specificity; /* how "specific" this address is */
+};
+
+typedef struct address ADDRESS;
+
+# define QDONTSEND 0x00000001 /* don't send to this address */
+# define QBADADDR 0x00000002 /* this address is verified bad */
+# define QGOODUID 0x00000004 /* the q_uid q_gid fields are good */
+# define QPRIMARY 0x00000008 /* set from RCPT or argv */
+# define QQUEUEUP 0x00000010 /* queue for later transmission */
+# define QSENT 0x00000020 /* has been successfully delivered */
+# define QNOTREMOTE 0x00000040 /* address not for remote forwarding */
+# define QSELFREF 0x00000080 /* this address references itself */
+# define QVERIFIED 0x00000100 /* verified, but not expanded */
+# define QBOGUSSHELL 0x00000400 /* user has no valid shell listed */
+# define QUNSAFEADDR 0x00000800 /* address aquired via unsafe path */
+# define QPINGONSUCCESS 0x00001000 /* give return on successful delivery */
+# define QPINGONFAILURE 0x00002000 /* give return on failure */
+# define QPINGONDELAY 0x00004000 /* give return on message delay */
+# define QHASNOTIFY 0x00008000 /* propogate notify parameter */
+# define QRELAYED 0x00010000 /* DSN: relayed to non-DSN aware sys */
+# define QEXPANDED 0x00020000 /* DSN: undergone list expansion */
+# define QDELIVERED 0x00040000 /* DSN: successful final delivery */
+# define QDELAYED 0x00080000 /* DSN: message delayed */
+# define QTHISPASS 0x80000000 /* temp: address set this pass */
+
+# define NULLADDR ((ADDRESS *) NULL)
+
+/* functions */
+extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *));
+extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
+extern char **prescan __P((char *, int, char[], int, char **, u_char *));
+extern int rewrite __P((char **, int, int, ENVELOPE *));
+extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *));
+extern ADDRESS *getctladdr __P((ADDRESS *));
+extern bool sameaddr __P((ADDRESS *, ADDRESS *));
+extern bool emptyaddr __P((ADDRESS *));
+extern void printaddr __P((ADDRESS *, bool));
+extern void cataddr __P((char **, char **, char *, int, int));
+extern int sendtolist __P((char *, ADDRESS *, ADDRESS **, int, ENVELOPE *));
+ /*
+** Mailer definition structure.
+** Every mailer known to the system is declared in this
+** structure. It defines the pathname of the mailer, some
+** flags associated with it, and the argument vector to
+** pass to it. The flags are defined in conf.c
+**
+** The argument vector is expanded before actual use. All
+** words except the first are passed through the macro
+** processor.
+*/
+
+struct mailer
+{
+ char *m_name; /* symbolic name of this mailer */
+ char *m_mailer; /* pathname of the mailer to use */
+ char *m_mtatype; /* type of this MTA */
+ char *m_addrtype; /* type for addresses */
+ char *m_diagtype; /* type for diagnostics */
+ BITMAP m_flags; /* status flags, see below */
+ short m_mno; /* mailer number internally */
+ short m_nice; /* niceness to run at (mostly for prog) */
+ char **m_argv; /* template argument vector */
+ 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 */
+ int m_linelimit; /* max # characters per line */
+ char *m_execdir; /* directory to chdir to before execv */
+ uid_t m_uid; /* UID to run as */
+ gid_t m_gid; /* GID to run as */
+ char *m_defcharset; /* default character set */
+};
+
+/* bits for m_flags */
+# define M_ESMTP 'a' /* run Extended SMTP protocol */
+# define M_ALIASABLE 'A' /* user can be LHS of an alias */
+# 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_NOBRACKET 'd' /* never angle bracket envelope route-addrs */
+ /* '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 */
+ /* '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_PREHEAD 'H' /* MAIL11V3: preview headers */
+# define M_UDBENVELOPE 'i' /* do udbsender rewriting on envelope */
+# define M_INTERNAL 'I' /* SMTP to another sendmail site */
+# define M_UDBRECIPIENT 'j' /* do udbsender rewriting on recipient lines */
+# define M_NOLOOPCHECK 'k' /* don't check for loops in HELO command */
+# 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 */
+ /* 'M' /* CF: include Message-Id: */
+# define M_NHDR 'n' /* don't insert From line */
+# define M_MANYSTATUS 'N' /* MAIL11V3: DATA returns multi-status */
+# define M_RUNASRCPT 'o' /* always run mailer as recipient */
+# 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_SPECIFIC_UID 'S' /* run as specific uid/gid */
+# define M_USR_UPPER 'u' /* preserve user case distinction */
+# define M_UGLYUUCP 'U' /* this wants an ugly UUCP from line */
+# define M_CONTENT_LEN 'v' /* add Content-Length: header (SVr4) */
+ /* 'V' /* UIUC: !-relativize all addresses */
+# define M_HASPWENT 'w' /* check for /etc/passwd entry */
+ /* 'x' /* CF: include Full-Name: */
+# define M_XDOT 'X' /* use hidden-dot algorithm */
+# define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */
+# define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */
+# define M_7BITS '7' /* use 7-bit path */
+# define M_8BITS '8' /* force "just send 8" behaviour */
+# define M_MAKE8BIT '9' /* convert 7 -> 8 bit if appropriate */
+# define M_CHECKINCLUDE ':' /* check for :include: files */
+# define M_CHECKPROG '|' /* check for |program addresses */
+# define M_CHECKFILE '/' /* check for /file addresses */
+# define M_CHECKUDB '@' /* user can be user database key */
+
+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 */
+ /*
+** Header structure.
+** This structure is used internally to store header items.
+*/
+
+struct header
+{
+ char *h_field; /* the name of the field */
+ char *h_value; /* the value of that field */
+ struct header *h_link; /* the next header */
+ u_short h_flags; /* status bits, see below */
+ BITMAP h_mflags; /* m_flags bits needed */
+};
+
+typedef struct header HDR;
+
+/*
+** Header information structure.
+** Defined in conf.c, this struct declares the header fields
+** that have some magic meaning.
+*/
+
+struct hdrinfo
+{
+ char *hi_field; /* the name of the field */
+ u_short hi_flags; /* status bits, see below */
+};
+
+extern struct hdrinfo HdrInfo[];
+
+/* bits for h_flags and hi_flags */
+# define H_EOH 0x0001 /* this field terminates header */
+# define H_RCPT 0x0002 /* contains recipient addresses */
+# define H_DEFAULT 0x0004 /* if another value is found, drop this */
+# define H_RESENT 0x0008 /* this address is a "Resent-..." address */
+# define H_CHECK 0x0010 /* check h_mflags against m_flags */
+# define H_ACHECK 0x0020 /* ditto, but always (not just default) */
+# define H_FORCE 0x0040 /* force this field, even if default */
+# define H_TRACE 0x0080 /* this field contains trace information */
+# define H_FROM 0x0100 /* this is a from-type field */
+# define H_VALID 0x0200 /* this field has a validated value */
+# define H_RECEIPTTO 0x0400 /* this field has return receipt info */
+# define H_ERRORSTO 0x0800 /* this field has error address info */
+# define H_CTE 0x1000 /* this field is a content-transfer-encoding */
+# define H_CTYPE 0x2000 /* this is a content-type field */
+# define H_BCC 0x4000 /* Bcc: header: strip value or delete */
+ /*
+** 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_herrno; /* h_errno from last DNS lookup */
+ 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 */
+ char *mci_status; /* DSN status to be copied to addrs */
+ time_t mci_lastuse; /* last usage time */
+};
+
+
+/* flag bits */
+#define MCIF_VALID 0x0001 /* this entry is valid */
+#define MCIF_TEMP 0x0002 /* don't cache this connection */
+#define MCIF_CACHED 0x0004 /* currently in open cache */
+#define MCIF_ESMTP 0x0008 /* this host speaks ESMTP */
+#define MCIF_EXPN 0x0010 /* EXPN command supported */
+#define MCIF_SIZE 0x0020 /* SIZE option supported */
+#define MCIF_8BITMIME 0x0040 /* BODY=8BITMIME supported */
+#define MCIF_7BIT 0x0080 /* strip this message to 7 bits */
+#define MCIF_MULTSTAT 0x0100 /* MAIL11V3: handles MULT status */
+#define MCIF_INHEADER 0x0200 /* currently outputing header */
+#define MCIF_CVT8TO7 0x0400 /* convert from 8 to 7 bits */
+#define MCIF_DSN 0x0800 /* DSN extension supported */
+#define MCIF_8BITOK 0x1000 /* OK to send 8 bit characters */
+#define MCIF_CVT7TO8 0x2000 /* convert from 7 to 8 bits */
+#define MCIF_INMIME 0x4000 /* currently reading MIME header */
+
+/* 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 */
+
+/* functions */
+extern MCI *mci_get __P((char *, MAILER *));
+extern void mci_cache __P((MCI *));
+extern void mci_flush __P((bool, MCI *));
+ /*
+** Envelope structure.
+** This structure defines the message itself. There is usually
+** only one of these -- for the message that we originally read
+** and which is our primary interest -- but other envelopes can
+** be generated during processing. For example, error messages
+** will have their own envelope.
+*/
+
+struct envelope
+{
+ HDR *e_header; /* head of header list */
+ long e_msgpriority; /* adjusted priority of this message */
+ time_t e_ctime; /* time message appeared in the queue */
+ 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 */
+ long e_msgsize; /* size of the message in bytes */
+ long e_flags; /* flags, see below */
+ int e_nrcpts; /* number of recipients */
+ short e_class; /* msg class (priority, junk, etc.) */
+ short e_hopcount; /* number of times processed */
+ short e_nsent; /* number of sends since checkpoint */
+ short e_sendmode; /* message send mode */
+ short e_errormode; /* error return mode */
+ short e_timeoutclass; /* message timeout class */
+ void (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *));
+ /* function to put header of message */
+ void (*e_putbody)__P((MCI *, 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 */
+ char *e_bodytype; /* type of message body */
+ 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_statmsg; /* stat msg (changes per delivery) */
+ char *e_msgboundary; /* MIME-style message part boundary */
+ char *e_origrcpt; /* original recipient (one only) */
+ char *e_envid; /* envelope id from MAIL FROM: line */
+ char *e_status; /* DSN status for this message */
+ time_t e_dtime; /* time of last delivery attempt */
+ int e_ntries; /* number of delivery attempts */
+ dev_t e_dfdev; /* df file's device, for crash recov */
+ ino_t e_dfino; /* df file's ino, for crash recovery */
+ char *e_macro[256]; /* macro definitions */
+};
+
+/* values for e_flags */
+#define EF_OLDSTYLE 0x0000001 /* use spaces (not commas) in hdrs */
+#define EF_INQUEUE 0x0000002 /* this message is fully queued */
+#define EF_NO_BODY_RETN 0x0000004 /* omit message body on error */
+#define EF_CLRQUEUE 0x0000008 /* disk copy is no longer needed */
+#define EF_SENDRECEIPT 0x0000010 /* send a return receipt */
+#define EF_FATALERRS 0x0000020 /* fatal errors occured */
+#define EF_DELETE_BCC 0x0000040 /* delete Bcc: headers entirely */
+#define EF_RESPONSE 0x0000080 /* this is an error or return receipt */
+#define EF_RESENT 0x0000100 /* this message is being forwarded */
+#define EF_VRFYONLY 0x0000200 /* verify only (don't expand aliases) */
+#define EF_WARNING 0x0000400 /* warning message has been sent */
+#define EF_QUEUERUN 0x0000800 /* this envelope is from queue */
+#define EF_GLOBALERRS 0x0001000 /* treat errors as global */
+#define EF_PM_NOTIFY 0x0002000 /* send return mail to postmaster */
+#define EF_METOO 0x0004000 /* send to me too */
+#define EF_LOGSENDER 0x0008000 /* need to log the sender */
+#define EF_NORECEIPT 0x0010000 /* suppress all return-receipts */
+#define EF_HAS8BIT 0x0020000 /* at least one 8-bit char in body */
+#define EF_NL_NOT_EOL 0x0040000 /* don't accept raw NL as EOLine */
+#define EF_CRLF_NOT_EOL 0x0080000 /* don't accept CR-LF as EOLine */
+#define EF_RET_PARAM 0x0100000 /* RCPT command had RET argument */
+#define EF_HAS_DF 0x0200000 /* set when df file is instantiated */
+#define EF_IS_MIME 0x0400000 /* really is a MIME message */
+#define EF_DONT_MIME 0x0800000 /* never MIME this message */
+
+EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */
+
+/* functions */
+extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *));
+extern void dropenvelope __P((ENVELOPE *));
+extern void clearenvelope __P((ENVELOPE *, bool));
+
+extern void putheader __P((MCI *, HDR *, ENVELOPE *));
+extern void putbody __P((MCI *, ENVELOPE *, char *));
+ /*
+** Message priority classes.
+**
+** The message class is read directly from the Priority: header
+** field in the message.
+**
+** CurEnv->e_msgpriority is the number of bytes in the message plus
+** the creation time (so that jobs ``tend'' to be ordered correctly),
+** adjusted by the message class, the number of recipients, and the
+** amount of time the message has been sitting around. This number
+** is used to order the queue. Higher values mean LOWER priority.
+**
+** Each priority class point is worth WkClassFact priority points;
+** each recipient is worth WkRecipFact priority points. Each time
+** we reprocess a message the priority is adjusted by WkTimeFact.
+** WkTimeFact should normally decrease the priority so that jobs
+** that have historically failed will be run later; thanks go to
+** Jay Lepreau at Utah for pointing out the error in my thinking.
+**
+** The "class" is this number, unadjusted by the age or size of
+** this message. Classes with negative representations will have
+** error messages thrown away if they are not local.
+*/
+
+struct priority
+{
+ char *pri_name; /* external name of priority */
+ int pri_val; /* internal value for same */
+};
+
+EXTERN struct priority Priorities[MAXPRIORITIES];
+EXTERN int NumPriorities; /* pointer into Priorities */
+ /*
+** Rewrite rules.
+*/
+
+struct rewrite
+{
+ char **r_lhs; /* pattern match */
+ char **r_rhs; /* substitution value */
+ struct rewrite *r_next;/* next in chain */
+};
+
+EXTERN struct rewrite *RewriteRules[MAXRWSETS];
+
+/*
+** Special characters in rewriting rules.
+** These are used internally only.
+** The COND* rules are actually used in macros rather than in
+** rewriting rules, but are given here because they
+** cannot conflict.
+*/
+
+/* left hand side items */
+# define MATCHZANY ((u_char)0220) /* match zero or more tokens */
+# define MATCHANY ((u_char)0221) /* match one or more tokens */
+# define MATCHONE ((u_char)0222) /* match exactly one token */
+# define MATCHCLASS ((u_char)0223) /* match one token in a class */
+# define MATCHNCLASS ((u_char)0224) /* match anything not in class */
+# define MATCHREPL ((u_char)0225) /* replacement on RHS for above */
+
+/* right hand side items */
+# define CANONNET ((u_char)0226) /* canonical net, next token */
+# define CANONHOST ((u_char)0227) /* canonical host, next token */
+# define CANONUSER ((u_char)0230) /* canonical user, next N tokens */
+# define CALLSUBR ((u_char)0231) /* call another rewriting set */
+
+/* conditionals in macros */
+# define CONDIF ((u_char)0232) /* conditional if-then */
+# define CONDELSE ((u_char)0233) /* conditional else */
+# define CONDFI ((u_char)0234) /* conditional fi */
+
+/* bracket characters for host name lookup */
+# define HOSTBEGIN ((u_char)0235) /* hostname lookup begin */
+# define HOSTEND ((u_char)0236) /* hostname lookup end */
+
+/* bracket characters for generalized lookup */
+# define LOOKUPBEGIN ((u_char)0205) /* generalized lookup begin */
+# define LOOKUPEND ((u_char)0206) /* generalized lookup end */
+
+/* macro substitution character */
+# define MACROEXPAND ((u_char)0201) /* macro expansion */
+# define MACRODEXPAND ((u_char)0202) /* deferred macro expansion */
+
+/* to make the code clearer */
+# define MATCHZERO CANONHOST
+
+/* external <==> internal mapping table */
+struct metamac
+{
+ char metaname; /* external code (after $) */
+ u_char metaval; /* internal code (as above) */
+};
+
+/* values for macros with external names only */
+# define MID_OPMODE 0202 /* operation mode */
+
+/* functions */
+extern void expand __P((char *, char *, size_t, ENVELOPE *));
+extern void define __P((int, char *, ENVELOPE *));
+extern char *macvalue __P((int, ENVELOPE *));
+extern char *macname __P((int));
+extern int macid __P((char *, char **));
+ /*
+** Name canonification short circuit.
+**
+** 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.
+*/
+
+#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 */
+ /*
+** 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 MAXMAPACTIONS 3 /* size of map_actions array */
+
+
+/*
+** An actual map.
+*/
+
+MAP
+{
+ MAPCLASS *map_class; /* the class of this map */
+ char *map_mname; /* name of this map */
+ long map_mflags; /* flags, see below */
+ char *map_file; /* the (nominal) filename */
+ ARBPTR_T map_db1; /* the open database ptr */
+ ARBPTR_T map_db2; /* an "extra" database pointer */
+ char *map_keycolnm; /* key column name */
+ char *map_valcolnm; /* value column name */
+ u_char map_keycolno; /* key column number */
+ u_char map_valcolno; /* value column number */
+ char map_coldelim; /* column delimiter */
+ 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 */
+ time_t map_mtime; /* last database modification time */
+ short map_specificity; /* specificity of alaases */
+ MAP *map_stack[MAXMAPSTACK]; /* list for stacked maps */
+ short map_return[MAXMAPACTIONS]; /* return bitmaps for stacked maps */
+};
+
+/* bit values for map_mflags */
+# define MF_VALID 0x00000001 /* this entry is valid */
+# define MF_INCLNULL 0x00000002 /* include null byte in key */
+# define MF_OPTIONAL 0x00000004 /* don't complain if map not found */
+# define MF_NOFOLDCASE 0x00000008 /* don't fold case in keys */
+# define MF_MATCHONLY 0x00000010 /* don't use the map value */
+# define MF_OPEN 0x00000020 /* this entry is open */
+# define MF_WRITABLE 0x00000040 /* open for writing */
+# define MF_ALIAS 0x00000080 /* this is an alias file */
+# define MF_TRY0NULL 0x00000100 /* try with no null byte */
+# define MF_TRY1NULL 0x00000200 /* try with the null byte */
+# define MF_LOCKED 0x00000400 /* this map is currently locked */
+# define MF_ALIASWAIT 0x00000800 /* alias map in aliaswait state */
+# define MF_IMPL_HASH 0x00001000 /* implicit: underlying hash database */
+# define MF_IMPL_NDBM 0x00002000 /* implicit: underlying NDBM database */
+# define MF_UNSAFEDB 0x00004000 /* this map is world writable */
+# define MF_APPEND 0x00008000 /* append new entry on rebuiled */
+# define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */
+
+/* indices for map_actions */
+# define MA_NOTFOUND 0 /* member map returned "not found" */
+# define MA_UNAVAIL 1 /* member map is not available */
+# define MA_TRYAGAIN 2 /* member map returns temp failure */
+
+/*
+** 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 */
+#define MCF_OPTFILE 0x0008 /* file name is optional */
+
+/* functions */
+extern char *map_rewrite __P((MAP *, char *, int, char **));
+extern MAP *makemapentry __P((char *));
+ /*
+** Symbol table definitions
+*/
+
+struct symtab
+{
+ char *s_name; /* name to be entered */
+ char s_type; /* general type (see below) */
+ struct symtab *s_next; /* pointer to next in chain */
+ union
+ {
+ BITMAP sv_class; /* bit-map of word classes */
+ ADDRESS *sv_addr; /* pointer to address header */
+ MAILER *sv_mailer; /* pointer to mailer */
+ char *sv_alias; /* alias */
+ 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 */
+ int sv_macro; /* macro name => id mapping */
+ int sv_ruleset; /* ruleset index */
+ } s_value;
+};
+
+typedef struct symtab STAB;
+
+/* symbol types */
+# define ST_UNDEF 0 /* undefined type */
+# define ST_CLASS 1 /* class map */
+# define ST_ADDRESS 2 /* an address in parsed format */
+# define ST_MAILER 3 /* a mailer header */
+# define ST_ALIAS 4 /* an alias */
+# 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_MACRO 9 /* macro name to id mapping */
+# define ST_RULESET 10 /* ruleset index */
+# 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_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
+# define s_macro s_value.sv_macro
+# define s_ruleset s_value.sv_ruleset
+
+extern STAB *stab __P((char *, int, int));
+extern void stabapply __P((void (*)(STAB *, int), int));
+
+/* opcodes to stab */
+# define ST_FIND 0 /* find entry */
+# define ST_ENTER 1 /* enter if not there */
+ /*
+** STRUCT EVENT -- event queue.
+**
+** Maintained in sorted order.
+**
+** We store the pid of the process that set this event to insure
+** that when we fork we will not take events intended for the parent.
+*/
+
+struct event
+{
+ time_t ev_time; /* time of the function call */
+ void (*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 */
+};
+
+typedef struct event EVENT;
+
+EXTERN EVENT *EventQueue; /* head of event queue */
+
+/* functions */
+extern EVENT *setevent __P((time_t, void(*)(), int));
+extern void clrevent __P((EVENT *));
+ /*
+** Operation, send, error, and MIME modes
+**
+** The operation mode describes the basic operation of sendmail.
+** This can be set from the command line, and is "send mail" by
+** default.
+**
+** The send mode tells how to send mail. It can be set in the
+** configuration file. It's setting determines how quickly the
+** mail will be delivered versus the load on your system. If the
+** -v (verbose) flag is given, it will be forced to SM_DELIVER
+** mode.
+**
+** The error mode tells how to return errors.
+*/
+
+EXTERN char OpMode; /* operation mode, see below */
+
+#define MD_DELIVER 'm' /* be a mail sender */
+#define MD_SMTP 's' /* run SMTP on standard input */
+#define MD_ARPAFTP 'a' /* obsolete ARPANET mode (Grey Book) */
+#define MD_DAEMON 'd' /* run as a daemon */
+#define MD_VERIFY 'v' /* verify: don't collect or deliver */
+#define MD_TEST 't' /* test mode: resolve addrs only */
+#define MD_INITALIAS 'i' /* initialize alias database */
+#define MD_PRINT 'p' /* print the queue */
+#define MD_FREEZE 'z' /* freeze the configuration file */
+
+
+/* values for e_sendmode -- send modes */
+#define SM_DELIVER 'i' /* interactive delivery */
+#define SM_FORK 'b' /* deliver in background */
+#define SM_QUEUE 'q' /* queue, don't deliver */
+#define SM_DEFER 'd' /* defer map lookups as well as queue */
+#define SM_VERIFY 'v' /* verify only (used internally) */
+
+/* used only as a parameter to sendall */
+#define SM_DEFAULT '\0' /* unspecified, use SendMode */
+
+
+/* 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) */
+
+
+/* MIME processing mode */
+EXTERN int MimeMode;
+
+/* bit values for MimeMode */
+#define MM_CVTMIME 0x0001 /* convert 8 to 7 bit MIME */
+#define MM_PASS8BIT 0x0002 /* just send 8 bit data blind */
+#define MM_MIME8BIT 0x0004 /* convert 8-bit data to MIME */
+
+/* queue sorting order algorithm */
+EXTERN int QueueSortOrder;
+
+#define QS_BYPRIORITY 0 /* sort by message priority */
+#define QS_BYHOST 1 /* sort by first host name */
+
+
+/* how to handle messages without any recipient addresses */
+EXTERN int NoRecipientAction;
+
+#define NRA_NO_ACTION 0 /* just leave it as is */
+#define NRA_ADD_TO 1 /* add To: header */
+#define NRA_ADD_APPARENTLY_TO 2 /* add Apparently-To: header */
+#define NRA_ADD_BCC 3 /* add empty Bcc: header */
+#define NRA_ADD_TO_UNDISCLOSED 4 /* add To: undisclosed:; header */
+
+
+/* flags to putxline */
+#define PXLF_NOTHINGSPECIAL 0 /* no special mapping */
+#define PXLF_MAPFROM 0x0001 /* map From_ to >From_ */
+#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit *e
+ /*
+** Additional definitions
+*/
+
+
+/*
+** Privacy flags
+** These are bit values for the PrivacyFlags word.
+*/
+
+#define PRIV_PUBLIC 0 /* what have I got to hide? */
+#define PRIV_NEEDMAILHELO 0x0001 /* insist on HELO for MAIL, at least */
+#define PRIV_NEEDEXPNHELO 0x0002 /* insist on HELO for EXPN */
+#define PRIV_NEEDVRFYHELO 0x0004 /* insist on HELO for VRFY */
+#define PRIV_NOEXPN 0x0008 /* disallow EXPN command entirely */
+#define PRIV_NOVRFY 0x0010 /* disallow VRFY command entirely */
+#define PRIV_AUTHWARNINGS 0x0020 /* flag possible authorization probs */
+#define PRIV_NORECEIPTS 0x0040 /* disallow return receipts */
+#define PRIV_RESTRICTMAILQ 0x1000 /* restrict mailq command */
+#define PRIV_RESTRICTQRUN 0x2000 /* restrict queue run */
+#define PRIV_GOAWAY 0x0fff /* 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, parseaddr, allocaddr, and buildaddr.
+*/
+
+#define RF_SENDERADDR 0x001 /* this is a sender address */
+#define RF_HEADERADDR 0x002 /* this is a header address */
+#define RF_CANONICAL 0x004 /* strip comment information */
+#define RF_ADDDOMAIN 0x008 /* OK to do domain extension */
+#define RF_COPYPARSE 0x010 /* copy parsed user & host */
+#define RF_COPYPADDR 0x020 /* copy print address */
+#define RF_COPYALL (RF_COPYPARSE|RF_COPYPADDR)
+#define RF_COPYNONE 0
+
+
+/*
+** Flags passed to safefile.
+*/
+
+#define SFF_ANYFILE 0 /* no special restrictions */
+#define SFF_MUSTOWN 0x0001 /* user must own this file */
+#define SFF_NOSLINK 0x0002 /* file cannot be a symbolic link */
+#define SFF_ROOTOK 0x0004 /* ok for root to own this file */
+#define SFF_RUNASREALUID 0x0008 /* if no ctladdr, run as real uid */
+#define SFF_NOPATHCHECK 0x0010 /* don't bother checking dir path */
+#define SFF_SETUIDOK 0x0020 /* setuid files are ok */
+#define SFF_CREAT 0x0040 /* ok to create file if necessary */
+#define SFF_REGONLY 0x0080 /* regular files only */
+
+/* flags that are actually specific to safefopen */
+#define SFF_OPENASROOT 0x1000 /* open as root instead of real user */
+
+
+/*
+** Flags passed to mime8to7.
+*/
+
+#define M87F_OUTER 0 /* outer context */
+#define M87F_NO8BIT 0x0001 /* can't have 8-bit in this section */
+#define M87F_DIGEST 0x0002 /* processing multipart/digest */
+
+
+/*
+** Regular UNIX sockaddrs are too small to handle ISO addresses, so
+** we are forced to declare a supertype here.
+*/
+
+#ifdef DAEMON
+union bigsockaddr
+{
+ struct sockaddr sa; /* general version */
+#if NETUNIX
+ struct sockaddr_un sunix; /* UNIX family */
+#endif
+#if NETINET
+ struct sockaddr_in sin; /* INET family */
+#endif
+#if NETISO
+ struct sockaddr_iso siso; /* ISO family */
+#endif
+#if NETNS
+ struct sockaddr_ns sns; /* XNS family */
+#endif
+#if NETX25
+ struct sockaddr_x25 sx25; /* X.25 family */
+#endif
+};
+
+#define SOCKADDR union bigsockaddr
+
+EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */
+extern char *anynet_ntoa __P((SOCKADDR *));
+
+#endif
+
+
+/*
+** Vendor codes
+**
+** Vendors can customize sendmail to add special behaviour,
+** generally for back compatibility. Ideally, this should
+** be set up in the .cf file using the "V" command. However,
+** it's quite reasonable for some vendors to want the default
+** be their old version; this can be set using
+** -DVENDOR_DEFAULT=VENDOR_xxx
+** in the Makefile.
+**
+** Vendors should apply to sendmail@CS.Berkeley.EDU for
+** unique vendor codes.
+*/
+
+#define VENDOR_BERKELEY 1 /* Berkeley-native configuration file */
+#define VENDOR_SUN 2 /* Sun-native configuration file */
+#define VENDOR_HP 3 /* Hewlett-Packard specific config syntax */
+#define VENDOR_IBM 4 /* IBM specific config syntax */
+
+EXTERN int VendorCode; /* vendor-specific operation enhancements */
+ /*
+** Global variables.
+*/
+
+EXTERN bool FromFlag; /* if set, "From" person is explicit */
+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 Verbose; /* set if blow-by-blow desired */
+EXTERN bool GrabTo; /* if set, get recipients from msg */
+EXTERN bool SuprErrs; /* set if we are suppressing errors */
+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; /* using DNS -- interpret h_errno & MX RRs */
+EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */
+EXTERN bool SevenBitInput; /* force 7-bit data on input */
+EXTERN bool HasEightBits; /* has at least one eight bit input byte */
+EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */
+EXTERN FILE *InChannel; /* input connection */
+EXTERN FILE *OutChannel; /* output connection */
+EXTERN char *RealUserName; /* real user name of caller */
+EXTERN uid_t RealUid; /* real uid of caller */
+EXTERN gid_t RealGid; /* 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 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 LineNumber; /* line number in current input */
+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 CurrentLA; /* current load average */
+EXTERN long QueueFactor; /* slope of queue function */
+EXTERN time_t QueueIntvl; /* intervals between running the queue */
+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 *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 bool TryNullMXList; /* if we are the best MX, try host directly */
+EXTERN bool InChild; /* true if running in an SMTP subprocess */
+EXTERN bool DisConnected; /* running with OutChannel redirected to xf */
+EXTERN bool ColonOkInAddr; /* single colon legal in address */
+EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */
+EXTERN char SpaceSub; /* substitution for <lwsp> */
+EXTERN int PrivacyFlags; /* privacy flags */
+EXTERN char *ConfFile; /* location of configuration file [conf.c] */
+extern char *PidFile; /* location of proc id file [conf.c] */
+extern ADDRESS NullAddress; /* a null (template) address [main.c] */
+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 time_t MaxHostStatAge; /* max age of cached host status info */
+EXTERN time_t MinQueueAge; /* min delivery interval */
+EXTERN time_t DialDelay; /* delay between dial-on-demand tries */
+EXTERN char *SafeFileEnv; /* chroot location for file delivery */
+EXTERN char *HostsFile; /* path to /etc/hosts file */
+EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */
+EXTERN int MaxChildren; /* maximum number of daemonic children */
+EXTERN int CurChildren; /* current number of daemonic children */
+EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */
+EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */
+EXTERN char *OperatorChars; /* operators (old $o macro) */
+EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
+EXTERN bool SingleLineFromHeader; /* force From: header to be one line */
+EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */
+EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */
+EXTERN char *MustQuoteChars; /* quote these characters in phrases */
+EXTERN char *ServiceSwitchFile; /* backup service switch */
+EXTERN char *DefaultCharSet; /* default character set for MIME */
+EXTERN int DeliveryNiceness; /* how nice to be during delivery */
+EXTERN char *PostMasterCopy; /* address to get errs cc's */
+EXTERN int CheckpointInterval; /* queue file checkpoint interval */
+EXTERN bool DontPruneRoutes; /* don't prune source routes */
+EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */
+EXTERN int MaxMciCache; /* maximum entries in MCI cache */
+EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */
+EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */
+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 */
+EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
+EXTERN char *UserEnviron[MAXUSERENVIRON + 1];
+ /* saved user environment */
+extern int errno;
+
+
+/*
+** Timeouts
+**
+** Indicated values are the MINIMUM per RFC 1123 section 5.3.2.
+*/
+
+EXTERN struct
+{
+ /* RFC 1123-specified timeouts [minimum value] */
+ 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_connect; /* initial connection timeout */
+ 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) */
+ time_t to_ident; /* IDENT protocol requests */
+ time_t to_fileopen; /* opening :include: and .forward files */
+ /* following are per message */
+ time_t to_q_return[MAXTOCLASS]; /* queue return timeouts */
+ time_t to_q_warning[MAXTOCLASS]; /* queue warning timeouts */
+} TimeOuts;
+
+/* timeout classes for return and warning timeouts */
+# define TOC_NORMAL 0 /* normal delivery */
+# define TOC_URGENT 1 /* urgent delivery */
+# define TOC_NONURGENT 2 /* non-urgent delivery */
+
+
+/*
+** Trace information
+*/
+
+/* trace vector and macros for debugging flags */
+EXTERN u_char tTdvect[100];
+# define tTd(flag, level) (tTdvect[flag] >= level)
+# define tTdlevel(flag) (tTdvect[flag])
+ /*
+** Miscellaneous information.
+*/
+
+
+
+/*
+** Some in-line functions
+*/
+
+/* set exit status */
+#define setstat(s) { \
+ if (ExitStat == EX_OK || ExitStat == EX_TEMPFAIL) \
+ ExitStat = s; \
+ }
+
+/* make a copy of a string */
+#define newstr(s) strcpy(xalloc(strlen(s) + 1), s)
+
+#define STRUCTCOPY(s, d) d = s
+
+
+/*
+** Declarations of useful functions
+*/
+
+extern char *xalloc __P((int));
+extern FILE *dfopen __P((char *, 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 char *fgetfolded __P((char *, int, FILE *));
+extern char *username __P(());
+extern char *pintvl __P((time_t, bool));
+extern bool shouldqueue __P((long, time_t));
+extern bool lockfile __P((int, char *, char *, int));
+extern char *hostsignature __P((MAILER *, char *, ENVELOPE *));
+extern void openxscript __P((ENVELOPE *));
+extern void closexscript __P((ENVELOPE *));
+extern char *shortenstring __P((const char *, int));
+extern bool usershellok __P((char *, char *));
+extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
+extern char *hvalue __P((char *, HDR *));
+extern char *defcharset __P((ENVELOPE *));
+extern bool wordinclass __P((char *, int));
+extern char *denlstring __P((char *, bool, bool));
+extern void makelower __P((char *));
+extern void rebuildaliases __P((MAP *, bool));
+extern void readaliases __P((MAP *, FILE *, bool, bool));
+extern void finis __P(());
+extern void setsender __P((char *, ENVELOPE *, char **, bool));
+extern FILE *safefopen __P((char *, int, int, int));
+extern void xputs __P((const char *));
+extern void logsender __P((ENVELOPE *, char *));
+extern void smtprset __P((MAILER *, MCI *, ENVELOPE *));
+extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *));
+extern void setuserenv __P((const char *, const char *));
+extern void disconnect __P((int, ENVELOPE *));
+extern void putxline __P((char *, MCI *, int));
+extern void dumpfd __P((int, bool, bool));
+extern void makemailer __P((char *));
+extern void putfromline __P((MCI *, ENVELOPE *));
+extern void setoption __P((int, char *, bool, bool, ENVELOPE *));
+extern void setclass __P((int, char *));
+extern void inittimeouts __P((char *));
+extern void logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
+extern void giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
+
+extern const char *errstring __P((int));
+extern sigfunc_t setsignal __P((int, sigfunc_t));
+extern struct hostent *sm_gethostbyname __P((char *));
+extern struct hostent *sm_gethostbyaddr __P((char *, int, int));
+extern struct passwd *sm_getpwnam __P((char *));
+extern struct passwd *sm_getpwuid __P((UID_T));
+
+#ifdef XDEBUG
+extern void checkfd012 __P((char *));
+#endif
+
+/* 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
+
+#if !HASSNPRINTF
+# ifdef __STDC__
+extern void snprintf(char *, size_t, const char *, ...);
+extern void vsnprintf(char *, size_t, const char *, va_list);
+# else
+extern void snprintf();
+extern void vsnprintf();
+# endif
+#endif
diff --git a/usr.sbin/sendmail/src/sendmail.hf b/usr.sbin/sendmail/src/sendmail.hf
new file mode 100644
index 000000000000..14db22c68ee5
--- /dev/null
+++ b/usr.sbin/sendmail/src/sendmail.hf
@@ -0,0 +1,78 @@
+cpyr
+cpyr Copyright (c) 1983, 1995 Eric P. Allman
+cpyr Copyright (c) 1988, 1993
+cpyr The Regents of the University of California. All rights reserved.
+cpyr
+cpyr @(#)sendmail.hf 8.7 (Berkeley) 10/1/95
+cpyr
+smtp Commands:
+smtp HELO EHLO MAIL RCPT DATA
+smtp RSET NOOP QUIT HELP VRFY
+smtp EXPN VERB
+smtp For more info use "HELP <topic>".
+smtp To report bugs in the implementation send email to
+smtp sendmail-bugs@sendmail.org.
+smtp For local information send email to Postmaster at your site.
+help HELP [ <topic> ]
+help The HELP command gives help info.
+helo HELO <hostname>
+helo Introduce yourself.
+ehlo EHLO <hostname>
+ehlo Introduce yourself, and request extended SMTP mode.
+mail MAIL FROM: <sender>
+mail Specifies the sender.
+rcpt RCPT TO: <recipient>
+rcpt Specifies the recipient. Can be used any number of times.
+data DATA
+data Following text is collected as the message.
+data End with a single dot.
+rset RSET
+rset Resets the system.
+quit QUIT
+quit Exit sendmail (SMTP).
+verb VERB
+verb Go into verbose mode. This sends 0xy responses that are
+verb not RFC821 standard (but should be) They are recognized
+verb by humans and other sendmail implementations.
+vrfy VRFY <recipient>
+vrfy Verify an address. If you want to see what it aliases
+vrfy to, use EXPN instead.
+expn EXPN <recipient>
+expn Expand an address. If the address indicates a mailing
+expn list, return the contents of that list.
+noop NOOP
+noop Do nothing.
+send SEND FROM: <sender>
+send replaces the MAIL command, and can be used to send
+send directly to a users terminal. Not supported in this
+send implementation.
+soml SOML FROM: <sender>
+soml Send or mail. If the user is logged in, send directly,
+soml otherwise mail. Not supported in this implementation.
+saml SAML FROM: <sender>
+saml Send and mail. Send directly to the user's terminal,
+saml and also mail a letter. Not supported in this
+saml implementation.
+turn TURN
+turn Reverses the direction of the connection. Not currently
+turn implemented.
+-bt Help for test mode:
+-bt ? :this help message.
+-bt .Dmvalue :define macro `m' to `value'.
+-bt .Ccvalue :add `value' to class `c'.
+-bt =Sruleset :dump the contents of the indicated ruleset.
+-bt =M :display the known mailers.
+-bt -ddebug-spec :equivalent to the command-line -d debug flag.
+-bt $m :print the value of macro $m.
+-bt $=c :print the contents of class $=c.
+-bt /mx host :returns the MX records for `host'.
+-bt /parse address :parse address, returning the value of crackaddr, and
+-bt the parsed address (same as -bv).
+-bt /try mailer addr :rewrite address into the form it will have when
+-bt presented to the indicated mailer.
+-bt /tryflags flags :set flags used by parsing. The flags can be `H' for
+-bt Header or `E' for Envelope, and `S' for Sender or `R'
+-bt for Recipient. These can be combined, `HR' sets
+-bt flags for header recipients.
+-bt /canon hostname :try to canonify hostname.
+-bt /map mapname key :look up `key' in the indicated `mapname'.
diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c
new file mode 100644
index 000000000000..5e7ab64b1045
--- /dev/null
+++ b/usr.sbin/sendmail/src/srvrsmtp.c
@@ -0,0 +1,1285 @@
+/*
+ * Copyright (c) 1983, 1995 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 SMTP
+static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (with SMTP)";
+#else
+static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (without SMTP)";
+#endif
+#endif /* not lint */
+
+# include <errno.h>
+
+# ifdef SMTP
+
+/*
+** SMTP -- run the SMTP protocol.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** never.
+**
+** Side Effects:
+** Reads commands from the input channel and processes
+** them.
+*/
+
+struct cmd
+{
+ char *cmdname; /* command name */
+ int cmdcode; /* internal code, see below */
+};
+
+/* values for cmdcode */
+# define CMDERROR 0 /* bad command */
+# define CMDMAIL 1 /* mail -- designate sender */
+# define CMDRCPT 2 /* rcpt -- designate recipient */
+# define CMDDATA 3 /* data -- send message text */
+# define CMDRSET 4 /* rset -- reset state */
+# define CMDVRFY 5 /* vrfy -- verify address */
+# 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 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 */
+/* use this to catch and log "door handle" attempts on your system */
+# define CMDLOGBOGUS 23 /* bogus command that should be logged */
+/* debugging-only commands, only enabled if SMTPDEBUG is defined */
+# define CMDDBGQSHOW 24 /* showq -- show send queue */
+# define CMDDBGDEBUG 25 /* debug -- set debug mode */
+
+static struct cmd CmdTab[] =
+{
+ "mail", CMDMAIL,
+ "rcpt", CMDRCPT,
+ "data", CMDDATA,
+ "rset", CMDRSET,
+ "vrfy", CMDVRFY,
+ "expn", CMDEXPN,
+ "help", CMDHELP,
+ "noop", CMDNOOP,
+ "quit", CMDQUIT,
+ "helo", CMDHELO,
+ "ehlo", CMDEHLO,
+ "verb", CMDVERB,
+ "onex", CMDONEX,
+ /*
+ * remaining commands are here only
+ * to trap and log attempts to use them
+ */
+ "showq", CMDDBGQSHOW,
+ "debug", CMDDBGDEBUG,
+ "wiz", CMDLOGBOGUS,
+ NULL, CMDERROR,
+};
+
+bool OneXact = FALSE; /* one xaction only this run */
+char *CurSmtpClient; /* who's at the other end of channel */
+
+static char *skipword();
+
+
+#define MAXBADCOMMANDS 25 /* maximum number of bad commands */
+
+void
+smtp(e)
+ register ENVELOPE *volatile e;
+{
+ register char *p;
+ register struct cmd *c;
+ char *cmd;
+ auto ADDRESS *vrfyqueue;
+ ADDRESS *a;
+ volatile bool gotmail; /* mail command received */
+ volatile bool gothello; /* helo command received */
+ bool vrfy; /* set if this is a vrfy command */
+ char *volatile protocol; /* sending protocol */
+ char *volatile sendinghost; /* sending hostname */
+ char *volatile peerhostname; /* name of SMTP peer or "localhost" */
+ auto char *delimptr;
+ char *id;
+ volatile int nrcpts = 0; /* number of RCPT commands */
+ bool doublequeue;
+ volatile int badcommands = 0; /* count of bad commands */
+ char inp[MAXLINE];
+ char cmdbuf[MAXLINE];
+ extern ENVELOPE BlankEnvelope;
+ extern void help __P((char *));
+
+ if (fileno(OutChannel) != fileno(stdout))
+ {
+ /* arrange for debugging output to go to remote host */
+ (void) dup2(fileno(OutChannel), fileno(stdout));
+ }
+ settime(e);
+ peerhostname = RealHostName;
+ if (peerhostname == NULL)
+ peerhostname = "localhost";
+ CurHostName = peerhostname;
+ CurSmtpClient = macvalue('_', e);
+ if (CurSmtpClient == NULL)
+ CurSmtpClient = CurHostName;
+
+ setproctitle("server %s startup", CurSmtpClient);
+#ifdef LOG
+ if (LogLevel > 11)
+ {
+ /* log connection information */
+ syslog(LOG_INFO, "SMTP connect from %.100s (%.100s)",
+ CurSmtpClient, anynet_ntoa(&RealHostAddr));
+ }
+#endif
+
+ /* output the first line, inserting "ESMTP" as second word */
+ expand(SmtpGreeting, inp, sizeof inp, e);
+ p = strchr(inp, '\n');
+ if (p != NULL)
+ *p++ = '\0';
+ id = strchr(inp, ' ');
+ if (id == NULL)
+ id = &inp[strlen(inp)];
+ cmd = p == NULL ? "220 %.*s ESMTP%s" : "220-%.*s ESMTP%s";
+ message(cmd, id - inp, inp, id);
+
+ /* output remaining lines */
+ while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL)
+ {
+ *p++ = '\0';
+ if (isascii(*id) && isspace(*id))
+ id++;
+ message("220-%s", id);
+ }
+ if (id != NULL)
+ {
+ if (isascii(*id) && isspace(*id))
+ id++;
+ message("220 %s", id);
+ }
+
+ protocol = NULL;
+ sendinghost = macvalue('s', e);
+ gothello = FALSE;
+ gotmail = FALSE;
+ for (;;)
+ {
+ /* arrange for backout */
+ if (setjmp(TopFrame) > 0)
+ {
+ /* if() nesting is necessary for Cray UNICOS */
+ if (InChild)
+ {
+ QuickAbort = FALSE;
+ SuprErrs = TRUE;
+ finis();
+ }
+ }
+ QuickAbort = FALSE;
+ HoldErrs = FALSE;
+ LogUsrErrs = FALSE;
+ e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
+
+ /* setup for the read */
+ e->e_to = NULL;
+ Errors = 0;
+ (void) fflush(stdout);
+
+ /* read the input line */
+ SmtpPhase = "server cmd read";
+ setproctitle("server %s cmd read", CurSmtpClient);
+ p = sfgets(inp, sizeof inp, InChannel, TimeOuts.to_nextcommand,
+ SmtpPhase);
+
+ /* handle errors */
+ if (p == NULL)
+ {
+ /* end of file, just die */
+ disconnect(1, e);
+ message("421 %s Lost input channel from %s",
+ MyHostName, CurSmtpClient);
+#ifdef LOG
+ if (LogLevel > (gotmail ? 1 : 19))
+ syslog(LOG_NOTICE, "lost input channel from %.100s",
+ CurSmtpClient);
+#endif
+ if (InChild)
+ ExitStat = EX_QUIT;
+ finis();
+ }
+
+ /* clean up end of line */
+ fixcrlf(inp, TRUE);
+
+ /* echo command to transcript */
+ if (e->e_xfp != NULL)
+ fprintf(e->e_xfp, "<<< %s\n", inp);
+
+ if (e->e_id == NULL)
+ setproctitle("%s: %.80s", CurSmtpClient, inp);
+ else
+ setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
+
+ /* break off command */
+ for (p = inp; isascii(*p) && isspace(*p); p++)
+ continue;
+ cmd = cmdbuf;
+ while (*p != '\0' &&
+ !(isascii(*p) && isspace(*p)) &&
+ cmd < &cmdbuf[sizeof cmdbuf - 2])
+ *cmd++ = *p++;
+ *cmd = '\0';
+
+ /* throw away leading whitespace */
+ while (isascii(*p) && isspace(*p))
+ p++;
+
+ /* decode command */
+ for (c = CmdTab; c->cmdname != NULL; c++)
+ {
+ if (!strcasecmp(c->cmdname, cmdbuf))
+ break;
+ }
+
+ /* reset errors */
+ errno = 0;
+
+ /* process command */
+ switch (c->cmdcode)
+ {
+ case CMDHELO: /* hello -- introduce yourself */
+ case CMDEHLO: /* extended hello */
+ if (c->cmdcode == CMDEHLO)
+ {
+ protocol = "ESMTP";
+ SmtpPhase = "server EHLO";
+ }
+ else
+ {
+ protocol = "SMTP";
+ SmtpPhase = "server HELO";
+ }
+
+ /* check for valid domain name (re 1123 5.2.5) */
+ if (*p == '\0')
+ {
+ message("501 %s requires domain address",
+ cmdbuf);
+ break;
+ }
+ else
+ {
+ register char *q;
+
+ for (q = p; *q != '\0'; q++)
+ {
+ if (!isascii(*q))
+ break;
+ if (isalnum(*q))
+ continue;
+ if (isspace(*q))
+ {
+ *q = '\0';
+ break;
+ }
+ if (strchr("[].-_#", *q) == NULL)
+ break;
+ }
+ if (*q != '\0')
+ {
+ message("501 Invalid domain name");
+ break;
+ }
+ }
+
+ sendinghost = newstr(p);
+ gothello = TRUE;
+ if (c->cmdcode != CMDEHLO)
+ {
+ /* print old message and be done with it */
+ message("250 %s Hello %s, pleased to meet you",
+ MyHostName, CurSmtpClient);
+ break;
+ }
+
+ /* print extended message and brag */
+ message("250-%s Hello %s, pleased to meet you",
+ MyHostName, CurSmtpClient);
+ if (!bitset(PRIV_NOEXPN, PrivacyFlags))
+ message("250-EXPN");
+#if MIME8TO7
+ message("250-8BITMIME");
+#endif
+ if (MaxMessageSize > 0)
+ message("250-SIZE %ld", MaxMessageSize);
+ else
+ message("250-SIZE");
+#if DSN
+ if (SendMIMEErrors)
+ message("250-DSN");
+#endif
+ message("250-VERB");
+ message("250-ONEX");
+ message("250 HELP");
+ break;
+
+ case CMDMAIL: /* mail -- designate sender */
+ SmtpPhase = "server MAIL";
+
+ /* check for validity of this command */
+ if (!gothello)
+ {
+ /* set sending host to our known value */
+ if (sendinghost == NULL)
+ sendinghost = peerhostname;
+
+ if (bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
+ {
+ message("503 Polite people say HELO first");
+ break;
+ }
+ }
+ if (gotmail)
+ {
+ message("503 Sender already specified");
+ if (InChild)
+ finis();
+ break;
+ }
+ if (InChild)
+ {
+ errno = 0;
+ syserr("503 Nested MAIL command: MAIL %s", p);
+ finis();
+ }
+
+ /* fork a subprocess to process this command */
+ if (runinchild("SMTP-MAIL", e) > 0)
+ break;
+ if (!gothello)
+ {
+ auth_warning(e,
+ "Host %s didn't use HELO protocol",
+ CurSmtpClient);
+ }
+#ifdef PICKY_HELO_CHECK
+ if (strcasecmp(sendinghost, peerhostname) != 0 &&
+ (strcasecmp(peerhostname, "localhost") != 0 ||
+ strcasecmp(sendinghost, MyHostName) != 0))
+ {
+ auth_warning(e, "Host %s claimed to be %s",
+ CurSmtpClient, sendinghost);
+ }
+#endif
+
+ if (protocol == NULL)
+ protocol = "SMTP";
+ define('r', protocol, e);
+ define('s', sendinghost, e);
+ initsys(e);
+ nrcpts = 0;
+ e->e_flags |= EF_LOGSENDER|EF_CLRQUEUE;
+ setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
+
+ /* child -- go do the processing */
+ p = skipword(p, "from");
+ if (p == NULL)
+ break;
+ if (setjmp(TopFrame) > 0)
+ {
+ /* this failed -- undo work */
+ if (InChild)
+ {
+ QuickAbort = FALSE;
+ SuprErrs = TRUE;
+ e->e_flags &= ~EF_FATALERRS;
+ finis();
+ }
+ break;
+ }
+ QuickAbort = TRUE;
+
+ /* must parse sender first */
+ delimptr = NULL;
+ setsender(p, e, &delimptr, FALSE);
+ p = delimptr;
+ if (p != NULL && *p != '\0')
+ *p++ = '\0';
+
+ /* check for possible spoofing */
+ if (RealUid != 0 && OpMode == MD_SMTP &&
+ !wordinclass(RealUserName, 't') &&
+ !bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) &&
+ strcmp(e->e_from.q_user, RealUserName) != 0)
+ {
+ auth_warning(e, "%s owned process doing -bs",
+ RealUserName);
+ }
+
+ /* now parse ESMTP arguments */
+ e->e_msgsize = 0;
+ while (p != NULL && *p != '\0')
+ {
+ char *kp;
+ char *vp = NULL;
+ extern void mail_esmtp_args __P((char *, char *, ENVELOPE *));
+
+ /* 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);
+
+ mail_esmtp_args(kp, vp, e);
+ }
+
+ if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
+ {
+ usrerr("552 Message size exceeds fixed maximum message size (%ld)",
+ MaxMessageSize);
+ /* NOTREACHED */
+ }
+
+ if (!enoughdiskspace(e->e_msgsize))
+ {
+ message("452 Insufficient disk space; try again later");
+ break;
+ }
+ message("250 Sender ok");
+ gotmail = TRUE;
+ break;
+
+ case CMDRCPT: /* rcpt -- designate recipient */
+ if (!gotmail)
+ {
+ usrerr("503 Need MAIL before RCPT");
+ break;
+ }
+ SmtpPhase = "server RCPT";
+ if (setjmp(TopFrame) > 0)
+ {
+ e->e_flags &= ~EF_FATALERRS;
+ break;
+ }
+ QuickAbort = TRUE;
+ LogUsrErrs = TRUE;
+
+ if (e->e_sendmode != SM_DELIVER)
+ e->e_flags |= EF_VRFYONLY;
+
+ p = skipword(p, "to");
+ if (p == NULL)
+ break;
+ a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e);
+ if (a == NULL)
+ break;
+ p = delimptr;
+
+ /* now parse ESMTP arguments */
+ while (p != NULL && *p != '\0')
+ {
+ char *kp;
+ char *vp = NULL;
+ extern void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *));
+
+ /* 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("RCPT: got arg %s=\"%s\"\n", kp,
+ vp == NULL ? "<null>" : vp);
+
+ rcpt_esmtp_args(a, kp, vp, e);
+ }
+
+ /* save in recipient list after ESMTP mods */
+ a = recipient(a, &e->e_sendqueue, 0, e);
+
+ if (Errors != 0)
+ break;
+
+ /* no errors during parsing, but might be a duplicate */
+ e->e_to = p;
+ if (!bitset(QBADADDR, a->q_flags))
+ {
+ message("250 Recipient ok%s",
+ bitset(QQUEUEUP, a->q_flags) ?
+ " (will queue)" : "");
+ nrcpts++;
+ }
+ else
+ {
+ /* punt -- should keep message in ADDRESS.... */
+ message("550 Addressee unknown");
+ }
+ e->e_to = NULL;
+ break;
+
+ case CMDDATA: /* data -- text of mail */
+ SmtpPhase = "server DATA";
+ if (!gotmail)
+ {
+ message("503 Need MAIL command");
+ break;
+ }
+ else if (nrcpts <= 0)
+ {
+ message("503 Need RCPT (recipient)");
+ break;
+ }
+
+ /* check to see if we need to re-expand aliases */
+ /* also reset QBADADDR on already-diagnosted addrs */
+ doublequeue = FALSE;
+ for (a = e->e_sendqueue; a != NULL; a = a->q_next)
+ {
+ if (bitset(QVERIFIED, a->q_flags))
+ {
+ /* need to re-expand aliases */
+ doublequeue = TRUE;
+ }
+ if (bitset(QBADADDR, a->q_flags))
+ {
+ /* make this "go away" */
+ a->q_flags |= QDONTSEND;
+ a->q_flags &= ~QBADADDR;
+ }
+ }
+
+ /* collect the text of the message */
+ SmtpPhase = "collect";
+ buffer_errors();
+ collect(InChannel, TRUE, doublequeue, NULL, e);
+ flush_errors(TRUE);
+ if (Errors != 0)
+ goto abortmessage;
+
+ /* make sure we actually do delivery */
+ e->e_flags &= ~EF_CLRQUEUE;
+
+ /* from now on, we have to operate silently */
+ buffer_errors();
+ e->e_errormode = EM_MAIL;
+
+ /*
+ ** Arrange to send to everyone.
+ ** If sending to multiple people, mail back
+ ** errors rather than reporting directly.
+ ** In any case, don't mail back errors for
+ ** anything that has happened up to
+ ** now (the other end will do this).
+ ** Truncate our transcript -- the mail has gotten
+ ** to us successfully, and if we have
+ ** to mail this back, it will be easier
+ ** on the reader.
+ ** Then send to everyone.
+ ** Finally give a reply code. If an error has
+ ** already been given, don't mail a
+ ** message back.
+ ** We goose error returns by clearing error bit.
+ */
+
+ SmtpPhase = "delivery";
+ e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp);
+ id = e->e_id;
+
+ if (doublequeue)
+ {
+ /* make sure it is in the queue */
+ queueup(e, FALSE);
+ }
+ else
+ {
+ /* send to all recipients */
+ sendall(e, SM_DEFAULT);
+ }
+ e->e_to = NULL;
+
+ /* issue success message */
+ message("250 %s Message accepted for delivery", id);
+
+ /* if we just queued, poke it */
+ if (doublequeue && e->e_sendmode != SM_QUEUE &&
+ e->e_sendmode != SM_DEFER)
+ {
+ extern pid_t dowork();
+
+ unlockqueue(e);
+ (void) dowork(id, TRUE, TRUE, e);
+ }
+
+ abortmessage:
+ /* if in a child, pop back to our parent */
+ if (InChild)
+ finis();
+
+ /* clean up a bit */
+ gotmail = FALSE;
+ dropenvelope(e);
+ CurEnv = e = newenvelope(e, CurEnv);
+ e->e_flags = BlankEnvelope.e_flags;
+ break;
+
+ case CMDRSET: /* rset -- reset state */
+ message("250 Reset state");
+
+ /* arrange to ignore any current send list */
+ e->e_sendqueue = NULL;
+ e->e_flags |= EF_CLRQUEUE;
+ if (InChild)
+ finis();
+
+ /* clean up a bit */
+ gotmail = FALSE;
+ dropenvelope(e);
+ CurEnv = e = newenvelope(e, CurEnv);
+ break;
+
+ case CMDVRFY: /* vrfy -- verify address */
+ case CMDEXPN: /* expn -- expand address */
+ vrfy = c->cmdcode == CMDVRFY;
+ if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
+ PrivacyFlags))
+ {
+ if (vrfy)
+ message("252 Cannot VRFY user; try RCPT to attempt delivery (or try finger)");
+ else
+ message("502 Sorry, we do not allow this operation");
+#ifdef LOG
+ if (LogLevel > 5)
+ syslog(LOG_INFO, "%.100s: %s [rejected]",
+ CurSmtpClient,
+ shortenstring(inp, 203));
+#endif
+ break;
+ }
+ 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, "%.100s: %s",
+ CurSmtpClient,
+ shortenstring(inp, 203));
+#endif
+ vrfyqueue = NULL;
+ QuickAbort = TRUE;
+ 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, NULLADDR, &vrfyqueue, 0, e);
+ }
+ if (Errors != 0)
+ {
+ if (InChild)
+ finis();
+ break;
+ }
+ if (vrfyqueue == NULL)
+ {
+ message("554 Nothing to %s", vrfy ? "VRFY" : "EXPN");
+ }
+ while (vrfyqueue != NULL)
+ {
+ extern void printvrfyaddr __P((ADDRESS *, bool));
+
+ a = vrfyqueue;
+ while ((a = a->q_next) != NULL &&
+ bitset(QDONTSEND|QBADADDR, a->q_flags))
+ continue;
+ if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
+ printvrfyaddr(vrfyqueue, a == NULL);
+ vrfyqueue = vrfyqueue->q_next;
+ }
+ if (InChild)
+ finis();
+ break;
+
+ case CMDHELP: /* help -- give user info */
+ help(p);
+ break;
+
+ case CMDNOOP: /* noop -- do nothing */
+ message("250 OK");
+ break;
+
+ case CMDQUIT: /* quit -- leave mail */
+ message("221 %s closing connection", MyHostName);
+
+doquit:
+ /* arrange to ignore any current send list */
+ e->e_sendqueue = NULL;
+
+ /* avoid future 050 messages */
+ disconnect(1, e);
+
+ 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;
+ e->e_sendmode = SM_DELIVER;
+ message("250 Verbose mode");
+ break;
+
+ case CMDONEX: /* doing one transaction only */
+ OneXact = TRUE;
+ message("250 Only one transaction");
+ break;
+
+# ifdef SMTPDEBUG
+ case CMDDBGQSHOW: /* show queues */
+ printf("Send Queue=");
+ printaddr(e->e_sendqueue, TRUE);
+ break;
+
+ case CMDDBGDEBUG: /* set debug mode */
+ tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+ tTflag(p);
+ message("200 Debug set");
+ break;
+
+# else /* not SMTPDEBUG */
+ case CMDDBGQSHOW: /* show queues */
+ case CMDDBGDEBUG: /* set debug mode */
+# endif /* SMTPDEBUG */
+ case CMDLOGBOGUS: /* bogus command */
+# ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_CRIT,
+ "\"%s\" command from %.100s (%.100s)",
+ c->cmdname, CurSmtpClient,
+ anynet_ntoa(&RealHostAddr));
+# endif
+ /* FALL THROUGH */
+
+ case CMDERROR: /* unknown command */
+ if (++badcommands > MAXBADCOMMANDS)
+ {
+ message("421 %s Too many bad commands; closing connection",
+ MyHostName);
+ goto doquit;
+ }
+
+ message("500 Command unrecognized");
+ break;
+
+ default:
+ errno = 0;
+ syserr("500 smtp: unknown code %d", c->cmdcode);
+ break;
+ }
+ }
+}
+ /*
+** SKIPWORD -- skip a fixed word.
+**
+** Parameters:
+** p -- place to start looking.
+** w -- word to skip.
+**
+** Returns:
+** p following w.
+** NULL on error.
+**
+** Side Effects:
+** clobbers the p data area.
+*/
+
+static char *
+skipword(p, w)
+ register char *p;
+ char *w;
+{
+ register char *q;
+ char *firstp = p;
+
+ /* find beginning of word */
+ while (isascii(*p) && isspace(*p))
+ p++;
+ q = p;
+
+ /* find end of word */
+ while (*p != '\0' && *p != ':' && !(isascii(*p) && isspace(*p)))
+ p++;
+ while (isascii(*p) && isspace(*p))
+ *p++ = '\0';
+ if (*p != ':')
+ {
+ syntax:
+ message("501 Syntax error in parameters scanning \"%s\"",
+ shortenstring(firstp, 203));
+ Errors++;
+ return (NULL);
+ }
+ *p++ = '\0';
+ while (isascii(*p) && isspace(*p))
+ p++;
+
+ if (*p == '\0')
+ goto syntax;
+
+ /* see if the input word matches desired word */
+ if (strcasecmp(q, w))
+ goto syntax;
+
+ return (p);
+}
+ /*
+** MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line
+**
+** Parameters:
+** kp -- the parameter key.
+** vp -- the value of that parameter.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+mail_esmtp_args(kp, vp, e)
+ char *kp;
+ char *vp;
+ ENVELOPE *e;
+{
+ if (strcasecmp(kp, "size") == 0)
+ {
+ if (vp == NULL)
+ {
+ usrerr("501 SIZE requires a value");
+ /* NOTREACHED */
+ }
+# if defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY)
+ e->e_msgsize = strtoul(vp, (char **) NULL, 10);
+# else
+ e->e_msgsize = strtol(vp, (char **) NULL, 10);
+# endif
+ }
+ else if (strcasecmp(kp, "body") == 0)
+ {
+ if (vp == NULL)
+ {
+ usrerr("501 BODY requires a value");
+ /* NOTREACHED */
+ }
+ else if (strcasecmp(vp, "8bitmime") == 0)
+ {
+ SevenBitInput = FALSE;
+ }
+ else if (strcasecmp(vp, "7bit") == 0)
+ {
+ SevenBitInput = TRUE;
+ }
+ else
+ {
+ usrerr("501 Unknown BODY type %s",
+ vp);
+ /* NOTREACHED */
+ }
+ e->e_bodytype = newstr(vp);
+ }
+ else if (strcasecmp(kp, "envid") == 0)
+ {
+ if (vp == NULL)
+ {
+ usrerr("501 ENVID requires a value");
+ /* NOTREACHED */
+ }
+ if (!xtextok(vp))
+ {
+ usrerr("501 Syntax error in ENVID parameter value");
+ /* NOTREACHED */
+ }
+ if (e->e_envid != NULL)
+ {
+ usrerr("501 Duplicate ENVID parameter");
+ /* NOTREACHED */
+ }
+ e->e_envid = newstr(vp);
+ }
+ else if (strcasecmp(kp, "ret") == 0)
+ {
+ if (vp == NULL)
+ {
+ usrerr("501 RET requires a value");
+ /* NOTREACHED */
+ }
+ if (bitset(EF_RET_PARAM, e->e_flags))
+ {
+ usrerr("501 Duplicate RET parameter");
+ /* NOTREACHED */
+ }
+ e->e_flags |= EF_RET_PARAM;
+ if (strcasecmp(vp, "hdrs") == 0)
+ e->e_flags |= EF_NO_BODY_RETN;
+ else if (strcasecmp(vp, "full") != 0)
+ {
+ usrerr("501 Bad argument \"%s\" to RET", vp);
+ /* NOTREACHED */
+ }
+ }
+ else
+ {
+ usrerr("501 %s parameter unrecognized", kp);
+ /* NOTREACHED */
+ }
+}
+ /*
+** RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line
+**
+** Parameters:
+** a -- the address corresponding to the To: parameter.
+** kp -- the parameter key.
+** vp -- the value of that parameter.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+rcpt_esmtp_args(a, kp, vp, e)
+ ADDRESS *a;
+ char *kp;
+ char *vp;
+ ENVELOPE *e;
+{
+ if (strcasecmp(kp, "notify") == 0)
+ {
+ char *p;
+
+ if (vp == NULL)
+ {
+ usrerr("501 NOTIFY requires a value");
+ /* NOTREACHED */
+ }
+ a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY);
+ a->q_flags |= QHASNOTIFY;
+ if (strcasecmp(vp, "never") == 0)
+ return;
+ for (p = vp; p != NULL; vp = p)
+ {
+ p = strchr(p, ',');
+ if (p != NULL)
+ *p++ = '\0';
+ if (strcasecmp(vp, "success") == 0)
+ a->q_flags |= QPINGONSUCCESS;
+ else if (strcasecmp(vp, "failure") == 0)
+ a->q_flags |= QPINGONFAILURE;
+ else if (strcasecmp(vp, "delay") == 0)
+ a->q_flags |= QPINGONDELAY;
+ else
+ {
+ usrerr("501 Bad argument \"%s\" to NOTIFY",
+ vp);
+ /* NOTREACHED */
+ }
+ }
+ }
+ else if (strcasecmp(kp, "orcpt") == 0)
+ {
+ if (vp == NULL)
+ {
+ usrerr("501 ORCPT requires a value");
+ /* NOTREACHED */
+ }
+ if (strchr(vp, ';') == NULL || !xtextok(vp))
+ {
+ usrerr("501 Syntax error in ORCPT parameter value");
+ /* NOTREACHED */
+ }
+ if (a->q_orcpt != NULL)
+ {
+ usrerr("501 Duplicate ORCPT parameter");
+ /* NOTREACHED */
+ }
+ a->q_orcpt = newstr(vp);
+ }
+ else
+ {
+ usrerr("501 %s parameter unrecognized", kp);
+ /* NOTREACHED */
+ }
+}
+ /*
+** 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.
+*/
+
+void
+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);
+ }
+}
+ /*
+** RUNINCHILD -- return twice -- once in the child, then in the parent again
+**
+** Parameters:
+** label -- a string used in error messages
+**
+** Returns:
+** zero in the child
+** one in the parent
+**
+** Side Effects:
+** none.
+*/
+
+int
+runinchild(label, e)
+ char *label;
+ register ENVELOPE *e;
+{
+ int childpid;
+
+ if (!OneXact)
+ {
+ childpid = dofork();
+ if (childpid < 0)
+ {
+ syserr("451 %s: cannot fork", label);
+ return (1);
+ }
+ if (childpid > 0)
+ {
+ auto int st;
+
+ /* parent -- wait for child to complete */
+ setproctitle("server %s child wait", CurSmtpClient);
+ st = waitfor(childpid);
+ if (st == -1)
+ syserr("451 %s: lost child", label);
+ else if (!WIFEXITED(st))
+ syserr("451 %s: died on signal %d",
+ label, st & 0177);
+
+ /* if we exited on a QUIT command, complete the process */
+ if (WEXITSTATUS(st) == EX_QUIT)
+ {
+ disconnect(1, e);
+ finis();
+ }
+
+ return (1);
+ }
+ else
+ {
+ /* child */
+ InChild = TRUE;
+ QuickAbort = FALSE;
+ clearenvelope(e, FALSE);
+ }
+ }
+
+ /* open alias database */
+ initmaps(FALSE, e);
+
+ return (0);
+}
+
+# endif /* SMTP */
+ /*
+** HELP -- implement the HELP command.
+**
+** Parameters:
+** topic -- the topic we want help for.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** outputs the help file to message output.
+*/
+
+void
+help(topic)
+ char *topic;
+{
+ register FILE *hf;
+ int len;
+ bool noinfo;
+ char buf[MAXLINE];
+ extern char Version[];
+
+
+ if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL)
+ {
+ /* no help */
+ errno = 0;
+ message("502 Sendmail %s -- HELP not implemented", Version);
+ return;
+ }
+
+ if (topic == NULL || *topic == '\0')
+ {
+ topic = "smtp";
+ message("214-This is Sendmail version %s", Version);
+ noinfo = FALSE;
+ }
+ else
+ {
+ makelower(topic);
+ noinfo = TRUE;
+ }
+
+ len = strlen(topic);
+
+ while (fgets(buf, sizeof buf, hf) != NULL)
+ {
+ if (strncmp(buf, topic, len) == 0)
+ {
+ register char *p;
+
+ p = strchr(buf, '\t');
+ if (p == NULL)
+ p = buf;
+ else
+ p++;
+ fixcrlf(p, TRUE);
+ message("214-%s", p);
+ noinfo = FALSE;
+ }
+ }
+
+ if (noinfo)
+ message("504 HELP topic \"%.10s\" unknown", topic);
+ else
+ message("214 End of HELP info");
+ (void) fclose(hf);
+}
diff --git a/usr.sbin/sendmail/src/stab.c b/usr.sbin/sendmail/src/stab.c
new file mode 100644
index 000000000000..cfb02c69686b
--- /dev/null
+++ b/usr.sbin/sendmail/src/stab.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)stab.c 8.6 (Berkeley) 8/31/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** STAB -- manage the symbol table
+**
+** Parameters:
+** name -- the name to be looked up or inserted.
+** type -- the type of symbol.
+** op -- what to do:
+** ST_ENTER -- enter the name if not
+** already present.
+** ST_FIND -- find it only.
+**
+** Returns:
+** pointer to a STAB entry for this name.
+** NULL if not found and not entered.
+**
+** Side Effects:
+** can update the symbol table.
+*/
+
+# define STABSIZE 2003
+
+static STAB *SymTab[STABSIZE];
+
+STAB *
+stab(name, type, op)
+ char *name;
+ int type;
+ int op;
+{
+ register STAB *s;
+ register STAB **ps;
+ register int hfunc;
+ register char *p;
+ extern char lower();
+
+ if (tTd(36, 5))
+ printf("STAB: %s %d ", name, type);
+
+ /*
+ ** Compute the hashing function
+ */
+
+ hfunc = type;
+ for (p = name; *p != '\0'; p++)
+ hfunc = ((hfunc << 1) ^ (lower(*p) & 0377)) % STABSIZE;
+
+ if (tTd(36, 9))
+ printf("(hfunc=%d) ", hfunc);
+
+ ps = &SymTab[hfunc];
+ if (type == ST_MACRO || type == ST_RULESET)
+ {
+ while ((s = *ps) != NULL &&
+ (s->s_type != type || strcmp(name, s->s_name)))
+ ps = &s->s_next;
+ }
+ else
+ {
+ while ((s = *ps) != NULL &&
+ (s->s_type != type || strcasecmp(name, s->s_name)))
+ ps = &s->s_next;
+ }
+
+ /*
+ ** Dispose of the entry.
+ */
+
+ if (s != NULL || op == ST_FIND)
+ {
+ if (tTd(36, 5))
+ {
+ if (s == NULL)
+ printf("not found\n");
+ else
+ {
+ long *lp = (long *) s->s_class;
+
+ printf("type %d val %lx %lx %lx %lx\n",
+ s->s_type, lp[0], lp[1], lp[2], lp[3]);
+ }
+ }
+ return (s);
+ }
+
+ /*
+ ** Make a new entry and link it in.
+ */
+
+ if (tTd(36, 5))
+ printf("entered\n");
+
+ /* make new entry */
+ s = (STAB *) xalloc(sizeof *s);
+ bzero((char *) s, sizeof *s);
+ s->s_name = newstr(name);
+ s->s_type = type;
+
+ /* link it in */
+ *ps = s;
+
+ return (s);
+}
+ /*
+** 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(36, 90))
+ printf("stabapply: trying %d/%s\n",
+ s->s_type, s->s_name);
+ func(s, arg);
+ }
+ }
+}
diff --git a/usr.sbin/sendmail/src/stats.c b/usr.sbin/sendmail/src/stats.c
new file mode 100644
index 000000000000..f59885a60674
--- /dev/null
+++ b/usr.sbin/sendmail/src/stats.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)stats.c 8.5 (Berkeley) 5/28/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+# include "mailstats.h"
+
+struct statistics Stat;
+
+bool GotStats = FALSE; /* set when we have stats to merge */
+
+#define ONE_K 1000 /* one thousand (twenty-four?) */
+#define KBYTES(x) (((x) + (ONE_K - 1)) / ONE_K)
+ /*
+** MARKSTATS -- mark statistics
+*/
+
+void
+markstats(e, to)
+ register ENVELOPE *e;
+ register ADDRESS *to;
+{
+ if (to == NULL)
+ {
+ if (e->e_from.q_mailer != NULL)
+ {
+ Stat.stat_nf[e->e_from.q_mailer->m_mno]++;
+ Stat.stat_bf[e->e_from.q_mailer->m_mno] +=
+ KBYTES(e->e_msgsize);
+ }
+ }
+ else
+ {
+ Stat.stat_nt[to->q_mailer->m_mno]++;
+ Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize);
+ }
+ GotStats = TRUE;
+}
+ /*
+** POSTSTATS -- post statistics in the statistics file
+**
+** Parameters:
+** sfile -- the name of the statistics file.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** merges the Stat structure with the sfile file.
+*/
+
+void
+poststats(sfile)
+ char *sfile;
+{
+ register int fd;
+ struct statistics stat;
+ extern off_t lseek();
+
+ if (sfile == NULL || !GotStats)
+ return;
+
+ (void) time(&Stat.stat_itime);
+ Stat.stat_size = sizeof Stat;
+
+ fd = open(sfile, O_RDWR);
+ if (fd < 0)
+ {
+ errno = 0;
+ return;
+ }
+ (void) lockfile(fd, sfile, NULL, LOCK_EX);
+ if (read(fd, (char *) &stat, sizeof stat) == sizeof stat &&
+ stat.stat_size == sizeof stat)
+ {
+ /* merge current statistics into statfile */
+ register int i;
+
+ for (i = 0; i < MAXMAILERS; i++)
+ {
+ stat.stat_nf[i] += Stat.stat_nf[i];
+ stat.stat_bf[i] += Stat.stat_bf[i];
+ stat.stat_nt[i] += Stat.stat_nt[i];
+ stat.stat_bt[i] += Stat.stat_bt[i];
+ }
+ }
+ else
+ bcopy((char *) &Stat, (char *) &stat, sizeof stat);
+
+ /* write out results */
+ (void) lseek(fd, (off_t) 0, 0);
+ (void) write(fd, (char *) &stat, sizeof stat);
+ (void) close(fd);
+
+ /* clear the structure to avoid future disappointment */
+ bzero(&Stat, sizeof stat);
+ GotStats = FALSE;
+}
diff --git a/usr.sbin/sendmail/src/sysexits.c b/usr.sbin/sendmail/src/sysexits.c
new file mode 100644
index 000000000000..ad4f1e1cffb8
--- /dev/null
+++ b/usr.sbin/sendmail/src/sysexits.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)sysexits.c 8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+
+#include <sendmail.h>
+
+/*
+** 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.
+*/
+
+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]);
+ /*
+** DSNTOEXITSTAT -- convert DSN-style error code to EX_ style.
+**
+** Parameters:
+** dsncode -- the text of the DSN-style code.
+**
+** Returns:
+** The corresponding exit status.
+*/
+
+int
+dsntoexitstat(dsncode)
+ char *dsncode;
+{
+ int code2, code3;
+
+ /* first the easy cases.... */
+ if (*dsncode == '2')
+ return EX_OK;
+ if (*dsncode == '4')
+ return EX_TEMPFAIL;
+
+ /* now decode the other two field parts */
+ if (*++dsncode == '.')
+ dsncode++;
+ code2 = atoi(dsncode);
+ while (*dsncode != '\0' && *dsncode != '.')
+ dsncode++;
+ if (*dsncode != '\0')
+ dsncode++;
+ code3 = atoi(dsncode);
+
+ /* and do a nested switch to work them out */
+ switch (code2)
+ {
+ case 0: /* Other or Undefined status */
+ return EX_UNAVAILABLE;
+
+ case 1: /* Address Status */
+ switch (code3)
+ {
+ case 0: /* Other Address Status */
+ return EX_DATAERR;
+
+ case 1: /* Bad destination mailbox address */
+ case 6: /* Mailbox has moved, No forwarding address */
+ return EX_NOUSER;
+
+ case 2: /* Bad destination system address */
+ case 8: /* Bad senders system address */
+ return EX_NOHOST;
+
+ case 3: /* Bad destination mailbox address syntax */
+ case 7: /* Bad senders mailbox address syntax */
+ return EX_USAGE;
+
+ case 4: /* Destination mailbox address ambiguous */
+ return EX_UNAVAILABLE;
+
+ case 5: /* Destination address valid */
+ return EX_OK;
+ }
+ break;
+
+ case 2: /* Mailbox Status */
+ switch (code3)
+ {
+ case 0: /* Other or Undefined mailbox status */
+ case 1: /* Mailbox disabled, not acccepting messages */
+ case 2: /* Mailbox full */
+ case 4: /* Mailing list expansion problem */
+ return EX_UNAVAILABLE;
+
+ case 3: /* Message length exceeds administrative lim */
+ return EX_DATAERR;
+ }
+ break;
+
+ case 3: /* System Status */
+ return EX_OSERR;
+
+ case 4: /* Network and Routing Status */
+ switch (code3)
+ {
+ case 0: /* Other or undefined network or routing stat */
+ return EX_IOERR;
+
+ case 1: /* No answer from host */
+ case 3: /* Routing server failure */
+ case 5: /* Network congestion */
+ return EX_TEMPFAIL;
+
+ case 2: /* Bad connection */
+ return EX_IOERR;
+
+ case 4: /* Unable to route */
+ return EX_PROTOCOL;
+
+ case 6: /* Routing loop detected */
+ return EX_CONFIG;
+
+ case 7: /* Delivery time expired */
+ return EX_UNAVAILABLE;
+ }
+ break;
+
+ case 5: /* Protocol Status */
+ return EX_PROTOCOL;
+
+ case 6: /* Message Content or Media Status */
+ return EX_UNAVAILABLE;
+
+ case 7: /* Security Status */
+ return EX_DATAERR;
+ }
+ return EX_CONFIG;
+}
diff --git a/usr.sbin/sendmail/src/sysexits.h b/usr.sbin/sendmail/src/sysexits.h
new file mode 100644
index 000000000000..464cb11bab2d
--- /dev/null
+++ b/usr.sbin/sendmail/src/sysexits.h
@@ -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_ */
diff --git a/usr.sbin/sendmail/src/trace.c b/usr.sbin/sendmail/src/trace.c
new file mode 100644
index 000000000000..9762cab18f59
--- /dev/null
+++ b/usr.sbin/sendmail/src/trace.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)trace.c 8.4 (Berkeley) 5/28/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+
+/*
+** TtSETUP -- set up for trace package.
+**
+** Parameters:
+** vect -- pointer to trace vector.
+** size -- number of flags in trace vector.
+** defflags -- flags to set if no value given.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** environment is set up.
+*/
+
+u_char *tTvect;
+int tTsize;
+static char *DefFlags;
+
+void
+tTsetup(vect, size, defflags)
+ u_char *vect;
+ int size;
+ char *defflags;
+{
+ tTvect = vect;
+ tTsize = size;
+ DefFlags = defflags;
+}
+ /*
+** TtFLAG -- process an external trace flag description.
+**
+** Parameters:
+** s -- the trace flag.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** sets/clears trace flags.
+*/
+
+void
+tTflag(s)
+ register char *s;
+{
+ unsigned int first, last;
+ register unsigned int i;
+
+ if (*s == '\0')
+ s = DefFlags;
+
+ for (;;)
+ {
+ /* find first flag to set */
+ i = 0;
+ while (isdigit(*s))
+ i = i * 10 + (*s++ - '0');
+ first = i;
+
+ /* find last flag to set */
+ if (*s == '-')
+ {
+ i = 0;
+ while (isdigit(*++s))
+ i = i * 10 + (*s - '0');
+ }
+ last = i;
+
+ /* find the level to set it to */
+ i = 1;
+ if (*s == '.')
+ {
+ i = 0;
+ while (isdigit(*++s))
+ i = i * 10 + (*s - '0');
+ }
+
+ /* clean up args */
+ if (first >= tTsize)
+ first = tTsize - 1;
+ if (last >= tTsize)
+ last = tTsize - 1;
+
+ /* set the flags */
+ while (first <= last)
+ tTvect[first++] = i;
+
+ /* more arguments? */
+ if (*s++ == '\0')
+ return;
+ }
+}
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
new file mode 100644
index 000000000000..d2b60fc19196
--- /dev/null
+++ b/usr.sbin/sendmail/src/udb.c
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (c) 1983, 1995 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
+#if USERDB
+static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (with USERDB)";
+#else
+static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (without USERDB)";
+#endif
+#endif
+
+#if USERDB
+
+#include <errno.h>
+
+#ifdef NEWDB
+# include <db.h>
+#else
+# define DBT struct _data_base_thang_
+DBT
+{
+ void *data; /* pointer to data */
+ size_t size; /* length of data */
+};
+#endif
+
+#ifdef HESIOD
+# include <hesiod.h>
+#endif /* HESIOD */
+
+/*
+** 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
+
+#ifdef NEWDB
+ /* 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
+#endif
+ } 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 UDB_HESIOD 5 /* look up via hesiod */
+
+#define MAXUDBENT 10 /* maximum number of UDB entries */
+
+
+struct option
+{
+ char *name;
+ char *val;
+};
+ /*
+** UDBEXPAND -- look up user in database and expand
+**
+** Parameters:
+** a -- address to expand.
+** sendq -- pointer to head of sendq to put the expansions in.
+** aliaslevel -- the current alias nesting depth.
+** e -- the current envelope.
+**
+** 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, aliaslevel, e)
+ register ADDRESS *a;
+ ADDRESS **sendq;
+ int aliaslevel;
+ register ENVELOPE *e;
+{
+ int i;
+ 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;
+
+ /* short circuit name begins with '\\' since it can't possibly match */
+ if (a->q_user[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)
+ {
+#ifdef NEWDB
+ case UDB_DBFETCH:
+ key.data = keybuf;
+ key.size = keylen;
+ if (tTd(28, 80))
+ printf("udbexpand: trying %s (%d) via db\n",
+ keybuf, keylen);
+ 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 (%d)\n",
+ keybuf, keylen);
+ 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;
+ 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 %.100s => %s",
+ e->e_id, e->e_to,
+ shortenstring(user, 203));
+#endif
+ naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e);
+
+ 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';
+
+ /* announce delivery; NORECEIPT bit set later */
+ if (e->e_xfp != NULL)
+ {
+ fprintf(e->e_xfp,
+ "Message delivered to mailing list %s\n",
+ a->q_paddr);
+ }
+ e->e_flags |= EF_SENDRECEIPT;
+ a->q_flags |= QDELIVERED|QEXPANDED;
+ break;
+#endif
+
+#ifdef HESIOD
+ case UDB_HESIOD:
+ key.data = keybuf;
+ key.size = keylen;
+ if (tTd(28, 80))
+ printf("udbexpand: trying %s (%d) via hesiod\n",
+ keybuf, keylen);
+ /* look up the key via hesiod */
+ i = hes_udb_get(&key, &info);
+ if (i < 0)
+ {
+ syserr("udbexpand: hesiod-get %.*s stat %d",
+ key.size, key.data, i);
+ return EX_TEMPFAIL;
+ }
+ else if (i > 0 || info.size <= 0)
+ {
+#if HES_GETMAILHOST
+ struct hes_postoffice *hp;
+#endif
+
+ if (tTd(28, 2))
+ printf("udbexpand: no match on %s (%d)\n",
+ keybuf, keylen);
+#if HES_GETMAILHOST
+ if (tTd(28, 8))
+ printf(" ... trying hes_getmailhost(%s)\n",
+ a->q_user);
+ hp = hes_getmailhost(a->q_user);
+ if (hp == NULL)
+ {
+ if (hes_error() == HES_ER_NET)
+ {
+ syserr("udbexpand: hesiod-getmail %s stat %d",
+ a->q_user, hes_error());
+ return EX_TEMPFAIL;
+ }
+ if (tTd(28, 2))
+ printf("hes_getmailhost(%s): %d\n",
+ a->q_user, hes_error();
+ continue;
+ }
+ sprintf(info.data, "%s@%s",
+ hp->po_name, hp->po_host);
+ info.size = strlen(info.data);
+#else
+ continue;
+#endif
+ }
+ if (tTd(28, 80))
+ printf("udbexpand: match %.*s: %.*s\n",
+ key.size, key.data, info.size, info.data);
+ a->q_flags &= ~QSELFREF;
+
+ if (bitset(EF_VRFYONLY, e->e_flags))
+ {
+ a->q_flags |= QVERIFIED;
+ 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("hesioded to %s", user);
+#ifdef LOG
+ if (LogLevel >= 10)
+ syslog(LOG_INFO, "%s: hesiod %.100s => %s",
+ e->e_id, e->e_to,
+ shortenstring(user, 203));
+#endif
+ naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
+
+ if (user != buf)
+ free(user);
+
+ if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
+ {
+ if (tTd(28, 5))
+ {
+ printf("udbexpand: QDONTSEND ");
+ printaddr(a, FALSE);
+ }
+ a->q_flags |= QDONTSEND;
+ }
+
+ /*
+ ** 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 = hes_udb_get(&key, &info);
+ 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;
+#endif /* HESIOD */
+
+ 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;
+ naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
+ 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;
+}
+ /*
+** 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;
+{
+ extern char *udbmatch();
+
+ return udbmatch(sender, "mailname");
+}
+
+
+char *
+udbmatch(user, field)
+ char *user;
+ char *field;
+{
+ register char *p;
+ register struct udbent *up;
+ int i;
+ int keylen;
+ DBT key, info;
+ char keybuf[MAXKEY];
+
+ if (tTd(28, 1))
+ printf("udbmatch(%s, %s)\n", user, field);
+
+ if (!UdbInitialized)
+ {
+ if (_udbx_init() == EX_TEMPFAIL)
+ return NULL;
+ }
+
+ /* short circuit if no spec */
+ if (UdbSpec == NULL || UdbSpec[0] == '\0')
+ return NULL;
+
+ /* short circuit name begins with '\\' since it can't possibly match */
+ if (user[0] == '\\')
+ return NULL;
+
+ /* long names can never match and are a pain to deal with */
+ if ((strlen(user) + strlen(field)) > sizeof keybuf - 4)
+ return NULL;
+
+ /* names beginning with colons indicate metadata */
+ if (user[0] == ':')
+ return NULL;
+
+ /* build database key */
+ (void) strcpy(keybuf, user);
+ (void) strcat(keybuf, ":");
+ (void) strcat(keybuf, field);
+ keylen = strlen(keybuf);
+
+ for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+ {
+ /*
+ ** Select action based on entry type.
+ */
+
+ switch (up->udb_type)
+ {
+#ifdef NEWDB
+ 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("udbmatch: no match on %s (%d) via db\n",
+ keybuf, keylen);
+ continue;
+ }
+
+ p = xalloc(info.size + 1);
+ bcopy(info.data, p, info.size);
+ p[info.size] = '\0';
+ if (tTd(28, 1))
+ printf("udbmatch ==> %s\n", p);
+ return p;
+ break;
+#endif
+
+#ifdef HESIOD
+ case UDB_HESIOD:
+ key.data = keybuf;
+ key.size = keylen;
+ i = hes_udb_get(&key, &info);
+ if (i != 0 || info.size <= 0)
+ {
+ if (tTd(28, 2))
+ printf("udbmatch: no match on %s (%d) via hesiod\n",
+ keybuf, keylen);
+ continue;
+ }
+
+ p = xalloc(info.size + 1);
+ bcopy(info.data, p, info.size);
+ p[info.size] = '\0';
+ if (tTd(28, 1))
+ printf("udbmatch ==> %s\n", p);
+ return p;
+#endif /* HESIOD */
+ }
+ }
+
+ if (strcmp(field, "mailname") != 0)
+ return NULL;
+
+ /*
+ ** 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, user);
+ (void) strcat(keybuf, ":maildrop");
+ keylen = strlen(keybuf);
+
+ for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+ {
+ switch (up->udb_type)
+ {
+#ifdef NEWDB
+ 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(user) + strlen(up->udb_default) + 2);
+ (void) strcpy(p, user);
+ (void) strcat(p, "@");
+ (void) strcat(p, up->udb_default);
+ if (tTd(28, 1))
+ printf("udbmatch ==> %s\n", p);
+ return p;
+ break;
+#endif
+
+#ifdef HESIOD
+ case UDB_HESIOD:
+ /* get the default case for this database */
+ if (up->udb_default == NULL)
+ {
+ key.data = ":default:mailname";
+ key.size = strlen(key.data);
+ i = hes_udb_get(&key, &info);
+
+ 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 = hes_udb_get(&key, &info);
+ if (i != 0 || info.size <= 0)
+ {
+ /* nope -- no aliasing for this user */
+ continue;
+ }
+
+ /* they exist -- build the actual address */
+ p = xalloc(strlen(user) + strlen(up->udb_default) + 2);
+ (void) strcpy(p, user);
+ (void) strcat(p, "@");
+ (void) strcat(p, up->udb_default);
+ if (tTd(28, 1))
+ printf("udbmatch ==> %s\n", p);
+ return p;
+ break;
+#endif /* HESIOD */
+ }
+ }
+
+ /* still nothing.... too bad */
+ return NULL;
+}
+ /*
+** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map
+**
+** Parameters:
+** map -- the map being queried.
+** name -- the name to look up.
+** av -- arguments to the map lookup.
+** statp -- to get any error status.
+**
+** Returns:
+** NULL if name not found in map.
+** The rewritten name otherwise.
+*/
+
+char *
+udb_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ char *val;
+ char *key;
+ char keybuf[MAXNAME + 1];
+
+ if (tTd(28, 20) || tTd(38, 20))
+ printf("udb_map_lookup(%s, %s)\n", map->map_mname, name);
+
+ if (bitset(MF_NOFOLDCASE, map->map_mflags))
+ {
+ key = name;
+ }
+ else
+ {
+ int keysize = strlen(name);
+
+ if (keysize > sizeof keybuf - 1)
+ keysize = sizeof keybuf - 1;
+ bcopy(name, keybuf, keysize);
+ keybuf[keysize] = '\0';
+ makelower(keybuf);
+ key = keybuf;
+ }
+ val = udbmatch(key, map->map_file);
+ if (val == NULL)
+ return NULL;
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ return map_rewrite(map, name, strlen(name), NULL);
+ else
+ return map_rewrite(map, val, strlen(val), av);
+}
+ /*
+** _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;
+ register struct udbent *up;
+
+ 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;
+ int nopts;
+# if 0
+ auto int rcode;
+ int nmx;
+ int i;
+ register struct hostent *h;
+ char *mxhosts[MAXMXHOSTS + 1];
+# endif
+ 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.
+ ** Hesiod -- search the named database with BIND
+ ** using the MIT Hesiod package.
+ */
+
+ switch (*spec)
+ {
+#if 0
+ case '+': /* search remote database */
+ case '*': /* search remote database (expand MX) */
+ if (*spec == '*')
+ {
+#if 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 = sm_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,
+ INADDRSZ);
+ 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;
+#endif
+
+ case '@': /* forward to remote host */
+ up->udb_type = UDB_FORWARD;
+ up->udb_fwdhost = spec + 1;
+ up++;
+ break;
+
+#ifdef HESIOD
+ case 'h': /* use hesiod */
+ case 'H':
+ if (strcasecmp(spec, "hesiod") != 0)
+ goto badspec;
+ up->udb_type = UDB_HESIOD;
+ up++;
+ break;
+#endif /* HESIOD */
+
+#ifdef NEWDB
+ 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 (tTd(28, 1))
+ {
+ int saveerrno = errno;
+
+ printf("dbopen(%s): %s",
+ spec, errstring(errno));
+ errno = saveerrno;
+ }
+ 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;
+#endif
+
+ default:
+badspec:
+ syserr("Unknown UDB spec %s", spec);
+ break;
+ }
+ }
+ up->udb_type = UDB_EOLIST;
+
+ if (tTd(28, 4))
+ {
+ for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+ {
+ switch (up->udb_type)
+ {
+#ifdef DAEMON
+ case UDB_REMOTE:
+ printf("REMOTE: addr %s, timeo %d\n",
+ anynet_ntoa((SOCKADDR *) &up->udb_addr),
+ up->udb_timeout);
+ break;
+#endif
+
+ case UDB_DBFETCH:
+#ifdef NEWDB
+ printf("FETCH: file %s\n",
+ up->udb_dbname);
+#else
+ printf("FETCH\n");
+#endif
+ break;
+
+ case UDB_FORWARD:
+ printf("FORWARD: host %s\n",
+ up->udb_fwdhost);
+ break;
+
+ case UDB_HESIOD:
+ printf("HESIOD\n");
+ break;
+
+ default:
+ printf("UNKNOWN\n");
+ break;
+ }
+ }
+ }
+
+ UdbInitialized = TRUE;
+ errno = 0;
+ return EX_OK;
+
+ /*
+ ** On temporary failure, back out anything we've already done
+ */
+
+ tempfail:
+#ifdef NEWDB
+ for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
+ {
+ if (up->udb_type == UDB_DBFETCH)
+ {
+ (*up->udb_dbp->close)(up->udb_dbp);
+ }
+ }
+#endif
+ 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;
+}
+
+#ifdef HESIOD
+
+int
+hes_udb_get(key, info)
+ DBT *key;
+ DBT *info;
+{
+ char *name, *type;
+ char *p, **hp;
+ char kbuf[MAXKEY + 1];
+
+ strcpy(kbuf, key->data);
+ name = kbuf;
+ type = strrchr(name, ':');
+ if (type == NULL)
+ return 1;
+ *type++ = '\0';
+ if (strchr(name, '@') != NULL)
+ return 1;
+
+ if (tTd(28, 1))
+ printf("hes_udb_get(%s, %s)\n", name, type);
+
+ /* make the hesiod query */
+ hp = hes_resolve(name, type);
+ *--type = ':';
+ if (hp == NULL || hp[0] == NULL)
+ {
+ /* network problem or timeout */
+ if (hes_error() == HES_ER_NET)
+ return -1;
+
+ return 1;
+ }
+ else
+ {
+ /*
+ ** If there are multiple matches, just return the
+ ** first one.
+ **
+ ** XXX These should really be returned; for example,
+ ** XXX it is legal for :maildrop to be multi-valued.
+ */
+
+ info->data = hp[0];
+ info->size = (size_t) strlen(info->data);
+ }
+
+ if (tTd(28, 80))
+ printf("hes_udb_get => %s\n", *hp);
+
+ return 0;
+}
+#endif /* HESIOD */
+
+#else /* not USERDB */
+
+int
+udbexpand(a, sendq, aliaslevel, e)
+ ADDRESS *a;
+ ADDRESS **sendq;
+ int aliaslevel;
+ ENVELOPE *e;
+{
+ return EX_OK;
+}
+
+#endif /* USERDB */
diff --git a/usr.sbin/sendmail/src/useful.h b/usr.sbin/sendmail/src/useful.h
new file mode 100644
index 000000000000..8f9009ecf0b0
--- /dev/null
+++ b/usr.sbin/sendmail/src/useful.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1995 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.
+ *
+ * @(#)useful.h 8.4 (Berkeley) 4/21/95
+ */
+
+# include <sys/types.h>
+
+/* support for bool type */
+typedef int bool;
+# define TRUE 1
+# define FALSE 0
+
+# ifndef NULL
+# define NULL 0
+# endif /* NULL */
+
+/* bit hacking */
+# define bitset(bit, word) (((word) & (bit)) != 0)
+
+/* some simple functions */
+# ifndef max
+# define max(a, b) ((a) > (b) ? (a) : (b))
+# define min(a, b) ((a) < (b) ? (a) : (b))
+# endif
+
+/* assertions */
+# ifndef NASSERT
+# define ASSERT(expr, msg, parm)\
+ if (!(expr))\
+ {\
+ fprintf(stderr, "assertion botch: %s:%d: ", __FILE__, __LINE__);\
+ fprintf(stderr, msg, parm);\
+ }
+# else /* NASSERT */
+# define ASSERT(expr, msg, parm)
+# endif /* NASSERT */
+
+/* sccs id's */
+# ifndef lint
+# ifdef __STDC__
+# define SCCSID(arg) static char SccsId[] = #arg;
+# else
+# define SCCSID(arg) static char SccsId[] = "arg";
+# endif
+# else
+# define SCCSID(arg)
+# endif
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
new file mode 100644
index 000000000000..d33bd5ed3d81
--- /dev/null
+++ b/usr.sbin/sendmail/src/usersmtp.c
@@ -0,0 +1,1055 @@
+/*
+ * Copyright (c) 1983, 1995 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 SMTP
+static char sccsid[] = "@(#)usersmtp.c 8.65 (Berkeley) 9/28/95 (with SMTP)";
+#else
+static char sccsid[] = "@(#)usersmtp.c 8.65 (Berkeley) 9/28/95 (without SMTP)";
+#endif
+#endif /* not lint */
+
+# include <sysexits.h>
+# include <errno.h>
+
+# ifdef SMTP
+
+/*
+** USERSMTP -- run SMTP protocol from the user end.
+**
+** This protocol is described in RFC821.
+*/
+
+#define REPLYTYPE(r) ((r) / 100) /* first digit of reply code */
+#define REPLYCLASS(r) (((r) / 10) % 10) /* second digit of reply code */
+#define SMTPCLOSING 421 /* "Service Shutting Down" */
+
+char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */
+char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */
+char SmtpError[MAXLINE] = ""; /* save failure error messages */
+int SmtpPid; /* pid of mailer */
+bool SmtpNeedIntro; /* need "while talking" in transcript */
+
+extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
+ /*
+** SMTPINIT -- initialize SMTP.
+**
+** Opens the connection and sends the initial protocol.
+**
+** Parameters:
+** m -- mailer to create connection to.
+** pvp -- pointer to parameter vector to pass to
+** the mailer.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** creates connection and sends initial protocol.
+*/
+
+void
+smtpinit(m, mci, e)
+ struct mailer *m;
+ register MCI *mci;
+ ENVELOPE *e;
+{
+ register int r;
+ register char *p;
+ extern void esmtp_check();
+ extern void helo_options();
+
+ if (tTd(18, 1))
+ {
+ printf("smtpinit ");
+ mci_dump(mci, FALSE);
+ }
+
+ /*
+ ** Open the connection to the mailer.
+ */
+
+ SmtpError[0] = '\0';
+ CurHostName = mci->mci_host; /* XXX UGLY XXX */
+ if (CurHostName == NULL)
+ CurHostName = MyHostName;
+ SmtpNeedIntro = TRUE;
+ switch (mci->mci_state)
+ {
+ case MCIS_ACTIVE:
+ /* need to clear old information */
+ smtprset(m, mci, e);
+ /* fall through */
+
+ 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;
+ }
+
+ mci->mci_state = MCIS_OPENING;
+
+ /*
+ ** Get the greeting message.
+ ** This should appear spontaneously. Give it five minutes to
+ ** happen.
+ */
+
+ 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) == 4)
+ goto tempfail1;
+ if (REPLYTYPE(r) != 2)
+ goto unavailable;
+
+ /*
+ ** Send the HELO command.
+ ** My mother taught me to always introduce myself.
+ */
+
+ 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)
+ goto tempfail1;
+ 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;
+ }
+ else if (REPLYTYPE(r) != 2)
+ 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 (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
+ strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
+ {
+ syserr("553 %s config error: mail loops back to me (MX problem?)",
+ mci->mci_host);
+ 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
+ ** commands.
+ */
+
+ if (bitnset(M_INTERNAL, m->m_flags))
+ {
+ /* tell it to be verbose */
+ smtpmessage("VERB", m, mci);
+ r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
+ if (r < 0)
+ goto tempfail2;
+ }
+
+ if (mci->mci_state != MCIS_CLOSED)
+ {
+ mci->mci_state = MCIS_OPEN;
+ return;
+ }
+
+ /* got a 421 error code during startup */
+
+ 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;
+}
+ /*
+** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol
+**
+** Parameters:
+** line -- the response line.
+** firstline -- set if this is the first line of the reply.
+** m -- the mailer.
+** mci -- the mailer connection info.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+esmtp_check(line, firstline, m, mci, e)
+ char *line;
+ bool firstline;
+ MAILER *m;
+ register MCI *mci;
+ ENVELOPE *e;
+{
+ if (strstr(line, "ESMTP") != NULL)
+ mci->mci_flags |= MCIF_ESMTP;
+ if (strstr(line, "8BIT-OK") != NULL)
+ mci->mci_flags |= MCIF_8BITOK;
+}
+ /*
+** HELO_OPTIONS -- process the options on a HELO line.
+**
+** Parameters:
+** line -- the response line.
+** firstline -- set if this is the first line of the reply.
+** m -- the mailer.
+** mci -- the mailer connection info.
+** e -- the envelope.
+**
+** Returns:
+** none.
+*/
+
+void
+helo_options(line, firstline, m, mci, e)
+ char *line;
+ bool firstline;
+ MAILER *m;
+ register MCI *mci;
+ ENVELOPE *e;
+{
+ register char *p;
+
+ if (firstline)
+ return;
+
+ if (strlen(line) < (SIZE_T) 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;
+ mci->mci_flags &= ~MCIF_7BIT;
+ }
+ else if (strcasecmp(line, "expn") == 0)
+ mci->mci_flags |= MCIF_EXPN;
+ else if (strcasecmp(line, "dsn") == 0)
+ mci->mci_flags |= MCIF_DSN;
+}
+ /*
+** SMTPMAILFROM -- send MAIL command
+**
+** Parameters:
+** m -- the mailer.
+** mci -- the mailer connection structure.
+** e -- the envelope (including the sender to specify).
+*/
+
+int
+smtpmailfrom(m, mci, e)
+ struct mailer *m;
+ MCI *mci;
+ ENVELOPE *e;
+{
+ int r;
+ char *bufp;
+ char *bodytype;
+ char buf[MAXNAME + 1];
+ char optbuf[MAXLINE];
+
+ if (tTd(18, 2))
+ printf("smtpmailfrom: CurHost=%s\n", CurHostName);
+
+ /* set up appropriate options to include */
+ if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
+ sprintf(optbuf, " SIZE=%ld", e->e_msgsize);
+ else
+ strcpy(optbuf, "");
+
+ bodytype = e->e_bodytype;
+ if (bitset(MCIF_8BITMIME, mci->mci_flags))
+ {
+ if (bodytype == NULL &&
+ bitset(MM_MIME8BIT, MimeMode) &&
+ bitset(EF_HAS8BIT, e->e_flags) &&
+ !bitset(EF_DONT_MIME, e->e_flags) &&
+ !bitnset(M_8BITS, m->m_flags))
+ bodytype = "8BITMIME";
+ if (bodytype != NULL)
+ {
+ strcat(optbuf, " BODY=");
+ strcat(optbuf, bodytype);
+ }
+ }
+ else if (bitnset(M_8BITS, m->m_flags) ||
+ !bitset(EF_HAS8BIT, e->e_flags) ||
+ bitset(MCIF_8BITOK, mci->mci_flags))
+ {
+ /* just pass it through */
+ }
+#if MIME8TO7
+ else if (bitset(MM_CVTMIME, MimeMode) &&
+ !bitset(EF_DONT_MIME, e->e_flags) &&
+ (!bitset(MM_PASS8BIT, MimeMode) ||
+ bitset(EF_IS_MIME, e->e_flags)))
+ {
+ /* must convert from 8bit MIME format to 7bit encoded */
+ mci->mci_flags |= MCIF_CVT8TO7;
+ }
+#endif
+ else if (!bitset(MM_PASS8BIT, MimeMode))
+ {
+ /* cannot just send a 8-bit version */
+ usrerr("%s does not support 8BITMIME", mci->mci_host);
+ mci->mci_status = "5.6.3";
+ return EX_DATAERR;
+ }
+
+ if (bitset(MCIF_DSN, mci->mci_flags))
+ {
+ if (e->e_envid != NULL)
+ {
+ strcat(optbuf, " ENVID=");
+ strcat(optbuf, e->e_envid);
+ }
+
+ /* RET= parameter */
+ if (bitset(EF_RET_PARAM, e->e_flags))
+ {
+ strcat(optbuf, " RET=");
+ if (bitset(EF_NO_BODY_RETN, e->e_flags))
+ strcat(optbuf, "HDRS");
+ else
+ strcat(optbuf, "FULL");
+ }
+ }
+
+ /*
+ ** Send the MAIL command.
+ ** Designates the sender.
+ */
+
+ 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, sizeof buf, e);
+ if (buf[0] == '<')
+ {
+ /* strip off <angle brackets> (put back on below) */
+ bufp = &buf[strlen(buf) - 1];
+ if (*bufp == '>')
+ *bufp = '\0';
+ bufp = &buf[1];
+ }
+ else
+ bufp = buf;
+ if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) ||
+ !bitnset(M_FROMPATH, m->m_flags))
+ {
+ smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
+ }
+ else
+ {
+ smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
+ *bufp == '@' ? ',' : ':', bufp, optbuf);
+ }
+ 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 || r == 421)
+ {
+ /* communications failure/service shutting down */
+ mci->mci_exitstat = EX_TEMPFAIL;
+ mci->mci_errno = errno;
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+ else if (REPLYTYPE(r) == 4)
+ {
+ return EX_TEMPFAIL;
+ }
+ else if (REPLYTYPE(r) == 2)
+ {
+ return EX_OK;
+ }
+ else if (r == 501)
+ {
+ /* syntax error in arguments */
+ mci->mci_status = "5.5.2";
+ return EX_DATAERR;
+ }
+ else if (r == 553)
+ {
+ /* mailbox name not allowed */
+ mci->mci_status = "5.1.3";
+ return EX_DATAERR;
+ }
+ else if (r == 552)
+ {
+ /* exceeded storage allocation */
+ mci->mci_status = "5.2.2";
+ return EX_UNAVAILABLE;
+ }
+ else if (REPLYTYPE(r) == 5)
+ {
+ /* unknown error */
+ return EX_UNAVAILABLE;
+ }
+
+#ifdef LOG
+ if (LogLevel > 1)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP MAIL protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+
+ /* protocol error -- close up */
+ smtpquit(m, mci, e);
+ return EX_PROTOCOL;
+}
+ /*
+** SMTPRCPT -- designate recipient.
+**
+** 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.
+**
+** Side Effects:
+** Sends the mail via SMTP.
+*/
+
+int
+smtprcpt(to, m, mci, e)
+ ADDRESS *to;
+ register MAILER *m;
+ MCI *mci;
+ ENVELOPE *e;
+{
+ register int r;
+ char optbuf[MAXLINE];
+ extern char *smtptodsn();
+
+ strcpy(optbuf, "");
+ if (bitset(MCIF_DSN, mci->mci_flags))
+ {
+ /* NOTIFY= parameter */
+ if (bitset(QHASNOTIFY, to->q_flags) &&
+ bitset(QPRIMARY, to->q_flags))
+ {
+ bool firstone = TRUE;
+
+ strcat(optbuf, " NOTIFY=");
+ if (bitset(QPINGONSUCCESS, to->q_flags))
+ {
+ strcat(optbuf, "SUCCESS");
+ firstone = FALSE;
+ }
+ if (bitset(QPINGONFAILURE, to->q_flags))
+ {
+ if (!firstone)
+ strcat(optbuf, ",");
+ strcat(optbuf, "FAILURE");
+ firstone = FALSE;
+ }
+ if (bitset(QPINGONDELAY, to->q_flags))
+ {
+ if (!firstone)
+ strcat(optbuf, ",");
+ strcat(optbuf, "DELAY");
+ firstone = FALSE;
+ }
+ if (firstone)
+ strcat(optbuf, "NEVER");
+ }
+
+ /* ORCPT= parameter */
+ if (to->q_orcpt != NULL)
+ {
+ strcat(optbuf, " ORCPT=");
+ strcat(optbuf, to->q_orcpt);
+ }
+ }
+
+ smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf);
+
+ 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);
+ to->q_rstatus = newstr(SmtpReplyBuffer);
+ to->q_status = smtptodsn(r);
+ to->q_statmta = mci->mci_host;
+ if (r < 0 || REPLYTYPE(r) == 4)
+ return EX_TEMPFAIL;
+ else if (REPLYTYPE(r) == 2)
+ return EX_OK;
+ else if (r == 550 || r == 551 || r == 553)
+ return EX_NOUSER;
+ else if (REPLYTYPE(r) == 5)
+ return EX_UNAVAILABLE;
+
+#ifdef LOG
+ if (LogLevel > 1)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP RCPT protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+
+ return EX_PROTOCOL;
+}
+ /*
+** SMTPDATA -- send the data and clean up the transaction.
+**
+** Parameters:
+** m -- mailer being sent to.
+** e -- the envelope for this message.
+**
+** Returns:
+** exit status corresponding to DATA command.
+**
+** Side Effects:
+** none.
+*/
+
+static jmp_buf CtxDataTimeout;
+static void datatimeout();
+
+int
+smtpdata(m, mci, e)
+ struct mailer *m;
+ register MCI *mci;
+ register ENVELOPE *e;
+{
+ register int r;
+ register EVENT *ev;
+ time_t timeout;
+
+ /*
+ ** Send the data.
+ ** First send the command and check that it is ok.
+ ** Then send the data.
+ ** Follow it up with a dot to terminate.
+ ** Finally get the results of the transaction.
+ */
+
+ /* send the command and check ok to proceed */
+ 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)
+ {
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+ else if (REPLYTYPE(r) == 5)
+ {
+ smtprset(m, mci, e);
+ return EX_UNAVAILABLE;
+ }
+ else if (r != 354)
+ {
+#ifdef LOG
+ if (LogLevel > 1)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-1 protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+ smtprset(m, mci, e);
+ return (EX_PROTOCOL);
+ }
+
+ /*
+ ** Set timeout around data writes. Make it at least large
+ ** enough for DNS timeouts on all recipients plus some fudge
+ ** factor. The main thing is that it should not be infinite.
+ */
+
+ if (setjmp(CtxDataTimeout) != 0)
+ {
+ mci->mci_errno = errno;
+ mci->mci_exitstat = EX_TEMPFAIL;
+ mci->mci_state = MCIS_ERROR;
+ syserr("451 timeout writing message to %s", mci->mci_host);
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+
+ timeout = e->e_msgsize / 16;
+ if (timeout < (time_t) 600)
+ timeout = (time_t) 600;
+ timeout += e->e_nrcpts * 300;
+ ev = setevent(timeout, datatimeout, 0);
+
+ /*
+ ** Output the actual message.
+ */
+
+ (*e->e_puthdr)(mci, e->e_header, e);
+ (*e->e_putbody)(mci, e, NULL);
+
+ /*
+ ** Cleanup after sending message.
+ */
+
+ clrevent(ev);
+
+ if (ferror(mci->mci_out))
+ {
+ /* error during processing -- don't send the dot */
+ mci->mci_errno = EIO;
+ mci->mci_exitstat = EX_IOERR;
+ mci->mci_state = MCIS_ERROR;
+ smtpquit(m, mci, e);
+ return EX_IOERR;
+ }
+
+ /* terminate the message */
+ fprintf(mci->mci_out, ".%s", m->m_eol);
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d >>> .\n", getpid());
+ if (Verbose)
+ nmessage(">>> .");
+
+ /* check for the results of the transaction */
+ 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 (REPLYCLASS(r) != 5)
+ /* fall through */ ;
+ else if (REPLYTYPE(r) == 2)
+ return EX_OK;
+ else if (REPLYTYPE(r) == 5)
+ return EX_UNAVAILABLE;
+#ifdef LOG
+ if (LogLevel > 1)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-2 protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+ return EX_PROTOCOL;
+}
+
+
+static void
+datatimeout()
+{
+ longjmp(CtxDataTimeout, 1);
+}
+ /*
+** SMTPQUIT -- close the SMTP connection.
+**
+** Parameters:
+** m -- a pointer to the mailer.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** sends the final protocol and closes the connection.
+*/
+
+void
+smtpquit(m, mci, e)
+ register MAILER *m;
+ register MCI *mci;
+ ENVELOPE *e;
+{
+ bool oldSuprErrs = SuprErrs;
+
+ /*
+ ** Suppress errors here -- we may be processing a different
+ ** job when we do the quit connection, and we don't want the
+ ** new job to be penalized for something that isn't it's
+ ** problem.
+ */
+
+ SuprErrs = TRUE;
+
+ /* send the quit message if we haven't gotten I/O error */
+ if (mci->mci_state != MCIS_ERROR)
+ {
+ SmtpPhase = "client QUIT";
+ smtpmessage("QUIT", m, mci);
+ (void) reply(m, mci, e, TimeOuts.to_quit, NULL);
+ SuprErrs = oldSuprErrs;
+ if (mci->mci_state == MCIS_CLOSED)
+ {
+ SuprErrs = oldSuprErrs;
+ return;
+ }
+ }
+
+ /* now actually close the connection and pick up the zombie */
+ (void) endmailer(mci, e, NULL);
+
+ SuprErrs = oldSuprErrs;
+}
+ /*
+** SMTPRSET -- send a RSET (reset) command
+*/
+
+void
+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);
+}
+ /*
+** SMTPPROBE -- check the connection state
+*/
+
+int
+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;
+}
+ /*
+** 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 called on each line of response.
+** If null, no special processing is done.
+**
+** Returns:
+** reply code it reads.
+**
+** Side Effects:
+** flushes the mail file.
+*/
+
+int
+reply(m, mci, e, timeout, pfunc)
+ MAILER *m;
+ MCI *mci;
+ ENVELOPE *e;
+ time_t timeout;
+ void (*pfunc)();
+{
+ 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");
+
+ /*
+ ** Read the input line, being careful not to hang.
+ */
+
+ for (bufp = SmtpReplyBuffer;; bufp = junkbuf)
+ {
+ register char *p;
+ extern time_t curtime();
+
+ /* actually do the read */
+ 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 (mci->mci_state == MCIS_CLOSED)
+ return (SMTPCLOSING);
+
+ if (mci->mci_out != NULL)
+ fflush(mci->mci_out);
+
+ /* get the line from the other side */
+ p = sfgets(bufp, MAXLINE, mci->mci_in, timeout, SmtpPhase);
+ mci->mci_lastuse = curtime();
+
+ if (p == NULL)
+ {
+ bool oldholderrs;
+
+ /* if the remote end closed early, fake an error */
+ if (errno == 0)
+# ifdef ECONNRESET
+ errno = ECONNRESET;
+# else /* ECONNRESET */
+ errno = EPIPE;
+# endif /* ECONNRESET */
+
+ mci->mci_errno = errno;
+ mci->mci_exitstat = EX_TEMPFAIL;
+ oldholderrs = HoldErrs;
+ HoldErrs = TRUE;
+ usrerr("451 reply: read error from %s", mci->mci_host);
+
+ /* if debugging, pause so we can see state */
+ if (tTd(18, 100))
+ pause();
+ mci->mci_state = MCIS_ERROR;
+ smtpquit(m, mci, e);
+#if XDEBUG
+ {
+ char wbuf[MAXLINE];
+ char *p = wbuf;
+
+ if (e->e_to != NULL)
+ {
+ sprintf(p, "%s... ",
+ shortenstring(e->e_to, 203));
+ p += strlen(p);
+ }
+ sprintf(p, "reply(%.100s) during %s",
+ mci->mci_host, SmtpPhase);
+ checkfd012(wbuf);
+ }
+#endif
+ HoldErrs = oldholderrs;
+ return (-1);
+ }
+ fixcrlf(bufp, TRUE);
+
+ /* EHLO failure is not a real error */
+ if (e->e_xfp != NULL && (bufp[0] == '4' ||
+ (bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
+ {
+ /* serious error -- log the previous command */
+ if (SmtpNeedIntro)
+ {
+ /* inform user who we are chatting with */
+ fprintf(CurEnv->e_xfp,
+ "... while talking to %s:\n",
+ CurHostName);
+ SmtpNeedIntro = FALSE;
+ }
+ if (SmtpMsgBuffer[0] != '\0')
+ fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
+ SmtpMsgBuffer[0] = '\0';
+
+ /* now log the message as from the other side */
+ fprintf(e->e_xfp, "<<< %s\n", bufp);
+ }
+
+ /* display the input for verbose mode */
+ if (Verbose)
+ nmessage("050 %s", bufp);
+
+ /* process the line */
+ if (pfunc != NULL)
+ (*pfunc)(bufp, firstline, m, mci, e);
+
+ firstline = FALSE;
+
+ /* if continuation is required, we can go on */
+ if (bufp[3] == '-')
+ continue;
+
+ /* ignore improperly formated input */
+ if (!(isascii(bufp[0]) && isdigit(bufp[0])))
+ continue;
+
+ /* decode the reply code */
+ r = atoi(bufp);
+
+ /* extra semantics: 0xx codes are "informational" */
+ if (r >= 100)
+ break;
+ }
+
+ /*
+ ** 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);
+
+ /* 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);
+}
+ /*
+** SMTPMESSAGE -- send message to server
+**
+** Parameters:
+** f -- format
+** m -- the mailer to control formatting.
+** a, b, c -- parameters
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** writes message to mci->mci_out.
+*/
+
+/*VARARGS1*/
+void
+#ifdef __STDC__
+smtpmessage(char *f, MAILER *m, MCI *mci, ...)
+#else
+smtpmessage(f, m, mci, va_alist)
+ char *f;
+ MAILER *m;
+ MCI *mci;
+ va_dcl
+#endif
+{
+ VA_LOCAL_DECL
+
+ VA_START(mci);
+ (void) vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap);
+ VA_END;
+
+ if (tTd(18, 1) || Verbose)
+ nmessage(">>> %s", SmtpMsgBuffer);
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(), 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 */
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c
new file mode 100644
index 000000000000..0685bf49c0f3
--- /dev/null
+++ b/usr.sbin/sendmail/src/util.c
@@ -0,0 +1,2008 @@
+/*
+ * Copyright (c) 1983, 1995 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[] = "@(#)util.c 8.84 (Berkeley) 11/18/95";
+#endif /* not lint */
+
+# include "sendmail.h"
+# include <sysexits.h>
+ /*
+** STRIPQUOTES -- Strip quotes & quote bits from a string.
+**
+** Runs through a string and strips off unquoted quote
+** characters and quote bits. This is done in place.
+**
+** Parameters:
+** s -- the string to strip.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+**
+** Called By:
+** deliver
+*/
+
+void
+stripquotes(s)
+ char *s;
+{
+ register char *p;
+ register char *q;
+ register char c;
+
+ if (s == NULL)
+ return;
+
+ p = q = s;
+ do
+ {
+ c = *p++;
+ if (c == '\\')
+ c = *p++;
+ else if (c == '"')
+ continue;
+ *q++ = c;
+ } while (c != '\0');
+}
+ /*
+** XALLOC -- Allocate memory and bitch wildly on failure.
+**
+** THIS IS A CLUDGE. This should be made to give a proper
+** error -- but after all, what can we do?
+**
+** Parameters:
+** sz -- size of area to allocate.
+**
+** Returns:
+** pointer to data region.
+**
+** Side Effects:
+** Memory is allocated.
+*/
+
+char *
+xalloc(sz)
+ register int sz;
+{
+ register char *p;
+
+ /* some systems can't handle size zero mallocs */
+ if (sz <= 0)
+ sz = 1;
+
+ p = malloc((unsigned) sz);
+ if (p == NULL)
+ {
+ syserr("!Out of memory!!");
+ /* exit(EX_UNAVAILABLE); */
+ }
+ return (p);
+}
+ /*
+** COPYPLIST -- copy list of pointers.
+**
+** This routine is the equivalent of newstr for lists of
+** pointers.
+**
+** Parameters:
+** list -- list of pointers to copy.
+** Must be NULL terminated.
+** copycont -- if TRUE, copy the contents of the vector
+** (which must be a string) also.
+**
+** Returns:
+** a copy of 'list'.
+**
+** Side Effects:
+** none.
+*/
+
+char **
+copyplist(list, copycont)
+ char **list;
+ bool copycont;
+{
+ register char **vp;
+ register char **newvp;
+
+ for (vp = list; *vp != NULL; vp++)
+ continue;
+
+ vp++;
+
+ newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
+ bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);
+
+ if (copycont)
+ {
+ for (vp = newvp; *vp != NULL; vp++)
+ *vp = newstr(*vp);
+ }
+
+ return (newvp);
+}
+ /*
+** 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;
+}
+ /*
+** PRINTAV -- print argument vector.
+**
+** Parameters:
+** av -- argument vector.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** prints av.
+*/
+
+void
+printav(av)
+ register char **av;
+{
+ while (*av != NULL)
+ {
+ if (tTd(0, 44))
+ printf("\n\t%08x=", *av);
+ else
+ (void) putchar(' ');
+ xputs(*av++);
+ }
+ (void) putchar('\n');
+}
+ /*
+** LOWER -- turn letter into lower case.
+**
+** Parameters:
+** c -- character to turn into lower case.
+**
+** Returns:
+** c, in lower case.
+**
+** Side Effects:
+** none.
+*/
+
+char
+lower(c)
+ register char c;
+{
+ return((isascii(c) && isupper(c)) ? tolower(c) : c);
+}
+ /*
+** XPUTS -- put string doing control escapes.
+**
+** Parameters:
+** s -- string to put.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** output to stdout
+*/
+
+void
+xputs(s)
+ register const char *s;
+{
+ register int c;
+ register struct metamac *mp;
+ extern struct metamac MetaMacros[];
+
+ if (s == NULL)
+ {
+ printf("<null>");
+ return;
+ }
+ while ((c = (*s++ & 0377)) != '\0')
+ {
+ if (!isascii(c))
+ {
+ if (c == MATCHREPL)
+ {
+ putchar('$');
+ continue;
+ }
+ if (c == MACROEXPAND)
+ {
+ putchar('$');
+ if (strchr("=~&?", *s) != NULL)
+ putchar(*s++);
+ if (bitset(0200, *s))
+ printf("{%s}", macname(*s++ & 0377));
+ continue;
+ }
+ for (mp = MetaMacros; mp->metaname != '\0'; mp++)
+ {
+ if ((mp->metaval & 0377) == c)
+ {
+ printf("$%c", mp->metaname);
+ break;
+ }
+ }
+ if (c == MATCHCLASS || c == MATCHNCLASS)
+ {
+ if (!bitset(0200, *s))
+ continue;
+ printf("{%s}", macname(*s++ & 0377));
+ }
+ if (mp->metaname != '\0')
+ continue;
+ (void) putchar('\\');
+ c &= 0177;
+ }
+ if (isprint(c))
+ {
+ putchar(c);
+ continue;
+ }
+
+ /* wasn't a meta-macro -- find another way to print it */
+ switch (c)
+ {
+ case '\n':
+ c = 'n';
+ break;
+
+ case '\r':
+ c = 'r';
+ break;
+
+ case '\t':
+ c = 't';
+ break;
+
+ default:
+ (void) putchar('^');
+ (void) putchar(c ^ 0100);
+ continue;
+ }
+ (void) putchar('\\');
+ (void) putchar(c);
+ }
+ (void) fflush(stdout);
+}
+ /*
+** MAKELOWER -- Translate a line into lower case
+**
+** Parameters:
+** p -- the string to translate. If NULL, return is
+** immediate.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** String pointed to by p is translated to lower case.
+**
+** Called By:
+** parse
+*/
+
+void
+makelower(p)
+ register char *p;
+{
+ register char c;
+
+ if (p == NULL)
+ return;
+ for (; (c = *p) != '\0'; p++)
+ if (isascii(c) && isupper(c))
+ *p = tolower(c);
+}
+ /*
+** BUILDFNAME -- build full name from gecos style entry.
+**
+** This routine interprets the strange entry that would appear
+** in the GECOS field of the password file.
+**
+** Parameters:
+** p -- name to build.
+** login -- the login name of this user (for &).
+** buf -- place to put the result.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** none.
+*/
+
+void
+buildfname(gecos, login, buf)
+ register char *gecos;
+ char *login;
+ char *buf;
+{
+ register char *p;
+ 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++;
+ }
+
+ /* now fill in buf */
+ for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
+ {
+ if (*p == '&')
+ {
+ (void) strcpy(bp, login);
+ *bp = toupper(*bp);
+ while (*bp != '\0')
+ bp++;
+ }
+ else
+ *bp++ = *p;
+ }
+ *bp = '\0';
+}
+ /*
+** SAFEFILE -- return true if a file exists and is safe for a user.
+**
+** Parameters:
+** fn -- filename to check.
+** uid -- user id to compare against.
+** gid -- group id to compare against.
+** uname -- user name to compare against (used for group
+** sets).
+** flags -- modifiers:
+** SFF_MUSTOWN -- "uid" must own this file.
+** SFF_NOSLINK -- file cannot be a symbolic link.
+** mode -- mode bits that must match.
+** st -- if set, points to a stat structure that will
+** get the stat info for the file.
+**
+** Returns:
+** 0 if fn exists, is owned by uid, and matches mode.
+** An errno otherwise. The actual errno is cleared.
+**
+** Side Effects:
+** none.
+*/
+
+#include <grp.h>
+
+#ifndef S_IXOTH
+# define S_IXOTH (S_IEXEC >> 6)
+#endif
+
+#ifndef S_IXGRP
+# define S_IXGRP (S_IEXEC >> 3)
+#endif
+
+#ifndef S_IXUSR
+# define S_IXUSR (S_IEXEC)
+#endif
+
+#define ST_MODE_NOFILE 0171147 /* unlikely to occur */
+
+int
+safefile(fn, uid, gid, uname, flags, mode, st)
+ char *fn;
+ uid_t uid;
+ gid_t gid;
+ char *uname;
+ int flags;
+ int mode;
+ struct stat *st;
+{
+ register char *p;
+ register struct group *gr = NULL;
+ int file_errno = 0;
+ struct stat stbuf;
+ struct stat fstbuf;
+
+ if (tTd(44, 4))
+ printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
+ fn, uid, gid, flags, mode);
+ errno = 0;
+ if (st == NULL)
+ st = &fstbuf;
+
+ /* first check to see if the file exists at all */
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st)
+ : stat(fn, st)) < 0)
+#else
+ if (stat(fn, st) < 0)
+#endif
+ {
+ file_errno = errno;
+ }
+ else if (bitset(SFF_SETUIDOK, flags) &&
+ !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) &&
+ S_ISREG(st->st_mode))
+ {
+ /*
+ ** If final file is setuid, run as the owner of that
+ ** file. Gotta be careful not to reveal anything too
+ ** soon here!
+ */
+
+#ifdef SUID_ROOT_FILES_OK
+ if (bitset(S_ISUID, st->st_mode))
+#else
+ if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0)
+#endif
+ {
+ uid = st->st_uid;
+ uname = NULL;
+ }
+#ifdef SUID_ROOT_FILES_OK
+ if (bitset(S_ISGID, st->st_mode))
+#else
+ if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0)
+#endif
+ gid = st->st_gid;
+ }
+
+ if (!bitset(SFF_NOPATHCHECK, flags) ||
+ (uid == 0 && !bitset(SFF_ROOTOK, flags)))
+ {
+ /* check the path to the file for acceptability */
+ for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
+ {
+ *p = '\0';
+ if (stat(fn, &stbuf) < 0)
+ break;
+ if (uid == 0 && bitset(S_IWGRP|S_IWOTH, stbuf.st_mode))
+ message("051 WARNING: writable directory %s",
+ fn);
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
+ {
+ if (bitset(S_IXOTH, stbuf.st_mode))
+ continue;
+ break;
+ }
+ if (stbuf.st_uid == uid &&
+ bitset(S_IXUSR, stbuf.st_mode))
+ continue;
+ if (stbuf.st_gid == gid &&
+ bitset(S_IXGRP, stbuf.st_mode))
+ continue;
+#ifndef NO_GROUP_SET
+ if (uname != NULL &&
+ ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
+ (gr = getgrgid(stbuf.st_gid)) != NULL))
+ {
+ register char **gp;
+
+ for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (gp != NULL && *gp != NULL &&
+ bitset(S_IXGRP, stbuf.st_mode))
+ continue;
+ }
+#endif
+ if (!bitset(S_IXOTH, stbuf.st_mode))
+ break;
+ }
+ if (p != NULL)
+ {
+ int ret = errno;
+
+ if (ret == 0)
+ ret = EACCES;
+ if (tTd(44, 4))
+ printf("\t[dir %s] %s\n", fn, errstring(ret));
+ *p = '/';
+ return ret;
+ }
+ }
+
+ /*
+ ** If the target file doesn't exist, check the directory to
+ ** ensure that it is writable by this user.
+ */
+
+ if (file_errno != 0)
+ {
+ int ret = file_errno;
+
+ if (tTd(44, 4))
+ printf("\t%s\n", errstring(ret));
+
+ errno = 0;
+ if (!bitset(SFF_CREAT, flags))
+ return ret;
+
+ /* check to see if legal to create the file */
+ p = strrchr(fn, '/');
+ if (p == NULL)
+ return ENOTDIR;
+ *p = '\0';
+ if (stat(fn, &stbuf) >= 0)
+ {
+ int md = S_IWRITE|S_IEXEC;
+ if (stbuf.st_uid != uid)
+ md >>= 6;
+ if ((stbuf.st_mode & md) != md)
+ errno = EACCES;
+ }
+ ret = errno;
+ if (tTd(44, 4))
+ printf("\t[final dir %s uid %d mode %o] %s\n",
+ fn, stbuf.st_uid, stbuf.st_mode,
+ errstring(ret));
+ *p = '/';
+ st->st_mode = ST_MODE_NOFILE;
+ return ret;
+ }
+
+#ifdef S_ISLNK
+ if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[slink mode %o]\tEPERM\n", st->st_mode);
+ return EPERM;
+ }
+#endif
+ if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[non-reg mode %o]\tEPERM\n", st->st_mode);
+ return EPERM;
+ }
+ if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) &&
+ bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode))
+ {
+ if (tTd(44, 4))
+ printf("\t[exec bits %o]\tEPERM]\n", st->st_mode);
+ return EPERM;
+ }
+
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
+ mode >>= 6;
+ else if (st->st_uid != uid)
+ {
+ mode >>= 3;
+ if (st->st_gid == gid)
+ ;
+#ifndef NO_GROUP_SET
+ else if (uname != NULL &&
+ ((gr != NULL && gr->gr_gid == st->st_gid) ||
+ (gr = getgrgid(st->st_gid)) != NULL))
+ {
+ register char **gp;
+
+ for (gp = gr->gr_mem; *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (*gp == NULL)
+ mode >>= 3;
+ }
+#endif
+ else
+ mode >>= 3;
+ }
+ if (tTd(44, 4))
+ printf("\t[uid %d, stat %o, mode %o] ",
+ st->st_uid, st->st_mode, mode);
+ if ((st->st_uid == uid || st->st_uid == 0 ||
+ !bitset(SFF_MUSTOWN, flags)) &&
+ (st->st_mode & mode) == mode)
+ {
+ if (tTd(44, 4))
+ printf("\tOK\n");
+ return 0;
+ }
+ if (tTd(44, 4))
+ printf("\tEACCES\n");
+ return EACCES;
+}
+ /*
+** SAFEFOPEN -- do a file open with extra checking
+**
+** Parameters:
+** fn -- the file name to open.
+** omode -- the open-style mode flags.
+** cmode -- the create-style mode flags.
+** sff -- safefile flags.
+**
+** Returns:
+** Same as fopen.
+*/
+
+#ifndef O_ACCMODE
+# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
+#endif
+
+FILE *
+safefopen(fn, omode, cmode, sff)
+ char *fn;
+ int omode;
+ int cmode;
+ int sff;
+{
+ int rval;
+ FILE *fp;
+ int smode;
+ struct stat stb, sta;
+
+ if (bitset(O_CREAT, omode))
+ sff |= SFF_CREAT;
+ smode = 0;
+ switch (omode & O_ACCMODE)
+ {
+ case O_RDONLY:
+ smode = S_IREAD;
+ break;
+
+ case O_WRONLY:
+ smode = S_IWRITE;
+ break;
+
+ case O_RDWR:
+ smode = S_IREAD|S_IWRITE;
+ break;
+
+ default:
+ smode = 0;
+ break;
+ }
+ if (bitset(SFF_OPENASROOT, sff))
+ rval = safefile(fn, 0, 0, NULL, sff, smode, &stb);
+ else
+ rval = safefile(fn, RealUid, RealGid, RealUserName,
+ sff, smode, &stb);
+ if (rval != 0)
+ {
+ errno = rval;
+ return NULL;
+ }
+ if (stb.st_mode == ST_MODE_NOFILE)
+ omode |= O_EXCL;
+
+ fp = dfopen(fn, omode, cmode);
+ if (fp == NULL)
+ return NULL;
+ if (bitset(O_EXCL, omode))
+ return fp;
+ if (fstat(fileno(fp), &sta) < 0 ||
+ sta.st_nlink != stb.st_nlink ||
+ sta.st_dev != stb.st_dev ||
+ sta.st_ino != stb.st_ino ||
+ sta.st_uid != stb.st_uid ||
+ sta.st_gid != stb.st_gid)
+ {
+ syserr("554 cannot open: file %s changed after open", fn);
+ fclose(fp);
+ errno = EPERM;
+ return NULL;
+ }
+ return fp;
+}
+ /*
+** FIXCRLF -- fix <CR><LF> in line.
+**
+** Looks for the <CR><LF> combination and turns it into the
+** UNIX canonical <NL> character. It only takes one line,
+** i.e., it is assumed that the first <NL> found is the end
+** of the line.
+**
+** Parameters:
+** line -- the line to fix.
+** stripnl -- if true, strip the newline also.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** line is changed in place.
+*/
+
+void
+fixcrlf(line, stripnl)
+ char *line;
+ bool stripnl;
+{
+ register char *p;
+
+ p = strchr(line, '\n');
+ if (p == NULL)
+ return;
+ if (p > line && p[-1] == '\r')
+ p--;
+ if (!stripnl)
+ *p++ = '\n';
+ *p = '\0';
+}
+ /*
+** DFOPEN -- determined file open
+**
+** This routine has the semantics of fopen, except that it will
+** keep trying a few times to make this happen. The idea is that
+** on very loaded systems, we may run out of resources (inodes,
+** whatever), so this tries to get around it.
+*/
+
+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 *
+dfopen(filename, omode, cmode)
+ char *filename;
+ int omode;
+ int cmode;
+{
+ register int tries;
+ 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;
+ fd = open(filename, omode, cmode);
+ if (fd >= 0)
+ break;
+ switch (errno)
+ {
+ case ENFILE: /* system file table full */
+ case EINTR: /* interrupted syscall */
+#ifdef ETXTBSY
+ case ETXTBSY: /* Apollo: net file locked */
+#endif
+ continue;
+ }
+ break;
+ }
+ if (fd >= 0 && fstat(fd, &st) >= 0 && S_ISREG(st.st_mode))
+ {
+ int locktype;
+
+ /* lock the file to avoid accidental conflicts */
+ if ((omode & O_ACCMODE) != O_RDONLY)
+ locktype = LOCK_EX;
+ else
+ locktype = LOCK_SH;
+ (void) lockfile(fd, filename, NULL, locktype);
+ errno = 0;
+ }
+ if (fd < 0)
+ return NULL;
+ else
+ return fdopen(fd, om->farg);
+}
+ /*
+** PUTLINE -- put a line like fputs obeying SMTP conventions
+**
+** This routine always guarantees outputing a newline (or CRLF,
+** as appropriate) at the end of the string.
+**
+** Parameters:
+** l -- line to put.
+** mci -- the mailer connection information.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** output of l to fp.
+*/
+
+void
+putline(l, mci)
+ register char *l;
+ register MCI *mci;
+{
+ putxline(l, mci, PXLF_MAPFROM);
+}
+ /*
+** PUTXLINE -- putline with flags bits.
+**
+** This routine always guarantees outputing a newline (or CRLF,
+** as appropriate) at the end of the string.
+**
+** Parameters:
+** l -- line to put.
+** mci -- the mailer connection information.
+** pxflags -- flag bits:
+** PXLF_MAPFROM -- map From_ to >From_.
+** PXLF_STRIP8BIT -- strip 8th bit.
+**
+** Returns:
+** none
+**
+** Side Effects:
+** output of l to fp.
+*/
+
+void
+putxline(l, mci, pxflags)
+ register char *l;
+ register MCI *mci;
+ int pxflags;
+{
+ register char *p;
+ register char svchar;
+ int slop = 0;
+
+ /* strip out 0200 bits -- these can look like TELNET protocol */
+ if (bitset(MCIF_7BIT, mci->mci_flags) ||
+ bitset(PXLF_STRIP8BIT, pxflags))
+ {
+ for (p = l; (svchar = *p) != '\0'; ++p)
+ if (bitset(0200, svchar))
+ *p = svchar &~ 0200;
+ }
+
+ do
+ {
+ /* find the end of the line */
+ p = strchr(l, '\n');
+ if (p == NULL)
+ p = &l[strlen(l)];
+
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d >>> ", getpid());
+
+ /* check for line overflow */
+ while (mci->mci_mailer->m_linelimit > 0 &&
+ (p - l + slop) > mci->mci_mailer->m_linelimit)
+ {
+ register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
+
+ svchar = *q;
+ *q = '\0';
+ if (l[0] == '.' && slop == 0 &&
+ bitnset(M_XDOT, mci->mci_mailer->m_flags))
+ {
+ (void) putc('.', mci->mci_out);
+ if (TrafficLogFile != NULL)
+ (void) putc('.', TrafficLogFile);
+ }
+ else if (l[0] == 'F' && slop == 0 &&
+ bitset(PXLF_MAPFROM, pxflags) &&
+ strncmp(l, "From ", 5) == 0 &&
+ bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
+ {
+ (void) putc('>', mci->mci_out);
+ if (TrafficLogFile != NULL)
+ (void) putc('>', TrafficLogFile);
+ }
+ fputs(l, mci->mci_out);
+ (void) putc('!', mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ (void) putc(' ', mci->mci_out);
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%s!\n%05d >>> ",
+ l, getpid());
+ *q = svchar;
+ l = q;
+ slop = 1;
+ }
+
+ /* output last part */
+ if (l[0] == '.' && slop == 0 &&
+ bitnset(M_XDOT, mci->mci_mailer->m_flags))
+ {
+ (void) putc('.', mci->mci_out);
+ if (TrafficLogFile != NULL)
+ (void) putc('.', TrafficLogFile);
+ }
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%.*s\n", p - l, l);
+ for ( ; l < p; ++l)
+ (void) putc(*l, mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ if (*l == '\n')
+ ++l;
+ } while (l[0] != '\0');
+}
+ /*
+** XUNLINK -- unlink a file, doing logging as appropriate.
+**
+** Parameters:
+** f -- name of file to unlink.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** f is unlinked.
+*/
+
+void
+xunlink(f)
+ char *f;
+{
+ register int i;
+
+# ifdef LOG
+ if (LogLevel > 98)
+ syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);
+# endif /* LOG */
+
+ i = unlink(f);
+# ifdef LOG
+ if (i < 0 && LogLevel > 97)
+ syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
+# endif /* LOG */
+}
+ /*
+** 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.
+*/
+
+void
+xfclose(fp, a, b)
+ FILE *fp;
+ char *a, *b;
+{
+ if (tTd(53, 99))
+ printf("xfclose(%x) %s %s\n", fp, a, b);
+#if XDEBUG
+ if (fileno(fp) == 1)
+ syserr("xfclose(%s %s): fd = 1", a, b);
+#endif
+ if (fclose(fp) < 0 && tTd(53, 99))
+ printf("xfclose FAILURE: %s\n", errstring(errno));
+}
+ /*
+** SFGETS -- "safe" fgets -- times out and ignores random interrupts.
+**
+** Parameters:
+** 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
+** buf containing a null string.
+** buf otherwise.
+**
+** Side Effects:
+** none.
+*/
+
+static jmp_buf CtxReadTimeout;
+static void readtimeout();
+
+char *
+sfgets(buf, siz, fp, timeout, during)
+ char *buf;
+ int siz;
+ FILE *fp;
+ time_t timeout;
+ char *during;
+{
+ register EVENT *ev = NULL;
+ register char *p;
+
+ if (fp == NULL)
+ {
+ buf[0] = '\0';
+ return NULL;
+ }
+
+ /* set the timeout */
+ if (timeout != 0)
+ {
+ if (setjmp(CtxReadTimeout) != 0)
+ {
+# ifdef LOG
+ syslog(LOG_NOTICE,
+ "timeout waiting for input from %.100s during %s",
+ CurHostName? CurHostName: "local", during);
+# endif
+ errno = 0;
+ usrerr("451 timeout waiting for input during %s",
+ during);
+ buf[0] = '\0';
+#if XDEBUG
+ checkfd012(during);
+#endif
+ return (NULL);
+ }
+ ev = setevent(timeout, readtimeout, 0);
+ }
+
+ /* try to read */
+ p = NULL;
+ while (!feof(fp) && !ferror(fp))
+ {
+ errno = 0;
+ p = fgets(buf, siz, fp);
+ if (p != NULL || errno != EINTR)
+ break;
+ clearerr(fp);
+ }
+
+ /* clear the event if it has not sprung */
+ clrevent(ev);
+
+ /* clean up the books and exit */
+ LineNumber++;
+ if (p == NULL)
+ {
+ buf[0] = '\0';
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d <<< [EOF]\n", getpid());
+ return (NULL);
+ }
+ if (TrafficLogFile != NULL)
+ fprintf(TrafficLogFile, "%05d <<< %s", getpid(), buf);
+ if (SevenBitInput)
+ {
+ for (p = buf; *p != '\0'; p++)
+ *p &= ~0200;
+ }
+ else if (!HasEightBits)
+ {
+ for (p = buf; *p != '\0'; p++)
+ {
+ if (bitset(0200, *p))
+ {
+ HasEightBits = TRUE;
+ break;
+ }
+ }
+ }
+ return (buf);
+}
+
+static void
+readtimeout(timeout)
+ time_t timeout;
+{
+ longjmp(CtxReadTimeout, 1);
+}
+ /*
+** FGETFOLDED -- like fgets, but know about folded lines.
+**
+** Parameters:
+** buf -- place to put result.
+** n -- bytes available.
+** f -- file to read from.
+**
+** Returns:
+** 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
+** with leading white space) appended. CRLF's are mapped
+** into single newlines. Any trailing NL is stripped.
+*/
+
+char *
+fgetfolded(buf, n, f)
+ char *buf;
+ register int n;
+ FILE *f;
+{
+ register char *p = buf;
+ char *bp = buf;
+ register int i;
+
+ n--;
+ while ((i = getc(f)) != EOF)
+ {
+ if (i == '\r')
+ {
+ i = getc(f);
+ if (i != '\n')
+ {
+ if (i != EOF)
+ (void) ungetc(i, f);
+ i = '\r';
+ }
+ }
+ 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++;
+ i = getc(f);
+ if (i != EOF)
+ (void) ungetc(i, f);
+ if (i != ' ' && i != '\t')
+ break;
+ }
+ }
+ if (p == bp)
+ return (NULL);
+ if (p[-1] == '\n')
+ p--;
+ *p = '\0';
+ return (bp);
+}
+ /*
+** CURTIME -- return current time.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** the current time.
+**
+** Side Effects:
+** none.
+*/
+
+time_t
+curtime()
+{
+ auto time_t t;
+
+ (void) time(&t);
+ return (t);
+}
+ /*
+** ATOBOOL -- convert a string representation to boolean.
+**
+** Defaults to "TRUE"
+**
+** Parameters:
+** s -- string to convert. Takes "tTyY" as true,
+** others as false.
+**
+** Returns:
+** A boolean representation of the string.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+atobool(s)
+ register char *s;
+{
+ if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL)
+ return (TRUE);
+ return (FALSE);
+}
+ /*
+** ATOOCT -- convert a string representation to octal.
+**
+** Parameters:
+** s -- string to convert.
+**
+** Returns:
+** An integer representing the string interpreted as an
+** octal number.
+**
+** Side Effects:
+** none.
+*/
+
+int
+atooct(s)
+ register char *s;
+{
+ register int i = 0;
+
+ while (*s >= '0' && *s <= '7')
+ i = (i << 3) | (*s++ - '0');
+ return (i);
+}
+ /*
+** WAITFOR -- wait for a particular process id.
+**
+** Parameters:
+** pid -- process id to wait for.
+**
+** Returns:
+** status of pid.
+** -1 if pid never shows up.
+**
+** Side Effects:
+** none.
+*/
+
+int
+waitfor(pid)
+ int pid;
+{
+#ifdef WAITUNION
+ union wait st;
+#else
+ auto int st;
+#endif
+ int i;
+
+ do
+ {
+ errno = 0;
+ i = wait(&st);
+ } while ((i >= 0 || errno == EINTR) && i != pid);
+ if (i < 0)
+ return -1;
+#ifdef WAITUNION
+ return st.w_status;
+#else
+ return st;
+#endif
+}
+ /*
+** BITINTERSECT -- tell if two bitmaps intersect
+**
+** Parameters:
+** a, b -- the bitmaps in question
+**
+** Returns:
+** TRUE if they have a non-null intersection
+** FALSE otherwise
+**
+** Side Effects:
+** none.
+*/
+
+bool
+bitintersect(a, b)
+ BITMAP a;
+ BITMAP b;
+{
+ int i;
+
+ for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
+ if ((a[i] & b[i]) != 0)
+ return (TRUE);
+ return (FALSE);
+}
+ /*
+** BITZEROP -- tell if a bitmap is all zero
+**
+** Parameters:
+** map -- the bit map to check
+**
+** Returns:
+** TRUE if map is all zero.
+** FALSE if there are any bits set in map.
+**
+** Side Effects:
+** none.
+*/
+
+bool
+bitzerop(map)
+ BITMAP map;
+{
+ int i;
+
+ for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
+ if (map[i] != 0)
+ return (FALSE);
+ return (TRUE);
+}
+ /*
+** 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 la;
+ int lb;
+ int c;
+
+ la = strlen(a);
+ lb = strlen(b);
+ c = *a;
+ if (isascii(c) && isupper(c))
+ c = tolower(c);
+ for (; lb-- >= la; b++)
+ {
+ if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
+ continue;
+ if (strncasecmp(a, b, la) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+ /*
+** CHECKFD012 -- check low numbered file descriptors
+**
+** File descriptors 0, 1, and 2 should be open at all times.
+** This routine verifies that, and fixes it if not true.
+**
+** Parameters:
+** where -- a tag printed if the assertion failed
+**
+** Returns:
+** none
+*/
+
+void
+checkfd012(where)
+ char *where;
+{
+#if XDEBUG
+ register int i;
+ struct stat stbuf;
+
+ for (i = 0; i < 3; i++)
+ {
+ if (fstat(i, &stbuf) < 0 && errno != EOPNOTSUPP)
+ {
+ /* oops.... */
+ int fd;
+
+ syserr("%s: fd %d not open", where, i);
+ fd = open("/dev/null", i == 0 ? O_RDONLY : O_WRONLY, 0666);
+ if (fd != i)
+ {
+ (void) dup2(fd, i);
+ (void) close(fd);
+ }
+ }
+ }
+#endif /* XDEBUG */
+}
+ /*
+** PRINTOPENFDS -- print the open file descriptors (for debugging)
+**
+** Parameters:
+** logit -- if set, send output to syslog; otherwise
+** print for debugging.
+**
+** Returns:
+** none.
+*/
+
+#include <arpa/inet.h>
+
+void
+printopenfds(logit)
+ bool logit;
+{
+ register int fd;
+ extern int DtableSize;
+
+ for (fd = 0; fd < DtableSize; fd++)
+ dumpfd(fd, FALSE, logit);
+}
+ /*
+** DUMPFD -- dump a file descriptor
+**
+** Parameters:
+** fd -- the file descriptor to dump.
+** printclosed -- if set, print a notification even if
+** it is closed; otherwise print nothing.
+** logit -- if set, send output to syslog instead of stdout.
+*/
+
+void
+dumpfd(fd, printclosed, logit)
+ int fd;
+ bool printclosed;
+ bool logit;
+{
+ register char *p;
+ char *hp;
+ char *fmtstr;
+#ifdef S_IFSOCK
+ SOCKADDR sa;
+#endif
+ auto int slen;
+ struct stat st;
+ char buf[200];
+ extern char *hostnamebyanyaddr();
+
+ p = buf;
+ sprintf(p, "%3d: ", fd);
+ p += strlen(p);
+
+ if (fstat(fd, &st) < 0)
+ {
+ if (printclosed || errno != EBADF)
+ {
+ sprintf(p, "CANNOT STAT (%s)", errstring(errno));
+ goto printit;
+ }
+ return;
+ }
+
+ slen = fcntl(fd, F_GETFL, NULL);
+ if (slen != -1)
+ {
+ sprintf(p, "fl=0x%x, ", slen);
+ p += strlen(p);
+ }
+
+ sprintf(p, "mode=%o: ", st.st_mode);
+ p += strlen(p);
+ switch (st.st_mode & S_IFMT)
+ {
+#ifdef S_IFSOCK
+ case S_IFSOCK:
+ sprintf(p, "SOCK ");
+ p += strlen(p);
+ slen = sizeof sa;
+ if (getsockname(fd, &sa.sa, &slen) < 0)
+ sprintf(p, "(%s)", errstring(errno));
+ else
+ {
+ hp = hostnamebyanyaddr(&sa);
+ if (sa.sa.sa_family == AF_INET)
+ sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port));
+ else
+ sprintf(p, "%s", hp);
+ }
+ p += strlen(p);
+ sprintf(p, "->");
+ p += strlen(p);
+ slen = sizeof sa;
+ if (getpeername(fd, &sa.sa, &slen) < 0)
+ sprintf(p, "(%s)", errstring(errno));
+ else
+ {
+ hp = hostnamebyanyaddr(&sa);
+ if (sa.sa.sa_family == AF_INET)
+ sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port));
+ else
+ sprintf(p, "%s", hp);
+ }
+ break;
+#endif
+
+ case S_IFCHR:
+ sprintf(p, "CHR: ");
+ p += strlen(p);
+ goto defprint;
+
+ case S_IFBLK:
+ sprintf(p, "BLK: ");
+ p += strlen(p);
+ goto defprint;
+
+#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
+ case S_IFIFO:
+ sprintf(p, "FIFO: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFDIR
+ case S_IFDIR:
+ sprintf(p, "DIR: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFLNK
+ case S_IFLNK:
+ sprintf(p, "LNK: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+ default:
+defprint:
+ if (sizeof st.st_size > sizeof (long))
+ fmtstr = "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%qd";
+ else
+ fmtstr = "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%ld";
+ sprintf(p, fmtstr,
+ major(st.st_dev), minor(st.st_dev), st.st_ino,
+ st.st_nlink, st.st_uid, st.st_gid, st.st_size);
+ break;
+ }
+
+printit:
+#ifdef LOG
+ if (logit)
+ syslog(LOG_DEBUG, "%.800s", buf);
+ else
+#endif
+ printf("%s\n", buf);
+}
+ /*
+** SHORTENSTRING -- return short version of a string
+**
+** If the string is already short, just return it. If it is too
+** long, return the head and tail of the string.
+**
+** Parameters:
+** s -- the string to shorten.
+** m -- the max length of the string.
+**
+** Returns:
+** Either s or a short version of s.
+*/
+
+#ifndef MAXSHORTSTR
+# define MAXSHORTSTR 203
+#endif
+
+char *
+shortenstring(s, m)
+ register const char *s;
+ int m;
+{
+ int l;
+ static char buf[MAXSHORTSTR + 1];
+
+ l = strlen(s);
+ if (l < m)
+ return (char *) s;
+ if (m > MAXSHORTSTR)
+ m = MAXSHORTSTR;
+ else if (m < 10)
+ {
+ if (m < 5)
+ {
+ strncpy(buf, s, m);
+ buf[m] = '\0';
+ return buf;
+ }
+ strncpy(buf, s, m - 3);
+ strcpy(buf + m - 3, "...");
+ return buf;
+ }
+ m = (m - 3) / 2;
+ strncpy(buf, s, m);
+ strcpy(buf + m, "...");
+ strcpy(buf + m + 3, s + l - m);
+ return buf;
+}
+ /*
+** SHORTEN_HOSTNAME -- strip local domain information off of hostname.
+**
+** Parameters:
+** host -- the host to shorten (stripped in place).
+**
+** Returns:
+** none.
+*/
+
+void
+shorten_hostname(host)
+ char host[];
+{
+ register char *p;
+ char *mydom;
+ int i;
+ bool canon = FALSE;
+
+ /* strip off final dot */
+ p = &host[strlen(host) - 1];
+ if (*p == '.')
+ {
+ *p = '\0';
+ canon = TRUE;
+ }
+
+ /* see if there is any domain at all -- if not, we are done */
+ p = strchr(host, '.');
+ if (p == NULL)
+ return;
+
+ /* yes, we have a domain -- see if it looks like us */
+ mydom = macvalue('m', CurEnv);
+ if (mydom == NULL)
+ mydom = "";
+ i = strlen(++p);
+ if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 &&
+ (mydom[i] == '.' || mydom[i] == '\0'))
+ *--p = '\0';
+}
+ /*
+** PROG_OPEN -- open a program for reading
+**
+** Parameters:
+** argv -- the argument list.
+** pfd -- pointer to a place to store the file descriptor.
+** e -- the current envelope.
+**
+** Returns:
+** pid of the process -- -1 if it failed.
+*/
+
+int
+prog_open(argv, pfd, e)
+ char **argv;
+ int *pfd;
+ ENVELOPE *e;
+{
+ int pid;
+ int i;
+ int saveerrno;
+ int fdv[2];
+ char *p, *q;
+ char buf[MAXLINE + 1];
+ extern int DtableSize;
+
+ if (pipe(fdv) < 0)
+ {
+ syserr("%s: cannot create pipe for stdout", argv[0]);
+ return -1;
+ }
+ pid = fork();
+ if (pid < 0)
+ {
+ syserr("%s: cannot fork", argv[0]);
+ close(fdv[0]);
+ close(fdv[1]);
+ return -1;
+ }
+ if (pid > 0)
+ {
+ /* parent */
+ close(fdv[1]);
+ *pfd = fdv[0];
+ return pid;
+ }
+
+ /* child -- close stdin */
+ close(0);
+
+ /* stdout goes back to parent */
+ close(fdv[0]);
+ if (dup2(fdv[1], 1) < 0)
+ {
+ syserr("%s: cannot dup2 for stdout", argv[0]);
+ _exit(EX_OSERR);
+ }
+ close(fdv[1]);
+
+ /* stderr goes to transcript if available */
+ if (e->e_xfp != NULL)
+ {
+ if (dup2(fileno(e->e_xfp), 2) < 0)
+ {
+ syserr("%s: cannot dup2 for stderr", argv[0]);
+ _exit(EX_OSERR);
+ }
+ }
+
+ /* this process has no right to the queue file */
+ if (e->e_lockfp != NULL)
+ close(fileno(e->e_lockfp));
+
+ /* run as default user */
+ endpwent();
+ setgid(DefGid);
+ setuid(DefUid);
+
+ /* run in some directory */
+ if (ProgMailer != NULL)
+ p = ProgMailer->m_execdir;
+ else
+ p = NULL;
+ for (; p != NULL; p = q)
+ {
+ q = strchr(p, ':');
+ if (q != NULL)
+ *q = '\0';
+ expand(p, buf, sizeof buf, e);
+ if (q != NULL)
+ *q++ = ':';
+ if (buf[0] != '\0' && chdir(buf) >= 0)
+ break;
+ }
+ if (p == NULL)
+ {
+ /* backup directories */
+ if (chdir("/tmp") < 0)
+ (void) chdir("/");
+ }
+
+ /* 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);
+ }
+
+ /* now exec the process */
+ execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron);
+
+ /* woops! failed */
+ saveerrno = errno;
+ syserr("%s: cannot exec", argv[0]);
+ if (transienterror(saveerrno))
+ _exit(EX_OSERR);
+ _exit(EX_CONFIG);
+}
+ /*
+** GET_COLUMN -- look up a Column in a line buffer
+**
+** Parameters:
+** line -- the raw text line to search.
+** col -- the column number to fetch.
+** delim -- the delimiter between columns. If null,
+** use white space.
+** buf -- the output buffer.
+**
+** Returns:
+** buf if successful.
+** NULL otherwise.
+*/
+
+char *
+get_column(line, col, delim, buf)
+ char line[];
+ int col;
+ char delim;
+ char buf[];
+{
+ char *p;
+ char *begin, *end;
+ int i;
+ char delimbuf[3];
+
+ if (delim == '\0')
+ strcpy(delimbuf, "\n\t ");
+ else
+ {
+ delimbuf[0] = delim;
+ delimbuf[1] = '\0';
+ }
+
+ p = line;
+ if (*p == '\0')
+ return NULL; /* line empty */
+ if (*p == delim && col == 0)
+ return NULL; /* first column empty */
+
+ begin = line;
+
+ if (col == 0 && delim == '\0')
+ {
+ while (*begin && isspace(*begin))
+ begin++;
+ }
+
+ for (i = 0; i < col; i++)
+ {
+ if ((begin = strpbrk(begin, delimbuf)) == NULL)
+ return NULL; /* no such column */
+ begin++;
+ if (delim == '\0')
+ {
+ while (*begin && isspace(*begin))
+ begin++;
+ }
+ }
+
+ end = strpbrk(begin, delimbuf);
+ if (end == NULL)
+ {
+ strcpy(buf, begin);
+ }
+ else
+ {
+ strncpy(buf, begin, end - begin);
+ buf[end - begin] = '\0';
+ }
+ return buf;
+}
+ /*
+** CLEANSTRCPY -- copy string keeping out bogus characters
+**
+** Parameters:
+** t -- "to" string.
+** f -- "from" string.
+** l -- length of space available in "to" string.
+**
+** Returns:
+** none.
+*/
+
+void
+cleanstrcpy(t, f, l)
+ register char *t;
+ register char *f;
+ int l;
+{
+#ifdef LOG
+ /* check for newlines and log if necessary */
+ (void) denlstring(f, TRUE, TRUE);
+#endif
+
+ l--;
+ while (l > 0 && *f != '\0')
+ {
+ if (isascii(*f) &&
+ (isalnum(*f) || strchr("!#$%&'*+-./^_`{|}~", *f) != NULL))
+ {
+ l--;
+ *t++ = *f;
+ }
+ f++;
+ }
+ *t = '\0';
+}
+ /*
+** DENLSTRING -- convert newlines in a string to spaces
+**
+** Parameters:
+** s -- the input string
+** strict -- if set, don't permit continuation lines.
+** logattacks -- if set, log attempted attacks.
+**
+** Returns:
+** A pointer to a version of the string with newlines
+** mapped to spaces. This should be copied.
+*/
+
+char *
+denlstring(s, strict, logattacks)
+ char *s;
+ bool strict;
+ bool logattacks;
+{
+ register char *p;
+ int l;
+ static char *bp = NULL;
+ static int bl = 0;
+
+ p = s;
+ while ((p = strchr(p, '\n')) != NULL)
+ if (strict || (*++p != ' ' && *p != '\t'))
+ break;
+ if (p == NULL)
+ return s;
+
+ l = strlen(s) + 1;
+ if (bl < l)
+ {
+ /* allocate more space */
+ if (bp != NULL)
+ free(bp);
+ bp = xalloc(l);
+ bl = l;
+ }
+ strcpy(bp, s);
+ for (p = bp; (p = strchr(p, '\n')) != NULL; )
+ *p++ = ' ';
+
+/*
+#ifdef LOG
+ if (logattacks)
+ {
+ syslog(LOG_NOTICE, "POSSIBLE ATTACK from %.100s: newline in string \"%s\"",
+ RealHostName == NULL ? "[UNKNOWN]" : RealHostName,
+ shortenstring(bp, 203));
+ }
+#endif
+*/
+
+ return bp;
+}
diff --git a/usr.sbin/sendmail/src/version.c b/usr.sbin/sendmail/src/version.c
new file mode 100644
index 000000000000..2d51c38c826f
--- /dev/null
+++ b/usr.sbin/sendmail/src/version.c
@@ -0,0 +1,39 @@
+/*
+ * 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[] = "@(#)version.c 8.7.2.2 (Berkeley) 11/20/95";
+#endif /* not lint */
+
+char Version[] = "8.7.2";
diff --git a/usr.sbin/sendmail/test/Results b/usr.sbin/sendmail/test/Results
new file mode 100644
index 000000000000..d703fe4881cb
--- /dev/null
+++ b/usr.sbin/sendmail/test/Results
@@ -0,0 +1,65 @@
+The following are results of running t_setreuid on various architectures.
+
+OPSYS VERSION STATUS DATE TESTER/NOTES
+===== ======= ====== ==== ============
+
+SunOS 4.1 OK 93.07.19 eric
+SunOS 4.1.2 OK 93.07.19 eric
+SunOS 4.1.3 OK 93.09.25 Robert Elz
+
+BSD 4.4 OK 93.07.19 eric (wierd results, but functional)
+BSD 4.3Utah OK 93.07.19 eric
+
+Ultrix 4.2A OK 93.07.19 eric
+Ultrix 4.3A OK 93.07.19 Allan Johannesen
+
+HP-UX 8.07 OK 93.07.19 eric (on 7xx series)
+HP-UX 8.02 OK 93.07.19 Michael Corrigan (on 8xx series)
+HP-UX 8.00 OK 93.07.21 Michael Corrigan (on 3xx/4xx series)
+HP-UX 9.01 OK 93.11.19 Cassidy (on 7xx series)
+
+Solaris 2.1
+Solaris 2.2 FAIL 93.07.19 Bill Wisner
+
+OSF/1 T1.3-4 OK 93.07.19 eric (on DEC Alpha)
+OSF/1 1.3 OK 94.12.10 Jeff A. Earickson (on Intel Paragon)
+
+CxOS 11.0 OK 93.01.21 Eric Schnoebelen (CxOS 11.0 beta 1)
+CxOS 10.x OK 93.01.21 Eric Schnoebelen
+
+AIX 3.1.5 FAIL 93.08.07 David J. N. Begley
+AIX 3.2.3e FAIL 93.07.26 Steve Bauer <sbauer@silver.sdsmt.edu>
+AIX 3.2.4 FAIL 93.10.07 David J. N. Begley
+AIX 3.2.5 FAIL 94.05.17 Steve Bauer <sbauer@hpcmmib.hpc.sdsmt.edu>
+
+IRIX 4.0.4 OK 93.09.25 Robert Elz
+IRIX 5.2 OK 94.12.06 Mark Andrews <mandrews@alias.com>
+IRIX 5.3 OK 94.12.06 Mark Andrews <mandrews@alias.com>
+
+SCO 3.2v4.0 OK 93.10.02 Peter Wemm (with -lsocket from 3.2v4 devsys)
+
+NeXT 2.1 OK 93.07.28 eric
+NeXT 3.0 OK 34.05.05 Kevin John Wang <kwang@lore.acs.calpoly.edu>
+
+Linux 0.99p10 OK 93.08.08 Karl London
+Linux 0.99p13 OK 93.09.27 Christian Kuhtz
+Linux 0.99p14 OK 93.11.30 Christian Kuhtz <chk@data-hh.Hanse.DE>
+Linux 1.0 OK 94.03.19 Shayne Smith <snsmith@rastus.brisnet.org.au>
+Linux 1.2.13 OK 95.11.02 Sven Neuhaus <sven@ping.de>
+
+BSD/386 1.0 OK 93.11.13 Tony Sanders
+
+DELL 2.2 OK 93.11.15 Peter Wemm (using -DSETEUID)
+
+Pyramid 5.0d OK 95.01.14 David Miller <davem@nadzieja.rutgers.edu>
+
+
+
+The following are results of running t_seteuid on various architectures.
+
+OPSYS VERSION STATUS DATE TESTER/NOTES
+===== ======= ====== ==== ============
+
+Solaris 2.4 OK 95.09.22 Thomas 'Mike' Michlmayr <mike@cosy.sbg.ac.at>
+
+Linux 1.2.13 FAIL 95.11.02 Sven Neuhaus <sven@ping.de>
diff --git a/usr.sbin/sendmail/test/t_seteuid.c b/usr.sbin/sendmail/test/t_seteuid.c
new file mode 100644
index 000000000000..4dfe3d63bf77
--- /dev/null
+++ b/usr.sbin/sendmail/test/t_seteuid.c
@@ -0,0 +1,120 @@
+/*
+** This program checks to see if your version of seteuid works.
+** Compile it, make it setuid root, and run it as yourself (NOT as
+** root). If it won't compile or outputs any MAYDAY messages, don't
+** define USESETEUID in conf.h.
+**
+** NOTE: It is not sufficient to have seteuid in your library.
+** You must also have saved uids that function properly.
+**
+** Compilation is trivial -- just "cc t_seteuid.c". Make it setuid,
+** root and then execute it as a non-root user.
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#ifdef __hpux
+#define seteuid(e) setresuid(-1, e, -1)
+#endif
+
+main()
+{
+ int fail = 0;
+ uid_t realuid = getuid();
+
+ printuids("initial uids", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ printf("SETUP ERROR: re-run setuid root\n");
+ exit(1);
+ }
+
+ if (getuid() == 0)
+ {
+ printf("SETUP ERROR: must be run by a non-root user\n");
+ exit(1);
+ }
+
+ if (seteuid(1) < 0)
+ printf("seteuid(1) failure\n");
+ printuids("after seteuid(1)", realuid, 1);
+
+ if (geteuid() != 1)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+
+ /* do activity here */
+
+ if (seteuid(0) < 0)
+ {
+ fail++;
+ printf("seteuid(0) failure\n");
+ }
+ printuids("after seteuid(0)", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+ if (getuid() != realuid)
+ {
+ fail++;
+ printf("MAYDAY! Wrong real uid\n");
+ }
+ printf("\n");
+
+ if (seteuid(2) < 0)
+ {
+ fail++;
+ printf("seteuid(2) failure\n");
+ }
+ printuids("after seteuid(2)", realuid, 2);
+
+ if (geteuid() != 2)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+
+ /* do activity here */
+
+ if (seteuid(0) < 0)
+ {
+ fail++;
+ printf("seteuid(0) failure\n");
+ }
+ printuids("after seteuid(0)", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+ if (getuid() != realuid)
+ {
+ fail++;
+ printf("MAYDAY! Wrong real uid\n");
+ }
+
+ if (fail)
+ {
+ printf("\nThis system cannot use seteuid\n");
+ exit(1);
+ }
+
+ exit(0);
+}
+
+printuids(str, r, e)
+ char *str;
+ int r, e;
+{
+ printf("%s (should be %d/%d): r/euid=%d/%d\n", str, r, e,
+ getuid(), geteuid());
+}
diff --git a/usr.sbin/sendmail/test/t_setreuid.c b/usr.sbin/sendmail/test/t_setreuid.c
new file mode 100644
index 000000000000..ca9a06f448b6
--- /dev/null
+++ b/usr.sbin/sendmail/test/t_setreuid.c
@@ -0,0 +1,132 @@
+/*
+** This program checks to see if your version of setreuid works.
+** Compile it, make it setuid root, and run it as yourself (NOT as
+** root). If it won't compile or outputs any MAYDAY messages, don't
+** define HASSETREUID in conf.h.
+**
+** Compilation is trivial -- just "cc t_setreuid.c". Make it setuid,
+** root and then execute it as a non-root user.
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#ifdef __hpux
+#define setreuid(r, e) setresuid(r, e, -1)
+#endif
+
+main()
+{
+ int fail = 0;
+ uid_t realuid = getuid();
+
+ printuids("initial uids", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ printf("SETUP ERROR: re-run setuid root\n");
+ exit(1);
+ }
+
+ if (getuid() == 0)
+ {
+ printf("SETUP ERROR: must be run by a non-root user\n");
+ exit(1);
+ }
+
+ if (setreuid(0, 1) < 0)
+ {
+ fail++;
+ printf("setreuid(0, 1) failure\n");
+ }
+ printuids("after setreuid(0, 1)", 0, 1);
+
+ if (geteuid() != 1)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+
+ /* do activity here */
+
+ if (setreuid(-1, 0) < 0)
+ {
+ fail++;
+ printf("setreuid(-1, 0) failure\n");
+ }
+ printuids("after setreuid(-1, 0)", 0, 0);
+ if (setreuid(realuid, 0) < 0)
+ {
+ fail++;
+ printf("setreuid(%d, 0) failure\n", realuid);
+ }
+ printuids("after setreuid(realuid, 0)", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+ if (getuid() != realuid)
+ {
+ fail++;
+ printf("MAYDAY! Wrong real uid\n");
+ }
+ printf("\n");
+
+ if (setreuid(0, 2) < 0)
+ {
+ fail++;
+ printf("setreuid(0, 2) failure\n");
+ }
+ printuids("after setreuid(0, 2)", 0, 2);
+
+ if (geteuid() != 2)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+
+ /* do activity here */
+
+ if (setreuid(-1, 0) < 0)
+ {
+ fail++;
+ printf("setreuid(-1, 0) failure\n");
+ }
+ printuids("after setreuid(-1, 0)", 0, 0);
+ if (setreuid(realuid, 0) < 0)
+ {
+ fail++;
+ printf("setreuid(%d, 0) failure\n", realuid);
+ }
+ printuids("after setreuid(realuid, 0)", realuid, 0);
+
+ if (geteuid() != 0)
+ {
+ fail++;
+ printf("MAYDAY! Wrong effective uid\n");
+ }
+ if (getuid() != realuid)
+ {
+ fail++;
+ printf("MAYDAY! Wrong real uid\n");
+ }
+
+ if (fail)
+ {
+ printf("\nThis system cannot use setreuid\n");
+ exit(1);
+ }
+
+ exit(0);
+}
+
+printuids(str, r, e)
+ char *str;
+ int r, e;
+{
+ printf("%s (should be %d/%d): r/euid=%d/%d\n", str, r, e,
+ getuid(), geteuid());
+}