From: millert Date: Sun, 2 Apr 2000 19:05:36 +0000 (+0000) Subject: stock sendmail 8.10.0 with $Id -> $Sendmail X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=901db8265b172303a79bb3d045b8785ef1163d63;p=openbsd stock sendmail 8.10.0 with $Id -> $Sendmail --- diff --git a/gnu/usr.sbin/sendmail/Build b/gnu/usr.sbin/sendmail/Build new file mode 100644 index 00000000000..580cefc8523 --- /dev/null +++ b/gnu/usr.sbin/sendmail/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.3 1999/09/23 21:31:12 ca Exp $ + +exec make OPTIONS="$*" diff --git a/gnu/usr.sbin/sendmail/FAQ b/gnu/usr.sbin/sendmail/FAQ new file mode 100644 index 00000000000..af51e194902 --- /dev/null +++ b/gnu/usr.sbin/sendmail/FAQ @@ -0,0 +1,8 @@ +The FAQ is no longer maintained with the sendmail release. It is +available at http://www.sendmail.org/faq/ . + +A plain-text version of the questions only, with URLs referring to +the answers, is posted to comp.mail.sendmail on the 10th and 25th +of each month. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/INSTALL b/gnu/usr.sbin/sendmail/INSTALL new file mode 100644 index 00000000000..7973fc6f24c --- /dev/null +++ b/gnu/usr.sbin/sendmail/INSTALL @@ -0,0 +1,33 @@ + + Installing sendmail + +Note: as of sendmail 8.9, a new build architecture is in place that allows +you to use the "Build" shell script in any of the program directories. +On many environments this will do everything for you, no fuss, no muss. + +1. Read all the README files noted in the INTRODUCTION section of the README + file in this top-level directory. + +2. Create any necessary site configuration build files, as noted in + devtools/Site/README. + +3. In the sendmail/ directory, run "sh Build" (see sendmail/README for + details). + +4. In the cf/cf/ directory (that's not a typo), copy whichever .mc file + best matches your environment to config.mc, where config can be any + name. Next, tailor it as explained in cf/README. Then run + "sh Build config.cf". + +5. Back up your current /etc/mail/sendmail.cf and the sendmail binary (whose + location varies from operating system to operating system, but is usually + in /usr/sbin or /usr/lib). + +6. Install config.cf as /etc/mail/sendmail.cf and install the sendmail binary + built in step 3 by cd-ing back to sendmail/ and running "sh Build install". + +7. For each of the associated sendmail utilities (makemap, mailstats, etc.), + read the README in the utility's directory. When you are ready to install + it, back up your installed version and type "sh Build install". + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/KNOWNBUGS b/gnu/usr.sbin/sendmail/KNOWNBUGS new file mode 100644 index 00000000000..6f1a6b6c163 --- /dev/null +++ b/gnu/usr.sbin/sendmail/KNOWNBUGS @@ -0,0 +1,201 @@ + + + K N O W N B U G S I N S E N D M A I L + (for 8.9.3) + + +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.sendmail.org +in /pub/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. + +* \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 weird 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.) + Apparently, this problem is due to linking -lc before -lsocket; + if you are having this problem, check your Makefile. + +* accept() problem on Linux. + + The accept() in sendmail daemon loop can return ETIMEDOUT. An + error is reported to syslog: + + Jun 9 17:14:12 hostname sendmail[207]: NOQUEUE: SYSERR(root): + getrequests: accept: Connection timed out + + "Connection timed out" is not documented as a valid return from + accept(2) and this was believed to be a bug in the Linux kernel. + Later information from the Linux kernel group states that Linux + 2.0 kernels follow RFC1122 while sendmail follows the original BSD + (now POSIX 1003.1g draft) specification. The 2.1.X and later kernels + will follow the POSIX draft. + +* 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. + +* Paths to programs being executed and the mode of program files are + not checked. Essentially, the RunProgramInUnsafeDirPath and + RunWritableProgram bits in the DontBlameSendmail option are always + set. This is not a problem if your system is well managed (that is, + if binaries and system directories are mode 755 instead of something + foolish like 777). + +* 8-bit data in GECOS field + + If the GECOS (personal name) information in the passwd file contains + 8-bit characters, those characters can be included in the message + header, which can cause problems when sending SMTP to hosts that + only accept 7-bit characters. + +* 8->7 bit MIME conversion + + When sendmail is doing 8->7 bit MIME conversions, and the message + contains certain MIME body types that cannot be converted to 7-bit, + sendmail will strip the message to 7-bit. + +* 7->8 bit MIME conversion + + If a message that is encoded as 7-bit MIME is converted to 8-bit and + that message when decoded is illegal (e.g., because of long lines or + illegal characters), sendmail can produce an illegal message. + +* MIME encoded full name phrases in the From: header + + If a full name phrase includes characters from MustQuoteChars, sendmail + will quote the entire full name phrase. If MustQuoteChars includes + characters which are not special characters according to STD 11 (RFC + 822), this quotation can interfere with MIME encoded full name phrases. + By default, sendmail includes the single quote character (') in + MustQuoteChars even though it is not listed as a special character in + STD 11. + +* bestmx map with -z flag truncates the list of MX hosts + + A bestmx map configured with the -z flag will truncate the list + of MX hosts. This prevents creation of strings which are too + long for ruleset parsing. This can have an adverse effect on the + relay_based_on_MX feature. + +* Saving to ~sender/dead.letter fails if su'ed to root + + If ErrorMode is set to print and an error in sending mail occurs, + the normal action is to print a message to the screen and append + the message to a dead.letter file in the sender's home directory. + In the case where the sender is using su to act as root, the file + safety checks prevent sendmail from saving the dead.letter file + because the sender's uid and the current real uid do not match. + +* Berkeley DB 2.X race condition with fcntl() locking + + There is a race condition for Berkeley DB 2.X databases on + operating systems which use fcntl() style locking, such as + Solaris. Sendmail locks the map before calling db_open() to + prevent others from modifying the map while it is being opened. + Unfortunately, Berkeley DB opens the map, closes it, and then + reopens it. fcntl() locking drops the lock when any file + descriptor pointing to the file is closed, even if it is a + different file descriptor than the one used to initially lock + the file. As a result there is a possibility that entries in a + map might not be found during a map rebuild. As a workaround, + you can use makemap to build a map with a new name and then + "mv" the new db file to replace the old one. + + Sleepycat Software has added code to avoid this race condition to + Berkeley DB versions after 2.7.5. + +* File open timeouts not available on hard mounted NFS file systems + + Since SIGALRM does not interrupt an RPC call for hard mounted + NFS file systems, it is impossible to implement a timeout on a file + open operation. Therefore, while the NFS server is not responding, + attempts to open a file on that server will hang. Systems with + local mail delivery and NFS hard mounted home directories should be + avoided, as attempts to open the forward files could hang. + +* Race condition for delivery to setuid files + + Sendmail will deliver to a fail if the file is owned by the DefaultUser + or has the setuid bit set. Unfortunately, some systems clear that bit + when a file is modified. Sendmail compensates by resetting the file mode + back to it's original settings. Unfortunately, there's still a + permission failure race as sendmail checks the permissions before locking + the file. This is unavoidable as sendmail must verify the file is safe + to open before opening it. A file can not be locked until it is open. + +* Potential denial of service attack with AutoRebuildAliases + + There is a potential for a denial of service attack if the + AutoRebuildAliases option is set as a user can kill the sendmail process + while it is rebuilding the aliases file leaving it in an inconsistent + state. This option and it's use is deprecated and will be removed from a + future version of sendmail. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/LICENSE b/gnu/usr.sbin/sendmail/LICENSE new file mode 100644 index 00000000000..702abf87296 --- /dev/null +++ b/gnu/usr.sbin/sendmail/LICENSE @@ -0,0 +1,79 @@ + SENDMAIL LICENSE + +The following license terms and conditions apply, unless a different +license is obtained from Sendmail, Inc., 6425 Christie Ave, Fourth Floor, +Emeryville, CA 94608, or by electronic mail at license@sendmail.com. + +License Terms: + +Use, Modification and Redistribution (including distribution of any +modified or derived work) in source and binary forms is permitted only if +each of the following conditions is met: + +1. Redistributions qualify as "freeware" or "Open Source Software" under + one of the following terms: + + (a) Redistributions are made at no charge beyond the reasonable cost of + materials and delivery. + + (b) Redistributions are accompanied by a copy of the Source Code or by an + irrevocable offer to provide a copy of the Source Code for up to three + years at the cost of materials and delivery. Such redistributions + must allow further use, modification, and redistribution of the Source + Code under substantially the same terms as this license. For the + purposes of redistribution "Source Code" means the complete compilable + and linkable source code of sendmail including all modifications. + +2. Redistributions of source code must retain the copyright notices as they + appear in each source code file, these license terms, and the + disclaimer/limitation of liability set forth as paragraph 6 below. + +3. Redistributions in binary form must reproduce the Copyright Notice, + these license terms, and the disclaimer/limitation of liability set + forth as paragraph 6 below, in the documentation and/or other materials + provided with the distribution. For the purposes of binary distribution + the "Copyright Notice" refers to the following language: + "Copyright (c) 1998-2000 Sendmail, Inc. All rights reserved." + +4. Neither the name of Sendmail, Inc. nor the University of California nor + the names of their contributors may be used to endorse or promote + products derived from this software without specific prior written + permission. The name "sendmail" is a trademark of Sendmail, Inc. + +5. All redistributions must comply with the conditions imposed by the + University of California on certain embedded code, whose copyright + notice and conditions for redistribution are as follows: + + (a) Copyright (c) 1988, 1993 The Regents of the University of + California. All rights reserved. + + (b) Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + (i) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (ii) 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. + + (iii) 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. + +6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY + SENDMAIL, INC. 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 SENDMAIL, INC., THE REGENTS OF THE UNIVERSITY OF + CALIFORNIA 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 DAMAGES. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/Makefile b/gnu/usr.sbin/sendmail/Makefile new file mode 100644 index 00000000000..ba21e875b51 --- /dev/null +++ b/gnu/usr.sbin/sendmail/Makefile @@ -0,0 +1,41 @@ +# $Sendmail: Makefile.dist,v 8.9 1999/09/27 21:39:11 gshapiro Exp $ + +SHELL= /bin/sh +SUBDIRS= libsmutil libsmdb sendmail mail.local mailstats makemap \ + praliases rmail smrsh vacation +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + @for x in $(SUBDIRS); \ + do \ + (cd $$x; echo Making $@ in:; pwd; \ + $(SHELL) $(BUILD) $(OPTIONS)); \ + done + +clean: FRC + @for x in $(SUBDIRS); \ + do \ + (cd $$x; echo Making $@ in:; pwd; \ + $(SHELL) $(BUILD) $(OPTIONS) $@); \ + done + +install: FRC + @for x in $(SUBDIRS); \ + do \ + (cd $$x; echo Making $@ in:; pwd; \ + $(SHELL) $(BUILD) $(OPTIONS) $@); \ + done + +fresh: FRC + @for x in $(SUBDIRS); \ + do \ + (cd $$x; echo Making $@ in:; pwd; \ + $(SHELL) $(BUILD) $(OPTIONS) -c); \ + done + +$(SUBDIRS): FRC + @cd $@; pwd; \ + $(SHELL) $(BUILD) $(OPTIONS) + +FRC: diff --git a/gnu/usr.sbin/sendmail/PGPKEYS b/gnu/usr.sbin/sendmail/PGPKEYS new file mode 100644 index 00000000000..838c13bf2d0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/PGPKEYS @@ -0,0 +1,392 @@ +This file contains the PGP keys used to sign the various versions of +sendmail. You can add them to your PGP keyring using: + +PGP 2.X: pgp -ka PGPKEYS +PGP 5.X: pgpk -a PGPKEYS + +Other versions of PGP may require you to separate each key into a +separate file and add them one at a time. + +Type Bits KeyID Created Expires Algorithm Use +pub 1024 0x16F4CCE9 1999-06-23 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = 18 A4 51 78 CA 72 D4 A7 ED 80 BA 8A C4 98 71 1D +uid Sendmail Security + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGPfreeware 5.0 for non-commercial use + +mQCNAzdxaGsAAAEEALq7JPrdyXCm3DdJEKR9miP8/B9vrferOBoNimPFceDEqCpm +0RiJtnGhUJwt/HZZhiGDWPYTIa7VajfxiEzJ7LZH+/uXgQFVN27fPwoNKCI+7sr3 +FnRs3Xapojn3d3LZSHagTh+VTuG5LxbP/m//sj2Rw1MMPw1b7sApykAW9MzpAAUR +tDJTZW5kbWFpbCBTZWN1cml0eSA8c2VuZG1haWwtc2VjdXJpdHlAc2VuZG1haWwu +b3JnPokAlQMFEDdxaGvAKcpAFvTM6QEB1bsD/jj+vTodXqoJphCrBLwFmwymopZp +/HHu8o8FURlL6jQ6ihCruCw6PxNMzSdgmnOgyXxyRZIVO1pUyWf/RnS/r09tPLlq +nZxdAPquhB2pkawvFp+Y///lb92SgfbS3/dtSDDAJ8FO+CDUKS5dKuZ6vSDU6ezH +BDYjhd6pPYVd5hz3iQCVAwUQN3Fv9XxLZ22gDhVjAQH4BQQAuCNG977A4v0xjQi8 +AJsJmlS5mKMqn/Lw+sl1h4yQwF2vzNDdxhNWjZVziK3lUIUPh86u8m5CSdN2BB1Y +1RawLvyfpl4b9KtyXxF4fh2BYmygJ4iG+WxhpaT5RS0eFvsSefO7/w13bx5U0Z7A +YfHMt7+CKHm7bAx3l17g3I9aCMCJAJUDBRA3cXDdzx61AyIyegEBAeZmA/4zCJxF +aathJ0soRJOcyRDzHKbAqlShF+Mx0tzcwbE3hAZrIqJ3TRK2MbrsBNnkFHPuPF0e +eKr7TQsXOa+ig57wlHsCOc/fd9jLITjSYKxrQuZz3CrNefPKvv6v6Ctc6TT4GwhC +zHglLC9Bfy9zgbv2wHswRvQBmRlCaERH3HLb1okAlQMFEDd41z8j5GLUv3ukIQEB +9WcD/iFFF2kfSTyD+IfcLl4WCaYSeD/q/fAplpOOZWnC9PB1x3YrMHn/H8zd3S5B +05D8+MR/QL8n8/5P+pyHa4VNRbeX8g8E34ocZf48y6FeqGi8qmcTBJDgqUTO5yMu +t+b57G2pAIzasGcoZDqC3aJnFKwPjGRxnUFJaxlogrbUYCNOiQCVAwUQN3jwKW9S +k9ijm6ZVAQEtugP/ewRrMCdhCbWsSUOrYn1a/pfN2KiJbhs0YyOyWbU6RvJiSFY1 +0BNAxYTbymHDOn2UhUhCrUpqatmgCuxmUsoH2Y4AAFC/94/oltwDUfnw6muqqn2K +7AelRBbJ5wUs65pHu8kfzVB5wJh8eDacKFkK0lqgtRQCE0suhqCSFUfvtzuJAJUD +BRA3fTCCXx7Ib4gMnlUBAWddA/oD0RKLIkLspmJC3ccmkncviMSv0rME4vY0NIfm +IC0zsYITlU/E6H/CqVmU4Hmr5hmr5GUNNtrVZ0oLH1PUjobmZcTITJZbQSS2nY02 +N6JZT5BSAwQBfUfSMwURISRQBUOfi1kLqYk3f6UTee37/+Ig2kb388T6ClcXCv82 +FrZuwIkAPwMFEDd9MMTU3njYeCkb2BEC7QAAn2sVWl+Q9a+4a34v827M0O6HpMrL +AJ9bLmUFO/+pyIRb3brK/v1RtERawIkAlQMFEDd9O7oA8tkJ67sbQQEBipcD/2rE +vofXLeEeujkhI13qbDL5dEqPHY19eboF29xBCY1kR9Xqbu6G4Q8pgIHUDg/TRK+w +RdBUjQlDspQEhrM3XEtZ+QJalfk2IoV1Z9uuQM8voYPINnpPe7Q/seibHirMdp4f +J/xLPs3d5gApNtarxwdFOBY3YkHkkoqza1BxmB2YiQA/AwUQN32KFYMCoaE+3wLq +EQK1IwCfR+jVCbESixyB0XR6zDsGf8n4GPoAoM3OjreUcSFSl/4kgaV8DbPNLTVn +iQCVAwUQN32XGgD83u1ILnWNAQGa+AP+KUsOgU8tvJwSiulcU/pXS2gS1N6W54B5 +C3JKioPdgH6lKNO1cOoV6c1ZoG7SFlvsHm2DjRherLEwRhBWkmHlyjLpKW6mYXZ/ +MGLrf74UeTG4bKb0R4As8mLG0z2vqlPNtfyt+8SUoQ2JT0MFRc2FGQChxizenGZS +B7T1MccjIM+JAHUDBRA3fa3dcslC2OpaI3kBAQhhAv9BkSO1zWkxiWc7uLQjO9lf ++YhF9f/SX7/6Od6hKo/YRubK8fcozKXlJ64CJ+iGSMrRIZGXKBIyXyRx5Qed14jK +fGCYzqGv1IpMHIWJPLxJl5Xyi9jIna8yTc6FRWm8aYCJAD8DBRA3gbAczsKIjL9q +TKERAhdDAJwKqcVkm9TBCmutXxwVTcffjINlBgCgrMqc6UOHlUtZps33xWZLgZh4 +awiJAJUDBRA3g9C+TCpm+b/C9j0BAaJMBACskZxjnZbvDgm0qdvESy5+jcluxTh5 +fUeHDpnkfOP0AUAe8Ykwt8syWOQZ+3Midez8JqTAu+uvNbUckuR5XL8nMYpN06og +jg1TCgjLito6IptqYUZgWFvGDCdDgC+m8vw7pUbqh59mDTe0X5Q/x9Cu5JxfhxnX +TNBQ+pI8lLAmsYkAlQMFEDeD0Jt3HZKuiXLHwQEBMZoD/2FaLFJ03tEAfNQhLmSg +unWVakXz8udE+pY7IWi6LJGu5iwtIDJ/r0nCrJ6/aqzu9JLpGhfTnhPPCXlz4Nfh +riRz12cv2Rlg+gI3Y0Fiju5eo5TWnu+qB36vQsv73xpfQ7oCmoVY2ZntQVBaf8dy +FrAdFBf1y33xWo58zRsg2u2h +=g1qL +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +pub 1024 0xA39BA655 1999-01-04 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = 25 73 4C 8E 94 B1 E8 EA EA 9B A4 D6 00 51 C3 71 +uid Sendmail Signing Key/1999 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3a + +mQCNAzaRMIoAAAEEAMWVJpGkwKWD6GFDUHtV6AUDzwSAXiWc6UinY7EpCLwFdYu9 +Le06VwQt8H9Xtb/2jrXDV61Wu0IDJub6g7PZxWxU8WHVnMX4aBT5WOCBpwFRme3u +idwCAbHuEJs12FQ3Tf+4CZ3R9uxlAovRaY6g3fJ7gtAc9HAjMW9Sk9ijm6ZVAAUR +tDFTZW5kbWFpbCBTaWduaW5nIEtleS8xOTk5IDxzZW5kbWFpbEBTZW5kbWFpbC5P +Ukc+iQCVAwUQNpEwi29Sk9ijm6ZVAQF3LQQAgpuD3UA69w5FjCAfY1iYBsaGJ31V +1IyFQbo5fAnVo8PMQzioqbsn2U1y1rRkf//gt8T5oVo6Q3e5oWQF/vcruEP2WUSZ +1BkV7zDWLsa6octYIEt4Rdr6gBxokzP0/Z7Ck0WOfSxEAGXbHZ6NpbcfNdIZAxhZ +WPqcem3zEwoK/l2JAJUDBRA2kTK271iWZNQy4Z0BAQltA/9b1Xtp6Sqr8LtBAUax +ziRYYmlIENgkYJGPrF5iB17d1M+aMyJ1IzdjKHaoa2+WpWYhzT7RalcxkrvXZEN7 +hTC5XqsmkGXeg2oiwJPCVTUoJY0goJKiMXI/zYcLGAxTnYr3rUevr+vOQyXPx6Ld +AUCXcsD8LFQWR9iQTgTOBVSOhYkAlQMFEDaRMloj5GLUv3ukIQEBjh4D/RbqKENF +51C6DrwE5IJrpIZ227mQwFzu3olcF3v0sOoHv9Iqw0iebEM8D9z2t6XiGNSgfmQy +EUhQ2gTLfbkz9lSUjUaH+ziN10SXSd0x63n2xqrk9XaG8YCWJOcMe+N5Gh7UGniS +UD9XQNBLoqnOL1FpScAC3F+KsH4kCKLQD1KJiQCVAwUQNpEwwXxLZ22gDhVjAQEC +GAP8Cle48mxG5TcrAglAXs25YBLhHK21tnSWrd8j0PdID7+9AKongjZOKxyAnFkZ +RNXDArmG+FVA0DAJatiFXikqpgyHAM/QKSCSjBEOru3Og+3qV/oFQjAVPfLQbFPb +6i1TIWzvYTp9L4TlzqUM3OF51Mx07W1S+qCciozA/0GqFGiJAJUDBRA2kTthAPLZ +Ceu7G0EBARPzBACbuAlTHMobN3Lw3YvsOUgwWHFLqKXLNTu59ozZUL4da/E+Aszj +MgE8343pV9Nwm/aHGXRNiAEOftrb+DdU1jcaFgwsrWnXK9NmnpAYbMkoOb8Om1Nx +E/5u0dIxypXO8ziyQIfkElsOVzhPzct9wZKh4qt2uLGcVWXeFnf23VRb4IkAlAMF +EDaRU60Gfl7Yv7VlaQEB46QD+IGxaViR7rQv6r1sAZJzxC6vMpMK5tgk/47gC6jm +8STb2DYvz/5KNYTkUDRB/85Uy8jY8jabkalWBNN6z/Cpod9ysSjSOKNBQ+6MMhXc +qXWKakxZIa0rIVNEYaRTAbVU4J1aXRdh7BtC2nEqf3SQD3c9HDLA3p1W8g8ZyHwr +QXqJAJUDBRA2kVJAXx7Ib4gMnlUBAX7IA/4mKF8EGahmbNXA8wcH4K2r6LzRLXsE +f444U7hWQRW1fCxDJz4DOodUO3aENzzWjfxL8BtoosuDTJeKGXoa+5S9bCmtaksm +86G20UuDx/vt1Ol+hZFW8q+bSS2bsAKLvXZVDnURtDu6nzdNR6Lt61ahsUDo4nLw +iiKUZeMdE2S+H4kAdQMFEDaRV+is4VzBBNt7HQEBLbMC/2wuZQqaLrLUm5raynph +rllKT+mQQSTedTACKjnpT4LE65YYGGFDrIMS151lQ1OVvu0DpGzmQ5b9kFNGp0GZ +giXndPbvmwPpOn4ONmCo/zZFWryNQKuqPn2EN4rPhngjRokAPwMFEDaRbhPU3njY +eCkb2BECLnMAn3t8IsH2yr+vd+1IWstXMCUwzBZnAKCtq5l+00/EYeH8PXhrhIIS +9EquTokAdQMFEDaRvApyyULY6lojeQEBQa8DALEmw8SIvCjwo55yu9p26czt/ohn +D1IdJPepf1H5X+QY99kUpsxb+Csnz5VSfNz7dSJxvhwsB0gJityk/YX8uOcEfvsK +NsABSN/fcLCnzlwO0SNGDPJc4KHTFXHfVy4SgA== +=f3oA +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +pub 1024 0xD432E19D 1998-03-14 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = F9 32 40 A1 3B 3A B6 DE B2 98 6A 70 AF 54 9D 26 +uid Sendmail Signing Key/1998 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGP for Personal Privacy 5.0 + +mQCNAzUKkdIAAAEEAKvdxY+iy7eLqxP5StbpZuxYNPWLye98bXA8oKwrEm1vy7Xq +LBg3uNXjlMtwcNW/r+oFu5A++2R+1qC7w/0867C+52D2zkfGRH3hn9Lh6YaA5uIP +LPbMGB3Tepbtj/lAtOJb7JKdybF7fkxkEUmwhuA5kAo1rKKWNu9YlmTUMuGdAAUT +tDFTZW5kbWFpbCBTaWduaW5nIEtleS8xOTk4IDxzZW5kbWFpbEBTZW5kbWFpbC5P +Ukc+iQCVAwUQNQqUqXxLZ22gDhVjAQHaYQQAiFITCRAEKhLlgjcFlehTDmVMFb92 +1jiclN6377xe+A2zEtq4p3R8IwwiVTGeBzs0Zmnrlo+fAdVFYBjIYCtwKVTwd72U +v6kxX40CjNkx6q264hUjILOumQ2P85/Aqg7wmnK9vM85CkmhKwu7b1OHsY+EFAlo +U9CWyVjwSQqzHnaJAJUDBRA1CpJ4I+Ri1L97pCEBAcRtA/0czuj3hK7YiVL3zZaV +EUnqw30auexjm0D+LhPpsHN7OM3im3z4+/4Pv2O2CH7nZhAsgRN9N+qdf3fCVGHq +Y/ULkdsxKNbPEjSEWI+dqUWj6EyMSewKvBo7Zvljii6tBsM48ohtkWTo4B1/SuJb +FM5TgXu2PMTgWHsT2DFb82wb/YkAlQMFEDUKkmfBnB0lEtNGHQEBmCwEALZgc6V1 +mvRL/dqtGwdt38Uuw430cdM1Nk0FlkQsGXVWY49A1yrLAcuPQi8wzx4GS0LhtIeo +vmrQ91DBaKxvxkboqM4orYf7PB5exSS9RQlTN2ezaf6IT9hVJHtXoYxU51Iny7hp +r5t8L7od0gue9SNsLWjW9PZH1eKz83/g5VJZiQCVAwUQNQqSVu9YlmTUMuGdAQEv +nwP9GvBao9wPX0r1aplZgkUItDwWGBbF8qQLgX5rM8b8IAxvHboIp8fbCkzhVxI7 +v0IdYc0u1hrY3YfCNNbELu09JEcvtsl3hhmXnalOxCEdjoMUiHSb5f04sTBNOhD6 +IWQqixDizoVzW5XljHBvgxWJhBus/dPJ6hdZPahioVd0oLiJAJUDBRA1CqZRAPLZ +Ceu7G0EBAYlJBACumnB7zeAOpuj0y9h0Cgh0DleNWnqpHzTus4lbt3vw/cMpKmXt +nGxMb4HE9rp6CHuuy3NumH9JHa9lwgb0T6bc0Zbc+LX1j0tKMC4BIsfEbFiOMSXU +P+meyMUGY67VysVEeTqCgG4FqK7yOhnJsxjwDxJTIlrMoYwSSmsF4/R8Y4kAlQMF +EDULPLgGfl7Yv7VlaQEBWZ0EALAGPhQbVEPTp2Hfm76ZRWjYJ8iDn98znfsHRYhS +A/yIXF17eDtSkYU/ANOPNT8g5fOCWKjfLTJX4Al78rbHeGeKS+eO21WQCh8AF7Bv +vZZWJZ0CyNnO++hzyamsOG1Z5Lrt/WQQPK4Jv5ZyqK3f2nGDufHuyQuIXxsdd+BX +oqp3iQEVAwUQNQwe/ReiaPz3pQGjAQFowAgAk2fARyp4iyRl89ZZHGY09HpRbwQS +4jeDIEkBPBpSCBXIELgR7UonSoTwHD0nGHuwgdil5Zjl3PAlQJdo47Sh+hLCMoN/ +mg0aI0vSnOxnnVgIcAigzlEAe03R12frWp32SjXJE1GdeFQWlzkk/6BoujKybvI1 +oRr8OeAb8WzwmUr0c4VITEdb/J5c85yriHIuWpqYWIq5gb7evdj6JTKXly3gFp9R +bwwd2tjlHYu6O7dHuEsmm4n4iK3rEglILvWIoS4kVV80v6IUE3xgLAVf7tnF5iNc +nXcA386xUBB17zNvJDiUrciX17TuZsIVvIQnB519NN/ZVr1KpHSbLgMyZokBFQMF +EDUMH1shtWni44zO8QEBGOEH+gKn6blq8L2AJ7Q2Pcw26Do4J9xlRPFKrDgAgy6y +U9x509y4BeAZ6yn9RV0iGwhgzbdd57QrUpgcYNKGXSC/tJZZj2h3CZ06m1zaGtJ0 +ig0dN7MU9gqZZMLy9f1EZmCwXeZHXL8t8lUMv8KEoq8+vvghCRvDNUgyQpkwcIOh +rSu9yJ+OeJ8SpucL0ebJE3MmP2JYmqBCBg3pbr8bWvzjZ2Ny40OiyRnuXFP/jC2f +ll6oMi8rOpWhjTTuHyrWEG9AxI8xeI5WsEOrJHH6stlmXJM1NtlJQ0D3qCdLn81M +vitLgTPb/xUepRkFdBhZESG5BPDwT5hm1w7m7yhVohcH8AOJAJUDBRA1C3M0THwE +EmD/AfUBAbzlA/9nDPPyBD9T1ygEHBsS2ZztO7enSk9DaYmt2jsqQ413UnpbhybR +zZiuHXpqgG1p5GkYjP2Cw1DtT/dHu2nrD6Mf9j/4QYaRi0sdWLMTKVFPDlT+j1G0 +Ag7/yCMhPv2xr3JOLPppCFiYPkdqRfmKnCWdCtrXmBvu4EiLTj1IXtc1WIkAlQMF +EDUMLbdfHshviAyeVQEBQOUD/0QsDaDnzgcQHbtvJvDM0x+JYuejbvQEXh6k/cDP +dLIC8XLZMd0uuAWE12SL1pm6J0q6+csKELascFKyOWTRoNrkWC5m1ltgRuyfXq3z +Ur9SfL0KlfWFLXRsmGRd5V37u5H9kRjeTRlyiOeAcAMzaLunI9dK8sWet4p03GLy +GOHQiQCVAwUQNQrIVW2DN4pRurLtAQG7gQP6AxTbsJ3Az+bwEgymYYo7EWADJGoB +e1r48/0YjocxddhcXJSGL5dRNqY8NURSyvw/dDtjH81mVIbRlZR0QS4D2Jp94Q5/ +mrWyqBW6Ah1EFtihncY3o/g1sxEC0hIj0/CklQmNttxeIGt1rRVyKxHa0tYkDtNW +w+y5xZQSkE0yin2JAJUDBRA1CrJtdMsnjUUcGpkBAQ11A/4rp8Oy2cVbkrHHIxxM +2dML/tqNOgOGaB5tEISgtpv9xy1sVuEEA5T6rQJefeC0K00M3Mb3Sy4uumSaX3Io +yTQr3XD3FZ4Q0n0AWR0ppRBvepqINfn/yeNF7268SDIMstQjlD9GzyCobqrR+VLT +pxF7wXqyHcLyfqQjRiM9ZNTzAokAlQMFEDUKyAd3HZKuiXLHwQEB0+cEAJ308jCg +rgWPcSstZH8Q8AoQajdxYMqImoQaqxC8zWjX7BK57pEFLelI3uXqkeEyqIGH0Yqc +SvHQSSe2vLe3DohfGraCL2VK+b3Dw9IOaff4+ZFlxLVsqNiq13Z6aqRuKJ5uNjhI +0q9PPBZ8xzOMGfa3cMmW18INJvrVyTu3ENXUiQCVAgUQNQqcZHfUAfkkYu7tAQFr +tAQA45cSUfYgq3d0RGx3RLUL0H+Bku5xMH2YuRJfpEI/Oc0Z1l/G7AfoR0pTqo9p +uCu21glCUWm4TvUEaGJjT7q2pmcoLO3LCavNVAZHNTPQvjJgu/Z8+290yR9Ln/f8 +4F1/zcRe4Gakq2weDM+h3gH914vXW7FoGJePc1X+azQ7pYCJARUDBRA1DBz15mc5 +PORZW/UBATL3B/0aknENUHmJ6+axITL1ZODUe/KqFmLRgvCl2g///FtMHlMCUyWy +q+MkyiHyjbgh1eN6gsCHUSHiROQdXMRRSxZm4FVsjznisjybCqzd93lBQQyKJ6XX +KWu9SjJq/b6yg83byTgHZRW6kwjmDal97kVyHtV1WZBGDJ+v9nCY2tSvqujtNQbJ +LWrHp447BSIXBBpMkF/J+cbl7yZLiUN8I1SnLYYttmKOtfD33eL41oKT2LK+j8sI +kCd4XbcGoMJ+DExDVhFeiwwXWzomvTP42Wv0b8DYI+xeuE+AyARxJ5AVbGUBl4sZ +qVuNMDZWhc0GLpT10RUeJ5HJVAGIWB2fLIsE +=ljft +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +pub 1024 0x12D3461D 1997-05-07 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = CA AE F2 94 3B 1D 41 3C 94 7B 72 5F AE 0B 6A 11 +uid Sendmail Signing Key/1997 + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGP for Personal Privacy 5.0 + +mQCNAzNwqnIAAAEEAL1KqbRgVm9kp9OHLkKGb1tbT8rwEIeeh8KKSKJyDFiV6lZG +wbEa8OC5vokXvjsJtJvvhMfrG5OYc1Q1sLzPXXBYzenzXFrPaXDO8F9DE8B5VTuy +yY7g3LVr0VZYfi+ZsNdOFGNLdwLz6a8GHBHdmAn6z+FKjMSbdMGcHSUS00YdAAUR +tDFTZW5kbWFpbCBTaWduaW5nIEtleS8xOTk3IDxzZW5kbWFpbEBTZW5kbWFpbC5P +Ukc+iQCVAwUQM3D1KcGcHSUS00YdAQGKTgP9E9r2jv1hB+q5yvJKyTWHiIS8oU5W +eLzdoFlRJUw74M5WBh0/AkcTMfv0BpCDMxu4zskDJ7L+urFRIsf9op5w6YjdsM15 +AvuCtWqgExRkdoac9WRCFNZ77WPQ4ul018k9EIpurIPaojLs5j2Q0+9vOXrtJmXj +S72Ol9nQFU/hl46JAHUDBRAzcoIxrOFcwQTbex0BAXvAAv4yS5fkL38pJTUJrijI +XhaHLV1Rq3XfTdQ2HuMG+rF9nxdBCz3a/YCWJSPvE11sINDTSni43BwbsXWqaxvs +UKD2fqgXB88zueY7rOt8rqi+PRMZ95QUFTgUP0kAN2+U2SmJAJUDBRAzcYIwAPLZ +Ceu7G0EBAdysBAClk5f+3LazjkjGZiEVRPBKyUYJDqx0j9phgVkqWRje9ot/ya4z +N+Zm8e+MGyIk6BfMi1QluMJUqPGY1p/mvLPMkiKhwYXHG3kymto8CMSF415mLxIP +/6P3SwCyRzJeEcBxKgXlwDwelj2joa1fWZH+rC1ZuZ5FCaiiyKvjSCqb5okAlQMF +EDNx7IPhx4Y6UUEd4QEBrfED/0tP5eMU4G4CDEAyV6susGl8WUSJCkfGjK8Z22V1 +vM4TLiVLSf7cec5tE6iau8IzumBgRV2kQWOz0+q1VBOStUOJQCGfwC81ou+74eTt +ThL8m9oJ44Y0JrQpztW7iBqU0KYsAgf95BtArvTqKqG2kLTlBVbjwb6PBqkyzm3C +6ZbMiQCVAwUQM3Gq0iluPWNaXACpAQFikwQAxYQKEPFIzF/5SyMiktsuNNLMYolh +UsNEUpU63+Yxhr9ofK7dMZFwaTHaEnCZ/zhjRRA6R+BjBOmnkD/W7fG/i94naJRV +rMejqJhfZhHYqbMN07yxGdjV47neghSoN4zddZdfLq4gEPD+MN3rVTDnO+xpHzLP +4jxqAda/0eKSFQyJAHUDBRAzcZsLcslC2OpaI3kBAX9cAv9K9QaxgI8kjyVJkVxY +KJuYE9PPXgjmQvqx7gS+HFm97ZTROEYhhNek7EFD+XJpVQ62KlQxNUaWe4VnNmZN +2QQyvRhNvE0bPC+rBKoi6np6Vha0NqWDA80xos3oswpj/+iJAJUDBRAzcRiTBn5e +2L+1ZWkBAY5YBACLvAw9AoqvMqnUVR4aXSkzK+s5aQG9hDDHac2FWsG66HLhh+Ux +HI5Cvnke7CF+qglNzDU7HpoIdDFovRgQkfGnB/I7Cy6ax1aRJpLc+JNXkwbDDcZw +9sXnMMymNl4xn0vUOyrnT2GIwLwFL/t5JIUqovm3mZ2SpL3FxKNWyxgDX4kAlQMF +EDNw+VVfHshviAyeVQEBrtsD/AtwAvvAduNZMFL9du224fvVZ16of9P5vLVB6tF3 +WKvo39FsFjOLr1xgZn5TWc09i1sVK6swi8O+IgcNLq7CLxRYaXpTjObbphktDVnU +2uWwc3wHzFA7nNAT9ACEa7gDc1GxFrJQ6QyjJVK4f2n3EyJxc9E1rBIoCSNnmBHh +vqJViQCVAwUQM3D6ZHcdkq6JcsfBAQGNFQP8CeATNOacSrL+x7JaFf2AlANLwZAo +G68VE/JMcUgGBCZdo6cptg1uBFgzWaOVq+aQU7AKkwLmbyMvCX04PS0tswnkSl5w +DTLgSmmOH5elIWWrv5J9MXrlsniIzc1MSokENMOaKIEWuC4yCgE00nBj8q2GfDRh +J816g1ndGU9zErmJAJUDBRAzcZZKH9vgQ8ZSyXEBAT6zBACDaXRCrBqqCmjIZ/xN +EQcXQF6VKoDFfMUXSgvRaJP0LRuBmbRuWQRZe+OIGA7vKWtvPti40bm3O4b8rESG +MMAxARn2PS7VPfOhrRNaVGV/s3NX8GkrPxYD+MuFVHoI3QKiKa/fzxDYMX3rTh6X +4ISe4cS5O/J6VCEKIjPvoVVFF4kAlQMFEDNxljgoffu9cgNgzQEBEyoD/3Ca0oBU +AuCJUsrPyFYVr5r9FYOWtvOZ/b8IynIXjxD2Lin9AlX2ijLFDJR0lbDoBVPM4IVt +4rb/yr9D71LU3plxKn+G9JdFpNK9IWJGqsn8iRmbnoERbbVzvZHVx6qA4qvRTt8s +TJYN+ueKng42DVvZVZQLWZv9mdDUKH9i7r7/iQCVAwUQM3EH4IY/IR3IPsbJAQG+ +pgP7B8mo+OP0lN6KRK83pje5wctThDHF7OMW9tSKXMqGUMEa8+GWrOrazyT+5R30 +cOHUnz3iNkjHaO2/3jLZ7VZTrewYGD7VSg5d5RW9PMCSm+MaJiHLVWKxS3exHHWK +b62c3mao1zRz5Oj468cRXnHABNaLt3CmMVvKUpAi3d/W7V2JARUDBRAzcQGwIbVp +4uOMzvEBAZc6B/0eqipGA88c3bxT0NXZoQtePdVen6Ub3BJiR72E3YA2kZx4Bi1B +pcJIAw/HhRx9vkc3EmwJkPCn1o1pnYnuMZTgGYH3KAV6WFsT/Yqp0KaHYLzHLCJP +CVKI29DClbI+LOw3sHWuG9ZHK/y26ue3Bd16dJzs7Wa3ryyqeZGi3gWijHbtVcgA +laNicb0QuWcMXsNYy2E62kP7tZIRR88cv3KVOlbEB/qEOZ8tYbk5UaI6ccZfIO2c +Oyo2xakKmw92DyqRdbNKbf6yFZLPYJbGZHsJeI89m+MyU+av7iIhh/ky1mSrZW63 +dPnQvE6sw2BpFS6L3hmtArLHWJKBSm8N3vobiQCVAwUQM3D5Rb3aj9Y/6n39AQGw +owP+Iu/HfZLks9GdaTXata1YEwC42GJFxB3+8Pgy+ZOimffkF/CFlYWBthD9Zwqb +NEQanNqQGLOtHgCX4JFLia+FktAX2hy92ciTcSFG9sVsaEHrWnjQRfh4OhqJa/D6 +rtud9sPWjx7TY2s+8BDZxjgNnq+gTCDnhRKvpsLHl9BogAyJAJUDBRAzcPU2I+Ri +1L97pCEBAYxXA/0cleagkyPhJZoZ2PfqtB3iN9/OcFLZCC4HDTdtpdOundLMTZe3 +WtjCdETnLCXQGOMghdf9fnuU6Em5xPDnXRi+xvMo1/WN+m5n/xfui6qZtUBrZp2D +35OUFjD6Wr2DGthKb1263P0pbdcCUAZkvqgTHasJfMeSDZR9bAcz77o7YYkAlQMF +EDUKj4B8S2dtoA4VYwEBHSkEAMOsCwolhlXpbhG1tz35lxdMa/dBCB+JokHvGH5B +JZNEARGpjlA7Q6oEYGtpTuIwj2lRqgiS7d3M/qCKL0HlrlMDOcBbNdjC6JZuVgnA +LEG2m+r6YZlLratpkK9rI/SeSpwz2AfmrC89PI+C9Pcysj+EH4hV8WyETjcNA0le +5UANiQA/AwUQNNg0q1F+HqlP3KvBEQIVngCguFDiBO3ZJR9RN9L0Vmg+/yMX7KMA +n2tSLsf98uStHSQOzboE0KgghjybiQCVAwUQM8wrnM7nzgldNyzFAQFfGAP8DWSO +R5ELTdPUugVgB26FStcadMS44is1JWwRT8NkRiewBP1cvVwS3c6zS75qdXNoAz3g +UklXw90/CeviKHNA1wHOupsMCxwPqy91Uo5SOT49vTOuHZ5HQxY17WfTgFXUUFx7 +RQTB+ga9BpGedHq0Fm5kfvH4L4Fdn1vOpEmsakg= +=9d88 +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +pub 1024 0xBF7BA421 1995-02-23 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = C0 28 E6 7B 13 5B 29 02 6F 7E 43 3A 48 4F 45 29 +uid Eric P. Allman + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGP for Personal Privacy 5.0 + +mQCNAy9MzZsAAAEEAK3o3N9W8Ynb47vNtIqUvdjYYl/nEt/hddhumsDNqt/icanP +7x9VTS1bCfKmAEQ86DSkWRWZmhIpExbcqmuRtixn/RfDHzJ4hU/wAd6kAzUTVIfY +wLC5NinszKoaqlBWlQkWKW/2GbryLmYIRhIDOKkIBxSgskpShSPkYtS/e6QhAAUR +tCVFcmljIFAuIEFsbG1hbiA8ZXJpY0BJblJlZmVyZW5jZS5DT00+iQCVAwUQMv+v +Pr3aj9Y/6n39AQF3hAQApIJUr5W7b1wvi+WVGVc9iWtmKB3U/O7iddjeqeOWCx+P +6XgD94rkSanFbfCT4Sq8HQNbtTDtBVYFU0SD6GTH5SZ93FUQ6h0OAW5cueHGnfH6 +s+a2N87pPVKxh/brycLvr08to2TvRTbxbebPkF6UWOlurdPI1Ga4kgLZF0Ppwd6J +AJUDBRAyWFEdXuWsrmbLc90BAaE6BACqO5uGZQ1rLrFxOi9ljDghYmDRLFI0x1ls +NWh//FAGduRs3N+NemP715N/8vH4n+nY0u0xfPDMi5UklmD1l4EHJlHxNvrXNnQl +I7gLkkKxvCly/hjbKiMciDtpnUYGa8dgSy/nru6J8QSpOhXbs+UeMsY8xtPYTZqp +e5fNjWhVJrQjRXJpYyBQLiBBbGxtYW4gPGVyaWNAUmVmZXJlbmNlLkNPTT6JAJUD +BRAyHkUOgEp1EPeh9ysBAZxGBACWWXNNwG/3fWmGFhDi0eFVSQXbIPK9nOk6/kSM +5hKqESarPrLsVNapNu5s2BSac4qi6xrrV+4SCEcEkkfESbG/3nXx6ieuxswLim03 +BTHvsceFjjPUN9X+Hny0LEbHbcwACHPq+yGgQ9kEYLmzMM6/9kaIy+56Iy/PbAyT +ARKGOrQgRXJpYyBQLiBBbGxtYW4gPGVyaWNAVXNlbml4Lk9SRz60IkVyaWMgUC4g +QWxsbWFuIDxlcmljQFNlbmRtYWlsLk9SRz6JAD8DBRA0qiAaXtpa2zmNWFARAkMb +AJ9sSKb6Aj1fwF8QyDH5rArzoWOXYgCgj0OcgAVTjMHV1BaAKDvq+dfASKG0JUVy +aWMgUC4gQWxsbWFuIDxlcmljQENTLkJlcmtlbGV5LkVEVT6JANUDBRAxPmCOSSSp +RrHt/oUBAVdpBf9fXDKX23m0mI35fy8GkH2n6p+2j+r5fTCsJr0ShtXA1E8BS3XR +Z9wPPbi925UoT0uBc8bAZhSwMMX19hVKyvo8tjmy3nRhhjfOZKTprjAGHDOQnfce +UY2URhmM2ELkKioY3jVYnoTSiL5tLXDUfii/frwEG7ZY31LW1YErCKMl4lqlZucK +XF7n7gijTPebGAYckU2XP1y0n5YZrNq4WQBv+6wgDD4wqtDiyCG1/O2jh7eJ1UDF +3FvDOEfdcgKoID2JAJUDBRAvbcy3g3t4fqRAn2UBAW2nBACXg7tSyMU+Jj9NBrjg +DLnYEoKWV0F++dWHqM0WisDOCwU+v51BUP/VJdqEwWc6CdUrbNbTHCVCG/3D0set +DuvmkxBKpBsljN7gxDTfUEMciCrdtlEh/jJ5YZ1ofSujxIHjYZ6OJg/4x9AgdJ5O +EsDUvK2fEI3+dFGRYrw2XUOqeokAVQMFEC9SbfUeUtMXXNLGGQEBz58B/AuGcYU/ +mNixrR5QYndJVmarw/0ewfRJMXzYXCn+9TFYy8gul9K6Mu3/zv3Z2BzB92sdsbVC +rXlcazNrR/gedMGJAJUDBRAvUm2lI+Ri1L97pCEBAdDhA/9YP8KoUDp/YmSekMBU +4myhSpFsCW5Fs6I07Cwn84Q/hkZ9myG+rGxUltBry2Z7CMcwQABa9D254FjV/BR6 +eVIgADSBIR2U3DSrEgSP0qGdT5yFCrbP5HOge59/b/0CknBlDvBLLD3HW+OrwOaQ +cF/4gBUnbMJ01gZEY36IFgXsvokAdQMFEC/gXgxqmwnIWCbPjQEBQwIDAJRi8+tW +be7gQpW5ZSriDbss6J3/dd/WDspD4WnwnoiNMFKzVDVRbZGAMjsSqsLCJSywdIus +P7eLs0kayCx0ov7UcF/O6N0MYw/jy6NkFtiSND6TqtJ7Pc2SZcjetbpIkA== +=StEG +-----END PGP PUBLIC KEY BLOCK----- + +Type Bits KeyID Created Expires Algorithm Use +sec+ 1024 0xA00E1563 1998-03-07 ---------- RSA Sign & Encrypt +f16 Fingerprint16 = 66 39 58 9A 83 5F 52 26 88 E4 59 36 5A 94 D9 48 +uid Gregory Neil Shapiro +uid Gregory Neil Shapiro + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: PGP for Personal Privacy 5.0 + +mQCNAzUB04kAAAEEANHOOWZH9BdsPi8071kHB49qWAWL7OjoUk2NpItw5D9o/sRa +jZbBwtvPSjx+/cC1Nka+apIuXGccjBzpu71DJFLxIYEk+MW33bSgymI19utPS1b7 +yHetCa6T3ggBsdSH3+gLbyK0bt+suRxxiAC6719HqHvUxuGWnHxLZ22gDhVjAAUR +tCxHcmVnb3J5IE5laWwgU2hhcGlybyA8Z3NoYXBpcm9Ac2VuZG1haWwub3JnPokA +lQMFEDUB04l8S2dtoA4VYwEBL7gEAIcDsmzwlzI5+KYILkeUmoOWeoOunDZ7ZRv9 +KvATWccEJdcdjGk4VPKtAGYWgPJBweLAaeZBHo5+cB/w4Ho+sPavHJoaXqk20u5T +AtIv/DUKcPcE6MVvOYuWUsnHGuWDeSke/KKA1uRw7KEn8vDlBYktUres8ifHLGy0 +JM+aEs26iQCVAwUQNQnbcr3aj9Y/6n39AQGzkgQAhcwsoDO9Rl2oQSUYZpvcxUHF +rroqSQFejRRfTCT2a3ejQDckeFTqT2VcLGv+QH+7sQFnRAlJrTWU6U/BoLsf3qnu +dSijd2DiiCTQ5F88SBQjlRyxvXpQXOWGlmemmkV6kry/px4MaFAyF/35HCo0Rzd9 +S0brLFgrCiTzAS7/wRCJAJUDBRA1Cd2jI+Ri1L97pCEBAYw4BACh5m75gsGcClEX +LUcxIOaANG2YNSr9r1lmHxcDq0V3Gpv02IauADL1+DX6o3sD+dX+WJxyAM7F8QBC +up2ZtADL1uxiGz+AarDT4qzXyUeQnB47tkhPTnlcO60srtgkRKNex+lAuzzbWSAT +vZpS4C90ZJASwMGr+M73V/66cwKA/4kAlQMFEDUVydtfHshviAyeVQEBwUMD/AoR +E9p0DSgbPpSdojFok7BEe8fHLwJR31fBWetLOk5nsHuAHWBCasO9bmjgG8vls8YS +iTkoJAMxXN03i1bRNL5X3F5Ex1HzrkjEsn51Fcx4Jyp3blXlf4yOBN2t+2DM8DfR +vy1yVrvKtZ1TEhjM0zoG1DqjN8zf/hG23t+1rGZ3iQEVAwUQNRXjouNaWM2W6V8r +AQEHowf/ZTBh0jzRC+oJHb/uewa/vnufEFeWoGZt5U9KZoKooUcZZ82RyZhzJzC2 +/5zQQQI9vY+Gh/bL+o7Eaj8+FlbXN9N31E/BhxTtR/v2FTr0HHn/kXKriG/Wjwpr +Rj2hF9fu5HTVD0Bp3A/uQ4bUO9xT7edKGtQWgXEN77/xbD+LGrZ8CTFSohA+WIyr +tgwL214ASBDv8j++V4lpTkzyJSjuFTL019hsjkeE4FvCXbELfvsVX0SOZK9Q45I+ +sgvsAZ0BBpasfaY47WShYGhTvvp2r/Z8xgy2erw4vhKz3jJCVmkK1cmAM0IvhwFn +LSYfxI/T/1zEUj+56XTMc4C3dltXfYkAlQMFEDUV9Q08YShHTKshIQEBY7cD/2Rw +Bu6ZJAoJaGKzbBOwEQG2JV3/o5W0Z/Tfy9x3kUDecgqEKN2M0b9zCkzCprotGNhJ +3KXvva3XL2H9AlJd5aorcmvNSph38rPlP35Tt3xWXMBrB1CNR79WMZU+Wx1TlJMf +i8EFURUkjD9WXRsn5P9ncPPKBGcCJ3MfA4LQvvvqiQCVAwUQNRZkreTJ6ktPts0d +AQGsMwP/beohoVn7bcp9kkYW0d3mAlbZyrDzbi6Q+C0lS9s67g4k/QzWLY8vZAYc +ywC2KDQjoc1mnw1bJ+S6u5WmMTnfrmXs8vUMpmM3no+ZIlk8FB6tdkKcIu3yuAd9 +CFz62uxnekRRCoIFnWadeZSyxOmdxtO99MUaM9D8Ob1fOH6vPWOJAJUDBRA1GUPT +vFYqkcU0pUkBAXQVA/42rM5+DyOA2VoCCkYa0VgIuA5ECROFnwigcY8mxQx9D/Xv +30Z0ePR4Bigur/eXqCC0Tt0cy213SUpED38xsXtmchK2lpCH5RlIwbr2SZKNWGSZ +jGlSCRbLT2xo+WYxvXcUL0q4NYgG5gXG4lXUf8yyuo/MztQlBkPsoO2SLLX3MIkA +dQMFEDVqLI6s4VzBBNt7HQEB/asC/igF9ebzNWnIlug1gienj8d31znRL1YKcn0h +e5b5N2XPIXQ3cOBQxlufuHVZKL0Cir5MSozxnEsavqKSGhGQuEnvv6lbYh0/OJgo +eB40EDPnPGjv6kcexzOB4rUOYr46w4kAlQMFEDVq3TUpbj1jWlwAqQEBqKQEAL9n +C6RFsBFabbAw0ScsmW9ir/0Zz28pBmxMkUY8RL9Kk6jEkwCa3phztMao3qGajqXd +iw5hzfAOdY+eWPXq/sqE2f81uU2TaFCsVq++rAcDqxhZ1p47xfGcBtVBTpgAl+9s +8h33IsggglCumuhBkyCwOBFZ2JiN+BUAv6LbUvBWiQCVAwUQNYgrcJqnRzvJFyx1 +AQGiCgP+LLh7c6FxqVQbgm3qpwgReYryaQQx8sdksX1gZ6jIEC5gYTDh+vHmUJdi +16I7Pz02e9R2yOsKU6e+zhCTauHtSM0CGYn9OdLx96WpJv6nul/KI8eztyV6Dl4k +T8rFbuo0qs8Ib9exDmkdRh78Ihbask69R1w/OwLIlKesOiLo04eJAJUDBRA1x/fK +P2UweumbYhUBAZCzA/0UQ5AB890HbWnvVHP9PdDT8KpIQYg7wm5aStpinY2/jfwA +zl+kvaAwL6nTsTJiWNLfZj4rLn0JsG8176/lyl4Lk6QLkbGyBD+/u8tD6yL0NzYW +lLIBwhxL8W8Fw889OKci72b6rrTcQNNEw2eZiSeTGJBQdZ4quDQZOthwtMEEe4kA +lQMFEDXQKC8offu9cgNgzQEBXYAEAJSZ+CEGKswFmmQqO2t0WaO9SKZxxXtnGe/Z ++M8emTESQecZ5oC4Sc+M9c6YE8jSH5CgDD4R5EHKeWXsVfFMV8wetcjgB9AicCnl +ki2hVT38Rf+b1go4lbKpPjKf+V32Xs/s/kblZ3SX11aOF7pkQCV2W1ebkZ+Tnim2 +Ec+pwLKytCxHcmVnb3J5IE5laWwgU2hhcGlybyA8Z3NoYXBpcm9Ac2VuZG1haWwu +Y29tPokAlQMFEDUUq258S2dtoA4VYwEBrTQD/A8sNe02YWwDwQx1sHMoDeCN3hjV +9lCdWlPa1Aj4Wsw4Jgf3Q1x+n2lmAUtov20tXVxtXohCjC0dNNyGZlIOKOXN/R8g +6g3KkdAhENarH9Fibw/XaXC/VTnvvv5QQWNT3VGUDp9lMj/rUu8LjrxNwANWcSfU +5mjUg0d0CFmYTqxqiQCVAwUQNRSr6L3aj9Y/6n39AQH0rAP/U8iMjZuwXGr280uC +FtEpEkSqlNvxFW+C4K+89jluK2o+6zhUu/N73nJM7HHt7kA40FaH9TJfxnTR3VDR +KbkpmZ1zPfrkgf+fE/rQgKn8enk8fWCMBdEDTjiCjXIoNNLK1Pyv0/x0yWt+n8kY +RaS4GV/d5nilK7lFx/uISOZmQ3uJARUDBRA1FePa41pYzZbpXysBAYYMCACIMf6P +Og0RgQS1QVpFrlUR2zQCEIv/ioWNGdXD43FDWkuyPmOGjOY8jpIYi7I2HBLtpbXR +WNl00ignGWcMhGzdZqK+K55cyDTIC14vGFc7SUKMcQUOEVfyMtytMYvNr+95EBGM +qlfUYxhoqfkguC3ZCmZvu2exdGndSXuxDA8d0KcjxDRAuIqfh7gekQTEkILf5Xkf +nSwsEdFwthW/vAWXYSNNF/L8Q5SXVi35ez0qqMJTa1rSzoRGkBKcxplJZ7YQfnBu +zp25LaeiF66UT9/6tAggKOfkqD/r7UwfVHYGK86HuzAdfepOv+hIrhouZZiXhkFQ +4ypAkFgaXj1AOgFTiQCVAwUQNRZkweTJ6ktPts0dAQHMqgP8DwJsWJUP7yELDOxc +x8Zh2EY78w1J94CTcYQPqF8+xaVpFdAt1tw1P6/KW0kjq2arfMW+xleXRhvchB/l +8kzjmocDIQx6C7x0rf4rwG7ZxulZgqI1NrB8EnIPzPBBeBP4aKdtGOg8S8585iH4 +zrWpW6Z/KOXQcDGge34pdN7JV9uJAJUDBRA1FmuyPGEoR0yrISEBAcsCBAChTZnQ +nS6PYAYp8OOB7/0evMSug+0PSGkxEzYZVcr/WUgijfsZ+DfVOYtXwKvuL3O+yUeK +oP3Uqs9wKMTr8tVIv8geoFYoxLuHD3P4EOYxjOI8Yk9/bNRT4E0NoEJQi58OIzwz +ORBztEhCFLWz/SCBpoXfMpLmplmxEUcHkj0ryokAlQMFEDUZQ9+8ViqRxTSlSQEB +mKgD/ibbOd/iRJ+cvaGSzns0hsz4nSFJdn2C09Bz4OPlIF6uslaeG7GR/fm7p8Qg +PPd5907mvMRStaK+gYLv3h50Nz9ckUvPB3erW/Xy7txCk1idI21b2QaAbmAYQ1r1 +HrFQXogDY/Pblj2pMYXC0sX4efQSbc5OTRr6W6ijqxRXNJQkiQCVAwUQNR+ubCPk +YtS/e6QhAQHiiwQAl9sGXG/TxwGyacjrgG6wTAz/PYhh+0CGDFjyC0wPXQjE/ICI +6/kjl6fYNhFQdRNPYhfY48TWk9iqIiInpylk5ieLzJD62yrUlXCZH5xx/MA3PzD5 +xczRO74R+4lVxuI/zGXdQMGm+P0ydzAma3gOhyN+85XzzFy/QOtPMihffLeJAHUD +BRA1aizMrOFcwQTbex0BAZP8Av0d+FY9zxS1okG2rXQFubkDoBREChWnKMSO+y+F +Kj2rDExoSt7EXn44DQWd8a3nz45u2Csr/JsntN9zr2OjOA3AUEsXyHmHHjDRQlaj +a5G7aHDRz4zaCDrxGiIMO5d1AfqJAJUDBRA1auWNKW49Y1pcAKkBActRA/4nLsGd ++N2OAiRhJvCZzLu6xhUEjMHwYJvxtYzcp2R3dFczbtgWKl8BGkeA91Gwm2ESu650 +WOyT5f9GC1T+zSZc8j0voZJOEMBxefrCA4jlwRA51CplYm7nbBaHk1OVER7zUYCB +olZLkgqCjUA39HvMZ/WhQoIAXpKMpU2zSCtTPYkAlQMFEDWILQyap0c7yRcsdQEB +TEQEAIElJUWiqoKT9X7TnHHlIHTSDhqVbsQdNjhB9g/hs5Rpl/pgDRCX1o32C2JT +b1OkjlWMd2RtKFcSCSYTqDKwmnxQfxvo/SgM0Gv3V5dpTlNc35g0gksgJGiozEIO +/6Hn6GHjrRh4fpRmv8ySHfzeJJq6+JttLy8uRmvywC4FSfp/iQCVAwUQNcf3kD9l +MHrpm2IVAQGu2AP+MjnlXXhtUH+i1V82j/Az5N+qwWKJbbQK2Qd95oE43BI8ES+8 +0MAuP58oA9XikkcFX6Lqunvv2FRC5hsi+SsSXx67poMsQzk71mqxDR+dY+iCw36O +BLK2NtITxxAIKQwj79xNqzgsfm3cpti32t+C/kGkYbONonZHz5uhAG+N0jQ= +=idnw +-----END PGP PUBLIC KEY BLOCK----- + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/README b/gnu/usr.sbin/sendmail/README new file mode 100644 index 00000000000..78b28e13d4c --- /dev/null +++ b/gnu/usr.sbin/sendmail/README @@ -0,0 +1,369 @@ + + SENDMAIL RELEASE 8 + +This directory has the latest sendmail(TM) software from Sendmail, Inc. + +Report any bugs to sendmail-bugs@sendmail.ORG + +There is a web site at http://WWW.Sendmail.ORG/ -- see that site for +the latest updates. + ++--------------+ +| INTRODUCTION | ++--------------+ + +0. The vast majority of queries to + are answered in the README files noted below. + +1. Read this README file, especially this introduction, and the DIRECTORY + PERMISSIONS sections. + +2. Read sendmail/README, especially: + a. the introduction + b. the BUILDING SENDMAIL section + c. the relevant part(s) of the OPERATING SYSTEM AND COMPILE QUIRKS section + + You may also find these useful: + + d. devtools/README + e. devtools/Site/README + +3. Read cf/README. + +Sendmail is a trademark of Sendmail, Inc. + ++-----------------------+ +| DIRECTORY PERMISSIONS | ++-----------------------+ + +Sendmail often gets blamed for many problems that are actually the +result of other problems, such as overly permissive modes on directories. +For this reason, sendmail checks the modes on system directories and +files to determine if they can be trusted. For sendmail to run without +complaining, you MUST execute the following command: + + chmod go-w / /etc /etc/mail /usr /var /var/spool /var/spool/mqueue + chown root / /etc /etc/mail /usr /var /var/spool /var/spool/mqueue + +You will probably have to tweak this for your environment (for example, +some systems put the spool directory into /usr/spool instead of +/var/spool and use /etc/mail for aliases file instead of /etc). If you +set the RunAsUser option in your sendmail.cf, the /var/spool/mqueue +directory will have to be owned by the RunAsUser user. As a general rule, +after you have compiled sendmail, run the command + + sendmail -v -bi + +to initialize the alias database. If it gives messages such as + + WARNING: writable directory /etc + WARNING: writable directory /var/spool/mqueue + +then the directories listed have inappropriate write permissions and +should be secured to avoid various possible security attacks. + +Beginning with sendmail 8.9, these checks have become more strict to +prevent users from being able to access files they would normally not +be able to read. In particular, .forward and :include: files in unsafe +directory paths (directory paths which are group or world writable) will +no longer be allowed. This would mean that if user joe's home directory +was writable by group staff, sendmail would not use his .forward file. +This behavior can be altered, at the expense of system security, by +setting the DontBlameSendmail option. For example, to allow .forward +files in group writable directories: + + O DontBlameSendmail=forwardfileingroupwritabledirpath + +Or to allow them in both group and world writable directories: + + O DontBlameSendmail=forwardfileinunsafedirpath + +Items from these unsafe .forward and :include: files will be marked +as unsafe addresses -- the items can not be deliveries to files or +programs. This behavior can also be altered via DontBlameSendmail: + + O DontBlameSendmail=forwardfileinunsafedirpath, + forwardfileinunsafedirpathsafe + +The first flag allows the .forward file to be read, the second allows +the items in the file to be marked as safe for file and program +delivery. + +Other files affected by this strengthened security include class +files (i.e. Fw /etc/sendmail.cw), persistent host status files, and +the files specified by the ErrorHeader and HelpFile options. Similar +DontBlameSendmail flags are available for the class, ErrorHeader, and +HelpFile files. + +If you have an unsafe configuration of .forward and :include: +files, you can make it safe by finding all such files, and doing +a "chmod go-w $FILE" on each. Also, do a "chmod go-w $DIR" for +each directory in the file's path. + + ++-----------------------+ +| RELATED DOCUMENTATION | ++-----------------------+ + +There are other files you should read. Rooted in this directory are: + + FAQ + Answers to Frequently Asked Questions. + INSTALL + Installation instructions for building and installing sendmail. + KNOWNBUGS + Known bugs in the current release. + RELEASE_NOTES + A detailed description of the changes in each version. This + is quite long, but informative. + sendmail/README + 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. For a list of the +primary repositories see: + + http://www.isi.edu/in-notes/rfc-retrieval.txt + +They are also online at: + + http://www.ietf.org/ + +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 + +For further instructions see: + + http://www.isi.edu/in-notes/rfc-editor/rfc-info + +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 + RFC1869 SMTP Service Extensions (ESMTP spec) + RFC1652 SMTP Service Extension for 8bit-MIMEtransport + RFC1870 SMTP Service Extension for Message Size Declaration + RFC2045 Multipurpose Internet Mail Extensions (MIME) Part One: + Format of Internet Message Bodies + RFC1344 Implications of MIME for Internet Mail Gateways + RFC1428 Transition of Internet Mail from Just-Send-8 to + 8-bit SMTP/MIME + RFC1891 SMTP Service Extension for Delivery Status Notifications + RFC1892 Multipart/Report Content Type for the Reporting of + Mail System Administrative Messages + RFC1893 Enhanced Mail System Status Codes + RFC1894 An Extensible Message Format for Delivery Status + Notifications + RFC1985 SMTP Service Extension for Remote Message Queue Starting + RFC2033 Local Mail Transfer Protocol (LMTP) + RFC2034 SMTP Service Extension for Returning Enhanced Error Codes + RFC2476 Message Submission + RFC2554 SMTP Service Extension for Authentication + +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 the web at +http://www.sleepycat.com/. 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. If the Berkeley DB include files +are installed in a location other than those which your compiler searches, +you will need to provide that directory when building: + + Build -I/path/to/include/directory + +If you are using Berkeley DB versions 1.85 or 1.86, you are *strongly* +urged to upgrade to DB version 2 or later, available from +http://www.sleepycat.com/. Berkeley DB versions 1.85 and 1.86 are known to +be broken in various nasty ways (see http://www.sleepycat.com/db.185.html), +and can cause sendmail to dump core. In addition, the newest versions of +gcc and the Solaris compilers perform optimizations in those versions that +may cause fairly random core dumps. + +If you have no choice but to use Berkeley DB 1.85 or 1.86, and you are +using both Berkeley DB and files in the UNIX ndbm format, remove ndbm.h +and ndbm.o from the DB library after building it. You should also apply +all of the patches for DB 1.85 and 1.86 found at the Sleepycat web site +(see http://www.sleepycat.com/db.185.html), as they fix some of the known +problems. + +If you are using a version of Berkeley DB 2 previous to 2.3.15, and you +are using both Berkeley DB and files in the UNIX ndbm format, remove dbm.o +from the DB library after building it. No other changes are necessary. + +If you are using Berkeley DB version 2.3.15 or greater, no changes are +necessary. + +The underlying database file formats changed between Berkeley DB versions +1.85 and 1.86, again between DB 1.86 and version 2.0, and finally between +DB 2.X and 3.X. If you are upgrading from one of those versions, you must +recreate your database file(s). Do this by rebuilding all maps with +makemap and rebuilding the alias file with newaliases. + + ++--------------------+ +| 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. +Note that the RFC states a client should wait at least 30 seconds +for a response. As of 8.10.0, the default Timeout.ident is 5 seconds +as many sites have adopted the practice of dropping IDENT queries. +This has lead to delays processing mail. + +No ident server is included with this distribution. It is available +from: + + ftp://ftp.lysator.liu.se/pub/ident/servers/ + ftp://romulus.ucs.uoknor.edu/networking/ident/servers/ + ftp://ftp.cyf-kr.edu.pl/agh/uciagh/network/ident/ + + ++-------------------------+ +| INTEROPERATION PROBLEMS | ++-------------------------+ + +Microsoft Exchange Server 5.0 + We have had a report that ``about 7% of messages from Sendmail + to Exchange were not being delivered with status messages of + "connection reset" and "I/O error".'' Upgrading Exchange from + Version 5.0 to Version 5.5 Service Pack 2 solved this problem. + +CommuniGate Pro + CommuniGate Pro 3.2.4 does not accept the AUTH= -parameter on + the MAIL FROM command if the client is not authenticated. Use + + define(`confAUTH_OPTIONS', `A') + + in .mc file if you have compiled sendmail with Cyrus SASL + and you communicate with CommuniGate Pro servers. + ++---------------------+ +| DIRECTORY STRUCTURE | ++---------------------+ + +The structure of this directory tree is: + +cf Source for sendmail 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 sendmail -- contact the original + authors if you have problems. (This directory is not + on the 4.4BSD tape.) +devtools Build environment. See devtools/README. +doc Documentation. If you are getting source, read + op.me -- it's long, but worth it. +include Include files used by multiple programs in the distribution. +libsmdb sendmail database library with support for Berkeley DB 1.X, + Berkeley DB 2.X, Berkeley DB 3.X, and NDBM. +libsmutil sendmail utility library with functions used by different + programs. +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. +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. There is no + guarantee it will even compile on your operating system. +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! +sendmail Source for the sendmail program itself. +test Some test scripts (currently only for compilation aids). +vacation Source for the vacation program. NOT PART OF SENDMAIL! + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:36 $ diff --git a/gnu/usr.sbin/sendmail/RELEASE_NOTES b/gnu/usr.sbin/sendmail/RELEASE_NOTES new file mode 100644 index 00000000000..ec32d427cb8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/RELEASE_NOTES @@ -0,0 +1,6748 @@ + SENDMAIL RELEASE NOTES + $Sendmail: RELEASE_NOTES,v 8.521 2000/03/03 19:28:31 gshapiro Exp $ + + +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.10.0/8.10.0 2000/03/01 + ************************************************************* + * The engineering department at Sendmail, Inc. has suffered * + * the tragic loss of a key member of our engineering team. * + * Julie Van Bourg was the Vice President of Engineering * + * at Sendmail, Inc. during the development and deployment * + * of this release. It was her vision, dedication, and * + * support that has made this release a success. Julie died * + * on October 26, 1999 of cancer. We have lost a leader, a * + * coach, and a friend. * + * * + * This release is dedicated to her memory and to the joy, * + * strength, ideals, and hope that she brought to all of us. * + * Julie, we miss you! * + ************************************************************* + SECURITY: The safe file checks now back track through symbolic + links to make sure the files can't be compromised due + to poor permissions on the parent directories of the + symbolic link target. + SECURITY: Only root, TrustedUser, and users in class t can rebuild + the alias map. Problem noted by Michal Zalewski of the + "Internet for Schools" project (IdS). + SECURITY: There is a potential for a denial of service attack if + the AutoRebuildAliases option is set as a user can kill the + sendmail process while it is rebuilding the aliases file + (leaving it in an inconsistent state). This option and + its use is deprecated and will be removed from a future + version of sendmail. + SECURITY: Make sure all file descriptors (besides stdin, stdout, and + stderr) are closed before restarting sendmail. Problem noted + by Michal Zalewski of the "Internet for Schools" project + (IdS). + Begin using /etc/mail/ for sendmail related files. This affects + a large number of files. See cf/README for more details. + The directory structure of the distribution has changed slightly + for easier code sharing among the programs. + Support SMTP AUTH (see RFC 2554). New macros for this purpose + are ${auth_authen}, ${auth_type}, and ${auth_author} + which hold the client's authentication credentials, + the mechanism used for authentication, and the + authorization identity (i.e., the AUTH= parameter if + supplied). Based on code contributed by Tim Martin of CMU. + On systems which use the Torek stdio library (all of the BSD + distributions), use memory-buffered files to reduce + file system overhead by not creating temporary files on + disk. Contributed by Exactis.com, Inc. + New option DataFileBufferSize to control the maximum size of a + memory-buffered data (df) file before a disk-based file is + used. Contributed by Exactis.com, Inc. + New option XscriptFileBufferSize to control the maximum size of a + memory-buffered transcript (xf) file before a disk-based + file is used. Contributed by Exactis.com, Inc. + sendmail implements RFC 2476 (Message Submission), e.g., it can + now listen on several different ports. Use: + O DaemonPortOptions=Name=MSA, Port=587, M=E + to run a Message Submission Agent (MSA); this is turned + on by default in m4-generated .cf files; it can be turned + off with FEATURE(`no_default_msa'). + The 'XUSR' SMTP command is deprecated. Mail user agents should + begin using RFC 2476 Message Submission for initial user + message submission. XUSR may disappear from a future release. + The new '-G' (relay (gateway) submission) command line option + indicates that the message being submitted from the command + line is for relaying, not initial submission. This means + the message will be rejected if the addresses are not fully + qualified and no canonicalization will be done. Future + releases may even reject improperly formed messages. + The '-U' (initial user submission) command line option is + deprecated and may be removed from a future release. + Mail user agents should begin using '-G' to indicate that + this is a relay submission (the inverse of -U). + The next release of sendmail will assume that any message submitted + from the command line is an initial user submission and act + accordingly. + If sendmail doesn't have enough privileges to run a .forward + program or deliver to file as the owner of that file, the + address is marked as unsafe. This means if RunAsUser is + set, users won't be able to use programs or delivery to + files in their .forward files. Administrators can override + this by setting the DontBlameSendmail option to the new + setting NonRootSafeAddr. + Allow group or world writable directories if the sticky bit is set + on the directory and DontBlameSendmail is set to + TrustStickyBit. Based on patch from Chris Metcalf of + InCert Software. + Prevent logging of unsafe directory paths for non-existent forward + files if the new DontWarnForwardFileInUnsafeDirPath bit is + set in the DontBlameSendmail option. Requested by many. + New Timeout.control option to limit the total time spent satisfying + a control socket request. + New Timeout.resolver options for controlling BIND resolver + settings: + Timeout.resolver.retrans + Sets the resolver's retransmission time interval (in + seconds). Sets both Timeout.resolver.retrans.first + and Timeout.resolver.retrans.normal. + Timeout.resolver.retrans.first + Sets the resolver's retransmission time interval (in + seconds) for the first attempt to deliver a message. + Timeout.resolver.retrans.normal + Sets the resolver's retransmission time interval (in + seconds) for all resolver lookups except the first + delivery attempt. + Timeout.resolver.retry + Sets the number of times to retransmit a resolver + query. Sets both Timeout.resolver.retry.first + and Timeout.resolver.retry.normal. + Timeout.resolver.retry.first + Sets the number of times to retransmit a resolver + query for the first attempt to deliver a message. + Timeout.resolver.retry.normal + Sets the number of times to retransmit a resolver + query for all resolver lookups except the first + delivery attempt. + Contributed by Exactis.com, Inc. + Support multiple queue directories. To use multiple queues, supply + a QueueDirectory option value ending with an asterisk. For + example, /var/spool/mqueue/q* will use all of the + directories or symbolic links to directories beginning with + 'q' in /var/spool/mqueue as queue directories. Keep in + mind, the queue directory structure should not be changed + while sendmail is running. Queue runs create a separate + process for running each queue unless the verbose flag is + given on a non-daemon queue run. New items are randomly + assigned to a queue. Contributed by Exactis.com, Inc. + Support different directories for qf, df, and xf queue files; if + subdirectories or symbolic links to directories of those names + exist in the queue directories, they are used for the + corresponding queue files. Keep in mind, the queue + directory structure should not be changed while sendmail is + running. Proposed by Mathias Koerber of Singapore + Telecommunications Ltd. + New queue file naming system which uses a filename guaranteed to be + unique for 60 years. This allows queue IDs to be assigned + without fancy file system locking. Queued items can be + moved between queues easily. Contributed by Exactis.com, + Inc. + Messages which are undeliverable due to temporary address failures + (e.g., DNS failure) will now go to the FallBackMX host, if + set. Contributed by Exactis.com, Inc. + New command line option '-L tag' which sets the identifier used for + syslog. Contributed by Exactis.com, Inc. + QueueSortOrder=Filename will sort the queue by filename. This + avoids opening and reading each queue file when preparing + to run the queue. Contributed by Exactis.com, Inc. + Shared memory counters and microtimers functionality has been + donated by Exactis.com, Inc. + The SCCS ID tags have been replaced with RCS ID tags. + Allow trusted users (those on a T line or in $=t) to set the + QueueDirectory (Q) option without an X-Authentication-Warning: + being added. Suggested by Michael K. Sanders. + IPv6 support based on patches from John Kennedy of Cal State + University, Chico, Motonori Nakamura of Kyoto University, + and John Beck of Sun Microsystems. + In low-disk space situations, where sendmail would previously refuse + connections, still accept them, but only allow ETRN commands. + Suggested by Mathias Koerber of Singapore Telecommunications + Ltd. + The [IPC] builtin mailer now allows delivery to a UNIX domain socket + on systems which support them. This can be used with LMTP + local delivery agents which listen on a named socket. An + example mailer might be: + Mexecmail, P=[IPC], F=lsDFMmnqSXzA5@/:|, E=\r\n, + S=10, R=20/40, T=DNS/RFC822/X-Unix, + A=FILE /var/run/lmtpd + Code contributed by Lyndon Nerenberg of Messaging Direct. + The [TCP] builtin mailer name is now deprecated. Use [IPC] + instead. + The first mailer argument in the [IPC] mailer is now checked for a + legitimate value. Possible values are TCP (for TCP/IP + connections), IPC (which will be deprecated in a future + version), and FILE (for UNIX domain socket delivery). + PrivacyOptions=goaway no longer includes the noetrn and the noreceipts + flags. + PrivacyOptions=nobodyreturn instructs sendmail not to include the + body of the original message on delivery status + notifications. + Don't announce DSN if PrivacyOptions=noreceipts is set. Problem noted + by Dan Bernstein, fix from Robert Harker of Harker Systems. + Accept the SMTP RSET command even when rejecting commands due to TCP + Wrappers or the check_relay ruleset. Problem noted by + Steve Schweinhart of America Online. + Warn if OperatorChars is set multiple times. OperatorChars should + not be set after rulesets are defined. Suggested by + Mitchell Blank Jr of Exec-PC. + Do not report temporary failure on delivery to files. In + interactive delivery mode, this would result in two SMTP + responses after the DATA command. Problem noted by + Nik Conwell of Boston University. + Check file close when mailing to files. Problem noted by Nik + Conwell of Boston University. + Avoid a segmentation fault when using the LDAP map. Patch from + Curtis W. Hillegas of Princeton University. + Always bind to the LDAP server regardless of whether you are using + ldap_open() or ldap_init(). Fix from Raj Kunjithapadam of + @Home Network. + New ruleset trust_auth to determine whether a given AUTH= + parameter of the MAIL command should be trusted. See SMTP + AUTH, cf/README, and doc/op/op.ps. + Allow new named config file rules check_vrfy, check_expn, and + check_etrn for VRFY, EXPN, and ETRN commands, respectively, + similar to check_rcpt etc. + Introduce new macros ${rcpt_mailer}, ${rcpt_host}, ${rcpt_addr}, + ${mail_mailer}, ${mail_host}, ${mail_addr} that hold + the results of parsing the RCPT and MAIL arguments, i.e. + the resolved triplet from $#mailer $@host $:addr. + From Kari Hurtta of the Finnish Meteorological Institute. + New macro ${client_resolve} which holds the result of the resolve + call for ${client_name}: OK, FAIL, FORGED, TEMP. Proposed + by Kari Hurtta of the Finnish Meteorological Institute. + New macros ${dsn_notify}, ${dsn_envid}, and ${dsn_ret} that hold + the corresponding DSN parameter values. Proposed by + Mathias Herberts. + New macro ${msg_size} which holds the value of the SIZE= parameter, + i.e., usually the size of the message (in an ESMTP dialogue), + before the message has been collected, thereafter it holds + the message size as computed by sendmail (and can be used + in check_compat). + The macro ${deliveryMode} now specifies the current delivery mode + sendmail is using instead of the value of the DeliveryMode + option. + New macro ${ntries} holds the number of delivery attempts. + Drop explicit From: if same as what would be generated only if it is + a local address. From Motonori Nakamura of Kyoto University. + Write pid to file also if sendmail only processes the queue. + Proposed by Roy J. Mongiovi of Georgia Tech. + Log "low on disk space" only when necessary. + New macro ${load_avg} can be used to check the current load average. + Suggested by Scott Gifford of The Internet Ramp. + Return-Receipt-To: header implies DSN request if option RrtImpliesDsn + is set. + Flag -S for maps to specify the character which is substituted + for spaces (instead of the default given by O BlankSub). + Flag -D for maps: perform no lookup in deferred delivery mode. + This flag is set by default for the host map. Based on a + proposal from Ian MacPhedran of the University of Saskatchewan. + Open maps only on demand, not at startup. + Log warning about unsupported IP address families. + New option MaxHeadersLength allows to specify a maximum length + of the sum of all headers. This can be used to prevent + a denial-of-service attack. + New option MaxMimeHeaderLength which limits the size of MIME + headers and parameters within those headers. This option + is intended to protect mail user agents from buffer + overflow attacks. + Added option MaxAliasRecursion to specify the maximum depth of + alias recursion. + New flag F=6 for mailers to strip headers to seven bit. + Map type syslog to log the key via syslogd. + Entries in the alias file can be continued by putting a backslash + directly before the newline. + New option DeadLetterDrop to define the location of the system-wide + dead.letter file, formerly hardcoded to + /usr/tmp/dead.letter. If this option is not set (the + default), sendmail will not attempt to save to a + system-wide dead.letter file if it can not bounce the mail + to the user nor postmaster. Instead, it will rename the qf + file as it has in the past when the dead.letter file + could not be opened. + New option PidFile to define the location of the pid file. The + value of this option is macro expanded. + New option ProcessTitlePrefix specifies a prefix string for the + process title shown in 'ps' listings. + New macros for use with the PidFile and ProcessTitlePrefix options + (along with the already existing macros): + ${daemon_info} Daemon information, e.g. + SMTP+queueing@00:30:00 + ${daemon_addr} Daemon address, e.g., 0.0.0.0 + ${daemon_family} Daemon family, e.g., inet, inet6, etc. + ${daemon_name} Daemon name, e.g., MSA. + ${daemon_port} Daemon port, e.g., 25 + ${queue_interval} Queue run interval, e.g., 00:30:00 + New macros especially for virtual hosting: + ${if_name} hostname of interface of incoming connection. + ${if_addr} address of interface of incoming connection. + The latter is only set if the interface does not belong to the + loopback net. + If a message being accepted via a method other than SMTP and + would be rejected by a header check, do not send the message. + Suggested by Phil Homewood of Mincom Pty Ltd. + Don't strip comments for header checks if $>+ is used instead of $>. + Provide header value as quoted string in the macro + ${currHeader} (possibly truncated to MAXNAME). Suggested by + Jan Krueger of Unix-AG of University of Hannover. + The length of the header value is stored in ${hdrlen}. + H*: allows to specify a default ruleset for header checks. This + ruleset will only be called if the individual header does + not have its own ruleset assigned. Suggested by Jan + Krueger of Unix-AG of University of Hannover. + The name of the header field stored in ${hdr_name}. + Comments (i.e., text within parentheses) in rulesets are not + removed if the config file version is greater than or equal + to 9. For example, "R$+ ( 1 ) $@ 1" matches the + input "token (1)" but does not match "token". + Avoid removing the Content-Transfer-Encoding MIME header on + MIME messages. Problem noted by Sigurbjorn B. Larusson of + Multimedia Consumer Services. Fix from Per Hedeland of + Ericsson. + Avoid duplicate Content-Transfer-Encoding MIME header on + messages with 8-bit text in headers. Problem noted by + Per Steinar Iversen of Oslo College. Fix from Per Hedeland + of Ericsson. + Avoid keeping maps locked longer than necessary when re-opening a + modified database map file. Problem noted by Chris Adams + of Renaissance Internet Services. + Resolving to the $#error mailer with a temporary failure code (e.g., + $#error $@ tempfail $: "400 Temporary failure") will now + queue up the message instead of bouncing it. + Be more liberal in acceptable responses to an SMTP RSET command as + standard does not provide any indication of what to do when + something other than 250 is received. Based on a patch + from Steve Schweinhart of America Online. + New option TrustedUser allows to specify a user who can own + important files instead of root. This requires HASFCHOWN. + Fix USERDB conditional so compiling with NEWDB or HESIOD and + setting USERDB=0 works. Fix from Jorg Zanger of Schock. + Fix another instance (similar to one in 8.9.3) of a network failure + being mis-logged as "Illegal Seek" instead of whatever + really went wrong. From John Beck of Sun Microsystems. + $? tests also whether the macro is non-null. + Print an error message if a mailer definition contains an invalid + equate name. + New mailer equate /= to specify a directory to chroot() into before + executing the mailer program. Suggested by Igor Vinokurov. + New mailer equate W= to specify the maximum time to wait for the + mailer to return after sending all data to it. + Only free memory from the process list when adding a new process + into a previously filled slot. Previously, the memory was + freed at removal time. Since removal can happen in a + signal handler, this may leave the memory map in an + inconsistent state. Problem noted by Jeff A. Earickson and + David Cooley of Colby College. + When using the UserDB @hostname catch-all, do not try to lookup + local users in the passwd file. The UserDB code has + already decided the message will be passed to another host + for processing. Fix from Tony Landells of Burdett + Buckeridge Young Limited. + Support LDAP authorization via either a file containing the + password or Kerberos V4 using the new map options + '-ddistinguished_name', '-Mmethod', and '-Pfilename'. The + distinguished_name is who to login as. The method can be + one of LDAP_AUTH_NONE, LDAP_AUTH_SIMPLE, or + LDAP_AUTH_KRBV4. The filename is the file containing the + secret key for LDAP_AUTH_SIMPLE or the name of the Kerberos + ticket file for LDAP_AUTH_KRBV4. Patch from Booker Bense + of Stanford University. + The ldapx map has been renamed to ldap. The use of ldapx is + deprecated and will be removed in a future version. + If the result of an LDAP search returns a multi-valued attribute + and the map has the column delimiter set, it turns that + response into a delimiter separated string. The LDAP map + will traverse multiple entries as well. LDAP alias maps + automatically set the column delimiter to the comma. + Based on patch from Booker Bense of Stanford University and + idea from Philip A. Prindeville of Mirapoint, Inc. + Support return of multiple values for a single LDAP lookup. The + values to be returned should be in a comma separated string. + For example, `-v "email,emailother"'. Patch from + Curtis W. Hillegas of Princeton University. + Allow the use of LDAP for alias maps. + If no LDAP attributes are specified in an LDAP map declaration, all + attributes found in the match will be returned. + Prevent commas in quoted strings in the AliasFile value from + breaking up a single entry into multiple entries. This is + needed for LDAP alias file specifications to allow for + comma separated key and value strings. + Keep connections to LDAP server open instead of opening and closing + for each lookup. To reduce overhead, sendmail will cache + connections such that multiple maps which use the same + host, port, bind DN, and authentication will only result in + a single connection to that host. + Put timeout in the proper place for USE_LDAP_INIT. + Be more careful about checking for errors and freeing memory on + LDAP lookups. + Use asynchronous LDAP searches to save memory and network + resources. + Do not copy LDAP query results if the map's match only flag is set. + Increase portability to the Netscape LDAP libraries. + Change the parsing of the LDAP filter specification. '%s' is still + replaced with the literal contents of the map lookup key -- + note that this means a lookup can be done using the LDAP + special characters. The new '%0' token can be used instead + of '%s' to encode the key buffer according to RFC 2254. + For example, if the LDAP map specification contains '-k + "(user=%s)"' and a lookup is done on "*", this would be + equivalent to '-k "(user=*)"' -- matching ANY record with a + user attribute. Instead, if the LDAP map specification + contains '-k "(user=%0)"' and a lookup is one on "*", this + would be equivalent to '-k "(user=\2A)"' -- matching a user + with the name "*". + New LDAP map flags: "-1" requires a single match to be returned, if + more than one is returned, it is equivalent to no records + being found; "-r never|always|search|find" sets the LDAP + alias dereference option; "-Z size" limits the number of + matches to return. + New option LDAPDefaultSpec allows a default map specification for + LDAP maps. The value should only contain LDAP specific + settings such as "-h host -p port -d bindDN", etc. The + settings will be used for all LDAP maps unless they are + specified in the individual map specification ('K' + command). This option should be set before any LDAP maps + are defined. + Prevent an NDBM alias file opening loop when the NDBM open + continually fails. Fix from Roy J. Mongiovi of Georgia + Tech. + Reduce memory utilization for smaller symbol table entries. In + particular, class entries get much smaller, which can be + important if you have large classes. + On network-related temporary failures, record the hostname which + gave error in the queued status message. Requested by + Ulrich Windl of the Universitat Regensburg. + Add new F=% mailer flag to allow for a store and forward + configuration. Mailers which have this flag will not attempt + delivery on initial recipient of a message or on queue runs + unless the queued message is selected using one of the + -qI/-qR/-qS queue run modifiers or an ETRN request. Code + provided by Philip Guenther of Gustavus Adolphus College. + New option ControlSocketName which, when set, creates a daemon + control socket. This socket allows an external program to + control and query status from the running sendmail daemon + via a named socket, similar to the ctlinnd interface to the + INN news server. Access to this interface is controlled by + the UNIX file permissions on the named socket on most UNIX + systems (see sendmail/README for more information). An + example control program is provided as contrib/smcontrol.pl. + Change the default values of QueueLA from 8 to (8 * numproc) and + RefuseLA from 12 to (12 * numproc) where numproc is the + number of processors online on the system (if that can be + determined). For single processor machines, this change + has no effect. + Don't return body of message to postmaster on "Too many hops" bounces. + Based on fix from Motonori Nakamura of Kyoto University. + Give more detailed DSN descriptions for some cases. Patch from + Motonori Nakamura of Kyoto University. + Logging of alias, forward file, and UserDB expansion now happens + at LogLevel 11 or higher instead of 10 or higher. + Logging of an envelope's complete delivery (the "done" message) now + happens at LogLevel 10 or higher instead of 11 or higher. + Logging of TCP/IP or UNIX standard input connections now happens at + LogLevel 10 or higher. Previously, only TCP/IP connections + were logged, and on at LogLevel 12 or higher. Setting + LogLevel to 10 will now assist users in tracking frequent + connection-based denial of service attacks. + Log basic information about authenticated connections at LogLevel + 10 or higher. + Log SMTP Authentication mechanism and author when logging the sender + information (from= syslog line). + Log the DSN code for each recipient if one is available as a new + equate (dsn=). + Macro expand PostmasterCopy and DoubleBounceAddress options. + New "ph" map for performing ph queries in rulesets. More + information is available at + http://www-wsg.cso.uiuc.edu/sendmail/patches/. + Contributed by Mark Roth of the University of Illinois at + Urbana-Champaign. + Detect temporary lookup failures in the host map if looking up a + bracketed IP address. Problem noted by Kari Hurtta of the + Finnish Meteorological Institute. + Do not report a Remote-MTA on local deliveries. Problem noted by + Kari Hurtta of the Finnish Meteorological Institute. + When a forward file points to an alias which runs a program, run + the program as the default user and the default group, not + the forward file user. This change also assures the + :include: directives in aliases are also processed using + the default user and group. Problem noted by Sergiu + Popovici of DNT Romania. + Prevent attempts to save a dead.letter file for a user with + no home directory (/no/such/directory). Problem noted by + Michael Brown of Finnigan FT/MS. + Include message delay and number of tries when logging that a + message has been completely delivered (LogLevel of 10 or + above). Suggested by Nick Hilliard of Ireland Online. + Log the sender of a message even if none of the recipients were + accepted. If some of the recipients were rejected, it is + helpful to know the sender of the message. + Check the root directory (/) when checking a path for safety. + Problem noted by John Beck of Sun Microsystems. + Prevent multiple responses to the DATA command if DeliveryMode is + interactive and delivering to an alias which resolves to + multiple files. + Macros in the helpfile are expanded if the helpfile version is 2 or + greater (see below); the help function doesn't print the + version of sendmail any longer, instead it is placed in + the helpfile ($v). Suggested by Chuck Foster of UUNET + PIPEX. Additionally, comment lines (starting with #) are + skipped and a version line (#vers) is introduced. The + helpfile version for 8.10.0 is 2, if no version or an older + version is found, a warning is logged. The '#vers' + directive should be placed at the top of the help file. + Use fsync() when delivering to a file to guarantee the delivery to + disk succeeded. Suggested by Nick Christenson. + If delivery to a file is unsuccessful, truncate the file back to its + length before the attempt. + If a forward points to a filename for delivery, change to the + user's uid before checking permissions on the file. This + allows delivery to files on NFS mounted directories where + root is remapped to nobody. Problem noted by Harald + Daeubler of Universitaet Ulm. + purgestat and sendmail -bH purge only expired (Timeout.hoststatus) + host status files, not all files. + Any macros stored in the class $={persistentMacros} will be saved + in the queue file for the message and set when delivery + is attempted on the queued item. Suggested by Kyle Jones of + Wonderworks Inc. + Add support for storing information between rulesets using the new + macro map class. This can be used to store information + between queue runs as well using $={persistentMacros}. + Based on an idea from Jan Krueger of Unix-AG of University + of Hannover. + New map class arith to allow for computations in rules. The + operation (+, -, *, /, l (for less than), and =) is given + as key. The two operands are specified as arguments; the + lookup returns the result of the computation. For example, + "$(arith l $@ 4 $@ 2 $)" will return "FALSE" and + "$(arith + $@ 4 $@ 2 $)" will return "6". + Add new syntax for header declarations which decide whether to + include the header based on a macro rather than a mailer + flag: + H?${MyMacro}?X-My-Header: ${MyMacro} + This should be used along with $={persistentMacros}. + It can be used for adding headers to a message based on + the results of check_* and header check rulesets. + Allow new named config file rule check_eoh which is called after + all of the headers have been collected. The input to the + ruleset the number of headers and the size of all of the + headers in bytes separated by $|. This ruleset along with + the macro storage map can be used to correlate information + gathered between headers and to check for missing headers. + See cf/README or doc/op/op.ps for an example. + Change the default for the MeToo option to True to correspond + to the clarification in the DRUMS SMTP Update spec. This + option is deprecated and will be removed from a future + version. + Change the sendmail binary default for SendMimeErrors to True. + Change the sendmail binary default for SuperSafe to True. + Display ruleset names in debug and address test mode output + if referencing a named ruleset. + New mailer equate m= which will limit the number of messages + delivered per connection on an SMTP or LMTP mailer. + Improve QueueSortOrder=Host by reversing the hostname before + using it to sort. Now all the same domains are really run + through the queue together. If they have the same MX host, + then they will have a much better opportunity to use the + connection cache if available. This should be a reasonable + performance improvement. Patch from Randall Winchester of + the University of Maryland. + If a message is rejected by a header check ruleset, log who would + have received the message if it had not been rejected. + New "now" value for Timeout.queuereturn to bounce entries from the + queue immediately. No delivery attempt is made. + Increase sleeping time exponentially after too many "bad" commands + up to 4 minutes delay (compare MAX{BAD,NOOP,HELO,VRFY,ETRN}- + COMMANDS). + New option ClientPortOptions similar to DaemonPortOptions + but for outgoing connections. + New suboptions for DaemonPortOptions: Name (a name used for + error messages and logging) and Modifiers, i.e. + a require authentication + b bind to interface through which mail has + been received + c perform hostname canonification + f require fully qualified hostname + h use name of interface for outgoing HELO + command + C don't perform hostname canonification + E disallow ETRN (see RFC 2476) + New suboption for ClientPortOptions: Modifiers, i.e. + h use name of interface for HELO command + The version number for queue files (qf) has been incremented to 4. + Log unacceptable HELO/EHLO domain name attempts if LogLevel is set + to 10 or higher. Suggested by Rick Troxel of the National + Institutes of Health. + If a mailer dies, print the status in decimal instead of octal + format. Suggested by Michael Shapiro of Sun Microsystems. + Limit the length of all MX records considered for delivery to 8k. + Move message priority from sender to recipient logging. Suggested by + Ulrich Windl of the Universitat Regensburg. + Add support for Berkeley DB 3.X. + Add fix for Berkeley DB 2.X fcntl() locking race condition. + Requires a post-2.7.5 version of Berkeley DB. + Support writing traffic log (sendmail -X option) to a FIFO. + Patch submitted by Rick Heaton of Network Associates, Inc. + Do not ignore Timeout settings in the .cf file when a Timeout + sub-options is set on the command line. Problem noted by + Graeme Hewson of Oracle. + Randomize equal preference MX records each time delivery is + attempted via a new connection to a host instead of once per + session. Suggested by Scott Salvidio of Compaq. + Implement enhanced status codes as defined by RFC 2034. + Add [hostname] to class w for the names of all interfaces unless + DontProbeInterfaces is set. This is useful for sending mails + to hosts which have dynamically assigned names. + If a message is bounced due to bad MIME conformance, avoid bouncing + the bounce for the same reason. If the body is not 8-bit + clean, and EightBitMode isn't set to pass8, the body will + not be included in the bounce. Problem noted by Valdis + Kletnieks of Virginia Tech. + The timeout for sending a message via SMTP has been changed from + '${msgsize} / 16 + (${nrcpts} * 300)' to a timeout which + simply checks for progress on sending data every 5 minutes. + This will detect the inability to send information quicker + and reduce the number of processes simply waiting to + timeout. + Prevent a segmentation fault on systems which give a partial filled + interface address structure when loading the system network + interface addresses. Fix from Reinier Bezuidenhout of + Nanoteq. + Add a compile-time configuration macro, MAXINTERFACES, which + indicates the number of interfaces to read when probing + for hostnames and IP addresses for class w ($=w). The + default value is 512. Based on idea from Reinier + Bezuidenhout of Nanoteq. + If the RefuseLA option is set to 0, do not reject connections based + on load average. + Allow ruleset 0 to have a name. Problem noted by Neil Rickert of + Northern Illinois University. + Expand the Return-Path: header at delivery time, after "owner-" + envelope splitting has occurred. + Don't try to sort the queue if there are no entries. Patch from + Luke Mewburn from RMIT University. + Add a "/quit" command to address test mode. + Include the proper sender in the UNIX "From " line and Return-Path: + header when undeliverable mail is saved to ~/dead.letter. + Problem noted by Kari Hurtta of the Finnish Meteorological + Institute. + The contents of a class can now be copied to another class using + the syntax: "C{Dest} $={Source}". This would copy all of + the items in class $={Source} into the class $={Dest}. + Include original envelope's error transcript in bounces created for + split (owner-) envelopes to see the original errors when + the recipients were added. Based on fix from Motonori + Nakamura of Kyoto University. + Show reason for permanent delivery errors directly after the + addresses. From Motonori Nakamura of Kyoto University. + Prevent a segmentation fault when bouncing a split-envelope + message. Patch from Motonori Nakamura of Kyoto University. + If the specification for the queue run interval (-q###) has a + syntax error, consider the error fatal and exit. + Pay attention to CheckpointInterval during LMTP delivery. Problem + noted by Motonori Nakamura of Kyoto University. + On operating systems which have setlogin(2), use it to set the + login name to the RunAsUserName when starting as a daemon. + This is for delivery to programs which use getlogin(). + Based on fix from Motonori Nakamura of Kyoto University. + Differentiate between "command not implemented" and "command + unrecognized" in the SMTP dialogue. + Strip returns from forward and include files. Problem noted by + Allan E Johannesen of Worcester Polytechnic Institute. + Prevent a core dump when using 'sendmail -bv' on an address which + resolves to the $#error mailer with a temporary failure. + Based on fix from Neil Rickert of Northern Illinois + University. + Prevent multiple deliveries of a message with a "non-local alias" + pointing to a local user, if canonicalization fails + the message was requeued *and* delivered to the alias. + If an invalid ruleset is declared, the ruleset name could be + ignored and its rules added to S0. Instead, ignore the + ruleset lines as well. + Avoid incorrect Final-Recipient, Action, and X-Actual-Recipient + success DSN fields as well as duplicate entries for a + single address due to S5 and UserDB processing. Problems + noted by Kari Hurtta of the Finnish Meteorological + Institute. + Turn off timeouts when exiting sendmail due to an interrupt signal + to prevent the timeout from firing during the exit process. + Problem noted by Michael Shapiro of Sun Microsystems. + Do not append @MyHostName to non-RFC822 addresses output by the EXPN + command or on Final-Recipient: and X-Actual-Recipient: DSN + headers. Non-RFC822 addresses include deliveries to + programs, file, DECnet, etc. + Fix logic for determining if a local user is using -f or -bs to + spoof their return address. Based on idea from Neil Rickert + of Northern Illinois University and patch from Per Hedeland + of Ericsson. + Report the proper UID in the bounce message if an :include: file is + owned by a uid that doesn't map to a username and the + :include: file contains delivery to a file or program. + Problem noted by John Beck of Sun Microsystems. + Avoid the attempt of trying to send a second SMTP QUIT command if + the remote server responds to the first QUIT with a 4xx + response code and drops the connection. This behavior was + noted by Ulrich Windl of the Universitat Regensburg when + sendmail was talking to the Mercury 1.43 MTA. + If a hostname lookup times out and ServiceSwitchFile is set but the + file is not present, the lookup failure would be marked as + a permanent failure instead of a temporary failure. Fix + from Russell King of the ARM Linux Project. + Handle aliases or forwards which deliver to programs using tabs + instead of spaces between arguments. Problem noted by Randy + Wormser. Fix from Neil Rickert of Northern Illinois + University. + Allow MaxRecipientsPerMessage option to be set on the command line + by normal users (e.g., sendmail won't drop its root + privileges) to allow overrides for message submission via + 'sendmail -bs'. + Set the names for help file and statistics file to "helpfile" and + "statistics", respectively, if no parameters are given for + them in the .cf file. + Avoid bogus 'errbody: I/O Error -7' log messages when sending + success DSN messages for messages relayed to non-DSN aware + systems. Problem noted by Juergen Georgi of RUS University + of Stuttgart and Kyle Tucker of Parexel International. + Prevent +detail information from interfering with local delivery to + multiple users in the same transaction (F=m). + Add H_FORCE flag for the X-Authentication-Warning: header, so it + will be added even if one already exists. Problem noted + by Michal Zalewski of Marchew Industries. + Stop processing SMTP commands if the SMTP connection is dropped. + This prevents a remote system from flooding the connection + with commands and then disconnecting. Previously, the + server would process all of the buffered commands. Problem + noted by Michal Zalewski of Marchew Industries. + Properly process user-supplied headers beginning with '?'. Problem + noted by Michal Zalewski of Marchew Industries. + If multiple header checks resolve to the $#error mailer, use the + last permanent (5XX) failure if any exist. Otherwise, use + the last temporary (4XX) failure. + RFC 1891 requires "hexchar" in a "xtext" to be upper case. Patch + from Ronald F. Guilmette of Infinite Monkeys & Co. + Timeout.ident now defaults to 5 seconds instead of 30 seconds to + prevent the now common delays associated with mailing to a + site which drops IDENT packets. Suggested by many. + Persistent host status data is not reloaded disk when current data + is available in the in-memory cache. Problem noted by Per + Hedeland of Ericsson. + mailq displays unprintable characters in addresses as their octal + representation and a leading backslash. This avoids problems + with "unprintable" characters. Problem noted by Michal + Zalewski of the "Internet for Schools" project (IdS). + The mail line length limit (L= equate) was adding the '!' indicator + one character past the limit. This would cause subsequent + hops to break the line again. The '!' is now placed in + the last column of the limit if the line needs to be broken. + Problem noted by Joe Pruett of Q7 Enterprises. Based on fix + from Per Hedeland of Ericsson. + If a resolver ANY query is larger than the UDP packet size, the + resolver will fall back to TCP. However, some + misconfigured firewalls black 53/TCP so the ANY lookup + fails whereas an MX or A record might succeed. Therefore, + don't fail on ANY queries. + If an SMTP recipient is rejected due to syntax errors in the + address, do not send an empty postmaster notification DSN + to the postmaster. Problem noted by Neil Rickert of + Northern Illinois University. + Allow '_' and '.' in map names when parsing a sequence map + specification. Patch from William Setzer of North Carolina + State University. + Fix hostname in logging of read timeouts for the QUIT command on + cached connections. Problem noted by Neil Rickert of + Northern Illinois University. + Use a more descriptive entry to log "null" connections, i.e., + "host did not issue MAIL/EXPN/VRFY/ETRN during connection". + Fix a file descriptor leak in ONEX mode. + Portability: + Reverse signal handling logic such that sigaction(2) with + the SA_RESTART flag is the preferred method and the + other signal methods are only tried if SA_RESTART + is not available. Problem noted by Allan E + Johannesen of Worcester Polytechnic Institute. + AIX 4.x supports the sa_len member of struct sockaddr. + This allows network interface probing to work + properly. Fix from David Bronder of the + University of Iowa. + AIX 4.3 has snprintf() support. + Use "PPC" as the architecture name when building under + AIX. This will be reflected in the obj.* directory + name. + Apple Darwin support based on Apple Rhapsody port. + Fixed AIX 'make depend' method from Valdis Kletnieks of + Virginia Tech. + Digital UNIX has uname(2). + GNU Hurd updates from Mark Kettenis of the University of + Amsterdam. + Improved HPUX 11.0 portability. + Properly determine the number of CPUs on FreeBSD 2.X, + FreeBSD 3.X, HP/UX 10.X and HP/UX 11.X. + Remove special IRIX ABI cases from Build script and the OS + files. Use the standard 'cc' options used by SGI + in building the operating system. Users can + override the defaults by setting confCC and + confLIBSEARCHPATH appropriately. + IRIX nsd map support from Bob Mende of SGI. + Minor devtools fixes for IRIX from Bob Mende of SGI. + Linux patch for IP_SRCROUTE support from Joerg Dorchain + of MW EDV & ELECTRONIC. + Linux now uses /usr/sbin for confEBINDIR in the build + system. From MATSUURA Takanori of Osaka University. + Remove special treatment for Linux PPC in the build + system. From MATSUURA Takanori of Osaka University. + Motorolla UNIX SYSTEM V/88 Release 4.0 support from + Sergey Rusanov of the Republic of Udmurtia. + NCR MP-RAS 3.x includes regular expression support. From + Tom J. Moore of NCR. + NEC EWS-UX/V series settings for _PATH_VENDOR_CF and + _PATH_SENDMAILPID from Oota Toshiya of + NEC Computers Group Planning Division. + Minor NetBSD owner/group tweaks from Ayamura Kikuchi, M.D. + NEWS-OS 6.X listed SYSLOG_BUFSIZE as 256 in confENVDEF and + 1024 in conf.h. Since confENVDEF would be used, + use that value in conf.h. + Use NeXT's NETINFO to get domain name. From Gerd Knops of + BITart Consulting. + Use NeXT's NETINFO for alias and hostname resolution if + AUTO_NETINFO_ALIASES and AUTO_NETINFO_HOSTS are + defined. Patch from Wilfredo Sanchez of Apple + Computer, Inc. + NeXT portability tweaks. Problems reported by Dragan + Milicic of the University of Utah and J. P. McCann + of E I A. + New compile flag FAST_PID_RECYCLE: set this if your system + can reuse the same PID in the same second. + New compile flag HASFCHOWN: set this if your OS has + fchown(2). + New compile flag HASRANDOM: set this to 0 if your OS does + not have random(3). rand() will be used instead. + New compile flag HASSRANDOMDEV: set this if your OS has + srandomdev(3). + New compile flag HASSETLOGIN: set this if your OS has + setlogin(2). + Replace SINIX and ReliantUNIX support with version + specific SINIX files. From Gerald Rinske of + Siemens Business Services. + Use the 60-second load average instead of the 5 second load + average on Compaq Tru64 UNIX (formerly Digital + UNIX). From Chris Teakle of the University of Qld. + Use ANSI C by default for Compaq Tru64 UNIX. Suggested by + Randall Winchester of Swales Aerospace. + Correct setgroups() prototype for Compaq Tru64 UNIX. + Problem noted by Randall Winchester of Swales + Aerospace. + Hitachi 3050R/3050RX and 3500 Workstations running + HI-UX/WE2 4.02, 6.10 and 7.10 from Motonori + NAKAMURA of Kyoto University. + New compile flag NO_GETSERVBYNAME: set this to disable + use of getservbyname() on systems which can + not lookup a service by name over NIS, such as + HI-UX. Patch from Motonori NAKAMURA of Kyoto + University. + Use devtools/bin/install.sh on SCO 5.x. Problem noted + by Sun Wenbing of the China Engineering and + Technology Information Network. + make depend didn't work properly on UNIXWARE 4.2. Problem + noted by Ariel Malik of Netology, Ltd. + Use /usr/lbin as confEBINDIR for Compaq Tru64 (Digital UNIX). + Set confSTDIO_TYPE to torek for BSD-OS, FreeBSD, NetBSD, + and OpenBSD. + A recent Compaq Ultrix 4.5 Y2K patch has broken detection + of local_hostname_length(). See sendmail/README + for more details. Problem noted by Allan E + Johannesen of Worcester Polytechnic Institute. + CONFIG: Begin using /etc/mail/ for sendmail related files. This + affects a large number of files. See cf/README for more + details. + CONFIG: New macro MAIL_SETTINGS_DIR contains the path (including + trailing slash) for the mail settings directory. + CONFIG: Increment version number of config file to 9. + CONFIG: OSTYPE(`bsdi1.0') and OSTYPE(`bsdi2.0') have been + deprecated and may be removed from a future release. + BSD/OS users should begin using OSTYPE(`bsdi'). + CONFIG: OpenBSD 2.4 installs mail.local non-setuid root. This + requires a new OSTYPE(`openbsd'). From Todd C. Miller of + Courtesan Consulting. + CONFIG: New OSTYPE(`hpux11') for HP/UX 11.X. + CONFIG: A syntax error in check_mail would cause fake top-level + domains (.BITNET, .DECNET, .FAX, .USENET, and .UUCP) to + be improperly rejected as unresolvable. + CONFIG: New FEATURE(`dnsbl') takes up to two arguments (name of + DNS server, rejection message) and can be included + multiple times. + CONFIG: New FEATURE(`relay_mail_from') allows relaying if the + mail sender is listed as RELAY in the access map (and tagged + with From:). + CONFIG: Optional tagging of LHS in the access map (Connect:, + From:, To:) to enable finer control. + CONFIG: New FEATURE(`ldap_routing') implements LDAP address + routing. See cf/README for a complete description of the + new functionality. + CONFIG: New variables for the new sendmail options: + confAUTH_MECHANISMS AuthMechanisms + confAUTH_OPTIONS AuthOptions + confCLIENT_OPTIONS ClientPortOptions + confCONTROL_SOCKET_NAME ControlSocketName + confDEAD_LETTER_DROP DeadLetterDrop + confDEF_AUTH_INFO DefaultAuthInfo + confDF_BUFFER_SIZE DataFileBufferSize + confLDAP_DEFAULT_SPEC LDAPDefaultSpec + confMAX_ALIAS_RECURSION MaxAliasRecursion + confMAX_HEADERS_LENGTH MaxHeadersLength + confMAX_MIME_HEADER_LENGTH MaxMimeHeaderLength + confPID_FILE PidFile + confPROCESS_TITLE_PREFIX ProcessTitlePrefix + confRRT_IMPLIES_DSN RrtImpliesDsn + confTO_CONTROL Timeout.control + confTO_RESOLVER_RETRANS Timeout.resolver.retrans + confTO_RESOLVER_RETRANS_FIRST Timeout.resolver.retrans.first + confTO_RESOLVER_RETRANS_NORMAL Timeout.resolver.retrans.normal + confTO_RESOLVER_RETRY Timeout.resolver.retry + confTO_RESOLVER_RETRY_FIRST Timeout.resolver.retry.first + confTO_RESOLVER_RETRY_NORMAL Timeout.resolver.retry.normal + confTRUSTED_USER TrustedUser + confXF_BUFFER_SIZE XscriptFileBufferSize + CONFIG: confDAEMON_OPTIONS has been replaced by DAEMON_OPTIONS(), + which takes the options as argument and can be used + multiple times; see cf/README for details. + CONFIG: Add a fifth mailer definition to MAILER(`smtp') called + "dsmtp". This mail provides on-demand delivery using the + F=% mailer flag described above. The "dsmtp" mailer + definition uses the new DSMTP_MAILER_ARGS which defaults + to "IPC $h". + CONFIG: New variables LOCAL_MAILER_MAXMSGS, SMTP_MAILER_MAXMSGS, + and RELAY_MAILER_MAXMSGS for setting the m= equate for the + local, smtp, and relay mailers respectively. + CONFIG: New variable LOCAL_MAILER_DSN_DIAGNOSTIC_CODE for setting + the DSN Diagnostic-Code type for the local mailer. The + value should be changed with care. + CONFIG: FEATURE(`local_lmtp') now sets the DSN Diagnostic-Code type + for the local mailer to the proper value of "SMTP". + CONFIG: All included maps are no longer optional by default; if + there there is a problem with a map, sendmail will + complain. + CONFIG: Removed root from class E; use EXPOSED_USER(`root') + to get the old behavior. Suggested by Joe Pruett + of Q7 Enterprises. + CONFIG: MASQUERADE_EXCEPTION() defines hosts/subdomains which + will not be masqueraded. Proposed by Arne Wichmann + of MPI Saarbruecken, Griff Miller of PGS Tensor, + Jayme Cox of Broderbund Software Inc. + CONFIG: A list of exceptions for FEATURE(`nocanonify') can be + specified by CANONIFY_DOMAIN or CANONIFY_DOMAIN_FILE, + i.e., a list of domains which are passed to $[ ... $] + for canonification. Based on an idea from Neil Rickert + of Northern Illinois University. + CONFIG: If `canonify_hosts' is specified as parameter for + FEATURE(`nocanonify') then addresses which have only + a hostname, e.g., , will be canonified. + CONFIG: If FEATURE(`nocanonify') is turned on, a trailing dot is + nevertheless added to addresses with more than one component + in it. + CONFIG: Canonification is no longer attempted for any host or domain + in class 'P' ($=P). + CONFIG: New class for matching virtusertable entries $={VirtHost} that + can be populated by VIRTUSER_DOMAIN or VIRTUSER_DOMAIN_FILE. + FEATURE(`virtuser_entire_domain') can be used to apply this + class also to entire subdomains. Hosts in this class are + treated as canonical in SCanonify2, i.e., a trailing dot + is added. + CONFIG: If VIRTUSER_DOMAIN() or VIRTUSER_DOMAIN_FILE() are used, + include $={VirtHost} in $=R (hosts allowed to relay). + CONFIG: FEATURE(`generics_entire_domain') can be used to apply the + genericstable also to subdomains of $=G. + CONFIG: Pass "+detail" as %2 for virtusertable lookups. + Patch from Noam Freedman from University of Chicago. + CONFIG: Pass "+detail" as %1 for genericstable lookups. Suggested + by Raymond S Brand of rsbx.net. + CONFIG: Allow @domain in genericstable to override masquerading. + Suggested by Owen Duffy from Owen Duffy & Associates. + CONFIG: LOCAL_DOMAIN() adds entries to class w. Suggested by Steve + Hubert of University of Washington. + CONFIG: OSTYPE(`gnuhurd') has been replaced by OSTYPE(`gnu') as + GNU is now the canonical system name. From Mark + Kettenis of the University of Amsterdam. + CONFIG: OSTYPE(`unixware7') updates from Larry Rosenman. + CONFIG: Do not include '=' in option expansion if there is no value + associated with the option. From Andrew Brown of + Graffiti World Wide, Inc. + CONFIG: Add MAILER(`qpage') to define a new pager mailer. Contributed + by Philip A. Prindeville of Enteka Enterprise Technology + Services. + CONFIG: MAILER(`cyrus') was not preserving case for mail folder + names. Problem noted by Randall Winchester of Swales + Aerospace. + CONFIG: RELAY_MAILER_FLAGS can be used to define additional flags + for the relay mailer. Suggested by Doug Hughes of Auburn + University and Brian Candler. + CONFIG: LOCAL_MAILER_FLAGS now includes 'P' (Add Return-Path: + header) by default. Suggested by Per Hedeland of Ericsson. + CONFIG: Use SMART_HOST for bracketed addresses, e.g., user@[host]. + Suggested by Kari Hurtta of the Finnish Meteorological + Institute. + CONFIG: New macro MODIFY_MAILER_FLAGS to tweak *_MAILER_FLAGS; + i.e., to set, add, or delete flags. + CONFIG: If SMTP AUTH is used then relaying is allowed for any user + who authenticated via a "trusted" mechanism, i.e., one that + is defined via TRUST_AUTH_MECH(`list of mechanisms'). + CONFIG: FEATURE(`delay_checks') delays check_mail and check_relay + after check_rcpt and allows for exceptions from the checks. + CONFIG: Map declarations have been moved into their associated + feature files to allow greater flexibility in use of + sequence maps. Suggested by Per Hedeland of Ericsson. + CONFIG: New macro LOCAL_MAILER_EOL to override the default end of + line string for the local mailer. Requested by Il Oh of + Willamette Industries, Inc. + CONFIG: Route addresses are stripped, i.e., <@a,@b,@c:user@d> is + converted to + CONFIG: Reject bogus return address of <@@hostname>, generated by + Sun's older, broken configuration files. + CONFIG: FEATURE(`nullclient') now provides the full rulesets of a + normal configuration, allowing anti-spam checks to be + performed. + CONFIG: Don't return a permanent error (Relaying denied) if + ${client_name} can't be resolved just temporarily. + Suggested by Kari Hurtta of the Finnish Meteorological + Institute. + CONFIG: Change numbered rulesets into named (which still can + be accessed by their numbers). + CONFIG: FEATURE(`nouucp') takes one parameter: reject or nospecial + which describes whether to disallow "!" in the local part + of an address. + CONFIG: Call Local_localaddr from localaddr (S5) which can be used + to rewrite an address from a mailer which has the F=5 flag + set. If the ruleset returns a mailer, the appropriate + action is taken, otherwise the returned tokens are ignored. + CONFIG: cf/ostype/solaris.m4 has been renamed to solaris2.pre5.m4 + and cf/ostype/solaris2.m4 is now a copy of solaris2.ml.m4. + The latter is kept around for backward compatibility. + CONFIG: Allow ":D.S.N:" for mailer/virtusertable "error:" entries, + where "D.S.N" is an RFC 1893 compliant error code. + CONFIG: Use /usr/lbin as confEBINDIR for Compaq Tru64 (Digital UNIX). + CONFIG: Remove second space between username and date in UNIX From_ + line. Noted by Allan E Johannesen of Worcester Polytechnic + Institute. + CONFIG: Make sure all of the mailers have complete T= equates. + CONFIG: Extend FEATURE(`local_procmail') so it can now take + arguments overriding the mailer program, arguments, and + mailer definition flags. This makes it possible to use + other programs such as maildrop for local delivery. + CONFIG: Emit warning if FEATURE(`local_lmtp') or + FEATURE(`local_procmail') is given after MAILER(`local'). + Patch from Richard A. Nelson of IBM. + CONFIG: Add SMTP Authentication information to Received: header + default value (confRECEIVED_HEADER). + CONFIG: Remove `l' flag from USENET_MAILER_FLAGS as it is not a + local mailer. Problem noted by Per Hedeland of Ericsson. + CONTRIB: Added bounce-resender.pl from Brian R. Gaeke of the + University of California at Berkeley. + CONTRIB: Added domainmap.m4 from Mark D. Roth of the University of + Illinois at Urbana-Champaign. + CONTRIB: etrn.pl now recognizes bogus host names. Patch from + Bruce Barnett of GE's R&D Lab. + CONTRIB: Patches for re-mqueue.pl by Graeme Hewson of Oracle + Corporation UK. + CONTRIB: Added qtool.pl to assist in managing the queues. + DEVTOOLS: Prevent user environment variables from interfering with + the Build scripts. Problem noted by Ezequiel H. Panepucci of + Yale University. + DEVTOOLS: 'Build -M' will display the obj.* directory which will + be used for building. + DEVTOOLS: 'Build -A' will display the architecture that would be + used for a fresh build. + DEVTOOLS: New variable confRANLIB, set automatically by configure.sh. + DEVTOOLS: New variable confRANLIBOPTS for the options to send to + ranlib. + DEVTOOLS: 'Build -O ' will have the object files build in + /obj.*. Suggested by Bryan Costales of Exactis. + DEVTOOLS: New variable confNO_MAN_BUILD which will prevent the + building of the man pages when defined. Suggested by Bryan + Costales. + DEVTOOLS: New variables confNO_HELPFILE_INSTALL and + confNO_STATISTICS_INSTALL which will prevent the + installation of the sendmail helpfile and statistics file + respectively. Suggested by Bryan Costales. + DEVTOOLS: Recognize ReliantUNIX as SINIX. Patch from Gerald Rinske + of Siemens Business Services. + DEVTOOLS: New variable confSTDIO_TYPE which defines the type of + stdio library. The new buffered file I/O depends on the + Torek stdio library. This option can be either portable or + torek. + DEVTOOLS: New variables confSRCADD and confSMSRCADD which + correspond to confOBJADD and confSMOBJADD respectively. + They should contain the C source files for the object files + listed in confOBJADD and confSMOBJADD. These file names + will be passed to the 'make depend' stage of compilation. + DEVTOOLS: New program specific variables for each of the programs + in the sendmail distribution. Each has the form + `conf_prog_ENVDEF', for example, `conf_sendmail_ENVDEF'. + The new variables are conf_prog_ENVDEF, conf_prog_LIBS, + conf_prog_SRCADD, and conf_prog_OBJADD. + DEVTOOLS: Build system redesign. This should have little affect on + building the distribution, but documentation on the changes + are in devtools/README. + DEVTOOLS: Don't allow 'Build -f file' if an object directory already + exists. Suggested by Valdis Kletnieks of Virginia Tech. + DEVTOOLS: Rename confSRCDIR to confSMSRCDIR since it only identifies + the path to the sendmail source directory. confSRCDIR is a + new variable which identifies the root of the source + directories for all of the programs in the distribution. + DEVTOOLS: confSRCDIR and confSMSRCDIR are now determined at Build + time. They can both still be overridden by setting the m4 + macro. + DEVTOOLS: confSBINGRP now defaults to bin instead of kmem. + DEVTOOLS: 'Build -Q prefix' uses devtools/Site/prefix.*.m4 for + build configurations, and places objects in obj.prefix.*/. + Complains as 'Build -f file' does for existing object + directories. Suggested by Tom Smith of Digital Equipment + Corporation. + DEVTOOLS: Setting confINSTALL_RAWMAN will install unformatted + manual pages in the directory tree specified by + confMANROOTMAN. + DEVTOOLS: If formatting the manual pages fails, copy in the + preformatted pages from the distribution. The new variable + confCOPY specifies the copying program. + DEVTOOLS: Defining confFORCE_RMAIL will install rmail without + question. Suggested by Terry Lambert of Whistle + Communications. + DEVTOOLS: confSTFILE and confHFFILE can be used to change the names + of the installed statistics and help files, respectively. + DEVTOOLS: Remove spaces in `uname -r` output when determining + operating system identity. Problem noted by Erik + Wachtenheim of Dartmouth College. + DEVTOOLS: New variable confLIBSEARCHPATH to specify the paths that + will be search for the libraries specified in confLIBSEARCH. + Defaults to "/lib /usr/lib /usr/shlib". + DEVTOOLS: New variables confSTRIP and confSTRIPOPTS for specifying + how to strip binaries. These are used by the new + install-strip target. + DEVTOOLS: New config file site.post.m4 which is included after + the others (if it exists). + DEVTOOLS: Change order of LIBS: first product specific libraries + then the default ones. + MAIL.LOCAL: Will not be installed setuid root. To use mail.local + as local delivery agent without LMTP mode, use + MODIFY_MAILER_FLAGS(`LOCAL', `+S') + to set the S flag. + MAIL.LOCAL: Do not reject addresses which would otherwise be + accepted by sendmail. Suggested by Neil Rickert of + Northern Illinois University. + MAIL.LOCAL: New -7 option which causes LMTP mode not to advertise + 8BITMIME in the LHLO response. Suggested by Kari Hurtta of + the Finnish Meteorological Institute. + MAIL.LOCAL: Add support for the maillock() routines by defining + MAILLOCK when compiling. Also requires linking with + -lmail. Patch from Neil Rickert of Northern Illinois + University. + MAIL.LOCAL: Create a Content-Length; header if CONTENTLENGTH is + defined when compiling. Automatically set for Solaris 2.3 + and later. Patch from Neil Rickert of Northern Illinois + University. + MAIL.LOCAL: Move the initialization of the 'notifybiff' address + structure to the beginning of the program. This ensures that + the getservbyname() is done before any seteuid to a possibly + unauthenticated user. If you are using NIS+ and secure RPC + on a Solaris system, this avoids syslog messages such as, + "authdes_refresh: keyserv(1m) is unable to encrypt session + key." Patch from Neil Rickert of Northern Illinois + University. + MAIL.LOCAL: Support group writable mail spool files when MAILGID is + set to the gid to use (-DMAILGID=6) when compiling. + Patch from Neil Rickert of Northern Illinois University. + MAIL.LOCAL: When a mail message includes lines longer than 2046 + characters (in LMTP mode), mail.local will split the + incoming line up into 2046-character output lines + (excluding the newline). If an input line is 2047 + characters long (excluding CR-LF) and the last character is + a '.', mail.local will see it as the end of input, transfer + it to the user mailbox and try to write an `ok' back to + sendmail. If the message was much longer, both sendmail + and mail.local will deadlock waiting for each other to read + what they have written. Problem noted by Peter Jeremy of + Alcatel Australia Limited. + MAIL.LOCAL: New option -b to return a permanent error instead of a + temporary error if a mailbox exceeds quota. Suggested by + Neil Rickert of Northern Illinois University. + MAIL.LOCAL: The creation of a lockfile is subject to a global + timeout to avoid starvation. + MAIL.LOCAL: Properly parse addresses with multiple quoted + local-parts. Problem noted by Ronald F. Guilmette of + Infinite Monkeys & Co. + MAIL.LOCAL: NCR MP/RAS 3.X portability from Tom J. Moore of NCR. + MAILSTATS: New -p option to invoke program mode in which stats are + printed in a machine readable fashion and the stats file + is reset. Patch from Kevin Hildebrand of the University + of Maryland. + MAKEMAP: If running as root, automatically change the ownership of + generated maps to the TrustedUser as specified in the + sendmail configuration file. + MAKEMAP: New -C option to accept an alternate sendmail + configuration file to use for finding the TrustedUser + option. + MAKEMAP: New -u option to dump (unmap) a database. Based on + code contributed by Roy Mongiovi of Georgia Tech. + MAKEMAP: New -e option to allow empty values. Suggested by Philip + A. Prindeville of Enteka Enterprise Technology Services. + MAKEMAP: Compile cleanly on 64-bit operating systems. Problem + noted by Gerald Rinske of Siemens Business Services. + OP.ME: Correctly document interaction between F=S and U= mailer + equates. Problem noted by Bob Halley of Internet Engines. + OP.ME: Fixup Timeout documentation. From Graeme Hewson of Oracle + Corporation UK. + OP.ME: The Timeout [r] option was incorrectly listed as "safe" + (e.g., sendmail would not drop root privileges if the + option was specified on the command line). Problem noted + by Todd C. Miller of Courtesan Consulting. + PRALIASES: Handle the hash and btree map specifications for + Berkeley DB. Patch from Brian J. Coan of the + Institute for Global Communications. + PRALIASES: Read the sendmail.cf file for the location(s) of the + alias file(s) if the -f option is not used. Patch from + John Beck of Sun Microsystems. + PRALIASES: New -C option to specify an alternate sendmail + configuration file to use for finding alias file(s). Patch + from John Beck of Sun Microsystems. + SMRSH: allow shell commands echo, exec, and exit. Allow command + lists using || and &&. Based on patch from Brian J. Coan + of the Institute for Global Communications. + SMRSH: Update README for the new Build system. From Tim Pierce + of RootsWeb Genealogical Data Cooperative. + VACATION: Added vacation auto-responder to sendmail distribution. + LIBSMDB: Added abstracted database library. Works with Berkeley + DB 1.85, Berkeley DB 2.X, Berkeley DB 3.X, and NDBM. + Changed Files: + The Build script in the various program subdirectories are + no longer symbolic links. They are now scripts + which execute the actual Build script in + devtools/bin. + All the manual pages are now written against -man and not + -mandoc as they were previously. + Add a simple Makefile to every directory so make instead + of Build will work (unless parameters are + required for Build). + New Directories: + devtools/M4/UNIX + include + libmilter + libsmdb + libsmutil + vacation + Renamed Directories: + BuildTools => devtools + src => sendmail + Deleted Files: + cf/m4/nullrelay.m4 + devtools/OS/Linux.ppc + devtools/OS/ReliantUNIX + devtools/OS/SINIX + sendmail/ldap_map.h + New Files: + INSTALL + PGPKEYS + cf/cf/generic-linux.cf + cf/cf/generic-linux.mc + cf/feature/delay_checks.m4 + cf/feature/dnsbl.m4 + cf/feature/generics_entire_domain.m4 + cf/feature/no_default_msa.m4 + cf/feature/relay_mail_from.m4 + cf/feature/virtuser_entire_domain.m4 + cf/mailer/qpage.m4 + cf/ostype/bsdi.m4 + cf/ostype/hpux11.m4 + cf/ostype/openbsd.m4 + contrib/bounce-resender.pl + contrib/domainmap.m4 + contrib/qtool.8 + contrib/qtool.pl + devtools/M4/depend/AIX.m4 + devtools/M4/list.m4 + devtools/M4/string.m4 + devtools/M4/subst_ext.m4 + devtools/M4/switch.m4 + devtools/OS/Darwin + devtools/OS/GNU + devtools/OS/SINIX.5.43 + devtools/OS/SINIX.5.44 + devtools/OS/m88k + devtools/bin/find_in_path.sh + mail.local/Makefile + mailstats/Makefile + makemap/Makefile + praliases/Makefile + rmail/Makefile + sendmail/Makefile + sendmail/bf.h + sendmail/bf_portable.c + sendmail/bf_portable.h + sendmail/bf_torek.c + sendmail/bf_torek.h + sendmail/shmticklib.c + sendmail/statusd_shm.h + sendmail/timers.c + sendmail/timers.h + smrsh/Makefile + vacation/Makefile + Renamed Files: + cf/ostype/gnuhurd.m4 => cf/ostype/gnu.m4 + sendmail/cdefs.h => include/sendmail/cdefs.h + sendmail/sendmail.hf => sendmail/helpfile + sendmail/mailstats.h => include/sendmail/mailstats.h + sendmail/pathnames.h => include/sendmail/pathnames.h + sendmail/safefile.c => libsmutil/safefile.c + sendmail/snprintf.c => libsmutil/snprintf.c + sendmail/useful.h => include/sendmail/useful.h + cf/ostype/solaris2.m4 => cf/ostype/solaris2.pre5.m4 + Copied Files: + cf/ostype/solaris2.ml.m4 => cf/ostype/solaris2.m4 + +8.9.3/8.9.3 1999/02/04 + SECURITY: Limit message headers to a maximum of 32K bytes (total + of all headers in a single message) to prevent a denial of + service attack. This limit will be configurable in 8.10. + Problem noted by Michal Zalewski of the "Internet for + Schools" project (IdS). + Prevent segmentation fault on an LDAP lookup if the LDAP map + was closed due to an earlier failure. Problem noted by + Jeff Wasilko of smoe.org. Fix from Booker Bense of + Stanford University and Per Hedeland of Ericsson. + Preserve the order of the MIME headers in multipart messages + when performing the MIME header length check. This + will allow PGP signatures to function properly. Problem + noted by Lars Hecking of University College, Cork, Ireland. + If ruleset 5 rewrote the local address to an :include: directive, + the delivery would fail with an "aliasing/forwarding loop + broken" error. Problem noted by Eric C Hagberg of Morgan + Stanley. Fix from Per Hedeland of Ericsson. + Allow -T to work for bestmx maps. Fix from Aaron Schrab of + ExecPC Internet Systems. + During the transfer of a message in an SMTP transaction, if a + TCP timeout occurs, the message would be properly queued + for later retry but the failure would be logged as + "Illegal Seek" instead of a timeout. Problem noted by + Piotr Kucharski of the Warsaw School of Economics (SGH) + and Carles Xavier Munyoz Baldo of CTV Internet. + Prevent multiple deliveries on a self-referencing alias if the + F=w mailer flag is not set. Problem noted by Murray S. + Kucherawy of Concentric Network Corporation and Per + Hedeland of Ericsson. + Do not strip empty headers but if there is no value and a + default is defined in sendmail.cf, use the default. + Problem noted by Philip Guenther of Gustavus Adolphus + College and Christopher McCrory of Netus, Inc. + Don't inherit information about the sender (notably the full name) + in SMTP (-bs) mode, since this might be called from inetd. + Accept any 3xx reply code in response to DATA command instead of + requiring 354. This change will match the wording to be + published in the updated SMTP specification from the DRUMS + group of the IETF. + Portability: + AIX 4.2.0 or 4.2.1 may become updated by the fileset + bos.rte.net level 4.2.0.2. This introduces the + softlink /usr/lib/libbind.a which should + not be used. It conflicts with the resolver + built into libc.a. "bind" has been removed + from the confLIBSEARCH BuildTools variable. + Users who have installed BIND 8.X will have + to add it back in their site.config.m4 file. + Problem noted by Ole Holm Nielsen of the + Technical University of Denmark. + CRAY TS 10.0.x from Sven Nielsen of San Diego + Supercomputer Center. + Improved LDAP version 3 integration based on input + from Kurt D. Zeilenga of the OpenLDAP Foundation, + John Beck of Sun Microsystems, and Booker Bense + of Stanford University. + Linux doesn't have a standard way to get the timezone + between different releases. Back out the + change in 8.9.2 and don't attempt to derive + a timezone. Problem reported by Igor S. Livshits + of the University of Illinois at Urbana-Champaign + and Michael Dickens of Tetranet Communications. + Reliant UNIX, the new name for SINIX, from Gert-Jan Looy + of Siemens/SNI. + SunOS 5.8 from John Beck of Sun Microsystems. + CONFIG: SCO UnixWare 2.1 and 7.0 need TZ to get the proper + timezone. Problem noted by Petr Lampa of Technical + University of Brno. + CONFIG: Handle <@bestmx-host:user@otherhost> addressing properly + when using FEATURE(bestmx_is_local). Patch from Neil W. + Rickert of Northern Illinois University. + CONFIG: Properly handle source routed and %-hack addresses on + hosts which the mailertable remaps to local:. Patch from + Neil W. Rickert of Northern Illinois University. + CONFIG: Internal fixup of mailertable local: map value. Patch from + Larry Parmelee of Cornell University. + CONFIG: Only add back +detail from host portion of mailer triplet + on local mailer triplets if it was originally +detail. + Patch from Neil W. Rickert of Northern Illinois University. + CONFIG: The bestmx_is_local checking done in check_rcpt would + cause later checks to fail. Patch from Paul J Murphy of + MIDS Europe. + New Files: + BuildTools/OS/CRAYTS.10.0.x + BuildTools/OS/ReliantUNIX + BuildTools/OS/SunOS.5.8 + +8.9.2/8.9.2 1998/12/30 + SECURITY: Remove five second sleep on accepting daemon connections + due to an accept() failure. This sleep could be used + for a denial of service attack. + Do not silently ignore queue files with names which are too long. + Patch from Bryan Costales of InfoBeat, Inc. + Do not store failures closing an SMTP session in persistent + host status. Reported by Graeme Hewson of Oracle + Corporation UK. + Allow symbolic link forward files if they are in safe directories. + Problem noted by Andreas Schott of the Max Planck Society. + Missing columns in a text map could cause a segmentation fault. + Fix from David Lee of the University of Durham. + Note that for 8.9.X, PrivacyOptions=goaway also includes the + noetrn flag. This is scheduled to change in a future + version of sendmail. Problem noted by Theo Van Dinter of + Chrysalis Symbolic Designa and Alan Brown of Manawatu + Internet Services. + When trying to do host canonification in a Wildcard MX + environment, try an MX lookup of the hostname without the + default domain appended. Problem noted by Olaf Seibert of + Polderland Language & Speech Technology. + Reject SMTP RCPT To: commands with only comments (i.e. + 'RCPT TO: (comment)'. Problem noted by Earle Ake of + Hassler Communication Systems Technology, Inc. + Handle any number of %s in the LDAP filter spec. Patch from + Per Hedeland of Ericsson. + Clear ldapx open timeouts even if the map open failed to prevent + a segmentation fault. Patch from Wayne Knowles of the + National Institute of Water & Atmospheric Research Ltd. + Do not syslog envelope clone messages when using address + verification (-bv). Problem noted by Kari Hurtta of the + Finnish Meteorological Institute. + Continue to perform queue runs while in daemon mode even if the + daemon is rejecting connections due to a disk full + condition. Problem noted by JR Oldroyd of TerraNet + Internet Services. + Include full filename on installation of the sendmail.hf file + in case the $HFDIR directory does not exist. Problem + noted by Josef Svitak of Montana State University. + Close all maps when exiting the process with one exception. + Berkeley DB can use internal shared memory locking for + its memory pool. Closing a map opened by another process + will interfere with the shared memory and locks of the + parent process leaving things in a bad state. For + Berkeley DB, only close the map if the current process + is also the one that opened the map, otherwise only close + the map file descriptor. Thanks to Yoseff Francus of + Collective Technologies for volunteering his system for + extended testing. + Avoid null pointer dereference on XDEBUG output for SMTP reply + failures. Problem noted by Carlos Canau of EUnet Portugal. + On mailq and hoststat listings being piped to another program, such + as more, if the pipe closes (i.e., the user quits more), + stop sending output and exit. Patch from Allan E Johannesen + of Worcester Polytechnic Institute. + In accordance with the documentation, LDAP map lookup failures + are now considered temporary failures instead of permanent + failures unless the -t flag is used in the map definition. + Problem noted by Booker Bense of Stanford University and + Eric C. Hagberg of Morgan Stanley. + Fix by one error reporting on long alias names. Problem noted by + H. Paul Hammann of the Missouri Research and Education + Network. + Fix DontBlameSendmail=IncludeFileInUnsafeDirPath behavior. Problem + noted by Barry S. Finkel of Argonne National Laboratory. + When automatically converting from 8 bit to quoted printable MIME, + be careful not to miss a multi-part boundary if that + boundary is preceded by a boundary-like line. Problem + noted by Andreas Raschle of Ansid Inc. Fix from + Kari Hurtta of the Finnish Meteorological Institute. + Avoid bogus reporting of "LMTP tobuf overflow" when the buffer + has enough space for the additional address. Problem + noted by Steve Cliffe of the University of Wollongong. + Fix DontBlameSendmail=FileDeliveryToSymlink behavior. Problem + noted by Alex Vorobiev of Swarthmore College. + If the check_compat ruleset resolves to the $#discard mailer, + discard the current recipient. Unlike check_relay, + check_mail, and check_rcpt, the entire envelope is not + discarded. Problem noted by RZ D. Rahlfs. Fix from + Claus Assmann of Christian-Albrechts-University of Kiel. + Avoid segmentation fault when reading ServiceSwitchFile files with + bogus formatting. Patch from Kari Hurtta of the Finnish + Meteorological Institute. + Support Berkeley DB 2.6.4 API change. + OP.ME: Pages weren't properly output on duplexed printers. Fix + from Matthew Black of CSU Long Beach. + Portability: + Apple Rhapsody from Wilfredo Sanchez of Apple Computer, Inc. + Avoid a clash with IRIX 6.2 getopt.h and the UserDatabase + option structure. Problem noted by Ashley M. + Kirchner of Photo Craft Laboratories, Inc. + Break out IP address to hostname translation for + reading network interface addresses into + class 'w'. Patch from John Kennedy of + Cal State University, Chico. + AIX 4.x use -qstrict with -O3 to prevent the optimized + from changing the semantics of the compiled + program. From Simon Travaglia of the + University of Waikato, New Zealand. + FreeBSD 2.2.2 and later support setusercontext(). From + Peter Wemm of DIALix. + FreeBSD 3.x fix from Peter Wemm of DIALix. + IRIX 5.x has a syslog buffer size of 512 bytes. From + Nao NINOMIYA of Utsunomiya University. + IRIX 6.5 64-bit Build support. + LDAP Version 3 support from John Beck and Ravi Iyer + of Sun Microsystems. + Linux does not implement seteuid() properly. From + John Kennedy of Cal State University, Chico. + Linux timezone type was set improperly. From Takeshi Itoh + of Bits Co., Ltd. + NCR MP-RAS 3.x needs -lresolv for confLIBS. From + Tom J. Moore of NCR. + NeXT 4.x correction to man page path. From J. P. McCann + of E I A. + System V Rel 5.x (a.k.a UnixWare7 w/o BSD-Compatibility Libs) + from Paul Gampe of the Asia Pacific Network + Information Center. + ULTRIX now requires an optimization limit of 970 from + Allan E Johannesen of Worcester Polytechnic + Institute. + Fix extern declaration for sm_dopr(). Fix from Henk + van Oers of Algemeen Nederlands Persbureau. + CONFIG: Catch @hostname,user@anotherhost.domain as relaying. + Problem noted by Mark Rogov of AirMedia, Inc. Fix from + Claus Assmann of Christian-Albrechts-University of Kiel. + CONFIG: Do not refer to http://maps.vix.com/ on RBL rejections as + there are multiple RBL's available and the MAPS RBL may + not be the one in use. Suggested by Alan Brown of + Manawatu Internet Services. + CONFIG: Properly strip route addresses (i.e., @host1:user@host2) + when stripping down a recipient address to check for + relaying. Patch from Claus Assmann of + Christian-Albrechts-University of Kiel and Neil W Rickert + of Northern Illinois University. + CONFIG: Allow the access database to override RBL lookups. Patch + from Claus Assmann of Christian-Albrechts-University of + Kiel. + CONFIG: UnixWare 7 support from Phillip P. Porch of The Porch + Dot Com. + CONFIG: Fixed check for deferred delivery mode warning. Patch + from Claus Assmann of Christian-Albrechts-University of + Kiel and Per Hedeland of Ericsson. + CONFIG: If a recipient using % addressing is used, e.g. + user%site@othersite, and othersite's MX records are now + checked for local hosts if FEATURE(relay_based_on_MX) is + used. Problem noted by Alexander Litvin of Lucky Net Ltd. + Patch from Alexander Litvin of Lucky Net Ltd and + Claus Assmann of Christian-Albrechts-University of Kiel. + MAIL.LOCAL: Prevent warning messages from appearing in the LMTP + stream. Do not allow more than one response per recipient. + MAIL.LOCAL: Handle routed addresses properly when using LMTP. Fix + from John Beck of Sun Microsystems. + MAIL.LOCAL: Properly check for CRLF when using LMTP. Fix from + John Beck of Sun Microsystems. + MAIL.LOCAL: Substitute MAILER-DAEMON for the LMTP empty sender in + the envelope From header. + MAIL.LOCAL: Accept underscores in hostnames in LMTP mode. + Problem noted by Glenn A. Malling of Syracuse University. + MAILSTATS: Document msgsrej and msgsdis fields in the man page. + Problem noted by Richard Wong of Princeton University. + MAKEMAP: Build group list so group writable files are allowed with + the -s flag. Problem noted by Curt Sampson of Internet + Portal Services, Inc. + PRALIASES: Automatically handle alias files created without the + NULL byte at the end of the key. Patch from John Beck of + Sun Microsystems. + PRALIASES: Support Berkeley DB 2.6.4 API change. + New Files: + BuildTools/OS/IRIX64.6.5 + BuildTools/OS/UnixWare.5.i386 + cf/ostype/unixware7.m4 + contrib/smcontrol.pl + src/control.c + +8.9.1/8.9.1 1998/07/02 + If both an OS specific site configuration file and a generic + site.config.m4 file existed, only the latter was used + instead of both. Problem noted by Geir Johannessen of + the Norwegian University of Science and Technology. + Fix segmentation fault while converting 8 bit to 7 bit MIME + multipart messages by trying to write to an unopened + file descriptor. Fix from Kari Hurtta of the Finnish + Meteorological Institute. + Do not assume Message: and Text: headers indicate the end of + the header area when parsing MIME headers. Problem noted + by Kari Hurtta of the Finnish Meteorological Institute. + Setting the confMAN#SRC Build variable would only effect the + installation commands. The man pages would still be + built with .0 extensions. Problem noted by Bryan + Costales of InfoBeat, Inc. + Installation of manual pages didn't honor the DESTDIR environment + variable. Problem noted by Bryan Costales of InfoBeat, Inc. + If the check_relay ruleset resolved to the discard mailer, messages + were still delivered. Problem noted by Mirek Luc of NASK. + Mail delivery to files would fail with an Operating System Error + if sendmail was not running as root, i.e., RunAsUser was set. + Problem noted by Leonard N. Zubkoff of Dandelion Digital. + Prevent MinQueueAge from interfering from queued items created + in the future, i.e., if the system clock was set ahead + and then back. Problem noted by Michael Miller of the + University of Natal, Pietermaritzburg. + Do not advertise ETRN support in ESTMP EHLO reply if noetrn is + set in the PrivacyOptions option. Fix from Ted Rule of + Flextech TV. + Log invalid persistent host status file lines instead of + bouncing the message. Problem noted by David Lindes of + DaveLtd Enterprises. + Move creation of empty sendmail.st file from installation to + compilation. Installation may be done from a read-only + mount. Fix from Bryan Costales of InfoBeat, Inc. and Ric + Anderson of the Oasis Research Center, Inc. + Enforce the maximum number of User Database entries limit. Problem + noted by Gary Buchanan of Credence Systems Inc. + Allow dead.letter files in root's home directory. Problem noted + by Anna Ullman of Sun Microsystems. + Program deliveries in forward files could be marked unsafe if + any directory listed in the ForwardPath option did not + exist. Problem noted by Jorg Bielak of Coastal Web Online. + Do not trust the length of the address structure returned by + gethostbyname(). Problem noted by Chris Evans of Oxford + University. + If the SIZE= MAIL From: ESMTP parameter is too large, use the + 5.3.4 DSN status code instead of 5.2.2. Similarly, for + non-local deliveries, if the message is larger than the + mailer maximum message size, use 5.3.4 instead of 5.2.3. + Suggested by Antony Bowesman of + Fujitsu/TeaWARE Mail/MIME System. + Portability: + Fix the check for an IP address reverse lookup for + use in $&{client_name} on 64 bit platforms. + From Gilles Gallot of Institut for Development + and Resources in Intensive Scientific computing. + BSD-OS uses .0 for man page extensions. From Jeff Polk + of BSDI. + DomainOS detection for Build. Also, version 10.4 and later + ship a unistd.h. Fixes from Takanobu Ishimura of + PICT Inc. + NeXT 4.x uses /usr/lib/man/cat for its man pages. From + J. P. McCann of E I A. + SCO 4.X and 5.X include NDBM support. From Vlado Potisk + of TEMPEST, Ltd. + CONFIG: Do not pass spoofed PTR results through resolver for + qualification. Problem noted by Michiel Boland of + Digital Valley Internet Professionals; fix from + Kari Hurtta of the Finnish Meteorological Institute. + CONFIG: Do not try to resolve non-DNS hostnames such as UUCP, + BITNET, and DECNET addresses for resolvable senders. + Problem noted by Alexander Litvin of Lucky Net Ltd. + CONFIG: Work around Sun's broken configuration which sends bounce + messages as coming from @@hostname instead of <>. LMTP + would not accept @@hostname. + OP.ME: Corrections to complex sendmail startup script from Rick + Troxel of the National Institutes of Health. + RMAIL: Do not install rmail by default, require 'make force-install' + as this rmail isn't the same as others. Suggested by + Kari Hurtta of the Finnish Meteorological Institute. + New Files: + BuildTools/OS/DomainOS.10.4 + +8.9.0/8.9.0 1998/05/19 + SECURITY: To prevent users from reading files not normally + readable, sendmail will no longer open forward, :include:, + class, ErrorHeader, or HelpFile files located in unsafe + (i.e., group or world writable) directory paths. Sites + which need the ability to override security can use the + DontBlameSendmail option. See the README file for more + information. + SECURITY: Problems can occur on poorly managed systems, specifically, + if maps or alias files are in world writable directories. + This fixes the change added to 8.8.6 to prevent links in these + world writable directories. + SECURITY: Make sure ServiceSwitchFile option file is not a link if + it is in a world writable directory. + SECURITY: Never pass a tty to a mailer -- if a mailer can get at the + tty it may be able to push bytes back to the senders input. + Unfortunately this breaks -v mode. Problem noted by + Wietse Venema of the Global Security Analysis Lab at + IBM T.J. Watson Research. + SECURITY: Empty group list if DontInitGroups is set to true to + prevent program deliveries from picking up extra group + privileges. Problem reported by Wolfgang Ley of DFN-CERT. + SECURITY: The default value for DefaultUser is now set to the uid and + gid of the first existing user mailnull, sendmail, or daemon + that has a non-zero uid. If none of these exist, sendmail + reverts back to the old behavior of using uid 1 and gid 1. + This is a security problem for Linux which has chosen that + uid and gid for user bin instead of daemon. If DefaultUser + is set in the configuration file, that value overrides this + default. + SECURITY: Since 8.8.7, the check for non-setuid binaries + interfered with setting an alternate group id for the + RunAsUser option. Problem noted by Randall Winchester of + the University of Maryland. + Add support for Berkeley DB 2.X. Based on patch from John Kennedy + of Cal State University, Chico. + Remove support for OLD_NEWDB (pre-1.5 version of Berkeley DB). Users + which previously defined OLD_NEWDB=1 must now upgrade to the + current version of Berkeley DB. + Added support for regular expressions using the new map class regex. + From Jan Krueger of Unix-AG of University of Hannover. + Support for BIND 8.1.1's hesiod for hesiod maps and hesiod + UserDatabases from Randall Winchester of the University + of Maryland. + Allow any shell for user shell on program deliveries on V1 + configurations for backwards compatibility on machines which + do not have getusershell(). Fix from John Beck of Sun + Microsystems. + On operating systems which change the process title by reusing the + argument vector memory, sendmail could corrupt memory if the + last argument was either "-q" or "-d". Problem noted by + Frank Langbein of the University of Stuttgart. + Support Local Mail Transfer Protocol (LMTP) between sendmail and + mail.local on the F=z flag. + Macro-expand the contents of the ErrMsgFile. Previously this was + only done if you had magic characters (0x81) to indicate + macro expansion. Now $x will be expanded. This means that + real dollar signs have to be backslash escaped. + TCP Wrappers expects "unknown" in the hostname argument if the + reverse DNS lookup for the incoming connection fails. + Problem noted by Randy Grimshaw of Syracuse University and + Wietse Venema of the Global Security Analysis Lab at + IBM T.J. Watson Research. + DSN success bounces generated from an invocation of sendmail -t + would be sent to both the sender and MAILER-DAEMON. + Problem noted by Claus Assmann of + Christian-Albrechts-University of Kiel. + Avoid "Error 0" messages on delivery mailers which exit with a + valid exit value such as EX_NOPERM. Fix from Andreas Luik + of ISA Informationssysteme GmbH. + Tokenize $&x expansions on right hand side of rules. This eliminates + the need to use tricks like $(dequote "" $&{client_name} $) + to cause the ${client_name} macro to be properly tokenized. + Add the MaxRecipientsPerMessage option: this limits the number of + recipients that will be accepted in a single SMTP + transaction. After this number is reached, sendmail + starts returning "452 Too many recipients" to all RCPT + commands. This can be used to limit the number of recipients + per envelope (in particular, to discourage use of the server + for spamming). Note: a better approach is to restrict + relaying entirely. + Fixed pointer initialization for LDAP lmap struct, fixed -s option + to ldapx map and added timeout for ldap_open call to + avoid hanging sendmail in the event of hung LDAP servers. + Patch from Booker Bense of Stanford University. + Allow multiple -qI, -qR, or -qS queue run limiters. For example, + '-qRfoo -qRbar' would deliver mail to recipients with foo or + bar in their address. Patch from Allan E Johannesen of + Worcester Polytechnic Institute. + The bestmx map will now return a list of the MX servers for a host if + passed a column delimiter via the -z map flag. This can be + used to check if the server is an MX server for the recipient + of a message. This can be used to help prevent relaying. + Patch from Mitchell Blank Jr of Exec-PC. + Mark failures for the *file* mailer and return bounce messages to the + sender for those failures. + Prevent bogus syslog timestamps on errors in sendmail.cf by + preserving the TZ environment variable until TimeZoneSpec + has been determined. Problem noted by Ralf Hildebrandt of + Technical University of Braunschweig. Patch from Per Hedeland + of Ericsson. + Print test input in address test mode when input is not from the tty + when the -v flag is given (i.e., sendmail -bt -v) to make + output easier to decipher. Problem noted by Aidan Nichol + of Procter & Gamble. + The LDAP map -s flag was not properly parsed and the error message + given included the remainder of the arguments instead of + solely the argument in error. Problem noted by Aidan Nichol + of Procter & Gamble. + New DontBlameSendmail option. This option allows administrators to + bypass some of sendmail's file security checks at the expense + of system security. This should only be used if you are + absolutely sure you know the consequences. The available + DontBlameSendmail options are: + Safe + AssumeSafeChown + ClassFileInUnsafeDirPath + ErrorHeaderInUnsafeDirPath + GroupWritableDirPathSafe + GroupWritableForwardFileSafe + GroupWritableIncludeFileSafe + GroupWritableAliasFile + HelpFileinUnsafeDirPath + WorldWritableAliasFile + ForwardFileInGroupWritableDirPath + IncludeFileInGroupWritableDirPath + ForwardFileInUnsafeDirPath + IncludeFileInUnsafeDirPath + ForwardFileInUnsafeDirPathSafe + IncludeFileInUnsafeDirPathSafe + MapInUnsafeDirPath + LinkedAliasFileInWritableDir + LinkedClassFileInWritableDir + LinkedForwardFileInWritableDir + LinkedIncludeFileInWritableDir + LinkedMapInWritableDir + LinkedServiceSwitchFileInWritableDir + FileDeliveryToHardLink + FileDeliveryToSymLink + WriteMapToHardLink + WriteMapToSymLink + WriteStatsToHardLink + WriteStatsToSymLink + RunProgramInUnsafeDirPath + RunWritableProgram + New DontProbeInterfaces option to turn off the inclusion of all the + interface names in $=w on startup. In particular, if you + have lots of virtual interfaces, this option will speed up + startup. However, unless you make other arrangements, mail + sent to those addresses will be bounced. + Automatically create alias databases if they don't exist and + AutoRebuildAliases is set. + Add PrivacyOptions=noetrn flag to disable the SMTP ETRN command. + Suggested by Christophe Wolfhugel of the Institut Pasteur. + Add PrivacyOptions=noverb flag to disable the SMTP VERB command. + When determining the client host name ($&{client_name} macro), do + a forward (A) DNS lookup on the result of the PTR lookup + and compare results. If they differ or if the PTR lookup + fails, &{client_name} will contain the IP address + surrounded by square brackets (e.g., [127.0.0.1]). + New map flag: -Tx appends "x" to lookups that return temporary failure + (i.e, it is like -ax for the temporary failure case, in + contrast to the success case). + New syntax to do limited checking of header syntax. A config line + of the form: + HHeader: $>Ruleset + causes the indicated Ruleset to be invoked on the Header + when read. This ruleset works like the check_* rulesets -- + that is, it can reject mail on the basis of the contents. + Limit the size of the HELO/EHLO parameter to prevent spammers + from hiding their connection information in Received: + headers. + When SingleThreadDelivery is active, deliveries to locked hosts + are skipped. This will cause the delivering process to + try the next MX host or queue the message if no other MX + hosts are available. Suggested by Alexander Litvin. + The [FILE] mailer type now delivers to the file specified in the + A= equate of the mailer definition instead of $u. It also + obeys all of the F= mailer flags such as the MIME + 7/8 bit conversion flags. This is useful for defining + a mailer which delivers to the same file regardless of the + recipient (e.g., 'A=FILE /dev/null' to discard unwanted mail). + Do not assume the identity of a remote connection is root@localhost + if the remote connection closes the socket before the + remote identity can be queried. + Change semantics of the F=S mailer flag back to 8.7.5 behavior. + Some mailers, including procmail, require that the real + uid is left unchanged by sendmail. Problem noted by Per + Hedeland of Ericsson. + No longer is the src/obj*/Makefile selected from a large list -- it + is now generated using the information in BuildTools/OS/ -- + some of the details are determined dynamically via + BuildTools/bin/configure.sh. + The other programs in the sendmail distribution -- mail.local, + mailstats, makemap, praliases, rmail, and smrsh -- now use + the new Build method which creates an operating system + specific Makefile using the information in BuildTools. + Make 4xx reply codes to the SMTP MAIL command be non-sticky (i.e., + a failure on one message won't affect future messages to the + same host). This is necessary if the remote host sends + a 451 error if the domain of the sender does not resolve + as is common in anti-spam configurations. Problem noted + by Mitchell Blank Jr of Exec-PC. + New "discard" mailer for check_* rulesets and header checking + rulesets. If one of the above rulesets resolves to the + $#discard mailer, the commands will be accepted but the + message will be completely discarded after it is accepting. + This means that even if only one of the recipients + resolves to the $#discard mailer, none of the recipients + will receive the mail. Suggested by Brian Kantor. + All but the last cloned envelope of a split envelope were queued + instead of being delivered. Problem noted by John Caruso + of CNET: The Computer Network. + Fix deadlock situation in persistent host status file locking. + Syslog an error if a user forward file could not be read due to + an error. Patch from John Beck of Sun Microsystems. + Use the first name returned on machine lookups when canonifying a + hostname via NetInfo. Patch from Timm Wetzel of GWDG. + Clear the $&{client_addr}, $&{client_name}, and $&{client_port} + macros when delivering a bounce message to prevent + rejection by a check_compat ruleset which uses these macros. + Problem noted by Jens Hamisch of AgiX Internetservices GmbH. + If the check_relay ruleset resolves to the the error mailer, the + error in the $: portion of the resolved triplet is used + in the rejection message given to the remote machine. + Suggested by Scott Gifford of The Internet Ramp. + Set the $&{client_addr}, $&{client_name}, and $&{client_port} macros + before calling the check_relay ruleset. Suggested by Scott + Gifford of The Internet Ramp. + Sendmail would get a segmentation fault if a mailer exited with an + exit code of 79. Problem noted by Aaron Schrab of ExecPC + Internet. Fix from Christophe Wolfhugel of the Pasteur + Institute. + Separate snprintf/vsnprintf routines into separate file for use by + mail.local. + Allow multiple map lookups on right hand side, e.g., + R$* $( host $1 $) $| $( passwd $1 $). Patch from + Christophe Wolfhugel of the Pasteur Institute. + Properly generate success DSN messages if requested for aliases + which have owner- aliases. Problem noted by Kari Hurtta + of the Finnish Meteorological Institute. + Properly display delayed-expansion macros ($&{macroname}) in + address test mode (-bt). Problem noted by Bryan Costales + of InfoBeat, Inc. + -qR could sometimes match names incorrectly. Problem noted by + Lutz Euler of Lavielle EDV Systemberatung GmbH & Co. + Include a magic number and version in the StatusFile for the + mailstats command. + Record the number of rejected and discarded messages in the + StatusFile for display by the mailstats command. Patch + from Randall Winchester of the University of Maryland. + IDENT returns where the OSTYPE field equals "OTHER" now list the + user portion as IDENT:username@site instead of + username@site to differentiate the two. Suggested by + Kari Hurtta of the Finnish Meteorological Institute. + Enforce timeout for LDAP queries. Patch from Per Hedeland of + Ericsson. + Change persistent host status filename substitution so '/' is + replaced by ':' instead of '|' to avoid clashes. Also + avoid clashes with hostnames with leading dots. Fix from + Mitchell Blank Jr. of Exec-PC. + If the system lock table is full, only attempt to create a new + queue entry five times before giving up. Previously, it + was attempted indefinitely which could cause the partition + to run out of inodes. Problem noted by Suzie Weigand of + Stratus Computer, Inc. + In verbose mode, warn if the sendmail.cf version is less than the + currently supported version. + Sorting for QueueSortOrder=host is now case insensitive. Patch + from Randall S. Winchester of the University of Maryland. + Properly quote a full name passed via the -F command line option, + the Full-Name: header, or the NAME environment variable if + it contains characters which must be quoted. Problem noted + by Kari Hurtta of the Finnish Meteorological Institute. + Avoid possible race condition that unlocked a mail job before + releasing the transcript file on systems that use flock(2). + In some cases, this might result in a "Transcript Unavailable" + message in error bounces. + Accept SMTP replies which contain only a reply code and no + accompanying text. Problem noted by Fernando Fraticelli of + Digital Equipment Corporation. + Portability: + AIX 4.1 uses int for SOCKADDR_LEN_T from Motonori Nakamura + of Kyoto University. + AIX 4.2 requires before . Patch from + Randall S. Winchester of the University of + Maryland. + AIX 4.3 from Valdis Kletnieks of Virginia Tech CNS. + CRAY T3E from Manu Mahonen of Center for Scientific Computing + in Finland. + Digital UNIX now uses statvfs for determining free + disk space. Patch from Randall S. Winchester of + the University of Maryland. + HP-UX 11.x from Richard Allen of Opin Kerfi HF and + Regis McEwen of Progress Software Corporation. + IRIX 64 bit fixes from Kari Hurtta of the Finnish + Meteorological Institute. + IRIX 6.2 configuration fix for mail.local from Michael Kyle + of CIC/Advanced Computing Laboratory. + IRIX 6.5 from Thomas H Jones II of SGI. + IRIX 6.X load average code from Bob Mende of SGI. + QNX from Glen McCready . + SCO 4.2 and 5.x use /usr/bin instead of /usr/ucb for links + to sendmail. Install with group bin instead of kmem + as kmem does not exist. From Guillermo Freige of + Gobernacion de la Pcia de Buenos Aires and Paul + Fischer of BTG, Inc. + SunOS 4.X does not include memmove(). Patch from + Per Hedeland of Ericsson. + SunOS 5.7 includes getloadavg() function for determining + load average. Patch from John Beck of Sun + Microsystems. + CONFIG: Increment version number of config file. + CONFIG: add DATABASE_MAP_TYPE to set the default type of database + map for the various maps. The default is hash. Patch from + Robert Harker of Harker Systems. + CONFIG: new confEBINDIR m4 variable for defining the executable + directory for certain programs. + CONFIG: new FEATURE(local_lmtp) to use the new LMTP support for + local mail delivery. By the default, /usr/libexec/mail.local + is used. This is expected to be the mail.local shipped + with 8.9 which is LMTP capable. The path is based on the + new confEBINDIR m4 variable. + CONFIG: Use confEBINDIR in determining path to smrsh for + FEATURE(smrsh). Note that this changes the default from + /usr/local/etc/smrsh to /usr/libexec/smrsh. To obtain the + old path for smrsh, use FEATURE(smrsh, /usr/local/etc/smrsh). + CONFIG: DOMAIN(generic) changes the default confFORWARD_PATH to + include $z/.forward.$w+$h and $z/.forward+$h which allow + the user to setup different .forward files for + user+detail addressing. + CONFIG: add confMAX_RCPTS_PER_MESSAGE, confDONT_PROBE_INTERFACES, + and confDONT_BLAME_SENDMAIL to set MaxRecipientsPerMessage, + DontProbeInterfaces, and DontBlameSendmail options. + CONFIG: by default do not allow relaying (that is, accepting mail + from outside your domain and sending it to another host + outside your domain). + CONFIG: new FEATURE(promiscuous_relay) to allow mail relaying from + any site to any site. + CONFIG: new FEATURE(relay_entire_domain) allows any host in your + domain as defined by the 'm' class ($=m) to relay. + CONFIG: new FEATURE(relay_based_on_MX) to allow relaying based on + the MX records of the host portion of an incoming recipient. + CONFIG: new FEATURE(access_db) which turns on the access database + feature. This database give you the ability to allow + or refuse to accept mail from specified domains for + administrative reasons. By default, names that are listed + as "OK" in the access db are domain names, not host names. + CONFIG: new confCR_FILE m4 variable for defining the name of the file + used for class 'R'. Defaults to /etc/mail/relay-domains. + CONFIG: new command RELAY_DOMAIN(domain) and RELAY_DOMAIN_FILE(file) + to add items to class 'R' ($=R) for hosts allowed to relay. + CONFIG: new FEATURE(relay_hosts_only) to change the behavior + of FEATURE(access_db) and class 'R' to lookup individual + host names only. + CONFIG: new FEATURE(loose_relay_check). Normally, if a recipient + using % addressing is used, e.g. user%site@othersite, + and othersite is in class 'R', the check_rcpt ruleset + will strip @othersite and recheck user@site for relaying. + This feature changes that behavior. It should not be + needed for most installations. + CONFIG: new FEATURE(relay_local_from) to allow relaying if the + domain portion of the mail sender is a local host. This + should only be used if absolutely necessary as it opens + a window for spammers. Patch from Randall S. Winchester of + the University of Maryland. + CONFIG: new FEATURE(blacklist_recipients) turns on the ability to + block incoming mail destined for certain recipient + usernames, hostnames, or addresses. + CONFIG: By default, MAIL FROM: commands in the SMTP session will be + refused if the host part of the argument to MAIL FROM: cannot + be located in the host name service (e.g., DNS). + CONFIG: new FEATURE(accept_unresolvable_domains) accepts + unresolvable hostnames in MAIL FROM: SMTP commands. + CONFIG: new FEATURE(accept_unqualified_senders) accepts + MAIL FROM: senders which do not include a domain. + CONFIG: new FEATURE(rbl) Turns on rejection of hosts found in the + Realtime Blackhole List. You can specify the RBL name + server to contact by specifying it as an optional argument. + The default is rbl.maps.vix.com. For details, see + http://maps.vix.com/rbl/. + CONFIG: Call Local_check_relay, Local_check_mail, and + Local_check_rcpt from check_relay, check_mail, and + check_rcpt. Users with local rulesets should place the + rules using LOCAL_RULESETS. If a Local_check_* ruleset + returns $#OK, the message is accepted. If the ruleset + returns a mailer, the appropriate action is taken, else + the return of the ruleset is ignored. + CONFIG: CYRUS_MAILER_FLAGS now includes the /:| mailer flags by + default to support file, :include:, and program deliveries. + CONFIG: Remove the default for confDEF_USER_ID so the binary can + pick the proper default value. See the SECURITY note + above for more information. + CONFIG: FEATURE(nodns) now warns the user that the feature is a + no-op. Patch from Kari Hurtta of the Finnish + Meteorological Institute. + CONFIG: OSTYPE(osf1) now sets DefaultUserID (confDEF_USER_ID) to + daemon since DEC's /bin/mail will drop the envelope + sender if run as mailnull. See the Digital UNIX section + of src/README for more information. Problem noted by + Kari Hurtta of the Finnish Meteorological Institute. + CONFIG: .cf files are now stored in the same directory with the + .mc files instead of in the obj directory. + CONFIG: New options confSINGLE_LINE_FROM_HEADER, + confALLOW_BOGUS_HELO, and confMUST_QUOTE_CHARS for + setting SingleLineFromHeader, AllowBogusHELO, and + MustQuoteChars respectively. + MAIL.LOCAL: support -l flag to run LMTP on stdin/stdout. This + SMTP-like protocol allows detailed reporting of delivery + status on a per-user basis. Code donated by John Myers of + CMU (now of Netscape). + MAIL.LOCAL: HP-UX support from Randall S. Winchester of the + University of Maryland. NOTE: mail.local is not + compatible with the stock HP-UX mail format. Be sure to + read mail.local/README. + MAIL.LOCAL: Prevent other mail delivery agents from stealing a + mailbox lock. Patch from Randall S. Winchester of the + University of Maryland. + MAIL.LOCAL: glibc portability from John Kennedy of Cal State + University, Chico. + MAIL.LOCAL: IRIX portability from Kari Hurtta of the Finnish + Meteorological Institute. + MAILSTATS: Display the number of rejected and discarded messages + in the StatusFile. Patch from Randall Winchester of the + University of Maryland. + MAKEMAP: New -s flag to ignore safety checks on database map files + such as linked files in world writable directories. + MAKEMAP: Add support for Berkeley DB 2.X. Remove OLD_NEWDB support. + PRALIASES: Add support for Berkeley DB 2.X. + PRALIASES: Do not automatically include NDBM support. Problem + noted by Ralf Hildebrandt of the Technical University of + Braunschweig. + RMAIL: Improve portability for other platforms. Patches from + Randall S. Winchester of the University of Maryland and + Kari Hurtta of the Finnish Meteorological Institute. + Changed Files: + src/Makefiles/Makefile.* files have been modified to use + the new build mechanism and are now BuildTools/OS/*. + src/makesendmail changed to symbolic link to src/Build. + New Files: + BuildTools/M4/header.m4 + BuildTools/M4/depend/BSD.m4 + BuildTools/M4/depend/CC-M.m4 + BuildTools/M4/depend/NCR.m4 + BuildTools/M4/depend/Solaris.m4 + BuildTools/M4/depend/X11.m4 + BuildTools/M4/depend/generic.m4 + BuildTools/OS/AIX.4.2 + BuildTools/OS/AIX.4.x + BuildTools/OS/CRAYT3E.2.0.x + BuildTools/OS/HP-UX.11.x + BuildTools/OS/IRIX.6.5 + BuildTools/OS/NEXTSTEP.4.x + BuildTools/OS/NeXT.4.x + BuildTools/OS/NetBSD.8.3 + BuildTools/OS/QNX + BuildTools/OS/SunOS.5.7 + BuildTools/OS/dcosx.1.x.NILE + BuildTools/README + BuildTools/Site/README + BuildTools/bin/Build + BuildTools/bin/configure.sh + BuildTools/bin/find_m4.sh + BuildTools/bin/install.sh + Makefile + cf/cf/Build + cf/cf/generic-hpux10.cf + cf/feature/accept_unqualified_senders.m4 + cf/feature/accept_unresolvable_domains.m4 + cf/feature/access_db.m4 + cf/feature/blacklist_recipients.m4 + cf/feature/loose_relay_check.m4 + cf/feature/local_lmtp.m4 + cf/feature/promiscuous_relay.m4 + cf/feature/rbl.m4 + cf/feature/relay_based_on_MX.m4 + cf/feature/relay_entire_domain.m4 + cf/feature/relay_hosts_only.m4 + cf/feature/relay_local_from.m4 + cf/ostype/qnx.m4 + contrib/doublebounce.pl + mail.local/Build + mail.local/Makefile.m4 + mail.local/README + mailstats/Build + mailstats/Makefile.m4 + makemap/Build + makemap/Makefile.m4 + praliases/Build + praliases/Makefile.m4 + rmail/Build + rmail/Makefile.m4 + rmail/rmail.0 + smrsh/Build + smrsh/Makefile.m4 + src/Build + src/Makefile.m4 + src/snprintf.c + Deleted Files: + cf/cf/Makefile (replaced by Makefile.dist) + mail.local/Makefile + mail.local/Makefile.dist + mailstats/Makefile + mailstats/Makefile.dist + makemap/Makefile + makemap/Makefile.dist + praliases/Makefile + praliases/Makefile.dist + rmail/Makefile + smrsh/Makefile + smrsh/Makefile.dist + src/Makefile + src/Makefiles/Makefile.AIX.4 (split into AIX.4.x and AIX.4.2) + src/Makefiles/Makefile.SMP_DC.OSx.NILE + (renamed BuildTools/OS/dcosx.1.x.NILE) + src/Makefiles/Makefile.Utah (obsolete platform) + Renamed Files: + READ_ME => README + cf/cf/Makefile.dist => Makefile + cf/cf/obj/* => cf/cf/* + src/READ_ME => src/README + +8.8.8/8.8.8 1997/10/24 + If the check_relay ruleset failed, the relay= field was logged + incorrectly. Problem noted by Kari Hurtta of the Finnish + Meteorological Institute. + If /usr/tmp/dead.letter already existed, sendmail could not + add additional bounces to it. Problem noted by Thomas J. + Arseneault of SRI International. + If an SMTP mailer used a non-standard port number for the outgoing + connection, it would be displayed incorrectly in verbose mode. + Problem noted by John Kennedy of Cal State University, Chico. + Log the ETRN parameter specified by the client before altering them + to internal form. Suggested by Bob Kupiec of GES-Verio. + EXPN and VRFY SMTP commands on malformed addresses were logging as + User unknown with bogus delay= values. Change them to log + the same as compliant addresses. Problem noted by Kari E. + Hurtta of the Finnish Meteorological Institute. + Ignore the debug resolver option unless using sendmail debug trace + option for resolver. Problem noted by Greg Nichols of Wind + River Systems. + If SingleThreadDelivery was enabled and the remote server returned a + protocol error on the DATA command, the connection would be + closed but the persistent host status file would not be + unlocked so other sendmail processes could not deliver to + that host. Problem noted by Peter Wemm of DIALix. + If queueing up a message due to an expensive mailer, don't increment + the number of delivery attempts or set the last delivery + attempt time so the message will be delivered on the next + queue run regardless of MinQueueAge. Problem noted by + Brian J. Coan of the Institute for Global Communications. + Authentication warnings of "Processed from queue _directory_" and + "Processed by _username_ with -C _filename_" would be logged + with the incorrect timestamp. Problem noted by Kari E. Hurtta + of the Finnish Meteorological Institute. + Use a better heuristic for detecting GDBM. + Log null connections on dropped connections. Problem noted by + Jon Lewis of Florida Digital Turnpike. + If class dbm maps are rebuilt, sendmail will now detect this and + reopen the map. Previously, they could give stale + results during a single message processing (but would + recover when the next message was received). Fix from + Joe Pruett of Q7 Enterprises. + Do not log failures such as "User unknown" on -bv or SMTP VRFY + requests. Problem noted by Kari E. Hurtta of the + Finnish Meteorological Institute. + Do not send a bounce message back to the sender regarding bad + recipients if the SMTP connection is dropped before the + message is accepted. Problem noted by Kari E. Hurtta of the + Finnish Meteorological Institute. + Use "localhost" instead of "[UNIX: localhost]" when connecting to + sendmail via a UNIX pipe. This will allow rulesets using + $&{client_name} to process without sending the string through + dequote. Problem noted by Alan Barrett of Internet Africa. + A combination of deferred delivery mode, a double bounce situation, + and the inability to save a bounce message to + /var/tmp/dead.letter would cause sendmail to send a bounce + to postmaster but not remove the offending envelope from the + queue causing it to create a new bounce message each time the + queue was run. Problem noted by Brad Doctor of Net Daemons + Associates. + Remove newlines from hostname information returned via DNS. There are + no known security implications of newlines in hostnames as + sendmail filters newlines in all vital areas; however, this + could cause confusing error messages. + Starting with sendmail 8.8.6, mail sent with the '-t' option would be + rejected if any of the specified addresses were bad. This + behavior was modified to only reject the bad addresses and not + the entire message. Problem noted by Jozsef Hollosi of + SuperNet, Inc. + Use Timeout.fileopen when delivering mail to a file. Suggested by + Bryan Costales of InfoBeat, Inc. + Display the proper Final-Recipient on DSN messages for non-SMTP + mailers. Problem noted by Kari E. Hurtta of the + Finnish Meteorological Institute. + An error in calculating the available space in the list of addresses + for logging deliveries could cause an address to be silently + dropped. + Include the initial user environment if sendmail is restarted via + a HUP signal. This will give room for the process title. + Problem noted by Jon Lewis of Florida Digital Turnpike. + Mail could be delivered without a body if the machine does not + support flock locking and runs out of processes during + delivery. Fix from Chuck Lever of the University of Michigan. + Drop recipient address from 251 and 551 SMTP responses per RFC 821. + Problem noted by Kari E. Hurtta of the Finnish Meteorological + Institute. + Make sure non-rebuildable database maps are opened before the + rebuildable maps (i.e., alias files) in case the database maps + are needed for verifying the left hand side of the aliases. + Problem noted by Lloyd Parkes of Victoria University. + Make sure sender RFC822 source route addresses are alias expanded for + bounce messages. Problem noted by Juergen Georgi of + RUS University of Stuttgart. + Minor lint fixes. + Return a temporary error instead of a permanent error if an LDAP map + search returns an error. This will allow sequenced maps which + use other LDAP servers to be checked. Fix from Booker Bense + of Stanford University. + When automatically converting from quoted printable to 8bit text do + not pad bare linefeeds with a space. Problem noted by Theo + Nolte of the University of Technology Aachen, Germany. + Portability: + Non-standard C compilers may have had a problem compiling + conf.c due to a standard C external declaration of + setproctitle(). Problem noted by Ted Roberts of + Electronic Data Systems. + AUX: has a broken O_EXCL implementation. Reported by Jim + Jagielski of jaguNET Access Services. + BSD/OS: didn't compile if HASSETUSERCONTEXT was defined. + Digital UNIX: Digital UNIX (and possibly others) moves + loader environment variables into the loader memory + area. If one of these environment variables (such as + LD_LIBRARY_PATH) was the last environment variable, + an invalid memory address would be used by the process + title routine causing memory corruption. Problem + noted by Sam Hartman of Mesa Internet Systems. + GNU libc: uses an enum for _PC_CHOWN_RESTRICTED which caused + chownsafe() to always return 0 even if the OS does + not permit file giveaways. Problem noted by + Yasutaka Sumi of The University of Tokyo. + IRIX6: Syslog buffer size set to 512 bytes. Reported by + Gerald Rinske of Siemens Business Services VAS. + Linux: Pad process title with NULLs. Problem noted by + Jon Lewis of Florida Digital Turnpike. + SCO OpenServer 5.0: SIOCGIFCONF ioctl call returns an + incorrect value for the number of interfaces. + Problem noted by Chris Loelke of JetStream Internet + Services. + SINIX: Update for Makefile and syslog buffer size from Gerald + Rinske of Siemens Business Services VAS. + Solaris: Make sure HASGETUSERSHELL setting for SunOS is not + used on a Solaris machine. Problem noted by + Stephen Ma of Jtec Pty Limited. + CONFIG: SINIX: Update from Gerald Rinske of Siemens Business + Services VAS. + MAKEMAP: Use a better heuristic for detecting GDBM. + CONTRIB: expn.pl: Updated version from the author, David Muir Sharnoff. + OP.ME: Document the F=i mailer flag. Problem noted by Per Hedeland of + Ericsson. + +8.8.7/8.8.7 1997/08/03 + If using Berkeley DB on systems without O_EXLOCK (open a file with + an exclusive lock already set -- i.e., almost all systems + except 4.4-BSD derived systems), the initial attempt at + rebuilding aliases file if the database didn't already + exist would fail. Patch from Raymund Will of LST Software + GmbH. + Bogus incoming SMTP commands would reset the SMTP conversation. + Problem noted by Fredrik Jönsson of the Royal Institute + of Technology, Stockholm. + Since TCP Wrappers includes setenv(), unsetenv(), and putenv(), + some environments could give "multiple definitions" for these + routines during compilation. If using TCP Wrappers, assume + that these routines are included as though they were in the + C library. Patch from Robert La Ferla. + When a NEWDB database map was rebuilt at the same time it was being + used by a queue run, the maps could be left locked for the + duration of the queue run, causing other processes to hang. + Problem noted by Kendall Libby of Shore.NET. + In some cases, NoRecipientAction=add-bcc was being ignored, so the + mail was passed on without any recipient header. This could + cause problems downstream. Problem noted by Xander Jansen + of SURFnet ExpertiseCentrum. + Give error when GDBM is used with sendmail. GDBM's locking and + linking of the .dir and .pag files interferes with sendmail's + locking and security checks. Problems noted by Fyodor + Yarochkin of the Kyrgyz Republic FreeNet. + Don't fsync qf files if SuperSafe option is not set. + Avoid extra calls to gethostbyname for addresses for which a + gethostbyaddr found no value. Also, ignore any returns + from gethostbyaddr that look like a dotted quad. + If PTR lookup fails when looking up an SMTP peer, don't tag it as + "may be forged", since at the network level we pretty much + have to assume that the information is good. + In some cases, errors during an SMTP session could leave files + open or locked. + Better handling of missing file descriptors (0, 1, 2) on startup. + Better handling of non-setuid binaries -- avoids certain obnoxious + errors during testing. + Errors in file locking of NEWDB maps had the incorrect file name + printed in the error message. + If the AllowBogusHELO option were set and an EHLO with a bad or + missing parameter were issued, the EHLO behaved like a HELO. + Load limiting never kicked in for incoming SMTP transactions if the + DeliveryMode=background and any recipient was an alias or + had a .forward file. From Nik Conwell of Boston University. + On some non-Posix systems, the decision of whether chown(2) permits + file giveaway was undefined. From Tetsu Ushijima of the + Tokyo Institute of Technology. + Fix race condition that could cause the body of a message to be + lost (so only the header was delivered). This only occurs + on systems that do not use flock(2), and only when a queue + runner runs during a critical section in another message + delivery. Based on a patch from Steve Schweinhart of + Results Computing. + If a qf file was found in a mail queue directory that had a problem + (wrong ownership, bad format, etc.) and the file name was + exactly MAXQFNAME bytes long, then instead of being tried + once, it would be tried on every queue run. Problem noted + by Bryan Costales of Mercury Mail. + If the system supports an st_gen field in the status structure, + include it when reporting that a file has changed after open. + This adds a new compile flag, HAS_ST_GEN (0/1 option). + This out to be checked as well as reported, since it is + theoretically possible for an attacker to remove a file after + it is opened and replace it with another file that has the + same i-number, but some filesystems (notably AFS) return + garbage in this field, and hence always look like the file + has changed. As a practical matter this is not a security + problem, since the files can be neither hard nor soft links, + and on no filesystem (that I am aware of) is it possible to + have two files on the same filesystem with the same i-number + simultaneously. + Delete the root Makefile from the distribution -- it is only for + use internally, and does not work at customer sites. + Fix botch that caused the second MAIL FROM: command in a single + transaction to clear the entire transaction. Problem + noted by John Kennedy of Cal State University, Chico. + Work properly on machines that have _PATH_VARTMP defined without + a trailing slash. (And a pox on vendors that decide to + ignore the established conventions!) Problem noted by + Gregory Neil Shapiro of WPI. + Internal changes to make it easier to add another protocol family + (intended for IPv6). Patches are from John Kennedy of + CSU Chico. + In certain cases, 7->8 bit MIME decoding of Base64 text could leave + an extra space at the beginning of some lines. Problem + noted by Charles Karney of Princeton University; fix based + on a patch from Christophe Wolfhugel. + Portability: + Allow _PATH_VENDOR_CF to be set in Makefile for consistency + with the _Sendmail_ book, 2nd edition. Note that + the book is actually wrong: _PATH_SENDMAILCF should + be used instead. + AIX 3.x: Include . Patch from Gene Rackow + of Argonne National Laboratory. + OpenBSD from from Paul DuBois of the University of Wisconsin. + RISC/os 4.0 from Paul DuBois of the University of Wisconsin. + SunOS: Include to fix warning from util.c. From + James Aldridge of EUnet Ltd. + Solaris: Change STDIR (location of status file) to /etc/mail + in Makefiles. + Linux, Dynix, UNICOS: Remove -DNDBM and -lgdbm from + Makefiles. Use NEWDB on Linux instead. + NCR MP-RAS 3.x with STREAMware TCP/IP: SIOCGIFNUM ioctl + exists but behaves differently than other OSes. + Add SIOCGIFNUM_IS_BROKEN compile flag to get + around the problem. Problem noted by Tom Moore of + NCR Corp. + HP-UX 9.x: fix compile warnings for old select API. Problem + noted by Tom Smith of Digital Equipment Corp. + UnixWare 2.x: compile warnings on offsetof macro. Problem + noted by Tom Good of the Community Access Information + Resource Network + SCO 4.2: compile problems caused by a change in the type of + the "length" parameters passed to accept, getpeername, + getsockname, and getsockopt. Adds new compile flags + SOCKADDR_SIZE_T and SOCKOPT_SIZE_T. Problem reported + by Tom Good of St. Vincent's North Richmond Community + Mental Health Center Residential Services. + AIX 4: Use size_t for SOCKADDR_SIZE_T and SOCKOPT_SIZE_T. + Suggested by Brett Hogden of Rochester Gas & Electric + Corp. + Linux: avoid compile problem for versions of that + #define both setjmp and longjmp. Problem pointed out + by J.R. Oldroyd of TerraNet. + CONFIG: SCO UnixWare 2.1: Support for OSTYPE(sco-uw-2.1) + from Christopher Durham of SCO. + CONFIG: NEXTSTEP: define confCW_FILE to + /etc/sendmail/sendmail.cw to match the usual + configuration. Patch from Dennis Glatting of + PlainTalk. + CONFIG: MAILER(fax) called a program that hasn't existed for a long + time. Convert to use the HylaFAX 4.0 conventions. Suggested + by Harry Styron. + CONFIG: Improve sample anti-spam rulesets in cf/cf/knecht.mc. These + are the rulesets in use on sendmail.org. + MAKEMAP: give error on GDBM files. + MAIL.LOCAL: Make error messages a bit more explicit, for example, + telling more details on what actually changed when "file + changed after open". + CONTRIB: etrn.pl: Ignore comments in Fw files. Support multiple Fw + files. + CONTRIB: passwd-to-alias.pl: Handle 8 bit characters and '-'. + NEW FILES: + src/Makefiles/Makefile.OpenBSD + src/Makefiles/Makefile.RISCos.4_0 + test/t_exclopen.c + cf/ostype/sco-uw-2.1.m4 + DELETED FILES: + Makefile + +8.8.6/8.8.6 1997/06/14 + ************************************************************* + * The extensive assistance of Gregory Neil Shapiro of WPI * + * in preparing this release is gratefully appreciated. * + * Sun Microsystems has also provided resources toward * + * continued sendmail development. * + ************************************************************* + SECURITY: A few systems allow an open with the O_EXCL|O_CREAT open + mode bits set to create a file that is a symbolic link that + points nowhere. This makes it possible to create a root + owned file in an arbitrary directory by inserting the symlink + into a writable directory after the initial lstat(2) check + determined that the file did not exist. The only verified + example of a system having these odd semantics for O_EXCL + and symbolic links was HP-UX prior to version 9.07. Most + systems do not have the problem, since a exclusive create + of a file disallows symbolic links. Systems that have been + verified to NOT have the problem include AIX 3.x, *BSD, + DEC OSF/1, HP-UX 9.07 and higher, Linux, SunOS, Solaris, + and Ultrix. This is a potential exposure on systems that + have this bug and which do not have a MAILER-DAEMON alias + pointing at a legitimate account, since this will cause old + mail to be dropped in /var/tmp/dead.letter. + SECURITY: Problems can occur on poorly managed systems, specifically, + if maps or alias files are in world writable directories. + If your system has alias maps in writable directories, it + is potentially possible for an attacker to replace the .db + (or .dir and .pag) files by symbolic links pointing at + another database; this can be used either to expose + information (e.g., by pointing an alias file at /etc/spwd.db + and probing for accounts), or as a denial-of-service attack + (by trashing the password database). The fix disallows + symbolic links entirely when rebuilding alias files or on + maps that are in writable directories, and always warns on + writable directories; 8.9 will probably consider writable + directories to be fatal errors. This does not represent an + exposure on systems that have alias files in unwritable + system directories. + SECURITY: disallow .forward or :include: files that are links (hard + or soft) if the parent directory (or any directory in the + path) is writable by anyone other than the owner. This is + similar to the previous case for user files. This change + should not affect most systems, but is necessary to prevent + an attacker who can write the directory from pointing such + files at other files that are readable only by the owner. + SECURITY: Tighten safechown rules: many systems will say that they + have a safe (restricted to root) chown even on files that + are mounted from another system that allows owners to give + away files. The new rules are very strict, trusting file + ownership only in those few cases where the system has + been verified to be at least as paranoid as necessary. + However, it is possible to relax the rules to partially + trust the ownership if the directory path is not world or + group writable. This might allow someone who has a legitimate + :include: file (referenced directly from /etc/aliases) to + become another non-root user if the :include: file is in a + non-writable directory on an NFS-mounted filesystem where + the local system says that giveaway is denied but it is + actually permitted. I believe this to be a very small set + of cases. If in doubt, do not point :include: aliases at + NFS-mounted filesystems. + SECURITY: When setting a numeric group id using the RunAsUser option + (e.g., "O RunAsUser=10:20", the group id would not be set. + Implicit group ids (e.g., "O RunAsUser=mailnull") or alpha + group ids (e.g., "O RunAsUser=mailuser:mailgrp") worked fine. + The user id was still set properly. Problem noted by Uli + Pralle of the Technical University of Berlin. + Save the initial gid set for use when checking for if the + PrivacyOptions=restrictmailq option is set. Problem reported + by Wolfgang Ley of DFN-CERT. + Make 55x reply codes to the SMTP DATA-"." be non-sticky (i.e., a + failure on one message won't affect future messages to the + same host). + IP source route printing had an "off by one" error that would + affect any options that came after the route option. Patch + from Theo de Raadt. + The "Message is too large" error didn't successfully bounce the error + back to the sender. Problem reported by Stephen More of + PSI; patch from Gregory Neil Shapiro of WPI. + Change SMTP status code 553 to map into Extended code 5.1.0 (instead + of 5.1.3); it apparently gets used in multiple ways. + Suggested by John Myers of Portola Communications. + Fix possible extra null byte generated during collection if errors + occur at the beginning of the stream. Patch contributed by + Andrey A. Chernov and Gregory Neil Shapiro. + Code changes to avoid possible reentrant call of malloc/free within + a signal handler. Problem noted by John Beck of Sun + Microsystems. + Move map initialization to be earlier so that check_relay ruleset + will have the latest version of the map data. Problem noted + by Paul Forgey of Metainfo; patch from Gregory Neil Shapiro. + If there are fatal errors during the collection phase (e.g., message + too large) don't send the bogus message. + Avoid "cannot open xfAAA00000" messages when sending to aliases that + have errors and have owner- aliases. Problem noted by Michael + Barber of MTU; fix from Gregory Neil Shapiro of WPI. + Avoid null pointer dereference on illegal Boundary= parameters in + multipart/mixed Content-Type: header. Problem noted by + Richard Muirden of RMIT University. + Always print error messages during newaliases (-bi) even if the + ErrorMode is not set to "print". Fix from Gregory Neil + Shapiro. + Test mode could core dump if you did a /map lookup in an optional map + that could not be opened. Based on a fix from John Beck of + Sun Microsystems. + If DNS is misconfigured so that the last MX record tried points to + a host that does not have an A record, but other MX records + pointed to something reasonable, don't bounce the message + with a "host unknown" error. Note that this should really + be fixed in the zone file for the domain. Problem noted by + Joe Rhett of Navigist, Inc. + If a map fails (e.g., DNS times out) on all recipient addresses, mark + the message as having been tried; otherwise the next queue + run will not realize that this is a second attempt and will + retry immediately. Problem noted by Bryan Costales of + Mercury Mail. + If the clock is set backwards, and a MinQueueAge is set, no jobs + will be run until the later setting of the clock is reached. + "Problem" (I use the term loosely) noted by Eric Hagberg of + Morgan Stanley. + If the load average rises above the cutoff threshold (above which + sendmail will not process the queue at all) during a queue + run, abort the queue run immediately. Problem noted by + Bryan Costales of Mercury Mail. + The variable queue processing algorithm (based on the message size, + number of recipients, message precedence, and job age) was + non-functional -- either the entire queue was processed or + none of the queue was processed. The updated algorithm + does no queue run if a single recipient zero size job will + not be run. + If there is a fatal ("panic") message that will cause sendmail to + die immediately, never hold the error message for future + printing. + Force ErrorMode=print in -bt mode so that all errors are printed + regardless of the setting of the ErrorMode option in the + configuration file. Patch from Gregory Neil Shapiro. + New compile flag HASSTRERROR says that this OS has the strerror(3) + routine available in one of the libraries. Use it in conf.h. + The -m (match only) flag now works on host class maps. + If class hash or btree maps are rebuilt, sendmail will now detect + this and reopen the map. Previously, they could give + erroneous results during a single message processing + (but would recover when the next message was received). + Don't delete zero length queue files when doing queue runs until the + files are at least ten minutes old. This avoids a potential + race condition: the creator creates the qf file, getting back + a file descriptor. The queue runner locks it and deletes it + because it is zero length. The creator then writes the + descriptor that is now for a disconnected file, and the + job goes away. Based on a suggestion by Bryan Costales. + When determining the "validated" host name ($_ macro), do a forward + (A) DNS lookup on the result of the PTR lookup and compare + results. If they differ or if the PTR lookup fails, tag the + address as "may be forged". + Log null connections (i.e., hosts that connect but do not do any + substantive activity on the connection before disconnecting; + "substantive" is defined to be MAIL, EXPN, VRFY, or ETRN. + Always permit "writes" to /dev/null regardless of the link count. + This is safe because /dev/null is special cased, and no open + or write is ever actually attempted. Patch from Villy Kruse + of TwinCom. + If a message cannot be sent because of a 552 (exceeded storage + allocation) response to the MAIL FROM:<>, and a SIZE= parameter + was given, don't return the body in the bounce, since there + is a very good chance that the message will double-bounce. + Fix possible line truncation if a quoted-printable had an =00 escape + in the body. Problem noted by Charles Karney of the Princeton + Plasma Physics Laboratory. + Notify flags (e.g., -NSUCCESS) were lost on user+detail addresses. + Problem noted by Kari Hurtta of the Finnish Meteorological + Institute. + The MaxDaemonChildren option wasn't applying to queue runs as + documented. Note that this increases the potential denial + of service problems with this option: an attacker can + connect many times, and thereby lock out queue runs as well + as incoming connections. If you use this option, you should + run the "sendmail -bd" and "sendmail -q30m" jobs separately + to avoid this attack. Failure to limit noted by Matthew + Dillon of BEST Internet Communications. + Always give a message in newaliases if alias files cannot be + opened instead of failing silently. Suggested by Gregory + Neil Shapiro. This change makes the code match the O'Reilly + book (2nd edition). + Some older versions of the resolver could return with h_errno == -1 + if no name server could be reached, causing mail to bounce + instead of queueing. Treat this like TRY_AGAIN. Fix from + John Beck of SunSoft. + If a :include: file is owned by a user that does not have an entry + in the passwd file, sendmail could dereference a null pointer. + Problem noted by Satish Mynam of Sun Microsystems. + Take precautions to make sure that the SMTP protocol cannot get out + of sync if (for example) an alias file cannot be opened. + Fix a possible race condition that can cause a SIGALRM to come in + immediately after a SIGHUP, causing the new sendmail to die. + Avoid possible hang on SVr3 systems when doing child reaping. Patch + from Villy Kruse of TwinCom. + Ignore improperly formatted SMTP reply codes. Previously these were + partially processed, which could cause confusing error + returns. + Fix possible bogus pointer dereference when doing ldapx map lookups + on some architectures. + Portability: + A/UX: from Jim Jagielski of NASA/GSFC. + glibc: SOCK_STREAM was changed from a #define to an enum, + thus breaking #ifdef SOCK_STREAM. Only option seems + to be to assume SOCK_STREAM if __GNU_LIBRARY__ is + defined. Problem reported by A Sun of the University + of Washington. + Solaris: use SIOCGIFNUM to get the number of interfaces on + the system rather than guessing at compile time. + Patch contributed by John Beck of Sun Microsystems. + Intel Paragon: from Wendy Lin of Purdue University. + GNU Hurd: from Miles Bader of the GNU project. + RISC/os 4.50 from Harlan Stenn of PFCS Corporation. + ISC Unix: wait never returns if SIGCLD signals are blocked. + Unfortunately releasing them opens a race condition, + but there appears to be no fix for this. Patch from + Gregory Neil Shapiro. + BIND 8.1 for IPv6 compatibility from John Kennedy. + Solaris: a bug in strcasecmp caused characters with the + high order bit set to apparently randomly match + letters -- for example, $| (0233) matches "i" and "I". + Problem noted by John Gregson of the University of + Cambridge. + IRIX 6.x: make Makefile.IRIX.6.2 apply to all 6.x. From + Kari Hurtta. + IRIX 6.x: Create Makefiles for systems that claim to be + IRIX64 but are 6.2 or higher (so use the regular + IRIX Makefile). + IRIX 6.x: Fix load average computation on 64 bit kernels. + Problem noted by Eric Hagberg of Morgan Stanley. + CONFIG: Some canonification was still done for UUCP-like addresses + even if FEATURE(nocanonify) was set. Problem pointed out by + Brian Candler. + CONFIG: In some cases UUCP mailers wouldn't properly recognize all + local names as local. Problem noted by Jeff Polk of BSDI; + fix provided by Gregory Neil Shapiro. + CONFIG: The "local:user" syntax entries in mailertables and other + "mailer:user" syntax locations returned an incorrect value + for the $h macro. Problem noted by Gregory Neil Shapiro. + CONFIG: Retain "+detail" information when forwarding mail to a + MAIL_HUB, LUSER_RELAY, or LOCAL_RELAY. Patch from Philip + Guenther of Gustavus Adolphus College. + CONFIG: Make sure user+detail works for FEATURE(virtusertable); + rules are the same as for aliasing. Based on a patch from + Gregory Neil Shapiro. + CONFIG: Break up parsing rules into several pieces; this should + have no functional change in this release, but makes it + possible to have better anti-spam rulesets in the future. + CONFIG: Disallow double dots in host names to avoid having the + HostStatusDirectory store status under the wrong name. + In some cases this can be used as a denial-of-service attack. + Problem noted by Ron Jarrell of Virginia Tech, patch from + Gregory Neil Shapiro. + CONFIG: Don't use F=m (multiple recipients per invocation) for + MAILER(procmail), but do pass F=Pn9 (include Return-Path:, + don't include From_, and convert to 8-bit). Suggestions + from Kimmo Suominen and Roderick Schertler. + CONFIG: Domains under $=M (specified with MASQUERADE_DOMAIN) were + being masqueraded as though FEATURE(masquerade_entire_domain) + was specified, even when it wasn't. + MAIL.LOCAL: Solaris 2.6 has snprintf. From John Beck of SunSoft. + MAIL.LOCAL: SECURITY: check to make sure that an attacker doesn't + "slip in" a symbolic link between the lstat(2) call and the + exclusive open. This is only a problem on System V derived + systems that allow an exclusive create on files that are + symbolic links pointing nowhere. + MAIL.LOCAL: If the final mailbox close() failed, the user id was + not reset back to root, which on some systems would cause + later mailboxes to fail. Also, any partial message would + not be truncated, which could result in repeated deliveries. + Problem noted by Bruce Evans via Peter Wemm (FreeBSD + developers). + MAKEMAP: Handle cases where O_EXLOCK is #defined to be 0. A similar + change to the sendmail map code was made in 8.8.3. Problem + noted by Gregory Neil Shapiro. + MAKEMAP: Give warnings on file problems such as map files that are + symbolic links; although makemap is not setuid root, it is + often run as root and hence has the potential for the same + sorts of problems as alias rebuilds. + MAKEMAP: Change compilation so that it will link properly on + NEXTSTEP. + CONTRIB: etrn.pl: search for Cw as well as Fw lines in sendmail.cf. + Accept an optional list of arguments following the server + name for the ETRN arguments to use (instead of $=w). Other + miscellaneous bug fixes. From Christian von Roques via + John Beck of Sun Microsystems. + CONTRIB: Add passwd-to-alias.pl, contributed by Kari Hurtta. This + Perl script converts GECOS information in the /etc/passwd + file into aliases, allowing for faster access to full name + lookups; it is also clever about adding aliases (to root) + for system accounts. + NEW FILES: + src/safefile.c + cf/ostype/gnuhurd.m4 + cf/ostype/irix6.m4 + contrib/passwd-to-alias.pl + src/Makefiles/Makefile.IRIX64.6.1 + src/Makefiles/Makefile.IRIX64.6.x + RENAMED FILES: + src/Makefiles/Makefile.IRIX.6.2 => Makefile.IRIX.6.x + src/Makefiles/Makefile.IRIX64 => Makefile.IRIX64.6.0 + +8.8.5/8.8.5 1997/01/21 + SECURITY: Clear out group list during startup. Without this, sendmail + will continue to run with the group permissions of the caller, + even if RunAsUser is specified. + SECURITY: Make purgestat (-bH) be root-only. This is not in response + to any known attack, but it's best to be conservative. + Suggested by Peter Wemm of DIALix. + SECURITY: Fix buffer overrun problem in MIME code that has possible + security implications. Patch from Alex Garthwaite of the + University of Pennsylvania. + Use of a -f flag with a phrase attached (e.g., "-f 'Full Name '") + would truncate the address after "Full". Although the -f + syntax is incorrect (since it is in the envelope, it + shouldn't have comments and full names), the failure mode + was unnecessarily awful. + Fix a possible null pointer dereference when converting 8-bit data + to a 7-bit format. Problem noted by Jim Hutchins of + Sandia National Labs and David James of British Telecom. + Clear out stale state that affected F=9 on SMTP mailers in queue + runs. Although this really shouldn't be used (F=9 is for + final delivery only, and using it on an SMTP mailer makes + it possible for a message to be converted from 8->7->8->7 + bits several times), it shouldn't have failed with a syserr. + Problem noted by Eric Hagberg of Morgan Stanley. + _Really_ fix the multiple :maildrop code in the user database + module. Patch from Roy Mongiovi of Georgia Tech. + Let F lines in the configuration file actually read root-only + files if the configuration file is safe. Based on a + patch from Keith Reynolds of SCO. + ETRN followed by QUIT would hold the connection open until the queue + run completed. Problem noted by Truck Lewis of TDK + Semiconductor Corp. + It turns out that despite the documentation, the TCP wrappers library + does _not_ log rejected connections. Do the logging ourselves. + Problem noted by Fletcher Mattox of the University of Texas + at Austin. + If sendmail finds a qf file in its queue directory that is an unknown + version (e.g., when backing out to an old version), the + error is reported on every queue run. Change it to only + give the error once (and rename the qf => Qf). Patch from + William A. Gianopoulos of Raytheon Company. + Start a new session when doing background delivery; currently it + ignored signals but didn't start a new signal, that caused + some problems if a background process tried to send mail + under certain circumstances. Problem noted by Eric Hagberg + of Morgan Stanley; fix from Kari Hurtta. + Simplify test for skipping a queue run to just check if the current + load average is >= the queueing load average. Previously + the check factored in some other parameters that caused it + to essentially never skip the queue run. Patch from Bryan + Costales. + If the SMTP server is running in "nullserver" mode (that is, it is + rejecting all commands), start sleeping after MAXBADCOMMAND + (25) commands; this helps prevent a bad guy from putting + you into a tight loop as a denial-of-service attack. Based + on an e-mail conversation with Brad Knowles of AOL. + Slow down when too many "light weight" commands have been issued; + this helps prevent a class of denial-of-service attacks. + The current values and defaults are: + MAXNOOPCOMMANDS 20 NOOP, VERB, ONEX, XUSR + MAXHELOCOMMANDS 3 HELO, EHLO + MAXVRFYCOMMANDS 6 VRFY, EXPN + MAXETRNCOMMANDS 8 ETRN + These will probably be configurable in a future release. + On systems that have uid_t typedefed to be an unsigned short, programs + that had the F=S flag and no U= equate would be invoked with + the real uid set to 65535 rather than being left unchanged. + In some cases, NOTIFY=NEVER was not being honored. Problem noted + by Steve Hubert of the University of Washington, Seattle. + Mail that was Quoted-Printable encoded and had a soft line break on + the last line (i.e., an incomplete continuation) had the last + line dropped. Since this appears to be illegal it isn't + clear what to do with it, but flushing the last line seems + to be a better "fail soft" approach. Based on a patch from + Eric Hagberg. + If AllowBogusHELO and PrivacyOptions=needmailhelo are both set, a + bogus HELO command still causes the "Polite people say HELO + first" error message. Problem pointed out by Chris Thomas + of UCLA; patch from John Beck of SunSoft. + Handle "sendmail -bp -qSfoobar" properly if restrictqrun is set + in PrivacyOptions. The -q shouldn't turn this command off. + Problem noted by Murray Kucherawy of Pacific Bell Internet; + based on a patch from Gregory Neil Shapiro of WPI. + Don't consider SMTP reply codes 452 or 552 (exceeded storage allocation) + in a DATA transaction to be sticky; these can occur because + a message is too large, and smaller messages should still go + through. Problem noted by Matt Dillon of Best Internet + Communications. + In some cases bounces were saved in /var/tmp/dead.letter even if they + had been successfully delivered to the envelope sender. + Problem noted Eric Hagberg of Morgan Stanley; solution from + Gregory Neil Shapiro of WPI. + Give better diagnostics on long alias lines. Based on code contributed + by Patrick Gosling of the University of Cambridge. + Increase the number of virtual interfaces that will be probed for + alternate names. Problem noted by Amy Rich of Shore.Net. + PORTABILITY: + UXP/DS V20L10 for Fujitsu DS/90: Makefile patches from + Toshiaki Nomura of Fujitsu Limited. + SunOS with LDAP support: compile problems with struct timeval. + Patch from Nick Cuccia of TCSI Corporation. + SCO: from Keith Reynolds of SCO. + Solaris: kstat load average computation wasn't being used. + Fixes from Michael Ju. Tokarev of Telecom Service, JSC + (Moscow). + OpenBSD: from Jason Downs of teeny.org. + Altos System V: from Tim Rice. + Solaris 2.5: from Alan Perry of SunSoft. + Solaris 2.6: from John Beck of SunSoft. + Harris Nighthawk PowerUX (mh6000 box): from Bob Miorelli + of Pratt & Whitney . + CONFIG: It seems that I hadn't gotten the Received: line syntax + _just_right_ yet. Tweak it again. I'll omit the names + of the "contributors" (quantity two) in this one case. + As of now, NO MORE DISCUSSION about the syntax of the + Received: line. + CONFIG: Although FEATURE(nullclient) uses EXPOSED_USER (class $=E), + it never inserts that class into the output file. Fix it + so it will honor EXPOSED_USER but will _not_ include root + automatically in this class. Problem noted by Ronan KERYELL + of Centre de Recherche en Informatique de l'École Nationale + Supérieure des Mines de Paris (CRI-ENSMP). + CONFIG: Clean up handling of "local:" syntax in relay specifications + such as LUSER_RELAY. This change permits the following + syntaxes: ``local:'' will send to the same user on the + local machine (e.g., in a mailertable entry for "host", + ``local:'' will cause an address addressed to user@host to + go to user on the local machone). ``local:user'' will send + to the named user on the local machine. ``local:user@host'' + is equivalent to ``local:user'' (the host is ignored). In + all cases, the original user@host is passed in $@ (i.e., the + detail information). Inspired by a report from Michael Fuhr. + CONFIG: Strip quotes from the first word of an "error:" host + indication. This lets you set (for example) the LUSER_RELAY + to be ``error:\"5.1.1\" Your Message Here''. Note the use + of the \" so that the resulting string is properly quoted. + Problem noted by Gregory Neil Shapiro of WPI. + OP.ME: documentation was inconsistent about whether sendmail did a + NOOP or a RSET to probe the connection (it does a RSET). + Inconsistency noted by Deeran Peethamparam. + OP.ME: insert additional blank pages so it will print properly on + a duplex printer. From Matthew Black of Cal State University, + Long Beach. + +8.8.4/8.8.4 1996/12/02 + SECURITY: under some circumstances, an attacker could get additional + permissions by hard linking to files that were group + writable by the attacker. The solution is to disallow any + files that have hard links -- this will affect .forward, + :include:, and output files. Problem noted by Terry + Kyriacopoulos of Interlog Internet Services. As a + workaround, set UnsafeGroupWrites -- always a good idea. + SECURITY: the TryNullMXList (w) option should not be safe -- if it + is, it is possible to do a denial-of-service attack on + MX hosts that rely on the use of the null MX list. There + is no danger if you have this option turned off (the default). + Problem noted by Dan Bernstein. Also, make the DontInitGroups + unsafe. I know of no specific attack against this, although + a denial-of-service attack is probably possible, but in theory + you should not be able to safely tweak anything that affects + the permissions that are used when mail is delivered. + Purgestat could go into an infinite loop if one of the host status + directories somehow became empty. Problem noted by Roy + Mongiovi of Georgia Tech. + Processes got "lost" when counting children due to a race condition. + This caused "proc_list_probe: lost pid" messages to be logged. + Problem noted by several people. + On systems with System V SIGCLD child signal semantics (notably AIX + and HP-UX), mail transactions would print the message "451 + SMTP-MAIL: lost child: No child processes". Problem noted + by several people. + Miscellaneous compiler warnings on picky compilers (or when setting + gcc to high warning levels). From Tom Moore of NCR Corp. + SMTP protocol errors, and most errors on MAIL FROM: lines should + not be persistent between runs, since they are based on the + message rather than the host. Problem noted by Matt Dillon + of Best Internet Communications. + The F=7 flag was ignored on SMTP mailers. Problem noted by Tom Moore + of NCR (a.k.a., AT&T Global Information Solutions). + Avoid the possibility of having a child daemon run to completion + (including closing the SMTP socket) before the parent has + had a chance to close the socket; this can cause the parent + to hang for a long time waiting for the socket to drain. + Patch from Don Lewis of TDK Semiconductor. + If the fork() failed in a queue run, the queue runners would not be + rescheduled (so queue runs would stop). Patch from Don Lewis. + Some error conditions in ETRN could cause output without an SMTP + status code. Problem noted by Don Lewis. + Multiple :maildrop addresses in the user database didn't work properly. + Patch from Roy Mongiovi of Georgia Tech. + Add ".db" automatically onto any user database spec that does not + already have it; this is for consistency with makemap, the + K line, and the documentation. Inconsistency pointed out + by Roy Mongiovi. + Allow sendmail to be properly called in nohup mode. Patch from + Kyle Jones of UUNET. + Change ETRN to ignore but still update host status files; previously + it would ignore them and not save the updated status, which + caused stale information to be maintained. Based on a patch + from Christopher Davis of Kapor Enterprises Inc. Also, have + ETRN ignore the MinQueueAge option. + Patch long term host status to recover more gracefully from an empty + host status file condition. Patch from NAKAMURA Motonori + of Kyoto University. + Several patches to signal handling code to fix potential race + conditions from Don Lewis. + Make it possible to compile with -DDAEMON=0 (previously it had some + compile errors). This turns DAEMON, QUEUE, and SMTP into + 0/1 compilation flags. Note that DAEMON is an obsolete + compile flag; use NETINET instead. Solution based on a + patch from Bryan Costales. + PORTABILITY FIXES: + AIX4: getpwnam() and getpwuid() do a sequential scan of the + /etc/security/passwd file when called as root. This + is very slow on some systems. To speed it up, use the + (undocumented) _getpw{nam,uid}_shadow() routines. + Patch from Chris Thomas of UCLA/OAC Systems Group. + SCO 5.x: include -lprot in the Makefile. Patch from Bill + Glicker of Burrelle's Information Service. + NEWS-OS 4.x: need a definition for MODE_T to compile. Patch + from Makoto MATSUSHITA of Osaka University. + SunOS 4.0.3: compile problems. Patches from Andrew Cole of + Leeds University and SASABE Tetsuro of the University + of Tokyo. + DG/UX 5.4.4.11 from Brian J. Murrell of InterLinx Support + Services, Inc. + Domain/OS from Don (Truck) Lewis of TDK Semiconductor Corp. + I believe this to have only been a problem if you + compiled with -DUSE_VENDOR_CF_PATH -- another reason + to stick with /etc/sendmail.cf as your One True Path. + Digital UNIX (OSF/1 on Alpha) load average computation from + Martin Laubach of the Technischen Universität Wien. + CONFIG: change default Received: line to be multiple lines rather + than one long one. By popular demand. + MAIL.LOCAL: warnings weren't being logged on some systems. Patch + from Jerome Berkman of U.C. Berkeley. + MAKEMAP: be sure to zero hinfo to avoid cruft that can cause runs + to take a very long time. Problem noted by Yoshiro YONEYA + of NTT Software Corporation. + CONTRIB: add etrn.pl, contributed by John Beck. + NEW FILES: + contrib/etrn.pl + +8.8.3/8.8.3 1996/11/17 + SECURITY: it was possible to get a root shell by lying to sendmail + about argv[0] and then sending it a signal. Problem noted + by Leshka Zakharoff on the + best-of-security list. + Log sendmail binary version number in "Warning: .cf version level + (%d) exceeds program functionality (%d) message" -- this + should make it clearer to people that they are running + the wrong binary. + Fix a problem that occurs when you open an SMTP connection and then + do one or more ETRN commands followed by a MAIL command; at + the end of the DATA phase sendmail would incorrectly report + "451 SMTP-MAIL: lost child: No child processes". Problem + noted by Eric Bishop of Virginia Tech. + When doing text-based host canonification (typically /etc/hosts + lookup), a null host name would match any /etc/hosts entry + with space at the end of the line. Problem noted by Steve + Hubert of the University of Washington, Seattle. + 7 to 8 bit BASE64 MIME conversions could duplicate bits of text. + Problem reported by Tom Smith of Digital Equipment Corp. + Increase the size of the DNS answer buffer -- the standard UDP packet + size PACKETSZ (512) is not sufficient for some nameserver + answers containing very many resource records. The resolver + may also switch to TCP and retry if it detects UDP packet + overflow. Also, allow for the fact that the resolver + routines res_query and res_search return the size of the + *un*truncated answer in case the supplied answer buffer it + not big enough to accommodate the entire answer. Patch from + Eric Wassenaar. + Improvements to MaxDaemonChildren code. If you think you have too + many children, probe the ones you have to verify that they + are still around. Suggested by Jared Mauch of CICnet, Inc. + Also, do this probe before growing the vector of children + pids; this previously caused the vector to grow indefinitely + due to a race condition. Problem reported by Kyle Jones of + UUNET. + On some architectures, (from the Berkeley DB library) defines + O_EXLOCK to zero; this fools the map compilation code into + thinking that it can avoid race conditions by locking on open. + Change it to check for O_EXLOCK non-zero. Problem noted by + Leif Erlingsson of Data Lege. + Always call res_init() on startup (if compiled in, of course) to + allow the sendmail.cf file to tweak resolver flags; without + it, flag tweaks in ResolverOptions are ignored. Patch from + Andrew Sun of Merrill Lynch. + Improvements to host status printing code. Suggested by Steve Hubert + of the University of Washington, Seattle. + Change MinQueueAge option processing to do the check for the job age + when reading the queue file, rather than at the end; this + avoids parsing the addresses, which can do DNS lookups. + Problem noted by John Beck of InReference, Inc. + When MIME was being 7->8 bit decoded, "From " lines weren't being + properly escaped. Problem noted by Peter Nilsson of the + University of Linkoping. + In some cases, sendmail would retain root permissions during queue + runs even if RunAsUser was set. Problem noted by Mark + Thomas of Mark G. Thomas Consulting. + If the F=l flag was set on an SMTP mailer to indicate that it is + actually local delivery, and NOTIFY=SUCCESS is specified in + the envelope, and the receiving SMTP server speaks DSN, then + the DSN would be both generated locally and propagated to the + other end. + The U= mailer field didn't correctly extract the group id if the + user id was numeric. Problem noted by Kenneth Herron of + MCI Telecommunications Communications. + If a message exceeded the fixed maximum size on input, the body of + the message was included in the bounce. Note that this did + not occur if it exceeded the maximum _output_ size. Problem + reported by Kyle Jones of UUNET. + PORTABILITY FIXES: + AIX4: 4.1 doesn't have a working setreuid(2); change the + AIX4 defines to use seteuid(2) instead, which + works on 4.1 as well as 4.2. Problem noted by + Håkan Lindholm of interAF, Sweden. + AIX4: use tzname[] vector to determine time zone name. + Patch from NAKAMURA Motonori of Kyoto University. + MkLinux: add Makefile.Linux.ppc and OSTYPE(mklinux) support. + Contributed by Paul DuBois . + Solaris: kstat(3k) support for retrieving the load average. + This adds the LA_KSTAT definition for LA_TYPE. + The outline of the implementation was contributed + by Michael Tokarev of Telecom Service, JSC, Moscow. + HP-UX 10.0 gripes about the (perfectly legal!) forward + declaration of struct rusage at the top of conf.h; + change it to only be included if you are using gcc, + which is apparently the only compiler that requires + it in the first place. Problem noted by Jeff + Earickson of Colby College. + IRIX: don't default to using gcc. IRIX is a civilized + operating system that comes with a decent compiler + by default. Problem noted by Barry Bouwsma and + Kari Hurtta. + CONFIG: specify F=9 as default in FEATURE(local_procmail) for + consistency with other local mailers. Inconsistency + pointed out by Teddy Hogeborn . + CONFIG: if the "limited best mx" feature is used (to reduce DNS + overhead) as part of the bestmx_is_local feature, the + domain part was dropped from the name. Patch from Steve + Hubert of the University of Washington, Seattle. + CONFIG: catch addresses of the form "user@.dom.ain"; these could + end up being translated to the null host name, which would + return any entry in /etc/hosts that had a space at the end + of the line. Problem noted by Steve Hubert of the + University of Washington, Seattle. + CONFIG: add OSTYPE(aix4). From Michael Sofka of Rensselaer + Polytechnic Institute. + MAKEMAP: tweak hash and btree parameters for better performance. + Patch from Matt Dillon of Best Internet Communications. + NEW FILES: + src/Makefiles/Makefile.Linux.ppc + cf/ostype/aix4.m4 + cf/ostype/mklinux.m4 + +8.8.2/8.8.2 1996/10/18 + SECURITY: fix a botch in the 7-bit MIME patch; the previous patch + changed the code but didn't fix the problem. + PORTABILITY FIXES: + Solaris: Don't use the system getusershell(3); it can + apparently corrupt the heap in some circumstances. + Problem found by Ken Pizzini of Spry, Inc. + OP.ME: document several mailer flags that were accidentally omitted + from this document. These flags were F=d, F=j, F=R, and F=9. + CONFIG: no changes. + +8.8.1/8.8.1 1996/10/17 + SECURITY: unset all environment variables that the resolver will + examine during queue runs and daemon mode. Problem noted + by Dan Bernstein of the University of Illinois at Chicago. + SECURITY: in some cases an illegal 7-bit MIME-encoded text/plain + message could overflow a buffer if it was converted back + to 8 bits. This caused core dumps and has the potential + for a remote attack. Problem first noted by Gregory Shapiro + of WPI. + Avoid duplicate deliveries of error messages on systems that don't + have flock(2) support. Patch from Motonori Nakamura of + Kyoto University. + Ignore null FallBackMX (V) options. If this option is null (as + opposed to undefined) it can cause "null signature" syserrs + on illegal host names. + If a Base64 encoded text/plain message has no trailing newline in + the encoded text, conversion back to 8 bits will drop the + final line. Problem noted by Pierre David. + If running with a RunAsUser, sendmail would give bogus "cannot + setuid" (or seteuid, or setreuid) messages on some systems. + Problem pointed out by Jordan Mendelson of Web Services, Inc. + Always print error messages in -bv mode -- previously, -bv would + be absolutely silent on errors if the error mode was sent + to (say) mail-back. Problem noted by Kyle Jones of UUNET. + If -qI/R/S is set (or the ETRN command is used), ignore all long + term host status. This is necessary because it is common + to do this when you know a host has just come back up. + Disallow duplicate HELO/EHLO commands as required by RFC 1651 section + 4.2. Excessive permissiveness noted by Lee Flight of the + University of Leicester. + If a service (such as NIS) is specified as the last entry in the + service switch, but that service is not compiled in, sendmail + would return a temporary failure when an entry was not found + in the map. This caused the message to be queued instead of + bouncing immediately. Problem noted by Harry Edmon of the + University of Washington. + PORTABILITY FIXES: + Solaris 2.3 had compilation problems in conf.c. Several + people pointed this out. + NetBSD from Charles Hannum of MIT. + AIX4 improvements based on info from Steve Bauer of South + Dakota School of Mines & Technology. + CONFIG: ``error:code message'' syntax was broken in virtusertable. + Patch from Gil Kloepfer Jr. + CONFIG: if FEATURE(nocanonify) was specified, hosts in $=M (set + using MASQUERADE_DOMAIN) were not masqueraded unless they + were also in $=w. Problem noted by Zoltan Basti of + Softec. + MAIL.LOCAL: patches to compile and link cleanly on AIX. Based + on a patch from Eric Hagberg of Morgan Stanley. + MAIL.LOCAL: patches to compile on NEXTSTEP. From Patrick Nolan + of Stanford via Robert La Ferla. + +8.8.0/8.8.0 1996/09/26 + Under some circumstances, Bcc: headers would not be properly + deleted. Pointed out by Jonathan Kamens of OpenVision. + Log a warning if the sendmail daemon is invoked without a full + pathname, which prevents "kill -1" from working. I was + urged to put this in by Andrey A. Chernov of DEMOS (Russia). + Fix small buffer overflow. Since the data in this buffer was not + read externally, there was no security problem (and in fact + probably wouldn't really overflow on most compilers). Pointed + out by KIZU takashi of Osaka University. + Fix problem causing domain literals such as [1.2.3.4] to be ignored + if a FallbackMXHost was specified in the configuration file + -- all mail would be sent to the fallback even if the original + host was accessible. Pointed out by Munenari Hirayama of + NSC (Japan). + A message that didn't terminate with a newline would (sometimes) not + have the trailing "." added properly in the SMTP dialogue, + causing SMTP to hang. Patch from Per Hedeland of Ericsson. + The DaemonPortOptions suboption to bind to a particular address was + incorrect and nonfunctional due to a misunderstanding of the + semantics of binding on a passive socket. Patch from + NIIBE Yutaka of Mitsubishi Research Institute. + Increase the number of MX hosts for a single name to 100 to better + handle the truly huge service providers such as AOL, which + has 13 at the moment (and climbing). In order to avoid + trashing memory, the buffer for all names has only been + slightly increased in size, to 12.8K from 10.2K -- this means + that if a single name had 100 MX records, the average size + of those records could not exceed 128 bytes. Requested by + Brad Knowles of America On Line. + Restore use of IDENT returns where the OSTYPE field equals "OTHER". + Urged by Dan Bernstein of U.C. Berkeley. + Print q_statdate and q_specificity in address structure debugging + printout. + Expand MCI structure flag bits for debugging output. + Support IPv6-style domain literals, which can have colons between + square braces. + Log open file descriptors for the "cannot dup" messages in deliver(); + this is an attempt to track down a bug that one person seems + to be having (it may be a Solaris bug!). + DSN NOTIFY parameters were not properly propagated across queue runs; + this caused the NOTIFY info to sometimes be lost. Problem + pointed out by Claus Assmann of the + Christian-Albrechts-University of Kiel. + The statistics gathered in the sendmail.st file were too high; in + some cases failures (e.g., user unknown or temporary failure) + would count as a delivery as far as the statistics were + concerned. Problem noted by Tom Moore of AT&T GIS. + Systems that don't have flock() would not send split envelopes in + the initial run. Problem pointed out by Leonard Zubkoff of + Dandelion Digital. + Move buffer overflow checking -- these primarily involve distrusting + results that may come from NIS and DNS. + 4.4-BSD-derived systems, including FreeBSD, NetBSD, and BSD/OS didn't + include and hence had the wrong pathnames for a few + things like /var/tmp. Reported by Matthew Green. + Conditions were reversed for the Priority: header, resulting in all + values being interpreted as non-urgent except for non-urgent, + which was interpreted as normal. Patch from Bryan Costales. + The -o (optional) flag was being ignored on hash and btree maps + since 8.7.2. Fix from Bryan Costales. + Content-Types listed in class "q" will always be encoded as + Quoted-Printable (or more accurately, will never be encoded + as base64). The class can have primary types (e.g., "text") + or full types (e.g., "text/plain"). Based on a suggestion by + Marius Olafsson of the University of Iceland. + Define ${envid} to be the original envelope id (from the ESMTP DSN + dialogue) so it can be passed to programs in mailers. + Define ${bodytype} to be the body type (from the -B flag or the + BODY= ESMTP parameter) so it can be passed to programs in + mailers. + Cause the VRFY command to return 252 instead of 250 unless the F=q + flag is set in the mailer descriptor. Suggested by John + Myers of CMU. + Implement ESMTP ETRN command to flush the queue for a specific host. + The command takes a host name; data for that host is + immediately (and asynchronously) flushed. Because this shares + the -qR implementation, other hosts may be attempted, but + there should be no security implications. Implementation + from John Beck of InReference, Inc. See RFC 1985 for details. + Add three new command line flags to pass in DSN parameters: -V envid + (equivalent to ENVID=envid on the MAIL command), -R ret + (equivalent to RET=ret on the MAIL command), and -Nnotify + (equivalent to NOTIFY=notify on the RCPT command). Note + that the -N flag applies to all recipients; there is no way + to specify per-address notifications on the command line, + nor is there an equivalent for the ORCPT= per-address + parameter. + Restore LogLevel option to be safe (it can only be increased); + apparently I went into paranoid mode between 8.6 and 8.7 + and made it unsafe. Pointed out by Dabe Murphy of the + University of Maryland. + New logging on log level 15: all SMTP traffic. Patches from + Andrew Gross of San Diego Supercomputer Center. + NetInfo property value searching code wasn't stopping when it found + a match. This was causing the wrong values to be found (and + had a memory leak). Found by Bastian Schleuter of TU-Berlin. + Add new F=0 (zero) mailer flag to turn off MX lookups. It was pointed + out by Bill Wisner of Electronics for Imaging that you can't + use the bracket address form for the MAIL_HUB macro, since + that causes the brackets to remain in the envelope recipient + address used for delivery. The simple fix (stripping off the + brackets in the config file) breaks the use of IP literal + addresses. This flag will solve that problem. + Add MustQuoteChars option. This is a list of characters that must + be quoted if they are found in the phrase part of an address + (that is, the full name part). The characters @,;:\()[] are + always in this list and cannot be removed. The default is + this list plus . and ' to match RFC 822. + Add AllowBogusHELO option; if set, sendmail will allow HELO commands + that do not include a host name for back compatibility with + some stupid SMTP clients. Setting this violates RFC 1123 + section 5.2.5. + Add MaxDaemonChildren option; if this is set, sendmail will start + rejecting connections if it has more than this many + outstanding children accepting mail. Note that you may + see more processes than this because of outgoing mail; this + is for incoming connections only. + Add ConnectionRateThrottle option. If set to a positive value, the + number of incoming SMTP connections that will be permitted + in a single second is limited to this number. Connections are + not refused during this time, just deferred. The intent is to + flatten out demand so that load average limiting can kick in. + It is less radical than MaxDaemonChildren, which will stop + accepting connections even if all the connections are idle + (e.g., due to connection caching). + Add Timeout.hoststatus option. This interval (defaulting to 30m) + specifies how long cached information about the state of a + host will be kept before they are considered stale and the + host is retried. If you are using persistent host status + (i.e., the HostStatusDirectory option is set) this will apply + between runs; otherwise, it applies only within a single queue + run and hence is useful only for hosts that have large queues + that take a very long time to run. + Add SingleLineFromHeader option. If set, From: headers are coerced + into being a single line even if they had newlines in them + when read. This is to get around a botch in Lotus Notes. + Text class maps were totally broken -- if you ever retrieved the last + item in a table it would be truncated. Problem noted by + Gregory Neil Shapiro of WPI. + Extend the lines printed by the mailq command (== the -bp flag) when + -v is given to 120 characters; this allows more information + to be displayed. Suggested by Gregory Neil Shapiro of WPI. + Allow macro definitions (`D' lines) with unquoted commas; previously + this was treated as end-of-input. Problem noted by Bryan + Costales. + The RET= envelope parameter (used for DSNs) wasn't properly written + to the queue file. Fix from John Hughes of Atlantic + Technologies, Inc. + Close /var/tmp/dead.letter after a successful write -- otherwise + if this happens in a queue run it can cause nasty delays. + Problem noted by Mark Horton of AT&T. + If userdb entries pointed to userdb entries, and there were multiple + values for a given key, the database cursor would get + trashed by the recursive call. Problem noted by Roy Mongiovi + of Georgia Tech. Fixed by reading all the values and creating + a comma-separated list; thus, the -v output will be somewhat + different for this case. + Fix buffer allocation problem with Hesiod-based userdb maps when + HES_GETMAILHOST is defined. Based on a patch by Betty Lee + of Stanford University. + When envelopes were split due to aliases with owner- aliases, and + there was some error on one of the lists, more than one of + the owners would get the message. Problem pointed out by + Roy Mongiovi of Georgia Tech. + Detect excessive recursion in macro expansions, e.g., $X defined + in terms of $Y which is defined in terms of $X. Problem + noted by Bryan Costales; patch from Eric Wassenaar. + When using F=U to get "ugly UUCP" From_ lines, a buffer could in + some cases get trashed causing bogus From_ lines. Fix from + Kyle Jones of UUNET. + When doing load average initialization, if the nlist call for avenrun + failed, the second and subsequent lookups wouldn't notice + that fact causing bogus load averages to be returned. Noted + by Casper Dik of Sun Holland. + Fix problem with incompatibility with some versions of inet_aton that + have changed the return value to unsigned, so a check for an + error return of -1 doesn't work. Use INADDR_NONE instead. + This could cause mail to addresses such as [foo.com] to bounce + or get dropped. Problem noted by Christophe Wolfhugel of the + Pasteur Institute. + DSNs were inconsistent if a failure occurred during the DATA phase + rather than the RCPT phase: the Action: would be correct, but + the detailed status information would be wrong. Problem noted + by Bob Snyder of General Electric Company. + Add -U command line flag and the XUSR ESMTP extension, both indicating + that this is the initial MUA->MTA submission. The flag current + does nothing, but in future releases (when MUAs start using + these flags) it will probably turn on things like DNS + canonification. + Default end-of-line string (E= specification on mailer [M] lines) + to \r\n on SMTP mailers. Default remains \n on non-SMTP + mailers. + Change the internal definition for the *file* and *include* mailers + to have $u in the argument vectors so that they aren't + misinterpreted as SMTP mailers and thus use \r\n line + termination. This will affect anyone who has redefined + either of these in their configuration file. + Don't assume that IDENT servers close the connection after a query; + responses can be newline terminated. From Terry Kennedy of + St. Peter's College. + Avoid core dumps on erroneous configuration files that have + $#mailer with nothing following. From Bryan Costales. + Avoid null pointer dereference with high debug values in unlockqueue. + Fix from Randy Martin of Clemson University. + Fix possible buffer overrun when expanding very large macros. Fix + from Kyle Jones of UUNET. + After 25 EXPN or VRFY commands, start pausing for a second before + processing each one. This avoids a certain form of denial + of service attack. Potential attack pointed out by Bryan + Costales. + Allow new named (not numbered!) config file rules to do validity + checking on SMTP arguments: check_mail for MAIL commands and + check_rcpt for RCPT commands. These rulesets can do anything + they want; their result is ignored unless they resolve to the + $#error mailer, in which case the indicated message is printed + and the command is rejected. Similarly, the check_compat + ruleset is called before delivery with "from_addr $| to_addr" + (the $| is a meta-symbol used to separate the two addresses); + it can give a "this sender can't send to this recipient" + notification. Note that this patch allows $| to stand alone + in rulesets. + Define new macros ${client_name}, ${client_addr}, and ${client_port} + that have the name, IP address, and port number (respectively) + of the SMTP client (that is, the entity at the other end of + the connection. These can be used in (e.g.) check_rcpt to + verify that someone isn't trying to relay mail through your + host inappropriately. Be sure to use the deferred evaluation + form, for example $&{client_name}, to avoid having these bound + when sendmail reads the configuration file. + Add new config file rule check_relay to check the incoming connection + information. Like check_compat, it is passed the host name + and host address separated by $| and can reject connections + on that basis. + Allow IDA-style recursive function calls. Code contributed by Mark + Lovell and Paul Vixie. + Eliminate the "No ! in UUCP From address!" message" -- instead, create + a virtual UUCP address using either a domain address or the $k + macro. Based on code contributed by Mark Lovell and Paul + Vixie. + Add Stanford LDAP map. Requires special libraries that are not + included with sendmail. Contributed by Booker C. Bense + ; contact him for support. + See also the src/READ_ME file. + Allow -dANSI to turn on ANSI escape sequences in debug output; this + puts metasymbols (e.g., $+) in reverse video. Really useful + only for debugging deep bits of code where it is important to + distinguish between the single-character metasymbol $+ and the + two characters $, +. + Changed ruleset 89 (executed in dumpstate()) to a named ruleset, + debug_dumpstate. + Add new UnsafeGroupWrites option; if set, .forward and :include: + files that are group writable are considered "unsafe" -- that + is, programs and files referenced from such files are not + valid recipients. + Delete bogosity test for FallBackMX host; this prevented it to be a + name that was not in DNS or was a domain-literal. Problem + noted by Tom May. + Change the introduction to error messages to more clearly delineate + permanent from temporary failures; if both existed in a + single message it could be confusing. Suggested by John + Beck of InReference, Inc. + The IngoreDot (i) option didn't work for lines that were terminated + with CRLF. Problem noted by Ted Stockwell of Secure + Computing Corporation. + Add a heuristic to improve the handling of unbalanced `<' signs in + message headers. Problem reported by Matt Dillon of Best + Internet Communications. + Check for bogus characters in the 0200-0237 range; since these are + used internally, very strange errors can occur if those + characters appear in headers. Problem noted by Anders Gertz + of Lysator. + Implement 7 -> 8 bit MIME conversions. This only takes place if the + recipient mailer has the F=9 flag set, and only works on + text/plain body types. Code contributed by Marius Olafsson + of the University of Iceland. + Special case "postmaster" name so that it is always treated as lower + case in alias files regardless of configuration settings; + this prevents some potential problems where "Postmaster" or + "POSTMASTER" might not match "postmaster". In most cases + this change is a no-op. + The -o map flag was ignored for text maps. Problem noted by Bryan + Costales. + The -a map flag was ignored for dequote maps. Problem noted by + Bryan Costales. + Fix core dump when a lookup of a class "prog" map returns no + response. Patch from Bryan Costales. + Log instances where sendmail is deferring or rejecting connections + on LogLevel 14. Suggested by Kyle Jones of UUNET. + Include port number in process title for network daemons. Suggested + by Kyle Jones of UUNET. + Send ``double bounces'' (errors that occur when sending an error + message) to the address indicated in the DoubleBounceAddress + option (default: postmaster). Previously they were always + sent to postmaster. Suggested by Kyle Jones of UUNET. + Add new mode, -bD, that acts like -bd in all respects except that + it runs in foreground. This is useful for using with a + wrapper that "watches" system services. Suggested by Kyle + Jones of UUNET. + Fix botch in spacing around (parenthesized) comments in addresses + when the comment comes before the address. Patch from + Motonori Nakamura of Kyoto University. + Use the prefix "Postmaster notify" on the Subject: lines of messages + that are being bounced to postmaster, rather than "Returned + mail". This permits the person who is postmaster more + easily determine what messages are to their role as + postmaster versus bounces to mail they actually sent. Based + on a suggestion by Motonori Nakamura. + Add new value "time" for QueueSortOrder option; this causes the queue + to be sorted strictly by the time of submission. Note that + this can cause very bad behavior over slow lines (because + large jobs will tend to delay small jobs) and on nodes with + heavy traffic (because old things in the queue for hosts that + are down delay processing of new jobs). Also, this does not + guarantee that jobs will be delivered in submission order + unless you also set DeliveryMode=queue. In general, it should + probably only be used on the command line, and only in + conjunction with -qRhost.domain. In fact, there are very few + cases where it should be used at all. Based on an + implementation by Motonori Nakamura. + If a map lookup in ruleset 5 returns tempfail, queue the message in + the same manner as other rulesets. Previously a temporary + failure in ruleset 5 was ignored. Patch from Booker Bense + of Stanford University. + Don't proceed to the next MX host if an SMTP MAIL command returns a + 5yz (permanent failure) code. The next MX host will still be + tried if the connection cannot be opened in the first place + or if the MAIL command returns a 4yz (temporary failure) code. + (It's hard to know what to do here, since neither RFC 974 nor + RFC 1123 specify when to proceed to the next MX host.) + Suggested by Jonathan Kamens of OpenVision, Inc. + Add new "-t" flag for map definitions (the "K" line in the .cf file). + This causes map lookups that get a temporary failure (e.g., + name server failure) to _not_ defer the delivery of the + message. This should only be used if your configuration file + is prepared to do something sensible in this case. Based on + an idea by Gregory Shapiro of WPI. + Fix problem finding network interface addresses. Patch from + Motonori Nakamura. + Don't reject qf entries that are not owned by your effective uid if + you are not running setuid; this makes management of certain + kinds of firewall setups difficult. Patch suggested by + Eamonn Coleman of Qualcomm. + Add persistent host status. This keeps the information normally + maintained within a single queue run in disk files that are + shared between sendmail instances. The HostStatusDirectory + is the directory in which the information is maintained. If + not set, persistent host status is turned off. If not a full + pathname, it is relative to the queue directory. A common + value is ".hoststat". + There are also two new operation modes: + * -bh prints the status of hosts that have had recent + connections. + * -bH purges the host statuses. No attempt is made to save + recent status information. + This feature was originally written by Paul Vixie of Vixie + Enterprises for KJS and adapted for V8 by Mark Lovell of + Bigrock Consulting. Paul's funding of Mark and Mark's patience + with my insistence that things fit cleanly into the V8 + framework is gratefully appreciated. + New SingleThreadDelivery option (requires HostStatusDirectory to + operate). Avoids letting two sendmails on the local machine + open connections to the same remote host at the same time. + This reduces load on the other machine, but can cause mail to + be delayed (for example, if one sendmail is delivering a huge + message, other sendmails won't be able to send even small + messages). Also, it requires another file descriptor (for the + lock file) per connection, so you may have to reduce + ConnectionCacheSize to avoid running out of per-process + file descriptors. Based on the persistent host status code + contributed by Paul Vixie and Mark Lovell. + Allow sending to non-simple files (e.g., /dev/null) even if the + SafeFileEnvironment option is set. Problem noted by Bryan + Costales. + The -qR flag mistakenly matched flags in the "R" line of the queue + file. Problem noted by Bryan Costales. + If a job was aborted using the interrupt signal (e.g., control-C from + the keyboard), on some occasions an empty df file would be + left around; these would collect in the queue directory. + Problem noted by Bryan Costales. + Change the makesendmail script to enhance the search for Makefiles + based on release number. For example, on SunOS 5.5.1, it will + search for Makefile.SunOS.5.5.1, Makefile.SunOS.5.5, and then + Makefile.SunOS.5.x (in addition to the other rules, e.g., + adding $arch). Problem noted by Jason Mastaler of Atlanta + Webmasters. + When creating maps using "newaliases", always map the keys to lower + case when creating the map unless the -f flag is specified on + the map itself. Previously this was done based on the F=u + flag in the local mailer, which meant you could create aliases + that you could never access. Problem noted by Bob Wu of DEC. + When a job was read from the queue, the bits causing notification on + failure or delay were always set. This caused those + notifications to be sent even if NOTIFY=NEVER had been + specified. Problem noted by Steve Hubert of the University + of Washington, Seattle. + Add new configurable routine validate_connection (in conf.c). This + lets you decide if you are willing to accept traffic from + this host. If it returns FALSE, all SMTP commands will return + "550 Access denied". -DTCPWRAPPERS will include support for + TCP wrappers; you will need to add -lwrap to the link line. + (See src/READ_ME for details.) + Don't include the "THIS IS A WARNING MESSAGE ONLY" banner on postmaster + bounces. Some people seemed to think that this could be + confusing (even though it is true). Suggested by Motonori + Nakamura. + Add new RunAsUser option; this causes sendmail to do a setuid to that + user early in processing to avoid potential security problems. + However, this means that all .forward and :include: files must + be readable by that user, and all files to be written must be + writable by that user and all programs will be executed by that + user. It is also incompatible with the SafeFileEnvironment + option. In other words, it may not actually add much to + security. However, it should be useful on firewalls and other + places where users don't have accounts and the aliases file is + well constrained. + Add Timeout.iconnect. This is like Timeout.connect except it is used + only on the first attempt to delivery to an address. It could + be set to be lower than Timeout.connect on the principle that + the mail should go through quickly to responsive hosts; less + responsive hosts get to wait for the next queue run. + Fix a problem on Solaris that occasionally causes programs + (such as vacation) to hang with their standard input connected + to a UDP port. It also created some signal handling problems. + The problems turned out to be an interaction between vfork(2) + and some of the libraries, particularly NIS/NIS+. I am + indebted to Tor Egge for this fix. + Change user class map to do the same matching that actual delivery + will do instead of just a /etc/passwd lookup. This adds + fuzzy matching to the user map. Patch from Dan Oscarsson. + The Timeout.* options are not safe -- they can be used to create a + denial-of-service attack. Problem noted by Christophe + Wolfhugel. + Don't send PostmasterCopy messages in the event of a "delayed" + notification. Suggested by Barry Bouwsma. + Don't advertise "VERB" ESMTP extension if the "noexpn" privacy + option is set, since this disables VERB mode. Suggested + by John Hawkinson of MIT. + Complain if the QueueDirectory (Q) option is not set. Problem noted + by Motonori Nakamura of Kyoto University. + Only queue messages on transient .forward open failures if there + were no successful opens. The previous behavior caused it + to queue even if a "fall back" .forward was found. Problem + noted by Ann-Kian Yeo of the Dept. of Information Systems + and Computer Science (DISCS), NUS, Singapore. + Don't do 8->7 bit conversions when bouncing a MIME message that + is bouncing because of a MIME error during 8->7 bit conversion; + the encapsulated message will bounce again, causing a loop. + Problem noted by Steve Hubert of the University of Washington. + Create xf (transcript) files using the TempFileMode option value + instead of 0644. Suggested by Ann-Kian Yeo of the + National University of Singapore. + Print errors if setgid/setuid/etc. fail during delivery. This helps + detect cases where DefaultUid is set to something that the + system can't cope with. + PORTABILITY FIXES: + Support for AIX/RS 2.2.1 from Mark Whetzel of Western + Atlas International. + Patches for Intel Paragon OSF/1 1.3 from Leo Bicknell + . + On DEC OSF/1 3.2 and earlier, the MatchGECOS code would only + work on the first recipient of a message due to a + bug in the getpwent family. If this is something you + use, you can define DEC_OSF_BROKEN_GETPWENT=1 for a + workaround. From Maximum Entropy of Sanford C. + Bernstein and Associates. + FreeBSD 1.1.5.1 uname -r returns a string containing + parentheses, which breaks makesendmail. Reported + by Piero Serini . + Sequent DYNIX/ptx 4.0.2 patches from Jack Woolley of + Systems and Computer Technology Corporation. + Solaris 2.x: omit the UUCP grade parameter (-g flag) because + it is system-dependent. Problem noted by J.J. Bailey + of Bailey Computer Consulting. + Pyramid NILE running DC/OSx support from Earle F. Ake of + Hassler Communication Systems Technology, Inc. + HP-UX 10.x compile glitches, reported by Anne Brink of the + U.S. Army and James Byrne of Harte & Lyne Limited. + NetBSD from Matthew Green of the NetBSD crew. + SCO 5.x from Keith Reynolds of SCO. + IRIX 6.2 from Robert Tarrall of the University of + Colorado and Kari Hurtta of the Finnish Meteorological + Institute. + UXP/DS (Fujitsu/ICL DS/90 series) support from Diego R. + Lopez, CICA (Seville). + NCR SVR4 MP-RAS 3.x support from Tom Moore of NCR. + PTX 3.2.0 from Kenneth Stailey of the US Department of Labor + Employment Standards Administration. + Altos System V (5.3.1) from Tim Rice of Multitalents. + Concurrent Systems Corporation Maxion from Donald R. Laster + Jr. + NetInfo maps (improved debugging and multi-valued aliases) + from Adrian Steinmann of Steinmann Consulting. + ConvexOS 11.5 (including SecureWare C2 and the Share Scheduler) + from Eric Schnoebelen of Convex. + Linux 2.0 mail.local patches from Horst von Brand. + NEXTSTEP 3.x compilation from Robert La Ferla. + NEXTSTEP 3.x code changes from Allan J. Nathanson of NeXT. + Solaris 2.5 configuration fixes for mail.local by Jim Davis + of the University of Arizona. + Solaris 2.5 has a working setreuid. Noted by David Linn of + Vanderbilt University. + Solaris changes for praliases, makemap, mailstats, and smrsh. + Previously you had to add -DSOLARIS in Makefile.dist; + this auto-detects. Based on a patch from Randall + Winchester of the University of Maryland. + CONFIG: add generic-nextstep3.3.mc file. Contributed by + Robert La Ferla of Hot Software. + CONFIG: allow mailertables to resolve to ``error:code message'' + (where "code" is an exit status) on domains (previously + worked only on hosts). Patch from Cor Bosman of Xs4all + Foundation. + CONFIG: hooks for IPv6-style domain literals. + CONFIG: predefine ALIAS_FILE and change the prototype file so that + if it is undefined the AliasFile option is never set; this + should be transparent for most everyone. Suggested by John + Myers of CMU. + CONFIG: add FEATURE(limited_masquerade). Without this feature, any + domain listed in $=w is masqueraded. With it, only those + domains listed in a MASQUERADE_DOMAIN macro are masqueraded. + CONFIG: add FEATURE(masquerade_entire_domain). This causes + masquerading specified by MASQUERADE_DOMAIN to apply to all + hosts under those domains as well as the domain headers + themselves. For example, if a configuration had + MASQUERADE_DOMAIN(foo.com), then without this feature only + foo.com would be masqueraded; with it, *.foo.com would be + masqueraded as well. Based on an implementation by Richard + (Pug) Bainter of U. Texas. + CONFIG: add FEATURE(genericstable) to do a more general rewriting of + outgoing addresses. Defaults to ``hash -o /etc/genericstable''. + Keys are user names; values are outgoing mail addresses. Yes, + this does overlap with the user database, and figuring out + just when to use which one may be tricky. Based on code + contributed by Richard (Pug) Bainter of U. Texas with updates + from Per Hedeland of Ericsson. + CONFIG: add FEATURE(virtusertable) to do generalized rewriting of + incoming addresses. Defaults to ``hash -o /etc/virtusertable''. + Keys are either fully qualified addresses or just the host + part (with the @ sign). For example, a table containing: + info@foo.com foo-info + info@bar.com bar-info + @baz.org jane@elsewhere.net + would send all mail destined for info@foo.com to foo-info + (which is presumably an alias), mail addressed to info@bar.com + to bar-info, and anything addressed to anyone at baz.org will + be sent to jane@elsewhere.net. The names foo.com, bar.com, + and baz.org must all be in $=w. Based on discussions with + a great many people. + CONFIG: add nullclient configurations to define SMTP_MAILER_FLAGS. + Suggested by Richard Bainter. + CONFIG: add FAX_MAILER_ARGS to tweak the arguments passed to the + "fax" mailer. + CONFIG: allow mailertable entries to resolve to local:user; this + passes the original user@host in to procmail-style local + mailers as the "detail" information to allow them to do + additional clever processing. From Joe Pruett of + Teleport Corporation. Delivery to the original user can + be done by specifying "local:" (with nothing after the colon). + CONFIG: allow any context that takes "mailer:domain" to also take + "mailer:user@domain" to force mailing to the given user; + "local:user" can also be used to do local delivery. This + applies on *_RELAY and in the mailertable entries. Based + on a suggestion by Ribert Kiessling of Easynet. + CONFIG: Allow FEATURE(bestmx_is_local) to take an argument that + limits the possible domains; this reduces the number of DNS + lookups required to support this feature. For example, + FEATURE(bestmx_is_local, my.site.com) limits the lookups + to domains under my.site.com. Code contributed by Anthony + Thyssen . + CONFIG: LOCAL_RULESETS introduces any locally defined rulesets, + such as the check_rcpt ruleset. Suggested by Gregory Shapiro + of WPI. + CONFIG: MAILER_DEFINITIONS introduces any mailer definitions, in the + event you have to define local mailers. Suggested by + Gregory Shapiro of WPI. + CONFIG: fix cases where a three- (or more-) stage route-addr could + be misinterpreted as a list:...; syntax. Based on a patch by + Vlado Potisk . + CONFIG: Fix masquerading of UUCP addresses when the UUCP relay is + remotely connected. The address host!user was being + converted to host!user@thishost instead of host!user@uurelay. + Problem noted by William Gianopoulos of Raytheon Company. + CONFIG: add confTO_ICONNECT to set Timeout.iconnect. + CONFIG: change FEATURE(redirect) message from "User not local" to + "User has moved"; the former wording was confusing if the + new address is still on the local host. Based on a suggestion + by Andreas Luik. + CONFIG: add support in FEATURE(nullclient) for $=E (exposed users). + However, the class is not pre-initialized to contain root. + Suggested by Gregory Neil Shapiro. + CONTRIB: Remove XLA code at the request of the author, Christophe + Wolfhugel. + CONTRIB: Add re-mqueue.pl, contributed by Paul Pomes of Qualcomm. + MAIL.LOCAL: make it possible to compile mail.local on Solaris. Note + well: this produces a slightly different mailbox format (no + Content-Length: headers), file ownerships and modes are + different (not owned by group mail; mode 600 instead of 660), + and the local mailer flags will have to be tweaked (make them + match bsd4.4) in order to use this mailer. Patches from Paul + Hammann of the Missouri Research and Education Network. + MAIL.LOCAL: in some cases it could return EX_OK even though there + was a delivery error, such as if the ownership on the file + was wrong or the mode changed between the initial stat and + the open. Problem reported by William Colburn of the New + Mexico Institute of Mining and Technology. + MAILSTATS: handle zero length files more reliably. Patch from Bryan + Costales. + MAILSTATS: add man page contributed by Keith Bostic of BSDI. + MAKEMAP: The -d flag (to allow duplicate keys) to a btree map wasn't + honored. Fix from Michael Scott Shappe. + PRALIASES: add man page contributed by Keith Bostic of BSDI. + NEW FILES: + src/Makefiles/Makefile.AIX.2 + src/Makefiles/Makefile.IRIX.6.2 + src/Makefiles/Makefile.maxion + src/Makefiles/Makefile.NCR.MP-RAS.3.x + src/Makefiles/Makefile.SCO.5.x + src/Makefiles/Makefile.UXPDSV20 + mailstats/mailstats.8 + praliases/praliases.8 + cf/cf/generic-nextstep3.3.mc + cf/feature/genericstable.m4 + cf/feature/limited_masquerade.m4 + cf/feature/masquerade_entire_domain.m4 + cf/feature/virtusertable.m4 + cf/ostype/aix2.m4 + cf/ostype/altos.m4 + cf/ostype/maxion.m4 + cf/ostype/solaris2.ml.m4 + cf/ostype/uxpds.m4 + contrib/re-mqueue.pl + DELETED FILES: + src/Makefiles/Makefile.Solaris + contrib/xla/README + contrib/xla/xla.c + RENAMED FILES: + src/Makefiles/Makefile.NCR3000 => Makefile.NCR.MP-RAS.2.x + src/Makefiles/Makefile.SCO.3.2v4.2 => Makefile.SCO.4.2 + src/Makefiles/Makefile.UXPDS => Makefile.UXPDSV10 + src/Makefiles/Makefile.NeXT => Makefile.NeXT.2.x + src/Makefiles/Makefile.NEXTSTEP => Makefile.NeXT.3.x + +8.7.6/8.7.3 1996/09/17 + SECURITY: It is possible to force getpwuid to fail when writing the + queue file, causing sendmail to fall back to running programs + as the default user. This is not exploitable from off-site. + Workarounds include using a unique user for the DefaultUser + (old u & g options) and using smrsh as the local shell. + SECURITY: fix some buffer overruns; in at least one case this allows + a local user to get root. This is not known to be exploitable + from off-site. The workaround is to disable chfn(1) commands. + +8.7.5/8.7.3 1996/03/04 + Fix glitch in 8.7.4 when putting certain internal lines; this can + in some case cause connections to hang or messages to have + extra spaces in odd places. Patch from Eric Wassenaar; + reports from Eric Hall of Chiron Corporation, Stephen + Hansen of Stanford University, Dean Gaudet of HotWired, + and others. + +8.7.4/8.7.3 1996/02/18 + SECURITY: In some cases it was still possible for an attacker to + insert newlines into a queue file, thus allowing access to + any user (except root). + CONFIG: no changes -- it is not a bug that the configuration + version number is unchanged. + +8.7.3/8.7.3 1995/12/03 + Fix botch in name server timeout in RCPT code; this problem caused + two responses in SMTP, which breaks things horribly. Fix + from Gregory Neil Shapiro of WPI. + Verify that L= value on M lines cannot be negative, which could cause + negative array subscripting. Not a security problem since + this has to be in the config file, but it could have caused + core dumps. Pointed out by Bryan Costales. + Fix -d21 debug output for long macro names. Pointed out by Bryan + Costales. + PORTABILITY FIXES: + SCO doesn't have ftruncate. From Bill Aten of Computerizers. + IBM's version of arpa/nameser.h defaults to the wrong byte + order. Tweak it to work properly. Based on fixes + from Fletcher Mattox of UTexas and Betty Lee of + Stanford University. + CONFIG: add confHOSTS_FILE m4 variable to set HostsFile option. + Deficiency pointed out by Bryan Costales of ICSI. + +8.7.2/8.7.2 1995/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, its value is tossed, + but the header name is kept. The old behavior (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: : set + sender to
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 behavior 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 pointed out 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. Suggested + 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 . + 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 + preponderance 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 + . + 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. + Extensive cleanups to map open code to handle a locking race condition + in ndbm, hash, and btree format database files on some (most + non-4.4-BSD based) OS architectures. This should solve the + occasional "user unknown" problem during alias rebuilds that + has plagued me for quite some time. Based on a patch from + Thomas Dwyer III of Michigan Technological 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 ; + portability changes for Posix environments (no functional + changes). + +8.7.1/8.7.1 1995/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 + 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 + . + Support for Fujitsu/ICL UXP/DS (For the DS/90 Series) + from Diego R. Lopez . + 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 1995/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 accidentally. + 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. + ``/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 weird because it + would cause a "warning" message to be sent to the Postmaster + for every message sent (but with no transcript). Problem + noted by Gregory Paris of Motorola. + 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 disastrous 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 behavior. 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 -- + support for them has been removed. + 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 "#@#", where + 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, + NAKAMURA Motonori + (romanized/less information) + =?ISO-2022-JP?B?GyRCQ2ZCPBsoQg==?= + =?ISO-2022-JP?B?GyRCQUdFNRsoQg==?= + (with MIME encoding, not human readable) + #@# ^[$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 propagate environment + variables into children. "E" will propagate + the named variable from the environment when sendmail + was invoked into any children it calls; "E=" + 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 . + 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 weird I haven't thought of. + Suggested by Barry Shein of Software Tool & Die. + SECURITY: .forward files cannot be symbolic links. If they are, + a bad guy can read your private files. + PORTABILITY FIXES: + Solaris 2 from Rob McMahon . + 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 . To + get the old behavior, use -DDGUX_5_4_2. + DG/UX hack: add _FORCE_MAIL_LOCAL_=yes environment + variable to fix bogus /bin/mail behavior. + Tandem NonStop-UX from Rick McCarty . + 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 licensed back to AT&T and + Microsoft and became System V release 3.2'') from + Tim Rice . + OSF/1 running on Intel Paragon from Jeff A. Earickson + of Intel Scalable Systems + Division. + Amdahl UTS System V 2.1.5 (SVr3-based) from Janet Jackson + . + 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 . + 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 behavior. 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 accidentally 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" (CheckAliases) 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 . + 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.13/8.6.12 1996/01/25 + SECURITY: In some cases it was still possible for an attacker to + insert newlines into a queue file, thus allowing access to + any user (except root). + CONFIG: no changes -- it is not a bug that the configuration + version number is unchanged. + +8.6.12/8.6.12 1995/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 1995/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 1995/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 long. 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 1994/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 behavior + 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 1994/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 1994/03/14 + SECURITY: it was possible to get root access by using weird + values to the -d flag. Thanks to Alain Durand of + INRIA for forwarding me the notice from the bugtraq + list. + +8.6.6/8.6.6 1994/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 , + , or 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 + . + 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 weird way the name server works in the presence + of CNAME loops). Problem noted by James M.R.Matheson + of Cambridge University. + Avoid giving ``warning: foo owned process doing -bs'' messages + if they use ``MAIL FROM:'' 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 . + 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 + . + 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 Software. + DomainOS from Don Lewis of Silicon Systems. + GNU m4 1.0.3 from Karst Koymans of Utrecht University. + Convex from Kimmo Suominen . + NetBSD from Adam Glass . + 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 1994/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 behaviors 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 publicly + readable but in a non-publicly 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 around + them in non-SMTP envelopes (SMTP envelopes already do + this properly). + Avoid weird headers on unbalanced punctuation of the form: + ``Joe User ; 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 + ). + 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 1993/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 syntax correctly. This isn't legal, but + it shouldn't fail miserably. From Motonori Nakamura. + +8.6.2/8.6.2 1993/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 PrivacyOptions 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 1993/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 + propagated to the queue file. + +8.6/8.6 1993/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 ), 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 `` '', auto-quote the first + ``'' part, giving ``"" ''. 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 The University of + Melbourne. + 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 1993/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 1993/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 -bs + instead of using standard flags. Oh joy. This + behavior 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 1993/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 weird error diagnoses. + From Michael Corrigan. + CONFIG: add UUCP_MAX_SIZE M4 macro to set the maximum size of + messages sent through UUCP-family mailers. Suggested + 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 1993/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 + . + Solaris 2 compatibility changes. Provided by Bob Cunningham + , John Oleynick + + 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 weird cases. From Eric Wassenaar. + Clean up statistics gathering; it was over-reporting because of + forks. From Eric Wassenaar. + Fix problem that causes old Return-Path: line to override new + 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 diagnosed. 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 permission 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 occasional 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 1993/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 1993/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 1993/06/08 + Another mailertable fix.... + +8.1/8.1 1993/06/07 + 4.4BSD freeze. No semantic changes. diff --git a/gnu/usr.sbin/sendmail/cf/README b/gnu/usr.sbin/sendmail/cf/README new file mode 100644 index 00000000000..7004aa983c8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/README @@ -0,0 +1,3013 @@ + + SENDMAIL CONFIGURATION FILES + +This document describes the sendmail configuration files. This package +requires a post-V7 version of m4; if you are running the 4.2bsd, SysV.2, or +7th Edition version. SunOS's /usr/5bin/m4 or BSD-Net/2's m4 both work. +GNU m4 version 1.1 or later also works. Unfortunately, the M4 on BSDI 1.0 +doesn't work -- you'll have to use a Net/2 or GNU version. GNU m4 is +available from ftp://ftp.gnu.org/pub/gnu/m4-1.4.tar.gz (check for the +latset version). EXCEPTIONS: DEC's m4 on Digital UNIX 4.x is broken (3.x +is fine). Use GNU m4 on this platform. + +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 previously used at +Berkeley. For example, ucbvax has gone away, but ucbvax.mc demonstrates +some interesting techniques. + +******************************************************************* +*** BE SURE YOU CUSTOMIZE THESE FILES! They have some *** +*** Berkeley-specific assumptions built in, such as the name *** +*** of their UUCP-relay. You'll want to create your own *** +*** domain description, and use that in place of *** +*** domain/Berkeley.EDU.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 + +Alternatively, you can simply: + + cd ${CFDIR}/cf + ./Build 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) 1998-2000 Sendmail, Inc. and its suppliers. + # All rights reserved. + # Copyright (c) 1983 Eric P. Allman. All rights reserved. + # Copyright (c) 1988, 1993 + # The Regents of the University of California. All rights reserved. + # + # By using this file, you agree to the terms and conditions set + # forth in the LICENSE file which can be found at the top level of + # the sendmail distribution. + # + + # + # This is a Berkeley-specific configuration file for HP-UX 9.x. + # It applies only to 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 replaced by whatever your lawyers require; +our lawyers require the one that is included in these files. A copyleft +is a copyright by another name. The divert(0) restores regular output. + + VERSIONID(`') + +VERSIONID is a macro that stuffs the version information into the +resulting file. You could use SCCS, RCS, CVS, 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. The +local mailer is always included automatically. Beware: MAILER +declarations should always be at the end of the configuration file, +and MAILER(`smtp') should always precede MAILER(`procmail'), and +MAILER(`uucp'). The general rules are that the order should be: + + VERSIONID + OSTYPE + DOMAIN + FEATURE + local macro definitions + MAILER + LOCAL_RULE_* + LOCAL_RULESETS + +There are a few exceptions to this rule. Local macro definitions which +influence a FEATURE() should be done before that feature. For example, +a define(`PROCMAIL_MAILER_PATH', ...) should be done before +FEATURE(`local_procmail'). + + ++----------------------------+ +| A BRIEF INTRODUCTION TO M4 | ++----------------------------+ + +Sendmail uses the M4 macro processor to ``compile'' the configuration +files. The most important thing to know is that M4 is stream-based, +that is, it doesn't understand about lines. For this reason, in some +places you may see the word ``dnl'', which stands for ``delete +through newline''; essentially, it deletes all characters starting +at the ``dnl'' up to and including the next newline character. In +most cases sendmail uses this only to avoid lots of unnecessary +blank lines in the output. + +Other important directives are define(A, B) which defines the macro +``A'' to have value ``B''. Macros are expanded as they are read, so +one normally quotes both values to prevent expansion. For example, + + define(`SMART_HOST', `smart.foo.com') + +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'. + ++----------------+ +| FILE LOCATIONS | ++----------------+ + +sendmail 8.9 has introduced a new configuration directory for sendmail +related files, /etc/mail. The new files available for sendmail 8.9 -- +the class 'R' /etc/mail/relay-domains and the access database +/etc/mail/access -- take advantage of this new directory. Beginning with +8.10, all files will use this directory by default (some options may be +set by OSTYPE() files). This new directory should help to restore +uniformity to sendmail's file locations. + +Below is a table of some of the common changes: + +Old filename New filename +------------ ------------ +/etc/bitdomain /etc/mail/bitdomain +/etc/domaintable /etc/mail/domaintable +/etc/genericstable /etc/mail/genericstable +/etc/uudomain /etc/mail/uudomain +/etc/virtusertable /etc/mail/virtusertable +/etc/userdb /etc/mail/userdb + +/etc/aliases /etc/mail/aliases +/etc/sendmail/aliases /etc/mail/aliases +/etc/ucbmail/aliases /etc/mail/aliases +/usr/adm/sendmail/aliases /etc/mail/aliases +/usr/lib/aliases /etc/mail/aliases +/usr/lib/mail/aliases /etc/mail/aliases +/usr/ucblib/aliases /etc/mail/aliases + +/etc/sendmail.cw /etc/mail/local-host-names +/etc/mail/sendmail.cw /etc/mail/local-host-names +/etc/sendmail/sendmail.cw /etc/mail/local-host-names + +/etc/sendmail.ct /etc/mail/trusted-users + +/etc/sendmail.oE /etc/mail/error-header + +/etc/sendmail.hf /etc/mail/helpfile +/etc/mail/sendmail.hf /etc/mail/helpfile +/usr/ucblib/sendmail.hf /etc/mail/helpfile +/etc/ucbmail/sendmail.hf /etc/mail/helpfile +/usr/lib/sendmail.hf /etc/mail/helpfile +/usr/share/lib/sendmail.hf /etc/mail/helpfile +/usr/share/misc/sendmail.hf /etc/mail/helpfile +/share/misc/sendmail.hf /etc/mail/helpfile + +/etc/service.switch /etc/mail/service.switch + +/etc/sendmail.st /etc/mail/statistics +/etc/mail/sendmail.st /etc/mail/statistics +/etc/mailer/sendmail.st /etc/mail/statistics +/etc/sendmail/sendmail.st /etc/mail/statistics +/usr/lib/sendmail.st /etc/mail/statistics +/usr/ucblib/sendmail.st /etc/mail/statistics + +Note that all of these paths actually use a new m4 macro MAIL_SETTINGS_DIR +to create the pathnames. The default value of this variable is +`/etc/mail/'. If you set this macro to a different value, you MUST include +a trailing slash. + ++--------+ +| 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/mail/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 [/etc/mail/helpfile] 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. To use multiple queues, supply + a value ending with an asterisk. For + example, /var/spool/mqueue/q* will use all of the + directories or symbolic links to directories + beginning with 'q' in /var/spool/mqueue as queue + directories. +STATUS_FILE [/etc/mail/statistics] The file containing status + information. +LOCAL_MAILER_PATH [/bin/mail] The program used to deliver local mail. +LOCAL_MAILER_FLAGS [Prmn9] The flags used by the local mailer. The + flags lsDFMAw5:/|@q 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_MAXMSGS [undefined] If defined, the maximum number of + messages to deliver in a single connection. Only + useful for LMTP local mailers. +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 + labeled with this character set. +LOCAL_MAILER_EOL [undefined] If defined, the string to use as the + end of line for the local mailer. +LOCAL_MAILER_DSN_DIAGNOSTIC_CODE + [X-Unix] The DSN Diagnostic-Code value for the + local mailer. This should be changed with care. +LOCAL_SHELL_PATH [/bin/sh] The shell used to deliver piped email. +LOCAL_SHELL_FLAGS [eu9] 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 [rsDFMmn] 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'; "smtp8" adds `8'; and + "dsmtp" adds `%'. +RELAY_MAILER_FLAGS [undefined] Flags added to the relay mailer. Default + flags are `mDFMuX' for all SMTP-based mailers; the + relay mailer adds `a8'. +SMTP_MAILER_MAX [undefined] The maximum size of messages that will + be transported using the smtp, smtp8, esmtp, or dsmtp + mailers. +SMTP_MAILER_MAXMSGS [undefined] If defined, the maximum number of + messages to deliver in a single connection for the + smtp, smtp8, esmtp, or dsmtp 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. +DSMTP_MAILER_ARGS [IPC $h] The arguments passed to the dsmtp mailer. +RELAY_MAILER_ARGS [IPC $h] The arguments passed to the relay mailer. +RELAY_MAILER_MAXMSGS [undefined] If defined, the maximum number of + messages to deliver in a single connection for 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 labeled with this character set. +UUCP_MAILER_PATH [/usr/bin/uux] The program used to send UUCP mail. +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 labeled with this character set. +FAX_MAILER_PATH [/usr/local/lib/fax/mailfax] The program used to + submit FAX messages. +FAX_MAILER_ARGS [mailfax $u $h $f] The arguments passed to the FAX + mailer. +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 lsDFMq + are always added. +POP_MAILER_ARGS [pop $u] The arguments passed to the POP mailer. +PROCMAIL_MAILER_PATH [/usr/local/bin/procmail] The path to the procmail + program. This is also used by + FEATURE(`local_procmail'). +PROCMAIL_MAILER_FLAGS [SPhnu9] Flags added to Procmail mailer. Flags + DFM are always set. This is NOT used by + FEATURE(`local_procmail'); tweak LOCAL_MAILER_FLAGS + instead. +PROCMAIL_MAILER_ARGS [procmail -Y -m $h $f $u] The arguments passed to + the Procmail mailer. This is NOT used by + FEATURE(`local_procmail'); tweak LOCAL_MAILER_ARGS + instead. +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. Flags nrDFM + are always set. +PH_MAILER_ARGS [phquery -- $u] -- arguments to the phquery mailer. +CYRUS_MAILER_FLAGS [Ah5@/:|] The flags used by the cyrus mailer. The + flags lsDFMnPq are always included. +CYRUS_MAILER_PATH [/usr/cyrus/bin/deliver] The program used to deliver + cyrus mail. +CYRUS_MAILER_ARGS [deliver -e -m $h -- $u] The arguments passed + to deliver cyrus mail. +CYRUS_MAILER_MAX [undefined] If set, the maximum size message that + will be accepted by the cyrus mailer. +CYRUS_MAILER_USER [cyrus:mail] The user and group to become when + running the cyrus mailer. +CYRUS_BB_MAILER_FLAGS [u] 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. +confEBINDIR [/usr/libexec] The directory for executables. + Currently used for FEATURE(`local_lmtp') and + FEATURE(`smrsh'). +QPAGE_MAILER_FLAGS [mDFMs] The flags used by the qpage mailer. +QPAGE_MAILER_PATH [/usr/local/bin/qpage] The program used to deliver + qpage mail. +QPAGE_MAILER_ARGS [qpage -l0 -m -P$u] The arguments passed + to deliver qpage mail. +QPAGE_MAILER_MAX [4096] If set, the maximum size message that + will be accepted by the qpage mailer. + +Note: to tweak Name_MAILER_FLAGS use the macro MODIFY_MAILER_FLAGS: +MODIFY_MAILER_FLAGS(`Name', `change') where Name is the first part of +the macro Name_MAILER_FLAGS and change can be: flags that should +be used directly (thus overriding the default value), or if it +starts with `+' (`-') then those flags are added to (removed from) +the default value. Example: + + MODIFY_MAILER_FLAGS(`LOCAL', `+e') + +will add the flag `e' to LOCAL_MAILER_FLAGS. +WARNING: The FEATUREs local_lmtp and local_procmail set LOCAL_MAILER_FLAGS +unconditionally, i.e., without respecting any definitions in an +OSTYPE setting. + + ++---------+ +| DOMAINS | ++---------+ + +You will probably want to collect domain-dependent defines into one +file, referenced by the DOMAIN macro. For example, the 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. To + specify a local user instead of a site, set this to + ``local:username''. + +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") 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') and MAILER(`procmail') -- several features and +definitions will modify the definition of mailers, and the smtp mailer +modifies the UUCP mailer. Moreover, MAILER(`cyrus'), MAILER(`pop'), +MAILER(`phquery'), and MAILER(`usenet') must be defined after +MAILER(`local'). + +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 + five 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), "dsmtp" to do on + demand delivery, and "relay" for transmission to the + RELAY_HOST, LUSER_RELAY, or MAIL_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 HylaFAX software. For more information, + see http://www.vix.com/hylafax/. + +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 cyrus mailer must be + defined after the local mailer. + +qpage A mailer for QuickPage, a pager interface. See + http://www.qpage.org/ for further information. + +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 , +"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/mail/local-host-names +file to get values for class $=w. The FEATURE may contain up to 9 +optional parameters -- for example: + + FEATURE(`mailertable', `dbm /usr/lib/mailertable') + +The default database map type for the table features can be set with + + define(`DATABASE_MAP_TYPE', `dbm') + +which would set it to use ndbm databases. The default is the Berkeley DB +hash database format. Note that you must still declare a database map type +if you specify an argument to a FEATURE. DATABASE_MAP_TYPE is only used +if no argument is given for the FEATURE. It must be specified before any +feature that uses a map. + +Available features are: + +use_cw_file Read the file /etc/mail/local-host-names 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 + ..." (where the names are fully qualified domain + names) is probably superior. The actual filename can be + overridden by redefining confCW_FILE. + +use_ct_file Read the file /etc/mail/trusted-users 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
'' message. + If this is set, you can alias people who have left + to their new address with ".REDIRECT" appended. + +nouucp Don't route UUCP addresses. This feature takes one + parameter: + `reject': reject addresses which have "!" in the local + part unless it originates from a system + that is allowed to relay. + `nospecial': don't do anything special with "!". + Warnings: 1. See the NOTICE in the ANTI-SPAM section. + 2. don't remove "!" from OperatorChars if `reject' is + given as parameter. + +nocanonify Don't pass addresses to $[ ... $] for canonification + by default. It can be changed by setting the + DaemonPortOptions modifiers (M=). That is, + FEATURE(`nocanonify') will be overridden by setting the + 'c' flag. Conversely, if FEATURE(`nocanonify') is not used, + it can be emulated by setting the 'C' flag + (DaemonPortOptions=Modifiers=C). 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. + + An exception list for FEATURE(`nocanonify') can be + specified with CANONIFY_DOMAIN or CANONIFY_DOMAIN_FILE, + i.e., a list of domains which are nevertheless passed to + $[ ... $] for canonification. This is useful to turn on + canonification for local domains, e.g., use + CANONIFY_DOMAIN(`my.domain my') to canonify addresses + which end in "my.domain" or "my". + Another way to require canonification in the local + domain is CANONIFY_DOMAIN(`$=m'). + + A trailing dot is added to addresses with more than + one component in it such that other features which + expect a trailing dot (e.g., virtusertable) will + still work. + + If `canonify_hosts' is specified as parameter, i.e., + FEATURE(`nocanonify', `canonify_hosts'), then + addresses which have only a hostname, e.g., + , will be canonified (and hopefully fully + qualified), too. + +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 (which are not in $=w, i.e. + local host names). The argument of the FEATURE may be the + key definition. If none is specified, the definition used + is: + + hash /etc/mail/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". As a + special case of the latter, "." matches any domain not + covered by other keys. 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. As a special case, + the forms: + local:user + will forward to the indicated user using the local mailer, + local: + will forward to the original user in the e-mail address + using the local mailer, and + error:code message + error:D.S.N:code message + will give an error message with the indicated SMTP reply + code and message, where D.S.N is an RFC 1893 compliant + error code. + +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 /etc/mail/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 /etc/mail/bitdomain + + Keys are the bitnet hostname; values are the corresponding + internet hostname. + +uucpdomain Similar feature for UUCP hosts. The default map definition + is: + + hash /etc/mail/uudomain + + 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 on unqualified names. + However, if you use a shared message store but do not use + the same user name space everywhere, you may need the host + name on local names. + +allmasquerade If masquerading is enabled (using MASQUERADE_AS), this + feature will cause recipient addresses to also masquerade + 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. + +limited_masquerade + Normally, any hosts listed in $=w are masqueraded. If this + feature is given, only the hosts listed in $=M are masqueraded. + This is useful if you have several domains with disjoint + namespaces hosted on the same machine. + +masquerade_entire_domain + If masquerading is enabled (using MASQUERADE_AS) and + MASQUERADE_DOMAIN (see below) is set, this feature will + cause addresses to be rewritten such that the masquerading + domains are actually entire domains to be hidden. All + hosts within the masquerading domains will be rewritten + to the masquerade name (used in MASQUERADE_AS). For example, + if you have: + + MASQUERADE_AS(`masq.com') + MASQUERADE_DOMAIN(`foo.org') + MASQUERADE_DOMAIN(`bar.com') + + then *foo.org and *bar.com are converted to masq.com. Without + this feature, only foo.org and bar.com are masqueraded. + + NOTE: only domains within your jurisdiction and + current hierarchy should be masqueraded using this. + +genericstable This feature will cause certain addresses originating locally + (i.e., that are unqualified) or a domain listed in $=G to be + looked up in a map and turned into another ("generic") form, + which can change both the domain name and the user name. This + is similar to the userdb functionality. The same types of + addresses as for masquerading are looked up, i.e., only header + sender addresses unless the allmasquerade and/or + masquerade_envelope features are given. Qualified addresses + must have the domain part in the list of names given by the + by the macros GENERICS_DOMAIN or GENERICS_DOMAIN_FILE + (analogously to MASQUERADE_DOMAIN and MASQUERADE_DOMAIN_FILE, + see below). + + The argument of FEATURE(`genericstable') may be the map + definition; the default map definition is: + + hash /etc/mail/genericstable + + The key for this table is either the full address, the domain + (with a leading @; the localpart is passed as first argument) + or the unqualified username (tried in the order mentioned); + the value is the new user address. If the new user address + does not include a domain, it will be qualified in the standard + manner, i.e., using $j or the masquerade name. Note that the + address being looked up must be fully qualified. For local + mail, it is necessary to use FEATURE(`always_add_domain') + for the addresses to be qualified. + The "+detail" of an address is passed as %1, so entries like + + old+*@foo.org new+%1@example.com + gen+*@foo.org %1@example.com + + and other forms are possible. + +generics_entire_domain + If the genericstable is enabled and GENERICS_DOMAIN or + GENERICS_DOMAIN_FILE is used, this feature will cause + addresses to be searched in the map if their domain + parts are subdomains of elements in class $=G. + +virtusertable A domain-specific form of aliasing, allowing multiple + virtual domains to be hosted on one machine. For example, + if the virtuser table contained: + + info@foo.com foo-info + info@bar.com bar-info + joe@bar.com error:nouser No such user here + jax@bar.com error:D.S.N:unavailable Address invalid + @baz.org jane@example.net + + then mail addressed to info@foo.com will be sent to the + address foo-info, mail addressed to info@bar.com will be + delivered to bar-info, and mail addressed to anyone at baz.org + will be sent to jane@example.net, mail to joe@bar.com will + be rejected with the specified error message, and mail to + jax@bar.com will also have a RFC 1893 compliant error code + D.S.N. + + The username from the original address is passed + as %1 allowing: + + @foo.org %1@example.com + + meaning someone@foo.org will be sent to someone@example.com. + Additionally, if the local part consists of "user+detail" + then "detail" is passed as %2 when a match against user+* + is attempted, so entries like + + old+*@foo.org new+%2@example.com + gen+*@foo.org %2@example.com + + and other forms are possible. + + All the host names on the left hand side (foo.com, bar.com, + and baz.org) must be in $=w or $={VirtHost}, the latter can + be defined by the macros VIRTUSER_DOMAIN or + VIRTUSER_DOMAIN_FILE (analogously to MASQUERADE_DOMAIN and + MASQUERADE_DOMAIN_FILE, see below). If VIRTUSER_DOMAIN or + VIRTUSER_DOMAIN_FILE is used, then the entries of $={VirtHost} + are added to class 'R', i.e., relaying is allowed to + (and from) those domains. The default map definition is: + + hash /etc/mail/virtusertable + + A new definition can be specified as the second argument of + the FEATURE macro, such as + + FEATURE(`virtusertable', `dbm /etc/mail/virtusers') + +virtuser_entire_domain + If the virtusertable is enabled and VIRTUSER_DOMAIN or + VIRTUSER_DOMAIN_FILE is used, this feature will cause + addresses to be searched in the map if their domain + parts are subdomains of elements in class $={VirtHost}. + +ldap_routing Implement LDAP-based e-mail recipient routing according to + the Internet Draft draft-lachman-laser-ldap-mail-routing-01. + This provides a method to re-route addresses with a + domain portion in the $={LDAPRoute} class to either a + different mail host or a different address. Hosts can + be added to this class using LDAPROUTE_DOMAIN and + LDAPROUTE_DOMAIN_FILE (analogously to MASQUERADE_DOMAIN and + MASQUERADE_DOMAIN_FILE, see below). + + See the LDAP ROUTING section below for more information. + +nodns If you aren't running DNS at your site (for example, + you are UUCP-only connected). It's hard to consider + this a "feature", but hey, it had to go somewhere. + Actually, as of 8.7 this is a no-op -- remove "dns" from + the hosts service switch entry instead. + +nullclient This is a special case -- it creates a 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 qualified 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_lmtp Use an LMTP capable local mailer. The argument to this + feature is the pathname of an LMTP capable mailer. By + default, mail.local is used. This is expected to be the + mail.local which came with the 8.9 distribution which is + LMTP capable. The path to mail.local is set by the + confEBINDIR m4 variable -- making the default + LOCAL_MAILER_PATH /usr/libexec/mail.local. + WARNING: This feature sets LOCAL_MAILER_FLAGS unconditionally, + i.e., without respecting any definitions in an OSTYPE setting. + +local_procmail Use procmail or another delivery agent as the local mailer. + The argument to this feature is the pathname of the + delivery agent, which defaults to PROCMAIL_MAILER_PATH. + Note that this does NOT use PROCMAIL_MAILER_FLAGS or + PROCMAIL_MAILER_ARGS for the local mailer; tweak + LOCAL_MAILER_FLAGS and LOCAL_MAILER_ARGS instead, or + specify the appropriate parameters. When procmail is used, + the local 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. + + This feature can take up to three arguments: + + 1. Path to the mailer program + [default: /usr/local/bin/procmail] + 2. Argument vector including name of the program + [default: procmail -Y -a $h -d $u] + 3. Flags for the mailer [default: SPfhn9] + + Empty arguments cause the defaults to be taken. + + For example, this allows it to use the maildrop + (http://www.flounder.net/~mrsam/maildrop/) mailer instead + by specifying: + + FEATURE(`local_procmail', `/usr/local/bin/maildrop', + `maildrop -d $u') + + or scanmails using: + + FEATURE(`local_procmail', `/usr/local/bin/scanmails') + + WARNING: This feature sets LOCAL_MAILER_FLAGS unconditionally, + i.e., without respecting any definitions in an OSTYPE setting. + +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. The argument may be a set of + domains, which will limit the feature to only apply to + these domains -- this will reduce unnecessary DNS + traffic. 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, the path defined by + confEBINDIR is used for the smrsh binary -- by default, + /usr/libexec/smrsh is assumed. + +promiscuous_relay + By default, the sendmail configuration files do not permit + mail relaying (that is, accepting mail from outside your + domain and sending it to another host outside your domain). + This option sets your site to allow mail relaying from any + site to any site. In general, it is better to control the + relaying more carefully with the access db and the 'R' + class ($=R). Domains can be added to class 'R' by the + macros RELAY_DOMAIN or RELAY_DOMAIN_FILE (analogously to + MASQUERADE_DOMAIN and MASQUERADE_DOMAIN_FILE, see below). + +relay_entire_domain + By default, only hosts listed as RELAY in the access db + will be allowed to relay. This option also allows any + host in your domain as defined by the 'm' class ($=m). + +relay_hosts_only + By default, names that are listed as RELAY in the access + db and class 'R' ($=R) are domain names, not host names. + For example, if you specify ``foo.com'', then mail to or + from foo.com, abc.foo.com, or a.very.deep.domain.foo.com + will all be accepted for relaying. This feature changes + the behaviour to lookup individual host names only. + +relay_based_on_MX + Turns on the ability to allow relaying based on the MX + records of the host portion of an incoming recipient; that + is, if an MX record for host foo.com points to your site, + you will accept and relay mail addressed to foo.com. See + description below for more information before using this + feature. Also, see the KNOWNBUGS entry regarding bestmx + map lookups. + + FEATURE(`relay_based_on_MX') does not necessarily allow + routing of these messages which you expect to be allowed, + if route address syntax (or %-hack syntax) is used. If + this is a problem, add entries to the access-table or use + FEATURE(`loose_relay_check'). + +relay_mail_from + Allows relaying if the mail sender is listed as RELAY in the + access map. If an optional argument `domain' is given, the + domain portion of the mail sender is checked too. This + should only be used if absolutely necessary as the sender + address can be easily forged. + +relay_local_from + Allows relaying if the domain portion of the mail sender + is a local host. This should only be used if absolutely + necessary as it opens a window for spammers. Specifically, + they can send mail to your mail server that claims to be + from your domain (either directly or via a routed address), + and you will go ahead and relay it out to arbitrary hosts + on the Internet. + +accept_unqualified_senders + Normally, MAIL FROM: commands in the SMTP session will be + refused if the connection is a network connection and the + sender address does not include a domain name. If your + setup sends local mail unqualified (i.e., MAIL FROM: ), + you will need to use this feature to accept unqualified + sender addresses. Setting the DaemonPortOptions modifier + 'u' overrides the default behavior, i.e., unqualified + addresses are accepted even without this FEATURE. + If this FEATURE is not used, the DaemonPortOptions modifier + 'f' can be used to enforce fully qualified addresses. + +accept_unresolvable_domains + Normally, MAIL FROM: commands in the SMTP session will be + refused if the host part of the argument to MAIL FROM: + cannot be located in the host name service (e.g., an A or + MX record in DNS). If you are inside a firewall that has + only a limited view of the Internet host name space, this + could cause problems. In this case you probably want to + use this feature to accept all domains on input, even if + they are unresolvable. + +access_db Turns on the access database feature. The access db gives + you the ability to allow or refuse to accept mail from + specified domains for administrative reasons. By default, + the access database specification is: + + hash /etc/mail/access + + The format of the database is described in the anti-spam + configuration control section later in this document. + +blacklist_recipients + Turns on the ability to block incoming mail for certain + recipient usernames, hostnames, or addresses. For + example, you can block incoming mail to user nobody, + host foo.mydomain.com, or guest@bar.mydomain.com. + These specifications are put in the access db as + described in the anti-spam configuration control section + later in this document. + +rbl This feature is deprecated! Please use dnsbl instead. + Turns on rejection of hosts found in the Realtime Blackhole + List. If an argument is provided it is used as the domain + in which blocked hosts are listed; otherwise, the main + RBL domain rbl.maps.vix.com is used. For details, see + http://maps.vix.com/rbl/. + +dnsbl Turns on rejection of hosts found in an DNS based rejection + list. If an argument is provided it is used as the name + sever to contact; otherwise it defaults to rbl.maps.vix.com. + An explanation for an DNS based rejection list can be found + http://maps.vix.com/rbl/. A second argument can be used to + change the default error message of + Mail from $&{client_addr} refused by blackhole site SERVER + where SERVER is replaced by the first argument. This feature + can be included several times to query different DNS based + rejection lists. + +loose_relay_check + Normally, if % addressing is used for a recipient, e.g. + user%site@othersite, and othersite is in class 'R', the + check_rcpt ruleset will strip @othersite and recheck + user@site for relaying. This feature changes that + behavior. It should not be needed for most installations. + +no_default_msa Don't generate the default MSA daemon, i.e., + DAEMON_OPTIONS(`Port=587,Name=MSA,M=E') + To define a MSA daemon with other parameters, use this + FEATURE and introduce new settings via DAEMON_OPTIONS(). + ++-------+ +| 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 moving 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/mail/local-host-names containing a list of your aliases (one per +line), and use ``FEATURE(`use_cw_file')'' in the .mc file, or add +``LOCAL_DOMAIN(`alias.host.name')''. 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 this +out-of-date configuration file has been left 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: + +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 addresses 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. Do not declare rulesets in +the LOCAL_CONFIG section. It can be used to declare local database maps or +whatever. For example: + + LOCAL_CONFIG + Khostmap hash /etc/mail/hostmap + Kyplocal nis -m hosts.byname + + ++---------------------------+ +| MASQUERADING AND RELAYING | ++---------------------------+ + +You can have your host masquerade as another using + + MASQUERADE_AS(`host.domain') + +This causes mail being sent to be labeled as coming from the +indicated host.domain, rather than $j. One normally masquerades as +one of one's own subdomains (for example, it's unlikely that +Berkeley would choose to masquerade as an MIT site). This +behaviour is modified by a plethora of FEATUREs; in particular, see +masquerade_envelope, allmasquerade, limited_masquerade, and +masquerade_entire_domain. + +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. However, if you use a CNAME, the receiving side may canonify +it for you, so don't think you can cheat CNAME mapping this way. + +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. + +To exempt hosts or subdomains from being masqueraded, you can use + + MASQUERADE_EXCEPTION(`host.domain') + +This can come handy if you want to masquerade a whole domain +except for one (or a few) host(s). + +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 (which has been "exposed" by default prior to 8.10). +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/mail/exposed-users + +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 +"relay". 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/mail/local-users + +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 "relay". 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 you 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 unqualified 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 or + bracketed addresses (e.g., "eric@mastodon.CS.Berkeley.EDU" + or "eric@[127.0.0.1]"). + +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. + +For duplicate suppression to work properly, the host name is best +specified with a terminal dot: + + define(`MAIL_HUB', `host.domain.') + note the trailing dot ---^ + + ++--------------+ +| LDAP ROUTING | ++--------------+ + +FEATURE(`ldap_routing') can be used to implement the IETF Internet Draft +LDAP Schema for Intranet Mail Routing +(draft-lachman-laser-ldap-mail-routing-01). This feature enables +LDAP-based rerouting of a particular address to either a different host +or a different address. The LDAP lookup is first attempted on the full +address (e.g., user@example.com) and then on the domain portion +(e.g., @example.com). Be sure to setup your domain for LDAP routing using +LDAPROUTE_DOMAIN(), e.g.: + + LDAPROUTE_DOMAIN(`example.com') + +By default, the feature will use the schemas as specified in the draft +and will not reject addresses not found by the LDAP lookup. However, +this behavior can be changed by giving additional arguments to the FEATURE() +command: + + FEATURE(`ldap_routing', , , ) + +where is a map definition describing how to lookup an alternative +mail host for a particular address; is a map definition +describing how to lookup an alternative address for a particular address; and +the argument, if present and not the word "passthru", dictates +that mail should be bounced if neither a mailHost nor mailRoutingAddress +is found. + +The default map definition is: + + ldap -1 -v mailHost -k (&(objectClass=inetLocalMailRecipient) + (mailLocalAddress=%0)) + +The default map definition is: + + ldap -1 -v mailRoutingAddress -k (&(objectClass=inetLocalMailRecipient) + (mailLocalAddress=%0)) + +Note that neither includes the LDAP server hostname (-h server) or base DN +(-b o=org,c=COUNTRY), both necessary for LDAP queries. It is presumed that +your .mc file contains a setting for the confLDAP_DEFAULT_SPEC option with +these settings. If this is not the case, the map definitions should be +changed as described above. + +The following possibilities exist as a result of an LDAP lookup on an +address: + + mailHost is mailRoutingAddress is Results in + ----------- --------------------- ---------- + set to a set mail delivered to + "local" host mailRoutingAddress + + set to a not set delivered to + "local" host original address + + set to a set mailRoutingAddress + remote host relayed to mailHost + + set to a not set original address + remote host relayed to mailHost + + not set set mail delivered to + mailRoutingAddress + + not set not set delivered to + original address *OR* + bounced as unknown user + +The term "local" host above means the host specified is in class 'w' ($=w). +Note that the last case depends on whether the third argument is given +to the FEATURE() command. The default is to deliver the message to the +original address. + +The LDAP entries should be set up with an objectClass of +inetLocalMailRecipient and the address be listed in a mailLocalAddress +attribute. If present, there must be only one mailHost attribute and it +must contain a fully qualified host name as its value. Similarly, if +present, there must be only one mailRoutingAddress attribute and it must +contain an RFC 822 compliant address. Some example LDAP records (in ldif +format): + + dn: uid=tom, o=example.com, c=US + objectClass: inetLocalMailRecipient + mailLocalAddress: tom@example.com + mailRoutingAddress: thomas@mailhost.example.com + +This would deliver mail for tom@example.com to thomas@mailhost.example.com. + + dn: uid=dick, o=example.com, c=US + objectClass: inetLocalMailRecipient + mailLocalAddress: dick@example.com + mailHost: eng.example.com + +This would relay mail for dick@example.com to the same address but redirect +the mail to MX records listed for the host eng.example.com. + + dn: uid=harry, o=example.com, c=US + objectClass: inetLocalMailRecipient + mailLocalAddress: harry@example.com + mailHost: mktmail.example.com + mailRoutingAddress: harry@mkt.example.com + +This would relay mail for harry@example.com to the MX records listed for +the host mktmail.example.com using the new address harry@mkt.example.com +when talking to that host. + + dn: uid=virtual.example.com, o=example.com, c=US + objectClass: inetLocalMailRecipient + mailLocalAddress: @virtual.example.com + mailHost: server.example.com + mailRoutingAddress: virtual@example.com + +This would send all mail destined for any username @virtual.example.com to +the machine server.example.com's MX servers and deliver to the address +virtual@example.com on that relay machine. + + ++---------------------------------+ +| ANTI-SPAM CONFIGURATION CONTROL | ++---------------------------------+ + +The primary anti-spam features available in sendmail are: + +* Relaying is denied by default. +* Better checking on sender information. +* Access database. +* Header checks. + +Relaying (transmission of messages from a site outside your domain to +another site outside your domain) is denied by default. Note that +this changed in sendmail 8.9; previous versions allowed relaying by +default. If you want to revert to the old behaviour, you will need +to use FEATURE(`promiscuous_relay'). You can allow certain domains to +relay through your server by adding their domain name or IP address to +class 'R' ($=R) using RELAY_DOMAIN() and RELAY_DOMAIN_FILE() or via the +access database (described below). + +If you use + + FEATURE(`relay_entire_domain') + +then any host in any of your local domains (that is, the $=m class) +will be relayed (that is, you will accept mail either to or from any +host in your domain). + +You can also allow relaying based on the MX records of the host +portion of an incoming recipient address by using + + FEATURE(`relay_based_on_MX') + +For example, if your server receives a recipient of user@domain.com +and domain.com lists your server in its MX records, the mail will be +accepted for relay to domain.com. Note that this will stop spammers +from using your host to relay spam but it will not stop outsiders from +using your server as a relay for their site (that is, they set up an +MX record pointing to your mail server, and you will relay mail addressed +to them without any prior arrangement). Along the same lines, + + FEATURE(`relay_local_from') + +will allow relaying if the sender specifies a return path (i.e. +MAIL FROM: ) domain which is a local domain. This a +dangerous feature as it will allow spammers to spam using your mail +server by simply specifying a return address of user@your.domain.com. +It should not be used unless absolutely necessary. +A slightly better solution is + + FEATURE(`relay_mail_from') + +which allows relaying if the mail sender is listed as RELAY in the +access map. If an optional argument `domain' is given, the domain +portion of the mail sender is also checked to allowing relaying. +This option only works together with the tag From: for the LHS of +the access map entries (see below: Finer control...). + + +If source routing is used in the recipient address (i.e. +RCPT TO: ), sendmail will check +user@site.com for relaying if othersite.com is an allowed relay host +in either class 'R', class 'm' if FEATURE(`relay_entire_domain') is used, +or the access database if FEATURE(`access_db') is used. To prevent +the address from being stripped down, use: + + FEATURE(`loose_relay_check') + +If you think you need to use this feature, you probably do not. This +should only be used for sites which have no control over the addresses +that they provide a gateway for. Use this FEATURE with caution as it +can allow spammers to relay through your server if not setup properly. + +NOTICE: It is possible to relay mail through a system which the anti-relay +rules do not prevent: the case of a system that does use FEATURE(`nouucp', +`nospecial') (system A) and relays local messages to a mail hub (e.g., via +LOCAL_RELAY or LUSER_RELAY) (system B). If system B doesn't use +FEATURE(`nouucp') at all, addresses of the form + would be relayed to . +System A doesn't recognize `!' as an address separator and therefore +forwards it to the mail hub which in turns relays it because it came from +a trusted local host. So if a mailserver allows UUCP (bang-format) +addresses, all systems from which it allows relaying should do the same +or reject those addresses. + +As of 8.9, sendmail will refuse mail if the MAIL FROM: parameter has +an unresolvable domain (i.e., one that DNS, your local name service, +or special case rules in ruleset 3 cannot locate). If you want to +continue to accept such domains, e.g., because you are inside a +firewall that has only a limited view of the Internet host name space +(note that you will not be able to return mail to them unless you have +some "smart host" forwarder), use + + FEATURE(`accept_unresolvable_domains') + +sendmail will also refuse mail if the MAIL FROM: parameter is not +fully qualified (i.e., contains a domain as well as a user). If you +want to continue to accept such senders, use + + FEATURE(`accept_unqualified_senders') + +Setting the DaemonPortOptions modifier 'u' overrides the default behavior, +i.e., unqualified addresses are accepted even without this FEATURE. If +this FEATURE is not used, the DaemonPortOptions modifier 'f' can be used +to enforce fully qualified addresses. + +An ``access'' database can be created to accept or reject mail from +selected domains. For example, you may choose to reject all mail +originating from known spammers. To enable such a database, use + + FEATURE(`access_db') + +The FEATURE macro can accept a second parameter giving the key file +definition for the database; for example + + FEATURE(`access_db', `hash /etc/mail/access') + +Remember, since /etc/mail/access is a database, after creating the text +file as described below, you must use makemap to create the database +map. For example: + + makemap hash /etc/mail/access < /etc/mail/access + +The table itself uses e-mail addresses, domain names, and network +numbers as keys. For example, + + spammer@aol.com REJECT + cyberspammer.com REJECT + 192.168.212 REJECT + +would refuse mail from spammer@aol.com, any user from cyberspammer.com +(or any host within the cyberspammer.com domain), and any host on the +192.168.212.* network. + +The value part of the map can contain: + + OK Accept mail even if other rules in the + running ruleset would reject it, for example, + if the domain name is unresolvable. + RELAY Accept mail addressed to the indicated domain or + received from the indicated domain for relaying + through your SMTP server. RELAY also serves as + an implicit OK for the other checks. + REJECT Reject the sender or recipient with a general + purpose message. + DISCARD Discard the message completely using the + $#discard mailer. For sender addresses it + indicates that you should discard anything + received from the indicated domain. If it + is used for recipients, it affects only + the designated recipients, not the whole + message. + ### any text where ### is an RFC 821 compliant error code + and "any text" is a message to return for + the command. + ERROR:### any text + as above, but useful to mark error messages as such. + ERROR:D.S.N:### any text + where D.S.N is an RFC 1893 compliant error code + and the rest as above. + +For example: + + cyberspammer.com 550 We don't accept mail from spammers + okay.cyberspammer.com OK + sendmail.org RELAY + 128.32 RELAY + 1:2:3:4:5:6:7 RELAY + [127.0.0.3] OK + [1:2:3:4:5:6:7:8] OK + +would accept mail from okay.cyberspammer.com, but would reject mail from +all other hosts at cyberspammer.com with the indicated message. It would +allow relaying mail from and to any hosts in the sendmail.org domain, and +allow relaying from the 128.32.*.* network and the IPv6 1:2:3:4:5:6:7:* +network. The latter two entries are for checks against ${client_name} if +the IP address doesn't resolve to a hostname (or is considered as "may be +forged"). + +Warning: if you change the RFC 821 compliant error code from the default +value of 550, then you should probably also change the RFC 1893 compliant +error code to match it. For example, if you use + + user@example.com 450 mailbox full + +the error returned would be "450 4.0.0 mailbox full" which is wrong. +Use "450 4.2.2 mailbox full" or "ERROR:4.2.2:450 mailbox full" +instead. + +Note, UUCP users may need to add hostname.UUCP to the access database +or class 'R' ($=R). If you also use: + + FEATURE(`relay_hosts_only') + +then the above example will allow relaying for sendmail.org, but not +hosts within the sendmail.org domain. Note that this will also require +hosts listed in class 'R' ($=R) to be fully qualified host names. + +You can also use the access database to block sender addresses based on +the username portion of the address. For example: + + FREE.STEALTH.MAILER@ 550 Spam not accepted + +Note that you must include the @ after the username to signify that +this database entry is for checking only the username portion of the +sender address. + +If you use: + + FEATURE(`blacklist_recipients') + +then you can add entries to the map for local users, hosts in your +domains, or addresses in your domain which should not receive mail: + + badlocaluser@ 550 Mailbox disabled for this username + host.mydomain.com 550 That host does not accept mail + user@otherhost.mydomain.com 550 Mailbox disabled for this recipient + +This would prevent a recipient of badlocaluser@mydomain.com, any +user at host.mydomain.com, and the single address +user@otherhost.mydomain.com from receiving mail. Please note: a +local username must be now tagged with an @ (this is consistent +with the check of the sender address, and hence it is possible to +distinguish between hostnames and usernames). Enabling this feature +will keep you from sending mails to all addresses that have an +error message or REJECT as value part in the access map. Taking +the example from above: + + spammer@aol.com REJECT + cyberspammer.com REJECT + +Mail can't be sent to spammer@aol.com or anyone at cyberspammer.com. + +There is also a ``Realtime Blackhole List'' run by the MAPS project +at http://maps.vix.com/. This is a database maintained in DNS of +spammers. To use this database, use + + FEATURE(`dnsbl') + +This will cause sendmail to reject mail from any site in the +Realtime Blackhole List database. You can specify an alternative +RBL domain to check by specifying an argument to the FEATURE. +A second argument can be used to change the default error message +Mail from $&{client_addr} refused by blackhole site DOMAIN +where DOMAIN is replaced by the first argument. This FEATURE can +be included several times to query different DNS based rejection +lists, e.g., the dial-up user list (see http://maps.vix.com/dul/). + +The features described above make use of the check_relay, check_mail, +and check_rcpt rulesets. If you wish to include your own checks, +you can put your checks in the rulesets Local_check_relay, +Local_check_mail, and Local_check_rcpt. For example if you wanted to +block senders with all numeric usernames (i.e. 2312343@bigisp.com), +you would use Local_check_mail and the new regex map: + + LOCAL_CONFIG + Kallnumbers regex -a@MATCH ^[0-9]+$ + + LOCAL_RULESETS + SLocal_check_mail + # check address against various regex checks + R$* $: $>Parse0 $>3 $1 + R$+ < @ bigisp.com. > $* $: $(allnumbers $1 $) + R@MATCH $#error $: 553 Header Error + +These rules are called with the original arguments of the corresponding +check_* ruleset. If the local ruleset returns $#OK, no further checking +is done by the features described above and the mail is accepted. If the +local ruleset resolves to a mailer (such as $#error or $#discard), the +appropriate action is taken. Otherwise, the results of the local +rewriting are ignored. + +Finer control by using tags for the LHS of the access map + +Read this section only if the options listed so far are not sufficient +for your purposes. There is now the option to tag entries in the +access map according to their type. Three tags are available: + + Connect: connection information (${client_addr}, ${client_name}) + From: sender + To: recipient + +If the required item is looked up in a map, it will be tried first +with the corresponding tag in front, then (as fallback to enable +backward compatibility) without any tag. For example, + + From:spammer@some.dom REJECT + To:friend.domain RELAY + Connect:friend.domain OK + Connect:from.domain RELAY + From:good@another.dom OK + From:another.dom REJECT + +This would deny mails from spammer@some.dom but you could still +send mail to that address even if FEATURE(`blacklist_recipients') +is enabled. Your system will allow relaying to friend.domain, but +not from it (unless enabled by other means). Connections from that +domain will be allowed even if it ends up in one of the DNS based +rejection lists. Relaying is enabled from from.domain but not to +it (since relaying is based on the connection information for +outgoing relaying, the tag Connect: must be used; for incoming +relaying, which is based on the recipient address, To: must be +used). The last two entries allow mails from good@another.dom but +reject mail from all other addresses with another.dom as domain +part. + +Delay all checks + +By using FEATURE(`delay_checks') the rulesets check_mail and check_relay +will not be called when a client connects or issues a MAIL command, +respectively. Instead, those rulesets will be called by the check_rcpt +ruleset; they will be skipped if a sender has been authenticated using +a "trusted" mechanism, i.e., one that is defined via TRUST_AUTH_MECH(). +Moreover, an argument can be specified for this option: + + friend: enable spamfriend test + hater: enable spamhater test + +If such an argument is given, the recipient will be looked up in the access +map (using the tag To:). If the argument is `friend', then the other +rulesets will be skipped if the recipient address is found and has RHS +spamfriend. If the argument is `hater', then the other rulesets will be +applied if the recipient address is found and has RHS spamhater. + +This allows for simple exceptions from the tests, e.g., by activating +the spamfriend option and having + + To:abuse@ SPAMFRIEND + +in the access map, mail to abuse@localdomain will get through. It is +also possible to specify a full address or an address with +detail: + + To:abuse@abuse.my.domain SPAMFRIEND + To:me+abuse@ SPAMFRIEND + + +Header Checks + +You can also reject mail on the basis of the contents of headers. +This is done by adding a ruleset call to the 'H' header definition command +in sendmail.cf. For example, this can be used to check the validity of +a Message-ID: header: + + LOCAL_RULESETS + HMessage-Id: $>CheckMessageId + + SCheckMessageId + R< $+ @ $+ > $@ OK + R$* $#error $: 553 Header Error + +The alternative format: + + HSubject: $>+CheckSubject + +that is, $>+ instead of $>, gives the full Subject: header including +comments to the ruleset (comments in parentheses () are stripped +by default). + +A default ruleset for headers which don't have a specific ruleset +defined for them can be given by: + + H*: $>CheckHdr + +After all of the headers are read, the check_eoh ruleset will be called for +any final header-related checks. The ruleset is called with the number of +headers and the size of all of the headers in bytes separated by $|. One +example usage is to reject messages which do not have a Message-Id: +header. However, the Message-Id: header is *NOT* a required header and is +not a guaranteed spam indicator. This ruleset is an example and should +probably not be used in production. + + LOCAL_CONFIG + Kstorage macro + + LOCAL_RULESETS + HMessage-Id: $>CheckMessageId + + SCheckMessageId + # Record the presence of the header + R$* $: $(storage {MessageIdCheck} $@ OK $) $1 + R< $+ @ $+ > $@ OK + R$* $#error $: 553 Header Error + + Scheck_eoh + # Check the macro + R$* $: < $&{MessageIdCheck} > + # Clear the macro for the next message + R$* $: $(storage {MessageIdCheck} $) $1 + # Has a Message-Id: header + R< $+ > $@ OK + # Allow missing Message-Id: from local mail + R$* $: < $&{client_name} > + R< > $@ OK + R< $=w > $@ OK + # Otherwise, reject the mail + R$* $#error $: 553 Header Error + ++--------------------------------+ +| SMTP AUTHENTICATION | ++--------------------------------+ + +The macros ${auth_authen}, ${auth_author}, and ${auth_type} can be +used in anti-relay rulesets to allow relaying for those users that +authenticated themselves. A very simple example is: + +SLocal_check_rcpt +R$* $: $&{auth_type} +R$+ $# OK + +which checks whether a user has successfully authenticated using +any available mechanism. Depending on the setup of the CYRUS SASL +library, more sophisticated rulesets might be required, e.g., + +SLocal_check_rcpt +R$* $: $&{auth_type} $| $&{auth_authen} +RDIGEST-MD5 $| $+@$=w $# OK + +to allow relaying for users that authenticated using DIGEST-MD5 +and have an identity in the local domains. + +The ruleset Strust_auth is used to determine whether a given AUTH= +parameter (that is passed to this ruleset) should be trusted. This +ruleset may make use of the other ${auth_*} macros. Only if the +ruleset resolves to the error mailer, the AUTH= parameter is not +trusted. A user supplied ruleset Local_trust_auth can be written +to modify the default behavior, which only trust the AUTH= +parameter if it is identical to the authenticated user. + +Per default, relaying is allowed for any user who authenticated +via a "trusted" mechanism, i.e., one that is defined via +TRUST_AUTH_MECH(`list of mechanisms') + ++--------------------------------+ +| ADDING NEW MAILERS OR RULESETS | ++--------------------------------+ + +Sometimes you may need to add entirely new mailers or rulesets. They +should be introduced with the constructs MAILER_DEFINITIONS and +LOCAL_RULESETS respectively. For example: + + MAILER_DEFINITIONS + Mmymailer, ... + ... + + LOCAL_RULESETS + Smyruleset + ... + + +#if _FFR_MILTER ++---------------------------+ +| ADDING NEW MAILER FILTERS | ++---------------------------+ + +Sendmail supports mail filters to filter incoming SMTP messages according +to the "Sendmail Mail Filter API" documentation. These filters can be +configured in your mc file using the two commands: + + MAIL_FILTER(`name', `equates') + INPUT_MAIL_FILTER(`name', `equates') + +The first command, MAIL_FILTER(), simply defines a filter with the given +name and equates. For example: + + MAIL_FILTER(`archiver', `S=local:/var/run/archivesock, F=R') + +This creates the equivalent sendmail.cf entry: + + Xarchive, S=local:/var/run/archivesock, F=R + +The INPUT_MAIL_FILTER() command performs the same actions as MAIL_FILTER +but also populates the m4 variable `confINPUT_MAIL_FILTERS' with the name +of the filter such that the filter will actually be called by sendmail. + +For example, the two commands: + + INPUT_MAIL_FILTER(`archive', `S=local:/var/run/archivesock, F=R') + INPUT_MAIL_FILTER(`spamcheck', `S=inet:2525@localhost, F=T') + +are equivalent to the three commands: + + MAIL_FILTER(`archive', `S=local:/var/run/archivesock, F=R') + MAIL_FILTER(`spamcheck', `S=inet:2525@localhost, F=T') + define(`confINPUT_MAIL_FILTERS', `archive, spamcheck') + +In general, INPUT_MAIL_FILTER() should be used unless you need to define +more filters than you want to use for `confINPUT_MAIL_FILTERS'. + +Note that setting `confINPUT_MAIL_FILTERS' after any INPUT_MAIL_FILTER() +commands will clear the list created by the prior INPUT_MAIL_FILTER() +commands. +#endif /* _FFR_MILTER */ + + ++-------------------------------+ +| NON-SMTP BASED CONFIGURATIONS | ++-------------------------------+ + +These configuration files are designed primarily for use by +SMTP-based sites. They may not be 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', `uucp-new: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 uucp-new (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. + +You may need to turn off the anti-spam rules in order to accept +UUCP mail with FEATURE(`promiscuous_relay') and +FEATURE(`accept_unresolvable_domains'). + + ++-----------+ +| 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 uucp-new:uuhost1 + .bitnet smtp:relay.bit.net + +This should normally be stored in /etc/mail/mailertable. The actual +database version of the mailertable is built using: + + makemap hash /etc/mail/mailertable < /etc/mail/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. Note: e-mail to "user@my.domain" does not match +any entry in the above table. You need to have something like: + + my.domain esmtp:host.my.domain + +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. (it is recommended 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 /etc/mail/userdb < /etc/mail/userdb.txt + +As a general rule, it is an extremely bad idea to using full names +as e-mail addresses, since they are not in any sense unique. For +example, the Unix software-development community has 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. + + ++--------------------------------+ +| 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, are 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, do so. + + ++--------------------------------+ +| 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: + [$?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.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/mail/local-host-names] Name + of file used to get the local + additions to the $=w (local host + names) class. +confCT_FILE Ft class [/etc/mail/trusted-users] Name of + file used to get the local + additions to the $=t (trusted + users) class. +confCR_FILE FR class [/etc/mail/relay-domains] Name of + file used to get the local additions + to the $=R (hosts allowed to relay) + 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'). +confTRUSTED_USER TrustedUser [no default] Trusted user for file + ownership and starting the daemon. + Not to be confused with + confTRUSTED_USERS (see above). +confSMTP_MAILER - [esmtp] The mailer name used when + SMTP connectivity is required. + One of "smtp", "smtp8", + "esmtp", or "dsmtp". +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 [infinite] 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 + [10] Checkpoint queue files every N + recipients. +confDELIVERY_MODE DeliveryMode [background] Default delivery mode. +confAUTO_REBUILD AutoRebuildAliases + [False] Automatically rebuild alias + file if needed. + There is a potential for a denial + of service attack if this is set. + This option is deprecated and will + be removed from a future version. +confERROR_MODE ErrorMode [print] Error message mode. +confERROR_MESSAGE ErrorHeader [undefined] Error message header/file. +confSAVE_FROM_LINES SaveFromLine Save extra leading From_ lines. +confTEMP_FILE_MODE TempFileMode [0600] Temporary file mode. +confMATCH_GECOS MatchGECOS [False] Match GECOS field. +confMAX_HOP MaxHopCount [25] Maximum hop count. +confIGNORE_DOTS* IgnoreDots [False; always False in -bs or -bd + mode] Ignore dot as terminator for + incoming messages? +confBIND_OPTS ResolverOptions [undefined] 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. +confHOST_STATUS_DIRECTORY HostStatusDirectory + [undefined] If set, host status is kept + on disk between sendmail runs in the + named directory tree. This need not be + a full pathname, in which case it is + interpreted relative to the queue + directory. +confSINGLE_THREAD_DELIVERY SingleThreadDelivery + [False] If this option and the + HostStatusDirectory option are both + set, single thread deliveries to other + hosts. That is, don't allow any two + sendmails on this host to connect + simultaneously to any other single + host. This can slow down delivery in + some cases, in particular since a + cached but otherwise idle connection + to a host will prevent other sendmails + from connecting to the other host. +confUSE_ERRORS_TO* UseErrorsTo [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 [True] Include sender in group + expansions. This option is + deprecated and will be removed from + a future version. +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. +confCLIENT_OPTIONS ClientPortOptions + [none] Options for outgoing SMTP client + connections. +confPRIVACY_FLAGS PrivacyOptions [authwarnings] Privacy flags. +confCOPY_ERRORS_TO PostmasterCopy [undefined] Address for additional + copies of all error messages. +confQUEUE_FACTOR QueueFactor [600000] Slope of queue-only function. +confDONT_PRUNE_ROUTES DontPruneRoutes [False] 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_CONNECT Timeout.connect [0] The timeout waiting for an initial + connect() to complete. This can only + shorten connection timeouts; the kernel + silently enforces an absolute maximum + (which varies depending on the system). +confTO_ICONNECT Timeout.iconnect + [undefined] Like Timeout.connect, but + applies only to the very first attempt + to connect to a host in a message. + This allows a single very fast pass + followed by more careful delivery + attempts in the future. +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 [5s] 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_CONTROL Timeout.control + [2m] The timeout for a complete + control socket transaction to complete. +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. +confTO_HOSTSTATUS Timeout.hoststatus + [30m] How long information about host + statuses will be maintained before it + is considered stale and the host should + be retried. This applies both within + a single queue run and to persistent + information (see below). +confTO_RESOLVER_RETRANS Timeout.resolver.retrans + [varies] Sets the resolver's + retransmition time interval (in + seconds). Sets both + Timeout.resolver.retrans.first and + Timeout.resolver.retrans.normal. +confTO_RESOLVER_RETRANS_FIRST Timeout.resolver.retrans.first + [varies] Sets the resolver's + retransmition time interval (in + seconds) for the first attempt to + deliver a message. +confTO_RESOLVER_RETRANS_NORMAL Timeout.resolver.retrans.normal + [varies] Sets the resolver's + retransmition time interval (in + seconds) for all resolver lookups + except the first delivery attempt. +confTO_RESOLVER_RETRY Timeout.resolver.retry + [varies] Sets the number of times + to retransmit a resolver query. + Sets both + Timeout.resolver.retry.first and + Timeout.resolver.retry.normal. +confTO_RESOLVER_RETRY_FIRST Timeout.resolver.retry.first + [varies] Sets the number of times + to retransmit a resolver query for + the first attempt to deliver a + message. +confTO_RESOLVER_RETRY_NORMAL Timeout.resolver.retry.normal + [varies] Sets the number of times + to retransmit a resolver query for + all resolver lookups except the + first delivery attempt. +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 + [undefined] User database + specification. +confFALLBACK_MX FallbackMXhost [undefined] Fallback MX host. +confTRY_NULL_MX_LIST TryNullMXList [False] If this host is the best MX + for a host and other arrangements + haven't been made, try connecting + to the host directly; normally this + would be a config error. +confQUEUE_LA QueueLA [varies] Load average at which + queue-only function kicks in. + Default values is (8 * numproc) + where numproc is the number of + processors online (if that can be + determined). +confREFUSE_LA RefuseLA [varies] Load average at which + incoming SMTP connections are + refused. Default values is (12 * + numproc) where numproc is the + number of processors online (if + that can be determined). +confMAX_ALIAS_RECURSION MaxAliasRecursion + [10] Maximum depth of alias recursion. +confMAX_DAEMON_CHILDREN MaxDaemonChildren + [undefined] The maximum number of + children the daemon will permit. After + this number, connections will be + rejected. If not set or <= 0, there is + no limit. +confMAX_HEADERS_LENGTH MaxHeadersLength + [undefined] Maximum length of the sum + of all headers. +confMAX_MIME_HEADER_LENGTH MaxMimeHeaderLength + [undefined] Maximum length of + certain MIME header field values. +confCONNECTION_RATE_THROTTLE ConnectionRateThrottle + [undefined] The maximum number of + connections permitted per second. + After this many connections are + accepted, further connections will be + delayed. If not set or <= 0, there is + no limit. +confWORK_RECIPIENT_FACTOR + RecipientFactor [30000] Cost of each recipient. +confSEPARATE_PROC ForkEachJob [False] Run all deliveries in a + separate process. +confWORK_CLASS_FACTOR ClassFactor [1800] Priority multiplier for class. +confWORK_TIME_FACTOR RetryFactor [90000] Cost of each delivery attempt. +confQUEUE_SORT_ORDER QueueSortOrder [Priority] Queue sort algorithm: + Priority, Host, Filename, or Time. +confMIN_QUEUE_AGE MinQueueAge [0] 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 + responsiveness without trying all + jobs in each run. +confDEF_CHAR_SET DefaultCharSet [unknown-8bit] When converting + unlabeled 8 bit input to MIME, the + character set to use by default. +confSERVICE_SWITCH_FILE ServiceSwitchFile + [/etc/mail/service.switch] The file + to use for the service switch on + systems that do not have a + system-defined switch. +confHOSTS_FILE HostsFile [/etc/hosts] The file to use when doing + "file" type access of hosts names. +confDIAL_DELAY DialDelay [0s] If a connection fails, wait this + long and try again. Zero means "don't + retry". This is to allow "dial on + demand" connections to have enough time + to complete a connection. +confNO_RCPT_ACTION NoRecipientAction + [none] 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:;''. +confSAFE_FILE_ENV SafeFileEnvironment + [undefined] If set, sendmail will do a + chroot() into this directory before + writing files. +confCOLON_OK_IN_ADDR ColonOkInAddr [True unless Configuration Level > 6] + 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 [0] If set, limit the maximum size of + any given queue run to this number of + entries. Essentially, this will stop + reading each 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 + [False] 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. +confSINGLE_LINE_FROM_HEADER SingleLineFromHeader + [False] From: lines that have + embedded newlines are unwrapped + onto one line. +confALLOW_BOGUS_HELO AllowBogusHELO [False] Allow HELO SMTP command that + does not include a host name. +confMUST_QUOTE_CHARS MustQuoteChars [.'] Characters to be quoted in a full + name phrase (@,;:\()[] are automatic). +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 [False] 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. +confUNSAFE_GROUP_WRITES UnsafeGroupWrites + [False] If set, group-writable + :include: and .forward files are + considered "unsafe", that is, programs + and files cannot be directly referenced + from such files. World-writable files + are always considered unsafe. +confCONNECT_ONLY_TO ConnectOnlyTo [undefined] override connection + address (for testing). +confCONTROL_SOCKET_NAME ControlSocketName + [undefined] Control socket for daemon + management. +confDOUBLE_BOUNCE_ADDRESS DoubleBounceAddress + [postmaster] If an error occurs when + sending an error message, send that + "double bounce" error message to this + address. +confDEAD_LETTER_DROP DeadLetterDrop [undefined] Filename to save bounce + messages which could not be returned + to the user or sent to postmaster. + If not set, the queue file will + be renamed. +confRRT_IMPLIES_DSN RrtImpliesDsn [False] Return-Receipt-To: header + implies DSN request. +confRUN_AS_USER RunAsUser [undefined] If set, become this user + when reading and delivering mail. + Causes all file reads (e.g., .forward + and :include: files) to be done as + this user. Also, all programs will + be run as this user, and all output + files will be written as this user. + Intended for use only on firewalls + where users do not have accounts. +confMAX_RCPTS_PER_MESSAGE MaxRecipientsPerMessage + [infinite] If set, allow no more than + the specified number of recipients in + an SMTP envelope. Further recipients + receive a 452 error code (i.e., they + are deferred for the next delivery + attempt). +confDONT_PROBE_INTERFACES DontProbeInterfaces + [False] If set, sendmail will _not_ + insert the names and addresses of any + local interfaces into the $=w class + (list of known "equivalent" addresses). + If you set this, you must also include + some support for these addresses (e.g., + in a mailertable entry) -- otherwise, + mail to addresses in this list will + bounce with a configuration error. +confPID_FILE PidFile [system dependent] Location of pid + file. +confPROCESS_TITLE_PREFIX ProcessTitlePrefix + [undefined] Prefix string for the + process title shown on 'ps' listings. +confDONT_BLAME_SENDMAIL DontBlameSendmail + [safe] Override sendmail's file + safety checks. This will definitely + compromise system security and should + not be used unless absolutely + necessary. +confREJECT_MSG - [550 Access denied] The message + given if the access database contains + REJECT in the value portion. +confDF_BUFFER_SIZE DataFileBufferSize + [4096] The maximum size of a + memory-buffered data (df) file + before a disk-based file is used. +confXF_BUFFER_SIZE XScriptFileBufferSize + [4096] The maximum size of a + memory-buffered transcript (xf) + file before a disk-based file is + used. +confAUTH_MECHANISMS AuthMechanisms [GSSAPI KERBEROS_V4 DIGEST-MD5 + CRAM-MD5] List of authentication + mechanisms for AUTH (separated by + spaces). The advertised list of + authentication mechanisms will be the + intersection of this list and the list + of available mechanisms as determined + by the CYRUS SASL library. +confDEF_AUTH_INFO DefaultAuthInfo [undefined] Filename that contains + authentication information for + outgoing connections. This file + must contain the user id, the + authorization id, the password + (plain text), and the realm to + use on separate lines and must be + readable by root (or the trusted + user) only. If no realm is + specified, $j is used. +confAUTH_OPTIONS AuthOptions [undefined] If this options is 'A' + then the AUTH= parameter for the + MAIL FROM command is only issued + when authentication succeeded. +confLDAP_DEFAULT_SPEC LDAPDefaultSpec [undefined] Default map + specification for LDAP maps. The + value should only contain LDAP + specific settings such as "-h host + -p port -d bindDN", etc. The + settings will be used for all LDAP + maps unless they are specified in + the individual map specification + ('K' command). + +See also the description of OSTYPE for some parameters that can be +tweaked (generally pathnames to mailers). + +DaemonPortOptions are a special case since multiple daemons can be +defined. This can be done via + + DAEMON_OPTIONS(`field1=value1,field2=value2,...') + +If DAEMON_OPTIONS is not used, then the default is + + DAEMON_OPTIONS(`Port=smtp, Name=MTA') + DAEMON_OPTIONS(`Port=587, Name=MSA, M=E') + +If you use one DAEMON_OPTIONS macro, it will alter the parameters +of the first of these. The second will still be defaulted; it +represents a "Message Submission Agent" (MSA) as defined by RFC +2476 (see below). To turn off the default definition for the MSA, +use FEATURE(`no_default_msa') (see also FEATURES). If you use +additional DAEMON_OPTIONS macros, they will add additional daemons. + +Example 1: To change the port for the SMTP listener, while +still using the MSA default, use + DAEMON_OPTIONS(`Port=925, Name=MTA') + +Example 2: To change the port for the MSA daemon, while still +using the default SMTP port, use + FEATURE(`no_default_msa') + DAEMON_OPTIONS(`Name=MTA') + DAEMON_OPTIONS(`Port=987, Name=MSA, M=E') + +Note that if the first of those DAEMON_OPTIONS lines were omitted, then +there would be no listener on the standard SMTP port. + +A "Message Submission Agent" still uses all of the same rulesets for +processing the message (and therefore still allows message rejection via +the check_* rulesets). In accordance with the RFC, the MSA will ensure +that all domains in the envelope are fully qualified if the message is +relayed to another MTA. It will also enforce the normal address syntax +rules and log error messages. Additionally, by using the M=a modifier +you can require authentication before messages are accepted by the MSA. +Finally, the M=E modifier shown above disables ETRN as required by RFC +2476. + + ++-----------+ +| 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? + +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 HylaFAX 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 you claim to be) + N + O + P + Q + R Relay (for unqualified names) + S Smart Host + T + U my UUCP name (if you 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 domains that are candidates for bestmx lookup + C + D + E addresses that should not seem to come from $M + F hosts this system forward for + G domains that should be looked up in genericstable + H + I + J + K + L addresses that should not be forwarded to $R + M domains that should be mapped to $M + N host/domains that should not be mapped to $M + O operators that indicate network operations (cannot be in local names) + P top level pseudo-domains: BITNET, DECNET, FAX, UUCP, etc. + Q + R domains this system is willing to relay (pass anti-spam filters) + 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 + [ the class containing only a left bracket + + +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 DNS based blacklists + 9 special local rulesets (1 and 2) + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:50 $ diff --git a/gnu/usr.sbin/sendmail/cf/cf/Build b/gnu/usr.sbin/sendmail/cf/cf/Build new file mode 100644 index 00000000000..0b3ac9144dc --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/Build @@ -0,0 +1,29 @@ +#!/bin/sh + +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.7 1999/03/02 02:37:12 peterh Exp $ +# + +# +# A quick-and-dirty script to create cf files. +# + +SMROOT=${SMROOT-../..} +BUILDTOOLS=${BUILDTOOLS-$SMROOT/devtools} + +M4=`sh $BUILDTOOLS/bin/find_m4.sh` +ret=$? +if [ $ret -ne 0 ] +then + exit $ret +fi +echo "Using M4=$M4" + +eval exec ${MAKE-make} M4=$M4 $* diff --git a/gnu/usr.sbin/sendmail/cf/cf/Makefile b/gnu/usr.sbin/sendmail/cf/cf/Makefile new file mode 100644 index 00000000000..15ffb28a214 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/Makefile @@ -0,0 +1,164 @@ +# +# Makefile for configuration files. +# +# $Sendmail: Makefile,v 8.40 2000/02/01 22:07:15 gshapiro Exp $ +# + +# +# Create configuration files using "m4 ../m4/cf.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 +CFDIR= .. +CHMOD= chmod +ROMODE= 444 +RM= rm -f + +.SUFFIXES: .mc .cf + +.mc.cf: + $(RM) $@ + $(M4) ${CFDIR}/m4/cf.m4 $*.mc > $@ || ( $(RM) $@ && exit 1 ) + $(CHMOD) $(ROMODE) $@ + +GENERIC=generic-bsd4.4.cf generic-hpux9.cf generic-hpux10.cf \ + generic-linux.cf \ + generic-osf1.cf generic-solaris2.cf \ + generic-sunos4.1.cf generic-ultrix4.cf +BERKELEY=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 +OTHER= knecht.cf +ALL= $(GENERIC) $(BERKELEY) $(OTHER) + +all: $(ALL) + +berkeley: $(BERKELEY) +generic: $(GENERIC) +other: $(OTHER) + +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}/domain/berkeley-only.m4 \ + ${CFDIR}/domain/generic.m4 \ + ${CFDIR}/feature/accept_unqualified_senders.m4 \ + ${CFDIR}/feature/accept_unresolvable_domains.m4 \ + ${CFDIR}/feature/access_db.m4 \ + ${CFDIR}/feature/allmasquerade.m4 \ + ${CFDIR}/feature/always_add_domain.m4 \ + ${CFDIR}/feature/bestmx_is_local.m4 \ + ${CFDIR}/feature/bitdomain.m4 \ + ${CFDIR}/feature/blacklist_recipients.m4 \ + ${CFDIR}/feature/dnsbl.m4 \ + ${CFDIR}/feature/domaintable.m4 \ + ${CFDIR}/feature/generics_entire_domain.m4 \ + ${CFDIR}/feature/genericstable.m4 \ + ${CFDIR}/feature/ldap_routing.m4 \ + ${CFDIR}/feature/limited_masquerade.m4 \ + ${CFDIR}/feature/local_lmtp.m4 \ + ${CFDIR}/feature/local_procmail.m4 \ + ${CFDIR}/feature/loose_relay_check.m4 \ + ${CFDIR}/feature/mailertable.m4 \ + ${CFDIR}/feature/masquerade_entire_domain.m4 \ + ${CFDIR}/feature/masquerade_envelope.m4 \ + ${CFDIR}/feature/no_default_msa.m4 \ + ${CFDIR}/feature/nocanonify.m4 \ + ${CFDIR}/feature/nodns.m4 \ + ${CFDIR}/feature/notsticky.m4 \ + ${CFDIR}/feature/nouucp.m4 \ + ${CFDIR}/feature/nullclient.m4 \ + ${CFDIR}/feature/promiscuous_relay.m4 \ + ${CFDIR}/feature/rbl.m4 \ + ${CFDIR}/feature/redirect.m4 \ + ${CFDIR}/feature/relay_based_on_MX.m4 \ + ${CFDIR}/feature/relay_entire_domain.m4 \ + ${CFDIR}/feature/relay_hosts_only.m4 \ + ${CFDIR}/feature/relay_local_from.m4 \ + ${CFDIR}/feature/relay_mail_from.m4 \ + ${CFDIR}/feature/smrsh.m4 \ + ${CFDIR}/feature/stickyhost.m4 \ + ${CFDIR}/feature/use_ct_file.m4 \ + ${CFDIR}/feature/use_cw_file.m4 \ + ${CFDIR}/feature/uucpdomain.m4 \ + ${CFDIR}/feature/virtuser_entire_domain.m4 \ + ${CFDIR}/feature/virtusertable.m4 \ + ${CFDIR}/hack/cssubdomain.m4 \ + ${CFDIR}/m4/cf.m4 \ + ${CFDIR}/m4/cfhead.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/phquery.m4 \ + ${CFDIR}/mailer/pop.m4 \ + ${CFDIR}/mailer/procmail.m4 \ + ${CFDIR}/mailer/qpage.m4 \ + ${CFDIR}/mailer/smtp.m4 \ + ${CFDIR}/mailer/usenet.m4 \ + ${CFDIR}/mailer/uucp.m4 \ + ${CFDIR}/ostype/aix2.m4 \ + ${CFDIR}/ostype/aix3.m4 \ + ${CFDIR}/ostype/aix4.m4 \ + ${CFDIR}/ostype/altos.m4 \ + ${CFDIR}/ostype/amdahl-uts.m4 \ + ${CFDIR}/ostype/aux.m4 \ + ${CFDIR}/ostype/bsd4.3.m4 \ + ${CFDIR}/ostype/bsd4.4.m4 \ + ${CFDIR}/ostype/bsdi.m4 \ + ${CFDIR}/ostype/bsdi1.0.m4 \ + ${CFDIR}/ostype/bsdi2.0.m4 \ + ${CFDIR}/ostype/dgux.m4 \ + ${CFDIR}/ostype/domainos.m4 \ + ${CFDIR}/ostype/dynix3.2.m4 \ + ${CFDIR}/ostype/gnu.m4 \ + ${CFDIR}/ostype/hpux10.m4 \ + ${CFDIR}/ostype/hpux11.m4 \ + ${CFDIR}/ostype/hpux9.m4 \ + ${CFDIR}/ostype/irix4.m4 \ + ${CFDIR}/ostype/irix5.m4 \ + ${CFDIR}/ostype/irix6.m4 \ + ${CFDIR}/ostype/isc4.1.m4 \ + ${CFDIR}/ostype/linux.m4 \ + ${CFDIR}/ostype/maxion.m4 \ + ${CFDIR}/ostype/mklinux.m4 \ + ${CFDIR}/ostype/nextstep.m4 \ + ${CFDIR}/ostype/openbsd.m4 \ + ${CFDIR}/ostype/osf1.m4 \ + ${CFDIR}/ostype/powerux.m4 \ + ${CFDIR}/ostype/ptx2.m4 \ + ${CFDIR}/ostype/qnx.m4 \ + ${CFDIR}/ostype/riscos4.5.m4 \ + ${CFDIR}/ostype/sco-uw-2.1.m4 \ + ${CFDIR}/ostype/sco3.2.m4 \ + ${CFDIR}/ostype/sinix.m4 \ + ${CFDIR}/ostype/solaris2.m4 \ + ${CFDIR}/ostype/solaris2.ml.m4 \ + ${CFDIR}/ostype/solaris2.pre5.m4 \ + ${CFDIR}/ostype/sunos3.5.m4 \ + ${CFDIR}/ostype/sunos4.1.m4 \ + ${CFDIR}/ostype/svr4.m4 \ + ${CFDIR}/ostype/ultrix4.m4 \ + ${CFDIR}/ostype/unixware7.m4 \ + ${CFDIR}/ostype/unknown.m4 \ + ${CFDIR}/ostype/uxpds.m4 + +$(ALL): $(M4FILES) +$(BERKELEY): $(M4FILES) +$(GENERIC): $(M4FILES) +$(OTHER): $(M4FILES) diff --git a/gnu/usr.sbin/sendmail/cf/cf/chez.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/chez.cs.mc new file mode 100644 index 00000000000..938d178c560 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/chez.cs.mc @@ -0,0 +1,34 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: chez.cs.mc,v 8.14 1999/02/07 07:25:59 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/clientproto.mc b/gnu/usr.sbin/sendmail/cf/cf/clientproto.mc new file mode 100644 index 00000000000..457a0aa769b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/clientproto.mc @@ -0,0 +1,34 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: clientproto.mc,v 8.15 1999/02/07 07:26:00 gshapiro Exp $') + +OSTYPE(unknown) +FEATURE(nullclient, mailhost.$m) diff --git a/gnu/usr.sbin/sendmail/cf/cf/cs-hpux10.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-hpux10.mc new file mode 100644 index 00000000000..dda668ada6c --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-hpux10.mc @@ -0,0 +1,31 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for HP-UX 9.x. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-hpux10.mc,v 8.13 1999/02/07 07:26:00 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/cs-hpux9.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-hpux9.mc new file mode 100644 index 00000000000..fb191417062 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-hpux9.mc @@ -0,0 +1,31 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for HP-UX 9.x. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-hpux9.mc,v 8.14 1999/02/07 07:26:00 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/cs-osf1.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-osf1.mc new file mode 100644 index 00000000000..acc1b9f843a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-osf1.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for OSF/1. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-osf1.mc,v 8.13 1999/02/07 07:26:00 gshapiro Exp $') +OSTYPE(osf1)dnl +DOMAIN(CS.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/cs-solaris2.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-solaris2.mc new file mode 100644 index 00000000000..74ec8f3c214 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-solaris2.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for Solaris 2.x. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-solaris2.mc,v 8.12 1999/02/07 07:26:00 gshapiro Exp $') +OSTYPE(solaris2)dnl +DOMAIN(CS.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc new file mode 100644 index 00000000000..885fd94ba89 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-sunos4.1.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for SunOS 4.1.x. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-sunos4.1.mc,v 8.13 1999/02/07 07:26:01 gshapiro Exp $') +OSTYPE(sunos4.1)dnl +DOMAIN(CS.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc b/gnu/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc new file mode 100644 index 00000000000..e5454f65d4f --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/cs-ultrix4.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for Ultrix 4.x. +# It applies only to 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)dnl +VERSIONID(`$Sendmail: cs-ultrix4.mc,v 8.13 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(ultrix4)dnl +DOMAIN(CS.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/cyrusproto.mc b/gnu/usr.sbin/sendmail/cf/cf/cyrusproto.mc new file mode 100644 index 00000000000..9c577c97f22 --- /dev/null +++ b/gnu/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 . +# +# This sample mc file is for a site that uses the Cyrus IMAP server +# exclusively for local mail. +# + +divert(0)dnl +VERSIONID(`$Sendmail: cyrusproto.mc,v 8.7 1999/09/07 14:57:10 ca Exp $') +define(`confBIND_OPTS',`-DNSRCH -DEFNAMES') +define(`confLOCAL_MAILER', `cyrus') +FEATURE(`nocanonify') +FEATURE(`always_add_domain') +MAILER(`local') +MAILER(`smtp') +MAILER(`cyrus') + +LOCAL_RULE_0 +Rbb + $+ < @ $=w . > $#cyrusbb $: $1 diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.cf new file mode 100644 index 00000000000..f42af2176b0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.cf @@ -0,0 +1,1178 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:25 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/var/log/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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/usr/libexec/mail.local, F=lsDFMAw5:/|@qPrmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-bsd4.4.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc new file mode 100644 index 00000000000..d534862807d --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-bsd4.4.mc @@ -0,0 +1,28 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-bsd4.4.mc,v 8.10 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(bsd4.4)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.cf new file mode 100644 index 00000000000..0a142a67067 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.cf @@ -0,0 +1,1179 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:27 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/usr/bin/rmail, F=lsDFMAw5:/|@qm9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=rmail -d $u +Mprog, P=/usr/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-hpux10.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.mc new file mode 100644 index 00000000000..073240f5ee5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux10.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-hpux10.mc,v 8.11 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(hpux10)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.cf new file mode 100644 index 00000000000..52cf3622aaf --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.cf @@ -0,0 +1,1179 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:26 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/usr/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/bin/rmail, F=lsDFMAw5:/|@qm9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=rmail -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-hpux9.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.mc new file mode 100644 index 00000000000..d9d4e34a5f5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-hpux9.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-hpux9.mc,v 8.11 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(hpux9)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-linux.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-linux.cf new file mode 100644 index 00000000000..cbd2191ede7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-linux.cf @@ -0,0 +1,1182 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:27 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=procmail -Y -a $h -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-linux.cf,v 1.1.1.1 2000/04/02 19:05:50 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-linux.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-linux.mc new file mode 100644 index 00000000000..374a06f174a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-linux.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a generic configuration file for Linux. +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-linux.mc,v 8.1 1999/09/24 22:48:05 gshapiro Exp $') +OSTYPE(linux)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-nextstep3.3.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-nextstep3.3.mc new file mode 100644 index 00000000000..f2c191cf0c6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-nextstep3.3.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a generic configuration file for NEXTSTEP 3.3 systems. +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-nextstep3.3.mc,v 8.10 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(nextstep)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.cf new file mode 100644 index 00000000000..2168e627875 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.cf @@ -0,0 +1,1179 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:27 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/usr/adm/sendmail/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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +O DefaultUser=daemon + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/bin/mail, F=lsDFMAw5:/|@qPrmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-osf1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.mc new file mode 100644 index 00000000000..98899745208 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-osf1.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-osf1.mc,v 8.11 1999/02/07 07:26:02 gshapiro Exp $') +OSTYPE(osf1)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.cf new file mode 100644 index 00000000000..38b8900203d --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.cf @@ -0,0 +1,1178 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:27 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/usr/lib/mail.local, F=lsDFMAw5:/|@qfSmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail.local -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-solaris2.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.mc new file mode 100644 index 00000000000..5477c9c89ec --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-solaris2.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-solaris2.mc,v 8.11 1999/02/07 07:26:03 gshapiro Exp $') +OSTYPE(solaris2)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.cf new file mode 100644 index 00000000000..ba3d4221c20 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.cf @@ -0,0 +1,1179 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:27 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/bin/mail, F=lsDFMAw5:/|@qPrmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-sunos4.1.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc new file mode 100644 index 00000000000..a2d240ebbc4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-sunos4.1.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-sunos4.1.mc,v 8.11 1999/02/07 07:26:03 gshapiro Exp $') +OSTYPE(sunos4.1)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.cf b/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.cf new file mode 100644 index 00000000000..44e971cc98f --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.cf @@ -0,0 +1,1179 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### SENDMAIL CONFIGURATION FILE +##### +##### built by gshapiro@horsey.gshapiro.net on Mon Mar 6 11:41:28 PST 2000 +##### in /usr/local/src/sendmail/devel/OpenSource/sendmail-8.10.0/cf/cf +##### using ../ as configuration include directory +##### +###################################################################### +###################################################################### + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + + +# level 9 config file format +V9/Berkeley + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +#O DontBlameSendmail=safe + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +#O LDAPDefaultSpec=-h localhost + +################## +# local info # +################## + +Cwlocalhost +# file containing names of hosts for which we receive email +Fw/etc/mail/local-host-names + +# my official domain name +# ... define this only if sendmail cannot automatically determine your domain +#Dj$w.Foo.COM + +CP. + +# "Smart" relay host (may be null) +DS + + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ! + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + + +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T + +# Hosts that will permit relaying ($=R) +FR-o /etc/mail/relay-domains + + +# who I send unqualified names to (null means deliver locally) +DR + +# who gets all local email traffic ($R has precedence for unqualified names) +DH + +# dequoting map +Kdequote dequote + +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +CEroot + +# who I masquerade as (null for no masquerading) (see also $=M) +DM + +# my name for error messages +DnMAILER-DAEMON + + +CPREDIRECT + +# Configuration version number +DZ8.10.0 + + +############### +# Options # +############### + +# strip message body to 7 bits on input? +O SevenBitInput=False + +# 8-bit data handling +O EightBitMode=pass8 + +# wait for alias file rebuild (default units: minutes) +O AliasWait=10 + +# location of alias file +O AliasFile=/etc/mail/aliases + +# minimum number of free blocks on filesystem +O MinFreeBlocks=100 + +# maximum message size +#O MaxMessageSize=1000000 + +# substitution for space (blank) characters +O BlankSub=. + +# avoid connecting to "expensive" mailers on initial submission? +O HoldExpensive=False + +# checkpoint queue runs after every N successful deliveries +#O CheckpointInterval=10 + +# default delivery mode +O DeliveryMode=background + +# automatically rebuild the alias database? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +#O AutoRebuildAliases=False + +# error message header/file +#O ErrorHeader=/etc/mail/error-header + +# error mode +#O ErrorMode=print + +# save Unix-style "From_" lines at top of header? +#O SaveFromLine=False + +# temporary file mode +O TempFileMode=0600 + +# match recipients against GECOS field? +#O MatchGECOS=False + +# maximum hop count +#O MaxHopCount=17 + +# location of help file +O HelpFile=/etc/mail/helpfile + +# ignore dots as terminators in incoming messages? +#O IgnoreDots=False + +# name resolver options +#O ResolverOptions=+AAONLY + +# deliver MIME-encapsulated error messages? +O SendMimeErrors=True + +# Forward file search path +O ForwardPath=$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward + +# open connection cache size +O ConnectionCacheSize=2 + +# open connection cache timeout +O ConnectionCacheTimeout=5m + +# persistent host status directory +#O HostStatusDirectory=.hoststat + +# single thread deliveries (requires HostStatusDirectory)? +#O SingleThreadDelivery=False + +# use Errors-To: header? +O UseErrorsTo=False + +# log level +O LogLevel=9 + +# send to me too, even in an alias expansion? +#O MeToo=True + +# verify RHS in newaliases? +O CheckAliases=False + +# default messages to old style headers if no special punctuation? +O OldStyleHeaders=True + +# SMTP daemon options +O DaemonPortOptions=Name=MTA +O DaemonPortOptions=Port=587, Name=MSA, M=E + +# SMTP client options +#O ClientPortOptions=Address=0.0.0.0 + +# privacy flags +O PrivacyOptions=authwarnings + +# who (if anyone) should get extra copies of error messages +#O PostmasterCopy=Postmaster + +# slope of queue-only function +#O QueueFactor=600000 + +# queue directory +O QueueDirectory=/var/spool/mqueue + +# timeouts (many of these) +#O Timeout.initial=5m +#O Timeout.connect=5m +#O Timeout.iconnect=5m +#O Timeout.helo=5m +#O Timeout.mail=10m +#O Timeout.rcpt=1h +#O Timeout.datainit=5m +#O Timeout.datablock=1h +#O Timeout.datafinal=1h +#O Timeout.rset=5m +#O Timeout.quit=2m +#O Timeout.misc=2m +#O Timeout.command=1h +#O Timeout.ident=5s +#O Timeout.fileopen=60s +#O Timeout.control=2m +O Timeout.queuereturn=5d +#O Timeout.queuereturn.normal=5d +#O Timeout.queuereturn.urgent=2d +#O Timeout.queuereturn.non-urgent=7d +O Timeout.queuewarn=4h +#O Timeout.queuewarn.normal=4h +#O Timeout.queuewarn.urgent=1h +#O Timeout.queuewarn.non-urgent=12h +#O Timeout.hoststatus=30m +#O Timeout.resolver.retrans=5s +#O Timeout.resolver.retrans.first=5s +#O Timeout.resolver.retrans.normal=5s +#O Timeout.resolver.retry=4 +#O Timeout.resolver.retry.first=4 +#O Timeout.resolver.retry.normal=4 + +# should we not prune routes in route-addr syntax addresses? +#O DontPruneRoutes=False + +# queue up everything before forking? +O SuperSafe=True + +# status file +O StatusFile=/etc/mail/statistics + +# 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 +#O TimeZoneSpec= + +# default UID (can be username or userid:groupid) +#O DefaultUser=mailnull + +# list of locations of user database file (null means no lookup) +#O UserDatabaseSpec=/etc/mail/userdb + +# fallback MX host +#O FallbackMXhost=fall.back.host.net + +# if we are the best MX host for a site, try it directly instead of config err +#O TryNullMXList=False + +# load average at which we just queue messages +#O QueueLA=8 + +# load average at which we refuse connections +#O RefuseLA=12 + +# maximum number of children we allow at one time +#O MaxDaemonChildren=12 + +# maximum number of new connections per second +#O ConnectionRateThrottle=3 + +# work recipient factor +#O RecipientFactor=30000 + +# deliver each queued job in a separate process? +#O ForkEachJob=False + +# work class factor +#O ClassFactor=1800 + +# work time factor +#O RetryFactor=90000 + +# shall we sort the queue by hostname first? +#O QueueSortOrder=priority + +# minimum time in queue before retry +#O MinQueueAge=30m + +# default character set +#O DefaultCharSet=iso-8859-1 + +# service switch file (ignored on Solaris, Ultrix, OSF/1, others) +#O ServiceSwitchFile=/etc/mail/service.switch + +# hosts file (normally /etc/hosts) +#O HostsFile=/etc/hosts + +# dialup line delay on connection failure +#O DialDelay=10s + +# action to take if there are no recipients in the message +#O NoRecipientAction=add-to-undisclosed + +# chrooted environment for writing to files +#O SafeFileEnvironment=/arch + +# are colons OK in addresses? +#O ColonOkInAddr=True + +# how many jobs can you process in the queue? +#O MaxQueueRunSize=10000 + +# shall I avoid expanding CNAMEs (violates protocols)? +#O DontExpandCnames=False + +# SMTP initial login message (old $e macro) +O SmtpGreetingMessage=$j Sendmail $v/$Z; $b + +# UNIX initial From header format (old $l macro) +O UnixFromLine=From $g $d + +# From: lines that have embedded newlines are unwrapped onto one line +#O SingleLineFromHeader=False + +# Allow HELO SMTP command that does not include a host name +#O AllowBogusHELO=False + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +#O MustQuoteChars=. + +# delimiter (operator) characters (old $o macro) +O OperatorChars=.:%@!^/[]+ + +# shall I avoid calling initgroups(3) because of high NIS costs? +#O DontInitGroups=False + +# are group-writable :include: and .forward files (un)trustworthy? +#O UnsafeGroupWrites=True + +# where do errors that occur when sending errors get sent? +#O DoubleBounceAddress=postmaster + +# where to save bounces if all else fails +#O DeadLetterDrop=/var/tmp/dead.letter + +# what user id do we assume for the majority of the processing? +#O RunAsUser=sendmail + +# maximum number of recipients per SMTP envelope +#O MaxRecipientsPerMessage=100 + +# shall we get local names from our installed interfaces? +#O DontProbeInterfaces=False + +# Return-Receipt-To: header implies DSN request +#O RrtImpliesDsn=False + +# override connection address (for testing) +#O ConnectOnlyTo=0.0.0.0 + +# Trusted user for file ownership and starting the daemon +#O TrustedUser=root + +# Control socket for daemon management +#O ControlSocketName=/var/spool/mqueue/.control + +# Maximum MIME header length to protect MUAs +#O MaxMimeHeaderLength=0/0 + +# Maximum length of the sum of all headers +O MaxHeadersLength=32768 + +# Maximum depth of alias recursion +#O MaxAliasRecursion=10 + +# location of pid file +#O PidFile=/var/run/sendmail.pid + +# Prefix string for the process title shown on 'ps' listings +#O ProcessTitlePrefix=prefix + +# Data file (df) memory-buffer file maximum size +#O DataFileBufferSize=4096 + +# Transcript file (xf) memory-buffer file maximum size +#O XscriptFileBufferSize=4096 + +# list of authentication mechanisms +#O AuthMechanisms=GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5 + +# default authentication information for outgoing connections +#O DefaultAuthInfo=/etc/mail/default-auth-info + +# try to authenticate? (Try when available/only when Authenticated) +#O AuthOptions=T + + + + + + +########################### +# Message precedences # +########################### + +Pfirst-class=0 +Pspecial-delivery=100 +Plist=-30 +Pbulk=-60 +Pjunk=-100 + +##################### +# Trusted users # +##################### + +# this is equivalent to setting class "t" +#Ft/etc/mail/trusted-users +Troot +Tdaemon +Tuucp + +######################### +# Format of headers # +######################### + +H?P?Return-Path: <$g> +HReceived: $?sfrom $s $.$?_($?s$|from $.$_) + $.$?{auth_type}(authenticated) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + for $u; $|; + $.$b +H?D?Resent-Date: $a +H?D?Date: $a +H?F?Resent-From: $?x$x <$g>$|$g$. +H?F?From: $?x$x <$g>$|$g$. +H?x?Full-Name: $x +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:include: $* <@> $: :include: $1 unmark :include:... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $1 < @ $2 > already canonical + +# do some sanity checking +R$* < @ $* : $* > $* $1 < @ $2 $3 > $4 nix colons in addrs + +# convert old-style addresses to a domain-based address +R$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains + +# if we have % signs, take the rightmost one +R$* % $* $1 @ $2 First make them all @s. +R$* @ $* @ $* $1 % $2 @ $3 Undo all but the last. +R$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + + + + + +# if really UUCP, handle it immediately + +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3 + +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4 +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +R$* < @ $=M > $* $: $1 < @ $2 . > $3 +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 canonical +R@ $* $@ @ $1 ... and exit + +# UUCP must always be presented in old form +R$+ @ $- . UUCP $2!$1 u@h.UUCP => h!u + +# delete duplicate local names +R$+ % $=w @ $=w $1 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#local $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 + +# handle numeric address spec +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#esmtp $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#esmtp $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#esmtp $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer + + +# short circuit local delivery so forwarded email works +R$=L < @ $=w . > $#local $: @ $1 special local names +R$+ < @ $=w . > $#local $: $1 regular local name + + +# resolve remotely connected UUCP links (if any) + +# resolve fake top level domains by forwarding to other hosts + + + +# pass names that still have a host to a smarthost (if defined) +R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name + +# deal with other remote names +R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 user@host.domain + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#local $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#relay $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#relay $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#local $@ $1@$2 $: $1 +R< > $+ $#local $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#local $@ $2@$3 $: $1 +R< $+ > $* $#local $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +R$=E < @ $=M . > $@ $1 < @ $2 . > +R$=E < @ $=w . > $@ $1 < @ $2 . > + +# handle domain-specific masquerading +R$* < @ $=M . > $* $: $1 < @ $2 . @ $M > $3 convert masqueraded doms +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 ### +################################################################### + +SMasqEnv=94 +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 + +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + + + + + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical + + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + + + +R $* < @ $* $=R > $: $1 < @ $2 $3 > + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck_relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + + + +###################################################################### +### check_mail -- check SMTP `MAIL FROM:' command argument +###################################################################### + +SLocal_check_mail +Scheck_mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +R<> $@ we MUST accept <> (RFC 1123) +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +R$* $: $&{daemon_flags} $| $1 +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R$* u $* $| <@> < $* > $: < $3 > +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP > +R<@> $* $: $1 no localhost as domain +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R $* $: $1 +R$* $: $>CanonAddr $1 canonify sender address and mark it +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 > + + +# handle case of no @domain on address +R $* $: $&{daemon_flags} $| $1 +R$* u $* $| $* $: $3 +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" + +###################################################################### +### check_rcpt -- check SMTP `RCPT TO:' command argument +###################################################################### + +SLocal_check_rcpt +Scheck_rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + + +R$* $: $>ParseRecipient $1 strip relayable hosts + + + + + +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +R$* $| $: $1 +R$* $| $={TrustAuthMech} $# RELAYAUTH +R$* $| $* $: $1 +# anything terminating locally is ok +R$+ < @ $=w > $@ RELAYTO +R$+ < @ $* $=R > $@ RELAYTO + + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +R $+ $@ RELAYTOLOCAL +R<$+> $* $: $2 + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + + +# check client name: first: did it resolve? +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +R$* $: $&{client_name} +R $@ RELAYFROM +R $=w $@ RELAYFROM +R $* $=R $@ RELAYFROM + +# anything else is bogus +R$* $#error $@ 5.7.1 $: "550 Relaying denied" + + +# is user trusted to authenticate as someone else? +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +SLocal_trust_auth + + +# +###################################################################### +###################################################################### +##### +##### MAILER DEFINITIONS +##### +###################################################################### +###################################################################### + + +################################################## +### Local and Program Mailer specification ### +################################################## + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 + +Mlocal, P=/bin/mail, F=lsDFMAw5:/|@qPrmn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=mail -d $u +Mprog, P=/bin/sh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/, + T=X-Unix/X-Unix/X-Unix, + A=sh -c $u + +##################################### +### SMTP Mailer specification ### +##################################### + +##### $Id: generic-ultrix4.cf,v 1.1.1.1 2000/04/02 19:05:51 millert Exp $ ##### + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# output fake domains as user%fake@relay + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mesmtp, P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Msmtp8, P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mdsmtp, P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990, + T=DNS/RFC822/SMTP, + A=IPC $h +Mrelay, P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040, + T=DNS/RFC822/SMTP, + A=IPC $h diff --git a/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc b/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc new file mode 100644 index 00000000000..9d8602452ab --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/generic-ultrix4.mc @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: generic-ultrix4.mc,v 8.11 1999/02/07 07:26:03 gshapiro Exp $') +OSTYPE(ultrix4)dnl +DOMAIN(generic)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/huginn.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/huginn.cs.mc new file mode 100644 index 00000000000..29322759c00 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/huginn.cs.mc @@ -0,0 +1,43 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: huginn.cs.mc,v 8.15 1999/02/07 07:26:03 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/knecht.mc b/gnu/usr.sbin/sendmail/cf/cf/knecht.mc new file mode 100644 index 00000000000..c3e686c6a24 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/knecht.mc @@ -0,0 +1,71 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is specific to Eric's home machine. +# + +divert(0)dnl +VERSIONID(`$Sendmail: knecht.mc,v 8.37 1999/11/19 05:18:12 gshapiro Exp $') +OSTYPE(bsdi)dnl +DOMAIN(generic)dnl +define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward+$h:$z/.forward')dnl +define(`confDEF_USER_ID', `mailnull')dnl +define(`confHOST_STATUS_DIRECTORY', `.hoststat')dnl +define(`confTO_ICONNECT', `10s')dnl +define(`confCOPY_ERRORS_TO', `Postmaster')dnl +define(`confTO_QUEUEWARN', `8h')dnl +define(`confTRUSTED_USERS', `www')dnl +define(`confPRIVACY_FLAGS', ``authwarnings,noexpn,novrfy'')dnl +FEATURE(virtusertable)dnl +FEATURE(access_db)dnl +FEATURE(local_lmtp)dnl +MODIFY_MAILER_FLAGS(`LOCAL', `+P')dnl +MAILER(local)dnl +MAILER(smtp)dnl + +LOCAL_CONFIG +# +# Regular expression to reject: +# * numeric-only localparts from aol.com and msn.com +# * localparts starting with a digit from juno.com +# +Kcheckaddress regex -a@MATCH + ^([0-9]+<@(aol|msn)\.com|[0-9][^<]*<@juno\.com)\.?> + +# +# Names that won't be allowed in a To: line (local-part and domains) +# +C{RejectToLocalparts} friend you +C{RejectToDomains} public.com + +LOCAL_RULESETS +HTo: $>CheckTo + +SCheckTo +R$={RejectToLocalparts}@$* $#error $: "553 Header error" +R$*@$={RejectToDomains} $#error $: "553 Header error" + +HMessage-Id: $>CheckMessageId + +SCheckMessageId +R< $+ @ $+ > $@ OK +R$* $#error $: "553 Header error" + +LOCAL_RULESETS +SLocal_check_mail +# check address against various regex checks +R$* $: $>Parse0 $>3 $1 +R$+ $: $(checkaddress $1 $) +R@MATCH $#error $: "553 Header error" diff --git a/gnu/usr.sbin/sendmail/cf/cf/mail.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/mail.cs.mc new file mode 100644 index 00000000000..9c4298f9ea6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/mail.cs.mc @@ -0,0 +1,44 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: mail.cs.mc,v 8.18 1999/02/07 07:26:04 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/mail.eecs.mc b/gnu/usr.sbin/sendmail/cf/cf/mail.eecs.mc new file mode 100644 index 00000000000..69bb12ee77a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/mail.eecs.mc @@ -0,0 +1,44 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: mail.eecs.mc,v 8.18 1999/02/07 07:26:04 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/mailspool.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/mailspool.cs.mc new file mode 100644 index 00000000000..5116e3eb5cf --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/mailspool.cs.mc @@ -0,0 +1,37 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: mailspool.cs.mc,v 8.12 1999/02/07 07:26:04 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/python.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/python.cs.mc new file mode 100644 index 00000000000..79699498886 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/python.cs.mc @@ -0,0 +1,42 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: python.cs.mc,v 8.12 1999/02/07 07:26:04 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/s2k-osf1.mc b/gnu/usr.sbin/sendmail/cf/cf/s2k-osf1.mc new file mode 100644 index 00000000000..045fc336aa5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/s2k-osf1.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for OSF/1. +# It applies only to 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: s2k-osf1.mc,v 8.13 1999/02/07 07:26:04 gshapiro Exp $') +OSTYPE(osf1)dnl +DOMAIN(S2K.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc b/gnu/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc new file mode 100644 index 00000000000..86e08a4bd15 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/s2k-ultrix4.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# This is a Berkeley-specific configuration file for Ultrix 4.x. +# It applies only to 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: s2k-ultrix4.mc,v 8.13 1999/02/07 07:26:04 gshapiro Exp $') +OSTYPE(ultrix4)dnl +DOMAIN(S2K.Berkeley.EDU)dnl +MAILER(local)dnl +MAILER(smtp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/tcpproto.mc b/gnu/usr.sbin/sendmail/cf/cf/tcpproto.mc new file mode 100644 index 00000000000..2564d5dd4e0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/tcpproto.mc @@ -0,0 +1,33 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: tcpproto.mc,v 8.13 1999/02/07 07:26:05 gshapiro Exp $') +OSTYPE(unknown) +FEATURE(nouucp) +MAILER(local) +MAILER(smtp) diff --git a/gnu/usr.sbin/sendmail/cf/cf/ucbarpa.mc b/gnu/usr.sbin/sendmail/cf/cf/ucbarpa.mc new file mode 100644 index 00000000000..68b2658a9c9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/ucbarpa.mc @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: ucbarpa.mc,v 8.12 1999/02/07 07:26:05 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/ucbvax.mc b/gnu/usr.sbin/sendmail/cf/cf/ucbvax.mc new file mode 100644 index 00000000000..349373e95e5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/ucbvax.mc @@ -0,0 +1,91 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: ucbvax.mc,v 8.14 1999/02/07 07:26:05 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/cf/uucpproto.mc b/gnu/usr.sbin/sendmail/cf/cf/uucpproto.mc new file mode 100644 index 00000000000..e2dd7a3b1db --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/uucpproto.mc @@ -0,0 +1,34 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: uucpproto.mc,v 8.15 1999/02/07 07:26:05 gshapiro Exp $') +OSTYPE(unknown) +FEATURE(promiscuous_relay)dnl +FEATURE(accept_unresolvable_domains)dnl +MAILER(local)dnl +MAILER(uucp)dnl diff --git a/gnu/usr.sbin/sendmail/cf/cf/vangogh.cs.mc b/gnu/usr.sbin/sendmail/cf/cf/vangogh.cs.mc new file mode 100644 index 00000000000..b5dcac9250f --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/cf/vangogh.cs.mc @@ -0,0 +1,33 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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. +# + +divert(0)dnl +VERSIONID(`$Sendmail: vangogh.cs.mc,v 8.13 1999/02/07 07:26:05 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4 b/gnu/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4 new file mode 100644 index 00000000000..e551c8ce800 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/Berkeley.EDU.m4 @@ -0,0 +1,24 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: Berkeley.EDU.m4,v 8.17 1999/02/07 07:26:06 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4 b/gnu/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4 new file mode 100644 index 00000000000..4c1715ac8f7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/CS.Berkeley.EDU.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: CS.Berkeley.EDU.m4,v 8.10 1999/02/07 07:26:06 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m4 b/gnu/usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m4 new file mode 100644 index 00000000000..3bd007e306c --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/EECS.Berkeley.EDU.m4 @@ -0,0 +1,17 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: EECS.Berkeley.EDU.m4,v 8.10 1999/02/07 07:26:06 gshapiro Exp $') +DOMAIN(Berkeley.EDU)dnl +MASQUERADE_AS(EECS.Berkeley.EDU)dnl diff --git a/gnu/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4 b/gnu/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4 new file mode 100644 index 00000000000..5d4afd1bff6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/S2K.Berkeley.EDU.m4 @@ -0,0 +1,17 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: S2K.Berkeley.EDU.m4,v 8.10 1999/02/07 07:26:06 gshapiro Exp $') +DOMAIN(CS.Berkeley.EDU)dnl +MASQUERADE_AS(postgres.Berkeley.EDU)dnl diff --git a/gnu/usr.sbin/sendmail/cf/domain/berkeley-only.m4 b/gnu/usr.sbin/sendmail/cf/domain/berkeley-only.m4 new file mode 100644 index 00000000000..4a980e7145e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/berkeley-only.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: unspecified-domain.m4,v 8.10 1999/02/07 07:26:07 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/domain/generic.m4 b/gnu/usr.sbin/sendmail/cf/domain/generic.m4 new file mode 100644 index 00000000000..f70e0ebce61 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/domain/generic.m4 @@ -0,0 +1,28 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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(`$Sendmail: generic.m4,v 8.15 1999/04/04 00:51:09 ca Exp $') +define(`confFORWARD_PATH', `$z/.forward.$w+$h:$z/.forward+$h:$z/.forward.$w:$z/.forward')dnl +define(`confMAX_HEADERS_LENGTH', `32768')dnl +FEATURE(`redirect')dnl +FEATURE(`use_cw_file')dnl +EXPOSED_USER(`root') diff --git a/gnu/usr.sbin/sendmail/cf/feature/accept_unqualified_senders.m4 b/gnu/usr.sbin/sendmail/cf/feature/accept_unqualified_senders.m4 new file mode 100644 index 00000000000..c08d2c30cf8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/accept_unqualified_senders.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: accept_unqualified_senders.m4,v 8.6 1999/02/07 07:26:07 gshapiro Exp $') +divert(-1) + +define(`_ACCEPT_UNQUALIFIED_SENDERS_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/accept_unresolvable_domains.m4 b/gnu/usr.sbin/sendmail/cf/feature/accept_unresolvable_domains.m4 new file mode 100644 index 00000000000..59b96d053d0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/accept_unresolvable_domains.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: accept_unresolvable_domains.m4,v 8.10 1999/02/07 07:26:07 gshapiro Exp $') +divert(-1) + +define(`_ACCEPT_UNRESOLVABLE_DOMAINS_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/access_db.m4 b/gnu/usr.sbin/sendmail/cf/feature/access_db.m4 new file mode 100644 index 00000000000..9e13f9c59cb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/access_db.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: access_db.m4,v 8.15 1999/07/22 17:55:34 gshapiro Exp $') +divert(-1) + +define(`_ACCESS_TABLE_', `') +define(`_TAG_DELIM_', `:')dnl should be in OperatorChars + +LOCAL_CONFIG +# Access list database (for spam stomping) +Kaccess ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`access', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/allmasquerade.m4 b/gnu/usr.sbin/sendmail/cf/feature/allmasquerade.m4 new file mode 100644 index 00000000000..731d7b5fc41 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/allmasquerade.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: allmasquerade.m4,v 8.11 1999/08/06 01:28:26 gshapiro Exp $') +divert(-1) + +define(`_ALL_MASQUERADE_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/always_add_domain.m4 b/gnu/usr.sbin/sendmail/cf/feature/always_add_domain.m4 new file mode 100644 index 00000000000..c7c6ebfcc42 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/always_add_domain.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: always_add_domain.m4,v 8.9 1999/02/07 07:26:08 gshapiro Exp $') +divert(-1) + +define(`_ALWAYS_ADD_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4 b/gnu/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4 new file mode 100644 index 00000000000..b8065ddccfb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/bestmx_is_local.m4 @@ -0,0 +1,51 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bestmx_is_local.m4,v 8.24 1999/10/18 21:50:24 ca Exp $') +divert(-1) + +define(_BESTMX_IS_LOCAL_, _ARG_) + +LOCAL_CONFIG +# turn on bestMX lookup table +Kbestmx bestmx +ifelse(defn(`_ARG_'), `', `dnl',` +# limit bestmx to these domains +CB`'_ARG_') + +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. If you use the limited bestmx +# by passing in a set of possible domains it will improve things. + +ifelse(defn(`_ARG_'), `', `dnl +# unlimited bestmx +R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3', +`dnl +# limit bestmx to $=B +R$* < @ $* $=B . > $* $: $1 < @ $2 $3 . @@ $(bestmx $2 $3 . $) > $4') +R$* $=O $* < @ $* @@ $=w . > $* $@ $>Recurse $1 $2 $3 +R< @ $* @@ $=w . > : $* $@ $>Recurse $3 +dnl we cannot use _LOCAL_ here since it is defined too late +R$* < @ $* @@ $=w . > $* $@ $>CanonLocal < $1 > +R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4 diff --git a/gnu/usr.sbin/sendmail/cf/feature/bitdomain.m4 b/gnu/usr.sbin/sendmail/cf/feature/bitdomain.m4 new file mode 100644 index 00000000000..d6423dd5470 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/bitdomain.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bitdomain.m4,v 8.23 1999/07/22 17:55:34 gshapiro Exp $') +divert(-1) + +define(`_BITDOMAIN_TABLE_', `') + +LOCAL_CONFIG +# BITNET mapping table +Kbitdomain ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`bitdomain', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/blacklist_recipients.m4 b/gnu/usr.sbin/sendmail/cf/feature/blacklist_recipients.m4 new file mode 100644 index 00000000000..6f828a7e342 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/blacklist_recipients.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: blacklist_recipients.m4,v 8.13 1999/04/02 02:25:13 gshapiro Exp $') +divert(-1) + +ifdef(`_ACCESS_TABLE_', + `define(`_BLACKLIST_RCPT_', 1)', + `errprint(`*** ERROR: FEATURE(blacklist_recipients) requires FEATURE(access_db) +')') diff --git a/gnu/usr.sbin/sendmail/cf/feature/delay_checks.m4 b/gnu/usr.sbin/sendmail/cf/feature/delay_checks.m4 new file mode 100644 index 00000000000..be92bcd6665 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/delay_checks.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: delay_checks.m4,v 8.7 2000/02/26 01:32:02 gshapiro Exp $') +divert(-1) + +define(`_DELAY_CHECKS_', 1) +ifelse(defn(`_ARG_'), `', `', + lower(substr(_ARG_,0,1)), `f', `define(`_SPAM_FRIEND_', 1) define(`_SPAM_FH_', 1)', + lower(substr(_ARG_,0,1)), `h', `define(`_SPAM_HATER_', 1) define(`_SPAM_FH_', 1)', + `errprint(`*** ERROR: illegal argument _ARG_ for FEATURE(delay_checks) +') + ') diff --git a/gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 b/gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 new file mode 100644 index 00000000000..5da04020089 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +ifdef(`_DNSBL_R_',`dnl',`dnl +VERSIONID(`$Sendmail: dnsbl.m4,v 8.18 1999/08/03 04:30:56 gshapiro Exp $')') +divert(-1) +define(`_DNSBL_SRV_', `ifelse(len(X`'_ARG_),`1',`rbl.maps.vix.com',_ARG_)')dnl +define(`_DNSBL_MSG_', `ifelse(len(X`'_ARG2_),`1',`"550 Mail from " $`'&{client_addr} " refused by blackhole site '_DNSBL_SRV_`"',`_ARG2_')')dnl +divert(8) +# DNS based IP address spam list _DNSBL_SRV_ +R$* $: $&{client_addr} +R::ffff:$-.$-.$-.$- $: $(host $4.$3.$2.$1._DNSBL_SRV_. $: OK $) +R$-.$-.$-.$- $: $(host $4.$3.$2.$1._DNSBL_SRV_. $: OK $) +ROK $: OKSOFAR +R$+ $#error $@ 5.7.1 $: _DNSBL_MSG_ +divert(-1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/domaintable.m4 b/gnu/usr.sbin/sendmail/cf/feature/domaintable.m4 new file mode 100644 index 00000000000..5542e315f29 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/domaintable.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: domaintable.m4,v 8.17 1999/07/22 17:55:35 gshapiro Exp $') +divert(-1) + +define(`_DOMAIN_TABLE_', `') + +LOCAL_CONFIG +# Domain table (adding domains) +Kdomaintable ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`domaintable', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/generics_entire_domain.m4 b/gnu/usr.sbin/sendmail/cf/feature/generics_entire_domain.m4 new file mode 100644 index 00000000000..32a07d32679 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/generics_entire_domain.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: generics_entire_domain.m4,v 8.1 1999/03/16 00:43:05 ca Exp $') +divert(-1) + +define(`_GENERICS_ENTIRE_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/genericstable.m4 b/gnu/usr.sbin/sendmail/cf/feature/genericstable.m4 new file mode 100644 index 00000000000..f03a7af8530 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/genericstable.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: genericstable.m4,v 8.16 1999/07/22 17:55:35 gshapiro Exp $') +divert(-1) + +define(`_GENERICS_TABLE_', `') + +LOCAL_CONFIG +# Generics table (mapping outgoing addresses) +Kgenerics ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`genericstable', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 b/gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 new file mode 100644 index 00000000000..89527e2f999 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 @@ -0,0 +1,34 @@ +divert(-1) +# +# Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: ldap_routing.m4,v 8.5 2000/02/26 01:32:03 gshapiro Exp $') +divert(-1) + +# Check first two arguments. If they aren't set, may need to warn in proto.m4 +ifelse(len(X`'_ARG1_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')') +ifelse(len(X`'_ARG2_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')') + +# Check for third argument to indicate how to deal with non-existant +# LDAP records +ifelse(len(X`'_ARG3_), `1', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')', + _ARG3_, `passthru', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')', + `define(`_LDAP_ROUTING_', `_MUST_EXIST_')') + +LOCAL_CONFIG +# LDAP routing maps +Kldap_mailhost ifelse(len(X`'_ARG1_), `1', + `ldap -1 -v mailHost -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', + `_ARG1_') + +Kldap_mailroutingaddress ifelse(len(X`'_ARG2_), `1', + `ldap -1 -v mailRoutingAddress -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', + `_ARG2_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/limited_masquerade.m4 b/gnu/usr.sbin/sendmail/cf/feature/limited_masquerade.m4 new file mode 100644 index 00000000000..c8219edd873 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/limited_masquerade.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: limited_masquerade.m4,v 8.9 1999/02/07 07:26:09 gshapiro Exp $') +divert(-1) + +define(`_LIMITED_MASQUERADE_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/local_lmtp.m4 b/gnu/usr.sbin/sendmail/cf/feature/local_lmtp.m4 new file mode 100644 index 00000000000..f680970fd3b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/local_lmtp.m4 @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: local_lmtp.m4,v 8.15 1999/11/18 05:06:22 ca Exp $') +divert(-1) + +ifdef(`_MAILER_local_', + `errprint(`*** FEATURE(local_lmtp) must occur before MAILER(local) +')')dnl + +define(`LOCAL_MAILER_PATH', + ifelse(defn(`_ARG_'), `', + ifdef(`confEBINDIR', confEBINDIR, `/usr/libexec')`/mail.local', + _ARG_)) +define(`LOCAL_MAILER_FLAGS', `PSXfmnz9') +define(`LOCAL_MAILER_ARGS', `mail.local -l') +define(`LOCAL_MAILER_DSN_DIAGNOSTIC_CODE', `SMTP') diff --git a/gnu/usr.sbin/sendmail/cf/feature/local_procmail.m4 b/gnu/usr.sbin/sendmail/cf/feature/local_procmail.m4 new file mode 100644 index 00000000000..3f57c454125 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/local_procmail.m4 @@ -0,0 +1,32 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1994 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: local_procmail.m4,v 8.21 1999/11/18 05:06:23 ca Exp $') +divert(-1) + +ifdef(`_MAILER_local_', + `errprint(`*** FEATURE(local_procmail) must occur before MAILER(local) +')')dnl + +define(`LOCAL_MAILER_PATH', + ifelse(defn(`_ARG_'), `', + ifdef(`PROCMAIL_MAILER_PATH', + PROCMAIL_MAILER_PATH, + `/usr/local/bin/procmail'), + _ARG_)) +define(`LOCAL_MAILER_ARGS', + ifelse(len(X`'_ARG2_), `1', `procmail -Y -a $h -d $u', _ARG2_)) +define(`LOCAL_MAILER_FLAGS', + ifelse(len(X`'_ARG3_), `1', `SPfhn9', _ARG3_)) diff --git a/gnu/usr.sbin/sendmail/cf/feature/loose_relay_check.m4 b/gnu/usr.sbin/sendmail/cf/feature/loose_relay_check.m4 new file mode 100644 index 00000000000..0e7d2b2787e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/loose_relay_check.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: loose_relay_check.m4,v 8.6 1999/02/07 07:26:10 gshapiro Exp $') +divert(-1) + +define(`_LOOSE_RELAY_CHECK_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/mailertable.m4 b/gnu/usr.sbin/sendmail/cf/feature/mailertable.m4 new file mode 100644 index 00000000000..ad6088e0d66 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/mailertable.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: mailertable.m4,v 8.18 1999/07/22 17:55:35 gshapiro Exp $') +divert(-1) + +define(`_MAILER_TABLE_', `') + +LOCAL_CONFIG +# Mailer table (overriding domains) +Kmailertable ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`mailertable', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/masquerade_entire_domain.m4 b/gnu/usr.sbin/sendmail/cf/feature/masquerade_entire_domain.m4 new file mode 100644 index 00000000000..cef2e52a09c --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/masquerade_entire_domain.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: masquerade_entire_domain.m4,v 8.9 1999/02/07 07:26:10 gshapiro Exp $') +divert(-1) + +define(`_MASQUERADE_ENTIRE_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4 b/gnu/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4 new file mode 100644 index 00000000000..93f0b915fe7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/masquerade_envelope.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: masquerade_envelope.m4,v 8.9 1999/02/07 07:26:10 gshapiro Exp $') +divert(-1) + +define(`_MASQUERADE_ENVELOPE_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/no_default_msa.m4 b/gnu/usr.sbin/sendmail/cf/feature/no_default_msa.m4 new file mode 100644 index 00000000000..eb5c033edd9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/no_default_msa.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1999, 2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: no_default_msa.m4,v 8.1 2000/02/01 15:56:30 ca Exp $') +divert(-1) + +define(`_NO_MSA_', `1') diff --git a/gnu/usr.sbin/sendmail/cf/feature/nocanonify.m4 b/gnu/usr.sbin/sendmail/cf/feature/nocanonify.m4 new file mode 100644 index 00000000000..0424ccc75f8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/nocanonify.m4 @@ -0,0 +1,24 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: nocanonify.m4,v 8.12 1999/08/28 00:42:01 ca Exp $') +divert(-1) + +define(`_NO_CANONIFY_', 1) +ifelse(defn(`_ARG_'), `', `', + strcasecmp(defn(`_ARG_'), `canonify_hosts'), `1', + `define(`_CANONIFY_HOSTS_', 1)', + `errprint(`*** ERROR: unknown parameter '"defn(`_ARG_')"` for FEATURE(`nocanonify') +')') diff --git a/gnu/usr.sbin/sendmail/cf/feature/nodns.m4 b/gnu/usr.sbin/sendmail/cf/feature/nodns.m4 new file mode 100644 index 00000000000..e3aab7d9d89 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/nodns.m4 @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: nodns.m4,v 8.14 1999/07/22 17:55:35 gshapiro Exp $') +divert(-1) + +undefine(`confBIND_OPTS')dnl +errprint(`FEATURE(nodns) is no-op. +Use ServiceSwitchFile ('ifdef(`confSERVICE_SWITCH_FILE',confSERVICE_SWITCH_FILE,MAIL_SETTINGS_DIR`service.switch')`) if your OS does not provide its own instead. +') diff --git a/gnu/usr.sbin/sendmail/cf/feature/notsticky.m4 b/gnu/usr.sbin/sendmail/cf/feature/notsticky.m4 new file mode 100644 index 00000000000..edee02d5c0b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/notsticky.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: notsticky.m4,v 8.11 1999/02/07 07:26:11 gshapiro Exp $') +# +# This is now the default. Use ``FEATURE(stickyhost)'' if you want +# the old default behaviour. +# +divert(-1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/nouucp.m4 b/gnu/usr.sbin/sendmail/cf/feature/nouucp.m4 new file mode 100644 index 00000000000..40dc7ef9659 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/nouucp.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: nouucp.m4,v 8.13 1999/11/24 18:37:07 ca Exp $') +divert(-1) + +ifelse(defn(`_ARG_'), `', + `errprint(`*** ERROR: missing argument for FEATURE(nouucp): + use `reject' or `nospecial'. See cf/README. +')define(`_NO_UUCP_', `e')', + substr(_ARG_,0,1), `r', `define(`_NO_UUCP_', `r')', + substr(_ARG_,0,1), `n', `define(`_NO_UUCP_', `n')', + `errprint(`*** ERROR: illegal argument _ARG_ for FEATURE(nouucp) +') + ') diff --git a/gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 b/gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 new file mode 100644 index 00000000000..b59385a4488 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 @@ -0,0 +1,36 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +ifelse(defn(`_ARG_'), `', `errprint(`Feature "nullclient" requires argument')', + `define(`_NULL_CLIENT_', _ARG_)') + +# +# 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. +# + +divert(0) +VERSIONID(`$Sendmail: nullclient.m4,v 8.21 1999/08/06 01:48:57 gshapiro Exp $') +divert(-1) + +undefine(`ALIAS_FILE') +define(`MAIL_HUB', _NULL_CLIENT_) +define(`SMART_HOST', _NULL_CLIENT_) +define(`confFORWARD_PATH', `') +MASQUERADE_AS(_NULL_CLIENT_) +FEATURE(`allmasquerade') +FEATURE(`masquerade_envelope') +MAILER(`local') +MAILER(`smtp') diff --git a/gnu/usr.sbin/sendmail/cf/feature/promiscuous_relay.m4 b/gnu/usr.sbin/sendmail/cf/feature/promiscuous_relay.m4 new file mode 100644 index 00000000000..8aac82e1965 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/promiscuous_relay.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: promiscuous_relay.m4,v 8.10 1999/02/07 07:26:11 gshapiro Exp $') +divert(-1) + +define(`_PROMISCUOUS_RELAY_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/rbl.m4 b/gnu/usr.sbin/sendmail/cf/feature/rbl.m4 new file mode 100644 index 00000000000..e169a778d37 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/rbl.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998 Sendmail, Inc. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: rbl.m4,v 8.17 1999/04/04 00:51:12 ca Exp $') +divert(-1) + +define(`_RBL_', ifelse(defn(`_ARG_'), `', `rbl.maps.vix.com', `_ARG_'))dnl +ifelse(defn(`_ARG_'), `', `', ` +errprint(`Warning: FEATURE(`rbl') is deprecated, use FEATURE(`dnsbl') instead +')')dnl diff --git a/gnu/usr.sbin/sendmail/cf/feature/redirect.m4 b/gnu/usr.sbin/sendmail/cf/feature/redirect.m4 new file mode 100644 index 00000000000..1018a67253b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/redirect.m4 @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: redirect.m4,v 8.15 1999/08/06 01:47:36 gshapiro Exp $') +divert(-1) + +LOCAL_RULE_0 +# addresses sent to foo@host.REDIRECT will give a 551 error code +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT . > < ${opMode} > +R$* < @ $+ .REDIRECT. > $: $1 < @ $2 . REDIRECT. > +R$* < @ $+ .REDIRECT. > < $- > $#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2> + +LOCAL_CONFIG +CPREDIRECT diff --git a/gnu/usr.sbin/sendmail/cf/feature/relay_based_on_MX.m4 b/gnu/usr.sbin/sendmail/cf/feature/relay_based_on_MX.m4 new file mode 100644 index 00000000000..bf4ce47b41e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/relay_based_on_MX.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: relay_based_on_MX.m4,v 8.11 1999/04/02 02:25:13 gshapiro Exp $') +divert(-1) + +define(`_RELAY_MX_SERVED_', 1) + +LOCAL_CONFIG +# MX map (to allow relaying to hosts that we MX for) +Kmxserved bestmx -z: -T + diff --git a/gnu/usr.sbin/sendmail/cf/feature/relay_entire_domain.m4 b/gnu/usr.sbin/sendmail/cf/feature/relay_entire_domain.m4 new file mode 100644 index 00000000000..6ae8cf1efea --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/relay_entire_domain.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: relay_entire_domain.m4,v 8.10 1999/02/07 07:26:12 gshapiro Exp $') +divert(-1) + +define(`_RELAY_ENTIRE_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/relay_hosts_only.m4 b/gnu/usr.sbin/sendmail/cf/feature/relay_hosts_only.m4 new file mode 100644 index 00000000000..555840b73e9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/relay_hosts_only.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: relay_hosts_only.m4,v 8.10 1999/02/07 07:26:12 gshapiro Exp $') +divert(-1) + +define(`_RELAY_HOSTS_ONLY_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/relay_local_from.m4 b/gnu/usr.sbin/sendmail/cf/feature/relay_local_from.m4 new file mode 100644 index 00000000000..8be79252014 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/relay_local_from.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: relay_local_from.m4,v 8.5 1999/02/07 07:26:12 gshapiro Exp $') +divert(-1) + +define(`_RELAY_LOCAL_FROM_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/relay_mail_from.m4 b/gnu/usr.sbin/sendmail/cf/feature/relay_mail_from.m4 new file mode 100644 index 00000000000..e65890c1c44 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/relay_mail_from.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: relay_mail_from.m4,v 8.2 1999/04/02 02:25:13 gshapiro Exp $') +divert(-1) + +ifdef(`_ACCESS_TABLE_', + `define(`_RELAY_DB_FROM_', 1) + ifelse(_ARG_,`domain',`define(`_RELAY_DB_FROM_DOMAIN_', 1)')', + `errprint(`*** ERROR: FEATURE(relay_mail_from) requires FEATURE(access_db) +')') diff --git a/gnu/usr.sbin/sendmail/cf/feature/smrsh.m4 b/gnu/usr.sbin/sendmail/cf/feature/smrsh.m4 new file mode 100644 index 00000000000..03b322a1bbb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/smrsh.m4 @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: smrsh.m4,v 8.14 1999/11/18 05:06:23 ca Exp $') +divert(-1) + +ifdef(`_MAILER_local_', + `errprint(`*** FEATURE(smrsh) must occur before MAILER(local) +')')dnl +define(`LOCAL_SHELL_PATH', + ifelse(defn(`_ARG_'), `', + ifdef(`confEBINDIR', confEBINDIR, `/usr/libexec')`/smrsh', + _ARG_)) +_DEFIFNOT(`LOCAL_SHELL_ARGS', `smrsh -c $u') diff --git a/gnu/usr.sbin/sendmail/cf/feature/stickyhost.m4 b/gnu/usr.sbin/sendmail/cf/feature/stickyhost.m4 new file mode 100644 index 00000000000..753ed28e3fb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/stickyhost.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: stickyhost.m4,v 8.9 1999/02/07 07:26:13 gshapiro Exp $') +divert(-1) + +define(`_STICKY_LOCAL_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/use_ct_file.m4 b/gnu/usr.sbin/sendmail/cf/feature/use_ct_file.m4 new file mode 100644 index 00000000000..db6c308e6ab --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/use_ct_file.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: use_ct_file.m4,v 8.9 1999/02/07 07:26:13 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/feature/use_cw_file.m4 b/gnu/usr.sbin/sendmail/cf/feature/use_cw_file.m4 new file mode 100644 index 00000000000..bad558f352e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/use_cw_file.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: use_cw_file.m4,v 8.9 1999/02/07 07:26:13 gshapiro Exp $') +divert(-1) + +# if defined, the sendmail.cf will read the /etc/sendmail.cw file +# to find alternate names for this host. Typically only used when +# several hosts have been squashed into one another at high speed. + +define(`USE_CW_FILE', `') + +divert(0) diff --git a/gnu/usr.sbin/sendmail/cf/feature/uucpdomain.m4 b/gnu/usr.sbin/sendmail/cf/feature/uucpdomain.m4 new file mode 100644 index 00000000000..0f7f78b99f2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/uucpdomain.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: uucpdomain.m4,v 8.22 1999/07/22 17:55:35 gshapiro Exp $') +divert(-1) + +define(`_UUDOMAIN_TABLE_', `') + +LOCAL_CONFIG +# UUCP domain table +Kuudomain ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`uudomain', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/feature/virtuser_entire_domain.m4 b/gnu/usr.sbin/sendmail/cf/feature/virtuser_entire_domain.m4 new file mode 100644 index 00000000000..163eff72eda --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/virtuser_entire_domain.m4 @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: virtuser_entire_domain.m4,v 8.2 1999/03/16 00:43:05 ca Exp $') +divert(-1) + +define(`_VIRTUSER_ENTIRE_DOMAIN_', 1) diff --git a/gnu/usr.sbin/sendmail/cf/feature/virtusertable.m4 b/gnu/usr.sbin/sendmail/cf/feature/virtusertable.m4 new file mode 100644 index 00000000000..1210ee98285 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/feature/virtusertable.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: virtusertable.m4,v 8.16 1999/07/22 17:55:36 gshapiro Exp $') +divert(-1) + +define(`_VIRTUSER_TABLE_', `') + +LOCAL_CONFIG +# Virtual user table (maps incoming users) +Kvirtuser ifelse(defn(`_ARG_'), `', + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`virtusertable', + `_ARG_') diff --git a/gnu/usr.sbin/sendmail/cf/hack/cssubdomain.m4 b/gnu/usr.sbin/sendmail/cf/hack/cssubdomain.m4 new file mode 100644 index 00000000000..9a67d18c8f8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/hack/cssubdomain.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) +VERSIONID(`$Sendmail: cssubdomain.m4,v 8.9 1999/02/07 07:26:14 gshapiro Exp $') + +divert(2) +# find possible (old & new) versions of our name via short circuit hack +# (this code should exist ONLY during the transition from .Berkeley.EDU +# names to .CS.Berkeley.EDU names -- probably not more than a few months) +R$* < @ $=w .CS.Berkeley.EDU > $* $: $1 < @ $j > $3 +R$* < @ $=w .Berkeley.EDU> $* $: $1 < @ $j > $3 +divert(0) diff --git a/gnu/usr.sbin/sendmail/cf/m4/cf.m4 b/gnu/usr.sbin/sendmail/cf/m4/cf.m4 new file mode 100644 index 00000000000..dd8ba766489 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/m4/cf.m4 @@ -0,0 +1,29 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# +# 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(`$Sendmail: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp $')') diff --git a/gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 b/gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 new file mode 100644 index 00000000000..239a26fc9d6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 @@ -0,0 +1,248 @@ +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +###################################################################### +###################################################################### +##### +##### 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`'') +## helpful functions +define(`lower', `translit(`$1', `ABCDEFGHIJKLMNOPQRSTUVWXYZ', `abcdefghijklmnopqrstuvwx')') +define(`strcasecmp', `ifelse(lower($1), lower($2), `1', `0')') +## new FEATUREs +define(`_DNSBL_R_',`') +## access to further arguments in FEATURE/HACK +define(`_ACC_ARG_1_',`$1') +define(`_ACC_ARG_2_',`$2') +define(`_ACC_ARG_3_',`$3') +define(`_ACC_ARG_4_',`$4') +define(`_ACC_ARG_5_',`$5') +define(`_ACC_ARG_6_',`$6') +define(`_ACC_ARG_7_',`$7') +define(`_ACC_ARG_8_',`$8') +define(`_ACC_ARG_9_',`$9') +define(`_ARG1_',`_ACC_ARG_1_(_ARGS_)') +define(`_ARG2_',`_ACC_ARG_2_(_ARGS_)') +define(`_ARG3_',`_ACC_ARG_3_(_ARGS_)') +define(`_ARG4_',`_ACC_ARG_4_(_ARGS_)') +define(`_ARG5_',`_ACC_ARG_5_(_ARGS_)') +define(`_ARG6_',`_ACC_ARG_6_(_ARGS_)') +define(`_ARG7_',`_ACC_ARG_7_(_ARGS_)') +define(`_ARG8_',`_ACC_ARG_8_(_ARGS_)') +define(`_ARG9_',`_ACC_ARG_9_(_ARGS_)') +dnl define if not yet defined: if `$1' is not defined it will be `$2' +define(`_DEFIFNOT',`ifdef(`$1',`',`define(`$1',`$2')')') +dnl ---------------------------------------- +dnl add a char $2 to a string $1 if it is not there +define(`_ADDCHAR_',`define(`_I_',`eval(index(`$1',`$2') >= 0)')`'ifelse(_I_,`1',`$1',`$1$2')') +dnl ---- +dnl delete a char $2 from a string $1 if it is there +define(`_DELCHAR_',`define(`_IDX_',`index(`$1',`$2')')`'define(`_I_',`eval(_IDX_ >= 0)')`'ifelse(_I_,`1',`substr(`$1',0,_IDX_)`'substr(`$1',eval(_IDX_+1))',`$1')') +dnl ---- +dnl apply a macro to a whole string by recursion (one char at a time) +dnl $1: macro +dnl $2: first argument to macro +dnl $3: list that is split up into characters +define(`_AP_',`ifelse(`$3',`',`$2',`_AP_(`$1',$1(`$2',substr(`$3',0,1)),substr(`$3',1))')') +dnl ---- +dnl MODIFY_MAILER_FLAGS: append tail of $2 to $1_MF_A/D_ +dnl A if head($2) = + +dnl D if head($2) = - +dnl $1_MF_ is set otherwise; set _A/D_ to `' +define(`MODIFY_MAILER_FLAGS',`define(`_hd_',`substr(`$2',0,1)')define(`_tl_',`substr(`$2',1)')`'ifelse(_hd_,`+',`ifdef($1`'_MF_A_, `define($1`'_MF_A_,$1_MF_A_`'_tl_)', `define($1`'_MF_A_, _tl_)')',_hd_,`-',`ifdef($1`'_MF_D_, `define($1`'_MF_D_,$1_MF_D_`'_tl_)', `define($1`'_MF_D_,_tl_)')',`define($1`'_MF_,`$2')define($1`'_MF_A_,`')define($1`'_MF_D_,`')')') +dnl ---- +dnl actually modify flags: +dnl $1: flags (strings) to modify +dnl $2: name of flags (just first part) to modify +dnl WARNING: the order might be important: if someone adds and delete the +dnl same characters, he does not deserve any better, does he? +dnl this could be coded more efficiently... (do not apply the macro if _MF_A/D_ is undefined) +define(`_MODMF_',`ifdef($2`'_MF_,`$2_MF_',`_AP_(`_ADDCHAR_',_AP_(`_DELCHAR_',$1,ifdef($2`'_MF_D_,`$2_MF_D_',`')),ifdef($2`'_MF_A_,`$2_MF_A_',`'))')') +dnl usage: +dnl MODIFY_MAILER_FLAGS(`LOCAL',`+FlaGs')dnl +dnl in MAILER.m4: _MODMF_(LMF,`LOCAL') +dnl ---------------------------------------- +define(`MAILER', +`define(`_M_N_', `ifelse(`$2', `', `$1', `$2')')dnl +ifdef(_MAILER_`'_M_N_`'_, `dnl`'', +`define(_MAILER_`'_M_N_`'_, `')define(`_ARG_', `$2')define(`_ARGS_', `shift($@)')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')define(`_ARGS_', `shift($@)')include(_CF_DIR_`'feature/$1.m4)POPDIVERT`'') +define(`HACK', `PUSHDIVERT(-1)define(`_ARG_', `$2')define(`_ARGS_', `shift($@)')include(_CF_DIR_`'hack/$1.m4)POPDIVERT`'') +define(`_DPO_',`') +define(`DAEMON_OPTIONS', `define(`_DPO_', defn(`_DPO_') +O DaemonPortOptions=`$1')') +define(`_MAIL_FILTERS_', `') +define(`MAIL_FILTER', `define(`_MAIL_FILTERS_', defn(`_MAIL_FILTERS_') +X`'$1`, '`$2')') +define(`INPUT_MAIL_FILTER', `MAIL_FILTER(`$1', `$2') +ifelse(defn(`confINPUT_MAIL_FILTERS')X, `X', +`define(`confINPUT_MAIL_FILTERS', $1)', +`define(`confINPUT_MAIL_FILTERS', defn(`confINPUT_MAIL_FILTERS')`, '`$1')')') +define(`CF_LEVEL', `9')dnl +define(`VERSIONID', ``##### $1 #####'') +define(`LOCAL_RULE_0', `divert(3)') +define(`LOCAL_RULE_1', +`divert(9)dnl +####################################### +### Ruleset 1 -- Sender Rewriting ### +####################################### + +Ssender=1 +') +define(`LOCAL_RULE_2', +`divert(9)dnl +########################################## +### Ruleset 2 -- Recipient Rewriting ### +########################################## + +Srecipient=2 +') +define(`LOCAL_RULESETS', +`divert(9) + +') +define(`LOCAL_RULE_3', `divert(2)') +define(`LOCAL_CONFIG', `divert(6)') +define(`MAILER_DEFINITIONS', `divert(7)') +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_EXCEPTION', `PUSHDIVERT(5)CN$1 +POPDIVERT`'dnl`'') +define(`MASQUERADE_DOMAIN_FILE', `PUSHDIVERT(5)FM$1 +POPDIVERT`'dnl`'') +define(`LOCAL_DOMAIN', `PUSHDIVERT(5)Cw$1 +POPDIVERT`'dnl`'') +define(`CANONIFY_DOMAIN', `PUSHDIVERT(5)C{Canonify}$1 +POPDIVERT`'dnl`'') +define(`CANONIFY_DOMAIN_FILE', `PUSHDIVERT(5)F{Canonify}$1 +POPDIVERT`'dnl`'') +define(`GENERICS_DOMAIN', `PUSHDIVERT(5)CG$1 +POPDIVERT`'dnl`'') +define(`GENERICS_DOMAIN_FILE', `PUSHDIVERT(5)FG$1 +POPDIVERT`'dnl`'') +define(`LDAPROUTE_DOMAIN', `PUSHDIVERT(5)C{LDAPRoute}$1 +POPDIVERT`'dnl`'') +define(`LDAPROUTE_DOMAIN_FILE', `PUSHDIVERT(5)F{LDAPRoute}$1 +POPDIVERT`'dnl`'') +define(`VIRTUSER_DOMAIN', `PUSHDIVERT(5)C{VirtHost}$1 +define(`_VIRTHOSTS_') +POPDIVERT`'dnl`'') +define(`VIRTUSER_DOMAIN_FILE', `PUSHDIVERT(5)F{VirtHost}$1 +define(`_VIRTHOSTS_') +POPDIVERT`'dnl`'') +define(`RELAY_DOMAIN', `PUSHDIVERT(5)CR$1 +POPDIVERT`'dnl`'') +define(`RELAY_DOMAIN_FILE', `PUSHDIVERT(5)FR$1 +POPDIVERT`'dnl`'') +define(`TRUST_AUTH_MECH', `PUSHDIVERT(5)C{TrustAuthMech}$1 +POPDIVERT`'dnl`'') +define(`_OPTINS', `ifdef(`$1', `$2$1$3')') + + +m4wrap(`include(_CF_DIR_`m4/proto.m4')') + +# default location for files +define(`MAIL_SETTINGS_DIR', `/etc/mail/') + +# set our default hashed database type +define(`DATABASE_MAP_TYPE', `hash') + +# set up default values for options +define(`ALIAS_FILE', `MAIL_SETTINGS_DIR`'aliases') +define(`confMAILER_NAME', ``MAILER-DAEMON'') +define(`confFROM_LINE', `From $g $d') +define(`confOPERATORS', `.:%@!^/[]+') +define(`confSMTP_LOGIN_MSG', `$j Sendmail $v/$Z; $b') +define(`_REC_AUTH_', `$.$?{auth_type}(authenticated') +define(`_REC_FULL_AUTH_', `$.$?{auth_type}(authenticated as ${auth_authen} $?{auth_author}for ${auth_author} $.with ${auth_type}') +define(`_REC_HDR_', `$?sfrom $s $.$?_($?s$|from $.$_)') +define(`_REC_END_', `for $u; $|; + $.$b') +define(`confRECEIVED_HEADER', `_REC_HDR_ + _REC_AUTH_) + $.by $j ($v/$Z)$?r with $r$. id $i$?u + _REC_END_') +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(`confCW_FILE', `MAIL_SETTINGS_DIR`'local-host-names') +define(`confMIME_FORMAT_ERRORS', `True') +define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward') +define(`confCR_FILE', `-o MAIL_SETTINGS_DIR`'relay-domains') +define(`confMILTER_MACROS_CONNECT', ``j, _, {daemon_name}, {if_name}, {if_addr}'') +define(`confMILTER_MACROS_ENVFROM', ``i, {auth_type}, {auth_authen}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr}'') +define(`confMILTER_MACROS_ENVRCPT', ``{rcpt_mailer}, {rcpt_host}, {rcpt_addr}'') + + +divert(0)dnl +VERSIONID(`$Sendmail: cfhead.m4,v 8.74 2000/02/26 01:00:32 gshapiro Exp $') diff --git a/gnu/usr.sbin/sendmail/cf/m4/proto.m4 b/gnu/usr.sbin/sendmail/cf/m4/proto.m4 new file mode 100644 index 00000000000..552a2c00d1b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/m4/proto.m4 @@ -0,0 +1,1867 @@ +divert(-1) +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +divert(0) + +VERSIONID(`$Sendmail: proto.m4,v 8.434 2000/02/22 22:55:17 ca Exp $') + +MAILER(local)dnl + +# level CF_LEVEL config file format +V`'CF_LEVEL/ifdef(`VENDOR_NAME', `VENDOR_NAME', `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', `esmtp')') +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. + Use confDEF_USER_ID with a colon in the value instead. +')') +ifdef(`confREAD_TIMEOUT', +`errprint(`*** confREAD_TIMEOUT is obsolete. + Use individual confTO_ 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. + Use confMAX_MESSAGE_SIZE for the second part of the value. +')')') + + +# Sanity check on ldap_routing feature +# If the user doesn't specify a new map, they better have given as a +# default LDAP specification which has the LDAP base (and most likely the host) +ifdef(`confLDAP_DEFAULT_SPEC',, `ifdef(`_LDAP_ROUTING_WARN_', `errprint(` +WARNING: Using default FEATURE(ldap_routing) map definition(s) +without setting confLDAP_DEFAULT_SPEC option. +')')')dnl + +# clean option definitions below.... +define(`_OPTION', `ifdef(`$2', `O $1`'ifelse(defn(`$2'), `',, `=$2')', `#O $1`'ifelse(`$3', `',,`=$3')')')dnl + +dnl required to "rename" the check_* rulesets... +define(`_U_',ifdef(`_DELAY_CHECKS_',`',`_')) +dnl default relaying denied message +ifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG', `"550 Relaying denied"')') +divert(0)dnl + +# override file safeties - setting this option compromises system security, +# addressing the actual file configuration problem is preferred +# need to set this before any file actions are encountered in the cf file +_OPTION(DontBlameSendmail, `confDONT_BLAME_SENDMAIL', `safe') + +# default LDAP map specification +# need to set this now before any LDAP maps are defined +_OPTION(LDAPDefaultSpec, `confLDAP_DEFAULT_SPEC', `-h localhost') + +################## +# 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') + +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) + +ifdef(`LUSER_RELAY', `dnl +# place to which unknown users should be forwarded +Kuser user -m -a<> +DL`'LUSER_RELAY', +`dnl') + +# operators that cannot be in local usernames (i.e., network indicators) +CO @ % ifdef(`_NO_UUCP_', `', `!') + +# a class with just dot (for identifying canonical names) +C.. + +# a class with just a left bracket (for identifying domain literals) +C[[ + +ifdef(`_ACCESS_TABLE_', `dnl +# access_db acceptance class +C{Accept}OK RELAY +ifdef(`_DELAY_CHECKS_',`dnl +ifdef(`_BLACKLIST_RCPT_',`dnl +# possible access_db RHS for spam friends/haters +C{SpamTag}SPAMFRIEND SPAMHATER')')', +`dnl') + +ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_',`dnl',`dnl +# Resolve map (to check if a host exists in check_mail) +Kresolve host -a -T') + +ifdef(`confCR_FILE', `dnl +# Hosts that will permit relaying ($=R) +FR`'confCR_FILE', +`dnl') + + +# 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) + +# dequoting map +Kdequote dequote + +divert(0)dnl # end of nullclient diversion +# class E: names that should be exposed as from this host, even if we masquerade +# class L: names that should be delivered locally, even if we have a relay +# class M: domains that should be converted to $M +# class N: domains that should not be converted to $M +#CL root +undivert(5)dnl +ifdef(`_VIRTHOSTS_', `CR$={VirtHost}', `dnl') + +# 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 LOCAL_CONFIG +include(_CF_DIR_`m4/version.m4') + +############### +# Options # +############### + +# strip message body to 7 bits on input? +_OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False') + +# 8-bit data handling +_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `adaptive') + +# wait for alias file rebuild (default units: minutes) +_OPTION(AliasWait, `confALIAS_WAIT', `5m') + +# location of alias file +_OPTION(AliasFile, `ALIAS_FILE', `MAIL_SETTINGS_DIR`'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', `False') + +# 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? +# NOTE: There is a potential for a denial of service attack if this is set. +# This option is deprecated and will be removed from a future version. +_OPTION(AutoRebuildAliases, `confAUTO_REBUILD', `False') + +# error message header/file +_OPTION(ErrorHeader, `confERROR_MESSAGE', `MAIL_SETTINGS_DIR`'error-header') + +# error mode +_OPTION(ErrorMode, `confERROR_MODE', `print') + +# save Unix-style "From_" lines at top of header? +_OPTION(SaveFromLine, `confSAVE_FROM_LINES', `False') + +# temporary file mode +_OPTION(TempFileMode, `confTEMP_FILE_MODE', `0600') + +# match recipients against GECOS field? +_OPTION(MatchGECOS, `confMATCH_GECOS', `False') + +# maximum hop count +_OPTION(MaxHopCount, `confMAX_HOP', `17') + +# location of help file +O HelpFile=ifdef(`HELP_FILE', HELP_FILE, `MAIL_SETTINGS_DIR`'helpfile') + +# ignore dots as terminators in incoming messages? +_OPTION(IgnoreDots, `confIGNORE_DOTS', `False') + +# name resolver options +_OPTION(ResolverOptions, `confBIND_OPTS', `+AAONLY') + +# deliver MIME-encapsulated error messages? +_OPTION(SendMimeErrors, `confMIME_FORMAT_ERRORS', `True') + +# 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') + +# persistent host status directory +_OPTION(HostStatusDirectory, `confHOST_STATUS_DIRECTORY', `.hoststat') + +# single thread deliveries (requires HostStatusDirectory)? +_OPTION(SingleThreadDelivery, `confSINGLE_THREAD_DELIVERY', `False') + +# use Errors-To: header? +_OPTION(UseErrorsTo, `confUSE_ERRORS_TO', `False') + +# log level +_OPTION(LogLevel, `confLOG_LEVEL', `10') + +# send to me too, even in an alias expansion? +_OPTION(MeToo, `confME_TOO', `True') + +# verify RHS in newaliases? +_OPTION(CheckAliases, `confCHECK_ALIASES', `False') + +# default messages to old style headers if no special punctuation? +_OPTION(OldStyleHeaders, `confOLD_STYLE_HEADERS', `False') + +# SMTP daemon options +ifelse(defn(`confDAEMON_OPTIONS'), `', `dnl', +`errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid. See cf/README for more information. +)'dnl +`DAEMON_OPTIONS(`confDAEMON_OPTIONS')') +ifelse(defn(`_DPO_'), `', `O DaemonPortOptions=Name=MTA', `_DPO_') +ifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E') + +# SMTP client options +_OPTION(ClientPortOptions, `confCLIENT_OPTIONS', `Address=0.0.0.0') + +# 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.connect, `confTO_CONNECT', `5m') +_OPTION(Timeout.iconnect, `confTO_ICONNECT', `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', `5s') +_OPTION(Timeout.fileopen, `confTO_FILEOPEN', `60s') +_OPTION(Timeout.control, `confTO_CONTROL', `2m') +_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') +_OPTION(Timeout.hoststatus, `confTO_HOSTSTATUS', `30m') +_OPTION(Timeout.resolver.retrans, `confTO_RESOLVER_RETRANS', `5s') +_OPTION(Timeout.resolver.retrans.first, `confTO_RESOLVER_RETRANS_FIRST', `5s') +_OPTION(Timeout.resolver.retrans.normal, `confTO_RESOLVER_RETRANS_NORMAL', `5s') +_OPTION(Timeout.resolver.retry, `confTO_RESOLVER_RETRY', `4') +_OPTION(Timeout.resolver.retry.first, `confTO_RESOLVER_RETRY_FIRST', `4') +_OPTION(Timeout.resolver.retry.normal, `confTO_RESOLVER_RETRY_NORMAL', `4') + +# should we not prune routes in route-addr syntax addresses? +_OPTION(DontPruneRoutes, `confDONT_PRUNE_ROUTES', `False') + +# queue up everything before forking? +_OPTION(SuperSafe, `confSAFE_QUEUE', `True') + +# status file +O StatusFile=ifdef(`STATUS_FILE', `STATUS_FILE', `MAIL_SETTINGS_DIR`'statistics') + +# 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', `mailnull') + +# list of locations of user database file (null means no lookup) +_OPTION(UserDatabaseSpec, `confUSERDB_SPEC', `MAIL_SETTINGS_DIR`'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', `False') + +# 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') + +# maximum number of children we allow at one time +_OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `12') + +# maximum number of new connections per second +_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `3') + +# work recipient factor +_OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000') + +# deliver each queued job in a separate process? +_OPTION(ForkEachJob, `confSEPARATE_PROC', `False') + +# 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', `MAIL_SETTINGS_DIR`'service.switch') + +# hosts file (normally /etc/hosts) +_OPTION(HostsFile, `confHOSTS_FILE', `/etc/hosts') + +# 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', `True') + +# 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', `False') + +# SMTP initial login message (old $e macro) +_OPTION(SmtpGreetingMessage, `confSMTP_LOGIN_MSG', `$j Sendmail $v ready at $b') + +# UNIX initial From header format (old $l macro) +_OPTION(UnixFromLine, `confFROM_LINE', `From $g $d') + +# From: lines that have embedded newlines are unwrapped onto one line +_OPTION(SingleLineFromHeader, `confSINGLE_LINE_FROM_HEADER', `False') + +# Allow HELO SMTP command that does not `include' a host name +_OPTION(AllowBogusHELO, `confALLOW_BOGUS_HELO', `False') + +# Characters to be quoted in a full name phrase (@,;:\()[] are automatic) +_OPTION(MustQuoteChars, `confMUST_QUOTE_CHARS', `.') + +# 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', `False') + +# are group-writable `:include:' and .forward files (un)trustworthy? +_OPTION(UnsafeGroupWrites, `confUNSAFE_GROUP_WRITES', `True') + +# where do errors that occur when sending errors get sent? +_OPTION(DoubleBounceAddress, `confDOUBLE_BOUNCE_ADDRESS', `postmaster') + +# where to save bounces if all else fails +_OPTION(DeadLetterDrop, `confDEAD_LETTER_DROP', `/var/tmp/dead.letter') + +# what user id do we assume for the majority of the processing? +_OPTION(RunAsUser, `confRUN_AS_USER', `sendmail') + +# maximum number of recipients per SMTP envelope +_OPTION(MaxRecipientsPerMessage, `confMAX_RCPTS_PER_MESSAGE', `100') + +# shall we get local names from our installed interfaces? +_OPTION(DontProbeInterfaces, `confDONT_PROBE_INTERFACES', `False') + +# Return-Receipt-To: header implies DSN request +_OPTION(RrtImpliesDsn, `confRRT_IMPLIES_DSN', `False') + +# override connection address (for testing) +_OPTION(ConnectOnlyTo, `confCONNECT_ONLY_TO', `0.0.0.0') + +# Trusted user for file ownership and starting the daemon +_OPTION(TrustedUser, `confTRUSTED_USER', `root') + +# Control socket for daemon management +_OPTION(ControlSocketName, `confCONTROL_SOCKET_NAME', `/var/spool/mqueue/.control') + +# Maximum MIME header length to protect MUAs +_OPTION(MaxMimeHeaderLength, `confMAX_MIME_HEADER_LENGTH', `0/0') + +# Maximum length of the sum of all headers +_OPTION(MaxHeadersLength, `confMAX_HEADERS_LENGTH', `32768') + +# Maximum depth of alias recursion +_OPTION(MaxAliasRecursion, `confMAX_ALIAS_RECURSION', `10') + +# location of pid file +_OPTION(PidFile, `confPID_FILE', `/var/run/sendmail.pid') + +# Prefix string for the process title shown on 'ps' listings +_OPTION(ProcessTitlePrefix, `confPROCESS_TITLE_PREFIX', `prefix') + +# Data file (df) memory-buffer file maximum size +_OPTION(DataFileBufferSize, `confDF_BUFFER_SIZE', `4096') + +# Transcript file (xf) memory-buffer file maximum size +_OPTION(XscriptFileBufferSize, `confXF_BUFFER_SIZE', `4096') + +# list of authentication mechanisms +_OPTION(AuthMechanisms, `confAUTH_MECHANISMS', `GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5') + +# default authentication information for outgoing connections +_OPTION(DefaultAuthInfo, `confDEF_AUTH_INFO', `MAIL_SETTINGS_DIR`'default-auth-info') + +# try to authenticate? (Try when available/only when Authenticated) +_OPTION(AuthOptions, `confAUTH_OPTIONS', `T') + +ifdef(`_FFR_MILTER', ` +# Input mail filters +_OPTION(InputMailFilters, `confINPUT_MAIL_FILTERS', `') + +# Milter options +_OPTION(Milter.macros.connect, `confMILTER_MACROS_CONNECT', `') +_OPTION(Milter.macros.helo, `confMILTER_MACROS_HELO', `') +_OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `') +_OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')') + + +ifdef(`confQUEUE_FILE_MODE', +`# queue file mode (qf files) +O QueueFileMode=confQUEUE_FILE_MODE +') + +########################### +# 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, `MAIL_SETTINGS_DIR`'trusted-users') +Troot +Tdaemon +ifdef(`_NO_UUCP_', `dnl', `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 +# HPosted-Date: $a +# H?l?Received-Date: $b +H?M?Resent-Message-Id: <$t.$i@$j> +H?M?Message-Id: <$t.$i@$j> + +# +###################################################################### +###################################################################### +##### +##### REWRITING RULES +##### +###################################################################### +###################################################################### + +############################################ +### Ruleset 3 -- Name Canonicalization ### +############################################ +Scanonify=3 + +# 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 +R@ $* <@> $: @ $1 unmark @host:... +R$* :: $* <@> $: $1 :: $2 unmark node::addr +R:`include': $* <@> $: :`include': $1 unmark :`include':... +R$* [ IPv6 $- ] <@> $: $1 [ IPv6 $2 ] unmark IPv6 addr +R$* : $* [ $* ] $: $1 : $2 [ $3 ] <@> remark if leading colon +R$* : $* <@> $: $2 strip colon if marked +R$* <@> $: $1 unmark +R$* ; $1 strip trailing semi +R$* < $* ; > $1 < $2 > bogus bracketed semi + +# null input now results from list:; syntax +R$@ $@ :; <@> + +# 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 <> + +ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl +# 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@ $+ : $+ $@ $>Canonify2 < @$1 > : $2 handle +dnl',`dnl +# strip route address <@a,@b,@c:user@d> -> +R@ $+ , $+ $2 +R@ $+ : $+ $2 +dnl') + +# find focus for list syntax +R $+ : $* ; @ $+ $@ $>Canonify2 $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$+ < @ $+ > $@ $>Canonify2 $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$- ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > resolve uucp names +R$+ . $- ! $+ $@ $>Canonify2 $3 < @ $1 . $2 > domain uucps +R$+ ! $+ $@ $>Canonify2 $2 < @ $1 .UUCP > uucp subdomains +') +ifdef(`_USE_DECNET_SYNTAX_', +`# convert node::user addresses into a domain-based address +R$- :: $+ $@ $>Canonify2 $2 < @ $1 .DECNET > resolve DECnet names +R$- . $- :: $+ $@ $>Canonify2 $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$* @ $* $@ $>Canonify2 $1 < @ $2 > Insert < > and finish + +# else we must be a local name +R$* $@ $>Canonify2 $1 + + +################################################ +### Ruleset 96 -- bottom half of ruleset 3 ### +################################################ + +SCanonify2=96 + +# handle special cases for local names +R$* < @ localhost > $* $: $1 < @ $j . > $2 no domain at all +R$* < @ localhost . $m > $* $: $1 < @ $j . > $2 local domain +ifdef(`_NO_UUCP_', `dnl', +`R$* < @ localhost . UUCP > $* $: $1 < @ $j . > $2 .UUCP domain') + +# check for IPv6 domain literal (save quoted form) +R$* < @ [ IPv6 $- ] > $* $: $2 $| $1 < @@ [ $(dequote $2 $) ] > $3 mark IPv6 addr +R$- $| $* < @@ $=w > $* $: $2 < @ $j . > $4 self-literal +R$- $| $* < @@ [ $+ ] > $* $@ $2 < @ [ IPv6 $1 ] > $4 canon IP addr + +# check for IPv4 domain literal +R$* < @ [ $+ ] > $* $: $1 < @@ [ $2 ] > $3 mark [a.b.c.d] +R$* < @@ $=w > $* $: $1 < @ $j . > $3 self-literal +R$* < @@ $+ > $* $@ $1 < @ $2 > $3 canon IP addr + +ifdef(`_DOMAIN_TABLE_', `dnl +# look up domains in the domain table +R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3', `dnl') + +undivert(2)dnl LOCAL_RULE_3 + +ifdef(`_BITDOMAIN_TABLE_', `dnl +# handle BITNET mapping +R$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3', `dnl') + +ifdef(`_UUDOMAIN_TABLE_', `dnl +# handle UUCP mapping +R$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3', `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') + +ifdef(`_NO_CANONIFY_', `dnl', `dnl +# try UUCP traffic as a local address +R$* < @ $+ . UUCP > $* $: $1 < @ $[ $2 $] . UUCP . > $3 +R$* < @ $+ . . UUCP . > $* $@ $1 < @ $2 . > $3') +')') +# hostnames ending in class P are always canonical +R$* < @ $* $=P > $* $: $1 < @ $2 $3 . > $4 +dnl apply the next rule only for hostnames not in class P +dnl this even works for phrases in class P since . is in class P +dnl which daemon flags are set? +R$* < @ $* $~P > $* $: $&{daemon_flags} $| $1 < @ $2 $3 > $4 +dnl the other rules in this section only apply if the hostname +dnl does not end in class P hence no further checks are done here +dnl if this ever changes make sure the lookups are "protected" again! +ifdef(`_NO_CANONIFY_', `dnl +dnl do not canonify unless: +dnl domain ends in class {Canonify} (this does not work if the intersection +dnl with class P is non-empty) +dnl or {daemon_flags} has c set +# pass to name server to make hostname canonical if in class {Canonify} +R$* $| $* < @ $* $={Canonify} > $* $: $2 < @ $[ $3 $4 $] > $5 +# pass to name server to make hostname canonical if requested +R$* c $* $| $* < @ $* > $* $: $3 < @ $[ $4 $] > $5 +dnl trailing dot? -> do not apply _CANONIFY_HOSTS_ +R$* $| $* < @ $+ . > $* $: $2 < @ $3 . > $4 +# add a trailing dot to qualified hostnames so other rules will work +R$* $| $* < @ $+.$+ > $* $: $2 < @ $3.$4 . > $5 +ifdef(`_CANONIFY_HOSTS_', `dnl +dnl this should only apply to unqualified hostnames +dnl but if a valid character inside an unqualified hostname is an OperatorChar +dnl then $- does not work. +# lookup unqualified hostnames +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl +dnl _NO_CANONIFY_ is not set: canonify unless: +dnl {daemon_flags} contains CC (do not canonify) +R$* CC $* $| $* $: $3 +# pass to name server to make hostname canonical +R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4') +dnl remove {daemon_flags} for other cases +R$* $| $* $: $2 + +# local host aliases and pseudo-domains are always canonical +R$* < @ $=w > $* $: $1 < @ $2 . > $3 +ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', +`R$* < @ $* $=M > $* $: $1 < @ $2 $3 . > $4', +`R$* < @ $=M > $* $: $1 < @ $2 . > $3') +ifdef(`_VIRTUSER_TABLE_', `dnl +dnl virtual hosts are also canonical +ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', +`R$* < @ $* $={VirtHost} > $* $: $1 < @ $2 $3 . > $4', +`R$* < @ $={VirtHost} > $* $: $1 < @ $2 . > $3')', +`dnl') +dnl remove superfluous dots (maybe repeatedly) which may have been added +dnl by one of the rules before +R$* < @ $* . . > $* $1 < @ $2 . > $3 + + +################################################## +### Ruleset 4 -- Final Output Post-rewriting ### +################################################## +Sfinal=4 + +R$* <@> $@ handle <> and list:; + +# strip trailing dot off possibly canonical name +R$* < @ $+ . > $* $1 < @ $2 > $3 + +# eliminate internal code +R$* < @ *LOCAL* > $* $1 < @ $j > $2 + +# externalize local domain info +R$* < $+ > $* $1 $2 $3 defocus +R@ $+ : @ $+ : $+ @ $1 , @ $2 : $3 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 @ $2 u%host@host => u@host + + + +############################################################## +### Ruleset 97 -- recanonicalize and call ruleset zero ### +### (used for recursive calls) ### +############################################################## + +SRecurse=97 +R$* $: $>canonify $1 +R$* $@ $>parse $1 + + +###################################### +### Ruleset 0 -- Parse Address ### +###################################### + +Sparse=0 + +R$* $: $>Parse0 $1 initial parsing +R<@> $#_LOCAL_ $: <@> special case error msgs +R$* $: $>ParseLocal $1 handle local hacks +R$* $: $>Parse1 $1 final parsing + +# +# Parse0 -- do initial syntax checking and eliminate local addresses. +# This should either return with the (possibly modified) input +# or return with a #error mailer. It should not return with a +# #mailer other than the #error mailer. +# + +SParse0 +R<@> $@ <@> special case error msgs +R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R@ <@ $* > < @ $1 > catch "@@host" bogosity +R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R$* $: <> $1 +R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* $1 +R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" + +# now delete the local info -- note $=O to find characters that cause forwarding +R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user +R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... +R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here +R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... +R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R$* $=O $* < @ *LOCAL* > + $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... +R$* < @ *LOCAL* > $: $1 + +# +# Parse1 -- the bottom half of ruleset 0. +# + +SParse1 +ifdef(`_LDAP_ROUTING_', `dnl +# handle LDAP routing for hosts in $={LDAPRoute} +R$+ < @ $={LDAPRoute} . > $: $>LDAPExpand <$1 < @ $2 . >> <$1 @ $2>', +`dnl') + +ifdef(`_MAILER_smtp_', +`# handle numeric address spec +dnl there is no check whether this is really an IP number +R$* < @ [ $+ ] > $* $: $>ParseLocal $1 < @ [ $2 ] > $3 numeric internet spec +R$* < @ [ $+ ] > $* $1 < @ [ $2 ] : $S > $3 Add smart host to path +R$* < @ [ IPv6 $- ] : > $* + $#_SMTP_ $@ [ $(dequote $2 $) ] $: $1 < @ [IPv6 $2 ] > $3 no smarthost: send +R$* < @ [ $+ ] : > $* $#_SMTP_ $@ [$2] $: $1 < @ [$2] > $3 no smarthost: send +R$* < @ [ $+ ] : $- : $*> $* $#$3 $@ $4 $: $1 < @ [$2] > $5 smarthost with mailer +R$* < @ [ $+ ] : $+ > $* $#_SMTP_ $@ $3 $: $1 < @ [$2] > $4 smarthost without mailer', + `dnl') + +ifdef(`_VIRTUSER_TABLE_', `dnl +# handle virtual users +R$+ $: $1 Mark for lookup +ifdef(`_VIRTUSER_ENTIRE_DOMAIN_', +`R $+ < @ $* $={VirtHost} . > $: < $(virtuser $1 @ $2 $3 $@ $1 $: @ $) > $1 < @ $2 $3 . >', +`R $+ < @ $={VirtHost} . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >') +R $+ < @ $=w . > $: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . > +R<@> $+ + $* < @ $* . > + $: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . > +R<@> $+ + $* < @ $* . > + $: < $(virtuser $1 @ $3 $@ $1 $: @ $) > $1 + $2 < @ $3 . > +dnl try default entry: @domain +dnl +detail +R<@> $+ + $* < @ $+ . > $: < $(virtuser @ $3 $@ $1 $@ $2 $: @ $) > $1 + $2 < @ $3 . > +dnl without +detail (or no match) +R<@> $+ < @ $+ . > $: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . > +R<@> $+ $: $1 +R $+ $: $1 +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< $+ > $+ < @ $+ > $: $>Recurse $1', +`dnl') + +# short circuit local delivery so forwarded email works +ifdef(`_MAILER_usenet_', `dnl +R$+ . USENET < @ $=w . > $#usenet $: $1 handle usenet specially', `dnl') +ifdef(`_STICKY_LOCAL_DOMAIN_', +`R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub +R< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep .... +dnl $H empty (but @$=w.) +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') + +ifdef(`_MAILER_TABLE_', `dnl +# not local -- try mailer table lookup +R$* <@ $+ > $* $: < $2 > $1 < @ $2 > $3 extract host name +R< $+ . > $* $: < $1 > $2 strip trailing dot +R< $+ > $* $: < $(mailertable $1 $) > $2 lookup +dnl it is $~[ instead of $- to avoid matches on IPv6 addresses +R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 check -- resolved? +R< $+ > $* $: $>Mailertable <$1> $2 try domain', +`dnl') +undivert(4)dnl UUCP rules from `MAILER(uucp)' + +ifdef(`_NO_UUCP_', `dnl', +`# resolve remotely connected UUCP links (if any) +ifdef(`_CLASS_V_', +`R$* < @ $=V . UUCP . > $* $: $>MailerToTriple < $V > $1 <@$2.UUCP.> $3', + `dnl') +ifdef(`_CLASS_W_', +`R$* < @ $=W . UUCP . > $* $: $>MailerToTriple < $W > $1 <@$2.UUCP.> $3', + `dnl') +ifdef(`_CLASS_X_', +`R$* < @ $=X . UUCP . > $* $: $>MailerToTriple < $X > $1 <@$2.UUCP.> $3', + `dnl')') + +# resolve fake top level domains by forwarding to other hosts +ifdef(`BITNET_RELAY', +`R$*<@$+.BITNET.>$* $: $>MailerToTriple < $B > $1 <@$2.BITNET.> $3 user@host.BITNET', + `dnl') +ifdef(`DECNET_RELAY', +`R$*<@$+.DECNET.>$* $: $>MailerToTriple < $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.>$* $: $>MailerToTriple < $F > $1 <@$2.FAX.> $3 user@host.FAX', + `dnl')') + +ifdef(`UUCP_RELAY', +`# forward non-local UUCP traffic to our UUCP relay +R$*<@$*.UUCP.>$* $: $>MailerToTriple < $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$* < @ $* > $* $: $>MailerToTriple < $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 $: "553 Unrecognized host name " $2') + +# 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 ### +########################################################################### + +SLocal_localaddr +Slocaladdr=5 +R$+ $: $1 $| $>"Local_localaddr" $1 +R$+ $| $#$* $#$2 +R$+ $| $* $: $1 + +# 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 + +ifdef(`LUSER_RELAY', `dnl +# send unrecognized local users to a relay host +R< > $+ $: < $L > $(user $1 $) look up user +R< $* > $+ <> $: < > $2 found; strip $L', +`dnl') + +# see if we have a relay or a hub +R< > $+ $: < $H > $1 try hub +R< > $+ $: < $R > $1 try relay +R< > $+ $: < > < $1 <> $&h > nope, restore +detail +R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail +R< > < $+ <> $* > $: < > < $1 > else discard +R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part +R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1 strip the extra + +R< > < $+ > $@ $1 no +detail +R$+ $: $1 <> $&h add +detail back in +R$+ <> + $* $: $1 + $2 check whether +detail +R$+ <> $* $: $1 else discard +R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension +R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension +R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > +R< $+ > $+ $@ $>MailerToTriple < $1 > $2 < @ $1 > + +ifdef(`_MAILER_TABLE_', `dnl +################################################################### +### Ruleset 90 -- try domain part of mailertable entry ### +dnl input: LeftPartOfDomain FullAddress +################################################################### + +SMailertable=90 +dnl shift and check +dnl %2 is not documented in cf/README +R$* <$- . $+ > $* $: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4 +dnl it is $~[ instead of $- to avoid matches on IPv6 addresses +R$* <$~[ : $* > $* $>MailerToTriple < $2 : $3 > $4 check -- resolved? +R$* < . $+ > $* $@ $>Mailertable $1 . <$2> $3 no -- strip & try again +dnl is $2 always empty? +R$* < $* > $* $: < $(mailertable . $@ $1$2 $) > $3 try "." +R< $~[ : $* > $* $>MailerToTriple < $1 : $2 > $3 "." found? +dnl return full address +R< $* > $* $@ $2 no mailertable match', +`dnl') + +################################################################### +### Ruleset 95 -- canonify mailer:[user@]host syntax to triple ### +dnl input: in general: <[mailer:]host> lp<@domain>rest +dnl <> address -> address +dnl -> error +dnl -> error +dnl lp<@domain>rest -> mailer host user +dnl address -> mailer host address +dnl address -> address +dnl <[IPv6 number]> address -> relay number address +dnl address -> relay host address +################################################################### + +SMailerToTriple=95 +R< > $* $@ $1 strip off null relay +R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 +R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 +R< local : $* > $* $>CanonLocal < $1 > $2 +R< $- : $+ @ $+ > $*<$*>$* $# $1 $@ $3 $: $2<@$3> use literal user +R< $- : $+ > $* $# $1 $@ $2 $: $3 try qualified mailer +R< $=w > $* $@ $2 delete local host +R< [ IPv6 $+ ] > $* $#_RELAY_ $@ $(dequote $1 $) $: $2 use unqualified mailer +R< $+ > $* $#_RELAY_ $@ $1 $: $2 use unqualified mailer + +################################################################### +### Ruleset CanonLocal -- canonify local: syntax ### +dnl input: address +dnl <@host> : rest -> Recurse rest +dnl p1 $=O p2 <@host> -> Recurse p1 $=O p2 +dnl <> user <@host> rest -> local user@host user +dnl <> user -> local user user +dnl lp <@domain> rest -> lp <@host> [cont] +dnl lp <@host> rest -> local lp@host user +dnl lp -> local lp user +################################################################### + +SCanonLocal +# strip local host from routed addresses +R< $* > < @ $+ > : $+ $@ $>Recurse $3 +R< $* > $+ $=O $+ < @ $+ > $@ $>Recurse $2 $3 $4 + +# strip trailing dot from any host name that may appear +R< $* > $* < @ $* . > $: < $1 > $2 < @ $3 > + +# handle local: syntax -- use old user, either with or without host +R< > $* < @ $* > $* $#_LOCAL_ $@ $1@$2 $: $1 +R< > $+ $#_LOCAL_ $@ $1 $: $1 + +# handle local:user@host syntax -- ignore host part +R< $+ @ $+ > $* < @ $* > $: < $1 > $3 < @ $4 > + +# handle local:user syntax +R< $+ > $* <@ $* > $* $#_LOCAL_ $@ $2@$3 $: $1 +R< $+ > $* $#_LOCAL_ $@ $2 $: $1 + +################################################################### +### Ruleset 93 -- convert header names to masqueraded form ### +################################################################### + +SMasqHdr=93 + +ifdef(`_GENERICS_TABLE_', `dnl +# handle generics database +ifdef(`_GENERICS_ENTIRE_DOMAIN_', +dnl if generics should be applied add a @ as mark +`R$+ < @ $* $=G . > $: < $1@$2$3 > $1 < @ $2$3 . > @ mark', +`R$+ < @ $=G . > $: < $1@$2 > $1 < @ $2 . > @ mark') +R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark +dnl workspace: either user<@domain> or user <@domain> @ +dnl ignore the first case for now +dnl if it has the mark lookup full address +R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 > +dnl workspace: ... or user <@domain> +dnl no match, try user+detail@domain +R<@$+ + $* @ $+> $+ < @ $+ > + $: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 > +R<@$+ + $* @ $+> $+ < @ $+ > + $: < $(generics $1@$3 $: $) > $4 < @ $5 > +dnl no match, remove mark +R<@$+ > $+ < @ $+ > $: < > $2 < @ $3 > +dnl no match, try @domain for exceptions +R< > $+ < @ $+ . > $: < $(generics @$2 $@ $1 $: $) > $1 < @ $2 . > +dnl workspace: ... or user <@domain> +dnl no match, try local part +R< > $+ < @ $+ > $: < $(generics $1 $: $) > $1 < @ $2 > +R< > $+ + $* < @ $+ > $: < $(generics $1+* $@ $2 $: $) > $1 + $2 < @ $3 > +R< > $+ + $* < @ $+ > $: < $(generics $1 $: $) > $1 + $2 < @ $3 > +R< $* @ $* > $* < $* > $@ $>canonify $1 @ $2 found qualified +R< $+ > $* < $* > $: $>canonify $1 @ *LOCAL* found unqualified +R< > $* $: $1 not found', +`dnl') + +# do not masquerade anything in class N +R$* < @ $* $=N . > $@ $1 < @ $2 $3 . > + +# special case the users that should be exposed +R$=E < @ *LOCAL* > $@ $1 < @ $j . > leave exposed +ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', +`R$=E < @ $* $=M . > $@ $1 < @ $2 $3 . >', +`R$=E < @ $=M . > $@ $1 < @ $2 . >') +ifdef(`_LIMITED_MASQUERADE_', `dnl', +`R$=E < @ $=w . > $@ $1 < @ $2 . >') + +# handle domain-specific masquerading +ifdef(`_MASQUERADE_ENTIRE_DOMAIN_', +`R$* < @ $* $=M . > $* $: $1 < @ $2 $3 . @ $M > $4 convert masqueraded doms', +`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 ### +################################################################### + +SMasqEnv=94 +ifdef(`_MASQUERADE_ENVELOPE_', +`R$+ $@ $>MasqHdr $1', +`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2') + +################################################################### +### Ruleset 98 -- local part of ruleset zero (can be null) ### +################################################################### + +SParseLocal=98 +undivert(3)dnl LOCAL_RULE_0 + +ifdef(`_LDAP_ROUTING_', `dnl +SLDAPExpand +# do the LDAP lookups +R<$+><$+> + $: <$(ldap_mailroutingaddress $2 $: $)> <$(ldap_mailhost $2 $: $)> <$1> <$2> + +# if mailRoutingAddress and local or non-existant mailHost, +# return the new mailRoutingAddress +R< $+ > < $=w > < $+ > < $+ > $@ $>Parse0 $>canonify $1 +R< $+ > < > < $+ > < $+ > $@ $>Parse0 $>canonify $1 + +# if mailRoutingAddress and non-local mailHost, +# relay to mailHost with new mailRoutingAddress +R< $+ > < $+ > < $+ > < $+ > $#_RELAY_ $@ $2 $: $>canonify $1 + +# if no mailRoutingAddress and local mailHost, +# return original address +R< > < $=w > <$+> <$+> $@ $2 + +# if no mailRoutingAddress and non-local mailHost, +# relay to mailHost with original address +R< > < $+ > <$+> <$+> $#_RELAY_ $@ $1 $: $2 + +# if no mailRoutingAddress and no mailHost, +# try @domain +R< > < > <$+> <$+ @ $+> $@ $>LDAPExpand <$1> <@ $3> + +# if no mailRoutingAddress and no mailHost and this was a domain attempt, +ifelse(_LDAP_ROUTING_, `_MUST_EXIST_', `dnl +# user does not exist +R< > < > <$+> <@ $+> $#error $@ nouser $: "550 User unknown"', +`dnl +# return the original address +R< > < > <$+> <@ $+> $@ $1')', +`dnl') + +ifelse(substr(confDELIVERY_MODE,0,1), `d', `errprint(`WARNING: Antispam rules not available in deferred delivery mode. +')') +ifdef(`_ACCESS_TABLE_', `dnl +###################################################################### +### LookUpDomain -- search for domain in access database +### +### Parameters: +### <$1> -- key (domain name) +### <$2> -- default (what to return if not found in db) +dnl must not be empty +### <$3> -- passthru (additional data passed unchanged through) +### <$4> -- mark (must be <(!|+) single-token>) +### ! does lookup only with tag +### + does lookup with and without tag +dnl returns: +dnl +###################################################################### + +SLookUpDomain +dnl remove IPv6 mark and dequote address +dnl it is a bit ugly because it is checked on each "iteration" +R<[IPv6 $-]> <$+> <$*> <$*> $: <[$(dequote $1 $)]> <$2> <$3> <$4> +dnl workspace +dnl lookup with tag (in front, no delimiter here) +R<$*> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5> +dnl workspace +ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest +R <$+.$+> <$+> <$*> <$- $-> $: < $(access $5`'_TAG_DELIM_`'.$2 $: ? $) > <$1.$2> <$3> <$4> <$5 $6>', `dnl') +dnl lookup without tag? +R <$+> <$+> <$*> <+ $*> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4> +ifdef(`_FFR_LOOKUPDOTDOMAIN', `dnl omit first component: lookup .rest +R <$+.$+> <$+> <$*> <+ $*> $: < $(access .$2 $: ? $) > <$1.$2> <$3> <$4> <+ $5>', `dnl') +dnl lookup IP address (no check is done whether it is an IP number!) +R <[$+.$-]> <$+> <$*> <$*> $@ $>LookUpDomain <[$1]> <$3> <$4> <$5> +dnl lookup IPv6 address +R <[$+:$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5> +dnl not found, but subdomain: try again +R <$+.$+> <$+> <$*> <$*> $@ $>LookUpDomain <$2> <$3> <$4> <$5> +dnl not found, no subdomain: return default +R <$+> <$+> <$*> <$*> $@ <$2> <$3> +dnl return result of lookup +R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4> + +###################################################################### +### LookUpAddress -- search for host address in access database +### +### Parameters: +### <$1> -- key (dot quadded host address) +### <$2> -- default (what to return if not found in db) +dnl must not be empty +### <$3> -- passthru (additional data passed through) +### <$4> -- mark (must be <(!|+) single-token>) +### ! does lookup only with tag +### + does lookup with and without tag +dnl returns: +dnl +###################################################################### + +SLookUpAddress +dnl lookup with tag +R<$+> <$+> <$*> <$- $+> $: < $(access $5`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3> <$4 $5> +dnl lookup without tag +R <$+> <$+> <$*> <+ $+> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4> +dnl no match; IPv6: remove last part +R <$+:$-> <$+> <$*> <$*> $: $>LookUpAddress <$1> <$3> <$4> <$5> +dnl no match; IPv4: remove last part +R <$+.$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> +dnl no match: return default +R <$+> <$+> <$*> <$*> $@ <$2> <$3> +dnl match: return result +R<$*> <$+> <$+> <$*> <$*> $@ <$1> <$4>', +`dnl') + +###################################################################### +### CanonAddr -- Convert an address into a standard form for +### relay checking. Route address syntax is +### crudely converted into a %-hack address. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed address, not in source route form +dnl user%host%host<@domain> +dnl host!user<@domain> +###################################################################### + +SCanonAddr +R$* $: $>Parse0 $>canonify $1 make domain canonical +ifdef(`_USE_DEPRECATED_ROUTE_ADDR_',`dnl +R< @ $+ > : $* @ $* < @ $1 > : $2 % $3 change @ to % in src route +R$* < @ $+ > : $* : $* $3 $1 < @ $2 > : $4 change to % hack. +R$* < @ $+ > : $* $3 $1 < @ $2 > +dnl') + +###################################################################### +### ParseRecipient -- Strip off hosts in $=R as well as possibly +### $* $=m or the access database. +### Check user portion for host separators. +### +### Parameters: +### $1 -- full recipient address +### +### Returns: +### parsed, non-local-relaying address +###################################################################### + +SParseRecipient +dnl mark and canonify address +R$* $: $>CanonAddr $1 +R $* < @ $* . > $1 < @ $2 > strip trailing dots +R $- < @ $* > $: $(dequote $1 $) < @ $2 > dequote local part + +# if no $=O character, no host in the user portion, we are done +R $* $=O $* < @ $* > $: $1 $2 $3 < @ $4> +R $* $@ $1 + +ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl +# if we relay, check username portion for user%host so host can be checked also +R $* < @ $* $=m > $: $1 < @ $2 $3 >', `dnl') + +ifdef(`_RELAY_MX_SERVED_', `dnl +R $* < @ $+ > $: < : $(mxserved $2 $) : > < $1 < @$2 > > +R < : $* : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 +R < $* : $=w. : $* > < $+ > $: $4 +R < : $* : > < $+ > $: $2', `dnl') + +ifdef(`_RELAY_HOSTS_ONLY_', +`R $* < @ $=R > $: $1 < @ $2 > +ifdef(`_ACCESS_TABLE_', `dnl +R $* < @ $+ > $: <$(access To:$2 $: NO $)> $1 < @ $2 > +R $* < @ $+ > $: <$(access $2 $: NO $)> $1 < @ $2 >',`dnl')', +`R $* < @ $* $=R > $: $1 < @ $2 $3 > +ifdef(`_ACCESS_TABLE_', `dnl +R $* < @ $+ > $: $>LookUpDomain <$2> <$1 < @ $2 >> <+To> +R<$+> <$+> $: <$1> $2',`dnl')') + +R $* < @ $* > $@ $>ParseRecipient $1 +R<$-> $* $@ $2 + + +###################################################################### +### check_relay -- check hostname/address on SMTP startup +###################################################################### + +SLocal_check_relay +Scheck`'_U_`'relay +R$* $: $1 $| $>"Local_check_relay" $1 +R$* $| $* $| $#$* $#$3 +R$* $| $* $| $* $@ $>"Basic_check_relay" $1 $| $2 + +SBasic_check_relay +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +ifdef(`_ACCESS_TABLE_', `dnl +R$+ $| $+ $: $>LookUpDomain < $1 > < $2 > <+Connect> +R <$+> $: $>LookUpAddress < $1 > < $1 > <+Connect> no: another lookup +R < $+ > $: $1 found nothing +R<$={Accept}> < $* > $@ $1 +R $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') +R $* $#discard $: discard +dnl error tag +R $* $#error $@ $1.$2.$3 $: $4 +R $* $#error $: $1 +dnl generic error from access map +R<$+> $* $#error $: $1', `dnl') + +ifdef(`_RBL_',`dnl +# DNS based IP address spam list +R$* $: $&{client_addr} +R::ffff:$-.$-.$-.$- $: $(host $4.$3.$2.$1._RBL_. $: OK $) +R$-.$-.$-.$- $: $(host $4.$3.$2.$1._RBL_. $: OK $) +ROK $: OKSOFAR +R$+ $#error $@ 5.7.1 $: "550 Mail from " $&{client_addr} " refused by blackhole site _RBL_"', +`dnl') +undivert(8) + +###################################################################### +### check_mail -- check SMTP ``MAIL FROM:'' command argument +###################################################################### + +SLocal_check_mail +Scheck`'_U_`'mail +R$* $: $1 $| $>"Local_check_mail" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_mail" $1 + +SBasic_check_mail +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +dnl workspace: address as given by MAIL FROM: +R<> $@ we MUST accept <> (RFC 1123) +ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl +dnl do some additional checks +dnl no user@host +dnl no user@localhost (if nonlocal sender) +dnl this is a pretty simple canonification, it will not catch every case +dnl just make sure the address has <> around it (which is required by +dnl the RFC anyway, maybe we should complain if they are missing...) +dnl dirty trick: if it is user@host, just add a dot: user@host. this will +dnl not be modified by host lookups. +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +dnl workspace: <@>
+dnl prepend daemon_flags +R$* $: $&{daemon_flags} $| $1 +dnl workspace: ${daemon_flags} $| <@>
+dnl do not allow these at all or only from local systems? +R$* f $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +dnl accept unqualified sender: change mark to avoid test +R$* u $* $| <@> < $* > $: < $3 > +dnl workspace: ${daemon_flags} $| <@>
+dnl or:
+dnl or:
+dnl remove daemon_flags +R$* $| $* $: $2 +# handle case of @localhost on address +R<@> < $* @ localhost > $: < ? $&{client_name} > < $1 @ localhost > +R<@> < $* @ [127.0.0.1] > + $: < ? $&{client_name} > < $1 @ [127.0.0.1] > +R<@> < $* @ localhost.$m > + $: < ? $&{client_name} > < $1 @ localhost.$m > +ifdef(`_NO_UUCP_', `dnl', +`R<@> < $* @ localhost.UUCP > + $: < ? $&{client_name} > < $1 @ localhost.UUCP >') +dnl workspace: < ? $&{client_name} > +dnl or: <@>
+dnl or:
(thanks to u in ${daemon_flags}) +R<@> $* $: $1 no localhost as domain +dnl workspace: < ? $&{client_name} > +dnl or:
+dnl or:
(thanks to u in ${daemon_flags}) +R $* $: $2 local client: ok +R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +dnl remove (happens only if ${client_name} == "" or u in ${daemon_flags}) +R $* $: $1') +dnl workspace: address (or
) +R$* $: $>CanonAddr $1 canonify sender address and mark it +dnl workspace: CanonicalAddress (i.e. address in canonical form localpart<@host>) +dnl there is nothing behind the <@host> so no trailing $* needed +R $* < @ $+ . > $1 < @ $2 > strip trailing dots +# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc) +R $* < @ $* $=P > $: $1 < @ $2 $3 > +dnl workspace CanonicalAddress where mark is ? or OK +ifdef(`_ACCEPT_UNRESOLVABLE_DOMAINS_', +`R $* < @ $+ > $: $1 < @ $2 > ... unresolvable OK', +`R $* < @ $+ > $: $) > $1 < @ $2 > +R> $* < @ $+ > + $: <$2> $3 < @ $4 >') +dnl workspace CanonicalAddress where mark is ?, OK, PERM, TEMP +dnl mark is ? iff the address is user (wo @domain) + +ifdef(`_ACCESS_TABLE_', `dnl +# check sender address: user@address, user@, @address +dnl should we remove +ext from user? +dnl workspace: CanonicalAddress where mark is: ?, OK, PERM, TEMP +R<$+> $+ < @ $* > $: @<$1> <$2 < @ $3 >> $| +R<$+> $+ $: @<$1> <$2> $| +dnl workspace: @ $| <@type:address> .... +dnl $| is used as delimiter, otherwise false matches may occur: > +dnl will only return user<@domain when "reversing" the args +R@ <$+> <$*> $| <$+> $: <@> <$1> <$2> $| $>SearchList <+From> $| <$3> <> +dnl workspace: <@> $| +R<@> <$+> <$*> $| <$*> $: <$3> <$1> <$2> reverse result +dnl workspace: +# retransform for further use +dnl required form: +dnl CanonicalAddress +R <$+> <$*> $: <$1> $2 no match +R<$+> <$+> <$*> $: <$1> $3 relevant result, keep it', `dnl') +dnl workspace CanonicalAddress +dnl mark is ? iff the address is user (wo @domain) + +ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl +# handle case of no @domain on address +dnl prepend daemon_flags +R $* $: $&{daemon_flags} $| $1 +dnl accept unqualified sender: change mark to avoid test +R$* u $* $| $* $: $3 +dnl remove daemon_flags +R$* $| $* $: $2 +R $* $: < ? $&{client_name} > $1 +R $* $@ ...local unqualed ok +R $* $#error $@ 5.5.4 $: "553 Domain name required" + ...remote is not') +# check results +R $* $: @ $1 mark address: nothing known about it +R $* $@ +R $* $#error $@ 4.1.8 $: "451 Sender domain must resolve" +R $* $#error $@ 5.1.8 $: "501 Sender domain must exist" +ifdef(`_ACCESS_TABLE_', `dnl +R<$={Accept}> $* $@ $1 +R $* $#discard $: discard +R $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') +dnl error tag +R $* $#error $@ $1.$2.$3 $: $4 +R $* $#error $: $1 +dnl generic error from access map +R<$+> $* $#error $: $1 error from access db', +`dnl') + +###################################################################### +### check_rcpt -- check SMTP ``RCPT TO:'' command argument +###################################################################### + +SLocal_check_rcpt +Scheck`'_U_`'rcpt +R$* $: $1 $| $>"Local_check_rcpt" $1 +R$* $| $#$* $#$2 +R$* $| $* $@ $>"Basic_check_rcpt" $1 + +SBasic_check_rcpt +# check for deferred delivery mode +R$* $: < ${deliveryMode} > $1 +R< d > $* $@ deferred +R< $* > $* $: $2 + +ifdef(`_REQUIRE_QUAL_RCPT_', `dnl +# require qualified recipient? +R$+ $: $1 +R<$+> $: <@> <$1> +R$+ $: <@> <$1> +dnl prepend daemon_flags +R$* $: $&{daemon_flags} $| $1 +dnl workspace: ${daemon_flags} $| <@>
+dnl do not allow these at all or only from local systems? +R$* r $* $| <@> < $* @ $- > $: < ? $&{client_name} > < $3 @ $4 > +R < $* > $: <$1> +R < $* > $: <$1> +R <$+> $#error $@ 5.5.4 $: "553 Domain name required" +dnl remove daemon_flags for other cases +R$* $| <@> $* $: $2', `dnl') + +ifdef(`_LOOSE_RELAY_CHECK_',`dnl +R$* $: $>CanonAddr $1 +R$* < @ $* . > $1 < @ $2 > strip trailing dots', +`R$* $: $>ParseRecipient $1 strip relayable hosts') + +ifdef(`_BESTMX_IS_LOCAL_',`dnl +ifelse(_BESTMX_IS_LOCAL_, `', `dnl +# unlimited bestmx +R$* < @ $* > $* $: $1 < @ $2 @@ $(bestmx $2 $) > $3', +`dnl +# limit bestmx to $=B +R$* < @ $* $=B > $* $: $1 < @ $2 $3 @@ $(bestmx $2 $3 $) > $4') +R$* $=O $* < @ $* @@ $=w . > $* $@ $>"Basic_check_rcpt" $1 $2 $3 +R$* < @ $* @@ $=w . > $* $: $1 < @ $3 > $4 +R$* < @ $* @@ $* > $* $: $1 < @ $2 > $4') + +ifdef(`_BLACKLIST_RCPT_',`dnl +ifdef(`_ACCESS_TABLE_', `dnl +# blacklist local users or any host from receiving mail +R$* $: $1 +dnl user is now tagged with @ to be consistent with check_mail +dnl and to distinguish users from hosts (com would be host, com@ would be user) +R $+ < @ $=w > $: <> <$1 < @ $2 >> $| +R $+ < @ $* > $: <> <$1 < @ $2 >> $| +R $+ $: <> <$1> $| +dnl $| is used as delimiter, otherwise false matches may occur: > +dnl will only return user<@domain when "reversing" the args +R<> <$*> $| <$+> $: <@> <$1> $| $>SearchList <+To> $| <$2> <> +R<@> <$*> $| <$*> $: <$2> <$1> reverse result +R <$*> $: @ $1 mark address as no match +R<$={Accept}> <$*> $: @ $2 mark address as no match +ifdef(`_DELAY_CHECKS_',`dnl +dnl we have to filter these because otherwise they would be interpreted +dnl as generic error message... +dnl error messages should be "tagged" by prefixing them with error: ! +dnl that would make a lot of things easier. +dnl maybe we should stop checks already here (if SPAM_xyx)? +R<$={SpamTag}> <$*> $: @ $2 mark address as no match') +R $* $#error $@ 5.2.1 $: "550 Mailbox disabled for this recipient" +R $* $#discard $: discard +dnl error tag +R $* $#error $@ $1.$2.$3 $: $4 +R $* $#error $: $1 +dnl generic error from access map +R<$+> $* $#error $: $1 error from access db +R@ $* $1 remove mark', `dnl')', `dnl') + +ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)') +# authenticated by a trusted mechanism? +R$* $: $1 $| $&{auth_type} +dnl empty ${auth_type}? +R$* $| $: $1 +dnl mechanism ${auth_type} accepted? +dnl use $# to override further tests (delay_checks): see check_rcpt below +R$* $| $={TrustAuthMech} $# RELAYAUTH +dnl undo addition of ${auth_type} +R$* $| $* $: $1 +ifelse(defn(`_NO_UUCP_'), `r', +`R$* ! $* < @ $* > $: $2 < @ BANG_PATH >', `dnl') +# anything terminating locally is ok +ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl +R$+ < @ $* $=m > $@ RELAYTO', `dnl') +R$+ < @ $=w > $@ RELAYTO +ifdef(`_RELAY_HOSTS_ONLY_', +`R$+ < @ $=R > $@ RELAYTO +ifdef(`_ACCESS_TABLE_', `dnl +R$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >> +R$+ < @ $+ > $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', +`R$+ < @ $* $=R > $@ RELAYTO +ifdef(`_ACCESS_TABLE_', `dnl +R$+ < @ $+ > $: $>LookUpDomain <$2> <$1 < @ $2 >> <+To>',`dnl')') +ifdef(`_ACCESS_TABLE_', `dnl +R $* $@ RELAYTO +R<$*> <$*> $: $2',`dnl') + +ifdef(`_RELAY_MX_SERVED_', `dnl +# allow relaying for hosts which we MX serve +R$+ < @ $+ > $: < : $(mxserved $2 $) : > $1 < @ $2 > +dnl this must not necessarily happen if the client is checked first... +R< : $* : > $* $#error $@ 4.7.1 $: "450 Can not check MX records for recipient host " $1 +R<$* : $=w . : $*> $* $@ RELAYTO +R< : $* : > $* $: $2', +`dnl') + +# check for local user (i.e. unqualified address) +R$* $: $1 +R $* < @ $+ > $: $1 < @ $2 > +# local user is ok +dnl is it really? the standard requires user@domain, not just user +dnl but we should accept it anyway (maybe making it an option: +dnl RequireFQDN ?) +dnl postmaster must be accepted without domain (DRUMS) +ifdef(`_REQUIRE_QUAL_RCPT_', `dnl +R postmaster $@ TOPOSTMASTER +# require qualified recipient? +dnl prepend daemon_flags +R $+ $: $&{daemon_flags} $| $1 +dnl workspace: ${daemon_flags} $| localpart +dnl do not allow these at all or only from local systems? +dnl r flag? add client_name +R$* r $* $| $+ $: < ? $&{client_name} > $3 +dnl no r flag: relay to local user (only local part) +# no qualified recipient required +R$* $| $+ $@ RELAYTOLOCAL +dnl client_name is empty +R $+ $@ RELAYTOLOCAL +dnl client_name is local +R $+ $@ RELAYTOLOCAL +dnl client_name is not local +R $+ $#error $@ 5.5.4 $: "553 Domain name required"', `dnl +dnl no qualified recipient required +R $+ $@ RELAYTOLOCAL') +dnl it is a remote user: remove mark and then check client +R<$+> $* $: $2 +dnl currently the recipient address is not used below + +# anything originating locally is ok +# check IP address +R$* $: $&{client_addr} +R$@ $@ RELAYFROM originated locally +R0 $@ RELAYFROM originated locally +R$=R $* $@ RELAYFROM relayable IP address +ifdef(`_ACCESS_TABLE_', `dnl +R$* $: $>LookUpAddress <$1> <$1> <+Connect> +R $* $@ RELAYFROM relayable IP address +R<$*> <$*> $: $2', `dnl') +R$* $: [ $1 ] put brackets around it... +R$=w $@ RELAYFROM ... and see if it is local + +ifdef(`_RELAY_DB_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl +ifdef(`_RELAY_LOCAL_FROM_', `define(`_RELAY_MAIL_FROM_', `1')')dnl +ifdef(`_RELAY_MAIL_FROM_', `dnl +dnl input: {client_addr} or something "broken" +dnl just throw the input away; we do not need it. +# check whether FROM is allowed to use system as relay +R$* $: $>CanonAddr $&f +ifdef(`_RELAY_LOCAL_FROM_', `dnl +# check whether local FROM is ok +R $+ < @ $=w . > $@ RELAYFROMMAIL FROM local', `dnl') +ifdef(`_RELAY_DB_FROM_', `dnl +R $+ < @ $+ . > $1 < @ $2 > remove trailing dot +R $+ < @ $+ > $: $1 < @ $2 > $| $>SearchList $| ifdef(`_RELAY_DB_FROM_DOMAIN_', `') <> +R$* $@ RELAYFROMMAIL RELAY FROM sender ok', `dnl +ifdef(`_RELAY_DB_FROM_DOMAIN_', `errprint(`*** ERROR: _RELAY_DB_FROM_DOMAIN_ requires _RELAY_DB_FROM_ +')', +`dnl') +dnl')', `dnl') + +# check client name: first: did it resolve? +dnl input: ignored +R$* $: < $&{client_resolve} > +R $#error $@ 4.7.1 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name} +R $#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name} +dnl ${client_resolve} should be OK, so go ahead +R$* $: $&{client_name} +dnl should not be necessary since it has been done for client_addr already +R $@ RELAYFROM +ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl +R $* $=m $@ RELAYFROM', `dnl') +R $=w $@ RELAYFROM +ifdef(`_RELAY_HOSTS_ONLY_', +`R $=R $@ RELAYFROM +ifdef(`_ACCESS_TABLE_', `dnl +R $* $: <$(access Connect:$1 $: ? $)> <$1> +R <$*> $: <$(access $1 $: ? $)> <$1>',`dnl')', +`R $* $=R $@ RELAYFROM +ifdef(`_ACCESS_TABLE_', `dnl +R $* $: $>LookUpDomain <$1> <$1> <+Connect>',`dnl')') +ifdef(`_ACCESS_TABLE_', `dnl +R $* $@ RELAYFROM +R<$*> <$*> $: $2',`dnl') + +# anything else is bogus +R$* $#error $@ 5.7.1 $: confRELAY_MSG +divert(0) +ifdef(`_DELAY_CHECKS_',`dnl +# turn a canonical address in the form user<@domain> +# qualify unqual. addresses with $j +dnl it might have been only user (without <@domain>) +SFullAddr +R$* <@ $+ . > $1 <@ $2 > +R$* <@ $* > $@ $1 <@ $2 > +R$+ $@ $1 <@ $j > + +# call all necessary rulesets +Scheck_rcpt +dnl this test should be in the Basic_check_rcpt ruleset +dnl which is the correct DSN code? +# R$@ $#error $@ 5.1.3 $: "553 Recipient address required" +R$+ $: $1 $| $>checkrcpt $1 +dnl now we can simply stop checks by returning "$# xyz" instead of just "ok" +R$+ $| $#$* $#$2 +R$+ $| $* $: $>FullAddr $>CanonAddr $1 +ifdef(`_SPAM_FH_', +`dnl lookup user@ and user@address +ifdef(`_ACCESS_TABLE_', `', +`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db') +')')dnl +dnl one of the next two rules is supposed to match +dnl this code has been copied from BLACKLIST... etc +dnl and simplified by omitting some < >. +R $+ < @ $=w > $: <> $1 < @ $2 > $| +R $+ < @ $* > $: <> $1 < @ $2 > $| +dnl R $@ something_is_very_wrong_here +# lookup the addresses only with To tag +R<> $* $| <$+> $: <@> $1 $| $>SearchList $| <$2> <> +R<@> $* $| $* $: $2 $1 reverse result +dnl', `dnl') +ifdef(`_SPAM_FRIEND_', +`# is the recipient a spam friend? +ifdef(`_SPAM_HATER_', + `errprint(`*** ERROR: define either SpamHater or SpamFriend +')', `dnl') +R $+ $@ SPAMFRIEND +R<$*> $+ $: $2', +`dnl') +ifdef(`_SPAM_HATER_', +`# is the recipient no spam hater? +R $+ $: $1 spam hater: continue checks +R<$*> $+ $@ NOSPAMHATER everyone else: stop +dnl',`dnl') +dnl run further checks: check_mail +dnl should we "clean up" $&f? +R$* $: $1 $| $>checkmail <$&f> +R$* $| $#$* $#$2 +dnl run further checks: check_relay +R$* $: $1 $| $>checkrelay $&{client_name} $| $&{client_addr} +R$* $| $#$* $#$2 +R$* $| $* $: $1 +', `dnl') +ifdef(`_ACCESS_TABLE_', `dnl +###################################################################### +### SearchList: search a list of items in the access map +### Parameters: +### $| ... <> +dnl maybe we should have a @ (again) in front of the mark to +dnl avoid errorneous matches (with error messages?) +dnl if we can make sure that tag is always a single token +dnl then we can omit the delimiter $|, otherwise we need it +dnl to avoid errorneous matchs (first rule: H: if there +dnl is that mark somewhere in the list, it will be taken). +dnl moreover, we can do some tricks to enforce lookup with +dnl the tag only, e.g.: +### where "exact" is either "+" or "!": +### <+ TAG> lookup with and w/o tag +### lookup with tag +dnl Warning: + and ! should be in OperatorChars (otherwise there must be +dnl a blank between them and the tag. +### possible values for "mark" are: +### H: recursive host lookup (LookUpDomain) +dnl A: recursive address lookup (LookUpAddress) [not yet required] +### E: exact lookup, no modifications +### F: full lookup, try user+ext@domain and user@domain +### U: user lookup, try user+ext and user (input must have trailing @) +### return: or (not found) +###################################################################### + +SSearchList +# if it is H: do lookup? +R<$+> $| <$*> $: <$1> $| <@> $>LookUpDomain <$2> <$3> <$1> +R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> +dnl A: NOT YET REQUIRED +dnl R<$+> $| <$*> $: <$1> $| <@> $>LookUpAddress <$2> <$3> <$1> +dnl R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> +dnl lookup of the item with tag +dnl this applies to F: U: E: +R<$- $-> $| <$-:$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$4 $: $3:$4 $)> <$5> +dnl no match, try without tag +R<+ $-> $| <$-:$+> <$*> $: <+ $1> $| <$(access $3 $: $2:$3 $)> <$4> +dnl do we really have to distinguish these cases? +dnl probably yes, there might be a + in the domain part (is that allowed?) +dnl user+detail lookups: should it be: +dnl user+detail, user+*, user; just like aliases? +R<$- $-> $| <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@$5 $: F:$3 + $4@$5$)> <$6> +R<+ $-> $| <$*> $: <+ $1> $| <$(access $2@$4 $: F:$2 + $3@$4$)> <$5> +dnl user lookups are always with trailing @ +dnl do not remove the @ from the lookup: +dnl it is part of the +detail@ which is omitted for the lookup +R<$- $-> $| <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@ $: U:$3 + $4$)> <$5> +R<+ $-> $| <$*> $: <+ $1> $| <$(access $2@ $: U:$2 + $3$)> <$4> +dnl special case for ERROR because this matches the input mark:address +R<$+> $| <> $@ +dnl no match, try rest of list +R<$+> $| <$-:$+> <$+> $@ $>SearchList <$1> $| <$4> +dnl no match, list empty: return failure +R<$+> $| <$-:$+> <> $@ +dnl got result, return it +R<$+> $| <$+> <$*> $@ <$2> +dnl return result from recursive invocation +R<$+> $| <$+> $@ <$2>', `dnl') + +# is user trusted to authenticate as someone else? +dnl AUTH= parameter from MAIL command +Strust_auth +R$* $: $&{auth_type} $| $1 +# required by RFC 2554 section 4. +R$@ $| $* $#error $@ 5.7.1 $: "550 not authenticated" +dnl seems to be useful... +R$* $| $&{auth_authen} $@ identical +R$* $| <$&{auth_authen}> $@ identical +dnl call user supplied code +R$* $| $* $: $1 $| $>"Local_trust_auth" $1 +R$* $| $#$* $#$2 +dnl default: error +R$* $#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author} + +dnl empty ruleset definition so it can be called +SLocal_trust_auth + +undivert(9)dnl LOCAL_RULESETS +ifdef(`_FFR_MILTER', ` +# +###################################################################### +###################################################################### +##### +`##### MAIL FILTER DEFINITIONS' +##### +###################################################################### +###################################################################### +_MAIL_FILTERS_') +# +###################################################################### +###################################################################### +##### +`##### MAILER DEFINITIONS' +##### +###################################################################### +###################################################################### +undivert(7)dnl MAILER_DEFINITIONS diff --git a/gnu/usr.sbin/sendmail/cf/m4/version.m4 b/gnu/usr.sbin/sendmail/cf/m4/version.m4 new file mode 100644 index 00000000000..b697d135b66 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/m4/version.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +VERSIONID(`$Sendmail: version.m4,v 8.34 2000/03/06 19:01:11 gshapiro Exp $') +# +divert(0) +# Configuration version number +DZ8.10.0`'ifdef(`confCF_VERSION', `/confCF_VERSION') diff --git a/gnu/usr.sbin/sendmail/cf/mailer/cyrus.m4 b/gnu/usr.sbin/sendmail/cf/mailer/cyrus.m4 new file mode 100644 index 00000000000..384d26a798a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/cyrus.m4 @@ -0,0 +1,62 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# This code incorporates code from Carnegie Mellon University, whose +# copyright notice and conditions of redistribution are as follows: +# +#*************************************************************************** +# (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 . +# + +ifdef(`_MAILER_local_', `', + `errprint(`*** MAILER(`local') must appear before MAILER(`cyrus')')')dnl + +_DEFIFNOT(`CYRUS_MAILER_FLAGS', `Ah5@/:|') +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_MAILER_USER',, `define(`CYRUS_MAILER_USER', `cyrus:mail')') +_DEFIFNOT(`CYRUS_BB_MAILER_FLAGS', `u') +ifdef(`CYRUS_BB_MAILER_ARGS',, `define(`CYRUS_BB_MAILER_ARGS', `deliver -e -m $u')') + +POPDIVERT + +################################################## +### Cyrus Mailer specification ### +################################################## + +VERSIONID(`$Sendmail: cyrus.m4,v 8.21 1999/10/18 04:57:52 gshapiro Exp $ (Carnegie Mellon)') + +Mcyrus, P=CYRUS_MAILER_PATH, F=_MODMF_(CONCAT(`lsDFMnPq', CYRUS_MAILER_FLAGS), `CYRUS'), S=EnvFromL, R=EnvToL/HdrToL, + ifdef(`CYRUS_MAILER_MAX', `M=CYRUS_MAILER_MAX, ')U=CYRUS_MAILER_USER, T=DNS/RFC822/X-Unix, + A=CYRUS_MAILER_ARGS + +Mcyrusbb, P=CYRUS_MAILER_PATH, F=_MODMF_(CONCAT(`lsDFMnP', CYRUS_BB_MAILER_FLAGS), `CYRUS'), S=EnvFromL, R=EnvToL/HdrToL, + ifdef(`CYRUS_MAILER_MAX', `M=CYRUS_MAILER_MAX, ')U=CYRUS_MAILER_USER, T=DNS/RFC822/X-Unix, + A=CYRUS_BB_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/fax.m4 b/gnu/usr.sbin/sendmail/cf/mailer/fax.m4 new file mode 100644 index 00000000000..c1aecce2536 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/fax.m4 @@ -0,0 +1,37 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# This assumes you already have Sam Leffler's HylaFAX software. +# +# Tested with HylaFAX 4.0pl1 +# + +ifdef(`FAX_MAILER_ARGS',, + `define(`FAX_MAILER_ARGS', faxmail -d $u@$h $f)') +ifdef(`FAX_MAILER_PATH',, + `define(`FAX_MAILER_PATH', /usr/local/bin/faxmail)') +ifdef(`FAX_MAILER_MAX',, + `define(`FAX_MAILER_MAX', 100000)') +POPDIVERT +#################################### +### FAX Mailer specification ### +#################################### + +VERSIONID(`$Sendmail: fax.m4,v 8.15 1999/10/18 04:57:53 gshapiro Exp $') + +Mfax, P=FAX_MAILER_PATH, F=DFMhu, S=14, R=24, + M=FAX_MAILER_MAX, T=X-Phone/X-FAX/X-Unix, + A=FAX_MAILER_ARGS + +LOCAL_CONFIG +CPFAX diff --git a/gnu/usr.sbin/sendmail/cf/mailer/local.m4 b/gnu/usr.sbin/sendmail/cf/mailer/local.m4 new file mode 100644 index 00000000000..80789444f0a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/local.m4 @@ -0,0 +1,85 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +_DEFIFNOT(`_DEF_LOCAL_MAILER_FLAGS', `lsDFMAw5:/|@q') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Prmn9') +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/mail)') +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -d $u')') +ifdef(`LOCAL_MAILER_DSN_DIAGNOSTIC_CODE',, `define(`LOCAL_MAILER_DSN_DIAGNOSTIC_CODE', `X-Unix')') +_DEFIFNOT(`_DEF_LOCAL_SHELL_FLAGS', `lsDFMoq') +_DEFIFNOT(`LOCAL_SHELL_FLAGS', `eu9') +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(`$Sendmail: local.m4,v 8.50 1999/11/21 19:02:08 ca Exp $') + +# +# Envelope sender rewriting +# +SEnvFromL=10 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqEnv $1 do masquerading + +# +# Envelope recipient rewriting +# +SEnvToL=20 +R$+ < @ $* > $: $1 strip host part +ifdef(`_FFR_ADDR_TYPE', `dnl +ifdef(`confUSERDB_SPEC', `dnl', +`dnl Do not forget to bump V9 to V10 before removing _FFR_ADDR_TYPE check +R$+ + $* $: < $&{addr_type} > $1 + $2 mark with addr type +R $+ + $* $: $1 remove +detail for sender +R< $* > $+ $: $2 else remove mark')', `dnl') + +# +# Header sender rewriting +# +SHdrFromL=30 +R<@> $n errors to mailer-daemon +R@ <@ $*> $n temporarily bypass Sun bogosity +R$+ $: $>AddDomain $1 add local domain if needed +R$* $: $>MasqHdr $1 do masquerading + +# +# Header recipient rewriting +# +SHdrToL=40 +R$+ $: $>AddDomain $1 add local domain if needed +ifdef(`_ALL_MASQUERADE_', +`R$* $: $>MasqHdr $1 do all-masquerading', +`R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2') + +# +# Common code to add local domain name (only if always-add-domain) +# +SAddDomain=50 +ifdef(`_ALWAYS_ADD_DOMAIN_', `dnl +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification', +`dnl') + +Mlocal, P=LOCAL_MAILER_PATH, F=_MODMF_(CONCAT(_DEF_LOCAL_MAILER_FLAGS, LOCAL_MAILER_FLAGS), `LOCAL'), S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,_OPTINS(`LOCAL_MAILER_EOL', ` E=', `, ') + _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')_OPTINS(`LOCAL_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`LOCAL_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/LOCAL_MAILER_DSN_DIAGNOSTIC_CODE, + A=LOCAL_MAILER_ARGS +Mprog, P=LOCAL_SHELL_PATH, F=CONCAT(_DEF_LOCAL_SHELL_FLAGS, LOCAL_SHELL_FLAGS), S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=LOCAL_SHELL_DIR, + _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')T=X-Unix/X-Unix/X-Unix, + A=LOCAL_SHELL_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/mail11.m4 b/gnu/usr.sbin/sendmail/cf/mailer/mail11.m4 new file mode 100644 index 00000000000..54261dfd470 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/mail11.m4 @@ -0,0 +1,60 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# 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)') +_DEFIFNOT(`MAIL11_MAILER_FLAGS', `nsFx') +ifdef(`MAIL11_MAILER_ARGS',, `define(`MAIL11_MAILER_ARGS', mail11 $g $x $h $u)') +define(`_USE_DECNET_SYNTAX_') +define(`_LOCAL_', ifdef(`confLOCAL_MAILER', confLOCAL_MAILER, `local')) + +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(`$Sendmail: mail11.m4,v 8.19 1999/10/18 04:57:54 gshapiro Exp $') + +SMail11From=15 +R$+ $: $>25 $1 preprocess +R$w :: $+ $@ $w :: $1 ready to go + +SMail11To=25 +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 + +Mmail11, P=MAIL11_MAILER_PATH, F=_MODMF_(MAIL11_MAILER_FLAGS, `MAIL11'), S=Mail11From, R=Mail11To, + T=DNS/X-DECnet/X-Unix, + A=MAIL11_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/phquery.m4 b/gnu/usr.sbin/sendmail/cf/mailer/phquery.m4 new file mode 100644 index 00000000000..3d1263aedab --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/phquery.m4 @@ -0,0 +1,34 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Contributed by Kimmo Suominen . +# + +ifdef(`_MAILER_local_', `', + `errprint(`*** MAILER(`local') must appear before MAILER(`phquery')')')dnl + +ifdef(`PH_MAILER_PATH',, `define(`PH_MAILER_PATH', /usr/local/etc/phquery)') +_DEFIFNOT(`PH_MAILER_FLAGS', `ehmu') +ifdef(`PH_MAILER_ARGS',, `define(`PH_MAILER_ARGS', `phquery -- $u')') + +POPDIVERT + +#################################### +### PH Mailer specification ### +#################################### + +VERSIONID(`$Sendmail: phquery.m4,v 8.15 1999/10/18 04:57:54 gshapiro Exp $') + +Mph, P=PH_MAILER_PATH, F=_MODMF_(CONCAT(`nrDFM', PH_MAILER_FLAGS), `PH'), S=EnvFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=PH_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/pop.m4 b/gnu/usr.sbin/sendmail/cf/mailer/pop.m4 new file mode 100644 index 00000000000..2c286406b81 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/pop.m4 @@ -0,0 +1,36 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +ifdef(`_MAILER_local_', `', + `errprint(`*** MAILER(`local') must appear before MAILER(`pop')')')dnl + +ifdef(`POP_MAILER_PATH',, `define(`POP_MAILER_PATH', /usr/lib/mh/spop)') +_DEFIFNOT(`POP_MAILER_FLAGS', `Penu') +ifdef(`POP_MAILER_ARGS',, `define(`POP_MAILER_ARGS', `pop $u')') + +POPDIVERT + +#################################### +### POP Mailer specification ### +#################################### + +VERSIONID(`$Sendmail: pop.m4,v 8.20 1999/10/18 04:57:54 gshapiro Exp $') + +Mpop, P=POP_MAILER_PATH, F=_MODMF_(CONCAT(`lsDFMq', POP_MAILER_FLAGS), `POP'), S=EnvFromL, R=EnvToL/HdrToL, + T=DNS/RFC822/X-Unix, + A=POP_MAILER_ARGS + +LOCAL_CONFIG +# POP mailer is a pseudo-domain +CPPOP diff --git a/gnu/usr.sbin/sendmail/cf/mailer/procmail.m4 b/gnu/usr.sbin/sendmail/cf/mailer/procmail.m4 new file mode 100644 index 00000000000..b523be61765 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/procmail.m4 @@ -0,0 +1,36 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +ifdef(`_MAILER_smtp_', `', + `errprint(`*** MAILER(`smtp') must appear before MAILER(`procmail')')')dnl + +ifdef(`PROCMAIL_MAILER_PATH',, + `ifdef(`PROCMAIL_PATH', + `define(`PROCMAIL_MAILER_PATH', PROCMAIL_PATH)', + `define(`PROCMAIL_MAILER_PATH', /usr/local/bin/procmail)')') +_DEFIFNOT(`PROCMAIL_MAILER_FLAGS', `SPhnu9') +ifdef(`PROCMAIL_MAILER_ARGS',, + `define(`PROCMAIL_MAILER_ARGS', `procmail -Y -m $h $f $u')') + +POPDIVERT + +######################*****############## +### PROCMAIL Mailer specification ### +##################*****################## + +VERSIONID(`$Sendmail: procmail.m4,v 8.20 1999/10/18 04:57:54 gshapiro Exp $') + +Mprocmail, P=PROCMAIL_MAILER_PATH, F=_MODMF_(CONCAT(`DFM', PROCMAIL_MAILER_FLAGS), `PROCMAIL'), S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP/HdrFromSMTP, + ifdef(`PROCMAIL_MAILER_MAX', `M=PROCMAIL_MAILER_MAX, ')T=DNS/RFC822/X-Unix, + A=PROCMAIL_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/qpage.m4 b/gnu/usr.sbin/sendmail/cf/mailer/qpage.m4 new file mode 100644 index 00000000000..4bea89e6ae0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/qpage.m4 @@ -0,0 +1,30 @@ +PUSHDIVERT(-1) +# +# Copyright (C) 1997, Philip A. Prindeville and Enteka Enterprise Technology +# Services +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# Tested with QuickPage version 3.2 +# +ifdef(`QPAGE_MAILER_PATH', `', `define(`QPAGE_MAILER_PATH', `/usr/local/bin/qpage')') +_DEFIFNOT(`QPAGE_MAILER_FLAGS', `mDFMs') +ifdef(`QPAGE_MAILER_ARGS', `', `define(`QPAGE_MAILER_ARGS', `qpage -l0 -m -P$u')') +ifdef(`QPAGE_MAILER_MAX', `', `define(`QPAGE_MAILER_MAX', `4096')') + +POPDIVERT + +###################################### +### QPAGE Mailer specification ### +###################################### + +VERSIONID(`$Sendmail: qpage.m4,v 8.9 1999/11/16 03:33:04 gshapiro Exp $') + +Mqpage, P=QPAGE_MAILER_PATH, F=_MODMF_(QPAGE_MAILER_FLAGS, `QPAGE'), + M=QPAGE_MAILER_MAX, T=DNS/RFC822/X-Unix, + A=QPAGE_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 b/gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 new file mode 100644 index 00000000000..6f9de7d5d20 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 @@ -0,0 +1,117 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +_DEFIFNOT(`_DEF_SMTP_MAILER_FLAGS', `mDFMuX') +_DEFIFNOT(`SMTP_MAILER_FLAGS',`') +_DEFIFNOT(`RELAY_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(`DSMTP_MAILER_ARGS',, `define(`DSMTP_MAILER_ARGS', `IPC $h')') +ifdef(`RELAY_MAILER_ARGS',, `define(`RELAY_MAILER_ARGS', `IPC $h')') +POPDIVERT +##################################### +### SMTP Mailer specification ### +##################################### + +VERSIONID(`$Sendmail: smtp.m4,v 8.55 1999/09/21 20:26:18 ca Exp $') + +# +# common sender and masquerading recipient rewriting +# +SMasqSMTP=61 +R$* < @ $* > $* $@ $1 < @ $2 > $3 already fully qualified +R$+ $@ $1 < @ *LOCAL* > add local qualification + +# +# convert pseudo-domain addresses to real domain addresses +# +SPseudoToReal=51 + +# pass s through +R< @ $+ > $* $@ < @ $1 > $2 resolve + +# 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 < @ $Y > use UUCP_RELAY +R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part +R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY') + + +# +# envelope sender rewriting +# +SEnvFromSMTP=11 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$* :; <@> $@ list:; special case +R$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqEnv $1 do masquerading + + +# +# envelope recipient rewriting -- +# also header recipient if not masquerading recipients +# +SEnvToSMTP=21 +R$+ $: $>PseudoToReal $1 sender/recipient common +R$+ $: $>MasqSMTP $1 qualify unqual'ed names +R$* < @ *LOCAL* > $* $: $1 < @ $j . > $2 + +# +# header sender and masquerading header recipient rewriting +# +SHdrFromSMTP=31 +R$+ $: $>PseudoToReal $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$* $: $>MasqSMTP $1 qualify unqual'ed names +R$+ $: $>MasqHdr $1 do masquerading + + +# +# relay mailer header masquerading recipient rewriting +# +SMasqRelay=71 +R$+ $: $>MasqSMTP $1 +R$+ $: $>MasqHdr $1 + +Msmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, + A=SMTP_MAILER_ARGS +Mesmtp, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, + A=ESMTP_MAILER_ARGS +Msmtp8, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `8', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, + A=SMTP8_MAILER_ARGS +Mdsmtp, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a%', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, + A=DSMTP_MAILER_ARGS +Mrelay, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a8', RELAY_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `MasqSMTP/MasqRelay', `MasqSMTP'), E=\r\n, L=2040, + _OPTINS(`RELAY_MAILER_CHARSET', `C=', `, ')_OPTINS(`RELAY_MAILER_MAXMSGS', `m=', `, ')T=DNS/RFC822/SMTP, + A=RELAY_MAILER_ARGS diff --git a/gnu/usr.sbin/sendmail/cf/mailer/usenet.m4 b/gnu/usr.sbin/sendmail/cf/mailer/usenet.m4 new file mode 100644 index 00000000000..6c0c13833a0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/usenet.m4 @@ -0,0 +1,30 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +ifdef(`_MAILER_local_', `', + `errprint(`*** MAILER(`local') must appear before MAILER(`usenet')')')dnl + +ifdef(`USENET_MAILER_PATH',, `define(`USENET_MAILER_PATH', /usr/lib/news/inews)') +_DEFIFNOT(`USENET_MAILER_FLAGS', `rsDFMmn') +ifdef(`USENET_MAILER_ARGS',, `define(`USENET_MAILER_ARGS', `inews -m -h -n')') +POPDIVERT +#################################### +### USENET Mailer specification ### +#################################### + +VERSIONID(`$Sendmail: usenet.m4,v 8.19 1999/11/16 03:33:04 gshapiro Exp $') + +Musenet, P=USENET_MAILER_PATH, F=_MODMF_(USENET_MAILER_FLAGS, `USENET'), S=EnvFromL, R=EnvToL, + _OPTINS(`USENET_MAILER_MAX', `M=', `, ')T=X-Usenet/X-Usenet/X-Unix, + A=USENET_MAILER_ARGS $u diff --git a/gnu/usr.sbin/sendmail/cf/mailer/uucp.m4 b/gnu/usr.sbin/sendmail/cf/mailer/uucp.m4 new file mode 100644 index 00000000000..9ea08b3a3d4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/mailer/uucp.m4 @@ -0,0 +1,156 @@ +PUSHDIVERT(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +ifdef(`_MAILER_smtp_', `', + `errprint(`*** MAILER(`smtp') must appear before MAILER(`uucp')')')dnl + +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)')') +_DEFIFNOT(`UUCP_MAILER_FLAGS', `') +ifdef(`UUCP_MAILER_MAX',, + `define(`UUCP_MAILER_MAX', + `ifdef(`UUCP_MAX_SIZE', `UUCP_MAX_SIZE', 100000)')') +POPDIVERT +##################################### +### UUCP Mailer specification ### +##################################### + +VERSIONID(`$Sendmail: uucp.m4,v 8.38 1999/10/18 04:57:55 gshapiro Exp $') + +# +# envelope and header sender rewriting +# +SFromU=12 + +# 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 +# +SEnvToU=22 + +# list:; 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 + +# +# header recipient rewriting +# +SHdrToU=42 + +# 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 + + +ifdef(`_MAILER_smtp_', +`# +# envelope sender rewriting for uucp-dom mailer +# +SEnvFromUD=52 + +# handle error address as a special case +R<@> $n errors to mailer-daemon + +# pass everything to standard SMTP mailer rewriting +R$* $@ $>EnvFromSMTP $1 + +# +# envelope sender rewriting for uucp-uudom mailer +# +SEnvFromUUD=72 + +# handle error address as a special case +R<@> $n errors to mailer-daemon + +# do standard SMTP mailer rewriting +R$* $: $>EnvFromSMTP $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 + +# +# There are innumerable variations on the UUCP mailer. It really +# is rather absurd. +# + +# old UUCP mailer (two names) +Muucp, P=UUCP_MAILER_PATH, F=_MODMF_(CONCAT(`DFMhuUd', UUCP_MAILER_FLAGS), `UUCP'), S=FromU, R=EnvToU/HdrToU, + 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=_MODMF_(CONCAT(`DFMhuUd', UUCP_MAILER_FLAGS), `UUCP'), S=FromU, R=EnvToU/HdrToU, + 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=_MODMF_(CONCAT(`mDFMhuUd', UUCP_MAILER_FLAGS), `UUCP'), S=FromU, R=EnvToU/HdrToU, + 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=_MODMF_(CONCAT(`mDFMhuUd', UUCP_MAILER_FLAGS), `UUCP'), S=FromU, R=EnvToU/HdrToU, + 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=_MODMF_(CONCAT(`mDFMhud', UUCP_MAILER_FLAGS), `UUCP'), S=EnvFromUD/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), + 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=_MODMF_(CONCAT(`mDFMhud', UUCP_MAILER_FLAGS), `UUCP'), S=EnvFromUUD/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), + M=UUCP_MAILER_MAX, _OPTINS(`UUCP_MAILER_CHARSET', `C=', `, ')T=X-UUCP/X-UUCP/X-Unix, + A=UUCP_MAILER_ARGS') + + diff --git a/gnu/usr.sbin/sendmail/cf/ostype/aix2.m4 b/gnu/usr.sbin/sendmail/cf/ostype/aix2.m4 new file mode 100644 index 00000000000..5b994fb2479 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/aix2.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: aix2.m4,v 8.12 1999/04/12 17:34:36 ca Exp $') +define(`LOCAL_MAILER_PATH', /bin/bellmail)dnl +define(`LOCAL_MAILER_ARGS', mail $u)dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +define(`confEBINDIR', `/usr/lib')dnl +define(`confTIME_ZONE', `USE_TZ')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/aix3.m4 b/gnu/usr.sbin/sendmail/cf/ostype/aix3.m4 new file mode 100644 index 00000000000..bc1a989099f --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/aix3.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: aix3.m4,v 8.16 1999/04/12 17:34:36 ca Exp $') +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/bellmail)')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', mail $u)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +define(`confEBINDIR', `/usr/lib')dnl +define(`confTIME_ZONE', `USE_TZ')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/aix4.m4 b/gnu/usr.sbin/sendmail/cf/ostype/aix4.m4 new file mode 100644 index 00000000000..83a6983ec94 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/aix4.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1996 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: aix4.m4,v 8.11 1999/04/12 17:34:37 ca Exp $') +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/bellmail)')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', mail -F $g $u)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +define(`confEBINDIR', `/usr/lib')dnl +define(`confTIME_ZONE', `USE_TZ')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/altos.m4 b/gnu/usr.sbin/sendmail/cf/ostype/altos.m4 new file mode 100644 index 00000000000..f4aecaa69cd --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/altos.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1996 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Contributed by Tim Rice . +# + +divert(0) +VERSIONID(`$Sendmail: altos.m4,v 8.15 1999/04/24 05:37:40 gshapiro Exp $') + +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')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 +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mPuhCE9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `lmail $u')')dnl +ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', Peu)')dnl +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4 b/gnu/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4 new file mode 100644 index 00000000000..b15b2686ff9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/amdahl-uts.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: amdahl-uts.m4,v 8.16 1999/04/24 05:37:40 gshapiro Exp $') +divert(-1) + +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `fSn9') +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/aux.m4 b/gnu/usr.sbin/sendmail/cf/ostype/aux.m4 new file mode 100644 index 00000000000..ada4e664685 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/aux.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: aux.m4,v 8.16 1999/04/24 05:37:40 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -d -r $f $u')')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/bsd4.3.m4 b/gnu/usr.sbin/sendmail/cf/ostype/bsd4.3.m4 new file mode 100644 index 00000000000..6377d619e2e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/bsd4.3.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bsd4.3.m4,v 8.12 1999/02/07 07:26:18 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/ostype/bsd4.4.m4 b/gnu/usr.sbin/sendmail/cf/ostype/bsd4.4.m4 new file mode 100644 index 00000000000..e1f315b3dac --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/bsd4.4.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# + +divert(0) +VERSIONID(`$Sendmail: bsd4.4.m4,v 8.14 1999/04/24 05:37:40 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/ostype/bsdi.m4 b/gnu/usr.sbin/sendmail/cf/ostype/bsdi.m4 new file mode 100644 index 00000000000..36a31fe1b8e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/bsdi.m4 @@ -0,0 +1,17 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bsdi.m4,v 8.1 1999/11/19 05:18:13 gshapiro Exp $') +include(_CF_DIR_`'ostype/bsd4.4.m4)dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4 b/gnu/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4 new file mode 100644 index 00000000000..6333f4f7030 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/bsdi1.0.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bsdi1.0.m4,v 8.11 1999/11/19 05:18:14 gshapiro Exp $') +errprint(`NOTE: OSTYPE(bsdi1.0) is deprecated. Use OSTYPE(bsdi) instead.') +include(_CF_DIR_`'ostype/bsdi.m4)dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4 b/gnu/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4 new file mode 100644 index 00000000000..d06f70e5adb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/bsdi2.0.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: bsdi2.0.m4,v 8.10 1999/11/19 05:18:14 gshapiro Exp $') +errprint(`NOTE: OSTYPE(bsdi2.0) is deprecated. Use OSTYPE(bsdi) instead.') +include(_CF_DIR_`'ostype/bsdi.m4)dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/dgux.m4 b/gnu/usr.sbin/sendmail/cf/ostype/dgux.m4 new file mode 100644 index 00000000000..bd2a01c5c9d --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/dgux.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: dgux.m4,v 8.14 1999/04/12 17:34:37 ca Exp $') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `m9')dnl +define(`confTIME_ZONE', `USE_TZ')dnl +define(`confEBINDIR', `/usr/lib')dnl +LOCAL_CONFIG +E_FORCE_MAIL_LOCAL_=yes diff --git a/gnu/usr.sbin/sendmail/cf/ostype/domainos.m4 b/gnu/usr.sbin/sendmail/cf/ostype/domainos.m4 new file mode 100644 index 00000000000..ac4911d1886 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/domainos.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: domainos.m4,v 8.14 1999/04/24 05:37:40 gshapiro Exp $') +divert(-1) + +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)') +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/dynix3.2.m4 b/gnu/usr.sbin/sendmail/cf/ostype/dynix3.2.m4 new file mode 100644 index 00000000000..c8528ecd835 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/dynix3.2.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: dynix3.2.m4,v 8.14 1999/04/24 05:37:41 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/gnu.m4 b/gnu/usr.sbin/sendmail/cf/ostype/gnu.m4 new file mode 100644 index 00000000000..31f7ce89a08 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/gnu.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1997 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# + +divert(0) +VERSIONID(`$Sendmail: gnu.m4,v 8.13 1999/04/24 05:37:41 gshapiro Exp $') +ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/log/sendmail.st')')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /libexec/mail.local)')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail $u')')dnl +define(`confEBINDIR', `/libexec')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/hpux10.m4 b/gnu/usr.sbin/sendmail/cf/ostype/hpux10.m4 new file mode 100644 index 00000000000..53a4171c6cc --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/hpux10.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: hpux10.m4,v 8.19 1999/04/24 05:37:41 gshapiro Exp $') + +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /var/spool/mqueue)')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/bin/rmail)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `m9')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/gnu/usr.sbin/sendmail/cf/ostype/hpux11.m4 b/gnu/usr.sbin/sendmail/cf/ostype/hpux11.m4 new file mode 100644 index 00000000000..389c83c5029 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/hpux11.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: hpux11.m4,v 8.1 1999/11/19 05:22:59 gshapiro Exp $') + +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/bin/rmail)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `m9')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 diff --git a/gnu/usr.sbin/sendmail/cf/ostype/hpux9.m4 b/gnu/usr.sbin/sendmail/cf/ostype/hpux9.m4 new file mode 100644 index 00000000000..1e79f905b82 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/hpux9.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: hpux9.m4,v 8.24 1999/04/24 05:37:41 gshapiro Exp $') + +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', `/bin/rmail')')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `m9')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 +define(`confEBINDIR', `/usr/lib')dnl +dnl +dnl For maximum compability with HP-UX, use: +dnl define(`confME_TOO', True)dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/irix4.m4 b/gnu/usr.sbin/sendmail/cf/ostype/irix4.m4 new file mode 100644 index 00000000000..9ebec78e7d1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/irix4.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: irix4.m4,v 8.19 1999/04/24 05:37:41 gshapiro Exp $') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Ehm9')dnl +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/irix5.m4 b/gnu/usr.sbin/sendmail/cf/ostype/irix5.m4 new file mode 100644 index 00000000000..11842b3b179 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/irix5.m4 @@ -0,0 +1,39 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Contributed by Kari E. Hurtta +# + +# +# 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(`$Sendmail: irix5.m4,v 8.16 1999/04/24 05:37:41 gshapiro Exp $') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Ehmu9')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(`STATUS_FILE',, `define(`STATUS_FILE', `/var/sendmail.st')')dnl +define(`confDEF_USER_ID', `998:998')dnl +define(`confTIME_ZONE', USE_TZ)dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/irix6.m4 b/gnu/usr.sbin/sendmail/cf/ostype/irix6.m4 new file mode 100644 index 00000000000..e8f97b7927a --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/irix6.m4 @@ -0,0 +1,39 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1995 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Contributed by Kari E. Hurtta +# + +# +# Notes: +# - SGI's /etc/sendmail.cf defines also 'u' for local mailer flags -- you +# perhaps don't want it. They have begun removing this flag in IRIX 6.5. +# - 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(`$Sendmail: irix6.m4,v 8.14 1999/08/05 20:35:55 gshapiro Exp $') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Ehmu9')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(`STATUS_FILE',, `define(`STATUS_FILE', `/var/sendmail.st')')dnl +define(`confDEF_USER_ID', `998:998')dnl +define(`confTIME_ZONE', USE_TZ)dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/isc4.1.m4 b/gnu/usr.sbin/sendmail/cf/ostype/isc4.1.m4 new file mode 100644 index 00000000000..9e4eabe4a4c --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/isc4.1.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# + +divert(0) +VERSIONID(`$Sendmail: isc4.1.m4,v 8.16 1999/04/24 05:37:42 gshapiro Exp $') +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `lmail -s $u')')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `humS9')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /bin/lmail)')dnl +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')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 +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/linux.m4 b/gnu/usr.sbin/sendmail/cf/ostype/linux.m4 new file mode 100644 index 00000000000..0fae19223e9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/linux.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: linux.m4,v 8.11 1999/03/12 22:21:25 ca Exp $') +ifdef(`PROCMAIL_MAILER_PATH',, + define(`PROCMAIL_MAILER_PATH', `/usr/bin/procmail')) +FEATURE(local_procmail) diff --git a/gnu/usr.sbin/sendmail/cf/ostype/maxion.m4 b/gnu/usr.sbin/sendmail/cf/ostype/maxion.m4 new file mode 100644 index 00000000000..c37d2f28ed2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/maxion.m4 @@ -0,0 +1,28 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1996 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Concurrent Computer Corporation Maxion system support contributed +# by Donald R. Laster Jr. . +# + +divert(0) +VERSIONID(`$Sendmail: maxion.m4,v 8.17 1999/10/21 00:31:39 gshapiro Exp $') + +define(`QUEUE_DIR', `/var/spool/mqueue')dnl +define(`STATUS_FILE', `/var/adm/log/sendmail.st')dnl +define(`LOCAL_MAILER_PATH', `/usr/bin/mail')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`LOCAL_MAILER_ARGS', `mail $u')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl +define(`confEBINDIR', `/usr/ucblib')dnl +divert(-1) diff --git a/gnu/usr.sbin/sendmail/cf/ostype/mklinux.m4 b/gnu/usr.sbin/sendmail/cf/ostype/mklinux.m4 new file mode 100644 index 00000000000..e19ee8402d1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/mklinux.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# MkLinux support contributed by Paul DuBois +# + +divert(0) +VERSIONID(`$Sendmail: mklinux.m4,v 8.12 1999/04/24 05:37:42 gshapiro Exp $') +ifdef(`STATUS_FILE',, + `define(`STATUS_FILE', `/var/log/sendmail.st')') +ifdef(`PROCMAIL_MAILER_PATH',, + define(`PROCMAIL_MAILER_PATH', `/usr/bin/procmail')) +FEATURE(local_procmail) diff --git a/gnu/usr.sbin/sendmail/cf/ostype/nextstep.m4 b/gnu/usr.sbin/sendmail/cf/ostype/nextstep.m4 new file mode 100644 index 00000000000..6b9ebb5d4e4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/nextstep.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: nextstep.m4,v 8.21 1999/10/21 00:31:40 gshapiro Exp $') +ifdef(`UUCP_MAILER_PATH',, `define(`UUCP_MAILER_PATH', /usr/bin/uux)')dnl +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', `euP')')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/openbsd.m4 b/gnu/usr.sbin/sendmail/cf/ostype/openbsd.m4 new file mode 100644 index 00000000000..6bde621a3e5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/openbsd.m4 @@ -0,0 +1,17 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: openbsd.m4,v 8.3 1999/04/24 05:37:42 gshapiro Exp $') +ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/log/sendmail.st')')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /usr/libexec/mail.local)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `rmn9S')dnl +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -z -a$g $h!rmail ($u)')')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/osf1.m4 b/gnu/usr.sbin/sendmail/cf/ostype/osf1.m4 new file mode 100644 index 00000000000..96a2244c21b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/osf1.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: osf1.m4,v 8.16 1999/10/11 18:45:43 gshapiro Exp $') +ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/usr/adm/sendmail/sendmail.st')')dnl +define(`confDEF_USER_ID', `daemon') +define(`confEBINDIR', `/usr/lbin')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/powerux.m4 b/gnu/usr.sbin/sendmail/cf/ostype/powerux.m4 new file mode 100644 index 00000000000..69eef34e7e1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/powerux.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: powerux.m4,v 8.13 1999/04/24 05:37:43 gshapiro Exp $') + +define(`LOCAL_MAILER_PATH', `/usr/bin/rmail')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `mn9')dnl +define(`LOCAL_MAILER_ARGS', `rmail $u')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl +define(`confEBINDIR', `/usr/local/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/ptx2.m4 b/gnu/usr.sbin/sendmail/cf/ostype/ptx2.m4 new file mode 100644 index 00000000000..508df0da6a7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/ptx2.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1994 Eric P. Allman. All rights reserved. +# Copyright (c) 1994 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +# Support for DYNIX/ptx 2.x. + +divert(0) +VERSIONID(`$Sendmail: ptx2.m4,v 8.17 1999/04/24 05:37:43 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')dnl +define(`LOCAL_MAILER_PATH', `/bin/mail')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `fmn9')dnl +define(`LOCAL_SHELL_FLAGS', `eu')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/qnx.m4 b/gnu/usr.sbin/sendmail/cf/ostype/qnx.m4 new file mode 100644 index 00000000000..ca97a0e611b --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/qnx.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1997 Eric P. Allman. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Contributed by Glen McCready +# + +divert(0) +VERSIONID(`$Sendmail: qnx.m4,v 8.13 1999/04/24 05:37:43 gshapiro Exp $') +define(`QUEUE_DIR', /usr/spool/mqueue)dnl +define(`LOCAL_MAILER_ARGS', `mail $u')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Sh')dnl +define(`LOCAL_MAILER_PATH', /usr/bin/mailx)dnl +define(`UUCP_MAILER_ARGS', `uux - -r -z -a$f $h!rmail ($u)')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/riscos4.5.m4 b/gnu/usr.sbin/sendmail/cf/ostype/riscos4.5.m4 new file mode 100644 index 00000000000..7cc5e60cddb --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/riscos4.5.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: riscos4.5.m4,v 8.15 1999/04/24 05:37:43 gshapiro Exp $') + +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `rmail -d $u')')dnl +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', `/usr/spool/mqueue')')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 b/gnu/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 new file mode 100644 index 00000000000..30da275a7ea --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 @@ -0,0 +1,24 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# SCO UnixWare 2.1.2 ostype file +# +# Contributed by Christopher Durham of SCO. +# +divert(0) +VERSIONID(`$Sendmail: sco-uw-2.1.m4,v 8.13 1999/04/24 05:37:43 gshapiro Exp $') + +define(`LOCAL_MAILER_PATH', `/usr/bin/rmail')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `fhCEn9')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl +define(`LOCAL_MAILER_ARGS',`rmail $u')dnl +define(`confEBINDIR', `/usr/lib')dnl +define(`confTIME_ZONE', `USE_TZ')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/sco3.2.m4 b/gnu/usr.sbin/sendmail/cf/ostype/sco3.2.m4 new file mode 100644 index 00000000000..91c725499db --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/sco3.2.m4 @@ -0,0 +1,23 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: sco3.2.m4,v 8.16 1999/04/24 05:37:43 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /usr/spool/mqueue)')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 +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `PuhCE9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `lmail $u')')dnl +ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', Peu)')dnl +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/sinix.m4 b/gnu/usr.sbin/sendmail/cf/ostype/sinix.m4 new file mode 100644 index 00000000000..60e7954e6d3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/sinix.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1996 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: sinix.m4,v 8.13 1999/04/24 05:37:43 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /var/spool/mqueue)')dnl +define(`LOCAL_MAILER_PATH', `/bin/mail.local')dnl +ifdef(`STATUS_FILE',, `define(`STATUS_FILE', `/var/sendmail.st')')dnl +define(`confEBINDIR', `/usr/ucblib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/solaris2.m4 b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.m4 new file mode 100644 index 00000000000..5cac8fd5043 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# This ostype file is suitable for use on Solaris 2.x systems that +# have mail.local installed. It is my understanding that this is +# standard as of Solaris 2.5. +# + +divert(0) +VERSIONID(`$Sendmail: solaris2.m4,v 8.22 1999/09/24 21:43:53 ca Exp $') +divert(-1) + +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', `/usr/lib/mail.local')') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `fSmn9') +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail.local -d $u')') +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')') +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/solaris2.ml.m4 b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.ml.m4 new file mode 100644 index 00000000000..886499dc4e0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.ml.m4 @@ -0,0 +1,27 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# This ostype file is suitable for use on Solaris 2.x systems that +# have mail.local installed. It is my understanding that this is +# standard as of Solaris 2.5. +# + +divert(0) +VERSIONID(`$Sendmail: solaris2.ml.m4,v 8.14 1999/04/24 05:37:44 gshapiro Exp $') +divert(-1) + +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', `/usr/lib/mail.local')') +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `fSmn9') +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail.local -d $u')') +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')') +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/solaris2.pre5.m4 b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.pre5.m4 new file mode 100644 index 00000000000..eafaa20ad8d --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/solaris2.pre5.m4 @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# This ostype file is suitable for use on Solaris 2.x systems that +# use mail as local mailer which are usually version before 2.5. +# + + +divert(0) +VERSIONID(`$Sendmail: solaris2.pre5.m4,v 1.1 1999/09/25 01:17:44 ca Exp $') +divert(-1) + +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `SnE9') +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `mail -f $g -d $u')') +ifdef(`UUCP_MAILER_ARGS',, `define(`UUCP_MAILER_ARGS', `uux - -r -a$g $h!rmail ($u)')') +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/sunos3.5.m4 b/gnu/usr.sbin/sendmail/cf/ostype/sunos3.5.m4 new file mode 100644 index 00000000000..6797322591d --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/sunos3.5.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: sunos3.5.m4,v 8.10 1999/02/07 07:26:23 gshapiro Exp $') + +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/sunos4.1.m4 b/gnu/usr.sbin/sendmail/cf/ostype/sunos4.1.m4 new file mode 100644 index 00000000000..f08abc97d4f --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/sunos4.1.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: sunos4.1.m4,v 8.10 1999/02/07 07:26:24 gshapiro Exp $') + +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/svr4.m4 b/gnu/usr.sbin/sendmail/cf/ostype/svr4.m4 new file mode 100644 index 00000000000..9cb6986f0da --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/svr4.m4 @@ -0,0 +1,21 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: svr4.m4,v 8.17 1999/10/21 00:31:41 gshapiro Exp $') + +define(`LOCAL_MAILER_PATH', `/usr/ucblib/binmail')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl +define(`confEBINDIR', `/usr/ucblib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/ultrix4.m4 b/gnu/usr.sbin/sendmail/cf/ostype/ultrix4.m4 new file mode 100644 index 00000000000..5c310feac78 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/ultrix4.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: ultrix4.m4,v 8.11 1999/02/07 07:26:24 gshapiro Exp $') + +define(`confEBINDIR', `/usr/lib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/unixware7.m4 b/gnu/usr.sbin/sendmail/cf/ostype/unixware7.m4 new file mode 100644 index 00000000000..2cae7bb51cf --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/unixware7.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: unixware7.m4,v 8.8 2000/02/26 01:32:04 gshapiro Exp $') +ifdef(`QUEUE_DIR',, `define(`QUEUE_DIR', /var/spool/mqueue)')dnl +define(`confEBINDIR', `/usr/lib')dnl +define(`confTIME_ZONE', `USE_TZ')dnl +ifdef(`LOCAL_MAILER_PATH',, `define(`LOCAL_MAILER_PATH', /etc/mail/slocal)')dnl +_DEFIFNOT(`LOCAL_MAILER_FLAGS', `Puho9')dnl +ifdef(`LOCAL_MAILER_ARGS',, `define(`LOCAL_MAILER_ARGS', `slocal -user $u')')dnl +ifdef(`LOCAL_SHELL_FLAGS',, `define(`LOCAL_SHELL_FLAGS', Peu)')dnl diff --git a/gnu/usr.sbin/sendmail/cf/ostype/unknown.m4 b/gnu/usr.sbin/sendmail/cf/ostype/unknown.m4 new file mode 100644 index 00000000000..6749c3f906c --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/unknown.m4 @@ -0,0 +1,20 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Sendmail: unknown.m4,v 8.9 1999/02/07 07:26:24 gshapiro Exp $') +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/gnu/usr.sbin/sendmail/cf/ostype/uxpds.m4 b/gnu/usr.sbin/sendmail/cf/ostype/uxpds.m4 new file mode 100644 index 00000000000..9d7567564c7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/ostype/uxpds.m4 @@ -0,0 +1,25 @@ +divert(-1) +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for UXP/DS (Fujitsu/ICL DS/90 series) +# Diego R. Lopez, CICA (Seville). 1995 +# + +divert(0) +VERSIONID(`$Sendmail: uxpds.m4,v 8.16 1999/10/21 00:31:42 gshapiro Exp $') + +define(`confDEF_GROUP_ID', `6') +define(`LOCAL_MAILER_PATH', `/usr/ucblib/binmail')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$f -gmedium $h!rmail ($u)')dnl +define(`confEBINDIR', `/usr/ucblib')dnl diff --git a/gnu/usr.sbin/sendmail/cf/sh/makeinfo.sh b/gnu/usr.sbin/sendmail/cf/sh/makeinfo.sh new file mode 100644 index 00000000000..ea3d0618f2e --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/sh/makeinfo.sh @@ -0,0 +1,58 @@ +#!/bin/sh +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983 Eric P. Allman. All rights reserved. +# Copyright (c) 1988, 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: makeinfo.sh,v 8.14 1999/02/07 07:26:25 gshapiro Exp $ +# + +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/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4 b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4 new file mode 100644 index 00000000000..33c71511781 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.cogsci.m4 @@ -0,0 +1,6 @@ +SITE(contessa) +SITE(emind) +SITE(hoptoad) +SITE(nkainc) +SITE(well) +SITE(ferdy) diff --git a/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4 b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4 new file mode 100644 index 00000000000..81d5e9443d9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.old.arpa.m4 @@ -0,0 +1,4 @@ +SITE(endotsew) +SITE(fateman) +SITE(interlan) +SITE(metron) diff --git a/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4 b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4 new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbarpa.m4 @@ -0,0 +1 @@ + diff --git a/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4 b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4 new file mode 100644 index 00000000000..ee2c34f60d9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/cf/siteconfig/uucp.ucbvax.m4 @@ -0,0 +1,73 @@ +SITE(Padova) +SITE(Shasta) +SITE(alice) +SITE(allegra) +SITE(amdcad) +SITE(att) +SITE(attunix) +SITE(avsd) +SITE(bellcore bellcor) +SITE(calma) +SITE(cithep) +SITE(cnmat) +SITE(craig) +SITE(craylab) +SITE(decusj) +SITE(decvax, S) +SITE(decwrl) +SITE(dssovax) +SITE(eagle) +SITE(ecovax) +SITE(floyd) +SITE(franz) +SITE(geoff) +SITE(harpo) +SITE(ho3e2) +SITE(hpda) +SITE(hplabs) +SITE(ibmsupt ibmuupa ibmpa) +SITE(iiasa70) +SITE(imagen) +SITE(isunix menlo70) +SITE(kentmth) +SITE(lbl-csam lbl-csa) +SITE(lime) +SITE(mothra) +SITE(mseonyx) +SITE(mtxinu) +SITE(pixar) +SITE(pur-ee) +SITE(purdue) +SITE(pwbd) +SITE(sdcarl) +SITE(sftig) +SITE(sgi olympus) +SITE(sii) +SITE(srivisi) +SITE(ssyx) +SITE(sun) +SITE(trwrb) +SITE(twg) +SITE(ucivax) +SITE(ucla-se) +SITE(ucla-cs) +SITE(ucsbcsl ucsbhub) +SITE(ucscc) +SITE(ucsd) +SITE(ucsfcgl) +SITE(ucsfmis) +SITE(ulysses) +SITE(unisoft) +SITE(unmvax) +SITE(usenix) +SITE(uw) +SITE(uwvax) +SITE(vax135) +SITE(voder) +SITE(wheps) +SITE(whuxle) +SITE(whuxlj) +SITE(xicomp) +SITE(xprin) +SITE(zehntel) +SITE(zilog) diff --git a/gnu/usr.sbin/sendmail/contrib/README b/gnu/usr.sbin/sendmail/contrib/README new file mode 100644 index 00000000000..b594b6dbfeb --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/README @@ -0,0 +1,10 @@ +Everything in this directory (except this file) has been contributed. +We will not fix bugs in these programs. Contact the original author +for assistance. + +Some of these are patches to sendmail itself. You may need to take +care -- some of the patches may be out of date with the latest release +of sendmail. Also, the previous comment applies -- patches belong to +the original author, not to us. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:57 $ diff --git a/gnu/usr.sbin/sendmail/contrib/bitdomain.c b/gnu/usr.sbin/sendmail/contrib/bitdomain.c new file mode 100644 index 00000000000..28fe287cd95 --- /dev/null +++ b/gnu/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/mail/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/mail/bitdomain" and + * "FEATURE(bitdomain,`dbm -o /etc/mail/bitdomain')" + * + * The bitdomain table should be rebuilt monthly. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/gnu/usr.sbin/sendmail/contrib/bounce-resender.pl b/gnu/usr.sbin/sendmail/contrib/bounce-resender.pl new file mode 100644 index 00000000000..9253cddff28 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/bounce-resender.pl @@ -0,0 +1,282 @@ +#!/usr/local/bin/perl -w +# +# bounce-resender: constructs mail queue from bounce spool for +# subsequent reprocessing by sendmail +# +# usage: given a mail spool full of (only) bounced mail called "bounces": +# # mkdir -m0700 bqueue; cd bqueue && bounce-resender < ../bounces +# # cd .. +# # chown -R root bqueue; chmod 600 bqueue/* +# # /usr/lib/sendmail -bp -oQ`pwd`/bqueue | more # does it look OK? +# # /usr/lib/sendmail -q -oQ`pwd`/bqueue -oT99d & # run the queue +# +# ** also read messages at end! ** +# +# Brian R. Gaeke Thu Feb 18 13:40:10 PST 1999 +# +############################################################################# +# This script has NO WARRANTY, NO BUG FIXES, and NO SUPPORT. You will +# need to modify it for your site and for your operating system, unless +# you are in the EECS Instructional group at UC Berkeley. (Search forward +# for two occurrences of "FIXME".) +# + +$state = "MSG_START"; +$ctr = 0; +$lineno = 0; +$getnrl = 0; +$nrl = ""; +$uname = "PhilOS"; # You don't want to change this here. +$myname = $0; +$myname =~ s,.*/([^/]*),$1,; + +chomp($hostname = `hostname`); +chomp($uname = `uname`); + +# FIXME: Define the functions "major" and "minor" for your OS. +if ($uname eq "SunOS") { + # from h2ph < /usr/include/sys/sysmacros.h on + # SunOS torus.CS.Berkeley.EDU 5.6 Generic_105182-11 i86pc i386 i86pc + eval 'sub O_BITSMINOR () {8;}' unless defined(&O_BITSMINOR); + eval 'sub O_MAXMAJ () {0x7f;}' unless defined(&O_MAXMAJ); + eval 'sub O_MAXMIN () {0xff;}' unless defined(&O_MAXMIN); + eval 'sub major { + local($x) = @_; + eval "((($x) >> &O_BITSMINOR) &O_MAXMAJ)"; + }' unless defined(&major); + eval 'sub minor { + local($x) = @_; + eval "(($x) &O_MAXMIN)"; + }' unless defined(&minor); +} else { + die "How do you calculate major and minor device numbers on $uname?\n"; +} + +sub ignorance { $ignored{$state}++; } + +sub unmunge { + my($addr) = @_; + $addr =~ s/_FNORD_/ /g; + # remove (Real Name) + $addr =~ s/^(.*)\([^\)]*\)(.*)$/$1$2/ + if $addr =~ /^.*\([^\)]*\).*$/; + # extract if it appears + $addr =~ s/^.*<([^>]*)>.*$/$1/ + if $addr =~ /^.*<[^>]*>.*$/; + # strip leading, trailing blanks + $addr =~ s/^\s*(.*)\s*/$1/; + # nuke local domain + # FIXME: Add a regular expression for your local domain here. + $addr =~ + s/@(cory|po|pasteur|torus|parker|cochise|franklin).(ee)?cs.berkeley.edu//i; + return $addr; +} + +print STDERR "$0: running on $hostname ($uname)\n"; + +open(INPUT,$ARGV[0]) || die "$ARGV[0]: $!\n"; + +sub working { + my($now); + $now = localtime; + print STDERR "$myname: Working... $now\n"; +} + +&working(); + +while (! eof INPUT) { + # get a new line + if ($state eq "IN_MESSAGE_HEADER") { + # handle multi-line headers + if ($nrl ne "" || $getnrl != 0) { + $_ = $nrl; + $getnrl = 0; + $nrl = ""; + } else { + $_ = ; $lineno++; + } + unless ($_ =~ /^\s*$/) { + while ($nrl eq "") { + $nrl = ; $lineno++; + if ($nrl =~ /^\s+[^\s].*$/) { # continuation line + chomp($_); + $_ .= "_FNORD_" . $nrl; + $nrl = ""; + } elsif ($nrl =~ /^\s*$/) { # end of headers + $getnrl++; + last; + } + } + } + } else { + # normal single line + if ($nrl ne "") { + $_ = $nrl; $nrl = ""; + } else { + $_ = ; $lineno++; + } + } + + if ($state eq "WAIT_FOR_FROM") { + if (/^From \S+.*$/) { + $state = "MSG_START"; + } else { + &ignorance(); + } + } elsif ($state eq "MSG_START") { + if (/^\s+boundary=\"([^\"]*)\".*$/) { + $boundary = $1; + $state = "GOT_BOUNDARY"; + $ctr++; + } else { + &ignorance(); + } + } elsif ($state eq "GOT_BOUNDARY") { + if (/^--$boundary/) { + $next = ; $lineno++; + if ($next =~ /^Content-Type: message\/rfc822/) { + $hour = (localtime)[2]; + $char = chr(ord("A") + $hour); + $ident = sprintf("%sAA%05d",$char,99999 - $ctr); + $qf = "qf$ident"; + $df = "df$ident"; + @rcpt = (); + open(MSGHDR,">$qf") || die "Can't write to $qf: $!\n"; + open(MSGBODY,">$df") || die "Can't write to $df: $!\n"; + chmod(0600, $qf, $df); + $state = "IN_MESSAGE_HEADER"; + $header = $body = ""; + $messageid = "bounce-resender-$ctr"; + $fromline = "MAILER-DAEMON"; + $ctencod = "7BIT"; + # skip a bit, brother maynard (boundary is separated from + # the header by a blank line) + $next = ; $lineno++; + unless ($next =~ /^\s*$/) { + print MSGHDR $next; + } + } + } else { + &ignorance(); + } + + $next = $char = $hour = undef; + } elsif ($state eq "IN_MESSAGE_HEADER") { + if (!(/^--$boundary/ || /^\s*$/)) { + if (/^Message-[iI][dD]:\s+<([^@]+)@[^>]*>.*$/) { + $messageid = $1; + } elsif (/^From:\s+(.*)$/) { + $fromline = $sender = $1; + $fromline = unmunge($fromline); + } elsif (/^Content-[Tt]ransfer-[Ee]ncoding:\s+(.*)$/) { + $ctencod = $1; + } elsif (/^(To|[Cc][Cc]):\s+(.*)$/) { + $toaddrs = $2; + foreach $toaddr (split(/,/,$toaddrs)) { + $toaddr = unmunge($toaddr); + push(@rcpt,$toaddr); + } + } + $headerline = $_; + # escape special chars + # (Perhaps not. It doesn't seem to be necessary (yet)). + #$headerline =~ s/([\(\)<>@,;:\\".\[\]])/\\$1/g; + # purely heuristic ;-) + $headerline =~ s/Return-Path:/?P?Return-Path:/g; + # save H-line to write to qf, later + $header .= "H$headerline"; + + $headerline = $toaddr = $toaddrs = undef; + } elsif (/^\s*$/) { + # write to qf + ($dev, $ino) = (stat($df))[0 .. 1]; + ($maj, $min) = (major($dev), minor($dev)); + $time = time(); + print MSGHDR "V2\n"; + print MSGHDR "B$ctencod\n"; + print MSGHDR "S$sender\n"; + print MSGHDR "I$maj/$min/$ino\n"; + print MSGHDR "K$time\n"; + print MSGHDR "T$time\n"; + print MSGHDR "D$df\n"; + print MSGHDR "N1\n"; + print MSGHDR "MDeferred: manually-requeued bounced message\n"; + foreach $r (@rcpt) { + print MSGHDR "RP:$r\n"; + } + $header =~ s/_FNORD_/\n/g; + print MSGHDR $header; + print MSGHDR "HMessage-ID: <$messageid@$hostname>\n" + if ($messageid =~ /bounce-resender/); + print MSGHDR ".\n"; + close MSGHDR; + + # jump to state waiting for message body + $state = "IN_MESSAGE_BODY"; + + $dev = $ino = $maj = $min = $r = $time = undef; + } elsif (/^--$boundary/) { + # signal an error + print "$myname: Header without message! Line $lineno qf $qf\n"; + + # write to qf anyway (SAME AS ABOVE, SHOULD BE A PROCEDURE) + ($dev, $ino) = (stat($df))[0 .. 1]; + ($maj, $min) = (major($dev), minor($dev)); + $time = time(); + print MSGHDR "V2\n"; + print MSGHDR "B$ctencod\n"; + print MSGHDR "S$sender\n"; + print MSGHDR "I$maj/$min/$ino\n"; + print MSGHDR "K$time\n"; + print MSGHDR "T$time\n"; + print MSGHDR "D$df\n"; + print MSGHDR "N1\n"; + print MSGHDR "MDeferred: manually-requeued bounced message\n"; + foreach $r (@rcpt) { + print MSGHDR "RP:$r\n"; + } + $header =~ s/_FNORD_/\n/g; + print MSGHDR $header; + print MSGHDR "HMessage-ID: <$messageid@$hostname>\n" + if ($messageid =~ /bounce-resender/); + print MSGHDR ".\n"; + close MSGHDR; + + # jump to state waiting for next bounce message + $state = "WAIT_FOR_FROM"; + + $dev = $ino = $maj = $min = $r = $time = undef; + } else { + # never got here + &ignorance(); + } + } elsif ($state eq "IN_MESSAGE_BODY") { + if (/^--$boundary/) { + print MSGBODY $body; + close MSGBODY; + $state = "WAIT_FOR_FROM"; + } else { + $body .= $_; + } + } + if ($lineno % 1900 == 0) { &working(); } +} + +close INPUT; + +foreach $x (keys %ignored) { + print STDERR + "$myname: ignored $ignored{$x} lines of bounce spool in state $x\n"; +} +print STDERR + "$myname: processed $lineno lines of input and wrote $ctr messages\n"; +print STDERR + "$myname: remember to chown the queue files to root before running:\n"; +chomp($pwd = `pwd`); +print STDERR "$myname: # sendmail -q -oQ$pwd -oT99d &\n"; + +print STDERR "$myname: to test the newly generated queue:\n"; +print STDERR "$myname: # sendmail -bp -oQ$pwd | more\n"; + +exit 0; + diff --git a/gnu/usr.sbin/sendmail/contrib/bsdi.mc b/gnu/usr.sbin/sendmail/contrib/bsdi.mc new file mode 100644 index 00000000000..76f26b04b46 --- /dev/null +++ b/gnu/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 ; 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 ; 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 ; Sat, 10 Dec 1994 12:49:01 -0600 +Message-Id: <199412101849.MAA14919@austin.BSDI.COM> +To: Eric Allman +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 +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(`@(#)$Sendmail: bsdi.mc,v 8.1 1999/02/06 18:44:08 gshapiro Exp $') + +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/gnu/usr.sbin/sendmail/contrib/converting.sun.configs b/gnu/usr.sbin/sendmail/contrib/converting.sun.configs new file mode 100644 index 00000000000..e6a3a9e8bd9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/converting.sun.configs @@ -0,0 +1,446 @@ + + Converting Standard Sun Config + Files to Sendmail Version 8 + + Rick McCarty + Texas Instruments Inc. + Latest Update: 08/25/93 - RJMc + +This document details the changes necessary to continue using your +current SunOS sendmail.cf with sendmail version 8. In the longer term, +it is recommended that one move to using an m4 based configuration such +as those shipped with sendmail, but if you're like me and have made +enough modifications to your .cf file that you'd rather put that task +off until later, here's the sum total of my experience to get you to +version 8 with minimal pain. I'll cover .cf as well as build issues. + +Some background - as many are surely aware, Sun has some "special" +features in the sendmail they ship ($%x, %y LHS lookup, NIS alias DB +search, etc.). (Some of those features can be had in alternative forms +in IDA sendmail, but v8 has picked up some IDA capabilities as well as +new ones, making it IMHO a most desirable version to go to.) What I +will explain below includes v8 functional "equivalences" to these Sun +sendmail features. + +So with that out of the way, let's begin. + +First, some assumptions: + + 1) I'm going to assume you've got sendmail version 8.6 or + later in hand - if not, grab it from ftp.cs.berkeley.edu + in the ucb/sendmail directory. There are bugs in earlier + versions which affect some of the needed functionality. + + 2) Second, I'm going to detail this based upon the + "sendmail.main.cf" configuration. (BTW, if you attempt + to move to using an m4 generated config in the future, + MAIL_HUB is the feature which should provide similar + functionality). + + In general, the changes will be similar for a subsidiary + file, but since we (my TI group) funnel all non-local mail + through our mailhost, we're not as interested in getting v8 + to run on such systems and I haven't tried it. + + 3) You're using DNS and sendmail.mx. If you're not, you ought + to be, even if you're also running it along with NIS (which + we do - except for gethostbyxxx() lookups, which I'll be + talking about later). I would imagine you could get things + running OK without DNS support, but I haven't tried it myself. + + 4) You're not mounting /var/spool/mail from other systems. + I haven't found a v8 feature to guarantee this will work + correctly. Anyway, in the past, we've tried doing that + here and found it to be a rather "ugly" feature, though + Sun ostensibly supports it ("R" option). Perhaps v8 + will one day have a similar feature, but for now, bottom + line, I would recommend against it. + + 5) You're not on Solaris or using NIS+. I'm on 4.1.3. I've + looked at Solaris briefly and have noted that things are + pretty much similar there except that they've moved some + things into the /etc/mail directory. I'd guess the + executables aren't functionally all that different from + what they had before - the configs are roughly the same. + So I'd bet most of what I say in here will apply to + Solaris. + +OK, let's configure our sendmail.cf! I'll just go from the top down... + + VARIOUS DECLARATIONS + +1) For v8, you need to define your .cf as AT LEAST a version level 4 + configuration. Add the following line: + + V4 + + There are some issues regarding certain predefined macros - $w, $j, and + $m. With a V4 configuration: + + $w is defined to be the hostname, which will usually be fully + qualified (i.e. "firefly.add.itg.ti.com"). + + $j should have the same value as $w. + + $m will be predefined as the domain portion of $w + (ex. "add.itg.ti.com"). + + One note about this - if your configuration relies on the "w" macro to + be the "simple" hostname (as mine does)... + + If the configuration version is 5 or larger: + + $w is supposed to be the "simple" name (ex. "firefly") + + $j should be the fully qualified name (i.e. "firefly.add.itg.ti.com") + + $m will be predefined as the domain portion of $j + (ex. "add.itg.ti.com"). + + I have not experimented with the various combinations, so I cannot + guarantee you that the above definitions will always come out as + expected. Bottom line: if your sendmail.cf depends on $w being the + simple hostname, test it carefully or define the name explicitly, + for example: + + Dwfirefly + +2) To replace the Sun's "%y" feature, we must use a hostname mapping + feature in v8. If you want to do similar lookups with v8, you need + to define the following map (we'll go over the rules that use this + map later): + + Khostlookup host -f -m -a. + + This will define a "lookup only" map that is otherwise the same as + sendmail version 8's built-in "host" map (see the "Sendmail + Installation and Operation Guide" for details on this map.). + + An important note: Whether or not these lookups will be done via + NIS is a function of what gethostbyxxx() functions you link into + your sendmail. DO NOT redefine your host mapping to use NIS + explicitly within sendmail - there can be unexpected behaviour if + you do so (if you do any canonicalization in your .cf, you can get + incorrect results, for one thing). + + For example, DO NOT TRY: + + Khost nis -f -a. hosts.byname + +3) If you're doing reverse alias mapping as done in ruleset 22, instead of: + + DZmail.byaddr + + you'll need to declare the following: + + Kaliasrev nis -f -N mail.byaddr + +4) If you are doing any other NIS map lookups, you'll need to define the + map as done in the below example. I have a "mailhosts" map, which I + use to distinguish between local and non-local hosts. Look at the + sendmail doc for details on this stuff. + + Kmailhosts nis -f -m -a. mailhosts + +5) You might wish to add the following line to support Errors-To: headers. + I don't. + + Ol + +6) Comment out/remove the following line: + + OR + + The R option means something different under v8 - check the documentation + if you're interested in using it. + +7) If you're running NIS and have a separate alias map, BELOW the + following line where the alias file is declared: + + OA/etc/aliases + + ADD the following: + + OAnis:mail.aliases + + This will set things up so v8 will look at the local alias DB first, + then the NIS map, just as Sun sendmail does. + +8) Though you don't have to, I'd suggest changing: + + OT3d + + to use v8's warning feature, which allows a warning message to be + sent if a message cannot be delivered within a specified period. + I use: + + OT5d/4h + + which says - bounce after 5 days, warn after 4 hours. + +9) I set the following option to be explicit about how I want DNS + handled: + + OI +DNSRCH +DEFNAMES + +10) The following line: + + T root daemon uucp + + may be deleted, though it will be ignored if you leave it around. + +11) It would probably be good to change the version macro value (which + shows up in "Received:" headers) so no one debugging mail problems + gets the wrong idea about what config you're running under. Look + for something like: + + DVSMI-4.1 + + Mine, for example is: + + DVADD-HUB-2.1 + + RULESETS + +1) In ruleset 3, BELOW this rule: + + # basic textual canonicalization + R$*<$+>$* $2 basic RFC822 parsing + + +I add the following rule to remove a trailing dot in the domain spec so +it won't interfere with v8 mapping features, etc. (Having a trailing dot is +not RFC-compliant anyway.): + + R$+. $1 + +2) Because ruleset 5 is special in v8, I rename it to S95 and also change + all RHS expressions containing ">5" to use ">95" instead. In v8, + 5 is executed against addresses which resolve to the local mailer and + are not an alias. If you don't change S5 to something else, you might + get a surprise! + +3) If you're doing any lookups via the generalized NIS "$%x/$!x" + mechanisms (such as with the mailhost map I referred to earlier) it's + done differently under v8. For example: + + DMmailhosts + ... + R$*<@$%M.uucp>$* $#ether $@$2 $:$1<@$2>$3 + + takes a different map definition and two rules under version 8: + + Kmailhosts nis -f -m -a. mailhosts + ... + R$*<@$+.uucp>$* $: $1<@$(mailhosts $2 $).uucp>$3 + R$*<@$+..uucp>$* $#ether $@$2 $:$1<@$2>$3 + +4) Sun has a special case of the "$%x" feature for host lookups - "%y" is + automagically defined to do an NIS "hosts.byname" search with no other + definition, as done in the below example: + + R$*<@$%y.LOCAL>$* $#ether $@$2 $:$1<@$2>$3 + + (Sun does this in more than one place. But the above syntax is almost + identical in each - mostly a case of changing names to protect the + innocent.) + + In version 8, the predefined "host" map can be used to do essentially + the same thing. (However, whether or not it does an NIS lookup is + a function of what gethostbyxxx() functions are linked in.) + + Recall the map definition I mentioned earlier in the DECLARATIONS + section: + + Khostlookup host -f -m -a. + + Here's where we will use it. It will take two rules: + + R$*<@$+.LOCAL>$* $: $1<@$(hostlookup $2 $).LOCAL>$3 + R$*<@$+..LOCAL>$* $#ether $@$2 $:$1<@$2>$3 + + Note that this is almost verbatim the same change as was used in the + previous "mailhosts" example. + +5) Although Sun's default configs don't do this, because I mentioned + canonicalization earlier, it deserves an example, as it's illustrative + of the functional difference in the map definitions I discussed before. + This stuff is also convered in the "Sendmail Installation and Operation + Guide". + + Remember the built-in "host" map definition? As you'll recall, unlike + the "hostlookup" map we defined, "host" will actually CHANGE the + hostname in addition to appending a dot. "hostlookup" only appends a + dot if the name is found and doesn't change it otherwise. Anyway, + here's the example: + + R$*<@$+>$* $: $1<@$(host $2 $)>$3 canonicalize + R$*<@$+.>$* $1<@$2>$3 remove trailing dot + + Using the above, say you had input of: + + joe<@tilde> + + OR + + joe<@[128.247.160.56]> + + Assuming "tilde" or the IP address is found, it might be + canonicalized as: + + joe<@tilde.csc.ti.com> + +6) As another instance of the NIS lookup feature, with a slightly + different twist, Sun implements reverse alias mapping in ruleset 22 + with the below: + + DZmail.byaddr + ... + R$-<@$-> $:$>3${Z$1@$2$} invert aliases + + To use this feature under v8, change the above rule a (remember to + define the alias map as I showed earlier): + + R$-<@$-> $:$>3$(aliasrev $1@$2 $) invert aliases + + + MAILER DEFINITIONS + +1) Where "TCP" is defined in the "P=" and "A=" parameters of mailers, I + changed it to "IPC". Version 8 will accept "TCP", but "IPC" is + preferred. + +2) On all IPC mailers, I also defined "E=\r\n" and added an "L=1000" as + in the below example: + + Mether, P=[IPC], F=mDFMuCX, S=11, R=21, L=1000, E=\r\n, A=IPC $h + + The "E=\r\n" will save you headaches interoperating with such things as + VMS TCP products. + + The "L=1000" is for RFC821 compatibility. Not strictly necessary. + + I also removed the "s" (strip quotes) mailer flag Sun puts in for + these mailers. Stripping quotes violates protocols, which say + clearly that you can't touch the local-part (left hand side of + the @) until you are on the delivering host. + +NOW. If I haven't left anything out, you should be able to run through +your Sun sendmail.cf file and convert it to run under v8. + + BUILD ISSUES + +Some important notes on building v8 on SunOS: + +Makefile + +The default makefile in the version 8 source (src) directory assumes the +new Berkeley make. Unless you want to go to the trouble of building it, +you can use your regular make, but you need to use a different makefile. +You can use "Makefile.dist" or "Makefile.SunOS" in the src directory. I +made changes to get it to build so it is as compatible as possible with +the file/directory locations Sun uses. Here are some relevant sections +out of my makefile: + + CC=gcc + + # use O=-O (usual) or O=-g (debugging) + O= -O + + # define the database mechanisms available for map & alias lookups: + # -DNDBM -- use new DBM + # -DNEWDB -- use new Berkeley DB + # -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility + # -DNIS -- include client NIS support + # The really old (V7) DBM library is no longer supported. + # See README for a description of how these flags interact. + #DBMDEF= -DNDBM -DNEWDB + DBMDEF= -DNDBM -DNIS + + # environment definitions (e.g., -D_AIX3) + ENVDEF= + + # see also conf.h for additional compilation flags + + # library directories + LIBDIRS=-L/usr/local/lib + + # libraries required on your system + #LIBS= -ldb -ldbm + LIBS= -ldbm -lresolv + + # location of sendmail binary (usually /usr/sbin or /usr/lib) + BINDIR= ${DESTDIR}/usr/lib + + # location of sendmail.st file (usually /var/log or /usr/lib) + STDIR= ${DESTDIR}/etc + + # location of sendmail.hf file (usually /usr/share/misc or /usr/lib) + HFDIR= ${DESTDIR}/usr/lib + +For the resolver library, you can use the one shipped with Sun if you +want. But I'd recommend using another version of the resolver library +(such as the one with Bind 4.8.3 or 4.9). Sun's resolver stuff (at +least with 4.1.x) is quite old - I believe it is of 4.3.1 vintage. (Do +you get the impression I don't TRUST what Sun ships with their systems?) + +If you want NIS host lookup while maintaining DNS capability, you might +take a look at resolv+, which has NIS capable gethostbyxxx() functions +in it. My recommendation, however, is to avoid doing NIS host lookups +in sendmail altogether, and to use a "pure" version of the resolver +library. + +There are probably no situations (at least I think so) where it makes +any sense to link in Sun's NIS gethostbyxxx() functions from libc. +You could, I guess do it (I haven't tried it) and wind up with a +sendmail equivalent to the non-mx version Sun ships. You'd need to +insure that NAMED_BIND is not defined in the build. (If you do +this and have the "-b" DNS passthru option set in NIS, remember that +while you have some DNS functionality you'll not have any MX support. +(This, IMO, is what makes this a non-optimal choice.) + + INSTALLATION/TESTING ISSUES + +The sendmail.hf file in the src directory should replace the one currently +in /usr/lib. You also might choose to edit it a bit to "localize" what it +says. + +The sendmail executable goes, of course, in /usr/lib in place of the current +one. What I did was create a subdirectory in /usr/lib and put all of the +Sun sendmail stuff in there. I named the v8 sendmail executable to be +sendmail.v8.mx and then symbolically linked it to sendmail. + +One other thing. If you use address test mode, keep in mind that +Version 8 is like IDA in that it does not automatically execute ruleset +3 first. So say you're playing around with things testing addresses and +you're used to things like: + + 0 jimbob@good.old.boy.com + +under v8 you need to say instead: + + 3,0 jimbob@good.old.boy.com + + INTEROPERABILITY ISSUES YOU MIGHT ENCOUNTER + +Be aware that sendmail v8 issues a multi-line SMTP welcome (220) +response upon a client connection. Most systems in your network should +handle it OK, but there are some that choke on it, because whoever wrote +the clients assumed only a single line. THIS IS NOT SENDMAIL's FAULT. +A multi-line 220 response is perfectly valid. A likely place you'll +encounter this problem is with non-Un*x SMTP clients. If you do run +into it, you should report it to the vendor. + +A final note about version 8 - if you follow the above configuration +scenario, you'll notice it doesn't like to get envelope sender +addresses it doesn't know how to get back to. Sun sendmail would take +anything, even though it might not be able to bounce the message back +should something happen downstream. So if another sendmail on a host +that's not locally known is trying to pump mail through your v8 host, +the ENVELOPE sender it gives had better be fully qualified. This is +a GREAT thing, because it helps clear up problems we've had with not +being able to get things back to the sender, resulting in an +overburdened postmaster. + +I hope this helps those running Sun sendmail feel more at ease with moving +on to v8. It's really worth going to. diff --git a/gnu/usr.sbin/sendmail/contrib/domainmap.m4 b/gnu/usr.sbin/sendmail/contrib/domainmap.m4 new file mode 100644 index 00000000000..31d284ce73c --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/domainmap.m4 @@ -0,0 +1,90 @@ +divert(-1)changequote(<<, >>)<< +----------------------------------------------------------------------------- + + FEATURE(domainmap) Macro + + The existing virtusertable feature distributed with sendmail is a good + basic approach to virtual hosting, but it is missing a few key + features: + + 1. Ability to have a different map for each domain. + 2. Ability to perform virtual hosting for domains which are not in $=w. + 3. Ability to use a centralized network-accessible database (such as + PH) which is keyed on username alone (as opposed to the + fully-qualified email address). + + The FEATURE(domainmap) macro neatly solves these problems. + + The basic syntax of the macro is: + FEATURE(domainmap, `domain.com', `map definition ...')dnl + + To illustrate how it works, here is an example: + FEATURE(domainmap, `foo.com', `dbm -o /etc/mail/foo-users')dnl + + In this example, mail sent to user@foo.com will be rewritten by the + domainmap. The username will be looked up in the DBM map + /etc/mail/foo-users, which looks like this: + jsmith johnsmith@mailbox.foo.com + jdoe janedoe@sandbox.bar.com + + So mail sent to jsmith@foo.com will be relayed to + johnsmith@mailbox.foo.com, and mail sent to jdoe@foo.com will be + relayed to janedoe@sandbox.bar.com. + + The FEATURE(domainmap) Macro supports the user+detail syntax by + stripping off the +detail portion before the domainmap lookup and + tacking it back on to the result. Using the example above, mail sent + to jsmith+sometext@foo.com will be rewritten as + johnsmith+sometext@mailbox.foo.com. + + If one of the elements in the $=w class (i.e., "local" delivery hosts) + is a domain specified in a FEATURE(domainmap) entry, you need to use + the LOCAL_USER(username) macro to specify the list of users for whom + domainmap lookups should not be done. + + To use this macro, simply copy this file into the cf/feature directory + in the sendmail source tree. For more information, please see the + following URL: + + http://www-wsg.cso.uiuc.edu/sendmail/patches/domainmap.html + + Feedback is welcome. + + Mark D. Roth + +----------------------------------------------------------------------------- +>>changequote(`, ')undivert(-1)divert + +ifdef(`_DOMAIN_MAP_',`',`dnl +LOCAL_RULE_0 +# do mapping for domains where applicable +R$* $=O $* <@ $={MappedDomain} .> $@ $>97 $1 $2 $3 Strip extraneous routing +R$+ <@ $={MappedDomain} .> $>DomainMapLookup $1 <@ $2 .> domain mapping + +LOCAL_RULESETS +########################################################################### +### Ruleset DomainMapLookup -- special rewriting for mapped domains ### +########################################################################### + +SDomainMapLookup +R $=L <@ $=w .> $@ $1 <@ $2 .> weed out local users, in case +# Cw contains a mapped domain +R $+ <@ $+ .> $1 <@ $2 > strip trailing dot +R $+ <@ $+ . $+ > $1 <@ $(dequote $2 "_" $3 $) > +# change "." to "_" +R $+ <@ $+ > $: $1 <@ $(dequote "domain_" $2 $) > +# prepend "domain_" +R $+ + $+ <@ $*> $1 <@ $3 > <+> $2 handle user+list syntax +R $+ <@ $* > $* $( $2 $1 $: $) $3 +# do actual domain map lookup +R $* $#error $@ 5.1.1 $: "550 email address lookup in domain map failed" +R $* $* $#error $@ 4.3.0 $: "450 domain map temporarily unavailable" +R $+ @ $+ <+> $+ $1 + $3 @ $2 reset original user+list +R $+ <+> $* $1 paranoid check - remove <+> +R $+ @ $+ . $1 @ $2 strip trailing dot +R $+ @ $+ $@ $>97 $1 @ $2 recanonify +define(`_DOMAIN_MAP_',`1')') + +LOCAL_CONFIG +C{MappedDomain} _ARG_ +K `domain_'translit(_ARG_, `.', `_') _ARG2_ -T diff --git a/gnu/usr.sbin/sendmail/contrib/doublebounce.pl b/gnu/usr.sbin/sendmail/contrib/doublebounce.pl new file mode 100644 index 00000000000..a853ec14f37 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/doublebounce.pl @@ -0,0 +1,232 @@ +#!/usr/bin/perl +# doublebounce.pl +# attempt to return a doubly-bounced email to a postmaster +# jr@terra.net, 12/4/97 +# +# invoke by creating an mail alias such as: +# doublebounce: "|/usr/local/sbin/doublebounce" +# then adding this line to your sendmail.cf: +# O DoubleBounceAddress=doublebounce +# +# optionally, add a "-d" flag in the aliases file, to send a +# debug trace to your own postmaster showing what is going on +# +# this allows the "postmaster" address to still go to a human being, +# while bounce messages can go to this script, which will bounce them +# back to the postmaster at the sending site. +# +# the algorithm is to scan the double-bounce error report generated +# by sendmail on stdin, for the original message (it starts after the +# second "Orignal message follows" marker), look for From, Sender, and +# Received headers from the point closest to the sender back to the point +# closest to us, and try to deliver a double-bounce report back to a +# postmaster at one of these sites in the hope that they can +# return the message to the original sender, or do something about +# the fact that that sender's return address is not valid. + + +use Socket; + +# look for debug flag +# +$dflag = 0; +$dflag = 1 if ($ARGV[0] eq "-d"); + +# get local host name +# you may need to edit these two lines for however your system does this +# +$host = `hostname`; chop($host); +$domain = `dnsdomainname`; chop($domain); + +# get temp file name +$tmp = "/tmp/doubb$$"; + +# save message from STDIN to a file +# I thought about reading it into a buffer here, but some messages +# are 10+Mb so a buffer may not be a good idea +# +if (! open(MSG, "+> $tmp")) { + # can't open temp file -- send message to local postmaster + # open(MAIL, "| /usr/sbin/sendmail -oeq postmaster"); + print MAIL ; + close(MAIL); + exit(1); +} +print MSG ; + +# scan message for list of possible sender sites +# note that original message appears after the second +# "Original message follows" marker +# look for From, Sender, and Reply-To and try them, too +# +$inhdr = 0; +$hdrs = 0; +$skip = 0; +seek(MSG, 0, 0); +while () { + chop; + if (/^ ----- Original message follows -----$/ + || /^ ----Unsent message follows----$/) { + $i = 0; + $inhdr = 1; + $hdrs++; + $skip = 1; + next; + } + if ($skip) { + $skip--; + next; + } + if (/^$/) { + last if ($hdrs >= 2); + $inhdr = 0; + next; + } + if (! $inhdr) { + next; + } + if (! /^[ \t]/) { $hdr[$i++] = $_ } + else { + $i--; + $hdr[$i++] .= $_; + } +} +$rcvd = 0; +for ($j = 0; $j < $i; $j++) { + print STDERR "DEBUG hdr[$j] = $hdr[$j]\n"; + if ($hdr[$j] =~ /^received:/i) { + ($addr[$rcvd++]) = $hdr[$j] =~ m/.*\sby\s([^\s]+)\s.*/; + } + if ($hdr[$j] =~ /^reply-to:/i) { + ($addr1{"reply-to"} = $hdr[$j]) =~ s/^reply-to: *//i; + } + if ($hdr[$j] =~ /^sender:/i) { + ($addr1{"sender"} = $hdr[$j]) =~ s/^sender: *//i; + } + if ($hdr[$j] =~ /^from:/i) { + ($addr1{"from"} = $hdr[$j]) =~ s/^from: *//i; + } +} + +# %addr and %addr1 arrays now contain lists of possible sites (or From headers). +# Go through them parsing for the site name, and attempting to send +# to the named person or postmaster@ each site in turn until successful +# +if ($dflag) { + open(DEBUG, "|/usr/sbin/sendmail postmaster"); + print DEBUG "Subject: double bounce dialog\n"; +} +$sent = 0; +# foreach $x ("from", "sender", "reply-to") { +foreach $x ("from", "sender") { + $y = &parseaddr($addr1{$x}); + if ($y) { + print DEBUG "Trying $y\n" if ($dflag); + if (&sendbounce("$y")) { + $sent++; + last; + } + $y =~ s/.*@//; + print DEBUG "Trying postmaster\@$y\n" if ($dflag); + if (&sendbounce("postmaster\@$y")) { + $sent++; + last; + } + } +} +if (! $sent) { + $rcvd--; + for ($i = $rcvd; $i >= 0; $i--) { + $y = &parseaddr($addr[$i]); + $y =~ s/.*@//; + if ($y) { + print DEBUG "Trying postmaster\@$y\n" if ($dflag); + if (&sendbounce("postmaster\@$y")) { + $sent++; + last; + } + } + } +} +if (! $sent) { + # queer things are happening to me + # $addr[0] should be own domain, so we should have just + # tried postmaster@our.domain. theoretically, we should + # not get here... + if ($dflag) { + print DEBUG "queer things are happening to me\n"; + print DEBUG "Trying postmaster\n"; + } + &sendbounce("postmaster"); +} + +# clean up and get out +# +if ($dflag) { + seek(MSG, 0, 0); + print DEBUG "\n---\n"; print DEBUG ; + close(DEBUG); +} +close(MSG); +unlink("$tmp"); +exit(0); + + + + + +# parseaddr() +# parse hostname from From: header +# +sub parseaddr { + local($hdr) = @_; + local($addr); + + if ($hdr =~ /<.*>/) { + ($addr) = $hdr =~ m/<(.*)>/; + return $addr; + } + if ($addr =~ /\s*\(/) { + ($addr) = $hdr =~ m/\s*(.*)\s*\(/; + return $addr; + } + ($addr) = $hdr =~ m/\s*(.*)\s*/; + return $addr; +} + + +# sendbounce() +# send bounce to postmaster +# +# this re-invokes sendmail in immediate and quiet mode to try +# to deliver to a postmaster. sendmail's exit status tells us +# wether the delivery attempt really was successful. +# +sub sendbounce { + local($dest) = @_; + local($st); + + open(MAIL, "| /usr/sbin/sendmail -ocn -odi -oeq $dest"); + print MAIL < +Subject: Postmaster notify: double bounce +Reply-To: nobody\@$domain +Errors-To: nobody\@$domain +Precedence: junk +Auto-Submitted: auto-generated (postmaster notification) + +The following message was received at $host.$domain for an invalid +recipient. The sender's address was also invalid. Since the message +originated at or transited through your mailer, this notification is being +sent to you in the hope that you will determine the real originator and +have them correct their From or Sender address. + +The invalid sender address was: $addr1{"from"}. + + ----- The following is a double bounce at $host.$domain ----- + +EOT + seek(MSG, 0, 0); + print MAIL ; + return close(MAIL); +} diff --git a/gnu/usr.sbin/sendmail/contrib/etrn.pl b/gnu/usr.sbin/sendmail/contrib/etrn.pl new file mode 100644 index 00000000000..2dfb58d2270 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/etrn.pl @@ -0,0 +1,339 @@ +#!/usr/local/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 +use Socket; +use Getopt::Std; +$sockaddr = 'S n a4 x8'; + +# system requirements: +# must have 'hostname' program. + +############################################################################# +# Copyright (c) 1996-2000 John T. Beck +# 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 John T. Beck. +# 4. The name of John Beck may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY JOHN T. BECK ``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 JOHN T. BECK 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 derived from material copyrighted by the Regents +# of the University of California. +# +# Contributions accepted. +############################################################################# +# Further disclaimer: the etrn.pl script was highly leveraged from the +# expn.pl script which is (C) 1993 David Muir Sharnoff. +############################################################################# + +$port = 'smtp'; +$av0 = $0; +select(STDERR); + +$0 = "$av0 - running hostname"; +chop($name = `hostname || uname -n`); + +$0 = "$av0 - lookup host FQDN and IP addr"; +($hostname,$aliases,$type,$len,undef) = gethostbyname($name); + +$0 = "$av0 - parsing args"; +$usage = "Usage: $av0 [-wd] host [args]"; +getopts('dw'); +$watch = $opt_w; +$debug = $opt_d; +$server = shift(@ARGV); +@hosts = @ARGV; +die $usage unless $server; +@cwfiles = (); +$alarm_action = ""; + +if (!@hosts) { + push(@hosts,$hostname); + + $0 = "$av0 - parsing sendmail.cf"; + open(CF, "){ + if (/^Fw.*$/){ # look for a line starting with "Fw" + $cwfile = $_; + chop($cwfile); + $optional = /^Fw-o/; + $cwfile =~ s,^Fw[^/]*,,; # extract the file name + + if (-r $cwfile) { + push (@cwfiles, $cwfile); + } else { + die "$cwfile is not readable" unless $optional; + } + } + if (/^Cw(.*)$/){ # look for a line starting with "Cw" + @cws = split (' ', $1); + while (@cws) { + $thishost = shift(@cws); + push(@hosts, $thishost) unless $thishost =~ "$hostname|localhost"; + } + } + } + close(CF); + + for $cwfile (@cwfiles) { + $0 = "$av0 - reading $cwfile"; + if (open(CW, "<$cwfile")){ + while (){ + next if /^\#/; + $thishost = $_; + chop($thishost); + push(@hosts, $thishost) unless $thishost =~ $hostname; + } + close(CW); + } else { + die "open $cwfile: $!"; + } + } +} + +$0 = "$av0 - building local socket"; +($name,$aliases,$proto) = getprotobyname('tcp'); +($name,$aliases,$port) = getservbyname($port,'tcp') + unless $port =~ /^\d+/; + +# look it up +$0 = "$av0 - gethostbyname($server)"; + +($name,$aliases,$type,$len,$thataddr) = gethostbyname($server); +(!defined($name)) && die "gethostbyname failed, unknown host $server"; + +# get a connection +$0 = "$av0 - socket to $server"; +$that = pack($sockaddr, &AF_INET, $port, $thataddr); +socket(S, &AF_INET, &SOCK_STREAM, $proto) + || die "socket: $!"; +$0 = "$av0 - connect to $server"; +print "debug = $debug server = $server\n" if (defined($debug) && $debug > 8); +&alarm("connect to $server"); +if (! connect(S, $that)) { + die "cannot connect to $server: $!\n"; +} +alarm(0); +select((select(S),$| = 1)[0]); # don't buffer output to S + +# read the greeting +$0 = "$av0 - talking to $server"; +&alarm("greeting with $server"); +while() { + 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 || $watch); + } + last if ($2 eq " "); + } else { + $0 = "$av0 - bad response from $server"; + print STDERR "$server: NOT 220 greeting: $_" + if ($debug || $watch); + close(S); + } + &alarm("greeting with $server"); +} +alarm(0); + +# if this causes problems, remove it +$0 = "$av0 - sending helo to $server"; +&alarm("sending ehlo to $server"); +&ps("ehlo $hostname"); +$etrn_support = 0; +while() { + if (/^250([- ])ETRN(.+)$/){ + $etrn_support = 1; + } + print if $watch; + last if /^\d+ /; +} +alarm(0); + +if ($etrn_support){ + print "ETRN supported\n" if ($debug); + &alarm("sending etrn to $server"); + while (@hosts) { + $server = shift(@hosts); + &ps("etrn $server"); + while() { + print if $watch; + last if /^\d+ /; + } + sleep(1); + } +} else { + print "\nETRN not supported\n\n" +} + +&alarm("sending 'quit' to $server"); +$0 = "$av0 - sending 'quit' to $server"; +&ps("quit"); +while() { + print if $watch; + last if /^\d+ /; +} +close(S); +alarm(0); + +select(STDOUT); +exit(0); + +# print to the server (also to stdout, if -w) +sub ps +{ + local($p) = @_; + print ">>> $p\n" if $watch; + print S "$p\n"; +} + +sub alarm +{ + ($alarm_action) = @_; + alarm(10); + $SIG{ALRM} = 'handle_alarm'; +} + +sub handle_alarm +{ + &giveup($alarm_action); +} + +sub giveup +{ + local($reason) = @_; + local($pk,$file,$line); + ($pk, $file, $line) = caller; + + $0 = "$av0 - giving up on $server: $reason"; + print "Timed out during $reason\n" if $debug; + exit(1); +} + +# 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 =~ /^\d+([- ])/)) { + print $s if $watch; + $done = $1; + push(@resp,$s); + } + return @resp; +} +# to pass perl -w: +my $x; +$x=$opt_d; +$x=$opt_w; +&handle_alarm; +################### BEGIN PERL/TROFF TRANSITION +.00 ; + +'di +.nr nl 0-1 +.nr % 0 +.\\"'; __END__ +.\" ############## END PERL/TROFF TRANSITION +.TH ETRN 1 "January 25, 1997" +.AT 3 +.SH NAME +etrn \- start mail queue run +.SH SYNOPSIS +.B etrn +.RI [ -w ] +.RI [ -d ] +.IR hostname +.RI [ args ] +.SH DESCRIPTION +.B etrn +will use the SMTP +.B etrn +command to start mail delivery from the host given on the command line. +.B etrn +usually sends an +.B etrn +for each host the local sendmail accepts e-mail for, but if +.IR args +are specified, +.B etrn +uses these as arguments for the SMTP +.B etrn +commands passed to the host given on the command line. +.SH OPTIONS +.LP +The normal mode of operation for +.B etrn +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. +The +.IR -w , +watch, flag will cause +.B etrn +to show you its conversations with the mail daemons. +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 +.B /etc/mail/sendmail.cf +.SH SEE ALSO +.BR sendmail (8), +RFC 1985. +.SH BUGS +Not all mail daemons will implement +.B etrn . +.LP +It is assumed that you are running domain names. +.SH CREDITS +Leveraged from David Muir Sharnoff's expn.pl script. +Christian von Roques added support for +.IR args +and fixed a couple of bugs. +.SH AVAILABILITY +The latest version of +.B etrn +is available in the contrib directory of the sendmail +distribution through anonymous ftp at +.IR ftp://ftp.sendmail.org/ucb/src/sendmail/ . +.SH AUTHOR +.I John T. Beck\ \ \ \ diff --git a/gnu/usr.sbin/sendmail/contrib/expn.pl b/gnu/usr.sbin/sendmail/contrib/expn.pl new file mode 100644 index 00000000000..dd777e69911 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/expn.pl @@ -0,0 +1,1359 @@ +#!/usr/bin/perl +'di '; +'ds 00 \\"'; +'ig 00 '; +# +# THIS PROGRAM IS ITS OWN MANUAL PAGE. INSTALL IN man & bin. +# + +use 5.001; +use IO::Socket; + +# system requirements: +# must have 'nslookup' and 'hostname' programs. + +# $OrigHeader: /home/muir/bin/RCS/expn,v 3.11 1997/09/10 08:14:02 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 +# disconnect & reconnect after 25 commands to the same sendmail 8.8.* host + +# 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; + } +} + +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"; + + $S = new IO::Socket::INET ( + 'PeerAddr' => $server, + 'PeerPort' => $port, + 'Proto' => 'tcp'); + + if (! $S || ($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; + } + $S->autoflush(1); + + # 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] + # [NAME] <[(NAME)] ADDR + # ADDR [(NAME)] + # (NAME) ADDR + # [(NAME)] + # + if ($newaddr =~ /^\<(.*)\>$/) { + print "\n" if $debug; + ($newaddr) = &trim($1); + print "na = $newaddr\n" if $debug; + } + if ($newaddr =~ /^([^\<\>]*)\<([^\<\>]*)\>([^\<\>]*)$/) { + # address has a < > pair in it. + print "N:$1 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() { + 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(); + 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\ \ \ \ diff --git a/gnu/usr.sbin/sendmail/contrib/mail.local.linux b/gnu/usr.sbin/sendmail/contrib/mail.local.linux new file mode 100644 index 00000000000..42d2c3c3d9c --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/mail.local.linux @@ -0,0 +1,205 @@ +From: Karl London +Message-Id: <199308111712.SAA05454@borg.demon.co.uk> +Subject: Final port of mail.local to Linux +To: eric@cs.berkeley.edu +Date: Wed, 11 Aug 1993 18:12:27 +0100 (BST) +X-Mailer: ELM [version 2.4 PL21] +MIME-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: 7bit +Content-Length: 11415 + +Hi, + Sorry about this.. This is a final version of mail.local for +linux.. + +This is what I would like to see distributed with 8.6 if poss... + +Karl + +-------------- + +begin 600 mail.local.linux.tar.Z +M'YV0;<*D8>."S9LQ8=B\`,"PH<.'$"-*G$BQHL6*(&C`N`$#!@@`($#$N%'# +M(TB1)$V&7,D2A$<0-6C,D$%3QHT8+V/HI$$#9(V+0(,*'4HT8ITY=,+("0E@ +MC5(V122.G>1@7IE$'8<,&A&O8Q,VSA?Z< +M#/C3X7V7(9,&J6LQ=>BD>>,&1!@W9(!P5&]I]#?'&W7(,49O_P4H1H%*5;>= +M'&W,P0((=TR'AG%+97@6@G3$U\8;])F1!D+Z\7>A4KW!`5T;T]$Q'PAPR/&& +M'6F0,>-99B7'&PC;D?=&AFZ<`<(8_-&7HAMSQ,;'%MY(;;^BWX(5GU0<" +M&_7)YB62`$ZW'Y/^`=@FD&\(2:216([!AD!KR?$>:C)8^1N6=-R7WZ'%L?E@ +M6G)(R%T;4)ZI7HTDUB&F@2%DW9J%<)AH@ +MK$$:]"@(D4Z:1J4@L*F&&0\)X=^TA4)I5G0I6$NE,(M6:"19I1A5H)L<2C@ +M'+UYV6=Q!YI!QQTL4IMJL%C",6EUR#:J[,'^C;$&GG>P,5]PV4H97@*[^A(\7$7/ZGCA:>T#:B.K$7_*,<9H:LPOB +MERZ.H=V)C>_7H6MTR-B?BQ36)QU_E\9'!1))3`'"%$\80<4504A1!`BU@P"% +M%$]8D00111`!@A!9@##[[[X?48035-@>A!/*#_$$]5(D(4055#PAA>U@@!&$ +M[;6?<`((UQ,1W_7-%X'%\$5,8;OXP#(6K@`X$3GD`%$/"O"4F@@O_"=Z'GQ2<)^N.?_P`H0.H5$`2Y`T$3 +MBB"%(2!A@$$00A+X1X7FM0\$1LB@$^IG.R/@+PC"ZQT!AU`%)O1.>%60`A2> +M,(4BO,]W(&C@%!08!!`FSTK`A6]>XG +MA=1LCPK=^U[XQK>\W_$OADQP(JY\V$;X13$)OAL"%0Z(/4`609"$',+QP!@$ +M)EQH"E`X9!(:>2'Y%2&$O"%34B$(FVRC+G-8/6OB[WM30"`/LZC!`%8! +M"@3<7@KB@X0G7,&++$Q-$+;IOQMNCWU.:-[SQ->\%-Y1AC34Y/_.^+PV(M"- +MW`L"(F\'QR0(,CX'G6$&%8J_.5:0E0E<8`.=<`0)II%_:J0F"MM(P3-*X0JU +M*X)M>E<[!V81H,WC71:>&<$4/@\$_`2F&8.'.]T!L`B5_*(6DQ#,(!#!>$U4 +MGD_/*#QL>D^C-01F?*90!1=&\92I+$+L3I,`(*!@!"DHRUGHUA8T)*`&+A`, +M"J0F!ZI9S38Q>,%(7I"#&(3G!0H8P\$"M:&BK#Q006!V9R`V]^0(4 +M@C"[+S!AEU307P)$\`(ZM`$.+S`(0@B"A=*:5@0*"(UJ5_L5@HAV+*T-RVA= +M,(;5@F8N=RR%[NP9"0PJ$$-!B.3FMBD(XSAR0T@8]OF#N5,E_D(9[@R +M7>=:][K8E:IIVN.,= +M>=G+/+9*3YH@)H?VC!4UFPH4O+B%M0%%RT`(4A"#%#6J"#&*0A;"D(8.=H2&'H7,420CE))`Y:0.1VE*N*K2E03,L;0E4!P9!@TOU8%29*5AIFIFK>A/D(=/*R.A!=&+?>3Q3[Z@PR^2C2M@`VO9H4B6L(7MUV$&EIBO=F:QS96!;ZKJ +MV,<6Y>=EA<%D*%,9&5A6,!BK`&:S;ERK('=@G.DL<[7V61F`MIH9B8%HRVDO +MTMZ[-++*]VD"B]K4JE:&JRGJ;L/BVI:^)B^Q2;!LX4*;6B*VWJ)I.SKK.&-/^KV6G3X%@:_`0YB@B,<@+Z&.&4OKD6.JUEQ)'>T`)G!;MT<7N>&_P[5=D7=7>]^%SQ=&@]YRF.>&=&H +MQNH!-'MOC"/XQ$<^\Z%O"NK[^?L"VL7Y^LGU!6V\(74BR%6;8@]'.IPG7QD7Q"E,,0B +M'A$*25QB$Y_X.RE2T8I$P.)#)]A%I89QC&7\:?3`R$:(5E2.1*_CU_&H1]3D +MW8\-#.0@LQCZ0XZ^E8N,NR-O%TE%4K+IE]Q?)L,)T4^&TH2-+"5853F;5FJ= +MI+'<(BW!KD&QXU)XQ./E)<$H5*X2TYC(!($RF>E,7$&3A=.LYC6AGD)^=I.R +MX(SZ.#,X!7.V$9WJA#H"VRF%=\;3"?/$53WO^<4V#F&?4?TY"K7HQX%*H:#! +ME%$)=2%7P%`N=5.=!$<2-7K%U#T7A2L"N%&TYU&]%U*O1%(F=00H-3TJA3\M +MQ4(PU40SU3WIA($/Y4QL05=``(] +MH``B8%9HE1I%1B>R01MXA1NZ85[`43#]QEY'@V]*$U_9`6[?P05NP`6F<5]B +M6!S[Q1[SX0)T*`([$%B%HQT@,!H@H"M_4B"RH0))*%AFP(1.J(@*8!EZ(Q*J(R$ +MM6/`*(PO<"`FHR;0F(S+^(O-^`(FHC+;V(O4"%GZ88XO4"#C*(V^6(US8!!G +ML([=R`-F,`;#01!H@(SD:%CF2`9B((_3:%AP<`?ND8_1.(_ZL18`V8YUT!Q( +M49#ZR([4"!W=\08+28T/N1\7R8QT0`:`\H\&R8T!Z8U<4R0;^8F(Q59N@5J- +MU80%4@8)8`3@QP0)D`!^-0*.]9(),$LR^4TT"0.,I8@)H".`HB\@\`62A0(H +MH(@7(H67H0(ID`*!:`=OD",)0)%'F91+.1Q-*66RX91+H0(7X@)D&953695D +MD`!)9@9Y\"!F@!Q("05*"9:G898*()1(P1V1I95T"952J0!4:95'$0;!D95R +MB0*!209VJ0!?X08HH!1G,`8<=@9V,$\)H(C^(0>1&8@)T)J"9F<:1\U0R-AL'($>1H#R9F8*8478@9D +M<"'3EA"<607%OT`:!2)K5Y@;PB`(B,(IBP08B<"&7=022 +MQ4+$(P7>^03@B4HS])>D"9VHT@,25$1,P)EWX"LJ,QNTL2'N&1QTH)J/J9F2 +MF9F4>2$B0`9FH`-RH`,B$)4@$`+N602Y8YD),`<>(H7W:1NC69,(`3$@<`)D +M<`(Z4).&*`:_M@:;$R!(\EG;(@;UR8BD69-BD"9AL`:VJ(9 +M:J-RX*$@BAHB:C(E.B8HJA\JVALL6I.7B1PHP)X0F@`L09$HT).OEYUUP`;Z +MX3&]T0+(H9J@DJ`SF@#LZ8FSJ9EA^J(*(Z,Z6J,;^@,Y6I..%097ZC)*.IC! +M@0)_69-]0)J0.08@T`+NZ:4`PIF@"0(K$*APL)K3N:2S$0*?J9F5V:)V6@9X +MNJBC09JXD@3(,::(&')E(#HF,A\78F!S,V^5$YT@H)_P6"!X&BWU=FM0BAK, +M^2]T((5L<2&/!AT9`C&CJJ&EJC9C"BMEH9O<87$#`:NX@B1RL%]PD&?^LI^+ +MPIS@$:N`E0"SFI]JPIR52IJ$B`(A,*8F8`*-VJ08AZUTL*J.J:!\P`>8NA(A +M@`(#Z8GZ.9!I0Z[1J:Y\0"-WT`(^,)!?,*L,*B`Y$I4M.J;N":]W(*]J,I#: +MRIP*^@/ZRJ_^2C<@H`.?^`,82XOK&2#NF9=I8J]MD*<3,AO%61[N"0/6]*B4 +M:4TKL`*@":$E"P)\X)Y$V89-.IRG\;*MB0?3@0(E^Y=[.HG[^;%.ZIR7J`+L +M*9JDF4-Y=!IF``>*)S5>;,">@KH#*[4H8`)T8+5LD*>TJYA/ZQK# +M809-"@<":@085P+%@;S=>:IMT)2VB[NZNY@),+9;``-9Z)XGP`4P<`*<.;(^ +M.[:>&`/69`;Z.0[W8:P3KH\`A(`9C\+?H^XG&BZK+ +M6P.3JZ2]FU;Y,08H<`(^<`+!"0=Y2KG@>[(SNJ\)Y:HA/D!]J+!MA +M<(AEX,2094VZLF2?JS3\-@=*/&4=EA#*TH>G4:UIO,9E;,)`@L*SFY@I\):$ +M-0=HX,.^R:0[;"-RX,,PNZQ3.I,"*B.?Q1VB>ZP8@CJ]09'<4;H)D"9TD"". +M*9Q`RU@UJR^.>XCS9IF8*9Q>>[1TH[01VBFW28E?(@:U*2']=;6=>8EN:085<@9;,!==<"'X809; +M@`,J@!,R0`/IC)MGL06H-#]RFT=.D+;4^994BV@VTLU_`C%EP+KJ6<0J@*FH +M003U03)#TA]L]:5A9Y,$'K7 +MG,N+VL6T$/=B1J +M308GC2S'BD4Q4QQK\1_%(=SU2=*(^#<"`MBYW8<*7:UX2\W"J85Y;1PNXIA< +MC4)?$`10$$G8PP=/\`5#X#N41=Y?<`7$XP1,H%!3@-CM-P52P`?QG017L$U2 +MH*`\X!)"?95$34&6B]D@T-3=;1^JO,D4B2=V69-1'=I4/<2D_!4,."?B+Q,/0>='=?QFR8\K.#+RN!0K;L!W*)GD"># +M(Z+-F0!$#-#'@1QL3="L>^,7`@.KUT1%L./30P2\"\E8+<,H,,[EW-5`4`(@ +M_H=EO19-F2!;?K=,2FEE4-"W+.:/5`1E_@5-1`6V,;BSL>7*F0*%^]^5:]0B +M(,J@6\HJ4^3+B^!+[K--_@8-WLI03M@S.N70:N423IKS:"*-D<,OK +MG+YIL+[MN\Z2[0/^7;#?@@);[HDH:QW(T=_8K,=+`:B'N,V^;JCNZ09W\*1X +MJ^R>:'+30:E@+F9U@!PKX.O7+`?\[=^3W:)#ODU*>J#(\S*&*8NW*VJWM\PX.B>+.21_KFD3&:C:^E)GNX+SNE_">]C\*$) +M`,,&#S`V7LTXJ^5O^>0)$>583MJ7&JNWHR:+M(<'QV^`@<.PSHPLG)@=@>H;8G_$1S'\MH8DIO^H1ZYR6@C +M:RT'<]('8M,L:N4?VJUC\-NVT:(P+(47W?#6'+']>@?_FB/FOJ]W_P5G,+"/ +MC+IF$(S*2/>*N0,_&D7\<0*R@3'3\6`"`@=D`#!;C,B0+"EO`#&&+Y6)GP2? +M!2BBLYS6>1!K4/FDW<44#J%KV9;:(;QN/@=GD*6+C'+`>WZ>%]F[4J +M@`902YK$#W)\J/TAYYM9JS)N<-8YW?R6TB]?8`9J,1!Y\-^&*#5?PTSA;7IB+#,`!R?6D +M9E\.,X#<3V%]"*3``.<-=B)%V(\.4,!NIZ0JFX"#="`P\TD)6`-1?7RL0[>_]L8'JX)ZX'[]"`U]`_5$'%S&C*%B100$^T`<`0?4W +MUVP@^V."*`T._,`O8/[.P%E(84X0!X(NV="QI*`/F`-?8`M*N!GWZUP""%!@ +M38IMD3XU@0*"@!%`;#N$`>V2'4<$CH``:0)A3G`1+JI&`@$FL13@'LJ>Q"%:NB5;R*6#$K:L6M*!&8X5AH`C'* +M):D,KJ@5<`MR.0F]1;>DQ;[0$F2`3B`N,Z$F<(2<(`-L@&)@+F2QN4"7I2!= +MGD)7J"YY,3`*1LDP`LI**`*+5&-TG2*YLHK(3?P3"7KE!L@BQJ)+CD`/2`!> +MD0TH`%3B!'#`9GK`"Q@5C,4%[*-?)`;F@'M@%?%H;RV6P4@`!@R&CF`#8*,,4`RI2"0TAL?@$IPC9=B+F,$O4A?U +M:![;HWMD"'Y(!("A[Q(;PDL9(B^G33Z@E_0@:[)-&WH;PN+;T!>!`1[B(Z@I +M#WE(/2A`Z18?%8"!##!>YE,PF@*CH=@$CA$36&/,F`H(DQ:P+(_`@A`R?>C!CBD7=BSNP)F`<2GTR>*19\IC?T +M&D!3'R1%EK$4/)++0,B`4RQ$!83P=Z>"QZR*B/,JEJ2;J4)/TD!&R5U19XI# +ME<0SQ`+,9$E&@6*N3)=T%M""T-P:.5DMKD7+.)&-9BGDJDA#+CQ:I;D1+U+" +MG`5-`R0E9,OAD9_FON`+?5%J_,6IF33&K6"L&G_1:E[9J_D6L:;>^(F*L7$& +MY8AD"4>26=0'CU%P>,V,]#7`9D@(&V(S'*9$?$0V,H--V@R)U#!8I:V!:-1& +M:(@9;`-4[@V`/`XX,@$(R.X0;I;'N+$:QL+?I!N]$1T*Y*MT-V3#;,B-'T&Q +M^F.S_(_YYEO\JKJ!'-!-WJ@Q>X-0_@N#\S!VQ.`H'`PGZEF./`%QEDWD"!B4 +M(U@E&V.9,>3EQ^%HH(ITU`C3<*SOG(F$FG??!(/R(_Z`?W<2AF9X2DG:M3/[+.!7H@ +M7$>64)"O@T&*C_,X/A[$0(*0J2,S`PC-S"8JA(6X$!CR@[+*#2$G.P3J?)Z] +MTW>,B#@)/$S$B1A(C&EXC`CB43Q:A/'@DU\B1AI)Y/F8:83R1)V1Z3V&#AT1 +M`G9DD@B!/,(C/P_3*3T3A38:DKR90%)/((0DDN3U6!),\G]H3R>Q/:(D]QC( +M(A165HGON9G!Q^O4$I\Y=G2)\O$E*RB8.)]BDD&BS_1I)CSR^D@3BZ)]+@OW +MT2;CNRP`2!`NG$F;B`&6KS +M$.AH4:%0SPB4!^00!)8">W*05;1>4D.R-$0W!/*8(MT#GMA.)X!#4058!`ND +M2`&PNN3V(RP#@%`*`:)`S+'(EQP&QQ4K'"W@.'`I4X8U<.)V(P.A0C9`*YJ' +M!K#H4IB&&XJ%0H$?>D`50$U3`*?-D&I1QJ0JG%L=TUTY0HLZM0'H(*$`'("D +M/\)+"@`CXVAH_!NGUABSA+^(IQE$?O6*?%HYA6APH5A]-#H+&$*J%3QHLR\`? +MM9>$X]=LB%J&V@)$-&4+R9"3`A$5]1\$&_CR$WYTH"8<0HK$,FH]355J30ZL +MTI2&]4(7Y#@;**!\E+#^%2TJC4,5J74T452'CZHDRP1&56(*X-35/"1QI1Q$ +MF0@48;$_C*PZYD]15=*I63""7)C3`JE,\R-,&UV"+)7A`9PA'8#&3EV#ZV+" +M.$@L8$5+'`B0`4&5/O'0FP=2X,5A1/L99TE&`_,]/S#YR.E:7 +M0OEB#QU0;0@&%J``8$7^6Y!+P4^LI30P([P$14T3%K6&QE50.BB9:&8,AOH! +M4"@-UX1N/`*CF0.NHK9%&*SA`SP"(;JC2\XX9*($`39:Z(:8'L:CO6%.!YE* +M_Q0K_5.O=%)^L8+A(&UI%[$#SD,+*(`J@'!R*L00I$O2K=J(A0DP$*K:T`/\ +M(6+T5.?*%I+"9S&FR)2(,JWZ05M5Z6UUI3EB4G:6SQ):$JAI,2U_ZD25!$)&`L&R.I+A]:Q>J/%Z,.VQQC\%$%)91!QU`UA4-MB! +M&P`"P(/7$U8VXN.IA3)Z8<'#>SRS:#;-JMDURV;;K)M]LW`VSLK9.4MGZZR= +HO;-X-L_JV3W+9_NLG_VS@#;0"MI!2V@+K:$]M(@VT2K:1; Thu, 31 Oct 1996 09:29:47 -0800 (PST) +Received: from austin.bsdi.com (localhost [127.0.0.1]) by austin.bsdi.com (8.7.4/8.7.3) with ESMTP id KAA19250; Thu, 31 Oct 1996 10:28:18 -0700 (MST) +Message-Id: <199610311728.KAA19250@austin.bsdi.com> +To: Eric Allman +cc: marc@xfree86.org +Subject: Updated mailprio_0_93.shar +From: Tony Sanders +Organization: Berkeley Software Design, Inc. +Date: Thu, 31 Oct 1996 10:28:14 -0700 +Sender: sanders@austin.bsdi.com + +Eric, please update contrib/mailprio in the sendmail distribution +to this version at your convenience. Thanks. + +I've also made this available in: + ftp://ftp.earth.com/pub/postmaster/ + +mailprio_0_93.shar follows... + +#!/bin/sh +# This is a shell archive (produced by GNU sharutils 4.1). +# To extract the files from this archive, save it to some FILE, remove +# everything before the `!/bin/sh' line above, then type `sh FILE'. +# +# Made on 1996-10-31 10:07 MST by . +# +# Existing files will *not* be overwritten unless `-c' is specified. +# +# This shar contains: +# length mode name +# ------ ---------- ------------------------------------------ +# 8260 -rwxr-xr-x mailprio +# 3402 -rw-r--r-- mailprio.README +# 4182 -rwxr-xr-x mailprio_mkdb +# +touch -am 1231235999 $$.touch >/dev/null 2>&1 +if test ! -f 1231235999 && test -f $$.touch; then + shar_touch=touch +else + shar_touch=: + echo + echo 'WARNING: not restoring timestamps. Consider getting and' + echo "installing GNU \`touch', distributed in GNU File Utilities..." + echo +fi +rm -f 1231235999 $$.touch +# +# ============= mailprio ============== +if test -f 'mailprio' && test X"$1" != X"-c"; then + echo 'x - skipping mailprio (file already exists)' +else + echo 'x - extracting mailprio (text)' + sed 's/^X//' << 'SHAR_EOF' > 'mailprio' && +#!/usr/bin/perl +# +# mailprio,v 1.4 1996/10/31 17:03:52 sanders Exp +# Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 +# +# mailprio -- setup mail priorities for a mailing list +# +# Copyright 1994, 1996, Tony Sanders +# Rights are hereby granted to download, use, modify, sell, copy, and +# redistribute this software so long as the original copyright notice +# and this list of conditions remain intact and modified versions are +# noted as such. +# +# I would also very much appreciate it if you could send me a copy of +# any changes you make so I can possibly integrate them into my version. +# +# Options: +# -p priority_database -- Specify database to use if not default +# -q -- Process sendmail V8.8.X queue format files +# +# Sort mailing lists or sendmail queue files by mailprio database. +# Files listed on the command line are locked and then sorted in place, in +# the absence of any file arguments it will read STDIN and write STDOUT. +# +# Examples: +# mailprio < mailing-list > sorted_list +# mailprio mailing-list1 mailing-list2 mailing-list3 ... +# mailprio -q /var/spool/mqueue/qf* +# To double check results: +# sort sorted_list > checkit; sort orig-mailing-list | diff - checkit +# +# To get the maximum value from a transaction delay based priority +# function you need to reorder the distribution list (and the mail +# queue files for that matter) fairly often; you could even have +# your mailing list software reorder the list before each outgoing +# message. +# +$usage = "Usage: mailprio [-p priodb] [-q] [mailinglists ...]\n"; +$home = "/home/sanders/lists"; +$priodb = "$home/mailprio"; +$locking = "flock"; # "flock" or "fcntl" +X +# In shell, it would go more or less like this: +# old_mailprio > /tmp/a +# fgrep -f lists/inet-access /tmp/a | sed -e 's/^.......//' > /tmp/b +# ; /tmp/b contains list of known users, faster delivery first +# fgrep -v -f /tmp/b lists/inet-access > /tmp/c +# ; put all unknown stuff at the top of new list for now +# echo '# -----' >> /tmp/c +# cat /tmp/b >> /tmp/c +X +$qflag = 0; +while ($main'ARGV[0] =~ /^-/) { +X $args = shift; +X if ($args =~ m/\?/) { print $usage; exit 0; } +X if ($args =~ m/q/) { $qflag = 1; } +X if ($args =~ m/p/) { +X $priodb = shift || die $usage, "-p requires argument\n"; } +} +X +push(@main'ARGV, '-') if ($#ARGV < 0); +while ($file = shift @ARGV) { +X if ($file eq "-") { +X $source = "main'STDIN"; +X $sink = "main'STDOUT"; +X } else { +X $sink = $source = "FH"; +X open($source, "+< $file") || do { warn "$file: $!\n"; next; }; +X if (!defined &seize($source, &LOCK_EX | &LOCK_NB)) { +X # couldn't get lock, just skip it +X close($source); +X next; +X } +X } +X +X local(*list); +X &process($source, *list); +X +X # setup to write output +X if ($file ne "-") { +X # zero the file (FH is hardcoded because truncate requires it, sigh) +X seek(FH, 0, 0) || die "$file: seek: $!\n"; +X truncate(FH, 0) || die "$file: truncate: $!\n"; +X } +X +X # do the dirty work +X &output($sink, *list); +X +X close($sink) || warn "$file: $!\n"; # close clears the lock +X close($source); +} +X +sub process { +X # Setup %list and @list +X local($source, *list) = @_; +X local($addr, $canon); +X while ($addr = <$source>) { +X chop $addr; +X next if $addr =~ /^# ----- /; # that's our line +X push(@list, $addr), next if $addr =~ /^\s*#/; # save comments +X if ($qflag) { +X next if $addr =~ m/^\./; +X push(@list, $addr), next if !($addr =~ s/^(R[^:]*:)//); +X $Rflags = $1; +X } +X $canon = &canonicalize((&simplify_address($addr))[0]); +X unless (defined $canon) { +X warn "$file: no address found: $addr\n"; +X push(@list, ($qflag?$Rflags:'') . $addr); # save it as is +X next; +X } +X if (defined $list{$canon}) { +X warn "$file: duplicate: ``$addr -> $canon''\n"; +X push(@list, ($qflag?$Rflags:'') . $addr); # save it as is +X next; +X } +X $list{$canon} = $addr; +X } +} +X +sub output { +X local($sink, *list) = @_; +X +X local($to, *prio, *userprio, *useracct); +X dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n"; +X foreach $to (keys %list) { +X if (defined $prio{$to}) { +X # add to list of found users (%userprio) and remove from %list +X # so that we know what users were not yet prioritized +X $userprio{$to} = $prio{$to}; # priority +X $useracct{$to} = $list{$to}; # string +X delete $list{$to}; +X } +X } +X dbmclose(%prio); +X +X # Put all the junk we found at the very top +X # (this might not always be a feature) +X print $sink join("\n", @list), "\n" if int(@list); +X +X # prioritized list of users +X if (int(keys %userprio)) { +X print $sink '# ----- prioritized users', "\n" unless $qflag; +X foreach $to (sort by_userprio keys %userprio) { +X die "Opps! Something is seriously wrong with useracct: $to\n" +X unless defined $useracct{$to}; +X print $sink 'RFD:' if $qflag; +X print $sink $useracct{$to}, "\n"; +X } +X } +X +X # unprioritized users go last, fast accounts will get moved up eventually +X # XXX: should go before the "really slow" prioritized users? +X if (int(keys %list)) { +X print $sink '# ----- unprioritized users', "\n" unless $qflag; +X foreach $to (keys %list) { +X print $sink 'RFD:' if $qflag; +X print $sink $list{$to}, "\n"; +X } +X } +X +X print $sink ".\n" if $qflag; +} +X +sub by_userprio { +X # sort first by priority, then by key. +X $userprio{$a} <=> $userprio{$b} || $a cmp $b; +} +X +# REPL-LIB --------------------------------------------------------------- +X +sub canonicalize { +X local($addr) = @_; +X # lowercase, strip leading/trailing whitespace +X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr; +} +X +# @addrs = simplify_address($addr); +sub simplify_address { +X local($_) = shift; +X 1 while s/\([^\(\)]*\)//g; # strip comments +X 1 while s/"[^"]*"//g; # strip comments +X split(/,/); # split into parts +X foreach (@_) { +X 1 while s/.*<(.*)>.*/\1/; +X s/^\s+//; +X s/\s+$//; +X } +X @_; +} +X +### ---- ### +# +# Error codes +# +do 'errno.ph'; +eval 'sub ENOENT {2;}' unless defined &ENOENT; +eval 'sub EINTR {4;}' unless defined &EINTR; +eval 'sub EINVAL {22;}' unless defined &EINVAL; +X +# +# File locking +# +do 'sys/unistd.ph'; +eval 'sub SEEK_SET {0;}' unless defined &SEEK_SET; +X +do 'sys/file.ph'; +eval 'sub LOCK_SH {0x01;}' unless defined &LOCK_SH; +eval 'sub LOCK_EX {0x02;}' unless defined &LOCK_EX; +eval 'sub LOCK_NB {0x04;}' unless defined &LOCK_NB; +eval 'sub LOCK_UN {0x08;}' unless defined &LOCK_UN; +X +do 'fcntl.ph'; +eval 'sub F_GETFD {1;}' unless defined &F_GETFD; +eval 'sub F_SETFD {2;}' unless defined &F_SETFD; +eval 'sub F_GETFL {3;}' unless defined &F_GETFL; +eval 'sub F_SETFL {4;}' unless defined &F_SETFL; +eval 'sub O_NONBLOCK {0x0004;}' unless defined &O_NONBLOCK; +eval 'sub F_SETLK {8;}' unless defined &F_SETLK; # nonblocking +eval 'sub F_SETLKW {9;}' unless defined &F_SETLKW; # lockwait +eval 'sub F_RDLCK {1;}' unless defined &F_RDLCK; +eval 'sub F_UNLCK {2;}' unless defined &F_UNLCK; +eval 'sub F_WRLCK {3;}' unless defined &F_WRLCK; +$s_flock = "sslll"; # struct flock {type, whence, start, len, pid} +X +# return undef on failure +sub seize { +X local ($FH, $lock) = @_; +X local ($ret); +X if ($locking eq "flock") { +X $ret = flock($FH, $lock); +X return ($ret == 0 ? undef : 1); +X } else { +X local ($flock, $type) = 0; +X if ($lock & &LOCK_SH) { $type = &F_RDLCK; } +X elsif ($lock & &LOCK_EX) { $type = &F_WRLCK; } +X elsif ($lock & &LOCK_UN) { $type = &F_UNLCK; } +X else { $! = &EINVAL; return undef; } +X $flock = pack($s_flock, $type, &SEEK_SET, 0, 0, 0); +X $ret = fcntl($FH, ($lock & &LOCK_NB) ? &F_SETLK : &F_SETLKW, $flock); +X return ($ret == -1 ? undef : 1); +X } +} +SHAR_EOF + $shar_touch -am 1031100396 'mailprio' && + chmod 0755 'mailprio' || + echo 'restore of mailprio failed' + shar_count="`wc -c < 'mailprio'`" + test 8260 -eq "$shar_count" || + echo "mailprio: original size 8260, current size $shar_count" +fi +# ============= mailprio.README ============== +if test -f 'mailprio.README' && test X"$1" != X"-c"; then + echo 'x - skipping mailprio.README (file already exists)' +else + echo 'x - extracting mailprio.README (text)' + sed 's/^X//' << 'SHAR_EOF' > 'mailprio.README' && +mailprio README +X +mailprio.README,v 1.2 1996/10/31 17:03:54 sanders Exp +Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 +X +Copyright 1994, 1996, Tony Sanders +Rights are hereby granted to download, use, modify, sell, copy, and +redistribute this software so long as the original copyright notice +and this list of conditions remain intact and modified versions are +noted as such. +X +I would also very much appreciate it if you could send me a copy of +any changes you make so I can possibly integrate them into my version. +X +The current version of this and other related mail tools are available in: +X ftp://ftp.earth.com/pub/postmaster/ +X +Even with the new persistent host status in sendmail V8.8.X this +function can still reduce the lag time distributing mail to a large +group of people. It also makes it a little more likely that everyone +will get mailing list mail in the order sent which can help reduce +duplicate postings. Basically, the goal is to put slow hosts at +the bottom of the list so that as many fast hosts are delivered +as quickly as possible. +X +CONTENTS +======== +X +X mailprio.README -- simple docs +X mailprio -- the address sorter +X mailprio_mkdb -- builds the database for the sorter +X +X +CHANGES +======= +X Version 0.92 +X Initial public release. +X +X Version 0.93 +X Updated to make use of the (somewhat) new xdelay statistic. +X Changed -q flag to support new sendmail queue file format (RFD:). +X Fixed argument parsing bug. +X Fixed bug with database getting "garbage" in it. +X +X +CONFIGURATION +============= +X +X You need to edit each script and ensure proper configuration. +X +X In mailprio check: #!perl path, $home, $priodb, $locking +X +X In mailprio_mkdb check: #!perl path, $home, $priodb, $maillog +X +X +USAGE: mailprio +=============== +X +X Usage: mailprio [-p priodb] [-q] [mailinglists ...] +X -p priority_database -- Specify database to use if not default +X -q -- Process sendmail queue format files +X [USE WITH CAUTION] +X +X Sort mailing lists or sendmail V8 queue files by mailprio database. +X Files listed on the command line are locked and then sorted in place, in +X the absence of any file arguments it will read STDIN and write STDOUT. +X +X Examples: +X mailprio < mailing-list > sorted_list +X mailprio mailing-list1 mailing-list2 mailing-list3 ... +X mailprio -q /var/spool/mqueue/qf* [not recommended] +X To double check results: +X sort sorted_list > checkit; sort orig-mailing-list | diff - checkit +X +X NOTE: +X To get the maximum value from a transaction delay based priority +X function you need to reorder the distribution list (and the mail +X queue files for that matter) fairly often; you could even have +X your mailing list software reorder the list before each outgoing +X message. +X +X +USAGE: mailprio_mkdb +==================== +X +X Usage: mailprio_mkdb [-l maillog] [-p priodb] +X -l maillog -- Specify maillog to process if not default +X -p priority_database -- Specify database to use if not default +X +X Builds the mail priority database using information from the maillog. +X +X Run at least nightly before you rotate the maillog. If you are +X going to run mailprio more often than that then you will need to +X load the current maillog information before that will do any good +X (and to keep from reloading the same information you will need +X some kind of incremental maillog information to load from). +SHAR_EOF + $shar_touch -am 1031100396 'mailprio.README' && + chmod 0644 'mailprio.README' || + echo 'restore of mailprio.README failed' + shar_count="`wc -c < 'mailprio.README'`" + test 3402 -eq "$shar_count" || + echo "mailprio.README: original size 3402, current size $shar_count" +fi +# ============= mailprio_mkdb ============== +if test -f 'mailprio_mkdb' && test X"$1" != X"-c"; then + echo 'x - skipping mailprio_mkdb (file already exists)' +else + echo 'x - extracting mailprio_mkdb (text)' + sed 's/^X//' << 'SHAR_EOF' > 'mailprio_mkdb' && +#!/usr/bin/perl +# +# mailprio_mkdb,v 1.5 1996/10/31 17:03:53 sanders Exp +# Version 0.93 -- Thu Oct 31 09:42:25 MST 1996 +# +# mailprio_mkdb -- make mail priority database based on delay times +# +# Copyright 1994, 1996, Tony Sanders +# Rights are hereby granted to download, use, modify, sell, copy, and +# redistribute this software so long as the original copyright notice +# and this list of conditions remain intact and modified versions are +# noted as such. +# +# I would also very much appreciate it if you could send me a copy of +# any changes you make so I can possibly integrate them into my version. +# +# The average function moves the value around quite rapidly (half-steps) +# which may or may not be a feature. This version uses the new xdelay +# statistic (new as of sendmail V8) which is per transaction. We also +# weight the result based on the overall delay. +# +# Something that might be worth doing for systems that don't support +# xdelay would be to compute an approximation of the transaction delay +# by sorting by messages-id and delay then computing the difference +# between adjacent delay values. +# +# To get the maximum value from a transaction delay based priority +# function you need to reorder the distribution list (and the mail +# queue files for that matter) fairly often; you could even have +# your mailing list software reorder the list before each outgoing +# message. +X +$usage = "Usage: mailprio_mkdb [-l maillog] [-p priodb]\n"; +$home = "/home/sanders/lists"; +$maillog = "/var/log/maillog"; +$priodb = "$home/mailprio"; +X +while ($ARGV[0] =~ /^-/) { +X $args = shift; +X if ($args =~ m/\?/) { print $usage; exit 0; } +X if ($args =~ m/l/) { +X $maillog = shift || die $usage, "-l requires argument\n"; } +X if ($args =~ m/p/) { +X $priodb = shift || die $usage, "-p requires argument\n"; } +} +X +$SIG{'PIPE'} = 'handle_pipe'; +X +# will merge with existing information +dbmopen(%prio, $priodb, 0644) || die "$priodb: $!\n"; +&getlog_stats($maillog, *prio); +dbmclose(%prio); +exit(0); +X +sub handle_pipe { +X dbmclose(%prio); +} +X +sub getlog_stats { +X local($maillog, *stats) = @_; +X local($to, $delay); +X local($h, $m, $s); +X open(MAILLOG, "< $maillog") || die "$maillog: $!\n"; +X while () { +X next unless / to=/ && / stat=/; +X next if / stat=queued/; +X if (/ stat=sent/i) { +X # read delay and xdelay and convert to seconds +X ($delay) = (m/ delay=([^,]*),/); +X next unless $delay; +X ($h, $m, $s) = split(/:/, $delay); +X $delay = ($h * 60 * 60) + ($m * 60) + $s; +X +X ($xdelay) = (m/ xdelay=([^,]*),/); +X next unless $xdelay; +X ($h, $m, $s) = split(/:/, $xdelay); +X $xdelay = ($h * 60 * 60) + ($m * 60) + $s; +X +X # Now weight the delay factor by the transaction delay (xdelay). +X $xdelay /= 300; # [0 - 1(@5 min)] +X $xdelay += 0.5; # [0.5 - 1.5] +X $xdelay = 1.5 if $xdelay > 1.5; # clamp +X $delay *= $xdelay; # weight delay by xdelay +X } +X elsif (/, stat=/) { +X # delivery failure of some sort (i.e. bad) +X $delay = 432000; # force 5 days +X } +X $delay = 1000000 if $delay > 1000000; +X +X # filter the address(es); isn't perfect but is "good enough" +X $to = $_; $to =~ s/^.* to=//; +X 1 while $to =~ s/\([^\(\)]*\)//g; # strip comments +X 1 while $to =~ s/"[^"]*"//g; # strip comments +X $to =~ s/, .*//; # remove other stat info +X foreach $addr (&simplify_address($to)) { +X next unless $addr; +X $addr = &canonicalize($addr); +X $stats{$addr} = $delay unless defined $stats{$addr}; # init +X # pseudo-average in the new delay (half-steps) +X # simple, moving average +X $stats{$addr} = int(($stats{$addr} + $delay) / 2); +X } +X } +X close(MAILLOG); +} +X +# REPL-LIB --------------------------------------------------------------- +X +sub canonicalize { +X local($addr) = @_; +X # lowercase, strip leading/trailing whitespace +X $addr =~ y/A-Z/a-z/; $addr =~ s/^\s+//; $addr =~ s/\s+$//; $addr; +} +X +# @addrs = simplify_address($addr); +sub simplify_address { +X local($_) = shift; +X 1 while s/\([^\(\)]*\)//g; # strip comments +X 1 while s/"[^"]*"//g; # strip comments +X split(/,/); # split into parts +X foreach (@_) { +X 1 while s/.*<(.*)>.*/\1/; +X s/^\s+//; +X s/\s+$//; +X } +X @_; +} +SHAR_EOF + $shar_touch -am 1031100396 'mailprio_mkdb' && + chmod 0755 'mailprio_mkdb' || + echo 'restore of mailprio_mkdb failed' + shar_count="`wc -c < 'mailprio_mkdb'`" + test 4182 -eq "$shar_count" || + echo "mailprio_mkdb: original size 4182, current size $shar_count" +fi +exit 0 diff --git a/gnu/usr.sbin/sendmail/contrib/mh.patch b/gnu/usr.sbin/sendmail/contrib/mh.patch new file mode 100644 index 00000000000..7b23a5b71dd --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/mh.patch @@ -0,0 +1,193 @@ +Message-Id: <199309031900.OAA19417@ignatz.acs.depaul.edu> +To: bug-mh@ics.uci.edu +cc: mh-users@ics.uci.edu, eric@cs.berkeley.edu +Subject: MH-6.8.1/Sendmail 8.X (MH patch) updated +Date: Fri, 03 Sep 1993 14:00:46 -0500 +From: Dave Nelson + + + This patch will fix the "X-auth..." warnings from the newer +Sendmails (8.X) while continuing to work with the old sendmails. + + I think the following patch will make everyone happy. + + 1) Anybody with MH-6.8.1 can install this. It doesn't matter + what version of sendmail you're running. It doesn't matter + if you're not running sendmail (but it won't fix anything + for you). + + 2) No configuration file hacks. If the -client switch is + absent (the default), the new sendmails will get an EHLO + using what LocalName() returns as the hostname. On my systems, + this returns the FQDN. If the EHLO fails with a result between + 500 and 599 and the -client switch is not set, we give up on + sending EHLO/HELO and just go deliver the mail. + + 3) No new configuration options. + + 4) Retains the undocumented -client switch. One warning: it + is possible using the -client switch to cause the old sendmails + to return "I refuse to talk to myself". You could do this under + the old code as well. This will happen if you claim to be the + same system as the sendmail you're sending to is running on. + That's pointless, but possible. If you do this, just like under + the old code, you will get an error. + + 5) If you're running a site with both old and new sendmails, you only + have to build MH once. The code's the same; works with them + both. + + If you decide to install this, make sure that you look the patch +over and that you agree with what it is doing. It works for me, but I +can't test it on every possible combination. Make sure that it works +before you really install it for your users, if any. No promises. + + To install this, save this to a file in the mts/sendmail directory. +Feed it to patch. Patch will ignore the non-patch stuff. You should have +"mts sendmail/smtp" in your configuration file. This works with old and +new sendmails. Using "mts sendmail" will cause the new sendmails to +print an "X-auth..." warning about who owns the process piping the mail +message. I don't know of anyway of getting rid of these. + + mh-config (if necessary), make, make inst-all. + + +I hope this helps people. + +/dcn + +Dave Nelson +Academic Computer Services +DePaul University, Chicago + +*** smail.c Fri Sep 3 11:58:05 1993 +--- smail.c Fri Sep 3 11:57:27 1993 +*************** +*** 239,261 **** + return RP_RPLY; + } + +! if (client && *client) { +! doingEHLO = 1; +! result = smtalk (SM_HELO, "EHLO %s", client); +! doingEHLO = 0; + +! if (500 <= result && result <= 599) + result = smtalk (SM_HELO, "HELO %s", client); +! +! switch (result) { + case 250: +! break; + + default: + (void) sm_end (NOTOK); + return RP_RPLY; + } + } + + #ifndef ZMAILER + if (onex) +--- 239,276 ---- + return RP_RPLY; + } + +! doingEHLO = 1; +! result = smtalk (SM_HELO, "EHLO %s", +! (client && *client) ? client : LocalName()); +! doingEHLO = 0; +! +! switch (result) +! { +! case 250: +! break; + +! default: +! if (!(500 <= result && result <= 599)) +! { +! (void) sm_end (NOTOK); +! return RP_RPLY; +! } +! +! if (client && *client) +! { + result = smtalk (SM_HELO, "HELO %s", client); +! switch (result) +! { + case 250: +! break; + + default: + (void) sm_end (NOTOK); + return RP_RPLY; ++ } + } + } ++ + + #ifndef ZMAILER + if (onex) +*************** +*** 357,380 **** + return RP_RPLY; + } + +! if (client && *client) { +! doingEHLO = 1; +! result = smtalk (SM_HELO, "EHLO %s", client); +! doingEHLO = 0; + +! if (500 <= result && result <= 599) + result = smtalk (SM_HELO, "HELO %s", client); +! +! switch (result) { +! case 250: + break; + +! default: + (void) sm_end (NOTOK); + return RP_RPLY; + } + } +! + send_options: ; + if (watch && EHLOset ("XVRB")) + (void) smtalk (SM_HELO, "VERB on"); +--- 372,409 ---- + return RP_RPLY; + } + +! doingEHLO = 1; +! result = smtalk (SM_HELO, "EHLO %s", +! (client && *client) ? client : LocalName()); +! doingEHLO = 0; +! +! switch (result) +! { +! case 250: +! break; +! +! default: +! if (!(500 <= result && result <= 599)) +! { +! (void) sm_end (NOTOK); +! return RP_RPLY; +! } + +! if (client && *client) +! { + result = smtalk (SM_HELO, "HELO %s", client); +! switch (result) +! { +! case 250: + break; + +! default: + (void) sm_end (NOTOK); + return RP_RPLY; ++ } + } + } +! + send_options: ; + if (watch && EHLOset ("XVRB")) + (void) smtalk (SM_HELO, "VERB on"); diff --git a/gnu/usr.sbin/sendmail/contrib/mmuegel b/gnu/usr.sbin/sendmail/contrib/mmuegel new file mode 100644 index 00000000000..6db4a45189c --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/mmuegel @@ -0,0 +1,2079 @@ +From: "Michael S. Muegel" +Message-Id: <199307280818.AA08111@cssun6.corp.mot.com> +Subject: Re: contributed software +To: eric@cs.berkeley.edu (Eric Allman) +Date: Wed, 28 Jul 1993 03:18:02 -0500 (CDT) +In-Reply-To: <199307221853.LAA04266@mastodon.CS.Berkeley.EDU> from "Eric Allman" at Jul 22, 93 11:53:47 am +X-Mailer: ELM [version 2.4 PL22] +Mime-Version: 1.0 +Content-Type: text/plain; charset=US-ASCII +Content-Transfer-Encoding: 7bit +Content-Length: 69132 + +OK. Here is a new shell archive. + +Cheers, +-Mike + +---- Cut Here and feed the following to sh ---- +#!/bin/sh +# This is a shell archive (produced by shar 3.49) +# To extract the files from this archive, save it to a file, remove +# everything above the "!/bin/sh" line above, and type "sh file_name". +# +# made 07/28/1993 08:13 UTC by mmuegel@mot.com (Michael S. Muegel) +# Source directory /home/ustart/NeXT/src/mail-tools/dist/foo +# +# existing files will NOT be overwritten unless -c is specified +# +# This shar contains: +# length mode name +# ------ ---------- ------------------------------------------ +# 4308 -r--r--r-- README +# 12339 -r--r--r-- libs/date.pl +# 3198 -r--r--r-- libs/elapsed.pl +# 4356 -r--r--r-- libs/mail.pl +# 6908 -r--r--r-- libs/mqueue.pl +# 7024 -r--r--r-- libs/newgetopts.pl +# 4687 -r--r--r-- libs/strings1.pl +# 1609 -r--r--r-- libs/timespec.pl +# 5212 -r--r--r-- man/cqueue.1 +# 2078 -r--r--r-- man/postclip.1 +# 6647 -r-xr-xr-x src/cqueue +# 1836 -r-xr-xr-x src/postclip +# +# ============= README ============== +if test -f 'README' -a X"$1" != X"-c"; then + echo 'x - skipping README (File already exists)' +else +echo 'x - extracting README (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'README' && +------------------------------------------------------------------------------- +Document Revision Control Information: +X mmuegel +X /usr/local/ustart/src/mail-tools/dist/foo/README,v +X 1.1 of 1993/07/28 08:12:53 +------------------------------------------------------------------------------- +X +1. Introduction +--------------- +X +These tools may be of use to those sites using sendmail. Both are written in +Perl. Our site, Mot.COM, receives a ton of mail being a top-level domain +gateway. We have over 24 domains under us. Needless to say, we must have +a robust mail system or my head, and others, would be on the chopping block. +X +2. Description +-------------- +X +The first tool, cqueue, checks the sendmail queue for problems. We use +it to flag problems with subdomain mail servers (and even our own servers +once in a while ;-). We run it via a cron job every hour during the day. +You may find this too frequent, however. +X +The other program, postclip, is used to "filter" non-deliverable NDNs that +get sent to our Postmaster account now and then. This ensures privacy of +e-mail and helps avoid disk problems from huge NDNs. It is different than +a brute force "just keep the header" approach because it tries hard to keep +other parts of the message that look like non-delivery information. +X +Both have been used for some time at our site with no problems. Everything +you need should be in this distribution: source, manual pages, and support +libs. See the manual pages for a complete description of each tool. +X +3. Installation +--------------- +X +No fancy Makefile simply because these tools are all under a large +hierarchy at my site. Installation should be a snap, however. Install +the nroff(1) man(5) manual pages from the man subdirectory to the +appropriate directory on your system. This might be something like +/usr/local/man/man1. +X +Next, install all of the Perl libraries located in the lib subdirectory +to your Perl library area. /usr/local/lib/perl is a good bet. The person +who installed Perl at your site will be able to tell you for sure. +X +Finally, you need to install the programs. Note that cqueue wants to +run setuid root by default. This is because the sendmail queue is normally +only readable by root or some special group. In order to let any user +run this suidperl is used. suidperl allows a Perl program to run with the +privileges of another user. +X +You will have to edit both the cqueue and postclip programs to change +the #! line at the top of each. Just change the pathname to whatever is +appropriate on your system. Note that Larry Wall's fixin program from +the Camel book can also be used to do this. It is very handy. It changes +#! lines by looking at your PATH. +X +If you do not have suidperl on your system change the #! line in cqueue +to reference perl instead of suidperl. +X +You may also wish to change some constants in cqueue. $DEF_QUEUE should be +changed to your queue directory if it is not /usr/spool/mqueue. $DEF_TIME +could be changed easy enough also. It is the time spec for the time duration +after which a mail message will be reported on if the -a option has not been +specified. See the manual page for more information and the format of this +constant (same as the -t argument). Then again, neither of these has to +be changed. Command line options are there to override their default +values. +X +After you have edited the programs as necessary, all that remains is to +install them to some executable directory. Install postclip mode 555 +and cqueue mode 4555 with owner root (if using suidperl) or mode 555 +(if not using suidperl). +X +4. Gripes, Comments, Etc +------------------------ +X +If you start using either of these let me know. I have other mail tools I +will likely post in the future if these prove useful. Also, if you think +something is just plain dumb/wrong/stupid let me know! +X +Cheers, +-Mike +X +-- ++----------------------------------------------------------------------------+ +| Michael S. Muegel | Internet E-Mail: mmuegel@mot.com | +| UNIX Applications Startup Group | Moto Dist E-Mail: X10090 | +| Corporate Information Office | Voice: (708) 576-0507 | +| Motorola | Fax: (708) 576-4153 | ++----------------------------------------------------------------------------+ +SHAR_EOF +chmod 0444 README || +echo 'restore of README failed' +Wc_c="`wc -c < 'README'`" +test 4308 -eq "$Wc_c" || + echo 'README: original size 4308, current size' "$Wc_c" +fi +# ============= libs/date.pl ============== +if test ! -d 'libs'; then + echo 'x - creating directory libs' + mkdir 'libs' +fi +if test -f 'libs/date.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/date.pl (File already exists)' +else +echo 'x - extracting libs/date.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/date.pl' && +;# +;# Name +;# date.pl - Perl emulation of (the output side of) date(1) +;# +;# Synopsis +;# require "date.pl"; +;# $Date = &date(time); +;# $Date = &date(time, $format); +;# +;# Description +;# This package implements the output formatting functions of date(1) in +;# Perl. The format options are based on those supported by Ultrix 4.0 +;# plus a couple of additions from SunOS 4.1.1 and elsewhere: +;# +;# %a abbreviated weekday name - Sun to Sat +;# %A full weekday name - Sunday to Saturday +;# %b abbreviated month name - Jan to Dec +;# %B full month name - January to December +;# %c date and time in local format [+] +;# %C date and time in long local format [+] +;# %d day of month - 01 to 31 +;# %D date as mm/dd/yy +;# %e day of month (space padded) - ` 1' to `31' +;# %E day of month (with suffix: 1st, 2nd, 3rd...) +;# %f month of year (space padded) - ` 1' to `12' +;# %h abbreviated month name - Jan to Dec +;# %H hour - 00 to 23 +;# %i hour (space padded) - ` 1' to `12' +;# %I hour - 01 to 12 +;# %j day of the year (Julian date) - 001 to 366 +;# %k hour (space padded) - ` 0' to `23' +;# %l date in ls(1) format +;# %m month of year - 01 to 12 +;# %M minute - 00 to 59 +;# %n insert a newline character +;# %p ante-meridiem or post-meridiem indicator (AM or PM) +;# %r time in AM/PM notation +;# %R time as HH:MM +;# %S second - 00 to 59 +;# %t insert a tab character +;# %T time as HH:MM:SS +;# %u date/time in date(1) required format +;# %U week number, Sunday as first day of week - 00 to 53 +;# %V date-time in SysV touch format (mmddHHMMyy) +;# %w day of week - 0 (Sunday) to 6 +;# %W week number, Monday as first day of week - 00 to 53 +;# %x date in local format [+] +;# %X time in local format [+] +;# %y last 2 digits of year - 00 to 99 +;# %Y all 4 digits of year ~ 1700 to 2000 odd ? +;# %z time zone from TZ environment variable w/ a trailing space +;# %Z time zone from TZ environment variable +;# %% insert a `%' character +;# %+ insert a `+' character +;# +;# [+]: These may need adjustment to fit local conventions, see below. +;# +;# For the sake of compatibility, a leading `+' in the format +;# specificaiton is removed if present. +;# +;# Remarks +;# This is version 3.4 of date.pl +;# +;# An extension of `ctime.pl' by Waldemar Kebsch (kebsch.pad@nixpbe.UUCP), +;# as modified by Marion Hakanson (hakanson@ogicse.ogi.edu). +;# +;# Unlike date(1), unknown format tags are silently replaced by "". +;# +;# defaultTZ is a blatant hack, but I wanted to be able to get date(1) +;# like behaviour by default and there does'nt seem to be an easy (read +;# portable) way to get the local TZ name back... +;# +;# For a cheap date, try... +;# +;# #!/usr/local/bin/perl +;# require "date.pl"; +;# exit print (&date(time, shift @ARGV) . "\n") ? 0 : 1; +;# +;# This package is redistributable under the same terms as apply to +;# the Perl 4.0 release. See the COPYING file in your Perl kit for +;# more information. +;# +;# Please send any bug reports or comments to tmcgonigal@gallium.com +;# +;# Modification History +;# Nmemonic Version Date Who +;# +;# NONE 1.0 02feb91 Terry McGonigal (tmcgonigal@gallium.com) +;# Created from ctime.pl +;# +;# NONE 2.0 07feb91 tmcgonigal +;# Added some of Marion Hakanson (hakanson@ogicse.ogi.edu)'s ctime.pl +;# TZ handling changes. +;# +;# NONE 2.1 09feb91 tmcgonigal +;# Corrected week number calculations. +;# +;# NONE 2.2 21oct91 tmcgonigal +;# Added ls(1) date format, `%l'. +;# +;# NONE 2.3 06nov91 tmcgonigal +;# Added SysV touch(1) date-time format, `%V' (pretty thin as +;# mnemonics go, I know, but `t' and `T' were both gone already!) +;# +;# NONE 2.4 05jan92 tmcgonigal +;# Corrected slight (cosmetic) problem with %V replacment string +;# +;# NONE 3.0 09jul92 tmcgonigal +;# Fixed a couple of problems with &ls as pointed out by +;# Thomas Richter (richter@ki1.chemie.fu-berlin.de), thanks Thomas! +;# Also added a couple of SunOS 4.1.1 strftime-ish formats, %i and %k +;# for space padded hours (` 1' to `12' and ` 0' to `23' respectivly), +;# and %C for locale long date/time format. Changed &mH to take a +;# pad char parameter to make to evaled code for %i and %k simpler. +;# Added %E for suffixed day-of-month (ie 1st, 3rd, 4th etc). +;# +;# NONE 3.1 16jul92 tmcgonigal +;# Added `%u' format to generate date/time in date(1) required +;# format (ie '%y%m%d%H%M.%S'). +;# +;# NONE 3.2 23jan93 tmcgonigal +;# Added `%f' format to generate space padded month numbers, added +;# `%E' to the header comments, it seems to have been left out (and +;# I'm sure I wanted to use it at some point in the past...). +;# +;# NONE 3.3 03feb93 tmcgonigal +;# Corrected some problems with AM/PM handling pointed out by +;# Michael S. Muegel (mmuegel@mot.com). Thanks Michael, I hope +;# this is the behaviour you were looking for, it seems more +;# correct to me... +;# +;# NONE 3.4 26jul93 tmcgonigal +;# Incorporated some fixes provided by DaviD W. Sanderson +;# (dws@ssec.wisc.edu): February was spelled incorrectly and +;# &wkno() was always using the current year while calculating +;# week numbers, regardless of year implied by the time value +;# passed to &date(). DaviD also contributed an improved &date() +;# test script, thanks DaviD, I appreciate the effort. Finally, +;# changed my mailling address from @gvc.com to @gallium.com +;# to reflect, well, my new address! +;# +;# SccsId = "%W% %E%" +;# +require 'timelocal.pl'; +package date; +X +# Months of the year +@MoY = ('January', 'February', 'March', 'April', 'May', 'June', +X 'July', 'August', 'September','October', 'November', 'December'); +X +# days of the week +@DoW = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', +X 'Thursday', 'Friday', 'Saturday'); +X +# CUSTOMIZE - defaults +$defaultTZ = 'CST'; # time zone (hack!) +$defaultFMT = '%a %h %e %T %z%Y'; # format (ala date(1)) +X +# CUSTOMIZE - `local' formats +$locTF = '%T'; # time (as HH:MM:SS) +$locDF = '%D'; # date (as mm/dd/yy) +$locDTF = '%a %b %d %T %Y'; # date/time (as dow mon dd HH:MM:SS yyyy) +$locLDTF = '%i:%M:%S %p %A %B %E %Y'; # long date/time (as HH:MM:SS a/p day month dom yyyy) +X +# Time zone info +$TZ; # wkno needs this info too +X +# define the known format tags as associative keys with their associated +# replacement strings as values. Each replacement string should be +# an eval-able expresion assigning a value to $rep. These expressions are +# eval-ed, then the value of $rep is substituted into the supplied +# format (if any). +%Tags = ( '%a', q|($rep = $DoW[$wday])=~ s/^(...).*/\1/|, # abbr. weekday name - Sun to Sat +X '%A', q|$rep = $DoW[$wday]|, # full weekday name - Sunday to Saturday +X '%b', q|($rep = $MoY[$mon]) =~ s/^(...).*/\1/|, # abbr. month name - Jan to Dec +X '%B', q|$rep = $MoY[$mon]|, # full month name - January to December +X '%c', q|$rep = $locDTF; 1|, # date/time in local format +X '%C', q|$rep = $locLDTF; 1|, # date/time in local long format +X '%d', q|$rep = &date'pad($mday, 2, "0")|, # day of month - 01 to 31 +X '%D', q|$rep = '%m/%d/%y'|, # date as mm/dd/yy +X '%e', q|$rep = &date'pad($mday, 2, " ")|, # day of month (space padded) ` 1' to `31' +X '%E', q|$rep = &date'dsuf($mday)|, # day of month (w/suffix) `1st' to `31st' +X '%f', q|$rep = &date'pad($mon+1, 2, " ")|, # month of year (space padded) ` 1' to `12' +X '%h', q|$rep = '%b'|, # abbr. month name (same as %b) +X '%H', q|$rep = &date'pad($hour, 2, "0")|, # hour - 00 to 23 +X '%i', q|$rep = &date'ampmH($hour, " ")|, # hour (space padded ` 1' to `12' +X '%I', q|$rep = &date'ampmH($hour, "0")|, # hour - 01 to 12 +X '%j', q|$rep = &date'pad($yday+1, 3, "0")|, # Julian date 001 - 366 +X '%k', q|$rep = &date'pad($hour, 2, " ")|, # hour (space padded) ` 0' to `23' +X '%l', q|$rep = '%b %d ' . &date'ls($year)|, # ls(1) style date +X '%m', q|$rep = &date'pad($mon+1, 2, "0")|, # month of year - 01 to 12 +X '%M', q|$rep = &date'pad($min, 2, "0")|, # minute - 00 to 59 +X '%n', q|$rep = "\n"|, # insert a newline +X '%p', q|$rep = &date'ampmD($hour)|, # insert `AM' or `PM' +X '%r', q|$rep = '%I:%M:%S %p'|, # time in AM/PM notation +X '%R', q|$rep = '%H:%M'|, # time as HH:MM +X '%S', q|$rep = &date'pad($sec, 2, "0")|, # second - 00 to 59 +X '%t', q|$rep = "\t"|, # insert a tab +X '%T', q|$rep = '%H:%M:%S'|, # time as HH:MM:SS +X '%u', q|$rep = '%y%m%d%H%M.%S'|, # daaate/time in date(1) required format +X '%U', q|$rep = &date'wkno($year, $yday, 0)|, # week number (weeks start on Sun) - 00 to 53 +X '%V', q|$rep = '%m%d%H%M%y'|, # SysV touch(1) date-time format (mmddHHMMyy) +X '%w', q|$rep = $wday; 1|, # day of week - Sunday = 0 +X '%W', q|$rep = &date'wkno($year, $yday, 1)|, # week number (weeks start on Mon) - 00 to 53 +X '%x', q|$rep = $locDF; 1|, # date in local format +X '%X', q|$rep = $locTF; 1|, # time in local format +X '%y', q|($rep = $year) =~ s/..(..)/\1/|, # last 2 digits of year - 00 to 99 +X '%Y', q|$rep = "$year"; 1|, # full year ~ 1700 to 2000 odd +X '%z', q|$rep = $TZ eq "" ? "" : "$TZ "|, # time zone from TZ env var (w/trail. space) +X '%Z', q|$rep = $TZ; 1|, # time zone from TZ env. var. +X '%%', q|$rep = '%'; $adv=1|, # insert a `%' +X '%+', q|$rep = '+'| # insert a `+' +); +X +sub main'date { +X local($time, $format) = @_; +X local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst); +X local($pos, $tag, $rep, $adv) = (0, "", "", 0); +X +X # default to date/ctime format or strip leading `+'... +X if ($format eq "") { +X $format = $defaultFMT; +X } elsif ($format =~ /^\+/) { +X $format = $'; +X } +X +X # Use local time if can't find a TZ in the environment +X $TZ = defined($ENV{'TZ'}) ? $ENV{'TZ'} : $defaultTZ; +X ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = +X &gettime ($TZ, $time); +X +X # Hack to deal with 'PST8PDT' format of TZ +X # Note that this can't deal with all the esoteric forms, but it +X # does recognize the most common: [:]STDoff[DST[off][,rule]] +X if ($TZ =~ /^([^:\d+\-,]{3,})([+-]?\d{1,2}(:\d{1,2}){0,2})([^\d+\-,]{3,})?/) { +X $TZ = $isdst ? $4 : $1; +X } +X +X # watch out in 2070... +X $year += ($year < 70) ? 2000 : 1900; +X +X # now loop throught the supplied format looking for tags... +X while (($pos = index ($format, '%')) != -1) { +X +X # grab the format tag +X $tag = substr($format, $pos, 2); +X $adv = 0; # for `%%' processing +X +X # do we have a replacement string? +X if (defined $Tags{$tag}) { +X +X # trap dead evals... +X if (! eval $Tags{$tag}) { +X print STDERR "date.pl: internal error: eval for $tag failed: $@\n"; +X return ""; +X } +X } else { +X $rep = ""; +X } +X +X # do the substitution +X substr ($format, $pos, 2) =~ s/$tag/$rep/; +X $pos++ if ($adv); +X } +X +X $format; +} +X +# dsuf - add `st', `nd', `rd', `th' to a date (ie 1st, 22nd, 29th) +sub dsuf { +X local ($mday) = @_; +X +X return $mday . 'st' if ($mday =~ m/.*1$/); +X return $mday . 'nd' if ($mday =~ m/.*2$/); +X return $mday . 'rd' if ($mday =~ m/.*3$/); +X return $mday . 'th'; +} +X +# weekno - figure out week number +sub wkno { +X local ($year, $yday, $firstweekday) = @_; +X local ($jan1, @jan1, $wks); +X +X # figure out the `time' value for January 1 of the given year +X $jan1 = &maketime ($TZ, 0, 0, 0, 1, 0, $year-1900); +X +X # figure out what day of the week January 1 was +X @jan1= &gettime ($TZ, $jan1); +X +X # and calculate the week number +X $wks = (($yday + ($jan1[6] - $firstweekday)) + 1)/ 7; +X $wks += (($wks - int($wks) > 0.0) ? 1 : 0); +X +X # supply zero padding +X &pad (int($wks), 2, "0"); +} +X +# ampmH - figure out am/pm (1 - 12) mode hour value, padded with $p (0 or ' ') +sub ampmH { local ($h, $p) = @_; &pad($h>12 ? $h-12 : ($h ? $h : 12), 2, $p); } +X +# ampmD - figure out am/pm designator +sub ampmD { shift @_ >= 12 ? "PM" : "AM"; } +X +# gettime - get the time via {local,gmt}time +sub gettime { ((shift @_) eq 'GMT') ? gmtime(shift @_) : localtime(shift @_); } +X +# maketime - make a time via time{local,gmt} +sub maketime { ((shift @_) eq 'GMT') ? &main'timegm(@_) : &main'timelocal(@_); } +X +# ls - generate the time/year portion of an ls(1) style date +sub ls { +X return ((&gettime ($TZ, time))[5] == @_[0]) ? "%R" : " %Y"; +} +X +# pad - pad $in with leading $pad until lenght $len +sub pad { +X local ($in, $len, $pad) = @_; +X local ($out) = "$in"; +X +X $out = $pad . $out until (length ($out) == $len); +X return $out; +} +X +1; +SHAR_EOF +chmod 0444 libs/date.pl || +echo 'restore of libs/date.pl failed' +Wc_c="`wc -c < 'libs/date.pl'`" +test 12339 -eq "$Wc_c" || + echo 'libs/date.pl: original size 12339, current size' "$Wc_c" +fi +# ============= libs/elapsed.pl ============== +if test -f 'libs/elapsed.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/elapsed.pl (File already exists)' +else +echo 'x - extracting libs/elapsed.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/elapsed.pl' && +;# NAME +;# elapsed.pl - convert seconds to elapsed time format +;# +;# AUTHOR +;# Michael S. Muegel +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/elapsed.pl,v +;# 1.1 of 1993/07/28 08:07:19 +X +package elapsed; +X +# Time field types +$DAYS = 1; +$HOURS = 2; +$MINUTES = 3; +$SECONDS = 4; +X +# The array contains four records each with four fields. The fields are, +# in order: +# +# Type Specifies what kind of time field this is. Once of +# $DAYS, $HOURS, $MINUTES, or $SECONDS. +# +# Multiplier Specifies what time field this is via the minimum +# number of seconds this time field may specify. For +# example, the minutes field would be non-zero +# when there are 60 or more seconds. +# +# Separator How to separate this time field from the next +# *greater* field. +# +# Format sprintf() format specifier on how to print this +# time field. +@MULT_AND_SEPS = ($DAYS, 60 * 60 * 24, "+", "%d", +X $HOURS, 60 * 60, ":", "%d", +X $MINUTES, 60, ":", "%02d", +X $SECONDS, 1, "", "%02d" +X ); +X +;############################################################################### +;# Seconds_To_Elapsed +;# +;# Coverts a seconds count to form [d+]h:mm:ss. If $Collapse +;# is true then the result is compacted somewhat. The string returned +;# will be of the form [d+][[h:]mm]:ss. +;# +;# Arguments: +;# $Seconds, $Collapse +;# +;# Examples: +;# &Seconds_To_Elapsed (0, 0) -> 0:00:00 +;# &Seconds_To_Elapsed (0, 1) -> :00 +;# +;# &Seconds_To_Elapsed (119, 0) -> 0:01:59 +;# &Seconds_To_Elapsed (119, 1) -> 01:59 +;# +;# &Seconds_To_Elapsed (3601, 0) -> 1:00:01 +;# &Seconds_To_Elapsed (3601, 1) -> 1:00:01 +;# +;# &Seconds_To_Elapsed (86401, 0) -> 1+0:00:01 +;# &Seconds_To_Elapsed (86401, 1) -> 1+:01 +;# +;# Returns: +;# $Elapsed +;############################################################################### +sub main'Seconds_To_Elapsed +{ +X local ($Seconds, $Collapse) = @_; +X local ($Type, $Multiplier, @Multipliers, $Separator, $DHMS_Used, +X $Elapsed, @Mult_And_Seps, $Print_Field); +X +X $Multiplier = 1; +X @Mult_And_Seps = @MULT_AND_SEPS; +X +X # Keep subtracting the number of seconds corresponding to a time field +X # from the number of seconds passed to the function. +X while (1) +X { +X ($Type, $Multiplier, $Separator, $Format) = splice (@Mult_And_Seps, 0, 4); +X last if (! $Multiplier); +X $Seconds -= $DHMS_Used * $Multiplier +X if ($DHMS_Used = int ($Seconds / $Multiplier)); +X +X # Figure out if we should print this field +X if ($Type == $DAYS) +X { +X $Print_Field = $DHMS_Used; +X } +X +X elsif ($Collapse) +X { +X if ($Type == $HOURS) +X { +X $Print_Field = $DHMS_Used; +X } +X elsif ($Type == $MINUTES) +X { +X $Print_Field = $DHMS_Used || $Printed_Field {$HOURS}; +X } +X else +X { +X $Format = ":%02d" +X if (! $Printed_Field {$MINUTES}); +X $Print_Field = 1; +X }; +X } +X +X else +X { +X $Print_Field = 1; +X }; +X +X $Printed_Field {$Type} = $Print_Field; +X $Elapsed .= sprintf ("$Format%s", $DHMS_Used, $Separator) +X if ($Print_Field); +X }; +X +X return ($Elapsed); +}; +X +1; +SHAR_EOF +chmod 0444 libs/elapsed.pl || +echo 'restore of libs/elapsed.pl failed' +Wc_c="`wc -c < 'libs/elapsed.pl'`" +test 3198 -eq "$Wc_c" || + echo 'libs/elapsed.pl: original size 3198, current size' "$Wc_c" +fi +# ============= libs/mail.pl ============== +if test -f 'libs/mail.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/mail.pl (File already exists)' +else +echo 'x - extracting libs/mail.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/mail.pl' && +;# NAME +;# mail.pl - perl function(s) to handle mail processing +;# +;# AUTHOR +;# Michael S. Muegel (mmuegel@mot.com) +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/mail.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp +X +package mail; +X +# Mailer statement to eval. $Users, $Subject, and $Verbose are substituted +# via eval +$BIN_MAILER = "/usr/ucb/mail \$Verbose -s '\$Subject' \$Users"; +X +# Sendmail command to use when $Use_Sendmail is true. +$SENDMAIL = '/usr/lib/sendmail $Verbose $Users'; +X +;############################################################################### +;# Send_Mail +;# +;# Sends $Message to $Users with a subject of $Subject. If $Message_Is_File +;# is true then $Message is assumed to be a filename pointing to the mail +;# message. This is a new option and thus the backwards-compatible hack. +;# $Users should be a space separated list of mail-ids. +;# +;# If everything went OK $Status will be 1 and $Error_Msg can be ignored; +;# otherwise, $Status will be 0 and $Error_Msg will contain an error message. +;# +;# If $Use_Sendmail is 1 then sendmail is used to send the message. Normally +;# a mailer such as Mail is used. By specifiying this you can include +;# headers in addition to text in either $Message or $Message_Is_File. +;# If either $Message or $Message_Is_File contain a Subject: header then +;# $Subject is ignored; otherwise, a Subject: header is automatically created. +;# Similar to the Subject: header, if a To: header does not exist one +;# is automatically created from the $Users argument. The mail is still +;# sent, however, to the recipients listed in $Users. This is keeping with +;# normal sendmail usage (header vs. envelope). +;# +;# In both bin mailer and sendmail modes $Verbose will turn on verbose mode +;# (normally just sendmail verbose mode output). +;# +;# Arguments: +;# $Users, $Subject, $Message, $Message_Is_File, $Verbose, $Use_Sendmail +;# +;# Returns: +;# $Status, $Error_Msg +;############################################################################### +sub main'Send_Mail +{ +X local ($Users, $Subject, $Message, $Message_Is_File, $Verbose, +X $Use_Sendmail) = @_; +X local ($BIN_MAILER_HANDLE, $Mailer_Command, $Header_Found, %Header_Map, +X $Header_Extra, $Mailer); +X +X # If the message is contained in a file read it in so we can have one +X # consistent interface +X if ($Message_Is_File) +X { +X undef $/; +X $Message_Is_File = 0; +X open (Message) || return (0, "error reading $Message: $!"); +X $Message = ; +X close (Message); +X }; +X +X # If sendmail mode see if we need to add some headers +X if ($Use_Sendmail) +X { +X # Determine if a header block is included in the message and what headers +X # are there +X foreach (split (/\n/, $Message)) +X { +X last if ($_ eq ""); +X $Header_Found = $Header_Map {$1} = 1 if (/^([A-Z]\S*): /); +X }; +X +X # Add some headers? +X if (! $Header_Map {"To"}) +X { +X $Header_Extra .= "To: " . join (", ", $Users) . "\n"; +X }; +X if (($Subject ne "") && (! $Header_Map {"Subject"})) +X { +X $Header_Extra .= "Subject: $Subject\n"; +X }; +X +X # Add the required blank line between header/body if there where no +X # headers to begin with +X if ($Header_Found) +X { +X $Message = "$Header_Extra$Message"; +X } +X else +X { +X $Message = "$Header_Extra\n$Message"; +X }; +X }; +X +X # Get a string that is the mail command +X $Verbose = ($Verbose) ? "-v" : ""; +X $Mailer = ($Use_Sendmail) ? $SENDMAIL : $BIN_MAILER; +X eval "\$Mailer = \"$Mailer\""; +X return (0, "error setting \$Mailer: $@") if ($@); +X +X # need to catch SIGPIPE in case the $Mailer call fails +X $SIG {'PIPE'} = "mail'Cleanup"; +X +X # Open mailer +X return (0, "can not open mail program: $Mailer") if (! open (MAILER, "| $Mailer")); +X +X # Send off the mail! +X print MAILER $Message; +X close (MAILER); +X return (0, "error running mail program: $Mailer") if ($?); +X +X # Everything must have went AOK +X return (1); +}; +X +;############################################################################### +;# Cleanup +;# +;# Simply here so we can catch SIGPIPE and not exit. +;# +;# Globals: +;# None +;# +;# Arguments: +;# None +;# +;# Returns: +;# Nothing exciting +;############################################################################### +sub Cleanup +{ +}; +X +1; +SHAR_EOF +chmod 0444 libs/mail.pl || +echo 'restore of libs/mail.pl failed' +Wc_c="`wc -c < 'libs/mail.pl'`" +test 4356 -eq "$Wc_c" || + echo 'libs/mail.pl: original size 4356, current size' "$Wc_c" +fi +# ============= libs/mqueue.pl ============== +if test -f 'libs/mqueue.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/mqueue.pl (File already exists)' +else +echo 'x - extracting libs/mqueue.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/mqueue.pl' && +;# NAME +;# mqueue.pl - functions to work with the sendmail queue +;# +;# DESCRIPTION +;# Both Get_Queue_IDs and Parse_Control_File are available to get +;# information about the sendmail queue. The cqueue program is a good +;# example of how these functions work. +;# +;# AUTHOR +;# Michael S. Muegel (mmuegel@mot.com) +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/mqueue.pl,v +;# 1.1 of 1993/07/28 08:07:19 +X +package mqueue; +X +;############################################################################### +;# Get_Queue_IDs +;# +;# Will figure out the queue IDs in $Queue that have both control and data +;# files. They are returned in @Valid_IDs. Those IDs that have a +;# control file and no data file are saved to the array globbed by +;# *Missing_Control_IDs. Likewise, those IDs that have a data file and no +;# control file are saved to the array globbed by *Missing_Data_IDs. +;# +;# If $Skip_Locked is true they a message that has a lock file is skipped +;# and will not show up in any of the arrays. +;# +;# If everything went AOK then $Status is 1; otherwise, $Status is 0 and +;# $Msg tells what went wrong. +;# +;# Globals: +;# None +;# +;# Arguments: +;# $Queue, $Skip_Locked, *Missing_Control_IDs, *Missing_Data_IDs +;# +;# Returns: +;# $Status, $Msg, @Valid_IDs +;############################################################################### +sub main'Get_Queue_IDs +{ +X local ($Queue, $Skip_Locked, *Missing_Control_IDs, +X *Missing_Data_IDs) = @_; +X local (*QUEUE, @Files, %Lock_IDs, %Data_IDs, %Control_IDs, $_); +X +X # Make sure that the * argument @arrays ar empty +X @Missing_Control_IDs = @Missing_Data_IDs = (); +X +X # Save each data, lock, and queue file in @Files +X opendir (QUEUE, $Queue) || return (0, "error getting directory listing of $Queue"); +X @Files = grep (/^(df|lf|qf)/, readdir (QUEUE)); +X closedir (QUEUE); +X +X # Create indexed list of data and control files. IF $Skip_Locked is true +X # then skip either if there is a lock file present. +X if ($Skip_Locked) +X { +X grep ((s/^lf//) && ($Lock_IDs {$_} = 1), @Files); +X grep ((s/^df//) && (! $Lock_IDs {$_}) && ($Data_IDs {$_} = 1), @Files); +X grep ((s/^qf//) && (! $Lock_IDs {$_}) && ($Control_IDs {$_} = 1), @Files); +X } +X else +X { +X grep ((s/^df//) && ($Data_IDs {$_} = 1), @Files); +X grep ((s/^qf//) && ($Control_IDs {$_} = 1), @Files); +X }; +X +X # Find missing control and data files and remove them from the lists of each +X @Missing_Control_IDs = sort (grep ((! $Control_IDs {$_}) && (delete $Data_IDs {$_}), keys (%Data_IDs))); +X @Missing_Data_IDs = sort (grep ((! $Data_IDs {$_} && (delete $Control_IDs {$_})), keys (%Control_IDs))); +X +X +X # Return the IDs in an appartently random order +X return (1, "", keys (%Control_IDs)); +}; +X +X +;############################################################################### +;# Parse_Control_File +;# +;# Will pase a sendmail queue control file for useful information. See the +;# Sendmail Installtion and Operation Guide (SMM:07) for a complete +;# explanation of each field. +;# +;# The following globbed variables are set (or cleared) by this function: +;# +;# $Sender The sender's address. +;# +;# @Recipients One or more addresses for the recipient of the mail. +;# +;# @Errors_To One or more addresses for addresses to which mail +;# delivery errors should be sent. +;# +;# $Creation_Time The job creation time in time(3) format. That is, +;# seconds since 00:00:00 GMT 1/1/70. +;# +;# $Priority An integer representing the current message priority. +;# This is used to order the queue. Higher numbers mean +;# lower priorities. +;# +;# $Status_Message The status of the mail message. It can contain any +;# text. +;# +;# @Headers Message headers unparsed but in their original order. +;# Headers that span multiple lines are not mucked with, +;# embedded \ns will be evident. +;# +;# In all e-mail addresses bounding <> pairs are stripped. +;# +;# If everything went AOK then $Status is 1. If the message with queue ID +;# $Queue_ID just does not exist anymore -1 is returned. This is very +;# possible and should be allowed for. Otherwise, $Status is 0 and $Msg +;# tells what went wrong. +;# +;# Globals: +;# None +;# +;# Arguments: +;# $Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, +;# *Priority, *Status_Message, *Headers +;# +;# Returns: +;# $Status, $Msg +;############################################################################### +sub main'Parse_Control_File +{ +X local ($Queue, $Queue_ID, *Sender, *Recipients, *Errors_To, *Creation_Time, +X *Priority, *Status_Message, *Headers) = @_; +X local (*Control, $_, $Not_Empty); +X +X # Required variables and the associated control. If empty at the end of +X # parsing we return a bad status. +X @REQUIRED_INFO = ('$Creation_Time', 'T', '$Sender', 'S', '@Recipients', 'R', +X '$Priority', 'P'); +X +X # Open up the control file for read +X $Control = "$Queue/qf$Queue_ID"; +X if (! open (Control)) +X { +X return (-1) if ((-x $Queue) && (! -f "$Queue/qf$Queue_ID") && +X (! -f "$Queue/df$Queue_ID")); +X return (0, "error opening $Control for read: $!"); +X }; +X +X # Reset the globbed variables just in case +X $Sender = $Creation_Time = $Priority = $Status_Message = ""; +X @Recipients = @Errors_To = @Headers = (); +X +X # Look for a few things in the control file +X READ: while () +X { +X $Not_Empty = 1; +X chop; +X +X PARSE: +X { +X if (/^T(\d+)$/) +X { +X $Creation_Time = $1; +X } +X elsif (/^S(<)?([^>]+)/) +X { +X $Sender = $2; +X } +X elsif (/^R(<)?([^>]+)/) +X { +X push (@Recipients, $2); +X } +X elsif (/^E(<)?([^>]+)/) +X { +X push (@Errors_To, $2); +X } +X elsif (/^M(.*)/) +X { +X $Status_Message = $1; +X } +X elsif (/^P(\d+)$/) +X { +X $Priority = $1; +X } +X elsif (/^H(.*)/) +X { +X $Header = $1; +X while () +X { +X chop; +X last if (/^[A-Z]/); +X $Header .= "\n$_"; +X }; +X push (@Headers, $Header); +X redo PARSE if ($_); +X last if (eof); +X }; +X }; +X }; +X +X # If the file was empty scream bloody murder +X return (0, "empty control file") if (! $Not_Empty); +X +X # Yell if we could not find a required field +X while (($Var, $Control) = splice (@REQUIRED_INFO, 0, 2)) +X { +X eval "return (0, 'required control field $Control not found') +X if (! $Var)"; +X return (0, "error checking \$Var: $@") if ($@); +X }; +X +X # Everything went AOK +X return (1); +}; +X +1; +SHAR_EOF +chmod 0444 libs/mqueue.pl || +echo 'restore of libs/mqueue.pl failed' +Wc_c="`wc -c < 'libs/mqueue.pl'`" +test 6908 -eq "$Wc_c" || + echo 'libs/mqueue.pl: original size 6908, current size' "$Wc_c" +fi +# ============= libs/newgetopts.pl ============== +if test -f 'libs/newgetopts.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/newgetopts.pl (File already exists)' +else +echo 'x - extracting libs/newgetopts.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/newgetopts.pl' && +;# NAME +;# newgetopts.pl - a better newgetopt (which is a better getopts which is +;# a better getopt ;-) +;# +;# AUTHOR +;# Mike Muegel (mmuegel@mot.com) +;# +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/newgetopts.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp +X +;############################################################################### +;# New_Getopts +;# +;# Does not care about order of switches, options, and arguments like +;# getopts.pl. Thus all non-switches/options will be kept in ARGV even if they +;# are not at the end. If $Pass_Invalid is set all unkown options will be +;# passed back to the caller by keeping them in @ARGV. This is useful when +;# parsing a command line for your script while ignoring options that you +;# may pass to another script. If this is set New_Getopts tries to maintain +;# the switch clustering on the unkown switches. +;# +;# Accepts the special argument -usage to print the Usage string. Also accepts +;# the special option -version which prints the contents of the string +;# $VERSION. $VERSION may or may not have an embeded \n in it. If -usage +;# or -version are specified a status of -1 is returned. Note that the usage +;# option is only accepted if the usage string is not null. +;# +;# $Switches is just like the formal arguemnt of getopts.pl. $Usage is a usage +;# string with or without a trailing \n. *Switch_To_Order is an optional +;# pointer to the name of an associative array which will contain a mapping of +;# switch names to the order in which (if at all) the argument was entered. +;# +;# For example, if @ARGV contains -v, -x, test: +;# +;# $Switch_To_Order {"v"} = 1; +;# $Switch_To_Order {"x"} = 2; +;# +;# Note that in the case of multiple occurances of an option $Switch_To_Order +;# will store each occurance of the argument via a string that emulates +;# an array. This is done by using join ($;, ...). You can retrieve the +;# array by using split (/$;/, ...). +;# +;# *Split_ARGV is an optional pointer to an array which will conatin the +;# original switches along with their values. For the example used above +;# Split_ARGV would contain: +;# +;# @Split_ARGV = ("v", "", "x", "test"); +;# +;# Another exciting ;-) feature that newgetopts has. Along with creating the +;# normal $opt_ scalars for the last value of an argument the list @opt_ is +;# created. It is an array which contains all the values of arguments to the +;# basename of the variable. They are stored in the order which they occured +;# on the command line starting with $[. Note that blank arguments are stored +;# as "". Along with providing support for multiple options on the command +;# line this also provides a method of counting the number of times an option +;# was specified via $#opt_. +;# +;# Automatically resets all $opt_, @opt_, %Switch_To_Order, and @Split_ARGV +;# variables so that New_Getopts may be called more than once from within +;# the same program. Thus, if $opt_v is set upon entry to New_Getopts and +;# -v is not in @ARGV $opt_v will not be set upon exit. +;# +;# Arguments: +;# $Switches, $Usage, $Pass_Invalid, *Switch_To_Order, *Split_ARGV +;# +;# Returns: +;# -1, 0, or 1 depending on status (printed Usage/Version, OK, not OK) +;############################################################################### +sub New_Getopts +{ +X local($taint_argumentative, $Usage, $Pass_Invalid, *Switch_To_Order, +X *Split_ARGV) = @_; +X local(@args,$_,$first,$rest,$errs, @leftovers, @current_leftovers, +X %Switch_Found); +X local($[, $*, $Script_Name, $argumentative); +X +X # Untaint the argument cluster so that we can use this with taintperl +X $taint_argumentative =~ /^(.*)$/; +X $argumentative = $1; +X +X # Clear anything that might still be set from a previous New_Getopts +X # call. +X @Split_ARGV = (); +X +X # Get the basename of the calling script +X ($Script_Name = $0) =~ s/.*\///; +X +X # Make Usage have a trailing \n +X $Usage .= "\n" if ($Usage !~ /\n$/); +X +X @args = split( / */, $argumentative ); +X +X # Clear anything that might still be set from a previous New_Getopts call. +X foreach $first (@args) +X { +X next if ($first eq ":"); +X delete $Switch_Found {$first}; +X delete $Switch_To_Order {$first}; +X eval "undef \@opt_$first; undef \$opt_$first;"; +X }; +X +X while (@ARGV) +X { +X # Let usage through +X if (($ARGV[0] eq "-usage") && ($Usage ne "\n")) +X { +X print $Usage; +X exit (-1); +X } +X +X elsif ($ARGV[0] eq "-version") +X { +X if ($VERSION) +X { +X print $VERSION; +X print "\n" if ($VERSION !~ /\n$/); +X } +X else +X { +X warn "${Script_Name}: no version information available, sorry\n"; +X } +X exit (-1); +X } +X +X elsif (($_ = $ARGV[0]) =~ /^-(.)(.*)/) +X { +X ($first,$rest) = ($1,$2); +X $pos = index($argumentative,$first); +X +X $Switch_To_Order {$first} = join ($;, split (/$;/, $Switch_To_Order {$first}), ++$Order); +X +X if($pos >= $[) +X { +X if($args[$pos+1] eq ':') +X { +X shift(@ARGV); +X if($rest eq '') +X { +X $rest = shift(@ARGV); +X } +X +X eval "\$opt_$first = \$rest;"; +X eval "push (\@opt_$first, \$rest);"; +X push (@Split_ARGV, $first, $rest); +X } +X else +X { +X eval "\$opt_$first = 1"; +X eval "push (\@opt_$first, '');"; +X push (@Split_ARGV, $first, ""); +X +X if($rest eq '') +X { +X shift(@ARGV); +X } +X else +X { +X $ARGV[0] = "-$rest"; +X } +X } +X } +X +X else +X { +X # Save any other switches if $Pass_Valid +X if ($Pass_Invalid) +X { +X push (@current_leftovers, $first); +X } +X else +X { +X warn "${Script_Name}: unknown option: $first\n"; +X ++$errs; +X }; +X if($rest ne '') +X { +X $ARGV[0] = "-$rest"; +X } +X else +X { +X shift(@ARGV); +X } +X } +X } +X +X else +X { +X push (@leftovers, shift (@ARGV)); +X }; +X +X # Save any other switches if $Pass_Valid +X if ((@current_leftovers) && ($rest eq '')) +X { +X push (@leftovers, "-" . join ("", @current_leftovers)); +X @current_leftovers = (); +X }; +X }; +X +X # Automatically print Usage if a warning was given +X @ARGV = @leftovers; +X if ($errs != 0) +X { +X warn $Usage; +X return (0); +X } +X else +X { +X return (1); +X } +X +} +X +1; +SHAR_EOF +chmod 0444 libs/newgetopts.pl || +echo 'restore of libs/newgetopts.pl failed' +Wc_c="`wc -c < 'libs/newgetopts.pl'`" +test 7024 -eq "$Wc_c" || + echo 'libs/newgetopts.pl: original size 7024, current size' "$Wc_c" +fi +# ============= libs/strings1.pl ============== +if test -f 'libs/strings1.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/strings1.pl (File already exists)' +else +echo 'x - extracting libs/strings1.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/strings1.pl' && +;# NAME +;# strings1.pl - FUN with strings #1 +;# +;# NOTES +;# I wrote Format_Text_Block when I just started programming Perl so +;# it is probably not very Perlish code. Center is more like it :-). +;# +;# AUTHOR +;# Michael S. Muegel (mmuegel@mot.com) +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/strings1.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp +X +package strings1; +X +;###############################################################################;# Center +;# +;# Center $Text assuming the output should be $Columns wide. $Text can span +;# multiple lines, of course :-). Lines within $Text that contain only +;# whitespace are not centered and are instead collapsed. This may save time +;# when printing them later. +;# +;# Arguments: +;# $Text, $Columns +;# +;# Returns: +;# $Centered_Text +;############################################################################### +sub main'Center +{ +X local ($_, $Columns) = @_; +X local ($*) = 1; +X +X s@^(.*)$@" " x (($Columns - length ($1)) / 2) . $1@eg; +X s/^[\t ]*$//g; +X return ($_); +}; +X +;############################################################################### +;# Format_Text_Block +;# +;# Formats a text string to be printed to the display or other similar device. +;# Text in $String will be fomratted such that the following hold: +;# +;# + $String contains the (possibly) multi-line text to print. It is +;# automatically word-wrapped to fit in $Columns. +;# +;# + \n'd are maintained and are not folded. +;# +;# + $Offset is pre-pended before each separate line of text. +;# +;# + If $Offset_Once is $TRUE $Offset will only appear on the first line. +;# All other lines will be indented to match the amount of whitespace of +;# $Offset. +;# +;# + If $Bullet_Indent is $TRUE $Offset will only be applied to the begining +;# of lines as they occured in the original $String. Lines that are created +;# by this routine will always be indented by blank spaces. +;# +;# + If $Columns is 0 no word-wrap is done. This might be useful to still +;# to offset each line in a buffer. +;# +;# + If $Split_Expr is supplied the string is split on it. If not supplied +;# the string is split on " \t\/\-\,\." by default. +;# +;# + If $Offset_Blank is $TRUE then empty lines will have $Offset pre-pended +;# to them. Otherwise, they will still empty. +;# +;# This is a realy workhorse routine that I use in many places because of its +;# veratility. +;# +;# Arguments: +;# $String, $Offset, $Offset_Once, $Bullet_Indent, $Columns, $Split_Expr, +;# $Offset_Blank +;# +;# Returns: +;# $Buffer +;############################################################################### +sub main'Format_Text_Block +{ +X local ($String, $Real_Offset, $Offset_Once, $Bullet_Indent, $Columns, +X $Split_Expr, $Offset_Blank) = @_; +X +X local ($New_Line, $Line, $Chars_Per_Line, $Space_Offset, $Buffer, +X $Next_New_Line, $Num_Lines, $Num_Offsets, $Offset); +X local ($*) = 0; +X local ($BLANK_TAG) = "__FORMAT_BLANK__"; +X local ($Blank_Offset) = $Real_Offset if ($Offset_Blank); +X +X # What should we split on? +X $Split_Expr = " \\t\\/\\-\\,\\." if (! $Split_Expr); +X +X # Pre-process the string - convert blank lines to __FORMAT_BLANK__ sequence +X $String =~ s/\n\n/\n$BLANK_TAG\n/g; +X $String =~ s/^\n/$BLANK_TAG\n/g; +X $String =~ s/\n$/\n$BLANK_TAG/g; +X +X # If bad $Columns/$Offset combo or no $Columns make a VERRRYYY wide $Column +X $Offset = $Real_Offset; +X $Chars_Per_Line = 16000 if (($Chars_Per_Line = $Columns - length ($Offset)) <= 0); +X $Space_Offset = " " x length ($Offset); +X +X # Get a buffer +X foreach $Line (split ("\n", $String)) +X { +X $Offset = $Real_Offset if ($Bullet_Indent); +X +X # Find where to split the line +X if ($Line ne $BLANK_TAG) +X { +X $New_Line = ""; +X while ($Line =~ /^([$Split_Expr]*)([^$Split_Expr]+)/) +X { +X if (length ("$New_Line$&") >= $Chars_Per_Line) +X { +X $Next_New_Line = $+; +X $New_Line = "$Offset$New_Line$1"; +X $Buffer .= "\n" if ($Num_Lines++); +X $Buffer .= $New_Line; +X $Offset = $Space_Offset if (($Offset) && ($Offset_Once)); +X $New_Line = $Next_New_Line; +X ++$Num_Lines; +X } +X else +X { +X $New_Line .= $&; +X }; +X $Line = $'; +X }; +X +X $Buffer .= "\n" if ($Num_Lines++); +X $Buffer .= "$Offset$New_Line$Line"; +X $Offset = $Space_Offset if (($Offset) && ($Offset_Once)); +X } +X +X else +X { +X $Buffer .= "\n$Blank_Offset"; +X }; +X }; +X +X return ($Buffer); +X +}; +X +1; +SHAR_EOF +chmod 0444 libs/strings1.pl || +echo 'restore of libs/strings1.pl failed' +Wc_c="`wc -c < 'libs/strings1.pl'`" +test 4687 -eq "$Wc_c" || + echo 'libs/strings1.pl: original size 4687, current size' "$Wc_c" +fi +# ============= libs/timespec.pl ============== +if test -f 'libs/timespec.pl' -a X"$1" != X"-c"; then + echo 'x - skipping libs/timespec.pl (File already exists)' +else +echo 'x - extracting libs/timespec.pl (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'libs/timespec.pl' && +;# NAME +;# timespec.pl - convert a pre-defined time specifyer to seconds +;# +;# AUTHOR +;# Michael S. Muegel (mmuegel@mot.com) +;# +;# RCS INFORMATION +;# mmuegel +;# /usr/local/ustart/src/mail-tools/dist/foo/libs/timespec.pl,v 1.1 1993/07/28 08:07:19 mmuegel Exp +X +package timespec; +X +%TIME_SPEC_TO_SECONDS = ("s", 1, +X "m", 60, +X "h", 60 * 60, +X "d", 60 * 60 * 24 +X ); +X +$VALID_TIME_SPEC_EXPR = "[" . join ("", keys (%TIME_SPEC_TO_SECONDS)) . "]"; +X +;############################################################################### +;# Time_Spec_To_Seconds +;# +;# Converts a string of the form: +;# +;# ((s|m|h|d))+ +;# +;# to seconds. The second part of the time spec specifies seconds, minutes, +;# hours, or days, respectfully. The first part is the number of those untis. +;# There can be any number of such specifiers. As an example, 1h30m means 1 +;# hour and 30 minutes. +;# +;# If the parsing went OK then $Status is 1, $Msg is undefined, and $Seconds +;# is $Time_Spec converted to seconds. If something went wrong then $Status +;# is 0 and $Msg explains what went wrong. +;# +;# Arguments: +;# $Time_Spec +;# +;# Returns: +;# $Status, $Msg, $Seconds +;############################################################################### +sub main'Time_Spec_To_Seconds +{ +X $Time_Spec = $_[0]; +X +X $Seconds = 0; +X while ($Time_Spec =~ /^(\d+)($VALID_TIME_SPEC_EXPR)/) +X { +X $Seconds += $1 * $TIME_SPEC_TO_SECONDS {$2}; +X $Time_Spec = $'; +X }; +X +X return (0, "error parsing time spec: $Time_Spec") if ($Time_Spec ne ""); +X return (1, "", $Seconds); +X +}; +X +X +1; +SHAR_EOF +chmod 0444 libs/timespec.pl || +echo 'restore of libs/timespec.pl failed' +Wc_c="`wc -c < 'libs/timespec.pl'`" +test 1609 -eq "$Wc_c" || + echo 'libs/timespec.pl: original size 1609, current size' "$Wc_c" +fi +# ============= man/cqueue.1 ============== +if test ! -d 'man'; then + echo 'x - creating directory man' + mkdir 'man' +fi +if test -f 'man/cqueue.1' -a X"$1" != X"-c"; then + echo 'x - skipping man/cqueue.1 (File already exists)' +else +echo 'x - extracting man/cqueue.1 (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'man/cqueue.1' && +.TH CQUEUE 1L +\" +\" mmuegel +\" /usr/local/ustart/src/mail-tools/dist/foo/man/cqueue.1,v 1.1 1993/07/28 08:08:25 mmuegel Exp +\" +.ds mp \fBcqueue\fR +.de IB +.IP \(bu 2 +.. +.SH NAME +\*(mp - check sendmail queue for problems +.SH SYNOPSIS +.IP \*(mp 7 +[ \fB-abdms\fR ] [ \fB-q\fR \fIqueue-dir\fI ] [ \fB-t\fR \fItime\fR ] +[ \fB-u\fR \fIusers\fR ] [ \fB-w\fR \fIwidth\fR ] +.SH DESCRIPTION +Reports on problems in the sendmail queue. With no options this simply +means listing messages that have been in the queue longer than a default +period along with a summary of queue mail by host and status message. +.SH OPTIONS +.IP \fB-a\fR 14 +Report on all messages in the queue. This is equivalent to saying \fB-t\fR 0s. +You may like this command so much that you use it as a replacement for +\fBmqueue\fR. For example: +.sp 1 +.RS +.RS +\fBalias mqueue cqueue -a\fR +.RE +.RE +.IP \fB-b\fR 14 +Also report on bogus queue files. Those are files that +have data files and no control files or vice versa. +.IP \fB-d\fR +Print a detailed report of mail messages that have been queued longer than +the specified or default time. Information that is presented includes: +.RS +.RS +.IB +Sendmail queue identifier. +.IB +Date the message was first queued. +.IB +Sender of the message. +.IB +One or more recipients of the message. +.IB +An optional status of the message. This usually indicates why the message +has not been delivered. +.RE +.RE +.IP \fB-m\fR 14 +Mail off the results if any problems were found. +Normaly results are printed to stdout. If this option +is specified they are mailed to one or more users. Results +are not printed to stdout in this case. Results are \fBonly\fR +mailed if \*(mp found something wrong. +.IP "\fB-q\fR \fIqueue-dir\fI" +The sendmail mail queue directory. Default is \fB/usr/spool/mqueue\fR or +some other site configured value. +.IP "\fB-t\fR \fItime\fR" +List messages that have been in the queue longer than +\fItime\fR. Time should of the form: +.sp 1 +.RS +.RS +((s|m|h|d))+ +.sp 1 +.RE +.RE +.RS 14 +The second portion of the above definition +specifies seconds, minutes, hours, or +days, respectfully. The first portion is the number of +those units. There can be any number of such specifiers. +As an example, 1h30m means 1 hour and 30 minutes. +.sp 1 +The default is 2 hours. +.RE +.IP \fB-s\fR 14 +Print a summary of messages that have been queued longer than +the specified or default time. Two separate types of summaries are printed. +The first summarizes the queue messages by destination host. The host name +is gleaned from the recipient addresses for each message. +Thus the actual host names for this summary should be taken with a grain +of salt since ruleset 0 has not been applied to the address the host was +taken from nor were MX records consulted. It would be possible to add +this; however, the execution time of the script would increase +dramatically. The second summary is by status message. +.IP "\fB-u\fR \fIusers\fR" +Specify list of users to send a mail report to other than +the invoker. This option is only valid when \fB-m\fR has been +specified. Multiple recipients may be separated by spaces. +.IP "\fB-w\fR \fIwidth\fR" +Specify the page width to which the output should tailored. \fIwidth\fR +should be an integer representing some character position. The default is +80 or some other site configured value. Output is folded neatly to match +\fIwidth\fR. +.SH EXAMPLES +.nf +% \fBdate\fR +Tue Jan 19 12:07:20 CST 1993 +X +% \fBcqueue -t 21h45m -w 70\fR +X +Summary of messages in queue longer than 21:45:00 by destination +host: +X +X Number of +X Messages Destination Host +X --------- ---------------- +X 2 cigseg.rtsg.mot.com +X 1 mnesouth.corp.mot.com +X --------- +X 3 +X +Summary of messages in queue longer than 21:45:00 by status message: +X +X Number of +X Messages Status Message +X --------- -------------- +X 1 Deferred: Connection refused by mnesouth.corp.mot.com +X 2 Deferred: Host Name Lookup Failure +X --------- +X 3 +X +Detail of messages in queue longer than 21:45:00 sorted by creation +date: +X +X ID: AA20573 +X Date: 02:09:27 PM 01/18/93 +X Sender: melrose-place-owner@ferkel.ucsb.edu +X Recipient: pbaker@cigseg.rtsg.mot.com +X Status: Deferred: Host Name Lookup Failure +X +X ID: AA20757 +X Date: 02:11:30 PM 01/18/93 +X Sender: 90210-owner@ferkel.ucsb.edu +X Recipient: pbaker@cigseg.rtsg.mot.com +X Status: Deferred: Host Name Lookup Failure +X +X ID: AA21110 +X Date: 02:17:01 PM 01/18/93 +X Sender: rd_lap_wg@mdd.comm.mot.com +X Recipient: jim_mathis@mnesouth.corp.mot.com +X Status: Deferred: Connection refused by mnesouth.corp.mot.com +.fi +.SH AUTHOR +.nf +Michael S. Muegel (mmuegel@mot.com) +UNIX Applications Startup Group +Corporate Information Office, Schaumburg, IL +Motorola, Inc. +.fi +.SH COPYRIGHT NOTICE +Copyright 1993, Motorola, Inc. +.sp 1 +Permission to use, copy, modify and distribute without charge this +software, documentation, etc. is granted, provided that this +comment and the author's name is retained. The author nor Motorola assume any +responsibility for problems resulting from the use of this software. +.SH SEE ALSO +.nf +\fBsendmail(8)\fR +\fISendmail Installation and Operation Guide\fR. +.fi +SHAR_EOF +chmod 0444 man/cqueue.1 || +echo 'restore of man/cqueue.1 failed' +Wc_c="`wc -c < 'man/cqueue.1'`" +test 5212 -eq "$Wc_c" || + echo 'man/cqueue.1: original size 5212, current size' "$Wc_c" +fi +# ============= man/postclip.1 ============== +if test -f 'man/postclip.1' -a X"$1" != X"-c"; then + echo 'x - skipping man/postclip.1 (File already exists)' +else +echo 'x - extracting man/postclip.1 (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'man/postclip.1' && +.TH POSTCLIP 1L +\" +\" mmuegel +\" /usr/local/ustart/src/mail-tools/dist/foo/man/postclip.1,v 1.1 1993/07/28 08:08:25 mmuegel Exp +\" +.ds mp \fBpostclip\fR +.SH NAME +\*(mp - send only the headers to Postmaster +.SH SYNOPSIS +\*(mp [ \fB-v\fR ] [ \fIto\fR ... ] +.SH DESCRIPTION +\*(mp will forward non-delivery reports to a postmaster after deleting the body +of the message. This keeps bounced mail private and helps to avoid disk space problems. \*(mp tries its best to keep as much of the header trail as possible. +Hopefully only the original body of the message will be filtered. Only messages +that have a subject that begins with 'Returned mail:' are filtered. This +ensures that other mail is not accidently mucked with. Finally, note that +\fBsendmail\fR is used to deliver the message after it has been (possibly) +filtered. All of the original headers will remain intact. +.sp 1 +You can use this with any \fBsendmail\fR by modifying the Postmaster alias. +If you use IDA \fBsendmail\fR you could add the following to .m4: +.sp 1 +.RS +define(POSTMASTERBOUNCE, mailer-errors) +.RE +.sp 1 +In the aliases file, add a line similar to the following: +.sp 1 +.RS +mailer-errors: "|/usr/local/bin/postclip postmaster" +.RE +.SH OPTIONS +.IP \fB-v\fR +Be verbose about delivery. Probably only useful when debugging \*(mp. +.IP \fIto\fR +A list of one or more e-mail ids to send the modified +Postmaster messages to. If none are specified postmaster +is used. +.SH AUTHOR +.nf +Michael S. Muegel (mmuegel@mot.com) +UNIX Applications Startup Group +Corporate Information Office, Schaumburg, IL +Motorola, Inc. +.fi +.SH CREDITS +The original idea to filter Postmaster mail was taken from a script by +Christopher Davis . +.SH COPYRIGHT NOTICE +Copyright 1992, Motorola, Inc. +.sp 1 +Permission to use, copy, modify and distribute without charge this +software, documentation, etc. is granted, provided that this +comment and the author's name is retained. The author nor Motorola assume any +responsibility for problems resulting from the use of this software. +.SH SEE ALSO +.nf +\fBsendmail(8)\fR +.fi +SHAR_EOF +chmod 0444 man/postclip.1 || +echo 'restore of man/postclip.1 failed' +Wc_c="`wc -c < 'man/postclip.1'`" +test 2078 -eq "$Wc_c" || + echo 'man/postclip.1: original size 2078, current size' "$Wc_c" +fi +# ============= src/cqueue ============== +if test ! -d 'src'; then + echo 'x - creating directory src' + mkdir 'src' +fi +if test -f 'src/cqueue' -a X"$1" != X"-c"; then + echo 'x - skipping src/cqueue (File already exists)' +else +echo 'x - extracting src/cqueue (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'src/cqueue' && +#!/usr/local/ustart/bin/suidperl +X +# NAME +# cqueue - check sendmail queue for problems +# +# SYNOPSIS +# Type cqueue -usage +# +# AUTHOR +# Michael S. Muegel +# +# RCS INFORMATION +# mmuegel +# /usr/local/ustart/src/mail-tools/dist/foo/src/cqueue,v 1.1 1993/07/28 08:09:02 mmuegel Exp +X +# So that date.pl does not yell (Domain/OS version does a ``) +$ENV{'PATH'} = ""; +X +# A better getopts routine +require "newgetopts.pl"; +require "timespec.pl"; +require "mail.pl"; +require "date.pl"; +require "mqueue.pl"; +require "strings1.pl"; +require "elapsed.pl"; +X +($Script_Name = $0) =~ s/.*\///; +X +# Some defaults you may want to change +$DEF_TIME = "2h"; +$DEF_QUEUE = "/usr/spool/mqueue"; +$DEF_COLUMNS = 80; +$DATE_FORMAT = "%r %D"; +X +# Constants that probably should not be changed +$USAGE = "Usage: $Script_Name [ -abdms ] [ -q queue-dir ] [ -t time ] [ -u user ] [ -w width ]\n"; +$VERSION = "${Script_Name} by mmuegel; 1.1 of 1993/07/28 08:09:02"; +$SWITCHES = "abdmst:u:q:w:"; +$SPLIT_EXPR = '\s,\.@!%:'; +$ADDR_PART_EXPR = '[^!@%]+'; +X +# Let getopts parse for switches +$Status = &New_Getopts ($SWITCHES, $USAGE); +exit (0) if ($Status == -1); +exit (1) if (! $Status); +X +# Check args +die "${Script_Name}: -u only valid with -m\n" if (($opt_u) && (! $opt_m)); +die "${Script_Name}: -a not valid with -t option\n" if ($opt_a && $opt_t); +$opt_u = getlogin || (getpwuid ($<))[0] || $ENV{"USER"} || die "${Script_Name}: can not determine who you are!\n" if (! $opt_u); +X +# Set defaults +$opt_t = "0s" if ($opt_a); +$opt_t = $DEF_TIME if ($opt_t eq ""); +$opt_w = $DEF_COLUMNS if ($opt_w eq ""); +$opt_q = $DEF_QUEUE if ($opt_q eq ""); +$opt_s = $opt_d = 1 if (! ($opt_s || $opt_d)); +X +# Untaint the users to mail to +$opt_u =~ /^(.*)$/; +$Users = $1; +X +# Convert time option to seconds and seconds to elapsed form +die "${Script_Name}: $Msg\n" if (! (($Status, $Msg, $Seconds) = &Time_Spec_To_Seconds ($opt_t))[0]); +$Elapsed = &Seconds_To_Elapsed ($Seconds, 1); +$Time_Info = " longer than $Elapsed" if ($Seconds); +X +# Get the current time +$Current_Time = time; +$Current_Date = &date ($Current_Time, $DATE_FORMAT); +X +($Status, $Msg, @Queue_IDs) = &Get_Queue_IDs ($opt_q, 1, @Missing_Control_IDs, +X @Missing_Data_IDs); +die "$Script_Name: $Msg\n" if (! $Status); +X +# Yell about missing data/control files? +if ($opt_b) +{ +X +X $Report = "\nMessages missing control files:\n\n " . +X join ("\n ", @Missing_Control_IDs) . +X "\n" +X if (@Missing_Control_IDs); +X +X $Report .= "\nMessages missing data files:\n\n " . +X join ("\n ", @Missing_Data_IDs) . +X "\n" +X if (@Missing_Data_IDs); +}; +X +# See if any mail messages are older than $Seconds +foreach $Queue_ID (@Queue_IDs) +{ +X # Get lots of info about this sendmail message via the control file +X ($Status, $Msg) = &Parse_Control_File ($opt_q, $Queue_ID, *Sender, +X *Recipients, *Errors_To, *Creation_Time, *Priority, *Status_Message, +X *Headers); +X next if ($Status == -1); +X if (! $Status) +X { +X warn "$Script_Name: $Queue_ID: $Msg\n"; +X next; +X }; +X +X # Report on message if it is older than $Seconds +X if ($Current_Time - $Creation_Time >= $Seconds) +X { +X # Build summary by host information. Keep track of each host destination +X # encountered. +X if ($opt_s) +X { +X %Host_Map = (); +X foreach (@Recipients) +X { +X if ((/@($ADDR_PART_EXPR)$/) || (/($ADDR_PART_EXPR)!$ADDR_PART_EXPR$/)) +X { +X ($Host = $1) =~ tr/A-Z/a-z/; +X $Host_Map {$Host} = 1; +X } +X else +X { +X warn "$Script_Name: could not find host part from $_; contact author\n"; +X }; +X }; +X +X # For each unique target host add to its stats +X grep ($Host_Queued {$_}++, keys (%Host_Map)); +X +X # Build summary by message information. +X $Message_Queued {$Status_Message}++ if ($Status_Message); +X }; +X +X # Build long report information for this creation time (there may be +X # more than one message created at the same time) +X if ($opt_d) +X { +X $Creation_Date = &date ($Creation_Time, $DATE_FORMAT); +X $Recipient_Info = &Format_Text_Block (join (", ", @Recipients), +X " Recipient: ", 1, 0, $opt_w, $SPLIT_EXPR); +X $Time_To_Report {$Creation_Time} .= <<"EOS"; +X +X ID: $Queue_ID +X Date: $Creation_Date +X Sender: $Sender +$Recipient_Info +EOS +X +X # Add the status message if available to long report +X if ($Status_Message) +X { +X $Time_To_Report {$Creation_Time} .= &Format_Text_Block ($Status_Message, +X " Status: ", 1, 0, $opt_w, $SPLIT_EXPR) . "\n"; +X }; +X }; +X }; +X +}; +X +# Add the summary report by target host? +if ($opt_s) +{ +X foreach $Host (sort (keys (%Host_Queued))) +X { +X $Host_Report .= &Format_Text_Block ($Host, +X sprintf (" %-9d ", $Host_Queued{$Host}), 1, 0, $opt_w, +X $SPLIT_EXPR) . "\n"; +X $Num_Hosts += $Host_Queued{$Host}; +X }; +X if ($Host_Report) +X { +X chop ($Host_Report); +X $Report .= &Format_Text_Block("\nSummary of messages in queue$Time_Info by destination host:\n", "", 0, 0, $opt_w); +X +X $Report .= <<"EOS"; +X +X Number of +X Messages Destination Host +X --------- ---------------- +$Host_Report +X --------- +X $Num_Hosts +EOS +X }; +}; +X +# Add the summary by message report? +if ($opt_s) +{ +X foreach $Message (sort (keys (%Message_Queued))) +X { +X $Message_Report .= &Format_Text_Block ($Message, +X sprintf (" %-9d ", $Message_Queued{$Message}), 1, 0, $opt_w, +X $SPLIT_EXPR) . "\n"; +X $Num_Messages += $Message_Queued{$Message}; +X }; +X if ($Message_Report) +X { +X chop ($Message_Report); +X $Report .= &Format_Text_Block ("\nSummary of messages in queue$Time_Info by status message:\n", "", 0, 0, $opt_w); +X +X $Report .= <<"EOS"; +X +X Number of +X Messages Status Message +X --------- -------------- +$Message_Report +X --------- +X $Num_Messages +EOS +X }; +}; +X +# Add the detailed message reports? +if ($opt_d) +{ +X foreach $Time (sort { $a <=> $b} (keys (%Time_To_Report))) +X { +X $Report .= &Format_Text_Block ("\nDetail of messages in queue$Time_Info sorted by creation date:\n","", 0, 0, $opt_w) if (! $Detailed_Header++); +X $Report .= $Time_To_Report {$Time}; +X }; +}; +X +# Now mail or print the report +if ($Report) +{ +X $Report .= "\n"; +X if ($opt_m) +X { +X ($Status, $Msg) = &Send_Mail ($Users, "sendmail queue report for $Current_Date", $Report, 0); +X die "${Script_Name}: $Msg" if (! $Status); +X } +X +X else +X { +X print $Report; +X }; +X +}; +X +# I am outta here... +exit (0); +SHAR_EOF +chmod 0555 src/cqueue || +echo 'restore of src/cqueue failed' +Wc_c="`wc -c < 'src/cqueue'`" +test 6647 -eq "$Wc_c" || + echo 'src/cqueue: original size 6647, current size' "$Wc_c" +fi +# ============= src/postclip ============== +if test -f 'src/postclip' -a X"$1" != X"-c"; then + echo 'x - skipping src/postclip (File already exists)' +else +echo 'x - extracting src/postclip (Text)' +sed 's/^X//' << 'SHAR_EOF' > 'src/postclip' && +#!/usr/local/bin/perl +X +# NAME +# postclip - send only the headers to Postmaster +# +# SYNOPSIS +# postclip [ -v ] [ to ... ] +# +# AUTHOR +# Michael S. Muegel +# +# RCS INFORMATION +# /usr/local/ustart/src/mail-tools/dist/foo/src/postclip,v +# 1.1 of 1993/07/28 08:09:02 +X +# We use this to send off the mail +require "newgetopts.pl"; +require "mail.pl"; +X +# Get the basename of the script +($Script_Name = $0) =~ s/.*\///; +X +# Some famous constants +$USAGE = "Usage: $Script_Name [ -v ] [ to ... ]\n"; +$VERSION = "${Script_Name} by mmuegel; 1.1 of 1993/07/28 08:09:02"; +$SWITCHES = "v"; +X +# Let getopts parse for switches +$Status = &New_Getopts ($SWITCHES, $USAGE); +exit (0) if ($Status == -1); +exit (1) if (! $Status); +X +# Who should we send the modified mail to? +@ARGV = ("postmaster") if (! @ARGV); +$Users = join (" ", @ARGV); +@ARGV = (); +X +# Suck in the original header and save a few interesting lines +while (<>) +{ +X $Buffer .= $_ if (! /^From /); +X $Subject = $1 if (/^Subject:\s+(.*)$/); +X $From = $1 if (/^From:\s+(.*)$/); +X last if (/^$/); +}; +X +# Do not filter the message unless it has a subject and the subject indicates +# it is an NDN +if ($Subject && ($Subject =~ /^returned mail/i)) +{ +X # Slurp input by paragraph. Keep track of the last time we saw what +X # appeared to be NDN text. We keep this. +X $/ = "\n\n"; +X $* = 1; +X while (<>) +X { +X push (@Paragraphs, $_); +X $Last_Error_Para = $#Paragraphs +X if (/unsent message follows/i || /was not delivered because/); +X }; +X +X # Now save the NDN text into $Buffer +X $Buffer .= join ("", @Paragraphs [0..$Last_Error_Para]); +} +X +else +{ +X undef $/; +X $Buffer .= <>; +}; +X +# Send off the (possibly) modified mail +($Status, $Msg) = &Send_Mail ($Users, "", $Buffer, 0, $opt_v, 1); +die "$Script_Name: $Msg\n" if (! $Status); +SHAR_EOF +chmod 0555 src/postclip || +echo 'restore of src/postclip failed' +Wc_c="`wc -c < 'src/postclip'`" +test 1836 -eq "$Wc_c" || + echo 'src/postclip: original size 1836, current size' "$Wc_c" +fi +exit 0 + +-- ++----------------------------------------------------------------------------+ +| Michael S. Muegel | Internet E-Mail: mmuegel@mot.com | +| UNIX Applications Startup Group | Moto Dist E-Mail: X10090 | +| Corporate Information Office | Voice: (708) 576-0507 | +| Motorola | Fax: (708) 576-4153 | ++----------------------------------------------------------------------------+ + + "I'm disturbed, I'm depressed, I'm inadequate -- I've got it all!" + -- George from _Seinfeld_ diff --git a/gnu/usr.sbin/sendmail/contrib/oldbind.compat.c b/gnu/usr.sbin/sendmail/contrib/oldbind.compat.c new file mode 100644 index 00000000000..1621a7ba5e8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/oldbind.compat.c @@ -0,0 +1,79 @@ +/* +** OLDBIND.COMPAT.C +** +** Very old systems do not have res_query(), res_querydomain() or +** res_search(), so emulate them here. +** +** You really ought to be upgrading to a newer version of BIND +** (4.8.2 or later) rather than be using this. +** +** J.R. Oldroyd +*/ + +#include +#include +#include +#include + +typedef union +{ + HEADER qb1; + char qb2[PACKETSZ]; +} querybuf; + +res_query(dname, class, type, data, datalen) + char * dname; + int class; + int type; + char * data; + int datalen; +{ + int n; + querybuf buf; + + n = res_mkquery(QUERY, dname, class, type, (char *) NULL, 0, + NULL, (char *) &buf, sizeof buf); + n = res_send((char *)&buf, n, data, datalen); + + return n; +} + +res_querydomain(host, dname, class, type, data, datalen) + char * host; + char * dname; + int class; + int type; + char * data; + int datalen; +{ + int n; + querybuf buf; + char dbuf[256]; + + strcpy(dbuf, host); + if (dbuf[strlen(dbuf)-1] != '.') + strcat(dbuf, "."); + strcat(dbuf, dname); + n = res_mkquery(QUERY, dbuf, class, type, (char *) NULL, 0, + NULL, (char *)&buf, sizeof buf); + n = res_send((char *) &buf, n, data, datalen); + + return n; +} + +res_search(dname, class, type, data, datalen) + char * dname; + int class; + int type; + char * data; + int datalen; +{ + int n; + querybuf buf; + + n = res_mkquery(QUERY, dname, class, type, (char *)NULL, 0, + NULL, (char *) &buf, sizeof buf); + n = res_send((char *) &buf, n, data, datalen); + + return n; +} diff --git a/gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl b/gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl new file mode 100644 index 00000000000..05a51b93496 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl @@ -0,0 +1,30 @@ +#!/bin/perl + +# +# Convert GECOS information in password files to alias syntax. +# +# Contributed by Kari E. Hurtta +# + +print "# Generated from passwd by $0\n"; + +while (@a = getpwent) { + ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = @a; + + ($fullname = $gcos) =~ s/,.*$//; + + if (!-d $dir || !-x $shell) { + print "$name: root\n"; + } + + $fullname =~ s/\.*[ _]+\.*/./g; + $fullname =~ tr [åäöÅÄÖé] [aaoAAOe]; # 1997-06-15 + if ($fullname =~ /^[a-zA-Z][a-zA-Z-]+(\.[a-zA-Z][a-zA-Z-]+)+$/) { +# if ($fullname =~ /^[a-zA-Z]+(\.[a-zA-Z]+)+$/) { # Kari E. Hurtta + print "$fullname: $name\n"; + } else { + print "# $fullname: $name\n"; + } +}; + +endpwent; diff --git a/gnu/usr.sbin/sendmail/contrib/qtool.8 b/gnu/usr.sbin/sendmail/contrib/qtool.8 new file mode 100644 index 00000000000..b8150b74de2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/qtool.8 @@ -0,0 +1,206 @@ +.\" Copyright (c) 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: qtool.8,v 8.9 1999/08/26 00:04:10 cying Exp $ +.\" +.TH QTOOL 8 "July 12, 1999" +.SH NAME +.B qtool +\- manipulate sendmail queues +.SH SYNOPSIS +.B qtool.pl +.RB [options] +target_directory source [source ...] +.PP +.B qtool.pl [-d/-b] +.RB [options] +source [source ...] +.SH DESCRIPTION +.B Qtool +moves the queue files used by sendmail between queues. It uses the same +locking mechanism as sendmail so can be safely used while sendmail is +running. +.PP +With no options, +.B qtool +will move any queue files as specified by \fIsource\fP into +\fItarget_directory\fP. \fISource\fP can be either an individual +queue control file, a queue file id, or a queue directory. +.PP +If the -d option is specified, qtool will delete the messages specified by +source instead of moving them. +.PP +If the -b option is specified, the selected messages will be bounced by +running sendmail with the -OTimeout.queuereturn=now option. +.SS Options +.TP +\fB\-b\fP +Bounce all of the messages specified by source. The messages will be bounced +immediately. No attempt will be made to deliver the messages. +.TP +\fB\-d\fP +Delete all of the messages specified by source. +.TP +\fB\-e\fP \fIperl_expression\fP +Evalute \fIperl_expression\fP for each queue file as specified +by \fIsource\fP. If \fIperl_expression\fP evaluates to true, then that +queue file is moved. See below for more detail on \fIperl_expression\fP. +.TP +\fB\-s\fP \fIseconds\fP +Move only the queue files specified by \fIsource\fP that have a +modification time older than \fIseconds\fP. +.SS Perl Expressions +You can use any valid perl expression. Inside the expression you have +access to a hash that contains many of the fields in the control file as +well as some other data about that queued message. The hash is called +\fI%msg\fP. If a field has multiple values (e.g. 'Recipient'), it will be +returned as an array, otherwise it will be returned as a scalar. Through +\fI%msg\fP, you can access the following variables: +.TP +\fBauth\fP +AUTH= parameter. +.TP +\fBbody_type\fP +Body type (\fB8BITMIME\fP, \fB7BIT\fP, or undefined). +.TP +\fBbody_last_mod_time\fP +The last time the body was modified since the epoch in seconds. +.TP +\fBbody_size\fP +The size of the body file in bytes. +.TP +\fBcharset\fP +Character set (for future use). +.TP +\fBcontent-length\fP +Content-Length: header value (Solaris sendmail only). +.TP +\fBcontrolling_user\fP +The controlling user. +.TP +\fBcontrol_last_mod_time\fP +The last time the body was modified since the epoch in seconds. +.TP +\fBcontrol_size\fP +The size of the control file in bytes. +.TP +\fBcreation_time\fP +The time when the control file was created. +.TP +\fBdata_file_name\fP +The data file name (deprecated). +.TP +\fBenvid\fP +Original envelope id form ESMTP. +.TP +\fBerror_recipient\fP +The error recipient (deprecated). +.TP +\fBflags\fP +Array of characters that can be the following values: +.PD 0 +.RS +8 +.TP 8 +w +warning message has been sent +.TP 8 +r +This is an error respone or DSN +.TP 8 +8 +has 8 bit data in body +.TP 8 +b +delete Bcc: headers +.TP 8 +d +envelope has DSN RET= parameter +.TP 8 +n +don't return body +.PD +.RE +.TP +\fBheaders\fP +This is a Perl hash where the keys are rfc822 field names and the values +are rfc822 field values. If a field has only one value it will be returned +as a string. If a field has more than one value (e.g. 'Received') it will +be returned as a list of strings. +.TP +\fBinode_number\fP +The inode number for the data (body) file. +.TP +\fBnext_delivery_time\fP +Earliest time of next delivery attempt. +.TP +\fBnum_delivery_attempts\fP +Number of delivery attempts that have been made. +.TP +\fBmacro\fP +Defined macro. +.TP +\fBmessage\fP +Envelope status message. +.TP +\fBoriginal_recipient\fP +Original recipient (ORCPT= parameter). +.TP +\fBpriority\fP +Adjusted priority of message. +.TP +\fBrecipient\fP +Array of character flags followed by colon and recipient name. Flags: +.PD 0 +.RS +8 +.TP 8 +N +Has NOTIFY= parameter. +.TP 8 +S +Success DSN requested. +.TP 8 +F +Failure DSN requested. +.TP 8 +D +Delay DSN requested. +.TP 8 +P +Primary address (not the result of alias/forward expansion). +.PD +.RE +.TP +\fBsender\fP +Sender +.TP +\fBversion\fP +Version of control file. +.SH EXAMPLES +.TP +\fBqtool.pl q2 q1\fP +Moves all of the queue files in queue q1 to queue q2. +.TP +\fBqtool.pl q2 q1/d6CLQh100847\fP +Moves the message with id d6CLQh100847 in queue q1 to queue q2. +.TP +\fBqtool.pl q2 q1/qfd6CLQh100847\fP +Moves the message with id d6CLQh100847 in queue q1 to queue q2. +.TP +\fBqtool.pl q2 q1/dfd6CLQh100847\fP +Moves the message with id d6CLQh100847 in queue q1 to queue q2. +.TP +\fBqtool.pl -e '$msg{num_delivery_attempts} == 3' /q2 /q1\fP +Moves all of the queue files that have had three attempted deliveries from +queue q1 to queue q2. +.SH SEE ALSO +sendmail(8) +.SH HISTORY +The +.B qtool +command appeared in +sendmail 8.10. diff --git a/gnu/usr.sbin/sendmail/contrib/qtool.pl b/gnu/usr.sbin/sendmail/contrib/qtool.pl new file mode 100644 index 00000000000..b2572fd6995 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/qtool.pl @@ -0,0 +1,1182 @@ +#!/usr/bin/env perl +## +## Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +## All rights reserved. +## +## $Sendmail: qtool.pl,v 8.15 1999/08/30 19:18:37 peterh Exp $ +## +use strict; +use File::Basename; +use File::Copy; +use File::Spec; +use Fcntl qw(:flock :DEFAULT); +use Getopt::Std; + +## +## QTOOL +## This program is for moving files between sendmail queues. It is +## pretty similar to just moving the files manually, but it locks the files +## the same way sendmail does to prevent problems. +## +## The syntax is the reverse of mv (ie. the target argument comes +## first). This lets you pick the files you want to move using find and +## xargs. +## +## Since you cannot delete queues while sendmail is running, QTOOL +## assumes that when you specify a directory as a source, you mean that you +## want all of the queue files within that directory moved, not the +## directory itself. +## +## There is a mechanism for adding conditionals for moving the files. +## Just create an Object with a check_move(source, dest) method and add it +## to the $conditions object. See the handling of the '-s' option for an +## example. +## + +## +## OPTION NOTES +## +## The -e option: +## The -e option takes any valid perl expression and evaluates it +## using the eval() function. Inside the expression the variable +## '$msg' is bound to the ControlFile object for the current source +## queue message. This lets you check for any value in the message +## headers or the control file. Here's an example: +## +## ./qtool.pl -e '$msg->{num_delivery_attempts} >= 2' /q1 /q2 +## +## This would move any queue files whose number of delivery attempts +## is greater than or equal to 2 from the queue 'q2' to the queue 'q1'. +## +## See the function ControlFile::parse for a list of available +## variables. +## + +my %opts; +my %sources; +my $dst_name; +my $destination; +my $source_name; +my $source; +my $result; +my $action; +my $new_condition; +my $conditions = new Compound(); + +Getopt::Std::getopts('bde:s:', \%opts); + +sub move_action +{ + my $source = shift; + my $destination = shift; + + $result = $destination->add($source); + if ($result) + { + print("$result.\n"); + } +} + +sub delete_action +{ + my $source = shift; + + return $source->delete(); +} + +sub bounce_action +{ + my $source = shift; + + return $source->bounce(); +} + +$action = \&move_action; +if (defined $opts{d}) +{ + $action = \&delete_action; +} +elsif (defined $opts{b}) +{ + $action = \&bounce_action; +} + +if (defined $opts{s}) +{ + $new_condition = new OlderThan($opts{s}); + $conditions->add($new_condition); +} + +if (defined $opts{e}) +{ + $new_condition = new Eval($opts{e}); + $conditions->add($new_condition); +} + +if ($action == \&move_action) +{ + $dst_name = shift(@ARGV); + if (!-d $dst_name) + { + print("The destination '$dst_name' must be an existing " . + "directory.\n"); + usage(); + exit; + } + $destination = new Queue($dst_name); +} + +while (@ARGV) +{ + $source_name = shift(@ARGV); + $result = add_source(\%sources, $source_name); + if ($result) + { + print("$result.\n"); + } +} + +if (keys(%sources) == 0) +{ + print("You must at least specify at least one source.\n"); + usage(); + exit; +} + +while (($source_name, $source) = each(%sources)) +{ + $result = $conditions->check_move($source, $destination); + if ($result) + { + $result = &{$action}($source, $destination); + if ($result) + { + print("$result\n"); + } + } +} + +sub usage +{ + print("Usage: $0 [options] directory source ...\n"); + print(" $0 [-d|-b] source ...\n"); + print("options:\n"); + print(" -b Bounce the messages specified by source.\n"); + print(" -d Delete the messages specified by source.\n"); + print(" -e [perl expression] Move only messages for which perl expression returns true.\n"); + print(" -s [seconds] Move only messages older than seconds.\n"); +} + +## +## ADD_SOURCE -- Adds a source to the source hash. +## +## Determines whether source is a file, directory, or id. Then it +## creates a QueuedMessage or Queue for that source and adds it to the +## list. +## +## Parameters: +## sources -- A hash that contains all of the sources. +## source_name -- The name of the source to add +## +## Returns: +## error_string -- Undef if ok. Error string otherwise. +## +## Notes: +## If a new source comes in with the same ID as a previous +## source, the previous source gets overwritten in the sources +## hash. This lets the user specify things like * and it still +## works nicely. +## + +sub add_source +{ + my $sources = shift; + my $source_name = shift; + my $source_base_name; + my $source_dir_name; + my $data_dir_name; + my $source_id; + my $source_prefix; + my $queued_message; + my $queue; + my $result; + + ($source_base_name, $source_dir_name) = File::Basename::fileparse($source_name); + $data_dir_name = $source_dir_name; + + $source_prefix = substr($source_base_name, 0, 2); + if (!-d $source_name && $source_prefix ne 'qf' && + $source_prefix ne 'df') + { + $source_base_name = "qf$source_base_name"; + $source_name = File::Spec->catfile("$source_dir_name", + "$source_base_name"); + } + $source_id = substr($source_base_name, 2); + + if (!-e $source_name) + { + $source_name = File::Spec->catfile("$source_dir_name", "qf", + "qf$source_id"); + if (!-e $source_name) + { + return "'$source_name' does not exist"; + } + $data_dir_name = File::Spec->catfile("$source_dir_name", "df"); + $source_dir_name = File::Spec->catfile("$source_dir_name", + "qf"); + } + + if (-f $source_name) + { + $queued_message = new QueuedMessage($source_dir_name, + $source_id, + $data_dir_name); + $sources->{$source_id} = $queued_message; + return undef; + } + + if (!-d $source_name) + { + return "'$source_name' is not a plain file or a directory"; + } + + $queue = new Queue($source_name); + $result = $queue->read(); + if ($result) + { + return $result; + } + + while (($source_id, $queued_message) = each(%{$queue->{files}})) + { + $sources->{$source_id} = $queued_message; + } + + return undef; +} + +## +## LOCK_FILE -- Opens and then locks a file. +## +## Opens a file for read/write and uses flock to obtain a lock on the +## file. The flock is Perl's flock which defaults to flock on systems +## that support it. On systems without flock it falls back to fcntl +## locking. +## +## Parameters: +## file_name -- The name of the file to open and lock. +## +## Returns: +## (file_handle, error_string) -- If everything works then +## file_handle is a reference to a file handle and +## error_string is undef. If there is a problem then +## file_handle is undef and error_string is a string +## explaining the problem. +## + +sub lock_file +{ + my $file_name = shift; + my $result; + + $result = sysopen(FILE_TO_LOCK, $file_name, Fcntl::O_RDWR); + if (!$result) + { + return (undef, "Unable to open '$file_name': $!"); + } + + $result = flock(FILE_TO_LOCK, Fcntl::LOCK_EX | Fcntl::LOCK_NB); + if (!$result) + { + return (undef, "Could not obtain lock on '$file_name': $!"); + } + + return (\*FILE_TO_LOCK, undef); +} + +## +## UNLOCK_FILE -- Unlocks a file. +## +## Unlocks a file using Perl's flock. +## +## Parameters: +## file -- A file handle. +## +## Returns: +## error_string -- If undef then no problem. Otherwise it is a +## string that explains problem. +## + +sub unlock_file +{ + my $file = shift; + my $result; + + $result = flock($file, Fcntl::LOCK_UN); + if (!$result) + { + return "Unlock failed on '$result': $!"; + } + + return undef; +} + +## +## MOVE_FILE -- Moves a file. +## +## Moves a file. +## +## Parameters: +## src_name -- The name of the file to be move. +## dst_nome -- The name of the place to move it to. +## +## Returns: +## error_string -- If undef then no problem. Otherwise it is a +## string that explains problem. +## + +sub move_file +{ + my $src_name = shift; + my $dst_name = shift; + my $result; + + $result = File::Copy::move($src_name, $dst_name); + if (!$result) + { + return "File move from '$src_name' to '$dst_name' failed: $!"; + } + + return undef; +} + + +## +## CONTROL_FILE - Represents a sendmail queue control file. +## +## This object represents represents a sendmail queue control file. +## It can parse and lock its file. +## + + +package ControlFile; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + my $queue_dir = shift; + $self->{id} = shift; + + $self->{file_name} = $queue_dir . '/qf' . $self->{id}; + $self->{headers} = {}; +} + +## +## PARSE - Parses the control file. +## +## Parses the control file. It just sticks each entry into a hash. +## If a key has more than one entry, then it points to a list of +## entries. +## + +sub parse +{ + my $self = shift; + if ($self->{parsed}) + { + return; + } + my %parse_table = + ( + 'A' => 'auth', + 'B' => 'body_type', + 'C' => 'controlling_user', + 'D' => 'data_file_name', + 'E' => 'error_recipient', + 'F' => 'flags', + 'H' => 'parse_header', + 'I' => 'inode_number', + 'K' => 'next_delivery_time', + 'L' => 'content-length', + 'M' => 'message', + 'N' => 'num_delivery_attempts', + 'P' => 'priority', + 'Q' => 'original_recipient', + 'R' => 'recipient', + 'S' => 'sender', + 'T' => 'creation_time', + 'V' => 'version', + 'X' => 'charset', + 'Z' => 'envid', + '$' => 'macro' + ); + my $line; + my $line_type; + my $line_value; + my $member_name; + my $member; + my $last_type; + + open(CONTROL_FILE, "$self->{file_name}"); + while ($line = ) + { + $line_type = substr($line, 0, 1); + if ($line_type eq "\t" && $last_type eq 'H') + { + $line_type = 'H'; + $line_value = $line; + } + else + { + $line_value = substr($line, 1); + } + $member_name = $parse_table{$line_type}; + $last_type = $line_type; + if (!$member_name) + { + $member_name = 'unknown'; + } + if ($self->can($member_name)) + { + $self->$member_name($line_value); + } + $member = $self->{$member_name}; + if (!$member) + { + $self->{$member_name} = $line_value; + next; + } + if (ref($member) eq 'ARRAY') + { + push(@{$member}, $line_value); + next; + } + $self->{$member_name} = [$member, $line_value]; + } + close(CONTROL_FILE); + + $self->{parsed} = 1; +} + +sub parse_header +{ + my $self = shift; + my $line = shift; + my $headers = $self->{headers}; + my $last_header = $self->{last_header}; + my $header_name; + my $header_value; + my $first_char; + + $first_char = substr($line, 0, 1); + if ($first_char eq "?") + { + $line = substr($line, 3); + } + elsif ($first_char eq "\t") + { + if (ref($headers->{$last_header}) eq 'ARRAY') + { + $headers->{$last_header}[-1] = + $headers->{$last_header}[-1] . $line; + } + else + { + $headers->{$last_header} = $headers->{$last_header} . + $line; + } + return; + } + ($header_name, $header_value) = split(/:/, $line, 2); + $self->{last_header} = $header_name; + if (exists $headers->{$header_name}) + { + $headers->{$header_name} = [$headers->{$header_name}, + $header_value]; + } + else + { + $headers->{$header_name} = $header_value; + } +} + +sub is_locked +{ + my $self = shift; + + return (defined $self->{lock_handle}); +} + +sub lock +{ + my $self = shift; + my $lock_handle; + my $result; + + if ($self->is_locked()) + { + # Already locked + return undef; + } + + ($lock_handle, $result) = ::lock_file($self->{file_name}); + if (!$lock_handle) + { + return $result; + } + + $self->{lock_handle} = $lock_handle; + + return undef; +} + +sub unlock +{ + my $self = shift; + my $result; + + if (!$self->is_locked()) + { + # Not locked + return undef; + } + + $result = ::unlock_file($self->{lock_handle}); + + $self->{lock_handle} = undef; + + return $result; +} + +sub do_stat +{ + my $self = shift; + my $result; + my @result; + + $result = open(QUEUE_FILE, $self->{file_name}); + if (!$result) + { + return "Unable to open '$self->{file_name}': $!"; + } + @result = stat(QUEUE_FILE); + if (!@result) + { + return "Unable to stat '$self->{file_name}': $!"; + } + $self->{control_size} = $result[7]; + $self->{control_last_mod_time} = $result[9]; +} + +sub DESTROY +{ + my $self = shift; + + $self->unlock(); +} + +sub delete +{ + my $self = shift; + my $result; + + $result = unlink($self->{file_name}); + if (!$result) + { + return "Unable to delete $self->{file_name}: $!"; + } + return undef; +} + + +## +## DATA_FILE - Represents a sendmail queue data file. +## +## This object represents represents a sendmail queue data file. +## It is really just a place-holder. +## + +package DataFile; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + my $queue_dir = shift; + $self->{id} = shift; + + $self->{file_name} = $queue_dir . '/df' . $self->{id}; +} + +sub do_stat +{ + my $self = shift; + my $result; + my @result; + + $result = open(QUEUE_FILE, $self->{file_name}); + if (!$result) + { + return "Unable to open '$self->{file_name}': $!"; + } + @result = stat(QUEUE_FILE); + if (!@result) + { + return "Unable to stat '$self->{file_name}': $!"; + } + $self->{body_size} = $result[7]; + $self->{body_last_mod_time} = $result[9]; +} + +sub delete +{ + my $self = shift; + my $result; + + $result = unlink($self->{file_name}); + if (!$result) + { + return "Unable to delete $self->{file_name}: $!"; + } + return undef; +} + + +## +## QUEUED_MESSAGE - Represents a queued sendmail message. +## +## This keeps track of the files that make up a queued sendmail +## message. +## Currently it has 'control_file' and 'data_file' as members. +## +## You can tie it to a fetch only hash using tie. You need to +## pass a reference to a QueuedMessage as the third argument +## to tie. +## + +package QueuedMessage; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + my $queue_dir = shift; + my $id = shift; + my $data_dir = shift; + + $self->{id} = $id; + $self->{control_file} = new ControlFile($queue_dir, $id); + if ($data_dir) + { + $self->{data_file} = new DataFile($data_dir, $id); + } + else + { + $self->{data_file} = new DataFile($queue_dir, $id); + } +} + +sub TIEHASH +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = shift; + return $self; +} + +sub FETCH +{ + my $self = shift; + my $key = shift; + + if (exists $self->{control_file}->{$key}) + { + return $self->{control_file}->{$key}; + } + if (exists $self->{data_file}->{$key}) + { + return $self->{data_file}->{$key}; + } + + return undef; +} + +sub lock +{ + my $self = shift; + + return $self->{control_file}->lock(); +} + +sub unlock +{ + my $self = shift; + + return $self->{control_file}->unlock(); +} + +sub move +{ + my $self = shift; + my $destination = shift; + my $df_dest; + my $qf_dest; + my $result; + + $result = $self->lock(); + if ($result) + { + return $result; + } + + $qf_dest = File::Spec->catfile($destination, "qf"); + if (-d $qf_dest) + { + $df_dest = File::Spec->catfile($destination, "df"); + if (!-d $df_dest) + { + $df_dest = $destination; + } + } + else + { + $qf_dest = $destination; + $df_dest = $destination; + } + + if (-e File::Spec->catfile($qf_dest, "qf$self->{id}")) + { + $result = "There is already a queued message with id '$self->{id}' in '$destination'"; + } + + if (!$result) + { + $result = ::move_file($self->{data_file}->{file_name}, + $df_dest); + } + + if (!$result) + { + $result = ::move_file($self->{control_file}->{file_name}, + $qf_dest); + } + + $self->unlock(); + + return $result; +} + +sub parse +{ + my $self = shift; + + return $self->{control_file}->parse(); +} + +sub do_stat +{ + my $self = shift; + + $self->{control_file}->do_stat(); + $self->{data_file}->do_stat(); +} + +sub setup_vars +{ + my $self = shift; + + $self->parse(); + $self->do_stat(); +} + +sub delete +{ + my $self = shift; + my $result; + + $result = $self->{control_file}->delete(); + if ($result) + { + return $result; + } + $result = $self->{data_file}->delete(); + if ($result) + { + return $result; + } + + return undef; +} + +sub bounce +{ + my $self = shift; + my $command; + + $command = "sendmail -qI$self->{id} -O Timeout.queuereturn=now"; +# print("$command\n"); + system($command); +} + +## +## QUEUE - Represents a queued sendmail queue. +## +## This manages all of the messages in a queue. +## + +package Queue; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + + $self->{queue_dir} = shift; + $self->{files} = {}; +} + +## +## READ - Loads the queue with all of the objects that reside in it. +## +## This reads the queue's directory and creates QueuedMessage objects +## for every file in the queue that starts with 'qf'. +## + +sub read +{ + my $self = shift; + my @control_files; + my $queued_message; + my $file_name; + my $id; + my $result; + my $control_dir; + my $data_dir; + + $control_dir = File::Spec->catfile($self->{queue_dir}, 'qf'); + + if (-e $control_dir) + { + $data_dir = File::Spec->catfile($self->{queue_dir}, 'df'); + if (!-e $data_dir) + { + $data_dir = $self->{queue_dir}; + } + } + else + { + $data_dir = $self->{queue_dir}; + $control_dir = $self->{queue_dir}; + } + + $result = opendir(QUEUE_DIR, $control_dir); + if (!$result) + { + return "Unable to open directory '$control_dir'"; + } + + @control_files = grep { /^qf.*/ && -f "$control_dir/$_" } readdir(QUEUE_DIR); + closedir(DIR); + foreach $file_name (@control_files) + { + $id = substr($file_name, 2); + $queued_message = new QueuedMessage($control_dir, $id, + $data_dir); + $self->{files}->{$id} = $queued_message; + } + + return undef; +} + + +## +## ADD_QUEUED_MESSAGE - Adds a QueuedMessage to this Queue. +## +## Adds the QueuedMessage object to the hash and moves the files +## associated with the QueuedMessage to this Queue's directory. +## + +sub add_queued_message +{ + my $self = shift; + my $queued_message = shift; + my $result; + + $result = $queued_message->move($self->{queue_dir}); + if ($result) + { + return $result; + } + + $self->{files}->{$queued_message->{id}} = $queued_message; + + return $result; +} + +## +## ADD_QUEUE - Adds another Queue's QueuedMessages to this Queue. +## +## Adds all of the QueuedMessage objects in the passed in queue +## to this queue. +## + +sub add_queue +{ + my $self = shift; + my $queue = shift; + my $id; + my $queued_message; + my $result; + + while (($id, $queued_message) = each %{$queue->{files}}) + { + $result = $self->add_queued_message($queued_message); + if ($result) + { + print("$result.\n"); + } + } +} + +## +## ADD - Adds an item to this queue. +## +## Adds either a Queue or a QueuedMessage to this Queue. +## + +sub add +{ + my $self = shift; + my $source = shift; + my $type_name; + my $result; + + $type_name = ref($source); + + if ($type_name eq "QueuedMessage") + { + return $self->add_queued_message($source); + } + + if ($type_name eq "Queue") + { + return $self->add_queue($source); + } + + return "Queue does not know how to add a '$type_name'" +} + +sub delete +{ + my $self = shift; + my $id; + my $queued_message; + + while (($id, $queued_message) = each %{$self->{files}}) + { + $result = $queued_message->delete(); + if ($result) + { + print("$result.\n"); + } + } +} + +sub bounce +{ + my $self = shift; + my $id; + my $queued_message; + + while (($id, $queued_message) = each %{$self->{files}}) + { + $result = $queued_message->bounce(); + if ($result) + { + print("$result.\n"); + } + } +} + +## +## Condition Class +## +## This next section is for any class that has an interface called +## check_move(source, dest). Each class represents some condition to +## check for to determine whether we should move the file from +## source to dest. +## + + +## +## OlderThan +## +## This Condition Class checks the modification time of the +## source file and returns true if the file's modification time is +## older than the number of seconds the class was initialzed with. +## + +package OlderThan; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + + $self->{age_in_seconds} = shift; +} + +sub check_move +{ + my $self = shift; + my $source = shift; + + if ((time() - $source->last_modified_time()) > $self->{age_in_seconds}) + { + return 1; + } + + return 0; +} + +## +## Compound +## +## Takes a list of Move Condition Classes. Check_move returns true +## if every Condition Class in the list's check_move function returns +## true. +## + +package Compound; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + + $self->{condition_list} = []; +} + +sub add +{ + my $self = shift; + my $new_condition = shift; + + push(@{$self->{condition_list}}, $new_condition); +} + +sub check_move +{ + my $self = shift; + my $source = shift; + my $dest = shift; + my $condition; + my $result; + + foreach $condition (@{$self->{condition_list}}) + { + if (!$condition->check_move($source, $dest)) + { + return 0; + } + } + + return 1; +} + +## +## Eval +## +## Takes a perl expression and evaluates it. The ControlFile object +## for the source QueuedMessage is avaliable through the name '$msg'. +## + +package Eval; + +sub new +{ + my $this = shift; + my $class = ref($this) || $this; + my $self = {}; + bless $self, $class; + $self->initialize(@_); + return $self; +} + +sub initialize +{ + my $self = shift; + + $self->{expression} = shift; +} + +sub check_move +{ + my $self = shift; + my $source = shift; + my $dest = shift; + my $result; + my %msg; + + $source->setup_vars(); + tie(%msg, 'QueuedMessage', $source); + $result = eval($self->{expression}); + + return $result; +} diff --git a/gnu/usr.sbin/sendmail/contrib/re-mqueue.pl b/gnu/usr.sbin/sendmail/contrib/re-mqueue.pl new file mode 100644 index 00000000000..d2af5144b89 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/re-mqueue.pl @@ -0,0 +1,238 @@ +#!/usr/bin/perl +# +# re-mqueue -- requeue messages from queueA to queueB based on age. +# +# Contributed by Paul Pomes . +# http://www.qualcomm.com/~ppomes/ +# +# Usage: re-mqueue [-d] queueA queueB seconds +# +# -d enable debugging +# queueA source directory +# queueB destination directory +# seconds select files older than this number of seconds +# +# Example: re-mqueue /var/spool/mqueue /var/spool/mqueue2 2700 +# +# Moves the qf* and df* files for a message from /var/spool/mqueue to +# /var/spool/mqueue2 if the df* file is over 2700 seconds old. +# +# The qf* file can't be used for age checking as it's partially re-written +# with the results of the last queue run. +# +# Rationale: With a limited number of sendmail processes allowed to run, +# messages that can't be delivered immediately slow down the ones that can. +# This becomes especially important when messages are being queued instead +# of delivered right away, or when the queue becomes excessively deep. +# By putting messages that have already failed one or more delivery attempts +# into another queue, the primary queue can be kept small and fast. +# +# On postoffice.cso.uiuc.edu, the primary sendmail daemon runs the queue +# every thirty minutes. Messages over 45 minutues old are moved to +# /var/spool/mqueue2 where sendmail runs every hour. Messages more than +# 3.25 hours old are moved to /var/spool/mqueue3 where sendmail runs every +# four hours. Messages more than a day old are moved to /var/spool/mqueue4 +# where sendmail runs three times a day. The idea is that a message is +# tried at least twice in the first three queues before being moved to the +# old-age ghetto. +# +# (Each must be re-formed into a single line before using in crontab) +# +# 08 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue ## /var/spool/mqueue2 2700 +# 11 * * * * /usr/lib/sendmail -oQ/var/spool/mqueue2 -q > ## > /var/log/mqueue2 2>&1 +# 38 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue2 +# /var/spool/mqueue3 11700 +# 41 1,5,9,13,17,21 * * * /usr/lib/sendmail -oQ/var/spool/mqueue3 -q ## > /var/log/mqueue3 2>&1 +# 48 * * * * /usr/local/libexec/re-mqueue /var/spool/mqueue3 +# /var/spool/mqueue4 100000 +#53 3,11,19 * * * /usr/lib/sendmail -oQ/var/spool/mqueue4 -q > ## > /var/log/mqueue4 2>&1 +# +# +# N.B., the moves are done with link(). This has two effects: 1) the mqueue* +# directories must all be on the same filesystem, and 2) the file modification +# times are not changed. All times must be cumulative from when the df* +# file was created. +# +# Copyright (c) 1995 University of Illinois Board of Trustees and Paul Pomes +# 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 +# Illinois at Urbana and their contributors. +# 4. Neither the name of the University nor the names of their contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE TRUSTEES 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 TRUSTEES 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. +# +# @(#)$OrigId: re-mqueue,v 1.3 1995/05/25 18:14:53 p-pomes Exp $ +# +# Updated by Graeme Hewson May 1999 +# +# 'use Sys::Syslog' for Perl 5 +# Move transcript (xf) files if they exist +# Allow zero-length df files (empty message body) +# Preserve $! for error messages +# + +use Sys::Syslog; + +$LOCK_EX = 2; +$LOCK_NB = 4; +$LOCK_UN = 8; + +# Count arguments, exit if wrong in any way. +die "Usage: $0 [-d] queueA queueB seconds\n" if ($#ARGV < 2); + +while ($_ = $ARGV[0], /^-/) { + shift; + last if /^--$/; + /^-d/ && $debug++; +} + +$queueA = shift; +$queueB = shift; +$age = shift; + +die "$0: $queueA not a directory\n" if (! -d $queueA); +die "$0: $queueB not a directory\n" if (! -d $queueB); +die "$0: $age isn't a valid number of seconds for age\n" if ($age =~ /\D/); + +# chdir to $queueA and read the directory. When a df* file is found, stat it. +# If it's older than $age, lock the corresponding qf* file. If the lock +# fails, give up and move on. Once the lock is obtained, verify that files +# of the same name *don't* already exist in $queueB and move on if they do. +# Otherwise re-link the qf* and df* files into $queueB then release the lock. + +chdir "$queueA" || die "$0: can't cd to $queueA: $!\n"; +opendir (QA, ".") || die "$0: can't open directory $queueA for reading: $!\n"; +@dfiles = grep(/^df/, readdir(QA)); +$now = time(); +($program = $0) =~ s,.*/,,; +&openlog($program, 'pid', 'mail'); + +# Loop through the dfiles +while ($dfile = pop(@dfiles)) { + print "Checking $dfile\n" if ($debug); + ($qfile = $dfile) =~ s/^d/q/; + ($xfile = $dfile) =~ s/^d/x/; + ($mfile = $dfile) =~ s/^df//; + if (! -e $dfile) { + print "$dfile is gone - skipping\n" if ($debug); + next; + } + if (! -e $qfile || -z $qfile) { + print "$qfile is gone or zero bytes - skipping\n" if ($debug); + next; + } + + $mtime = $now; + ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, + $atime,$mtime,$ctime,$blksize,$blocks) = stat($dfile); + + # Compare timestamps + if (($mtime + $age) > $now) { + printf ("%s is %d seconds old - skipping\n", $dfile, $now-$mtime) if ($debug); + next; + } + + # See if files of the same name already exist in $queueB + if (-e "$queueB/$dfile") { + print "$queueb/$dfile already exists - skipping\n" if ($debug); + next; + } + if (-e "$queueB/$qfile") { + print "$queueb/$qfile already exists - skipping\n" if ($debug); + next; + } + if (-e "$queueB/$xfile") { + print "$queueb/$xfile already exists - skipping\n" if ($debug); + next; + } + + # Try and lock qf* file + unless (open(QF, ">>$qfile")) { + print "$qfile: $!\n" if ($debug); + next; + } + $retval = flock(QF, $LOCK_EX|$LOCK_NB) || ($retval = -1); + if ($retval == -1) { + print "$qfile already flock()ed - skipping\n" if ($debug); + close(QF); + next; + } + print "$qfile now flock()ed\n" if ($debug); + + # Show time! Do the link()s + if (link("$dfile", "$queueB/$dfile") == 0) { + $bang = $!; + &syslog('err', 'link(%s, %s/%s): %s', $dfile, $queueB, $dfile, $bang); + print STDERR "$0: link($dfile, $queueB/$dfile): $bang\n"; + exit (1); + } + if (link("$qfile", "$queueB/$qfile") == 0) { + $bang = $!; + &syslog('err', 'link(%s, %s/%s): %s', $qfile, $queueB, $qfile, $bang); + print STDERR "$0: link($qfile, $queueB/$qfile): $bang\n"; + unlink("$queueB/$dfile"); + exit (1); + } + if (-e "$xfile") { + if (link("$xfile", "$queueB/$xfile") == 0) { + $bang = $!; + &syslog('err', 'link(%s, %s/%s): %s', $xfile, $queueB, $xfile, $bang); + print STDERR "$0: link($xfile, $queueB/$xfile): $bang\n"; + unlink("$queueB/$dfile"); + unlink("$queueB/$qfile"); + exit (1); + } + } + + # Links created successfully. Unlink the original files, release the + # lock, and close the file. + print "links ok\n" if ($debug); + if (unlink($qfile) == 0) { + $bang = $!; + &syslog('err', 'unlink(%s): %s', $qfile, $bang); + print STDERR "$0: unlink($qfile): $bang\n"; + exit (1); + } + if (unlink($dfile) == 0) { + $bang = $!; + &syslog('err', 'unlink(%s): %s', $dfile, $bang); + print STDERR "$0: unlink($dfile): $bang\n"; + exit (1); + } + if (-e "$xfile") { + if (unlink($xfile) == 0) { + $bang = $!; + &syslog('err', 'unlink(%s): %s', $xfile, $bang); + print STDERR "$0: unlink($xfile): $bang\n"; + exit (1); + } + } + flock(QF, $LOCK_UN); + close(QF); + &syslog('info', '%s moved to %s', $mfile, $queueB); + print "Done with $dfile $qfile\n\n" if ($debug); +} +exit 0; diff --git a/gnu/usr.sbin/sendmail/contrib/rmail.oldsys.patch b/gnu/usr.sbin/sendmail/contrib/rmail.oldsys.patch new file mode 100644 index 00000000000..856fcf1f93e --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/rmail.oldsys.patch @@ -0,0 +1,108 @@ +From: Bill Gianopoulos +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 + #include + ++ #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/gnu/usr.sbin/sendmail/contrib/smcontrol.pl b/gnu/usr.sbin/sendmail/contrib/smcontrol.pl new file mode 100644 index 00000000000..58b5d7c2855 --- /dev/null +++ b/gnu/usr.sbin/sendmail/contrib/smcontrol.pl @@ -0,0 +1,363 @@ +#!/usr/local/bin/perl -w + +use FileHandle; +use Socket; + +$sendmailDaemon = "/usr/sbin/sendmail -q30m -bd"; + +########################################################################## +# +# &get_controlname -- read ControlSocketName option from sendmail.cf +# +# Parameters: +# none. +# +# Returns: +# control socket filename, undef if not found +# + +sub get_controlname +{ + my $cn = undef; + my $qd = undef; + + open(CF, ") + { + chomp; + if (/^O ControlSocketName\s*=\s*([^#]+)$/o) + { + $cn = $1; + } + if (/^O QueueDirectory\s*=\s*([^#]+)$/o) + { + $qd = $1; + } + if (/^OQ([^#]+)$/o) + { + $qd = $1; + } + } + close(CF); + if (not defined $cn) + { + return undef; + } + if ($cn !~ /^\//o) + { + return undef if (not defined $qd); + + $cn = $qd . "/" . $cn; + } + return $cn; +} + +########################################################################## +# +# &do_command -- send command to sendmail daemon view control socket +# +# Parameters: +# controlsocket -- filename for socket +# command -- command to send +# +# Returns: +# reply from sendmail daemon +# + +sub do_command +{ + my $controlsocket = shift; + my $command = shift; + my $proto = getprotobyname('ip'); + my @reply; + + socket(SOCK, PF_UNIX, SOCK_STREAM, $proto) or return undef; + + for ($i = 0; $i < 4; $i++) + { + if (!connect(SOCK, sockaddr_un($controlsocket))) + { + if ($i == 3) + { + close(SOCK); + return undef; + } + sleep 1; + next; + } + last; + } + autoflush SOCK 1; + print SOCK "$command\n"; + @reply = ; + close(SOCK); + return join '', @reply; +} + +########################################################################## +# +# &sendmail_running -- check if sendmail is running via SMTP +# +# Parameters: +# none +# +# Returns: +# 1 if running, undef otherwise +# + +sub sendmail_running +{ + my $port = getservbyname("smtp", "tcp") || 25; + my $proto = getprotobyname("tcp"); + my $iaddr = inet_aton("localhost"); + my $paddr = sockaddr_in($port, $iaddr); + + socket(SOCK, PF_INET, SOCK_STREAM, $proto) or return undef; + if (!connect(SOCK, $paddr)) + { + close(SOCK); + return undef; + } + autoflush SOCK 1; + while () + { + if (/^(\d{3})([ -])/) + { + if ($1 != 220) + { + close(SOCK); + return undef; + } + } + else + { + close(SOCK); + return undef; + } + last if ($2 eq " "); + } + print SOCK "QUIT\n"; + while () + { + last if (/^\d{3} /); + } + close(SOCK); + return 1; +} + +########################################################################## +# +# &munge_status -- turn machine readable status into human readable text +# +# Parameters: +# raw -- raw results from sendmail daemon STATUS query +# +# Returns: +# human readable text +# + +sub munge_status +{ + my $raw = shift; + my $cooked = ""; + my $daemonStatus = ""; + + if ($raw =~ /^(\d+)\/(\d+)\/(\d+)\/(\d+)$/mg) + { + $cooked .= "Current number of children: $1"; + if ($2 > 0) + { + $cooked .= " (maximum $2)"; + } + $cooked .= "\n"; + $cooked .= "QueueDir free disk space (in blocks): $3\n"; + $cooked .= "Load average: $4\n"; + } + while ($raw =~ /^(\d+) (.*)$/mg) + { + if (not $daemonStatus) + { + $daemonStatus = "(process $1) " . ucfirst($2) . "\n"; + } + else + { + $cooked .= "Child Process $1 Status: $2\n"; + } + } + return ($daemonStatus, $cooked); +} + +########################################################################## +# +# &start_daemon -- fork off a sendmail daemon +# +# Parameters: +# control -- control socket name +# +# Returns: +# Error message or "OK" if successful +# + +sub start_daemon +{ + my $control = shift; + my $pid; + + if ($pid = fork) + { + my $exitstat; + + waitpid $pid, 0 or return "Could not get status of created process: $!\n"; + $exitstat = $? / 256; + if ($exitstat != 0) + { + return "sendmail daemon startup exited with exit value $exitstat"; + } + } + elsif (defined $pid) + { + exec($main::sendmailDaemon); + die "Unable to start sendmail daemon: $!.\n"; + } + else + { + return "Could not create new process: $!\n"; + } + return "OK\n"; +} + +########################################################################## +# +# &stop_daemon -- stop the sendmail daemon using control socket +# +# Parameters: +# control -- control socket name +# +# Returns: +# Error message or status message +# + +sub stop_daemon +{ + my $control = shift; + my $status; + + if (not defined $control) + { + return "The control socket is not configured so the daemon can not be stopped.\n"; + } + return &do_command($control, "SHUTDOWN"); +} + +########################################################################## +# +# &restart_daemon -- restart the sendmail daemon using control socket +# +# Parameters: +# control -- control socket name +# +# Returns: +# Error message or status message +# + +sub restart_daemon +{ + my $control = shift; + my $status; + + if (not defined $control) + { + return "The control socket is not configured so the daemon can not be restarted."; + } + return &do_command($control, "RESTART"); +} + +########################################################################## +# +# &help -- get help from the daemon using the control socket +# +# Parameters: +# control -- control socket name +# +# Returns: +# Error message or status message +# + +sub help +{ + my $control = shift; + my $status; + + if (not defined $control) + { + return "The control socket is not configured so the daemon can not be queried for help."; + } + return &do_command($control, "HELP"); +} + +my $command = shift; +my $control = &get_controlname; +my $status = undef; +my $daemonStatus = undef; + +if (not defined $control) +{ + die "No control socket available.\n"; +} +if (not defined $command) +{ + die "Usage: $0 command\n"; +} +if ($command eq "status") +{ + $status = &do_command($control, "STATUS"); + if (not defined $status) + { + # Not responding on control channel, query via SMTP + if (&sendmail_running) + { + $daemonStatus = "Sendmail is running but not answering status queries."; + } + else + { + $daemonStatus = "Sendmail does not appear to be running."; + } + } + else + { + # Munge control channel output + ($daemonStatus, $status) = &munge_status($status); + } +} +elsif (lc($command) eq "shutdown") +{ + $status = &stop_daemon($control); +} +elsif (lc($command) eq "restart") +{ + $status = &restart_daemon($control); +} +elsif (lc($command) eq "start") +{ + $status = &start_daemon($control); +} +elsif (lc($command) eq "help") +{ + $status = &help($control); +} +else +{ + die "Unrecognized command $command\n"; +} +if (defined $daemonStatus) +{ + print "Daemon Status: $daemonStatus\n"; +} +if (defined $status) +{ + print "$status\n"; +} +else +{ + die "No response\n"; +} diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/all.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/all.m4 new file mode 100644 index 00000000000..828950ea68d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/all.m4 @@ -0,0 +1,38 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: all.m4,v 8.7 1999/10/13 07:08:36 gshapiro Exp $ +# +divert(0)dnl +ALL=${BEFORE} ${LINKS} bldTARGETS + +all: ${ALL} + +clean: bldCLEAN_TARGETS + +define(`bldADD_SRC', ${$1SRCS} )dnl +SRCS=bldFOREACH(`bldADD_SRC(', bldC_PRODUCTS) +define(`bldADD_OBJS', ${$1OBJS} )dnl +OBJS=bldFOREACH(`bldADD_OBJS(', bldC_PRODUCTS) + +ifdef(`bldNO_INSTALL', `divert(-1)') +install: bldINSTALL_TARGETS + +install-strip: bldINSTALL_TARGETS ifdef(`bldSTRIP_TARGETS', `bldSTRIP_TARGETS') +ifdef(`bldNO_INSTALL', `divert(0)') + +divert(bldDEPENDENCY_SECTION) +################ Dependency scripts +include(confBUILDTOOLSDIR/M4/depend/ifdef(`confDEPEND_TYPE', `confDEPEND_TYPE', +`generic').m4)dnl +################ End of dependency scripts +divert(0) diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/defines.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/defines.m4 new file mode 100644 index 00000000000..df2adbe846a --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/defines.m4 @@ -0,0 +1,121 @@ +divert(-1) +# +# Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: defines.m4,v 8.27 2000/02/26 01:32:06 gshapiro Exp $ +# +divert(0)dnl + +# C compiler +CC= confCC +CCOPTS= ifdef(`confCCOPTS', `confCCOPTS', ` ') ifdef(`confMT', ifdef(`confMTCCOPTS', `confMTCCOPTS', `'), `') + +# C Linker +LD= ifdef(`confLD', `confLD', `confCC') +LDOPTS= ifdef(`confLDOPTS', `confLDOPTS') ifdef(`confMT', ifdef(`confMTLDOPTS', `confMTLDOPTS', `'), `') +LDOPTS_SO= ${LDOPTS} ifdef(`confLDOPTS_SO', `confLDOPTS_SO', `-shared') + +# Shell +SHELL= confSHELL + +# use O=-O (usual) or O=-g (debugging) +O= ifdef(`confOPTIMIZE', `confOPTIMIZE', `-O') + +# Object archiver +AR= ifdef(`confAR', `confAR', `ar') +AROPTS= ifdef(`confAROPTS', `confAROPTS', `crv') + +# Ranlib (or echo) +RANLIB= ifdef(`confRANLIB', `confRANLIB', `ranlib') +RANLIBOPTS= ifdef(`confRANLIBOPTS', `confRANLIBOPTS', `') + +# Object stripper +STRIP= ifdef(`confSTRIP', `confSTRIP', `strip') +STRIPOPTS= ifdef(`confSTRIPOPTS', `confSTRIPOPTS', `') + +# environment definitions (e.g., -D_AIX3) +ENVDEF= ifdef(`confENVDEF', `confENVDEF') ifdef(`conf_'bldCURRENT_PRD`_ENVDEF', `conf_'bldCURRENT_PRD`_ENVDEF') + +# location of the source directory +SRCDIR= ifdef(`confSRCDIR', `confSRCDIR', `_SRC_PATH_') + +# include directories +INCDIRS= confINCDIRS + +# library directories +LIBDIRS=confLIBDIRS + +# Additional libs needed +LIBADD= ifdef(`conf_'bldCURRENT_PRD`_LIBS', `conf_'bldCURRENT_PRD`_LIBS') + +# libraries required on your system +# delete -l44bsd if you are not running BIND 4.9.x +LIBS= ${LIBADD} ifdef(`confLIBS', `confLIBS') + +# location of sendmail binary (usually /usr/sbin or /usr/lib) +BINDIR= ifdef(`confMBINDIR', `confMBINDIR', `/usr/sbin') + +# location of "user" binaries (usually /usr/bin or /usr/ucb) +UBINDIR=ifdef(`confUBINDIR', `confUBINDIR', `/usr/bin') + +# location of "root" binaries (usually /usr/sbin or /usr/etc) +SBINDIR=ifdef(`confSBINDIR', `confSBINDIR', `/usr/sbin') + +# location of "libexec" binaries (usually /usr/libexec or /usr/etc) +EBINDIR=ifdef(`confEBINDIR', `confEBINDIR', `/usr/libexec') + +# additional .c files needed +SRCADD= ifdef(`confSRCADD', `confSRCADD') + +ifdef(`conf_'bldCURRENT_PRD`_SRCADD', `bldLIST_PUSH_ITEM(`bldSOURCES', `conf_'bldCURRENT_PRD`_SRCADD')') + +# additional .o files needed +OBJADD= ifdef(`confOBJADD', `confOBJADD') +bldCURRENT_PRODUCT`OBJADD'= ifdef(`conf_'bldCURRENT_PRD`_OBJADD', `conf_'bldCURRENT_PRD`_OBJADD') ifdef(`confLIBADD', `bldADD_EXTENSIONS(`a', confLIBADD)', `') + +# copy files +CP= ifdef(`confCOPY', `confCOPY', `cp') + +################### end of user configuration flags ###################### + +BUILDBIN=confBUILDBIN +COPTS= -I. ${INCDIRS} ${ENVDEF} ${CCOPTS} +CFLAGS= $O ${COPTS} ifdef(`confMT', ifdef(`confMTCFLAGS', `confMTCFLAGS -DXP_MT', `-DXP_MT'), `') + +BEFORE= confBEFORE + +LINKS=ifdef(`bldLINK_SOURCES', `bldLINK_SOURCES', `') + +bldCURRENT_PRODUCT`SRCS'= bldSOURCES ${SRCADD} +bldCURRENT_PRODUCT`OBJS'= bldSUBST_EXTENSIONS(`o', bldSOURCES) ifdef(`bldLINK_SOURCES', `bldSUBST_EXTENSIONS(`o', bldLINK_SOURCES)') ${OBJADD} ${bldCURRENT_PRODUCT`OBJADD'} +bldCURRENT_PRODUCT`SMDEPLIBS'= ifdef(`bldSMDEPLIBS', `bldSMDEPLIBS', `') +bldCURRENT_PRODUCT`TARGET_LINKS'= ifdef(`bldTARGET_LINKS', `bldTARGET_LINKS', `') + +bldPUSH_ALL_SRCS(bldCURRENT_PRODUCT`SRCS')dnl + +ifdef(`bldBIN_TYPE', , `define(`bldBIN_TYPE', `U')')dnl +ifdef(`bldINSTALL_DIR', , `define(`bldINSTALL_DIR', `U')')dnl + +NROFF= ifdef(`confNROFF', `confNROFF', `groff -Tascii') +MANDOC= ifdef(`confMANDOC', `confMANDOC', `-man') + +INSTALL=ifdef(`confINSTALL', `confINSTALL', `install') + +# User binary ownership/permissions +UBINOWN=ifdef(`confUBINOWN', `confUBINOWN', `bin') +UBINGRP=ifdef(`confUBINGRP', `confUBINGRP', `bin') +UBINMODE=ifdef(`confSBINMODE', `confSBINMODE', `555') + +# Setuid binary ownership/permissions +SBINOWN=ifdef(`confSBINOWN', `confSBINOWN', `root') +SBINGRP=ifdef(`confSBINGRP', `confSBINGRP', `bin') +SBINMODE=ifdef(`confSBINMODE', `confSBINMODE', `4555') + diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/executable.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/executable.m4 new file mode 100644 index 00000000000..0e7d5b82805 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/executable.m4 @@ -0,0 +1,41 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: executable.m4,v 8.18 1999/10/13 07:08:36 gshapiro Exp $ +# +divert(0)dnl +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/links.m4')dnl +bldLIST_PUSH_ITEM(`bldC_PRODUCTS', bldCURRENT_PRODUCT)dnl +bldPUSH_TARGET(bldCURRENT_PRODUCT)dnl +bldPUSH_INSTALL_TARGET(`install-'bldCURRENT_PRODUCT)dnl +bldPUSH_CLEAN_TARGET(bldCURRENT_PRODUCT`-clean')dnl +bldPUSH_ALL_SRCS(bldCURRENT_PRODUCT`SRCS')dnl +bldPUSH_STRIP_TARGET(`strip-'bldCURRENT_PRODUCT)dnl + +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/defines.m4') +divert(bldTARGETS_SECTION) +bldCURRENT_PRODUCT: ${bldCURRENT_PRODUCT`OBJS'} ${bldCURRENT_PRODUCT`SMDEPLIBS'} + ${CC} -o bldCURRENT_PRODUCT ${LDOPTS} ${LIBDIRS} ${bldCURRENT_PRODUCT`OBJS'} ${LIBS} + +ifdef(`bldLINK_SOURCES', `bldMAKE_SOURCE_LINKS(bldLINK_SOURCES)') + +ifdef(`bldNO_INSTALL', , +`install-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT + ${INSTALL} -c -o ${bldBIN_TYPE`'BINOWN} -g ${bldBIN_TYPE`'BINGRP} -m ${bldBIN_TYPE`'BINMODE} bldCURRENT_PRODUCT ${DESTDIR}${bldINSTALL_DIR`'BINDIR} +ifdef(`bldTARGET_LINKS', `bldMAKE_TARGET_LINKS(${bldINSTALL_DIR`'BINDIR}/bldCURRENT_PRODUCT, ${bldCURRENT_PRODUCT`'TARGET_LINKS})')') + +strip-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT + ${STRIP} ${STRIPOPTS} ${DESTDIR}${bldINSTALL_DIR`'BINDIR}`'/bldCURRENT_PRODUCT + +bldCURRENT_PRODUCT-clean: + rm -f ${OBJS} bldCURRENT_PRODUCT ${MANPAGES} +divert(0) diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/footer.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/footer.m4 new file mode 100644 index 00000000000..664a0baac09 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/footer.m4 @@ -0,0 +1,19 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: footer.m4,v 8.2 1999/05/13 16:16:35 gshapiro Exp $ +# +divert(0)dnl +################ Dependency scripts +include(confBUILDTOOLSDIR/M4/depend/ifdef(`confDEPEND_TYPE', `confDEPEND_TYPE', +`generic').m4)dnl +################ End of dependency scripts diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/library.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/library.m4 new file mode 100644 index 00000000000..3e2833cb251 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/library.m4 @@ -0,0 +1,34 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: library.m4,v 8.6 1999/08/13 21:31:08 gshapiro Exp $ +# +divert(0)dnl +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/links.m4')dnl +bldLIST_PUSH_ITEM(`bldC_PRODUCTS', bldCURRENT_PRODUCT)dnl +bldPUSH_TARGET(bldCURRENT_PRODUCT`.a')dnl +bldPUSH_INSTALL_TARGET(`install-'bldCURRENT_PRODUCT)dnl +bldPUSH_CLEAN_TARGET(bldCURRENT_PRODUCT`-clean')dnl + +include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/defines.m4') +divert(bldTARGETS_SECTION) +bldCURRENT_PRODUCT.a: ${BEFORE} ${bldCURRENT_PRODUCT`OBJS'} + ${AR} ${AROPTS} bldCURRENT_PRODUCT.a ${bldCURRENT_PRODUCT`OBJS'} + ${RANLIB} ${RANLIBOPTS} bldCURRENT_PRODUCT.a +ifdef(`bldLINK_SOURCES', `bldMAKE_SOURCE_LINKS(bldLINK_SOURCES)') + +install-`'bldCURRENT_PRODUCT: bldCURRENT_PRODUCT.a + +bldCURRENT_PRODUCT-clean: + rm -f ${OBJS} bldCURRENT_PRODUCT.a ${MANPAGES} + +divert(0) diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/links.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/links.m4 new file mode 100644 index 00000000000..5b61eecc7b3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/links.m4 @@ -0,0 +1,29 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: links.m4,v 8.5 1999/07/25 03:53:08 gshapiro Exp $ +# +divert(0)dnl +define(`bldMAKE_SOURCE_LINK', +`$1: ${SRCDIR}/$1 + -ln -s ${SRCDIR}/$1 $1' +)dnl +define(`bldMAKE_SOURCE_LINKS', +`bldFOREACH(`bldMAKE_SOURCE_LINK(', $1)'dnl +)dnl +define(`bldMAKE_TARGET_LINKS', +` for i in $2; do \ + rm -f $$i; \ + ln -s $1 $$i; \ + done' +)dnl + diff --git a/gnu/usr.sbin/sendmail/devtools/M4/UNIX/manpage.m4 b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/manpage.m4 new file mode 100644 index 00000000000..f2813473b4f --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/UNIX/manpage.m4 @@ -0,0 +1,76 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: manpage.m4,v 8.10 1999/10/27 05:17:55 gshapiro Exp $ +# +divert(0)dnl + +define(`bldGET_MAN_SOURCE_NUM', +`substr($1, eval(len($1) - 1))'dnl +)dnl +define(`bldGET_MAN_BASE_NAME', +`substr($1, 0, eval(len($1) - 2))'dnl +)dnl +ifdef(`confNO_MAN_BUILD',, ` +bldPUSH_TARGET(`${MANPAGES}') +bldPUSH_INSTALL_TARGET(`install-docs')') +bldLIST_PUSH_ITEM(`bldMAN_PAGES', `bldSOURCES')dnl + +MANOWN= ifdef(`confMANOWN', `confMANOWN', `bin') +MANGRP= ifdef(`confMANGRP', `confMANGRP', `bin') +MANMODE=ifdef(`confMANMODE', `confMANMODE', `444') +MANROOT=ifdef(`confMANROOT', `confMANROOT', `/usr/share/man/cat') +MANROOTMAN=ifdef(`confMANROOTMAN', `confMANROOTMAN', `/usr/share/man/man') +MAN1= ${MANROOT}ifdef(`confMAN1', `confMAN1', `1') +MAN1MAN=${MANROOTMAN}ifdef(`confMAN1', `confMAN1', `1') +MAN1EXT=ifdef(`confMAN1EXT', `confMAN1EXT', `1') +MAN1SRC=ifdef(`confMAN1SRC', `confMAN1SRC', `0') +MAN3= ${MANROOT}ifdef(`confMAN3', `confMAN3', `3') +MAN3MAN=${MANROOTMAN}ifdef(`confMAN3', `confMAN3', `3') +MAN3EXT=ifdef(`confMAN3EXT', `confMAN3EXT', `3') +MAN3SRC=ifdef(`confMAN3SRC', `confMAN3SRC', `0') +MAN4= ${MANROOT}ifdef(`confMAN4', `confMAN4', `4') +MAN4MAN=${MANROOTMAN}ifdef(`confMAN4', `confMAN4', `4') +MAN4EXT=ifdef(`confMAN4EXT', `confMAN4EXT', `4') +MAN4SRC=ifdef(`confMAN4SRC', `confMAN4SRC', `0') +MAN5= ${MANROOT}ifdef(`confMAN5', `confMAN5', `5') +MAN5MAN=${MANROOTMAN}ifdef(`confMAN5', `confMAN5', `5') +MAN5EXT=ifdef(`confMAN5EXT', `confMAN5EXT', `5') +MAN5SRC=ifdef(`confMAN5SRC', `confMAN5SRC', `0') +MAN8= ${MANROOT}ifdef(`confMAN8', `confMAN8', `8') +MAN8MAN=${MANROOTMAN}ifdef(`confMAN8', `confMAN8', `8') +MAN8EXT=ifdef(`confMAN8EXT', `confMAN8EXT', `8') +MAN8SRC=ifdef(`confMAN8SRC', `confMAN8SRC', `0') + +define(`bldMAN_TARGET_NAME', +`bldGET_MAN_BASE_NAME($1).${MAN`'bldGET_MAN_SOURCE_NUM($1)`SRC}' 'dnl +)dnl +MANPAGES= bldFOREACH(`bldMAN_TARGET_NAME(', `bldMAN_PAGES') + +divert(bldTARGETS_SECTION) +define(`bldMAN_BUILD_CMD', +`bldGET_MAN_BASE_NAME($1).${MAN`'bldGET_MAN_SOURCE_NUM($1)`SRC}': bldGET_MAN_BASE_NAME($1).bldGET_MAN_SOURCE_NUM($1) + ${NROFF} ${MANDOC} bldGET_MAN_BASE_NAME($1).bldGET_MAN_SOURCE_NUM($1) > bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}' || ${CP} bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}'.dist bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}'' + +)dnl +bldFOREACH(`bldMAN_BUILD_CMD(', `bldMAN_PAGES') + +install-docs: ${MANPAGES} +ifdef(`confNO_MAN_INSTALL', `divert(-1)', `dnl') +define(`bldMAN_INSTALL_CMD', +` ${INSTALL} -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} bldGET_MAN_BASE_NAME($1).`${MAN'bldGET_MAN_SOURCE_NUM($1)`SRC}' `${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)}/bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`EXT}' +ifdef(`confINSTALL_RAWMAN', +` ${INSTALL} -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} bldGET_MAN_BASE_NAME($1).`${MAN'bldGET_MAN_SOURCE_NUM($1)`EXT}' `${DESTDIR}${MAN'bldGET_MAN_SOURCE_NUM($1)`MAN}'/bldGET_MAN_BASE_NAME($1)`.${MAN'bldGET_MAN_SOURCE_NUM($1)`EXT}'', `dnl')' +)dnl +bldFOREACH(`bldMAN_INSTALL_CMD(', `bldMAN_PAGES') +ifdef(`confNO_MAN_INSTALL', `divert(0)', `dnl') +divert(0) diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/AIX.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/AIX.m4 new file mode 100644 index 00000000000..af024ad9b04 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/AIX.m4 @@ -0,0 +1,15 @@ +# $Sendmail: AIX.m4,v 8.2 1999/05/28 05:54:26 gshapiro Exp $ +depend: ${BEFORE} ${LINKS} + @mv Makefile Makefile.old + @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile + @echo "# Do not edit or remove this line or anything below it." >> Makefile + changequote([,]) + for i in ${SRCS}; \ + do \ + ${CC} -M -E ${COPTS} $$i > /dev/null; \ + cat `basename $$i .c`.u >> Makefile ; \ + rm -f `basename $$i .c`.u ; \ + done; + changequote + +# End of $RCSfile: AIX.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/BSD.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/BSD.m4 new file mode 100644 index 00000000000..d06375eea0f --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/BSD.m4 @@ -0,0 +1,8 @@ +# $Sendmail: BSD.m4,v 8.6 1999/05/27 22:03:28 peterh Exp $ +depend: ${BEFORE} ${LINKS} + @mv Makefile Makefile.old + @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile + @echo "# Do not edit or remove this line or anything below it." >> Makefile + mkdep -a -f Makefile ${COPTS} ${SRCS} + +# End of $RCSfile: BSD.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/CC-M.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/CC-M.m4 new file mode 100644 index 00000000000..5d2936280e9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/CC-M.m4 @@ -0,0 +1,8 @@ +# $Sendmail: CC-M.m4,v 8.5 1999/05/27 22:03:28 peterh Exp $ +depend: ${BEFORE} ${LINKS} + @mv Makefile Makefile.old + @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile + @echo "# Do not edit or remove this line or anything below it." >> Makefile + ${CC} -M ${COPTS} ${SRCS} >> Makefile + +# End of $RCSfile: CC-M.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/NCR.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/NCR.m4 new file mode 100644 index 00000000000..bb288d1a897 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/NCR.m4 @@ -0,0 +1,8 @@ +# $Sendmail: NCR.m4,v 8.6 1999/05/27 22:03:29 peterh Exp $ +depend: ${BEFORE} ${LINKS} + @mv Makefile Makefile.old + @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile + @echo "# Do not edit or remove this line or anything below it." >> Makefile + ${CC} -w0 -Hmake ${COPTS} ${SRCS} >> Makefile + +# End of $RCSfile: NCR.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/Solaris.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/Solaris.m4 new file mode 100644 index 00000000000..847c9d59a34 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/Solaris.m4 @@ -0,0 +1,8 @@ +# $Sendmail: Solaris.m4,v 8.4 1999/05/27 22:03:29 peterh Exp $ +depend: ${BEFORE} ${LINKS} + @mv Makefile Makefile.old + @sed -e '/^# Do not edit or remove this line or anything below it.$$/,$$d' < Makefile.old > Makefile + @echo "# Do not edit or remove this line or anything below it." >> Makefile + ${CC} -xM ${COPTS} ${SRCS} >> Makefile + +# End of $RCSfile: Solaris.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/X11.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/X11.m4 new file mode 100644 index 00000000000..40c3ab85c8d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/X11.m4 @@ -0,0 +1,5 @@ +# $Sendmail: X11.m4,v 8.4 1999/05/27 22:03:29 peterh Exp $ +depend: ${BEFORE} ${LINKS} + makedepend -- ${COPTS} -- ${SRCS} + +# End of $RCSfile: X11.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/depend/generic.m4 b/gnu/usr.sbin/sendmail/devtools/M4/depend/generic.m4 new file mode 100644 index 00000000000..f3fa117a4fe --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/depend/generic.m4 @@ -0,0 +1,6 @@ +# $Sendmail: generic.m4,v 8.5 1999/05/24 18:38:33 rand Exp $ +# dependencies + +# give a null "depend" list so that the startup script will work +depend: +# End of $RCSfile: generic.m4,v $ diff --git a/gnu/usr.sbin/sendmail/devtools/M4/header.m4 b/gnu/usr.sbin/sendmail/devtools/M4/header.m4 new file mode 100644 index 00000000000..e3b6c9cc90b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/header.m4 @@ -0,0 +1,35 @@ +# +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: header.m4,v 8.26 1999/08/09 18:57:22 gshapiro Exp $ +# +changecom(^A) +undefine(`format') +undefine(`hpux') +undefine(`unix') +ifdef(`pushdef', `', + `errprint(`You need a newer version of M4, at least as new as +System V or GNU') + include(NoSuchFile)') +define(`confCC', `cc') +define(`confSHELL', `/bin/sh') +define(`confBEFORE', `') +define(`confLIBDIRS', `') +define(`confINCDIRS', `') +define(`confLIBSEARCH', `db bind resolv 44bsd') +define(`confLIBSEARCHPATH', `/lib /usr/lib /usr/shlib') +define(`confSITECONFIG', `site.config') +define(`confBUILDBIN', `${SRCDIR}/devtools/bin') +define(`confRANLIB', `echo') +define(`PUSHDIVERT', `pushdef(`__D__', divnum)divert($1)') +define(`POPDIVERT', `divert(__D__)popdef(`__D__')') +define(`APPENDDEF', `define(`$1', ifdef(`$1', `$1 $2', `$2'))') +define(`PREPENDDEF', `define(`$1', ifdef(`$1', `$2 $1', `$2'))') diff --git a/gnu/usr.sbin/sendmail/devtools/M4/list.m4 b/gnu/usr.sbin/sendmail/devtools/M4/list.m4 new file mode 100644 index 00000000000..fb072c78c1e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/list.m4 @@ -0,0 +1,26 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: list.m4,v 8.3 1999/07/15 22:46:05 rand Exp $ +# +divert(0)dnl +define(`bldLIST_PUSH_ITEM', +`define(`$1', ifdef(`$1', `$1 $2 ', `$2 '))' +)dnl +define(`bldFOREACH', +`$1substr($2, `0', index($2, ` ')))`'ifelse(index($2, ` '), eval(len($2)-1), , `bldFOREACH(`$1', substr($2, index($2, ` ')))')'dnl +)dnl + +define(`bldADD_PATH', `$1/$2 ')dnl +define(`bldADD_PATHS', +`bldFOREACH(`bldADD_PATH(`$1',', $2)'dnl +)dnl diff --git a/gnu/usr.sbin/sendmail/devtools/M4/string.m4 b/gnu/usr.sbin/sendmail/devtools/M4/string.m4 new file mode 100644 index 00000000000..866061b4ddc --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/string.m4 @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: string.m4,v 8.2 1999/05/13 16:16:33 gshapiro Exp $ +# +divert(0)dnl +define(`bldRINDEX', +`ifelse(index($1, $2), `-1', `-1', `eval(index($1, $2) + bldRINDEX(substr($1, eval(index($1, $2) + 1)), $2) + 1)')'dnl +)dnl diff --git a/gnu/usr.sbin/sendmail/devtools/M4/subst_ext.m4 b/gnu/usr.sbin/sendmail/devtools/M4/subst_ext.m4 new file mode 100644 index 00000000000..24cf311149b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/subst_ext.m4 @@ -0,0 +1,30 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: subst_ext.m4,v 8.3 1999/05/24 18:29:46 rand Exp $ +# +divert(0)dnl +define(`bldSUBST_EXTENSION', +`substr($2, 0, bldRINDEX($2, `.'))`'.$1 'dnl +)dnl +define(`bldSUBST_EXTENSIONS', +`bldFOREACH(`bldSUBST_EXTENSION(`$1',', $2)'dnl +)dnl +define(`bldREMOVE_COMMAS', +`$1 ifelse($#, 1, , `bldREMOVE_COMMAS(shift($@))')'dnl +)dnl + +define(`bldADD_EXTENSION', `$2.$1 ')dnl +define(`bldADD_EXTENSIONS', +`bldFOREACH(`bldADD_EXTENSION(`$1',', $2)'dnl +)dnl + diff --git a/gnu/usr.sbin/sendmail/devtools/M4/switch.m4 b/gnu/usr.sbin/sendmail/devtools/M4/switch.m4 new file mode 100644 index 00000000000..1be998a6013 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/M4/switch.m4 @@ -0,0 +1,71 @@ +divert(-1) +# +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# Definitions for Makefile construction for sendmail +# +# $Sendmail: switch.m4,v 8.13 1999/09/07 17:21:50 ca Exp $ +# +divert(0)dnl +include(confBUILDTOOLSDIR`/M4/string.m4')dnl +include(confBUILDTOOLSDIR`/M4/list.m4')dnl +include(confBUILDTOOLSDIR`/M4/subst_ext.m4')dnl +define(`bldDEPENDENCY_SECTION', `3')dnl +define(`bldTARGETS_SECTION', `6')dnl +define(`bldPUSH_TARGET', + `bldLIST_PUSH_ITEM(`bldTARGETS', `$1')'dnl +)dnl + +define(`bldPUSH_INSTALL_TARGET', + `bldLIST_PUSH_ITEM(`bldINSTALL_TARGETS', `$1')'dnl +)dnl + +define(`bldPUSH_CLEAN_TARGET', + `bldLIST_PUSH_ITEM(`bldCLEAN_TARGETS', `$1')'dnl +)dnl + +define(`bldPUSH_ALL_SRCS', + `bldLIST_PUSH_ITEM(`bldALL_SRCS', `$1')'dnl +)dnl + +define(`bldPUSH_SMDEPLIB', + `bldLIST_PUSH_ITEM(`bldSMDEPLIBS', `$1')'dnl +)dnl + +define(`bldPUSH_SMLIB', + `bldPUSH_TARGET(`../lib$1/lib$1.a') +bldPUSH_SMDEPLIB(`../lib$1/lib$1.a') +PREPENDDEF(`confLIBDIRS', `-L../lib$1') +PREPENDDEF(`confLIBS', `-l$1') +divert(bldTARGETS_SECTION) +../lib$1/lib$1.a: + (cd ${SRCDIR}/lib$1; sh Build ${SENDMAIL_BUILD_FLAGS}) +divert +')dnl + +define(`bldPUSH_STRIP_TARGET', + `bldLIST_PUSH_ITEM(`bldSTRIP_TARGETS', `$1')'dnl +)dnl + +define(`bldPRODUCT_START', +`define(`bldCURRENT_PRODUCT', `$2')dnl +define(`bldCURRENT_PRD', translit(`$2', `.', `_'))dnl +define(`bldPRODUCT_TYPE', `$1')dnl' +)dnl + +define(`bldM4_TYPE_DIR',ifdef(`confNT', `NT', ``UNIX''))dnl + +define(`bldPRODUCT_END', +`include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/'bldPRODUCT_TYPE`.m4')' +)dnl + +define(`bldFINISH', +ifdef(`bldDONT_INCLUDE_ALL', ,``include(confBUILDTOOLSDIR`/M4/'bldM4_TYPE_DIR`/all.m4')'')dnl +undivert(bldTARGETS_SECTION)dnl +)dnl diff --git a/gnu/usr.sbin/sendmail/devtools/OS/386BSD b/gnu/usr.sbin/sendmail/devtools/OS/386BSD new file mode 100644 index 00000000000..2e4771e8191 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/386BSD @@ -0,0 +1,7 @@ +# $Sendmail: 386BSD,v 8.2 1999/02/07 03:21:07 gshapiro Exp $ +define(`confENVDEF', ` -DMIME') +define(`confLIBS', `-lutil') +define(`confLINKS', `/usr/sbin/sendmail /usr/bin/newaliases \ + /usr/sbin/sendmail /usr/bin/mailq \ + /usr/sbin/sendmail /usr/bin/hoststat \ + /usr/sbin/sendmail /usr/bin/purgestat') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/A-UX b/gnu/usr.sbin/sendmail/devtools/OS/A-UX new file mode 100644 index 00000000000..34c999725e1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/A-UX @@ -0,0 +1,9 @@ +# $Sendmail: A-UX,v 8.7 1999/06/02 22:53:34 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-D_POSIX_SOURCE') +define(`confLIBS', `-ldbm -lposix -lUTIL') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/AIX b/gnu/usr.sbin/sendmail/devtools/OS/AIX new file mode 100644 index 00000000000..3caf4bb0e1c --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/AIX @@ -0,0 +1,9 @@ +# $Sendmail: AIX,v 8.10 1999/06/02 22:53:34 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-D_AIX3') +define(`confOPTIMIZE', `-g') +define(`confLIBS', `-ldbm') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `AIX') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/AIX.2 b/gnu/usr.sbin/sendmail/devtools/OS/AIX.2 new file mode 100644 index 00000000000..5624db642ed --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/AIX.2 @@ -0,0 +1,8 @@ +# $Sendmail: AIX.2,v 8.10 1999/04/04 06:48:02 gshapiro Exp $ +define(`confMAPDEF', `-DNIS') +define(`confENVDEF', `-DBSD -DBSD_INCLUDES -DBSD_REMAP_SIGNAL_TO_SIGVEC') +define(`confOPTIMIZE', `-g') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confINSTALL', `/usr/ucb/install') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.2 b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.2 new file mode 100644 index 00000000000..e31115e5de7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.2 @@ -0,0 +1,10 @@ +# $Sendmail: AIX.4.2,v 8.11 1999/06/02 22:53:35 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-D_AIX4=40200') +define(`confOPTIMIZE', `-O3 -qstrict') +define(`confLIBS', `-ldbm') +define(`confLIBSEARCH', `db resolv 44bsd') +define(`confINSTALL', `/usr/ucb/install') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confDEPEND_TYPE', `AIX') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.3 b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.3 new file mode 100644 index 00000000000..0e48454e914 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.3 @@ -0,0 +1,13 @@ +# $Sendmail: AIX.4.3,v 8.11 1999/07/03 02:06:07 rand Exp $ +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-D_AIX4=40300') +define(`confOPTIMIZE', `-O3 -qstrict') +define(`confCC', `/usr/bin/xlc') +define(`confLIBS', `-ldbm') +define(`confINSTALL', `/usr/ucb/install') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confDEPEND_TYPE', `AIX') + +define(`confMTLDOPTS', `-lpthread') +define(`confLDOPTS_SO', `-Wl,-G -Wl,-bexpall') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.x b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.x new file mode 100644 index 00000000000..b1dbc7443ba --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/AIX.4.x @@ -0,0 +1,9 @@ +# $Sendmail: AIX.4.x,v 8.12 1999/06/02 22:53:35 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-D_AIX4') +define(`confOPTIMIZE', `-O3 -qstrict') +define(`confLIBS', `-ldbm') +define(`confINSTALL', `/usr/ucb/install') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `system') +define(`confDEPEND_TYPE', `AIX') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Altos b/gnu/usr.sbin/sendmail/devtools/OS/Altos new file mode 100644 index 00000000000..fd609f31062 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Altos @@ -0,0 +1,10 @@ +# $Sendmail: Altos,v 8.9 1999/06/02 22:53:35 gshapiro Exp $ +define(`confCC', `gcc') +define(`confENVDEF', `-DALTOS_SYSTEM_V') +define(`confLIBS', `-lsocket -lrpc') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/BSD-OS b/gnu/usr.sbin/sendmail/devtools/OS/BSD-OS new file mode 100644 index 00000000000..7aa4b213bac --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/BSD-OS @@ -0,0 +1,9 @@ +# $Sendmail: BSD-OS,v 8.11 1999/05/06 19:45:40 gshapiro Exp $ +define(`confMAPDEF', `-DNEWDB -DMAP_REGEX') +define(`confENVDEF', `-DNETISO') +define(`confLIBS', `-lutil -lkvm') +define(`confOPTIMIZE', `-O2') +define(`confMAN1EXT', `0') +define(`confMAN5EXT', `0') +define(`confMAN8EXT', `0') +define(`confSTDIO_TYPE', `torek') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/BSD43 b/gnu/usr.sbin/sendmail/devtools/OS/BSD43 new file mode 100644 index 00000000000..f4a01c6ff59 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/BSD43 @@ -0,0 +1,19 @@ +# $Sendmail: BSD43,v 8.8 1999/06/02 22:53:35 gshapiro Exp $ +define(`confBEFORE', `unistd.h stddef.h stdlib.h dirent.h sys/time.h') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DoldBSD43') +define(`confLIBS', `-ldbm -ll') +define(`confUBINDIR', `/usr/ucb') +PUSHDIVERT(3) +unistd.h stddef.h stdlib.h sys/time.h: + cp /dev/null $@ + +sys/time.h: sys + +sys: + mkdir sys + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/CLIX b/gnu/usr.sbin/sendmail/devtools/OS/CLIX new file mode 100644 index 00000000000..e879365676d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/CLIX @@ -0,0 +1,12 @@ +# $Sendmail: CLIX,v 8.12 1999/06/02 22:53:36 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DCLIX') +APPENDDEF(`confINCDIRS', `-I/usr/include') +define(`confLIBS', `-lnsl -lbsd') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `cp') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/CRAYT3E.2.0.x b/gnu/usr.sbin/sendmail/devtools/OS/CRAYT3E.2.0.x new file mode 100644 index 00000000000..a5c820aa007 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/CRAYT3E.2.0.x @@ -0,0 +1,9 @@ +# $Sendmail: CRAYT3E.2.0.x,v 8.4 1999/06/02 22:53:36 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DUNICOS') +define(`confOPTIMIZE', `-O') +define(`confINSTALL', `cpset') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bin') +define(`confEBINDIR', `/usr/lib') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/CRAYTS.10.0.x b/gnu/usr.sbin/sendmail/devtools/OS/CRAYTS.10.0.x new file mode 100644 index 00000000000..11bccb9b54c --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/CRAYTS.10.0.x @@ -0,0 +1,9 @@ +# $Sendmail: CRAYTS.10.0.x,v 8.4 1999/06/02 22:53:36 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DUNICOS') +define(`confOPTIMIZE', `-O') +define(`confINSTALL', `cpset') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bin') +define(`confEBINDIR', `/usr/lib') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/CSOS b/gnu/usr.sbin/sendmail/devtools/OS/CSOS new file mode 100644 index 00000000000..f2eb5b308c5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/CSOS @@ -0,0 +1,7 @@ +# $Sendmail: CSOS,v 8.7 1999/04/24 05:37:49 gshapiro Exp $ +define(`confLIBS', `-lnet') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confUBINDIR', `/usr/ucb') +define(`confINSTALL', `${BUILDBIN}/install.sh') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/ConvexOS b/gnu/usr.sbin/sendmail/devtools/OS/ConvexOS new file mode 100644 index 00000000000..dd5410da39e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/ConvexOS @@ -0,0 +1,9 @@ +# $Sendmail: ConvexOS,v 8.8 1999/04/24 05:37:49 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DYPCOMPAT -DNIS') +define(`confENVDEF', `-D__STDC__ -d non_int_bit_field') +define(`confOPTIMIZE', `-g') +define(`confLIBS', `-lshare') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Darwin b/gnu/usr.sbin/sendmail/devtools/OS/Darwin new file mode 100644 index 00000000000..657fea5e2ac --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Darwin @@ -0,0 +1,18 @@ +# $Sendmail: Darwin,v 8.2 1999/08/13 21:31:10 gshapiro Exp $ +# +# Wilfredo Sanchez : +# We look a lot more like 4.4BSD than NeXTStep or OpenStep. +# +define(`confCC', `cc -traditional-cpp -pipe ${Extra_CC_Flags}') +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX -DNETINFO -DAUTO_NETINFO_ALIASES -DAUTO_NETINFO_HOSTS') +define(`confENVDEF', `-DNETISO') +define(`confLDOPTS', `${Extra_LD_Flags}') +define(`confOPTIMIZE', `-O3') +define(`confRANLIBOPTS', `-c') +define(`confHFDIR', `/usr/share/sendmail') +define(`confMANOWN', `root') +define(`confMANGRP', `wheel') +define(`confUBINOWN', `root') +define(`confUBINGRP', `wheel') +define(`confSBINOWN', `root') +define(`confSBINGRP', `wheel') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Dell b/gnu/usr.sbin/sendmail/devtools/OS/Dell new file mode 100644 index 00000000000..12e8ad5b766 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Dell @@ -0,0 +1,13 @@ +# $Sendmail: Dell,v 8.11 1999/06/02 22:53:36 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-D__svr4__') +define(`confOPTIMIZE', `-O2') +define(`confLIBS', `-ldbm -lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucblib') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/DomainOS b/gnu/usr.sbin/sendmail/devtools/OS/DomainOS new file mode 100644 index 00000000000..8ae4393321b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/DomainOS @@ -0,0 +1,16 @@ +# $Sendmail: DomainOS,v 8.8 1999/04/24 05:37:50 gshapiro Exp $ +define(`confCC', `cc -A nansi -A,systype,any -A,runtype,bsd4.3') +define(`confBEFORE', `unistd.h dirent.h') +define(`confMAPDEF', `-DNDBM') +define(`confSBINDIR', `/usr/etc') +define(`confMBINDIR', `/usr/lib') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +unistd.h: + cp /dev/null unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/DomainOS.10.4 b/gnu/usr.sbin/sendmail/devtools/OS/DomainOS.10.4 new file mode 100644 index 00000000000..0acf7ec009f --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/DomainOS.10.4 @@ -0,0 +1,13 @@ +# $Sendmail: DomainOS.10.4,v 8.3 1999/04/24 05:37:52 gshapiro Exp $ +define(`confCC', `cc -A nansi -A,systype,any -A,runtype,bsd4.3') +define(`confBEFORE', `dirent.h') +define(`confMAPDEF', `-DNDBM') +define(`confSBINDIR', `/usr/etc') +define(`confMBINDIR', `/usr/lib') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Dynix b/gnu/usr.sbin/sendmail/devtools/OS/Dynix new file mode 100644 index 00000000000..09cc1bde7f9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Dynix @@ -0,0 +1,12 @@ +# $Sendmail: Dynix,v 8.10 1999/05/07 17:19:01 gshapiro Exp $ +define(`confCC', `gcc') +define(`confOPTIMIZE', `-O -g') +define(`confLIBS', `-lseq') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `staff # no kmem group,') +define(`confOBJADD', `strtol.o') +define(`confSRCADD', `strtol.c') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/EWS-UX_V b/gnu/usr.sbin/sendmail/devtools/OS/EWS-UX_V new file mode 100644 index 00000000000..27fcd04ddcc --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/EWS-UX_V @@ -0,0 +1,28 @@ +# $Sendmail: EWS-UX_V,v 8.10 1999/06/02 22:53:36 gshapiro Exp $ +define(`confCC', `/usr/abiccs/bin/cc -KOlimit=1000') +define(`confBEFORE', `sysexits.h ndbm.h ndbm.o') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-Dnec_ews_svr4') +define(`confLIBS', `ndbm.o -lsocket -lnsl -lelf # # with NDBM') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var/ucblib') +define(`confINSTALL', `/usr/ucb/install') +PUSHDIVERT(3) +sysexits.h: + echo '#ifndef _LOCAL_SYSEXITS_H_' > sysexits.h; + echo '#define _LOCAL_SYSEXITS_H_' >> sysexits.h; + cat /usr/abiccs/ucbinclude/sysexits.h >> sysexits.h; + echo '#endif /* _LOCAL_SYSEXITS_H_ */' >> sysexits.h; +# ln -s /usr/abiccs/ucbinclude/sysexits.h . + +ndbm.h: + ln -s /usr/abiccs/ucbinclude/ndbm.h . + +ndbm.o: + ar x /usr/abiccs/ucblib/libucb.a ndbm.o +# ar x /usr/ucblib/libucb.a ndbm.o +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/FreeBSD b/gnu/usr.sbin/sendmail/devtools/OS/FreeBSD new file mode 100644 index 00000000000..20ad9e6ede3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/FreeBSD @@ -0,0 +1,11 @@ +# $Sendmail: FreeBSD,v 8.19 1999/10/07 23:14:25 peterh Exp $ +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') +define(`confLIBS', `-lutil') +define(`confMTLDOPTS', `-pthread') +define(`confSTDIO_TYPE', `torek') + +define(`confLD', `cc') +define(`confLDOPTS_SO', `-shared') +define(`confCCOPTS_SO', `-fPIC') + +define(`confPERL_CONFIGURE_ARGS', `-Dlddlflags=-shared -Dccdlflags="-export-dynamic"') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/GNU b/gnu/usr.sbin/sendmail/devtools/OS/GNU new file mode 100644 index 00000000000..31be5133ea1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/GNU @@ -0,0 +1,18 @@ +# $Sendmail: GNU,v 8.2 2000/01/28 18:50:33 gshapiro Exp $ +define(`confCC', `gcc') +define(`confOPTIMIZE', `-g -O2') +define(`confDEPEND_TYPE', `CC-M') +define(`confEBINDIR', `/libexec') +define(`confMANROOT', `/man/man') +define(`confMANOWN', `root') +define(`confMANGRP', `wheel') +define(`confMANMODE', `644') +define(`confMBINDIR', `/sbin') +define(`confSBINDIR', `/sbin') +define(`confSBINOWN', `root') +define(`confSBINGRP', `wheel') +define(`confSBINMODE', `4755') +define(`confUBINDIR', `/bin') +define(`confUBINOWN', `root') +define(`confUBINGRP', `wheel') +define(`confUBINMODE', `755') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/HP-UX b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX new file mode 100644 index 00000000000..919f1615009 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX @@ -0,0 +1,11 @@ +# $Sendmail: HP-UX,v 8.12 1999/08/10 00:06:41 gshapiro Exp $ +define(`confCC', `cc -Aa') +define(`confENVDEF', `-D_HPUX_SOURCE') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confOPTIMIZE', `+O1') +define(`confLIBS', `-lndbm') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `${BUILDBIN}/install.sh') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.10.x b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.10.x new file mode 100644 index 00000000000..707d9f31ed4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.10.x @@ -0,0 +1,9 @@ +# $Sendmail: HP-UX.10.x,v 8.14 1999/08/10 00:06:41 gshapiro Exp $ +define(`confCC', `cc -Aa') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-D_HPUX_SOURCE -DV4FS') +define(`confOPTIMIZE', `+O3') +define(`confLIBS', `-lndbm') +define(`confSHELL', `/usr/bin/sh') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confSBINGRP', `mail') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.11.x b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.11.x new file mode 100644 index 00000000000..80475e8a71e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/HP-UX.11.x @@ -0,0 +1,17 @@ +# $Sendmail: HP-UX.11.x,v 8.11 1999/07/02 23:54:55 rand Exp $ + +# +z is to generate position independant code +define(`confCC', `cc -Ae +z') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-DV4FS -DHPUX11') +define(`confOPTIMIZE', `+O3') +define(`confLIBS', `-ldbm -lnsl') +define(`confSHELL', `/usr/bin/sh') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confSBINGRP', `mail') + +define(`confMTCCOPTS', `-D_POSIX_C_SOURCE=199506L') +define(`confMTLDOPTS', `-lpthread') +define(`confLD', `ld') +define(`confLDOPTS_SO', `-b') +define(`confCCOPTS_SO', `') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX b/gnu/usr.sbin/sendmail/devtools/OS/IRIX new file mode 100644 index 00000000000..e139c62a302 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX @@ -0,0 +1,11 @@ +# $Sendmail: IRIX,v 8.10 1999/06/02 22:53:37 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DIRIX') +define(`confLIBS', `-lmld -lmalloc -lsun') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX.5.x b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.5.x new file mode 100644 index 00000000000..2f6e7df7189 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.5.x @@ -0,0 +1,13 @@ +# $Sendmail: IRIX.5.x,v 8.11 1999/07/24 23:37:45 gshapiro Exp $ +define(`confCC', `cc -mips2') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DIRIX5') +define(`confLIBS', `-lmld -lmalloc') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.5 b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.5 new file mode 100644 index 00000000000..043797ab742 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.5 @@ -0,0 +1,13 @@ +# $Sendmail: IRIX.6.5,v 8.12 2000/01/27 19:27:45 ca Exp $ +define(`confCC', `cc -mips3 -n32 -OPT:Olimit=2700') +define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') +define(`confMAPDEF', `-DNEWDB -DNDBM -DNIS -DMAP_REGEX -DMAP_NSD') +define(`confENVDEF', `-DIRIX6 -DHASSNPRINTF=1') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.x b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.x new file mode 100644 index 00000000000..875d38ea807 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX.6.x @@ -0,0 +1,13 @@ +# $Sendmail: IRIX.6.x,v 8.20 1999/12/13 02:08:29 ca Exp $ +define(`confCC', `cc -mips3 -n32 -OPT:Olimit=2700') +define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-DIRIX6') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.0 b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.0 new file mode 100644 index 00000000000..5f5524e23f0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.0 @@ -0,0 +1,11 @@ +# $Sendmail: IRIX64.6.0,v 8.14 1999/07/24 23:37:45 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DIRIX64') +define(`confLIBS', `-lelf -lmalloc') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.1 b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.1 new file mode 100644 index 00000000000..721a05d0096 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.1 @@ -0,0 +1,11 @@ +# $Sendmail: IRIX64.6.1,v 8.14 1999/07/24 23:37:46 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DIRIX64') +define(`confLIBS', `-lelf -lmalloc') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.5 b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.5 new file mode 100644 index 00000000000..b8d65885df5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.5 @@ -0,0 +1,13 @@ +# $Sendmail: IRIX64.6.5,v 8.9 2000/01/27 19:27:45 ca Exp $ +define(`confCC', `cc -mips3 -n32 -OPT:Olimit=2700') +define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-DIRIX6 -DHASSNPRINTF=1') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.x b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.x new file mode 100644 index 00000000000..31da3358447 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/IRIX64.6.x @@ -0,0 +1,13 @@ +# $Sendmail: IRIX64.6.x,v 8.19 2000/01/27 19:27:46 ca Exp $ +define(`confCC', `cc -mips3 -n32 -OPT:Olimit=2700') +define(`confLIBSEARCHPATH', `/lib32 /usr/lib32') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confENVDEF', `-DIRIX6') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bsd') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/ISC b/gnu/usr.sbin/sendmail/devtools/OS/ISC new file mode 100644 index 00000000000..de0ed1848f7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/ISC @@ -0,0 +1,9 @@ +# $Sendmail: ISC,v 8.8 1999/06/02 22:53:38 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DISC_UNIX -D_POSIX_SOURCE -D_SYSV3') +define(`confLIBS', `-lyp -lrpc -lndbm -linet -lcposix') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSTDIR', `/usr/spool/log') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/KSR b/gnu/usr.sbin/sendmail/devtools/OS/KSR new file mode 100644 index 00000000000..73c613973c6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/KSR @@ -0,0 +1,6 @@ +# $Sendmail: KSR,v 8.6 1999/04/24 05:37:55 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confLIBDIRS', `-L/usr/shlib -L/usr/lib') +define(`confLIBS', `-ldbm') +define(`confSTDIR', `/var/adm/sendmail') +define(`confINSTALL', `installbsd') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/LUNA b/gnu/usr.sbin/sendmail/devtools/OS/LUNA new file mode 100644 index 00000000000..5da37333f6e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/LUNA @@ -0,0 +1,44 @@ +# $Sendmail: LUNA,v 8.10 1999/04/24 05:37:55 gshapiro Exp $ +define(`confBEFORE', `dirent.h stddef.h stdlib.h unistd.h limits.h time.h sys/time.h') +define(`confMAPDEF', `-DNDBM') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h + +stddef.h unistd.h limits.h: + if [ -f /usr/include/$@ ]; then \ + ln -s /usr/include/$@ .; \ + else \ + cp /dev/null $@; \ + fi + +stdlib.h: + if [ -f /usr/include/stdlib.h ]; then \ + ln -s /usr/include/stdlib.h .; \ + else \ + if [ -f /usr/include/libc.h ]; then \ + ln -s /usr/include/libc.h stdlib.h; \ + else \ + cp /dev/null stdlib.h; \ + fi; \ + fi + +# just for UNIOS-B +time.h: + echo "#ifndef _LOCAL_TIME_H_" > time.h + echo "#define _LOCAL_TIME_H_" >> time.h + cat /usr/include/time.h >> time.h + echo "#endif" >> time.h + +sys/time.h: + -mkdir sys + echo "#ifndef _LOCAL_SYS_TIME_H_" > sys/time.h + echo "#define _LOCAL_SYS_TIME_H_" >> sys/time.h + cat /usr/include/sys/time.h >> sys/time.h + echo "#endif" >> sys/time.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Linux b/gnu/usr.sbin/sendmail/devtools/OS/Linux new file mode 100644 index 00000000000..85da7d69ff6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Linux @@ -0,0 +1,9 @@ +# $Sendmail: Linux,v 8.17 1999/12/27 18:53:09 tony Exp $ +define(`confDEPEND_TYPE', `CC-M') +define(`confMANROOT', `/usr/man/man') +define(`confLIBS', `-ldl') +define(`confEBINDIR', `/usr/sbin') +APPENDDEF(`confLIBSEARCH', `crypt nsl') + +define(`confMTLDOPTS', `-lpthread') +define(`confLDOPTS_SO', `-shared') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Mach386 b/gnu/usr.sbin/sendmail/devtools/OS/Mach386 new file mode 100644 index 00000000000..a46dd62f33c --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Mach386 @@ -0,0 +1,9 @@ +# $Sendmail: Mach386,v 8.8 1999/04/24 05:37:55 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confLIBS', `-ldbm') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.2.x b/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.2.x new file mode 100644 index 00000000000..b8245fc3628 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.2.x @@ -0,0 +1,14 @@ +# $Sendmail: NCR.MP-RAS.2.x,v 8.13 1999/06/02 22:53:39 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DNCR_MP_RAS2') +define(`confOPTIMIZE', `-O2') +APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') +define(`confLIBDIRS', `-L/usr/ucblib') +define(`confLIBS', `-lnsl -lnet -lsocket -lelf -lc -lucb') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSTDIR', `/var/ucblib') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `NCR') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.3.x b/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.3.x new file mode 100644 index 00000000000..f5be81114cd --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NCR.MP-RAS.3.x @@ -0,0 +1,14 @@ +# $Sendmail: NCR.MP-RAS.3.x,v 8.16 1999/10/25 16:32:02 ca Exp $ +define(`confMAPDEF', `-DNDBM -DMAP_REGEX') +define(`confENVDEF', `-DNCR_MP_RAS3') +define(`confOPTIMIZE', `-O2') +APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') +define(`confLIBDIRS', `-L/usr/ucblib') +define(`confLIBS', `-lsocket -lnsl -lelf -lc -lucb') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSTDIR', `/var/ucblib') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `NCR') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.4.x b/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.4.x new file mode 100644 index 00000000000..15f4889ba3c --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.4.x @@ -0,0 +1,12 @@ +# $Sendmail: NEWS-OS.4.x,v 8.8 1999/04/24 05:37:56 gshapiro Exp $ +define(`confBEFORE', `limits.h') +define(`confMAPDEF', `-DNDBM') +define(`confLIBS', `-lmld') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +limits.h: + touch limits.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.6.x b/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.6.x new file mode 100644 index 00000000000..a8199e4696f --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NEWS-OS.6.x @@ -0,0 +1,25 @@ +# $Sendmail: NEWS-OS.6.x,v 8.13 1999/08/08 06:42:07 gshapiro Exp $ +define(`confCC', `/bin/cc') +define(`confBEFORE', `sysexits.h ndbm.o') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confLIBS', `ndbm.o -lelf -lsocket -lnsl') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `/usr/ucb/install') +PUSHDIVERT(3) +sysexits.h: + ln -s /usr/ucbinclude/sysexits.h . + +ndbm.o: + if [ ! -f /usr/include/ndbm.h ]; then \ + ln -s /usr/ucbinclude/ndbm.h .; \ + fi; \ + if [ -f /usr/lib/libndbm.a ]; then \ + ar x /usr/lib/libndbm.a ndbm.o; \ + else \ + ar x /usr/ucblib/libucb.a ndbm.o; \ + fi; +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NEXTSTEP.4.x b/gnu/usr.sbin/sendmail/devtools/OS/NEXTSTEP.4.x new file mode 100644 index 00000000000..ecc85596596 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NEXTSTEP.4.x @@ -0,0 +1,27 @@ +# $Sendmail: NEXTSTEP.4.x,v 8.5 1999/12/08 06:08:07 gshapiro Exp $ +PUSHDIVERT(1) +# NEXTSTEP 3.1 and 3.2 only support m68k and i386 +#ARCH= -arch m68k -arch i386 -arch hppa -arch sparc +#ARCH= -arch m68k -arch i386 +#ARCH= ${RC_CFLAGS} +# For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS +POPDIVERT +define(`confBEFORE', `unistd.h dirent.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') +define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') +define(`confLDOPTS', `${RC_CFLAGS}') +define(`confLIBS', `-ldbm') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confRANLIBOPTS', `-c') +PUSHDIVERT(3) +unistd.h: + cp /dev/null unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NeXT.2.x b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.2.x new file mode 100644 index 00000000000..641386adcfb --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.2.x @@ -0,0 +1,19 @@ +# $Sendmail: NeXT.2.x,v 8.11 1999/12/08 06:08:07 gshapiro Exp $ +define(`confBEFORE', `unistd.h dirent.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') +define(`confENVDEF', `-DNeXT') +define(`confLIBS', `-ldbm') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confRANLIBOPTS', `-c') +PUSHDIVERT(3) +unistd.h: + cp /dev/null unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NeXT.3.x b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.3.x new file mode 100644 index 00000000000..f3dad83d47c --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.3.x @@ -0,0 +1,30 @@ +# $Sendmail: NeXT.3.x,v 8.12 2000/02/01 08:39:38 gshapiro Exp $ +PUSHDIVERT(1) +# NEXTSTEP 3.1 and 3.2 only support m68k and i386 +#ARCH= -arch m68k -arch i386 -arch hppa -arch sparc +#ARCH= -arch m68k -arch i386 +#ARCH= ${RC_CFLAGS} +# For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS +POPDIVERT +define(`confBEFORE', `unistd.h dirent.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') +define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') +define(`confLDOPTS', `${RC_CFLAGS}') +define(`confLIBS', `-ldbm') +define(`confMANROOT', `/usr/man/cat') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confUBINOWN', `root') +define(`confMANOWN', `root') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confRANLIBOPTS', `-c') +PUSHDIVERT(3) +unistd.h: + cp /dev/null unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NeXT.4.x b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.4.x new file mode 100644 index 00000000000..b4e5d863ade --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NeXT.4.x @@ -0,0 +1,31 @@ +# $Sendmail: NeXT.4.x,v 8.15 2000/02/02 07:16:30 gshapiro Exp $ +PUSHDIVERT(1) +# NEXTSTEP 3.1 and 3.2 only support m68k and i386 +#ARCH= -arch m68k -arch i386 -arch hppa -arch sparc +#ARCH= -arch m68k -arch i386 +#ARCH= ${RC_CFLAGS} +# For new sendmail Makefile structure, this must go in the ENVDEF and LDOPTS +POPDIVERT +define(`confBEFORE', `unistd.h dirent.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNETINFO') +define(`confENVDEF', `-DNeXT -Wno-precomp -pipe ${RC_CFLAGS}') +define(`confLDOPTS', `${RC_CFLAGS}') +define(`confLIBS', `-ldbm') +define(`confRANLIBOPTS', `-c') +define(`confMANROOT', `/usr/man/cat') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confUBINOWN', `root') +define(`confMANOWN', `root') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confRANLIBOPTS', `-c') +PUSHDIVERT(3) +unistd.h: + cp /dev/null unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NetBSD b/gnu/usr.sbin/sendmail/devtools/OS/NetBSD new file mode 100644 index 00000000000..d2621cbca31 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NetBSD @@ -0,0 +1,10 @@ +# $Sendmail: NetBSD,v 8.9 1999/12/25 01:24:09 gshapiro Exp $ +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') +define(`confENVDEF', ` -DNETISO') +define(`confDEPEND_TYPE', `CC-M') +define(`confSTDIO_TYPE', `torek') +define(`confSBINGRP', `wheel') +define(`confUBINOWN', `root') +define(`confUBINGRP', `wheel') +define(`confMANOWN', `root') +define(`confMANGRP', `wheel') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NetBSD.8.3 b/gnu/usr.sbin/sendmail/devtools/OS/NetBSD.8.3 new file mode 100644 index 00000000000..d5b47995615 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NetBSD.8.3 @@ -0,0 +1,2 @@ +# $Sendmail: NetBSD.8.3,v 8.8 1999/08/08 02:52:05 gshapiro Exp $ +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/NonStop-UX b/gnu/usr.sbin/sendmail/devtools/OS/NonStop-UX new file mode 100644 index 00000000000..52606b6744b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/NonStop-UX @@ -0,0 +1,14 @@ +# $Sendmail: NonStop-UX,v 8.12 1999/06/02 22:53:39 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DNonStop_UX_BXX -D_SVID') +APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') +define(`confLIBDIRS', `-L/usr/ucblib') +define(`confLIBS', `-lsocket -lnsl -lelf -lucb') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/OSF1 b/gnu/usr.sbin/sendmail/devtools/OS/OSF1 new file mode 100644 index 00000000000..2c4f2de84b3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/OSF1 @@ -0,0 +1,11 @@ +# $Sendmail: OSF1,v 8.12 1999/11/12 21:19:05 rand Exp $ +define(`confCC', `cc -std1 -Olimit 1000') +define(`confMAPDEF', `-DNDBM -DNIS -DMAP_REGEX') +define(`confLIBS', `-ldbm') +define(`confSTDIR', `/var/adm/sendmail') +define(`confINSTALL', `installbsd') +define(`confEBINDIR', `/usr/lbin') +define(`confUBINDIR', `${BINDIR}') +define(`confDEPEND_TYPE', `CC-M') + +define(`confMTLDOPTS', `-lpthread') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/OpenBSD b/gnu/usr.sbin/sendmail/devtools/OS/OpenBSD new file mode 100644 index 00000000000..936ebc44227 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/OpenBSD @@ -0,0 +1,4 @@ +# $Sendmail: OpenBSD,v 8.7 1999/05/06 19:45:41 gshapiro Exp $ +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX') +define(`confENVDEF', ` -DNETISO') +define(`confSTDIO_TYPE', `torek') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/PTX b/gnu/usr.sbin/sendmail/devtools/OS/PTX new file mode 100644 index 00000000000..a3acfeaf6ff --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/PTX @@ -0,0 +1,8 @@ +# $Sendmail: PTX,v 8.8 1999/04/24 05:37:57 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confOPTIMIZE', `-g') +define(`confLIBS', `-lsocket -linet -lelf -lnsl -lseq') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Paragon b/gnu/usr.sbin/sendmail/devtools/OS/Paragon new file mode 100644 index 00000000000..32a347a6106 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Paragon @@ -0,0 +1,7 @@ +# $Sendmail: Paragon,v 8.5 1999/04/24 05:37:57 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM') +define(`confLIBDIRS', `-L/usr/shlib -L/usr/lib') +define(`confLIBS', `-ldbm') +define(`confSTDIR', `/var/adm/sendmail') +define(`confINSTALL', `installbsd') +define(`confUBINDIR', `${BINDIR}') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/PowerUX b/gnu/usr.sbin/sendmail/devtools/OS/PowerUX new file mode 100644 index 00000000000..9e4d9c9a469 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/PowerUX @@ -0,0 +1,9 @@ +# $Sendmail: PowerUX,v 8.7 1999/06/02 22:53:39 gshapiro Exp $ +define(`confENVDEF', `-D__svr4__') +define(`confLIBS', `-Bstatic -lsocket -lnsl -lelf -lgen') +define(`confMBINDIR', `/usr/local/etc') +define(`confSBINDIR', `/usr/local/etc') +define(`confUBINDIR', `/usr/local/bin') +define(`confEBINDIR', `/usr/local/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/QNX b/gnu/usr.sbin/sendmail/devtools/OS/QNX new file mode 100644 index 00000000000..5d06fb45d2b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/QNX @@ -0,0 +1,15 @@ +# $Sendmail: QNX,v 8.6 1999/04/05 20:00:39 gshapiro Exp $ +PUSHDIVERT(1) +# +# For this Makefile to work you must compile and install the libdb package +# and then change DBMINC and DBMLIB as appropriate. +# +DBMINC= /usr/local/include +DBMLIB= /usr/local/lib +POPDIVERT +define(`confENVDEF', `-Osax -w4 -zc -fr= -D__BIT_TYPES_DEFINED__') +APPENDDEF(`confINCDIRS', `${DBMINC}') +define(`confLIBDIRS', `${DBMLIB}') +define(`confLIBS', `-lsocket') +define(`confLDOPTS', `-M -N256k') +define(`confINSTALL', `${BUILDBIN}/install.sh') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/RISCos b/gnu/usr.sbin/sendmail/devtools/OS/RISCos new file mode 100644 index 00000000000..e2310935455 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/RISCos @@ -0,0 +1,23 @@ +# $Sendmail: RISCos,v 8.8 1999/06/02 22:53:40 gshapiro Exp $ +define(`confCC', `cc -systype bsd43 -Olimit 900') +define(`confBEFORE', `stdlib.h dirent.h unistd.h stddef.h') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DRISCOS') +define(`confLIBS', `-lmld') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `/usr/bsd43/bin/install') +PUSHDIVERT(3) +stdlib.h stddef.h: + cp /dev/null $@ + +unistd.h: + echo "typedef unsigned short mode_t;" > unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/RISCos.4_0 b/gnu/usr.sbin/sendmail/devtools/OS/RISCos.4_0 new file mode 100644 index 00000000000..871d70c49cc --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/RISCos.4_0 @@ -0,0 +1,23 @@ +# $Sendmail: RISCos.4_0,v 8.9 1999/06/02 22:53:40 gshapiro Exp $ +define(`confCC', `cc -systype bsd43 -Olimit 900') +define(`confBEFORE', `stdlib.h dirent.h unistd.h stddef.h') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DRISCOS -DRISCOS_4_0') +define(`confLIBS', `-lmld') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +PUSHDIVERT(3) +stdlib.h stddef.h: + cp /dev/null $@ + +unistd.h: + echo "typedef unsigned short mode_t;" > unistd.h + +dirent.h: + echo "#include " > dirent.h + echo "#define dirent direct" >> dirent.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Rhapsody b/gnu/usr.sbin/sendmail/devtools/OS/Rhapsody new file mode 100644 index 00000000000..e23c5af91a9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Rhapsody @@ -0,0 +1,18 @@ +# $Sendmail: Rhapsody,v 8.4 1999/08/13 21:31:10 gshapiro Exp $ +# +# Wilfredo Sanchez : +# We look a lot more like 4.4BSD than NeXTStep or OpenStep. +# +define(`confCC', `cc -traditional-cpp -pipe ${Extra_CC_Flags}') +define(`confMAPDEF', `-DNEWDB -DNIS -DMAP_REGEX -DNETINFO -DAUTO_NETINFO_ALIASES -DAUTO_NETINFO_HOSTS') +define(`confENVDEF', `-DNETISO') +define(`confLDOPTS', `${Extra_LD_Flags}') +define(`confOPTIMIZE', `-O3') +define(`confRANLIBOPTS', `-c') +define(`confHFDIR', `/usr/share/sendmail') +define(`confMANOWN', `root') +define(`confMANGRP', `wheel') +define(`confUBINOWN', `root') +define(`confUBINGRP', `wheel') +define(`confSBINOWN', `root') +define(`confSBINGRP', `wheel') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SCO b/gnu/usr.sbin/sendmail/devtools/OS/SCO new file mode 100644 index 00000000000..121cec34c55 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SCO @@ -0,0 +1,7 @@ +# $Sendmail: SCO,v 8.6 1999/06/02 22:53:40 gshapiro Exp $ +define(`confENVDEF', `-D_SCO_unix_') +define(`confLIBS', `-lsocket -lprot_s -lx -lc_s') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SCO.4.2 b/gnu/usr.sbin/sendmail/devtools/OS/SCO.4.2 new file mode 100644 index 00000000000..1887569d2fd --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SCO.4.2 @@ -0,0 +1,9 @@ +# $Sendmail: SCO.4.2,v 8.8 1999/06/02 22:53:40 gshapiro Exp $ +define(`confENVDEF', `-D_SCO_unix_4_2') +define(`confLIBS', `-lsocket -lndbm -lprot_s -lx -lc_s') +define(`confMAPDEF', `-DNDBM') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `bin') +define(`confINSTALL', `${BUILDBIN}/install.sh') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SCO.5.x b/gnu/usr.sbin/sendmail/devtools/OS/SCO.5.x new file mode 100644 index 00000000000..8c10390376a --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SCO.5.x @@ -0,0 +1,9 @@ +# $Sendmail: SCO.5.x,v 8.13 1999/04/26 16:11:50 gshapiro Exp $ +define(`confCC', `cc -b elf') +define(`confLIBS', `-lsocket -lndbm -lprot -lcurses -lm -lx -lgen') +define(`confMAPDEF', `-DMAP_REGEX -DNDBM') +define(`confSBINGRP', `bin') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/bin') +define(`confINSTALL', `${BUILDBIN}/install.sh') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.43 b/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.43 new file mode 100644 index 00000000000..38c88df3f9e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.43 @@ -0,0 +1,11 @@ +# $Sendmail: SINIX.5.43,v 8.2 1999/04/24 05:37:59 gshapiro Exp $ +define(`confCC', `/usr/bin/cc') +define(`confENVDEF', `-W0 -D__svr4__') +define(`confLIBS', `-lsocket -lnsl -lelf -lmproc') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confLDOPTS', `-s') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.44 b/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.44 new file mode 100644 index 00000000000..94034100b7a --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SINIX.5.44 @@ -0,0 +1,11 @@ +# $Sendmail: SINIX.5.44,v 8.2 1999/04/24 05:37:59 gshapiro Exp $ +define(`confCC', `/usr/bin/cc') +define(`confENVDEF', `-W0 -D__svr4__ -Klp64') +define(`confLIBS', `-lsocket -lnsl -lelf -lmproc') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confLDOPTS', `-Klp64 -s') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SVR4 b/gnu/usr.sbin/sendmail/devtools/OS/SVR4 new file mode 100644 index 00000000000..0e36d94b936 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SVR4 @@ -0,0 +1,12 @@ +# $Sendmail: SVR4,v 8.9 1999/06/02 22:53:40 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-D__svr4__') +define(`confLIBS', `-ldbm -lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS b/gnu/usr.sbin/sendmail/devtools/OS/SunOS new file mode 100644 index 00000000000..5c97b0353f7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS @@ -0,0 +1,8 @@ +# $Sendmail: SunOS,v 8.8 1999/04/24 05:37:59 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confLDOPTS', `-Bstatic') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.4.0 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.4.0 new file mode 100644 index 00000000000..ff8bc30e7a7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.4.0 @@ -0,0 +1,13 @@ +# $Sendmail: SunOS.4.0,v 8.9 1999/06/02 22:53:41 gshapiro Exp $ +define(`confBEFORE', `stdlib.h stddef.h limits.h') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DSUNOS403') +define(`confLDOPTS', `-Bstatic') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +stddef.h stdlib.h limits.h: + cp /dev/null $@ +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.1 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.1 new file mode 100644 index 00000000000..6161adf474d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.1 @@ -0,0 +1,20 @@ +# $Sendmail: SunOS.5.1,v 8.11 1999/06/02 22:53:41 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DSOLARIS=20100') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/ucbinclude/sysexits.h ]; \ + then \ + ln -s /usr/ucbinclude/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.2 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.2 new file mode 100644 index 00000000000..d521b2842b7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.2 @@ -0,0 +1,20 @@ +# $Sendmail: SunOS.5.2,v 8.11 1999/06/02 22:53:41 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DSOLARIS=20100') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/ucbinclude/sysexits.h ]; \ + then \ + ln -s /usr/ucbinclude/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.3 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.3 new file mode 100644 index 00000000000..743329409a1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.3 @@ -0,0 +1,18 @@ +# $Sendmail: SunOS.5.3,v 8.11 1999/06/02 22:53:41 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS') +define(`confENVDEF', `-DSOLARIS=20300') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/ucbinclude/sysexits.h ]; \ + then \ + ln -s /usr/ucbinclude/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.4 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.4 new file mode 100644 index 00000000000..5a20ae7258f --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.4 @@ -0,0 +1,18 @@ +# $Sendmail: SunOS.5.4,v 8.13 1999/06/02 22:53:41 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS') +define(`confENVDEF', `-DSOLARIS=20400') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.5 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.5 new file mode 100644 index 00000000000..8f2b401547a --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.5 @@ -0,0 +1,18 @@ +# $Sendmail: SunOS.5.5,v 8.14 1999/06/02 22:53:42 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') +define(`confENVDEF', `-DSOLARIS=20500') +define(`confLIBS', `-lsocket -lnsl -lkstat') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.6 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.6 new file mode 100644 index 00000000000..a0e79ab4c8b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.6 @@ -0,0 +1,19 @@ +# $Sendmail: SunOS.5.6,v 8.14 1999/06/02 22:53:42 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') +define(`confENVDEF', `-DSOLARIS=20600') +define(`confLIBS', `-lsocket -lnsl -lkstat') +define(`confMTLDOPTS', `-lpthread') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.7 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.7 new file mode 100644 index 00000000000..03cee185ba6 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.7 @@ -0,0 +1,19 @@ +# $Sendmail: SunOS.5.7,v 8.15 1999/07/30 22:42:47 rand Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX') +define(`confENVDEF', `-DSOLARIS=20700') +define(`confLIBS', `-lsocket -lnsl') +define(`confMTLDOPTS', `-lpthread') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.8 b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.8 new file mode 100644 index 00000000000..8bcdf21dc7d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/SunOS.5.8 @@ -0,0 +1,19 @@ +# $Sendmail: SunOS.5.8,v 8.6 1999/10/27 03:02:03 gshapiro Exp $ +define(`confCC', `gcc') +define(`confBEFORE', `sysexits.h') +define(`confMAPDEF', `-DNDBM -DNIS -DNISPLUS -DMAP_REGEX -DLDAPMAP') +define(`confENVDEF', `-DSOLARIS=20800') +define(`confLIBS', `-lsocket -lnsl -lldap') +define(`confMTLDOPTS', `-lpthread') +define(`confMBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `sys') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confDEPEND_TYPE', `CC-M') +PUSHDIVERT(3) +sysexits.h: + if [ -r /usr/include/sysexits.h ]; \ + then \ + ln -s /usr/include/sysexits.h; \ + fi +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/Titan b/gnu/usr.sbin/sendmail/devtools/OS/Titan new file mode 100644 index 00000000000..11e033007fb --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/Titan @@ -0,0 +1,13 @@ +# $Sendmail: Titan,v 8.6 1999/02/07 03:21:22 gshapiro Exp $ +define(`confCC', `cc -43') +define(`confBEFORE', `stddef.h stdlib.h') +define(`confMAPDEF', `-DNDBM') +define(`confLIBS', `-ldbm') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +PUSHDIVERT(3) +stddef.h stdlib.h: + cp /dev/null $@ +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/ULTRIX b/gnu/usr.sbin/sendmail/devtools/OS/ULTRIX new file mode 100644 index 00000000000..4293e2aafcf --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/ULTRIX @@ -0,0 +1,9 @@ +# $Sendmail: ULTRIX,v 8.12 1999/09/23 20:51:48 gshapiro Exp $ +define(`confCC', `cc -Olimit 1095') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confHFDIR', `/usr/lib') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UMAX b/gnu/usr.sbin/sendmail/devtools/OS/UMAX new file mode 100644 index 00000000000..bc27df753bd --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UMAX @@ -0,0 +1,15 @@ +# $Sendmail: UMAX,v 8.7 1999/06/02 22:53:42 gshapiro Exp $ +define(`confBEFORE', `stddef.h') +define(`confMAPDEF', `-DNIS') +define(`confENVDEF', `-DUMAXV') +define(`confLIBS', `-lyp -lrpc') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confHFDIR', `/usr/lib') +PUSHDIVERT(3) +stddef.h: + echo "#define _STDDEF_H" > stddef.h + chmod 444 stddef.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UNICOS b/gnu/usr.sbin/sendmail/devtools/OS/UNICOS new file mode 100644 index 00000000000..207f3b8620d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UNICOS @@ -0,0 +1,7 @@ +# $Sendmail: UNICOS,v 8.10 1999/06/02 22:53:43 gshapiro Exp $ +define(`confENVDEF', `-DUNICOS') +define(`confOPTIMIZE', `-O') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UNIX_SV.4.x.i386 b/gnu/usr.sbin/sendmail/devtools/OS/UNIX_SV.4.x.i386 new file mode 100644 index 00000000000..fbd801c128e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UNIX_SV.4.x.i386 @@ -0,0 +1,11 @@ +# $Sendmail: UNIX_SV.4.x.i386,v 8.10 1999/09/17 20:49:59 gshapiro Exp $ +define(`confCC', `gcc') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-D__svr4__ -DUNIXWARE') +define(`confLIBS', `-lc -ldbm -lsocket -lnsl -lgen -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UX4800 b/gnu/usr.sbin/sendmail/devtools/OS/UX4800 new file mode 100644 index 00000000000..7739e7afb20 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UX4800 @@ -0,0 +1,23 @@ +# $Sendmail: UX4800,v 8.13 1999/08/08 02:52:05 gshapiro Exp $ +define(`confCC', `/usr/abiccs/bin/cc -KOlimit=1000') +define(`confBEFORE', `sysexits.h ndbm.h') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DHASSNPRINTF=1') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `sys') +define(`confSTDIR', `/var/ucblib') +define(`confINSTALL', `/usr/ucb/install') +PUSHDIVERT(3) +sysexits.h: + echo '#ifndef _LOCAL_SYSEXITS_H_' > sysexits.h; + echo '#define _LOCAL_SYSEXITS_H_' >> sysexits.h; + cat /usr/abiccs/ucbinclude/sysexits.h >> sysexits.h; + echo '#endif /* _LOCAL_SYSEXITS_H_ */' >> sysexits.h; + +ndbm.h: + sed 's/void/char/' /usr/abiccs/include/ndbm.h > ndbm.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V10 b/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V10 new file mode 100644 index 00000000000..69792cb19ae --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V10 @@ -0,0 +1,13 @@ +# $Sendmail: UXPDS.V10,v 8.13 1999/06/02 22:53:45 gshapiro Exp $ +define(`confCC', `/usr/ccs/bin/cc') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DUXPDS=10') +APPENDDEF(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') +define(`confLIBS', `/usr/ucblib/libdbm.a /usr/ucblib/libucb.a -lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confMANROOT', `/usr/local/man/man') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V20 b/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V20 new file mode 100644 index 00000000000..7c599bce3c5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UXPDS.V20 @@ -0,0 +1,20 @@ +# $Sendmail: UXPDS.V20,v 8.12 1999/06/02 22:53:45 gshapiro Exp $ +define(`confCC', `/usr/ccs/bin/cc') +define(`confBEFORE', `netinet/ip_var.h') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confENVDEF', `-DUXPDS=20') +define(`confLIBS', `/usr/ucblib/libdbm.a -lsocket -lnsl -lelf') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `${BUILDBIN}/install.sh') +define(`confMANROOT', `/usr/local/man/man') +PUSHDIVERT(3) +netinet/ip_var.h: netinet /usr/include/netinet/ip_var.h + sed '/ip_var_f.h/d' /usr/include/netinet/ip_var.h > netinet/ip_var.h + +netinet: + mkdir netinet +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/OS/UnixWare.5.i386 b/gnu/usr.sbin/sendmail/devtools/OS/UnixWare.5.i386 new file mode 100644 index 00000000000..2bb606330f8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/UnixWare.5.i386 @@ -0,0 +1,16 @@ +# $Sendmail: UnixWare.5.i386,v 8.4 1999/04/24 05:38:02 gshapiro Exp $ +# +# System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatiblity Libs ie. native) +# Contributed by Paul Gampe +# +define(`confCC', `/usr/ccs/bin/cc') +define(`confMAPDEF', `-DNDBM -DMAP_REGEX') +define(`confENVDEF', `-D__svr5__') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confSHELL', `/usr/bin/sh') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/etc/mail') +define(`confUBINDIR', `/etc/mail') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `/usr/ucb/install') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/dcosx.1.x.NILE b/gnu/usr.sbin/sendmail/devtools/OS/dcosx.1.x.NILE new file mode 100644 index 00000000000..79de489dc36 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/dcosx.1.x.NILE @@ -0,0 +1,6 @@ +# $Sendmail: dcosx.1.x.NILE,v 8.5 1999/06/02 22:53:46 gshapiro Exp $ +define(`confENVDEF', `-D__svr4__ -DDCOSx') +define(`confLIBS', `-lsocket -lnsl -lelf') +define(`confHFDIR', `/usr/share/lib/mail') +define(`confINSTALL', `/usr/ucb/install') +define(`confSBINGRP', `sys') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/dgux b/gnu/usr.sbin/sendmail/devtools/OS/dgux new file mode 100644 index 00000000000..c9695d7f64b --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/dgux @@ -0,0 +1,8 @@ +# $Sendmail: dgux,v 8.7 1999/04/24 05:38:02 gshapiro Exp $ +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confLIBS', `-ldbm') +define(`confMBINDIR', `/usr/bin') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `bin') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/m88k b/gnu/usr.sbin/sendmail/devtools/OS/m88k new file mode 100644 index 00000000000..f72a1af38de --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/m88k @@ -0,0 +1,20 @@ +# $Sendmail: m88k,v 8.2 2000/01/28 19:00:01 gshapiro Exp $ +# +# Contributed by Sergey Rusanov +# +define(`confCC', `gcc') +define(`confOPTIMIZE', `-O2') +define(`confMAPDEF', `-DNDBM') +define(`confENVDEF', `-DMOTO') +define(`confINCDIRS', `-I/usr/include -I/usr/ucbinclude') +define(`confLIBDIRS', `-L/usr/lib -L/usr/ucblib') +define(`confLIBS', `-lc -ldbm -lsocket -lnsl -lelf -lucb') +define(`confMBINDIR', `/usr/local/sbin') +define(`confSBINDIR', `/usr/ucb') +define(`confUBINDIR', `/usr/local/bin') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINGRP', `mail') +define(`confSTDIR', `/var/log') +define(`confHFDIR', `/usr/local/sbin') +define(`confINSTALL', `/usr/ucb/install') +define(`confDEPEND_TYPE', `CC-M') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/maxion b/gnu/usr.sbin/sendmail/devtools/OS/maxion new file mode 100644 index 00000000000..226baf593ed --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/maxion @@ -0,0 +1,13 @@ +# $Sendmail: maxion,v 8.8 1999/04/24 05:38:02 gshapiro Exp $ +define(`confCC', `/usr/ucb/cc') +define(`confMAPDEF', `-DNDBM -DNIS') +define(`confLIBDIRS', `-L/usr/ucblib') +define(`confLIBS', `-ldbm -lgen -lucb') +define(`confMBINDIR', `/usr/ucblib') +define(`confSBINDIR', `/usr/ucbetc') +define(`confUBINDIR', `/usr/ucb') +define(`confEBINDIR', `/usr/ucblib') +define(`confSBINOWN', `smtp') +define(`confSBINGRP', `mail') +define(`confSTDIR', `/var/adm/log') +define(`confINSTALL', `/usr/ucb/install') diff --git a/gnu/usr.sbin/sendmail/devtools/OS/uts.systemV b/gnu/usr.sbin/sendmail/devtools/OS/uts.systemV new file mode 100644 index 00000000000..3f718f63b8e --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/OS/uts.systemV @@ -0,0 +1,24 @@ +# $Sendmail: uts.systemV,v 8.14 1999/06/02 22:53:47 gshapiro Exp $ +PUSHDIVERT(1) +# Sendmail 8 on UTS requires BIND 4.9's include files and lib44bsd and +# libresolv libraries. The BIND version on UTS is much too old. +# +BINDPATH=../../../bind +POPDIVERT +define(`confBEFORE', `stddef.h') +define(`confMAPDEF', `-DNIS -DNDBM') +define(`confENVDEF', `-D_UTS') +define(`confOPTIMIZE', `-g') +APPENDDEF(`confINCDIRS', `-I${BINDPATH}/include -I${BINDPATH}/compat/include') +define(`confLIBDIRS', `-L${BINDPATH}/res -L${BINDPATH}/compat/lib') +define(`confLIBS', `-lyp -lrpc -lbsd -lsocket -la') +define(`confMBINDIR', `/usr/lib') +define(`confSBINDIR', `/usr/etc') +define(`confUBINDIR', `/usr/lib') +define(`confEBINDIR', `/usr/lib') +define(`confSBINGRP', `mail') +define(`confINSTALL', `${BUILDBIN}/install.sh') +PUSHDIVERT(3) +stddef.h: + echo "#include " > stddef.h +POPDIVERT diff --git a/gnu/usr.sbin/sendmail/devtools/README b/gnu/usr.sbin/sendmail/devtools/README new file mode 100644 index 00000000000..bae04f73d52 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/README @@ -0,0 +1,311 @@ +This directory contains tools. Do not attempt to actually build +anything in this directory. + +The Build script allows you to specify a base location for the object +files by using the -O flag: + + Build -O /tmp + +will put the object files in /tmp/obj.*/. Also, if the SENDMAIL_SUFFIX +environment variable is set, its value will be used in the obj.* directory +name. + +The Build script allows you to specify a site configuration file by using +the -f flag: + + Build -f siteconfig.m4 + +You can put such site configuration files in the Site sub-directory; +see Site/README for details. + +If you need to support multiple build configurations from the same tree, +you can use prefixes to differentiate your configurations. Use the -Q +flag to Build: + + Build -Q prefix + +Build will select a prefix.*.m4 file instead of the site.*.m4 file according +to the conventions in Site/README, and use it to modify the build +configuration. The object directory used will be obj.prefix.*/. Your +prefix.*.m4 files should reside in the Site directory. You may not use +-Q and -f simultaneously. + +While building a site configuration file, beyond using define() to set +variables, you can also add to a definition using the APPENDDEF() and +PREPENDDEF() macros. For example: + + APPENDDEF(`confINCDIRS', `-I/usr/local/bind/include') + +will add -I/usr/local/bind/include to the already existing confINCDIRS. +Note: There must be no trailing spaces after the last quote mark and +before the closing parenthesis. Also you may need to properly quote +m4 reserved words as specified by your vendor's m4 command. + +By default, sendmail will search your system for include and library +directories as well as certain libraries (libdb.* for Berkeley DB and +libbind.a or libresolv.* for name resolution). You can turn off this +configuration step by specifying the -S flag with the Build command. + +The OS subtree contains definitions for variations on a standard +model for system installation. The M4 variables that can be defined +and their defaults before referencing the appropriate OS definitions +are listed below. Note that variables preceded by an asterisk (*) +are currently not used in the open source distribution. + +confBEFORE [empty] Files to create before sendmail is + compiled. The methods must be defined + in the Makefile using PUSHDIVERT(3). +confBUILDBIN ../../devtools/bin The location of the build support + binaries, relative to the obj.* + directory. +confCC cc The C compiler to use. +confOPTIMIZE -O Flags passed to C compiler as ${O}. +confCCOPTS [empty] Additional options to pass to confCC. +*confCCOPTS_SO -fPIC Additional options for compiling + shared object libraries. +*confMTCCOPTS [empty] Additional options for compiling + multi-threaded object files. +confCOPY cp A program that copies files. +confDEPEND_TYPE generic How to build dependencies. This should + be the name of a file in + devtools/M4/depend +confEBINDIR /usr/libexec The location for binaries executed + from other binaries, e.g., mail.local + or smrsh. +confENVDEF [empty] -D flags passed to C compiler. +confFORCE_RMAIL [undefined] If defined, install the rmail program + without question. +confHFDIR /etc/mail Location of the sendmail helpfile. +confHFFILE helpfile Name of the installed helpfile. +confINCDIRS [empty] -I flags passed to C compiler. +confINSTALL install The BSD-compatible install program. + Use ${BUILDBIN}/install.sh if none + is available on your system. +confINSTALL_RAWMAN [undefined] Install the unformatted manual pages. +*confLD confCC Linker to use. +confLDOPTS [empty] Linker options passed to ld. +*confLDOPTS_SO -shared -Wl Additional linker options for + linking shared object libraries. +*confMTLDOPTS [empty] Additional linker options for + linking multithreaded binaries. +confLIBDIRS [empty] -L flags passed to ld. +confLIBS [varies] -l flags passed to ld. +confLIBSEARCH db bind resolv 44bsd + Search for these libraries for + linking with programs. +confLIBSEARCHPATH /lib /usr/lib /usr/shlib + Locations to search for the + libraries specified by confLIBSEARCH. +confLINKS ${UBINDIR}/newaliases ${UBINDIR}/mailq \ + ${UBINDIR}/hoststat ${UBINDIR}/purgestat + Names of links to sendmail. +confMANROOT /usr/share/man/cat The root of the man subtree. +confMANROOTMAN /usr/share/man/man The root of the man subtree, for + unformatted manual pages. +confMAN1 confMANROOT 1 The location of man1 files. +confMAN1EXT 1 The extension on files in confMAN1. +confMAN1SRC 0 The source for man pages installed + in confMAN1. +confMAN3 confMANROOT 3 The location of man3 files. +confMAN3EXT 4 The extension on files in confMAN3. +confMAN3SRC 0 The source for man pages installed + in confMAN3. +confMAN4 confMANROOT 4 The location of man4 files. +confMAN4EXT 4 The extension on files in confMAN4. +confMAN4SRC 0 The source for man pages installed + in confMAN4. +confMAN5 confMANROOT 5 The location of man5 files. +confMAN5EXT 5 The extension on files in confMAN5. +confMAN5SRC 0 The source for man pages installed + in confMAN5. +confMAN8 confMANROOT 8 The location of man8 files. +confMAN8EXT 8 The extension on files in confMAN8. +confMAN8SRC 0 The source for man pages installed + in confMAN8. +confMANDOC -man The macros used to format man pages. +confMANOWN bin The owner of installed man pages. +confMANGRP bin The group of installed man pages. +confMANMODE 444 The mode of installed man pages. +confMAPDEF [varies] The map definitions, e.g., + -DNDBM -DNEWDB. -DNEWDB is always + added if libdb.* can be found. +confNO_MAN_BUILD [undefined] If defined, don't build the man + pages. +confNO_HELPFILE_INSTALL [undefined] If defined, don't install the sendmail + helpfile by default. +confNO_MAN_INSTALL [undefined] If defined, don't install the man + pages by default. +confNO_STATISTICS_INSTALL [undefined] If defined, don't install the sendmail + statistics file by default. +confMBINDIR /usr/sbin The location of the MTA (sendmail) + binary. +confNROFF groff -Tascii The command to format man pages. +confOBJADD [empty] Objects that should be included in + when linking sendmail and the + associated utilities. See also + confSRCADD. +confRANLIB echo The path to the program to use + as ranlib. +confRANLIBOPTS [empty] Options to pass to ranlib. +confSBINDIR /usr/sbin The location of root-oriented + commands, such as makemap. +confSBINOWN root The owner for setuid binaries. +confSBINGRP sbin The group for setuid binaries. +confSBINMODE 4555 The mode for setuid binaries. +confSHELL /bin/sh The shell to use inside make. +confSMOBJADD [empty] Objects that should be included in + when linking sendmail. See also + confSMSRCADD. +confSMSRCADD [empty] C source files which correspond to + objects listed in confSMOBJADD. +confSMSRCDIR [varies] The sendmail source directory + relative to support program obj.* + directories. If not set, the + Makefile will use a path set by the + Build script. +confSRCADD [empty] C source files which correspond to + objects listed in confOBJADD. +confSRCDIR [varies] The root of the source directories + relative to support program obj.* + directories. If not set, the + Makefile will use a path set by the + Build script. +confSTDIO_TYPE portable Buffered file implementation + (based on stdio library). Either + portable or torek. +confSTDIR /etc/mail The directory in which to store the + sendmail statistics file. +confSTFILE statistics Name of the installed statistics file. +confSTRIP strip What program to use for stripping + executables. +confSTRIPOPTS [empty] Options to pass to the strip program. +confUBINDIR /usr/bin The directory for user-executable + binaries. +confUBINOWN bin The owner for user-executable binaries. +confUBINGRP bin The group for user-executable binaries. +confUBINMODE 555 The mode for user-executable binaries. + +There are also program specific variables for each of the programs +in the sendmail distribution. Each has the form `conf_prog_ENVDEF', +for example, `conf_sendmail_ENVDEF'. If the program name consists +a '.' it must be replaced by '_' first, e.g., use `conf_mail_local_LIBS' +instead of `conf_mail.local_LIBS'. The variables are: + +conf_prog_ENVDEF [empty] -D flags passed to C compiler when + compiling prog. +conf_prog_LIBS [varies] -l flags passed to ld when linking + prog. +conf_prog_SRCADD [empty] C source files to compile and link + for prog. +conf_prog_OBJADD [empty] Additional object files given to ld + when linking prog. + +---------------------------------------------------------------- + +---------------- +New build system +---------------- + +Sendmail's build system has undergone some rearrangement to accommodate +future development. To the end user building sendmail from a distribution, +this should have little effect. All the same configuration files and macros +should still behave the same. + +If you need to make some radical changes to a Makefile.m4 or are adding new +libraries or utilities, you may want to read the rest of this document on +how to work with the new system. + + +-------- +Overview +-------- + +The purpose of the redesign is twofold. First, it cuts down massively on +replicated information. Second, the new design should lend itself better to +working on platforms with somewhat different build tools than on standard +unix. + +The main idea is to have the Makefile.m4 in each subdirectory contain the +minimum amount of information needed to describe the elements needed for +the build process and the products produced. + +Each product has a type and each type has a template that provides a basic +makefile for that type. Right now the templates are organized by the broad +type of the operating system. The two existing types are UNIX and NT. + + +------------------ +Makefile.m4 basics +------------------ + +Each Makefile.m4 is split into separate products. For the most part, the +products are considered totally separate from other products in the +Makefile.m4. Each products is delineated by two macros: bldPRODUCT_START and +bldPRODUCT_END. + +The form for bldPRODUCT_START is: +bldPRODUCT_START(, ) +where is the type of product to be produced (e.g., executable, +library, manpage) and is a unique identifier within the +product_type name space for this Makefile.m4 + +The form for bldPRODUCT_END is: +bldPRODUCT_END + +This is marks the end of all the information for the current product. + +There is one other macro required in any Makefile.m4 and that is bldFINISH +which takes no arguments and must appear after all the products have been +defined. + +When the actual makefile is generated each product appears in two sections. +The first is where makefile variables are set (e.g., CFLAGS=-O). The second +is where the targets appear (e.g., foo.o: foo.c). Anything diverted to +bldTARGETS_SECTION ends up in the second part of the makefile. Anything +else turns up in the header part where variables are defined. + +As always, any straight text put into Makefile.m4 will just show up as is +in the finished makefile. + + +------------- +Product Types +------------- + +executable +---------- + +This means an executable created from C sources. The name of the executable +is derived from the product_name in the bldPRODUCT_START macro. + +bldSOURCES - This should be defined to a space separated list of source +files that make up the executable. + +bldBIN_TYPE - This determines where the binaries will be installed and what +permissions they will have. Available types are `U', `K', `S', and `E'. See +M4/make/executable.m4 for what the different types mean. + +bldTARGET_LINKS - This determines where additional symbolic links to the +executable are placed. These should be full pathnames, separated by +spaces. + + +manpage +------- + +This builds manpages from source using *roff. + +bldSOURCES - This should be defined to a space separated list of man source +files. + + +library +------- + +This builds a static library from C sources. + +bldSOURCES - This should be defined to a space separated list of C source +files that make up the library. + + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:37 $ diff --git a/gnu/usr.sbin/sendmail/devtools/Site/README b/gnu/usr.sbin/sendmail/devtools/Site/README new file mode 100644 index 00000000000..0c6b4b98b40 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/Site/README @@ -0,0 +1,18 @@ +The Build script will look for the default site configuration files in +this directory. Build will include the following files if they are +present in this directory: + + site.config.m4 + site.OS.$SENDMAIL_SUFFIX.m4 + site.OS.m4 + site.post.m4 + +OS is the name of the operating system file selected from the devtools/OS +directory. SENDMAIL_SUFFIX is a user environment variable which can be +used to further distinguish between site configuration files in this +directory. If set, it will also be used in generating the obj.* directory +name. + +See the README in the devtools directory for more information. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:39 $ diff --git a/gnu/usr.sbin/sendmail/devtools/bin/Build b/gnu/usr.sbin/sendmail/devtools/bin/Build new file mode 100644 index 00000000000..52e3a7d72a1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/bin/Build @@ -0,0 +1,743 @@ +#!/bin/sh + +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1993, 1996-1997 Eric P. Allman. All rights reserved. +# Copyright (c) 1993 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.145 2000/02/01 05:49:49 gshapiro Exp $ +# + +# +# A quick-and-dirty script to compile sendmail and related programs +# in the presence of multiple architectures. To use, just use +# "sh Build". +# + +trap "rm -f $obj/.settings$$; exit" 1 2 3 15 + +cflag="" +mflag="" +Mflag="" +Aflag="" +sflag="" +makeargs="" +libdirs="" +incdirs="" +libsrch="" +libpath="" +siteconfig="" +pfx="" +obj="" +oscf="" +arch="" +os="" +rel="" +mkdir="mkdir -p" +SENDMAIL_BUILD_FLAGS="" +EX_OK=0 +EX_USAGE=64 +EX_NOINPUT=66 +EX_UNAVAILABLE=69 + +full_src_dir=`pwd` +if [ -z "$src_dir" ] +then + src_dir=`basename ${full_src_dir}` +fi +absolute_base_dir=`echo ${full_src_dir} | sed "s#${src_dir}\\$##"` +obj_rel_base_dir='../..' + +while [ ! -z "$1" ] +do + case $1 + in + -c) # clean out existing $obj tree + cflag=1 + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" + shift + ;; + + -m) # show Makefile name only + mflag=1 + shift + ;; + + -M) # show the name of the obj. directory + Mflag=1 + shift + ;; + + -A) # show the name of the architecture + Aflag=1 + shift + ;; + + -E*) # environment variables to pass into Build + arg=`echo $1 | sed 's/^-E//'` + if [ -z "$arg" ] + then + shift # move to argument + arg=$1 + fi + if [ -z "$arg" ] + then + echo "Empty -E flag" >&2 + exit $EX_USAGE + else + case $arg + in + *=*) # check format + eval $arg + export `echo $arg | sed 's;=.*;;'` + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -E \"$arg\"" + ;; + *) # bad format + echo "Bad format for -E argument ($arg)" >&2 + exit $EX_USAGE + ;; + esac + shift + fi + ;; + + -L*) # set up LIBDIRS + libdirs="$libdirs $1" + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" + shift + ;; + + -I*) # set up INCDIRS + incdirs="$incdirs $1" + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" + shift + ;; + + -f*) # select site config file + arg=`echo $1 | sed 's/^-f//'` + if [ -z "$arg" ] + then + shift # move to argument + arg=$1 + fi + if [ "$pfx" ] + then + echo "May not use -f and -Q together" + exit $EX_USAGE + fi + if [ "$siteconfig" ] + then + echo "Only one -f flag allowed" >&2 + exit $EX_USAGE + else + siteconfig=$arg + if [ -z "$siteconfig" ] + then + echo "Missing argument for -f flag" >&2 + exit $EX_USAGE + elif [ ! -f "$siteconfig" ] + then + echo "${siteconfig}: File not found" + exit $EX_NOINPUT + else + shift # move past argument + case $arg + in + /*) + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -f \"$siteconfig\"" + ;; + *) + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -f \"${full_src_dir}/$siteconfig\"" + ;; + esac + fi + fi + ;; + + -O*) # Set object directory manually. + arg="`echo $1 | sed 's/^-O//'`" + if [ -z "$arg" ] + then + shift # move to argument + arg="$1" + fi + case $arg + in + /*) + OBJ_ROOT="$arg" + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -O \"$OBJ_ROOT\"" + obj_rel_base_dir=$absolute_base_dir + ;; + *) + echo "Absolute directory path required for -O flag" >&2 + exit $EX_USAGE + ;; + esac + shift + ;; + + -S) # skip auto-configure + sflag="-s" + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS $1" + shift + ;; + + -Q*) # Select a prefix for the Site/*.config.m4 file + arg=`echo $1 | sed 's/^-Q//'` + if [ -z "$arg" ] + then + shift # move to argument + arg=$1 + fi + if [ -z "$arg" ] + then + echo "Empty -Q flag" >&2 + exit $EX_USAGE + elif [ "$siteconfig" ] + then + echo "May not use -Q and -f together" >&2 + exit $EX_USAGE + elif [ "$pfx" ] + then + echo "Only one -Q allowed" >&2 + exit $EX_USAGE + else + pfx=$arg + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS -Q \"$pfx\"" + fi + shift + ;; + + *) # pass argument to make + makeargs="$makeargs \"$1\"" + SENDMAIL_BUILD_FLAGS="$SENDMAIL_BUILD_FLAGS \"$1\"" + shift + ;; + esac +done + +# +# Do heuristic guesses !ONLY! for machines that do not have uname +# +if [ -d /NextApps -a ! -f /bin/uname -a ! -f /usr/bin/uname ] +then + # probably a NeXT box + arch=`hostinfo | sed -n 's/.*Processor type: \([^ ]*\).*/\1/p'` + os=NeXT + rel=`hostinfo | sed -n 's/.*NeXT Mach \([0-9\.]*\).*/\1/p'` +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 +elif [ -d /usr/apollo -a -d \`node_data ] +then + # probably a Apollo/DOMAIN + os=DomainOS + arch=$ISP + rel=`/usr/apollo/bin/bldt | grep Domain | awk '{ print $4 }' | sed -e 's/,//g'` +fi + +if [ ! "$arch" -a ! "$os" -a ! "$rel" ] +then + arch=`uname -m | sed -e 's/ //g' -e 's/\//-/g'` + os=`uname -s | sed -e 's/\//-/g' -e 's/ //g'` + rel=`uname -r | sed -e 's/(/-/g' -e 's/)//g' -e 's/ //g'` +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/'`;; + + DS/907000) arch=ds90;; + + NILE*) arch=NILE + os=`uname -v`;; + + CRAYT3E|CRAYTS) + os=$arch;; + +esac + +# tweak operating system type and release +node=`uname -n | sed -e 's/\//-/g' -e 's/ //g'` +if [ "$os" = "$node" -a "$arch" = "i386" -a "$rel" = 3.2 -a "`uname -v`" = 2 ] +then + # old versions of SCO UNIX set uname -s the same as uname -n + os=SCO_SV +fi +if [ "$rel" = 4.0 ] +then + case $arch in + 3[34]??|3[34]??,*) + if [ -d /usr/sadm/sysadm/add-ons/WIN-TCP ] + then + os=NCR.MP-RAS.2.x + elif [ -d /usr/sadm/sysadm/add-ons/inet ] + then + os=NCR.MP-RAS.3.x + fi + ;; + esac +fi + +case $os +in + DYNIX-ptx) os=PTX;; + Paragon*) os=Paragon;; + HP-UX) rel=`echo $rel | sed -e 's/^[^.]*\.0*//'`;; + AIX) rela=$rel + rel=`uname -v` + arch=PPC + rel=$rel.$rela + ;; + BSD-386) os=BSD-OS;; + SCO_SV) os=SCO; rel=`uname -X | sed -n 's/Release = 3.2v//p'`;; + UNIX_System_V) if [ "$arch" = "ds90" ] + then + os="UXPDS" + rel=`uname -v | sed -e 's/\(V.*\)L.*/\1/'` + fi;; + ReliantUNIX-?|SINIX-?) os=SINIX;; + DomainOS) case $rel in + 10.4*) rel=10.4;; + esac + ;; + IRIX*) rel=`echo $rel | sed -e 's/-.*$//'`;; + NeXT) mkdir="mkdirs";; +esac + +# get "base part" of operating system release +rroot=`echo $rel | sed -e 's/\.[^.]*$//'` +rbase=`echo $rel | sed -e 's/\..*//'` +if [ "$rroot" = "$rbase" ] +then + rroot=$rel +fi + +# 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 + +if [ ! -n "$Mflag" -a ! -n "$Aflag" ] +then + echo "Configuration: pfx=$pfx, os=$os, rel=$rel, rbase=$rbase, rroot=$rroot, arch=$arch, sfx=$sfx" +fi + +SMROOT=${SMROOT-..} +BUILDTOOLS=${BUILDTOOLS-$SMROOT/devtools} +export SMROOT BUILDTOOLS + +# see if we are in a Build-able directory +if [ ! -f Makefile.m4 -a ! -n "$Aflag" ]; then + echo "Makefile.m4 not found. Build can only be run from a source directory." + exit $EX_UNAVAILABLE +fi + +incdirs="$incdirs -I\${SRCDIR}/include" + +if [ -z "$OBJ_ROOT" ]; then + OBJ_ROOT=${SMROOT} +fi + +if [ "${pfx}x" = "x" ] +then + prefix="" +else + prefix=".$pfx" +fi + +# Print out the architecture (to build up an obj dir path) and exit +if [ -n "$Aflag" ] +then + echo "$os.$rel.$arch$sfx" + exit $EX_OK +fi + +# now try to find a reasonable object directory +if [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rroot.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rroot.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rbase.x.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rbase.x.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rel$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rel$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$rbase.x$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rbase.x$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$rel.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$rel.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$rbase.x.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$rbase.x.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$os$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$os$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$arch$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$arch$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$rel$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$rel$sfx +elif [ -r ${OBJ_ROOT}/obj${prefix}.$sfx ]; then + obj=${OBJ_ROOT}/obj${prefix}.$sfx +fi + +if [ -n "$obj" ] +then + obj=${obj}/${src_dir} +fi + +# Print the directory which would be used for the build and exit +if [ -n "$Mflag" ] +then + if [ ! -n "$obj" ] + then + obj=${OBJ_ROOT}/obj.$os.$rel.$arch$sfx/${src_dir} + fi + echo "$obj" + exit $EX_OK +fi + +# Check if trying to use -f with an existing obj directory +if [ -n "$siteconfig" -a -n "$obj" -a -d "$obj" -a -z "$cflag" ] +then + echo "Can not use Build's -f flag with an existing object tree." + echo "If you wish to change configuration information, use the -c flag to clear" + echo "the existing $obj tree." + exit $EX_USAGE +fi + +# Check if trying to use -Q with an existing obj directory +if [ -n "$pfx" -a -n "$obj" -a -d "$obj" -a -z "$cflag" ] +then + echo "Can not use Build's -Q flag with an existing object tree." + echo "If you wish to change configuration information, use the -c flag to clear" + echo "the existing $obj tree." + exit $EX_USAGE +fi + + +# Clean out the directory before building. +if [ "$cflag" ] +then + if [ -n "$obj" ] + then + echo "Clearing out existing $obj tree" + rm -rf $obj + fi +fi + +# If we didn't detect an existing obj directory, makeup a new obj name. +if [ -z "$obj" ] +then + obj=${OBJ_ROOT}/obj${prefix}.$os.$rel.$arch$sfx/${src_dir} +fi + +# Check if obj directory exists +if [ ! -r "$obj" ] +then + if [ -r $BUILDTOOLS/OS/$os.$rel.$arch$sfx ]; then + oscf=$os.$rel.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rel.$arch ]; then + oscf=$os.$rel.$arch + elif [ -r $BUILDTOOLS/OS/$os.$rroot.$arch$sfx ]; then + oscf=$os.$rroot.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rroot.$arch ]; then + oscf=$os.$rroot.$arch + elif [ -r $BUILDTOOLS/OS/$os.$rbase.x.$arch$sfx ]; then + oscf=$os.$rbase.x.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rbase.x.$arch ]; then + oscf=$os.$rbase.x.$arch + elif [ -r $BUILDTOOLS/OS/$os.$rel$sfx ]; then + oscf=$os.$rel$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rel ]; then + oscf=$os.$rel + elif [ -r $BUILDTOOLS/OS/$os.$rroot$sfx ]; then + oscf=$os.$rroot$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rroot ]; then + oscf=$os.$rroot + elif [ -r $BUILDTOOLS/OS/$os.$rbase.x$sfx ]; then + oscf=$os.$rbase.x$sfx + elif [ -r $BUILDTOOLS/OS/$os.$rbase.x ]; then + oscf=$os.$rbase.x + elif [ -r $BUILDTOOLS/OS/$os.$arch$sfx ]; then + oscf=$os.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$os.$arch ]; then + oscf=$os.$arch + elif [ -r $BUILDTOOLS/OS/$rel.$arch$sfx ]; then + oscf=$rel.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$rel.$arch ]; then + oscf=$rel.$arch + elif [ -r $BUILDTOOLS/OS/$rroot.$arch$sfx ]; then + oscf=$rroot.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$rroot.$arch ]; then + oscf=$rroot.$arch + elif [ -r $BUILDTOOLS/OS/$rbase.x.$arch$sfx ]; then + oscf=$rbase.x.$arch$sfx + elif [ -r $BUILDTOOLS/OS/$rbase.x.$arch ]; then + oscf=$rbase.x.$arch + elif [ -r $BUILDTOOLS/OS/$os$sfx ]; then + oscf=$os$sfx + elif [ -r $BUILDTOOLS/OS/$os ]; then + oscf=$os + elif [ -r $BUILDTOOLS/OS/$arch$sfx ]; then + oscf=$arch$sfx + elif [ -r $BUILDTOOLS/OS/$arch ]; then + oscf=$arch + elif [ -r $BUILDTOOLS/OS/$rel$sfx ]; then + oscf=$rel$sfx + elif [ -r $BUILDTOOLS/OS/$rel ]; then + oscf=$rel + elif [ -r $BUILDTOOLS/OS/$rel$sfx ]; then + oscf=$rel$sfx + else + echo "Cannot determine how to support $arch.$os.$rel" >&2 + exit $EX_UNAVAILABLE + fi + M4=`sh $BUILDTOOLS/bin/find_m4.sh` + ret=$? + if [ $ret -ne 0 ] + then + exit $ret + fi + echo "Using M4=$M4" + export M4 + if [ "$mflag" ] + then + echo "Will run in virgin $obj using $BUILDTOOLS/OS/$oscf" + exit $EX_OK + fi + + echo "Creating $obj using $BUILDTOOLS/OS/$oscf" + ${mkdir} $obj + + # If this is WINNT then compile with relative paths + # (based on REL_SRC_DIR), so we don't need to do any "linking" + if [ ! $os = "WINNT" ] + then + ln="ln -s" + (cd $obj; $ln ${obj_rel_base_dir}/${src_dir}/*.[ch13458] .) + (cd $obj + # This glob doesn't actually glob to something everywhere, + # thus the protective measures. + for i in ${obj_rel_base_dir}/${src_dir}/*.0 + do + if [ -f $i ] + then + $ln $i `basename $i`.dist + fi + done) + if [ -f helpfile ] + then + (cd $obj; $ln ${obj_rel_base_dir}/${src_dir}/helpfile .) + fi + fi + + rm -f $obj/.settings$$ + echo 'divert(-1)' > $obj/.settings$$ + cat $BUILDTOOLS/M4/header.m4 >> $obj/.settings$$ + cat $BUILDTOOLS/OS/$oscf >> $obj/.settings$$ + + if [ $os = "WINNT" ] + then + # Append C: onto pwd's which don't have the preceding // + # so that we can compile on non-network drives. + # (Is there a way to get the real drive letter?) + dir_prefix=`echo $absolute_base_dir | sed 's#\(..\).*#\1#'` + if [ ! $dir_prefix = "//" ] + then + absolute_base_dir="//C$absolute_base_dir" + fi + + # Convert sh's //X to X: drive letters to make make (and cl) happy + obj_rel_base_dir=`echo $absolute_base_dir | sed 's#^//\([a-zA-Z]\)#\1:#'` + cur_dir=`pwd` + cd $obj/.. + absolute_obj_dir=`pwd | sed 's#/#\\\\\\\\#g'` + cd $cur_dir + echo "ifdef(\`bldABS_OBJ_DIR',,define(\`bldABS_OBJ_DIR', \`$absolute_obj_dir'))" >> $obj/.settings$$ + rel_src_dir="$obj_rel_base_dir/$src_dir" + echo "define(\`bldREL_SRC_DIR', \`$rel_src_dir')" >> $obj/.settings$$ + else + cur_dir=`pwd` + cd $obj/.. + absolute_obj_dir=`pwd` + cd $cur_dir + echo "ifdef(\`bldABS_OBJ_DIR',,define(\`bldABS_OBJ_DIR', \`$absolute_obj_dir'))" >> $obj/.settings$$ + rel_src_dir="$obj_rel_base_dir/$src_dir" + echo "define(\`bldREL_SRC_DIR', \`$rel_src_dir')" >> $obj/.settings$$ + fi + + if [ ! -z "$pfx" ] + then + # They gave us a specific prefix, let's try it out. + if [ -f $BUILDTOOLS/Site/$pfx.$oscf$sfx.m4 ] + then + siteconfig=$BUILDTOOLS/Site/$pfx.$oscf$sfx.m4 + elif [ -f $BUILDTOOLS/Site/$pfx.$oscf.m4 ] + then + siteconfig=$BUILDTOOLS/Site/$pfx.$oscf.m4 + fi + if [ -f $BUILDTOOLS/Site/$pfx.config.m4 ] + then + siteconfig="$BUILDTOOLS/Site/$pfx.config.m4 $siteconfig" + fi + elif [ -z "$siteconfig" ] + then + # none specified, use defaults + if [ -f $BUILDTOOLS/Site/site.$oscf$sfx.m4 ] + then + siteconfig=$BUILDTOOLS/Site/site.$oscf$sfx.m4 + elif [ -f $BUILDTOOLS/Site/site.$oscf.m4 ] + then + siteconfig=$BUILDTOOLS/Site/site.$oscf.m4 + fi + if [ -f $BUILDTOOLS/Site/site.config.m4 ] + then + siteconfig="$BUILDTOOLS/Site/site.config.m4 $siteconfig" + fi + if [ -f $BUILDTOOLS/Site/site.post.m4 ] + then + siteconfig="$siteconfig $BUILDTOOLS/Site/site.post.m4" + fi + fi + if [ ! -z "$siteconfig" ] + then + echo "Including $siteconfig" + cat $siteconfig >> $obj/.settings$$ + fi + if [ "$libdirs" ] + then + echo "define(\`confLIBDIRS', confLIBDIRS \`\`$libdirs'')" >> $obj/.settings$$ + fi + if [ "$incdirs" ] + then + echo "define(\`confINCDIRS', \`\`$incdirs'' confINCDIRS)" >> $obj/.settings$$ + fi + echo "define(\`_SRC_PATH_', \`\`$obj_rel_base_dir'')" >> $obj/.settings$$ + echo 'divert(0)dnl' >> $obj/.settings$$ + libdirs=`(cat $obj/.settings$$; echo "_SRIDBIL_= confLIBDIRS" ) | \ + sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ + ${M4} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ + grep "^_SRIDBIL_=" | \ + sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_SRIDBIL_=//"` + libsrch=`(cat $obj/.settings$$; echo "_HCRSBIL_= confLIBSEARCH" ) | \ + sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ + ${M4} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ + grep "^_HCRSBIL_=" | \ + sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_HCRSBIL_=//"` + libpath=`(cat $obj/.settings$$; echo "_HCRSBIL_= confLIBSEARCHPATH" ) | \ + sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' | \ + ${M4} -DconfBUILDTOOLSDIR=$BUILDTOOLS - | \ + grep "^_HCRSBIL_=" | \ + sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e "s/^_HCRSBIL_=//"` + echo 'divert(-1)' >> $obj/.settings$$ + LIBDIRS="$libdirs" LIBSRCH="$libsrch" LIBPATH="$libpath" SITECONFIG="$siteconfig" sh $BUILDTOOLS/bin/configure.sh $sflag $oscf >> $obj/.settings$$ + echo 'divert(0)dnl' >> $obj/.settings$$ + sed -e 's/\(.\)include/\1_include_/g' -e 's/#define/#_define_/g' -e 's/ //g' $obj/.settings$$ | \ + ${M4} -DconfBUILDTOOLSDIR=$BUILDTOOLS - Makefile.m4 | \ + sed -e 's/#_define_/#define/g' -e 's/_include_/include/g' -e 's/ //g' > $obj/Makefile + # That ^M up there was added by quoting it in emacs. + # Make has problems if lines end in ^M^M, but not in ^M apparently + if [ $? -ne 0 -o ! -s $obj/Makefile ] + then + echo "ERROR: ${M4} failed; You may need a newer version of M4, at least as new as System V or GNU" 1>&2 + rm -rf $obj + exit $EX_UNAVAILABLE + fi + rm -f $obj/.settings$$ + 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" >&2 + exit $EX_NOINPUT + fi + echo "Will run in existing $obj using $makefile" + exit $EX_OK +fi + +echo "Making in $obj" +cd $obj +eval exec ${MAKE-make} SENDMAIL_BUILD_FLAGS=\"$SENDMAIL_BUILD_FLAGS\" $makeargs diff --git a/gnu/usr.sbin/sendmail/devtools/bin/configure.sh b/gnu/usr.sbin/sendmail/devtools/bin/configure.sh new file mode 100644 index 00000000000..e0e2f988610 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/bin/configure.sh @@ -0,0 +1,182 @@ +#!/bin/sh + +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: configure.sh,v 8.39 2000/02/26 01:32:07 gshapiro Exp $ + +# +# Special script to autoconfigure for M4 generation of Makefile +# + +os="" +resolver="" +sflag="" +bin_dir=`echo $0 | sed -e 's/\/[^/]*$//'` +if [ ! -d $bin_dir ] +then + bin_dir="." +fi +find_prog=$bin_dir/find_in_path.sh + +while [ ! -z "$1" ] +do + case $1 + in + -s) # skip auto-configure + sflag=1 + shift + ;; + + *) # OS definition + os=$1 + shift + ;; + esac +done + +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 "PUSHDIVERT(0)" +echo "####################################################################" +echo "##### This file is automatically generated -- edit at your own risk" +echo '#####' Built by $user@$host +echo '#####' on `date` using template OS/$os +if [ ! -z "$SITECONFIG" ] +then + echo '#####' including $SITECONFIG +fi +echo '#####' in `pwd` | sed 's/\/tmp_mnt//' +echo "####################################################################" +echo "" +echo "POPDIVERT" +echo "define(\`__HOST__', \`$host')dnl" +echo "ifdef(\`confMAPDEF',, \`define(\`confMAPDEF', \`')')dnl" +echo "ifdef(\`confLIBS',, \`define(\`confLIBS', \`')')dnl" + +LIBDIRS="$LIBDIRS $LIBPATH" +libs="" +mapdef="" +for l in $LIBSRCH +do + for p in `echo $LIBDIRS | sed -e 's/:/ /g' -e 's/^-L//g' -e 's/ -L/ /g'` + do + if [ "x$p" = "x" ] + then + p = "." + fi + if [ -f $p/lib$l.a -o -f $p/lib$l.so ] + then + case $l + in + db) + mapdef="$mapdef -DNEWDB" + ;; + bind|resolv) + if [ -n "$resolver" ] + then + continue + else + resolver=$l + fi + ;; + 44bsd) + if [ "x$resolver" != "xresolv" ] + then + continue + fi + ;; + esac + libs="$libs -l$l" + break + fi + done +done + +for p in `echo $PATH | sed 's/:/ /g'` +do + pbase=`echo $p | sed -e 's,/bin,,'` + if [ "x$p" = "x" ] + then + p="." + fi + if [ -f $p/mkdep ] + then + echo "ifdef(\`confDEPEND_TYPE',, \`define(\`confDEPEND_TYPE', \`BSD')')dnl" + fi +done + +if [ -z "$sflag" ] +then + echo "define(\`confMAPDEF', \`$mapdef' confMAPDEF)dnl" + echo "define(\`confLIBS', \`$libs' confLIBS)dnl" +fi + +if [ ! -z "`sh $find_prog ranlib`" ] +then + echo "define(\`confRANLIB', \`ranlib')dnl" +fi + +roff_progs="groff nroff" +for roff_prog in $roff_progs +do + if [ ! -z "`sh $find_prog $roff_prog`" ] + then + found_roff=$roff_prog + break; + fi +done + +case $found_roff +in + groff) + echo "ifdef(\`confNROFF',,define(\`confNROFF', \`$found_roff -Tascii'))dnl" + ;; + nroff) + echo "ifdef(\`confNROFF',,define(\`confNROFF', \`$found_roff'))dnl" + ;; + *) + echo "ifdef(\`confNROFF',,define(\`confNO_MAN_BUILD'))dnl" + ;; +esac diff --git a/gnu/usr.sbin/sendmail/devtools/bin/find_in_path.sh b/gnu/usr.sbin/sendmail/devtools/bin/find_in_path.sh new file mode 100644 index 00000000000..f0affd2ec94 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/bin/find_in_path.sh @@ -0,0 +1,19 @@ +#! /bin/sh +# +# $Sendmail: find_in_path.sh,v 8.2 1999/09/23 20:42:22 gshapiro Exp $ +# +EX_OK=0 +EX_NOT_FOUND=1 + +ifs="$IFS"; IFS="${IFS}:" +for dir in $PATH /usr/5bin /usr/ccs/bin +do + if [ -r $dir/$1 ] + then + echo $dir/$1 + exit $EX_OK + fi +done +IFS=$ifs + +exit $EX_NOT_FOUND diff --git a/gnu/usr.sbin/sendmail/devtools/bin/find_m4.sh b/gnu/usr.sbin/sendmail/devtools/bin/find_m4.sh new file mode 100644 index 00000000000..684b45a29f5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/bin/find_m4.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: find_m4.sh,v 8.7 1999/02/07 07:25:58 gshapiro Exp $ +# + +# Try to find a working M4 program. +# If $M4 is already set, we use it, otherwise we prefer GNU m4. + +EX_UNAVAILABLE=69 + +test="ifdef(\`pushdef', \`', +\`errprint(\`You need a newer version of M4, at least as new as System V or GNU') +include(NoSuchFile)') +define(\`BadNumber', \`10') +ifdef(\`BadNumber', \`', \`errprint(\`This version of m4 is broken')')" + +if [ "$M4" ] +then + err=`(echo "$test" | $M4) 2>&1 >/dev/null` + code=$? +else + firstfound= + ifs="$IFS"; IFS="${IFS}:" + for m4 in gm4 gnum4 pdm4 m4 + do + for dir in $PATH /usr/5bin /usr/ccs/bin + do + [ -z "$dir" ] && dir=. + if [ -f $dir/$m4 ] + then + err=`(echo "$test" | $dir/$m4) 2>&1 >/dev/null` + ret=$? + if [ $ret -eq 0 -a "X$err" = "X" ] + then + M4=$dir/$m4 + code=0 + break + else + case "$firstfound:$err" in + :*version\ of*) + firstfound=$dir/$m4 + firsterr="$err" + firstcode=$ret + ;; + esac + fi + fi + done + [ "$M4" ] && break + done + IFS="$ifs" + if [ ! "$M4" ] + then + if [ "$firstfound" ] + then + M4=$firstfound + err="$firsterr" + code=$firstcode + else + echo "ERROR: Can not locate an M4 program" >&2 + exit $EX_UNAVAILABLE + fi + fi +fi +if [ $code -ne 0 ] +then + echo "ERROR: Using M4=$M4: $err" | grep -v NoSuchFile >&2 + exit $EX_UNAVAILABLE +elif [ "X$err" != "X" ] +then + echo "WARNING: $err" >&2 +fi +echo $M4 +exit 0 + diff --git a/gnu/usr.sbin/sendmail/devtools/bin/install.sh b/gnu/usr.sbin/sendmail/devtools/bin/install.sh new file mode 100644 index 00000000000..49ad7ead40d --- /dev/null +++ b/gnu/usr.sbin/sendmail/devtools/bin/install.sh @@ -0,0 +1,133 @@ +#!/bin/sh + +# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: install.sh,v 8.13 1999/02/22 21:34:38 gshapiro Exp $ + +# Set default program +program=mv +owner="" +group="" +mode="" +strip="" + +# chown program -- ultrix keeps it in /etc/chown and /usr/etc/chown +if [ -f /etc/chown ] +then + chown=/etc/chown +elif [ -f /usr/etc/chown ] +then + chown=/usr/etc/chown +else + chown=chown +fi + +# Check arguments +while [ ! -z "$1" ] +do + case $1 + in + -o) owner=$2 + shift; shift + ;; + + -g) group=$2 + shift; shift + ;; + + -m) mode=$2 + shift; shift + ;; + + -c) program=cp + shift + ;; + + -s) strip="strip" + shift + ;; + + -*) echo $0: Unknown option $1 + exit 1 + ;; + + *) break + ;; + esac +done + +# Check source file +if [ -z "$1" ] +then + echo "Source file required" >&2 + exit 1 +elif [ -f $1 -o $1 = /dev/null ] +then + src=$1 +else + echo "Source file must be a regular file or /dev/null" >&2 + exit 1 +fi + +# Check destination +if [ -z "$2" ] +then + echo "Destination required" >&2 + exit 1 +elif [ -d $2 ] +then + dst=$2/$src +else + dst=$2 +fi + +# Do install operation +$program $src $dst +if [ $? != 0 ] +then + exit 1 +fi + +# Strip if requested +if [ ! -z "$strip" ] +then + $strip $dst +fi + +# Change owner if requested +if [ ! -z "$owner" ] +then + $chown $owner $dst + if [ $? != 0 ] + then + exit 1 + fi +fi + +# Change group if requested +if [ ! -z "$group" ] +then + chgrp $group $dst + if [ $? != 0 ] + then + exit 1 + fi +fi + +# Change mode if requested +if [ ! -z "$mode" ] +then + chmod $mode $dst + if [ $? != 0 ] + then + exit 1 + fi +fi + +exit 0 diff --git a/gnu/usr.sbin/sendmail/doc/op/Makefile b/gnu/usr.sbin/sendmail/doc/op/Makefile new file mode 100644 index 00000000000..cbe4a58b5b8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/doc/op/Makefile @@ -0,0 +1,23 @@ +# $Sendmail: Makefile,v 8.7 2000/02/01 08:21:47 gshapiro Exp $ + +DIR= smm/08.sendmailop +SRCS= op.me +OBJS= op.ps +MACROS= -me +ROFF_CMD= groff +PIC_CMD= pic +EQN_CMD= eqn +PIC= ${PIC_CMD} -C +EQN= ${EQN_CMD} -C -Tps +ROFF= ${ROFF_CMD} -Tps -mps ${MACROS} + +all: ${OBJS} + +${OBJS}: ${SRCS} + rm -f $@ + ${PIC} ${SRCS} | ${EQN} | ${ROFF} > $@ + +clean: + rm -f ${OBJS} + +install: ${OBJS} diff --git a/gnu/usr.sbin/sendmail/doc/op/op.me b/gnu/usr.sbin/sendmail/doc/op/op.me new file mode 100644 index 00000000000..16c0935d35c --- /dev/null +++ b/gnu/usr.sbin/sendmail/doc/op/op.me @@ -0,0 +1,9155 @@ +.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: op.me,v 8.310 2000/02/01 22:19:12 gshapiro Exp $ +.\" +.\" 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\u\s-6TM\s0\d +.sz 12 +.sp +.b "INSTALLATION AND OPERATION GUIDE" +.(f +.b DISCLAIMER: +This documentation is under modification. +.)f +.sz 10 +.sp +.r +Eric Allman +Sendmail, Inc. +eric@Sendmail.COM +.sp +.de Ve +Version \\$2 +.. +.Ve $Revision: 1.1.1.1 $ +.rm Ve +.sp +For Sendmail Version 8.10 +.)l +.(f +Sendmail is a trademark of Sendmail, Inc. +.)f +.sp 2 +.pp +.i Sendmail \u\s-2TM\s0\d +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 file +incrementally. +.pp +.i Sendmail +is based on +RFC821 (Simple Mail Transport Protocol), +RFC822 (Internet Mail Headers Format), +RFC974 (MX routing), +RFC1123 (Internet Host Requirements), +RFC2045 (MIME), +RFC1869 (SMTP Service Extensions), +RFC1652 (SMTP 8BITMIME Extension), +RFC1870 (SMTP SIZE Extension), +RFC1891 (SMTP Delivery Status Notifications), +RFC1892 (Multipart/Report), +RFC1893 (Mail System Status Codes), +RFC1894 (Delivery Status Notifications), +RFC1985 (SMTP Service Extension for Remote Message Queue Starting), +RFC2033 (Local Message Transmission Protocol), +RFC2034 (SMTP Service Extension for Returning Enhanced Error Codes), +RFC2476 (Message Submission), +and +RFC2554 (SMTP Service Extension for Authentication). +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. +The appendixes give a brief +but detailed explanation of a number of features +not described in the rest of the paper. +.bp +.rs +.sp |4i +.ce 2 +This page intentionally left blank; +replace it with a blank sheet for double-sided output. +.bp 7 +.sh 1 "BASIC INSTALLATION" +.pp +There are two basic steps to installing +.i sendmail . +First, you have to compile and install the binary. +If +.i sendmail +has already been ported to your operating system +that should be simple. +Second, you must build a run-time configuration file. +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 file can be quite complex, +a configuration can usually be built +using an M4-based configuration language. +.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 sendmail +subdirectory. +To compile sendmail, +.q cd +into the +.i sendmail +directory and type +.(b +\&./Build +.)b +This will leave the binary in an appropriately named subdirectory, +e.g., +obj.BSD-OS.2.1.i386. +It works for multiple object versions +compiled out of the same directory. +.sh 3 "Tweaking the Build Invocation" +.pp +You can give parameters on the +.i Build +command. +In most cases these are only used when the +.i obj.* +directory is first created. +These commands include: +.nr ii 0.5i +.ip "\-L \fIlibdirs\fP" +A list of directories to search for libraries. +.ip "\-I \fIincdirs\fP" +A list of directories to search for include files. +.ip "\-E \fIenvar\fP=\fIvalue\fP" +Set an environment variable to an indicated +.i value +before compiling. +.ip "\-c" +Create a new +.i obj.* +tree before running. +.ip "\-f \fIsiteconfig\fP" +Read the indicated site configuration file. +If this parameter is not specified, +.i Build +includes +.i all +of the files +.i $BUILDTOOLS/Site/site.$oscf.m4 +and +.i $BUILDTOOLS/Site/site.config.m4 , +where $BUILDTOOLS is normally +.i \&../devtools +and $oscf is the same name as used on the +.i obj.* +directory. +See below for a description of the site configuration file. +.ip "\-S" +Skip auto-configuration. +.i Build +will avoid auto-detecting libraries if this is set. +All libraries and map definitions must be specified +in the site configuration file. +.lp +Any other parameters are passed to the +.i make +program. +.sh 3 "Creating a Site Configuration File" +.\"XXX +.pp +(This section is not yet complete. +For now, see the file devtools/README for details.) +.sh 3 "Tweaking the Makefile" +.pp +.\" .b "XXX This should all be in the Site Configuration File section." +.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 Berkeley DB package. +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 +.sm NDBM ; +if you do, +old alias 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 Build +is the best approach on most systems: +.(b +\&./Build +.)b +This will use +.i uname (1) +to create a custom Makefile for your environment. +.pp +If you are installing in the standard places, +you should be able to install using +.(b +\&./Build 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 "generic-solaris2.mc" +as a general description of an SMTP-connected host +running Solaris 2.x. +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.Berkeley.EDU.m4 +is our description for hosts in the CS.Berkeley.EDU subdomain. +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/mail/local-host-names 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 UUCP connectivity information. +This directory has been supplanted by the mailertable feature; +any new configurations should use that feature to do UUCP +(and other) routing. +.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 +and features you want enabled site-wide: +for example, Berkeley's domain definition +defines relays for +BitNET +and UUCP. +These are specific to Berkeley, +and should be fully-qualified 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.Berkeley.EDU +is the Computer Science subdomain, +EECS.Berkeley.EDU +is the Electrical Engineering and Computer Sciences subdomain, +and +S2K.Berkeley.EDU +is the Sequoia 2000 subdomain. +You will probably have to add an entry to 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, /etc/mail, /usr/etc, /lib, and /usr/lib. +.)f +.sh 3 "/etc/mail/sendmail.cf" +.pp +This is the configuration file for +.i sendmail \**. +.(f +\**Actually, the pathname varies depending on the operating system; +/etc/mail 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 . +If you want to move this file, +add -D_PATH_SENDMAILCF=\e"/file/name\e" +to the flags passed to the C compiler. +Moving this file is not recommended: +other programs and scripts know of this location. +.)f +This is the only non-library file name 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 "/usr/\*(SB/hoststat" +.pp +The +.i hoststat +command should just be a link to +.i sendmail , +in a fashion similar to +.i newaliases . +This command lists the status of the last mail transaction +with all remote hosts. The +.b \-v +flag will prevent the status display from being truncated. +It functions only when the +.b HostStatusDirectory +option is set. +.sh 3 "/usr/\*(SB/purgestat" +.pp +This command is also a link to +.i sendmail . +It flushes all information that is stored in the +.b HostStatusDirectory +tree. +.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. +To use multiple queues, +supply a value ending with an asterisk. +For example, +.i /var/spool/mqueue/q* +will use all of the directories or symbolic links to directories +beginning with `q' in +.i /var/spool/mqueue +as queue directories. +Do not change the queue directory structure +while sendmail is running. +.pp +If these directories have subdirectories or symbolic links to directories +named `qf', `df', and `xf', then these will be used for the different +queue file types. +That is, the data files are stored in the `df' subdirectory, +the transcript files are stored in the `xf' subdirectory, and +all others are stored in the `qf' subdirectory. +.sh 3 "/var/spool/mqueue/.hoststat" +.pp +This is a typical value for the +.b HostStatusDirectory +option, +containing one file per host +that this sendmail has chatted with recently. +It is normally a subdirectory of +.i mqueue . +.sh 3 "/etc/mail/aliases*" +.pp +The system aliases are held in +.q /etc/mail/aliases . +A sample is given in +.q sendmail/aliases +which includes some aliases which +.i must +be defined: +.(b +cp lib/aliases /etc/mail/aliases +.i "edit /etc/mail/aliases" +.)b +You should extend this file with any aliases that are apropos to your system. +.pp +Normally +.i sendmail +looks at a database version of the files, +stored either in +.q /etc/mail/aliases.dir +and +.q /etc/mail/aliases.pag +or +.q /etc/mail/aliases.db +depending on which database package you are using. +The actual path of this file +is defined in the +.b AliasFile +option of the +.i sendmail.cf +file. +.sh 3 "/etc/rc or /etc/init.d/sendmail" +.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 +on a BSD-base system, +or on a System-V-based system +in one of the startup files, typically +.q /etc/init.d/sendmail : +.(b +if [ \-f /usr/\*(SD/sendmail \-a \-f /etc/mail/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 script which does this clean up. +.(z +.hl +#!/bin/sh +# remove zero length qf files +for qffile in qf* +do + if [ \-r $qffile ] + then + if [ ! \-s $qffile ] + then + echo \-n " " > /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 " " > /dev/console + mv $tffile $qffile + else + if [ \-f $tffile ] + then + echo \-n " " > /dev/console + rm \-f $tffile + fi + 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 " " > /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 + if [ \-f $xffile ] + then + echo \-n " " > /dev/console + fi +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 "/etc/mail/helpfile" +.pp +This is the help file used by the SMTP +.b HELP +command. +It should be copied from +.q sendmail/helpfile : +.(b +cp sendmail/helpfile /etc/mail/helpfile +.)b +The actual path of this file +is defined in the +.b HelpFile +option of the +.i sendmail.cf +file. +.sh 3 "/etc/mail/statistics" +.pp +If you wish to collect statistics +about your mail traffic, +you should create the file +.q /etc/mail/statistics : +.(b +cp /dev/null /etc/mail/statistics +chmod 644 /etc/mail/statistics +.)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. +When using multiple queues, +a separate process will be created to +run each of the queues +unless the queue run is initiated by a user +with the verbose flag. +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 "Disk Based Connection Information" +.pp +.i Sendmail +stores a large amount of information about each remote system it +has connected to in memory. It is now possible to preserve some +of this information on disk as well, by using the +.b HostStatusDirectory +option, so that it may be shared between several invocations of +.i sendmail . +This allows mail to be queued immediately or skipped during a queue run if +there has been a recent failure in connecting to a remote machine. +.pp +Additionally enabling +.b SingleThreadDelivery +has the added effect of single-threading mail delivery to a destination. +This can be quite helpful +if the remote machine is running an SMTP server that is easily overloaded +or cannot accept more than a single connection at a time, +but can cause some messages to be punted to a future queue run. +It also applies to +.i all +hosts, so setting this because you have one machine on site +that runs some software that is easily overrun +can cause mail to other hosts to be slowed down. +If this option is set, +you probably want to set the +.b MinQueueAge +option as well and run the queue fairly frequently; +this way jobs that are skipped because another +.i sendmail +is talking to the same host will be tried again quickly +rather than being delayed for a long time. +.pp +The disk based host information is stored in a subdirectory of the +.b mqueue +directory called +.b \&.hoststat \**. +.(f +\**This is the usual value of the +.b HostStatusDirectory +option; +it can, of course, go anywhere you like in your filesystem. +.)f +Removing this directory and its subdirectories has an effect similar to +the +.i purgestat +command and is completely safe. +The information in these directories can +be perused with the +.i hoststat +command, which will indicate the host name, the last access, and the +status of that access. +An asterisk in the left most column indicates that a +.i sendmail +process currently has the host locked for mail delivery. +.pp +The disk based connection information is treated the same way as memory based +connection information for the purpose of timeouts. +By default, information about host failures is valid for 30 minutes. +This can be adjusted with +the +.b Timeout.hoststatus +option. +.pp +The connection information stored on disk may be purged at any time +with the +.i purgestat +command or by invoking sendmail with the +.b \-bH +switch. +The connection information may be viewed with the +.i hoststat +command or by invoking sendmail with the +.b \-bh +switch. +.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\**. +.(f +\**HP-UX 10 has service switch support, +but since the APIs are apparently not available in the libraries +.i sendmail +does not use the native service switch in this release. +.)f +.pp +If the underlying operating system does not support a service switch +(e.g., SunOS 4.X, 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 +After recipient addresses are read from the SMTP connection +or command line +they are parsed by ruleset 0, +which must resolve to a +{\c +.i mailer , +.i host , +.i address } +triple. +If the flags selected by the +.i mailer +include the +.b A +(aliasable) flag, +the +.i address +part of the triple is looked up as the key +(i.e., the left hand side) +into the alias database. +If there is a match, the address is deleted from the send queue +and all addresses on the right hand side of the alias +are added in place of the alias that was found. +This is a recursive operation, +so aliases found in the right hand side of the alias +are similarly expanded. +.pp +The alias database exists in two forms. +One is a text form, +maintained in the file +.i /etc/mail/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 or by putting a backslash directly before +the newline. +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 does not work. +.)f +or the Berkeley DB library. +This form is in the file +.i /etc/mail/aliases.db +(if using NEWDB) +or +.i /etc/mail/aliases.dir +and +.i /etc/mail/aliases.pag +(if using NDBM). +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 +O AliasFile=switch: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 +O AliasFile=/etc/mail/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/mail/aliases, +then in the NIS+ database. +.pp +You can also use +.sm NIS -based +alias files. +For example, the specification: +.(b +O AliasFile=/etc/mail/aliases +O AliasFile=nis:mail.aliases@my.nis.domain +.)b +will first search the /etc/mail/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 +O AliasFile=nis:\-N mail.aliases@my.nis.domain +.)b +will search the appropriate NIS map and always include null bytes in the key. +Also: +.(b +O AliasFile=nis:\-f mail.aliases@my.nis.domain +.)b +will prevent sendmail from downcasing the key before the alias lookup. +.sh 3 "Rebuilding the alias database" +.pp +The +.i hash +or +.i 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 ForwardPath +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 officially 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. +.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. +Note that the RFC states +a client should wait at least 30 seconds for a response. +The default Timeout.ident is 5 seconds +as many sites have adopted the practice of dropping IDENT queries. +This has lead to delays processing mail. +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 -OTimeout.queuereturn=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/mail/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 2 "Persistent Host Status Information" +.pp +When +.b HostStatusDirectory +is enabled, +information about the status of hosts is maintained on disk +and can thus be shared between different instantiations of +.i sendmail . +The status of the last connection with each remote host +may be viewed with the command: +.(b +sendmail \-bh +.)b +This information may be flushed with the command: +.(b +sendmail \-bH +.)b +Flushing the information prevents new +.i sendmail +processes from loading it, +but does not prevent existing processes from using the status information +that they already have. +.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 iconnect +The same as +.i connect, +except it applies only to the initial attempt to connect to a host +for a given message +[0, unspecified]. +The concept is that this should be very short (a few seconds); +hosts that are well connected and responsive will thus be serviced immediately. +Hosts that are slow will not hold up other deliveries in the initial +delivery attempt. +.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\(dd +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\(dd +In server SMTP, +the time to wait for another command. +[1h, 5m]. +.ip ident\(dd +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 +.ip fileopen\(dd +The timeout for opening .forward and :include: files [60s, none]. +.ip control\(dd +The timeout for a complete control socket transaction to complete [2m, none]. +.ip hoststatus\(dd +How long status information about a host +(e.g., host down) +will be cached before it is considered stale +[30m, unspecified]. +.ip resolver.retrans +The resolver's +retransmission time interval +(in seconds) +[varies]. +Sets both +.i Timeout.resolver.retrans.first +and +.i Timeout.resolver.retrans.normal . +.ip resolver.retrans.first +The resolver's +retransmission time interval +(in seconds) +for the first attempt to +deliver a message +[varies]. +.ip resolver.retrans.normal +The resolver's +retransmission time interval +(in seconds) +for all resolver lookups +except the first delivery attempt +[varies]. +.ip resolver.retry +The number of times +to retransmit a resolver query. +Sets both +.i Timeout.resolver.retry.first +and +.i Timeout.resolver.retry.normal +[varies]. +.ip resolver.retry.first +The number of times +to retransmit a resolver query +for the first attempt +to deliver a message +[varies]. +.ip resolver.retry.normal +The number of times +to retransmit a resolver query +for all resolver lookups + except the first delivery attempt +[varies]. +.lp +For compatibility with old configuration files, +if no +.i suboption +is specified, +all the timeouts marked with a dagger (\(dg) are set to the indicated value. +All but those marked with a double dagger (\(dd) apply to client SMTP. +.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 +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. +The value "now" can be used for +-O Timeout.queuereturn +to return entries immediately during a queue run, +e.g., to bounce messages independent of their time in the queue. +.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 +Minimal logging. +.ip 1 +Serious system failures and potential security problems. +.ip 2 +Lost communications (network problems) and protocol failures. +.ip 3 +Other serious failures, malformed addresses, transient forward/include +errors, connection timeouts. +.ip 4 +Minor failures, out of date alias databases, connection rejections +via check_ rulesets. +.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 11 +NIS errors and end of job processing. +.ip 12 +Logs all SMTP connections. +.ip 13 +Log bad user shells, files with improper permissions, and other +questionable situations. +.ip 14 +Logs refused connections. +.ip 15 +Log all incoming and outgoing SMTP commands. +.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. +In many cases +.i sendmail +does careful checking of the modes +of files and directories +to avoid accidental compromise; +if you want to make it possible to have group-writable support files +you may need to use the +.b DontBlameSendmail +option to turn off some of these checks. +.sh 3 "To suid or not to suid?" +.pp +.i Sendmail +is normally installed +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 (root); +if so, +it resets the userid and groupid to a default +(set by the +.b U= +equate in the mailer line; +if that is not set, the +.b DefaultUser +option is used). +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. +Note however that +.i sendmail +must run as root or the trusted user in order to create the SMTP listener +socket. +.pp +A middle ground is to make +.i sendmail +setuid to root, +but set the +.b RunAsUser +option. +This causes +.i sendmail +to become the indicated user as soon as it has done the startup +that requires root privileges +(primarily, opening the +.sm SMTP +socket). +If you use +.b RunAsUser , +the queue directory +(normally +.i /var/spool/mqueue ) +should be owned by that user, +and all files and databases +(including user +.i \&.forward +files, +alias files, +:include: files, +and external databases) +must be readable by that user. +Also, since sendmail will not be able to change it's uid, +delivery to programs or files will be marked as unsafe, +e.g., undeliverable, +in +.i \&.forward , +aliases, +and :include: files. +Administrators can override this by setting the +.b DontBlameSendmail +option to the setting +.b NonRootSafeAddr . +.b RunAsUser +is probably best suited for firewall configurations +that don't have regular user logins. +.sh 3 "Turning off security checks" +.pp +.i Sendmail +is very particular about the modes of files that it reads or writes. +For example, by default it will refuse to read most files +that are group writable +on the grounds that they might have been tampered with +by someone other than the owner; +it will even refuse to read files in group writable directories. +.pp +If you are +.i quite +sure that your configuration is safe and you want +.i sendmail +to avoid these security checks, +you can turn off certain checks using the +.b DontBlameSendmail +option. +This option takes one or more names that disable checks. +In the descriptions that follow, +.q "unsafe directory" +means a directory that is writable by anyone other than the owner. +The values are: +.nr ii 0.5i +.ip Safe +No special handling. +.ip AssumeSafeChown +Assume that the +.i chown +system call is restricted to root. +Since some versions of Unix permit regular users +to give away their files to other users on some filesystems, +.i sendmail +often cannot assume that a given file was created by the owner, +particularly when it is in a writable directory. +You can set this flag if you know that file giveaway is restricted +on your system. +.ip ClassFileInUnsafeDirPath +When reading class files (using the +.b F +line in the configuration file), +allow files that are in unsafe directories. +.ip DontWarnForwardFileInUnsafeDirPath +Prevent logging of +unsafe directory path warnings +for non-existent forward files. +.ip ErrorHeaderInUnsafeDirPath +Allow the file named in the +.b ErrorHeader +option to be in an unsafe directory. +.ip GroupWritableDirPathSafe +Change the definition of +.q "unsafe directory" +to consider group-writable directories to be safe. +World-writable directories are always unsafe. +.ip GroupWritableForwardFileSafe +Accept group-writable +.i \&.forward +files. +.ip GroupWritableIncludeFileSafe +Accept group-writable +.i :include: +files. +.ip GroupWritableAliasFile +Allow group-writable alias files. +.ip HelpFileInUnsafeDirPath +Allow the file named in the +.b HelpFile +option to be in an unsafe directory. +.ip WorldWritableAliasFile +Accept world-writable alias files. +.ip ForwardFileInGroupWritableDirPath +Allow +.i \&.forward +files in group writable directories. +.ip IncludeFileInGroupWritableDirPath +Allow +.i :include: +files in group writable directories. +.ip ForwardFileInUnsafeDirPath +Allow +.i \&.forward +files in unsafe directories. +.ip IncludeFileInUnsafeDirPath +Allow +.i :include: +files in unsafe directories. +.ip ForwardFileInUnsafeDirPathSafe +Allow a +.i \&.forward +file that is in an unsafe directory to include references +to program and files. +.ip IncludeFileInUnsafeDirPathSafe +Allow a +.i :include: +file that is in an unsafe directory to include references +to program and files. +.ip MapInUnsafeDirPath +Allow maps (e.g., +.i hash , +.i btree , +and +.i dbm +files) +in unsafe directories. +.ip LinkedAliasFileInWritableDir +Allow an alias file that is a link in a writable directory. +.ip LinkedClassFileInWritableDir +Allow class files that are links in writable directories. +.ip LinkedForwardFileInWritableDir +Allow +.i \&.forward +files that are links in writable directories. +.ip LinkedIncludeFileInWritableDir +Allow +.i :include: +files that are links in writable directories. +.ip LinkedMapInWritableDir +Allow map files that are links in writable directories. +.ip LinkedServiceSwitchFileInWritableDir +Allow the service switch file to be a link +even if the directory is writable. +.ip FileDeliveryToHardLink +Allow delivery to files that are hard links. +.ip FileDeliveryToSymLink +Allow delivery to files that are symbolic links. +.ip RunProgramInUnsafeDirPath +Go ahead and run programs that are in writable directories. +.ip RunWritableProgram +Go ahead and run programs that are group- or world-writable. +.ip WriteMapToHardLink +Allow writes to maps that are hard links. +.ip WriteMapToSymLink +Allow writes to maps that are symbolic links. +.ip WriteStatsToHardLink +Allow the status file to be a hard link. +.ip WriteStatsToSymLink +Allow the status file to be a symbolic link. +.ip TrustStickyBit +Allow group or world writable directories +if the sticky bit is set on the directory. +Do not set this on systems which do not honor +the sticky bit on directories. +.ip NonRootSafeAddr +Do not mark file and program deliveries as unsafe +if sendmail is not running with root privileges. +.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 RSET +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/mail/service.switch , +which should be created. +.i Sendmail +only uses two entries: +.b hosts +and +.b aliases , +although system routines may use other services +(notably the +.b passwd +service for user name lookups by +.i getpwname ). +.pp +However, some systems (such as SunOS 4.X) +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 4.X) +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. +Note that you must use the +forwardfileinunsafedirpath and +forwardfileinunsafedirpathsafe +flags with the DontBlameSendmail option +to allow forward files in a world +writable directory. +This might also be used as a +denial of service +attack (users could create forward files for other users); +a better approach might be to create +/var/forward +mode 755 +and create empty files for each user, +owned by that user, +mode 644. +If you do this, you don't have to set the DontBlameSendmail options +indicated above. +.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.6. +.sh 2 "Send to Me Too" +.pp +Beginning with version 8.10, +.i sendmail +includes by default the (envelope) sender in any list expansions. +For example, if +.q matt +sends to a list that contains +.q matt +as one of the members he will get a copy of the message. +If the +.b MeToo +option is set to +.sm FALSE +(in the configuration file or via the command line), +this behavior is changed, i.e., +the (envelope) sender is excluded in list expansions. +.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 appends to 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 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 its numeric IP address +without calling the name server +and replaces it with its 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 expands everything after the ruleset name +to the end of the replacement string +and then passes that as the initial input to the ruleset. +Recursive calls are allowed. +For example, +.(b +$>0 $>3 $1 +.)b +expands $1, passes that to ruleset 3, and then passes the result +of ruleset 3 to ruleset 0. +.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 mailer specified has the +.b F=@ +flag specified +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 six rewriting sets +that have specific semantics. +Five 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, address}" +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. +.pp +In addition, +ruleset 5 is applied to all local addresses +(specifically, those that resolve to a mailer with the `F=5' +flag set) +that do not have aliases. +This allows a last minute hook for local names. +.sh 3 "Ruleset hooks" +.pp +A few extra rulesets are defined as +.q hooks +that can be defined to get special features. +They are all named rulesets. +The +.q check_* +forms all give accept/reject status; +falling off the end or returning normally is an accept, +and resolving to +.b $#error +is a reject. +Many of these can also resolve to the special mailer name +.b $#discard ; +this accepts the message as though it were successful +but then discards it without delivery. +Note, +this mailer can not be chosen as a mailer in ruleset 0. +.sh 4 "check_relay" +.pp +The +.i check_relay +ruleset is called after a connection is accepted. +It is passed +.(b +client.host.name $| client.host.address +.)b +where +.b $| +is a metacharacter separating the two parts. +This ruleset can reject connections from various locations. +.sh 4 "check_mail" +.pp +The +.i check_mail +ruleset is passed the user name parameter of the +.sm "SMTP MAIL" +command. +It can accept or reject the address. +.sh 4 "check_rcpt" +.pp +The +.i check_rcpt +ruleset is passed the user name parameter of the +.sm "SMTP RCPT" +command. +It can accept or reject the address. +.sh 4 "check_compat" +.pp +The +.i check_compat +ruleset is passed +.(b +sender-address $| recipient-address +.)b +where +.b $| +is a metacharacter separating the addresses. +It can accept or reject mail transfer between these two addresses +much like the +.i checkcompat() +function. +.sh 4 "check_eoh" +.pp +The +.i check_eoh +ruleset is passed +.(b +number-of-headers $| size-of-headers +.)b +where +.b $| +is a metacharacter separating the numbers. +These numbers can be used for size comparisons with the +.b arith +map. +The ruleset is triggered after +all of the headers have been read. +It can be used to correlate information gathered +from those headers using the +.b macro +storage map. +One possible use is to check for a missing header. +For example: +.(b +.ta 1.5i +Kstorage macro +HMessage-Id: $>CheckMessageId + +SCheckMessageId +# Record the presence of the header +R$* $: $(storage {MessageIdCheck} $@ OK $) $1 +R< $+ @ $+ > $@ OK +R$* $#error $: 553 Header Error + +Scheck_eoh +# Check the macro +R$* $: < $&{MessageIdCheck} > +# Clear the macro for the next message +R$* $: $(storage {MessageIdCheck} $) $1 +# Has a Message-Id: header +R< $+ > $@ OK +# Allow missing Message-Id: from local mail +R$* $: < $&{client_name} > +R< > $@ OK +R< $=w > $@ OK +# Otherwise, reject the mail +R$* $#error $: 553 Header Error +.)b +Keep in mind the Message-Id: header is not a required header and +is not a guaranteed spam indicator. +This ruleset is an example and +should probably not be used in production. +.sh 4 "check_etrn" +.pp +The +.i check_etrn +ruleset is passed the parameter of the +.sm "SMTP ETRN" +command. +It can accept or reject the command. +.sh 4 "check_expn" +.pp +The +.i check_expn +ruleset is passed the user name parameter of the +.sm "SMTP EXPN" +command. +It can accept or reject the address. +.sh 4 "check_vrfy" +.pp +The +.i check_vrfy +ruleset is passed the user name parameter of the +.sm "SMTP VRFY" +command. +It can accept or reject the command. +.sh 4 "trust_auth" +.pp +The +.i trust_auth +ruleset is passed the AUTH= parameter of the +.sm "SMTP MAIL" +command. +It is used to determine whether this value should be +trusted. In order to make this decision, the ruleset +may make use of the various +.b ${auth_*} +macros. +If the ruleset does resolve to the +.q error +mailer the AUTH= parameter is not trusted and hence +not passed on to the next relay. +.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 if not delivering via a named socket; +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 an 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 non-null, +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 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. +.ip ${auth_authen} +The client's authentication credentials as determined by authentication +(only set if successful). +.ip ${auth_author} +The authorization identity, i.e. the AUTH= parameter of the +.sm "SMTP MAIL" +command if supplied. +.ip ${auth_type} +The mechanism used for authentication +(only set if successful). +.ip ${bodytype} +The message body type +(7BIT or 8BITMIME), +as determined from the envelope. +.ip ${client_addr} +The IP address of the SMTP client. +Defined in the SMTP server only. +.ip ${client_name} +The host name of the SMTP client. +This may be the client's bracketed IP address +in the form [ nnn.nnn.nnn.nnn ] if the client's +IP address is not resolvable, or if the resolved +name doesn't match ${client_name}. +Defined in the SMTP server only. +.ip ${client_port} +The port number of the SMTP client. +Defined in the SMTP server only. +.ip ${client_resolve} +Holds the result of the resolve call for +.b ${client_name} +: OK, FAIL, FORGED, TEMP. +Defined in the SMTP server only. +.ip ${currHeader} +Header value as quoted string +(possibly truncated to +.b MAXNAME ). +.ip ${daemon_addr} +The IP address the daemon is listening on for connections. +Unless +.b DaemonPortOptions +is set, this will be +.q 0.0.0.0 . +.ip ${daemon_family} +The network family +if the daemon is accepting network connections. +Possible values include +.q inet , +.q inet6 , +.q iso , +.q ns , +.q x.25 +.ip ${daemon_flags} +The flags for the daemon as specified by the +Modifier= part of +.b DaemonPortOptions +whereby the flags are separated from each other by spaces, +and upper case flags are doubled. +That is, +Modifier=Ea +will be represented as +"EE a" in +.b ${daemon_flags} , +which is required for testing the flags in rulesets. +.ip ${daemon_info} +Some information about a daemon as a text string. +For example, +.q SMTP+queueing@00:30:00 . +.ip ${daemon_name} +The name of the daemon from +.b DaemonPortOptions +Name= suboption. +If this suboption is not set, +"Daemon#", +where # is the daemon number, +is used. +.ip ${daemon_port} +The port the daemon is accepting connection on. +Unless +.b DaemonPortOptions +is set, this will most likely be +.q 25 . +.ip ${deliveryMode} +The current delivery mode sendmail is using. +It is initially set to the value of the +.b DeliveryMode +option. +.ip ${envid} +The envelope id passed to sendmail as part of the envelope. +.ip ${hdrlen} +The length of the header value which is stored in +${currHeader} (before possible truncation). +If this value is greater than or equal +.b MAXNAME +the header has been truncated. +.ip ${hdr_name} +The name of the header field for which the current header +check ruleset has been called. +This is useful for a default header check ruleset to get +the name of the header. +.ip ${if_addr} +The IP address of the interface of an incoming connection +unless it is in the loopback net. +.ip ${if_name} +The name of the interface of an incoming connection. +This macro can be used for +SmtpGreetingMessage and HReceived for virtual hosting. +For example: +O SmtpGreetingMessage=$?{if_name}${if_name}$|$j$. Sendmail $v/$Z; $b +.ip ${mail_addr} +The address part of the resolved triple of the address given for the +.sm "SMTP MAIL" +command. +Defined in the SMTP server only. +.ip ${mail_host} +The host from the resolved triple of the address given for the +.sm "SMTP MAIL" +command. +Defined in the SMTP server only. +.ip ${mail_mailer} +The mailer from the resolved triple of the address given for the +.sm "SMTP MAIL" +command. +Defined in the SMTP server only. +.ip ${ntries} +The number of delivery attempts. +.ip ${opMode} +The current operation mode (from the +.b \-b +flag). +.ip ${queue_interval} +The queue run interval given by the +.b \-q +flag. +For example, +.b \-q30m +would set +.b ${queue_interval} +to +.q 00:30:00 . +.ip ${rcpt_addr} +The address part of the resolved triple of the address given for the +.sm "SMTP RCPT" +command. +Defined in the SMTP server only. +.ip ${rcpt_host} +The host from the resolved triple of the address given for the +.sm "SMTP RCPT" +command. +Defined in the SMTP server only. +.ip ${rcpt_mailer} +The mailer from the resolved triple of the address given for the +.sm "SMTP RCPT" +command. +Defined in the SMTP server only. +.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. +.pp +The +.b ${client_name} , +.b ${client_addr} , +and +.b ${client_port} +macros +are set to the name, address, and port number of the SMTP client +who is invoking +.i sendmail +as a server. +These can be used in the +.i check_* +rulesets (using the +.b $& +deferred evaluation form, of course!). +.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 does 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. +If +.i phrase1 +or +.i phrase2 +is another class, +e.g., +.i $=S , +the contents of class +.i S +are added to class +.i c . +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 +Some classes have internal meaning to +.i sendmail : +.nr ii 0.5i +.\".ip $=b +.\"A set of Content-Types that will not have the newline character +.\"translated to CR-LF before encoding into base64 MIME. +.\"The class can have major times +.\"(e.g., +.\".q image ) +.\"or full types +.\"(such as +.\".q application/octet-stream ). +.\"The class is initialized with +.\".q application/octet-stream , +.\".q image , +.\".q audio , +.\"and +.\".q video . +.ip $=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 . +.ip $=k +set to be the same as +.b $k , +that is, the UUCP node name. +.ip $=m +set to the set of domains by which this host is known, +initially just +.b $m . +.ip $=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 . +.ip $=q +A set of Content-Types that will never be encoded as base64 +(if they have to be encoded, they will be encoded as quoted-printable). +It can have primary types +(e.g., +.q text ) +or full types +(such as +.q text/plain ). +The class is initialized to have +.q text/plain +only. +.ip $=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. +.ip $=t +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 . +.ip $=w +set to be the set of all names +this host is known by. +This can be used to match local hostnames. +.ip $={persistentMacros} +set to the macros would should be saved across queue runs. +Care should be taken when adding macro names to this class. +.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 +maxmessages The maximum message deliveries per connection +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 Type information for DSN diagnostics +Wait The maximum time to wait for the mailer +/ The root directory for the mailer +.)b +Only the first character of the field name is checked. +.pp +The following flags may be set in the mailer description. +Any other flags may be used freely +to conditionally assign headers to messages +destined for particular mailers. +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 1869, 1652, and 1870). +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
" +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 +Do not include angle brackets around route-address syntax addresses. +This is useful on mailers that are going to pass addresses to a shell +that might interpret angle brackets as I/O redirection. +However, it does not protect against other shell metacharacters. +Therefore, passing addresses to a shell should not be considered secure. +.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. +See also option +.b HoldExpensive . +.ip E +Escape lines beginning with +.q From\0 +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 +Do User Database rewriting on envelope sender address. +.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 j +Do User Database rewriting on recipients as well as senders. +.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 behavior 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 q +When an address that resolves to this mailer is verified +(SMTP VRFY command), +generate 250 responses instead of 252 responses. +This will imply that the address is local. +.ip r +Same as +.b f , +but sends a +.b \-r +flag. +.ip R +Open SMTP connections from a +.q secure +port. +Secure ports aren't +(secure, that is) +except on UNIX machines, +so it is unclear that this adds anything. +.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 effective user id to be set to that user. +.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 " +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 z +Run Local Mail Transfer Protocol (LMTP) +between +.i sendmail +and the local mailer. +This is a variant on SMTP +defined in RFC 2033 +that is specifically designed for delivery to a local mailbox. +.ip 0 +Don't look up MX records for hosts sent via SMTP. +.ip 3 +Extend the list of characters converted to =XX notation +when converting to Quoted-Printable +to include those that don't map cleanly between ASCII and EBCDIC. +Useful if you have IBM mainframes on site. +.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 6 +Strip headers to seven bits. +.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 9 +If set, +do +.i limited +7\(->8 bit MIME conversions. +These conversions are limited to text/plain data. +.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. +.ip % +Do not attempt delivery on initial recipient of a message +or on queue runs +unless the queued message is selected +using one of the -qI/-qR/-qS queue run modifiers +or an ETRN request. +.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, +or an enhanced error code as described in RFC 1893, +.ul +Enhanced Mail System Status Codes. +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 0, 5, +or one of the check_* rulesets. +.pp +The mailer with the special name +.q discard +causes any mail sent to it to be discarded +but otherwise treated as though it were successfully delivered. +This mailer can not be used in ruleset 0, +only in the various address checking rulesets. +.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=lsoDq9, T=DNS/RFC822/X-Unix, A=sh \-c $u +M*file*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE $u +M*include*, P=/dev/null, F=su, A=INCLUDE $u +.)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. +Setting any value zero disables corresponding mailer-specific rewriting. +.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 user and group will be set as the +effective uid and gid for the process. +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 1894. +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 . +.pp +The m= field specifies the maximum number of messages to attempt to deliver +on a single SMTP or LMTP connection. +.pp +The /= field specifies a new root directory for the mailer. The path is +macro expanded and then passed to the +.q chroot +system call. The root directory is changed before the Directory field is +consulted or the uid is changed. +.pp +The Wait= field specifies the maximum time to wait for the +mailer to return after sending all data to it. +This applies to mailers that have been forked by +.i sendmail . +.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 one of the following: +.(b F +.b H \c +.i hname \c +.b : +.i htemplate +.)b +.(b F +.b H [\c +.b ? \c +.i mflags \c +.b ? \c +.b ]\c +.i hname \c +.b : +.i htemplate +.)b +.(b F +.b H [\c +.b ? \c +.i ${macro} \c +.b ? \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 a +.i ${macro} +(surrounded by question marks) +is specified, +the header will be automatically output +if the macro is set. +The macro may be set using any of the normal methods, +including using the +.b macro +storage map in a ruleset. +If one of these headers is in the input +it is reflected to the output +regardless of these flags or macros. +.pp +Some headers have special semantics +that will be described later. +.pp +A secondary syntax allows validation of headers as they are being read. +To enable validation, use: +.(b +.b H \c +.i Header \c +.b ": $>" \c +.i Ruleset +.b H \c +.i Header \c +.b ": $>+" \c +.i Ruleset +.)b +The indicated +.i Ruleset +is called for the specified +.i Header , +and can return +.b $#error +to reject the message or +.b $#discard +to discard the message +(as with the other +.b check_ * +rulesets). +The header is treated as a structured field, +that is, +comments (in parentheses) are deleted before processing, +unless the second form +.b $>+ +is used. +.pp +For example, the configuration lines: +.(b +HMessage-Id: $>CheckMessageId + +SCheckMessageId +R< $+ @ $+ > $@ OK +R$* $#error $: Illegal Message-Id header +.)b +would refuse any message that had a Message-Id: header of any of the +following forms: +.(b +Message-Id: <> +Message-Id: some text +Message-Id: extra crud +.)b +A default ruleset that is called for headers which don't have a +specific ruleset defined for them can be specified by: +.(b +.b H \c +.i * \c +.b ": $>" \c +.i Ruleset +.)b +or +.(b +.b H \c +.i * \c +.b ": $>+" \c +.i Ruleset +.)b +.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 AllowBogusHELO +[no short name] +If set, allow HELO SMTP commands that don't include a host name. +Setting this violates RFC 1123 section 5.2.5, +but is necessary to interoperate with several SMTP clients. +If there is a value, it is still checked for legitimacy. +.ip AuthMechanisms +[no short name] +List of authentication mechanisms for AUTH (separated by spaces). +The advertised list of authentication mechanisms will be the +intersection of this list and the list of available mechanisms as +determined by the Cyrus SASL library. +.ip AuthOptions +[no short name] +When to use the AUTH= parameter for the MAIL FROM command; +.(b +.ta 1i +A Only when authentication succeeded. +.)b +The default is to try whenever SMTP AUTH is available. +.ip AutoRebuildAliases +[D] +If set, +rebuild the alias database if necessary and possible. +The rebuild will happen the next time an alias is looked up. +If this option is not set, +.i sendmail +will never rebuild the alias database +unless explicitly requested +using +.b \-bi . +.b NOTE : +There is a potential for a denial of service attack if this is set. +This option is deprecated and +will be removed from a future version. +.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 ClientPortOptions=\fIoptions\fP +[O] +Set client SMTP options. +The options are +.i key=value +pairs separated by commas. +Known keys are: +.(b +.ta 1i +Port Name/number of source port for connection (defaults to any free port) +Addr Address mask (defaults INADDR_ANY) +Family Address family (defaults to INET) +SndBufSize Size of TCP send buffer +RcvBufSize Size of TCP receive buffer +Modifier Options (flags) for the daemon +.)b +The +.i Addr ess +mask may be a numeric address in dot notation +or a network name. +.i Modifier +can be the following character: +.(b +.ta 1i +h use name of interface for HELO command +.)b +If ``h'' is set, the name corresponding to the outgoing interface +address (whether chosen via the Connection parameter or +the default) is used for the HELO/EHLO command. +.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 ConnectOnlyTo=\fIaddress\fP +[no short name] +This can be used to +override the connection address (for testing purposes). +.ip ConnectionRateThrottle=\fIN\fP +[no short name] +If set to a positive value, +allow no more than +.i N +incoming daemon connections in a one second period. +This is intended to flatten out peaks +and allow the load average checking to cut in. +Defaults to zero (no limits). +.ip ControlSocketName=\fIname\fP +[no short name] +Name of the control socket for daemon management. +A running +.i sendmail +daemon can be controlled through this named socket. +Available commands are: +.i help, +.i restart, +.i shutdown, +and +.i status. +The +.i status +command returns the current number of daemon children, +the maximum number of daemon children, +the free disk space (in blocks) of the queue directory, +and the load average of the machine expressed as an integer. +If not set, no control socket will be available. +Solaris and pre-4.4BSD kernel users should see the note in sendmail/README . +.ip DaemonPortOptions=\fIoptions\fP +[O] +Set server SMTP options. +The options are +.i key=value +pairs. +Known keys are: +.(b +.ta 1i +Name User-definable name for the daemon (defaults to "Daemon#") +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) +Modifier Options (flags) for the daemon +SndBufSize Size of TCP send buffer +RcvBufSize Size of TCP receive buffer +.)b +The +.i Name +field is used for error messages and logging. +The +.i Addr ess +mask may be a numeric address in dot notation +or a network name. +.i Modifier +can be a sequence (without any delimiters) +of the following characters: +.(b +.ta 1i +a require authentication +b bind to interface through which mail has been received +c perform hostname canonification (.cf) +f require fully qualified hostname (.cf) +u allow unqualified addresses (.cf) +C don't perform hostname canonification +E disallow ETRN (see RFC 2476) +.)b +That is, one way to specify a message submission agent (MSA) that +requires authentication is: +.(b +O DaemonPortOptions=Name=MSA, Port=587, M=Ea +.)b +The modifiers that are marked with "(.cf)" have only +effect in the standard configuration file, in which +they are available via +.b ${daemon_flags} . +The flags ``c'' and ``C'' can change the default for +hostname canonification in the +.i sendmail.cf +file. +See the relevant documentation for +.sm FEATURE(nocanonify) . +The modifier ``f'' disallows addresses of the form +.b user@host +unless they are submitted directly. +The flag ``u'' allows unqualified sender addresses. +``b'' forces sendmail to bind to the interface +through which the e-mail has been +received for the outgoing connection. +.b WARNING: +Use ``b'' +only if outgoing mail can be routed through the incoming connection's +interface to its destination. No attempt is made to catch problems due to a +misconfiguration of this parameter, use it only for virtual hosting +where each virtual interface can connect to every possible location. +This will also override possible settings via +.b ClientPortOptions. +Note, +.i sendmail +will listen on a new socket +for each occurence of the DaemonPortOptions option +in a configuration file. +.ip DefaultAuthInfo +[no short name] +Filename that contains default authentication information for outgoing +connections. This file must contain the user id, the authorization id, +the password (plain text), and the realm to use +on separate lines and must be readable by +root (or the trusted user) only. +If no realm is specified, +.b $j +is used. +.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 DataFileBufferSize=\fIthreshold\fP +[no short name] +Set the +.i threshold , +in bytes, +before a memory-based +queue data file +becomes disk-based. +The default is 4096 bytes. +.ip DeadLetterDrop=\fIfile\fP +[no short name] +Defines the location of the system-wide dead.letter file, +formerly hardcoded to /usr/tmp/dead.letter. +If this option is not set (the default), +sendmail will not attempt to save to a system-wide dead.letter file +in the event +it can not bounce the mail to the user or postmaster. +Instead, it will rename the qf file +as it has in the past +when the dead.letter file could not be opened. +.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 DontBlameSendmail=\fIoption,option,...\fP +[no short name] +In order to avoid possible cracking attempts +caused by world- and group-writable files and directories, +.i sendmail +does paranoid checking when opening most of its support files. +If for some reason you absolutely must run with, +for example, +a group-writable +.i /etc +directory, +then you will have to turn off this checking +(at the cost of making your system more vulnerable to attack). +The arguments are individual options that turn off checking: +.(b +Safe +AssumeSafeChown +ClassFileInUnsafeDirPath +DontWarnForwardFileInUnsafeDirPath +ErrorHeaderInUnsafeDirPath +FileDeliveryToHardLink +FileDeliveryToSymLink +ForwardFileInUnsafeDirPath +ForwardFileInUnsafeDirPathSafe +ForwardFileIngroupWritableDirPath +GroupWritableAliasFile +GroupWritableDirPathSafe +GroupWritableForwardFileSafe +GroupWritableIncludeFileSafe +HelpFileinUnsafeDirPath +IncludeFileInUnsafeDirPath +IncludeFileInUnsafeDirPathSafe +IncludeFileIngroupWritableDirPath +LinkedAliasFileInWritableDir +LinkedClassFileInWritableDir +LinkedForwardFileInWritableDir +LinkedIncludeFileInWritableDir +LinkedMapInWritableDir +LinkedServiceSwitchFileInWritableDir +MapInUnsafeDirPath +NonRootSafeAddr +RunProgramInUnsafeDirPath +RunWritableProgram +TrustStickyBit +WorldWritableAliasFile +WriteMapToHardLink +WriteMapToSymLink +WriteStatsToHardLink +WriteStatsToSymLink +.)b +.b Safe +is the default. +The details of these flags are described above. +.\"XXX should have more here!!! XXX +.b "Use of this option is not recommended." +.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 behavior 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 DontProbeInterfaces +[no short name] +.i Sendmail +normally finds the names of all interfaces active on your machine +when it starts up +and adds their name to the +.b $=w +class of known host aliases. +If you have a large number of virtual interfaces +or if your DNS inverse lookups are slow +this can be time consuming. +This option turns off that probing. +However, you will need to be certain to include all variant names +in the +.b $=w +class by some other mechanism. +.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 DoubleBounceAddress=\fIerror-address\fP +[no short name] +If an error occurs when sending an error message, +send the error report +(termed a +.q "double bounce" +because it is an error +.q bounce +that occurs when trying to send another error +.q bounce ) +to the indicated address. +The address is macro expanded +at the time of delivery. +If not set, defaults to +.q postmaster . +.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 +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. +Messages which are undeliverable due to temporary address failures +(e.g., DNS failure) +also go to the FallBackMX host. +.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. +If no file name is specified, "helpfile" is used. +.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 HostsFile=\fIpath\fP +[no short name] +The path to the hosts database, +normally +.q /etc/hosts . +This option is only consulted when sendmail +is canonifying addresses, +and then only when +.q files +is in the +.q hosts +service switch entry. +In particular, this file is +.i never +used when looking up host addresses; +that is under the control of the system +.i gethostbyname (3) +routine. +.ip HostStatusDirectory=\fIpath\fP +[no short name] +The location of the long term host status information. +When set, +information about the status of hosts +(e.g., host down or not accepting connections) +will be shared between all +.i sendmail +processes; +normally, this information is only held within a single queue run. +This option requires a connection cache of at least 1 to function. +If the option begins with a leading `/', +it is an absolute pathname; +otherwise, +it is relative to the mail queue directory. +A suggested value for sites desiring persistent host status is +.q \&.hoststat +(i.e., a subdirectory of the queue directory). +.ip IgnoreDots +[i] +Ignore dots in incoming messages. +This is always disabled (that is, dots are always accepted) +when reading SMTP mail. +.ip LDAPDefaultSpec=\fIspec\fP +[no short name] +Sets a default map specification for LDAP maps. +The value should only contain LDAP specific settings +such as +.q "-h host -p port -d bindDN" . +The settings will be used for all LDAP maps +unless the individual map specification overrides a setting. +This option should be set before any LDAP maps are defined. +.ip LogLevel=\fIn\fP +[L] +Set the 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 MaxAliasRecursion=\fIN\fP +[no short name] +The maximum depth of alias recursion (default: 10). +.ip MaxDaemonChildren=\fIN\fP +[no short name] +If set, +.i sendmail +will refuse connections when it has more than +.i N +children processing incoming mail. +This does not limit the number of outgoing connections. +If not set, there is no limit to the number of children -- +that is, the system load averaging controls this. +.ip MaxHeadersLength=\fIN\fP +[no short name] +The maximum length of the sum of all headers. +This can be used to prevent a denial of service attack. +The default is no limit. +.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 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 MaxMimeHeaderLength=\fIN[/M]\fP +[no short name] +Sets the maximum length of certain MIME header field values +to +.i N +characters. +For some of these headers which take parameters, +the maximum length of each parameter is set to +.i M +if specified. If +.i /M +is not specified, one half of +.i N +will be used. +By default, +these values are 0, meaning no checks are done. +.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 MaxRecipientsPerMessage=\fIN\fP +[no short name] +The maximum number of recipients that will be accepted per message +in an SMTP transaction. +Note: setting this too low can interfere with sending mail from +MUAs that use SMTP for initial submission. +If not set, there is no limit on the number of recipients per envelope. +.ip MeToo +[m] +Send to me too, +even if I am in an alias expansion. +This option is deprecated +and will be removed from a future version. +.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 MustQuoteChars=\fIs\fP +[no short name] +Sets the list of characters that must be quoted if used in a full name +that is in the phrase part of a ``phrase
'' syntax. +The default is ``\'.''. +The characters ``@,;:\e()[]'' are always added to this list. +.ip NoRecipientAction +[no short name] +The action to take when you receive a message that has no valid +recipient headers (To:, Cc:, Bcc:, or Apparently-To: \(em +the last included for back compatibility with old +.i sendmail s). +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. +Note that OperatorChars must be set in the +configuration file before any rulesets. +.ip PidFile=\fIfilename\fP +[no short name] +Filename of the pid file. +(default is _PATH_SENDMAILPID). +The +.i filename +is macro-expanded before it is opened. +.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. +The address is macro expanded +at the time of delivery. +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 +noetrn Disallow ETRN entirely +noverb Disallow VERB entirely +restrictmailq Restrict mailq command +restrictqrun Restrict \-q command line flag +noreceipts Don't return success DSNs\** +nobodyreturn Don't return the body of a message with DSNs +goaway Disallow essentially all SMTP status queries +authwarnings Put X-Authentication-Warning: headers in messages +.)b +.(f +\**N.B.: +the +.b noreceipts +flag turns off support for RFC 1891 +(Delivery Status Notification). +.)f +The +.q goaway +pseudo-flag sets all flags except +.q noreceipts , +.q restrictmailq , +.q restrictqrun , +.q noetrn , +and +.q nobodyreturn . +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 ProcessTitlePrefix=\fIstring\fP +[no short name] +Prefix the process title shown on 'ps' listings with +.i string . +The +.i string +will be macro processed. +.ip QueueDirectory=\fIdir\fP +[Q] +Use the named +.i dir +as the queue directory. +To use multiple queues, supply a value ending with an asterisk. +For example, +.i /var/spool/mqueue/q* +will use all of the directories or symbolic links to directories +beginning with +.i q +in +.i /var/spool/mqueue +as queue directories. +Do not change the queue directory structure +while sendmail is running. +.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 multiplied by +the number of processors online on the system +(if that can be determined). +.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), +.q filename +(to order by the name of the queue file name), +.q time +(to order by the submission time), +and +.q priority +(to order 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. +Filename ordering saves the overhead of +reading all of the queued items +before starting the queue run. +Time ordering is almost always a bad idea, +since it allows large, bulk mail to go out +before smaller, personal mail, +but may have applicability on some hosts with very fast connections. +Priority ordering is the default. +.ip QueueTimeout=\fItimeout\fP +[T] +A synonym for +.q Timeout.queuereturn . +Use that form instead of the +.q QueueTimeout +form. +.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 RrtImpliesDsn +[R] +If this option is set, a +.q Return-Receipt-To: +header causes the request of a DSN, which is sent to +the envelope sender as required by RFC1891, +not to the address given in the header. +.ip RunAsUser=\fIuser\fP +[no short name] +The +.i user +parameter may be a user name +(looked up in +.i /etc/passwd ) +or a numeric user id; +either form can have +.q ":group" +attached +(where group can be numeric or symbolic). +If set to a non-zero (non-root) value, +.i sendmail +will change to this user id shortly after startup\**. +.(f +\**When running as a daemon, +it changes to this user after accepting a connection +but before reading any +.sm SMTP +commands. +.)f +This avoids a certain class of security problems. +However, this means that all +.q \&.forward +and +.q :include: +files must be readable by the indicated +.i user +and all files to be written must be writable by +.i user +Also, all file and program deliveries will be marked unsafe +unless the option +.b DontBlameSendmail=NonRootAddrSafe +is set, +in which case the delivery will be done as +.i user . +It is also incompatible with the +.b SafeFileEnvironment +option. +In other words, it may not actually add much to security on an average system, +and may in fact detract from security +(because other file permissions must be loosened). +However, it should be useful on firewalls and other +places where users don't have accounts and the aliases file is +well constrained. +.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 multiplied by +the number of processors online on the system +(if that can be determined). +.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 SafeFileEnvironment=\fIdir\fP +[no short name] +If this option is set, +.i sendmail +will do a +.i chroot (2) +call into the indicated +.i dir ectory +before doing any file writes. +If the file name specified by the user begins with +.i dir , +that partial path name will be stripped off before writing, +so (for example) +if the SafeFileEnvironment variable is set to +.q /safe +then aliases of +.q /safe/logs/file +and +.q /logs/file +actually indicate the same file. +Additionally, if this option is set, +.i sendmail +refuses to deliver to symbolic links. +.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 RFC2045 and RFC1344 for details). +If disabled, +.i sendmail +will not return the DSN keyword in response to an EHLO +and will not do Delivery Status Notification processing as described in +RFC1891. +.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/mail/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/mail/service.switch . +.ip SevenBitInput +[7] +Strip input to seven bits for compatibility with old systems. +This shouldn't be necessary. +.ip SingleLineFromHeader +[no short name] +If set, From: lines that have embedded newlines are unwrapped +onto one line. +This is to get around a botch in Lotus Notes +that apparently cannot understand legally wrapped RFC822 headers. +.ip SingleThreadDelivery +[no short name] +If set, a client machine will never try to open two SMTP connections +to a single server machine at the same time, +even in different processes. +That is, if another +.i sendmail +is already talking to some host a new +.i sendmail +will not open another connection. +This property is of mixed value; +although this reduces the load on the other machine, +it can cause mail to be delayed +(for example, if one +.i sendmail +is delivering a huge message, other +.i sendmail s +won't be able to send even small messages). +Also, it requires another file descriptor +(for the lock file) +per connection, so you may have to reduce the +.b ConnectionCacheSize +option to avoid running out of per-process file descriptors. +Requires the +.b HostStatusDirectory +option. +.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 StatusFile=\fIfile\fP +[S] +Log summary statistics in the named +.i file . +If no file name is specified, "statistics" is used. +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 to 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 Timeout.\fItype\fP=\|\fItimeout\fP +[r; subsumes old T option as well] +Set timeout values. +For more information, +see section +.\" XREF +4.1. +.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 TrustedUser=\fIuser\fP +[no short name] +The +.i user +parameter may be a user name +(looked up in +.i /etc/passwd ) +or a numeric user id. +Trusted user for file ownership and starting the daemon. If set, generated +alias databases and the control socket (if configured) will automatically +be owned by this user. +.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 Fromuser ). +Defaults to +.q "From $g $d" . +Don't change this unless your system uses a different UNIX mailbox format +(very unlikely). +.ip UnsafeGroupWrites +[no short name] +If set, +:include: and .forward files that are group writable are considered +.q unsafe , +that is, +they cannot reference programs or write directly to files. +World writable :include: and .forward files +are always unsafe.. +.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. +.ip XscriptFileBufferSize=\fIthreshold\fP +[no short name] +Set the +.i threshold , +in bytes, +before a memory-based +queue transcript file +becomes disk-based. +The default is 4096 bytes. +.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 +SevenBitInput [7], +EightBitMode [8], +MinFreeBlocks [b], +CheckpointInterval [C], +DeliveryMode [d], +ErrorMode [e], +IgnoreDots [i], +SendMimeErrors [j], +LogLevel [L], +MeToo [m], +OldStyleHeaders [o], +PrivacyOptions [p], +SuperSafe [s], +Verbose [v], +QueueSortOrder, +MinQueueAge, +DefaultCharSet, +Dial Delay, +NoRecipientAction, +ColonOkInAddr, +MaxQueueRunSize, +SingleLineFromHeader, +and +AllowBogusHELO. +Actually, PrivacyOptions [p] given on the command line +are added to those already specified in the +.i sendmail.cf +file, i.e., they can't be reset. +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.10) +used version level 9 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 behavior 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 +Version level seven configuration files +used new option names to replace old macros +(\c +.b $e +became +.b SmtpGreetingMessage , +.b $l +became +.b UnixFromLine , +and +.b $o +became +.b OperatorChars . +Also, prior to version seven, +the +.b F=q +flag (use 250 instead of 252 return value for +.sm "SMTP VRFY" +commands) +was assumed. +.pp +Version level eight configuration files allow +.b $# +on the left hand side of ruleset lines. +.pp +Version level nine configuration files allow +parentheses in rulesets, i.e. they are not treated +as comments and hence removed. +.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@Sendmail.ORG +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 +The +.i arguments +are passed to the map for arbitrary use. +Most map classes can interpolate these arguments +into their values using the syntax +.q %\fIn\fP +(where +.i n +is a digit) +to indicate the corresponding +.i argument . +Argument +.q %0 +indicates 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 +Note that +.i default +clauses never do this mapping. +.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 +library. +.i Sendmail +must be compiled with +.b NEWDB +defined. +.ip hash +Database lookups using the hash interface to the Berkeley DB +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 ldap +LDAP X500 directory lookups. +.i Sendmail +must be compiled with +.b LDAPMAP +defined. +The map supports most of the standard arguments +and most of the command line arguments of the +.i ldapsearch +program. +Note that, +by default, +if a single query matches multiple values, +only the first value will be returned +unless the +.b \-z +(value separator) +map flag is set. +Also, the +.b \-1 +map flag will treat a multiple value return +as if there were no matches. +.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 ph +PH query map. +Contributed and supported by +Mark Roth, roth@uiuc.edu. +For more information, +consult the web site +.q http://www-wsg.cso.uiuc.edu/sendmail/sendmail-phmap/ . +.ip nsd +nsd map for IRIX 6.5 and later. +Contributed and supported by Bob Mende of SGI, +mende@sgi.com. +.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 bestmx +Returns the best MX record for a host name given as the key. +The current machine is always preferred \*- +that is, if the current machine is one of the hosts listed as a +lowest-preference MX record, then it will be guaranteed to be returned. +This can be used to find out if this machine is the target for an MX record, +and mail can be accepted on that basis. +If the +.b \-z +flag is given, then all MX names are returned, +separated by the given delimiter. +.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 syslog +the key is logged via +.i syslogd \|(8). +The lookup returns the empty string. +.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. +.ip regex +The map definition on the +.b K +line contains a regular expression. +Any key input is compared to that expression using the +POSIX regular expressions routines regcomp(), regerr(), and regexec(). +Refer to the documentation for those routines for more information +about the regular expression matching. +No rewriting of the key is done if the +.b \-m +flag is used. Without it, the key is discarded or if +.b \-s +if used, it is substituted by the substring matches, delimited by +.b $| +or the string specified with the the +.b \-d +flag. The flags available for the map are +.(b +-n not +-f case sensitive +-b basic regular expressions + (default is extended) +-s substring match +-d set the delimiter used for -s +-a append string to key +-m match only, do not + replace/discard value +-D perform no lookup in deferred delivery mode. +.)b +The +.b \-s +flag can include an optional parameter which can be used +to select the substrings in the result of the lookup. For example, +.(b +-s1,3,4 +.)b +.ip program +The arguments on the +.b K +line are the pathname to a program and any initial parameters to be passed. +When the map is called, +the key is added to the initial parameters +and the program is invoked +as the default user/group id. +The first line of standard output is returned as the value of the lookup. +This has many potential security problems, +and has terrible performance; +it should be used only when absolutely necessary. +.ip macro +Set or clear a macro value. +To set a macro, +pass the value as the first argument in the map lookup. +To clear a macro, +do not pass an argument in the map lookup. +The map always returns the empty string. +Example of typical usage include: +.(b +Kstorage macro + +\&... + +# set macro ${MyMacro} to the ruleset match +R$+ $: $(storage {MyMacro} $@ $1 $) $1 +# set macro ${MyMacro} to an empty string +R$* $: $(storage {MyMacro} $@ $) $1 +# clear macro ${MyMacro} +R$\- $: $(storage {MyMacro} $) $1 +.)b +.ip arith +Perform simple arithmetic operations. +The operation is given as key, currently +, -, *, /, +l (for less than), and = are supported. +The two operands are given as arguments. +The lookup returns the result of the computation, +i.e. +.sm TRUE +or +.sm FALSE +for comparisons, integer values otherwise. +All options which are possible for maps are ignored. +A simple example is: +.(b +Kcomp arith + +\&... + +Scheck_etrn +R$* $: $(comp l $@ $&{load_avg} $@ 7 $) $1 +RFALSE $# error \&... +.)b +.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 "\-T\fIx\fP" +Append the string +.i x +on temporary failures. +For example, +.i x +would be appended if a DNS lookup returned +.q "server failed" +or an NIS lookup could not locate a server. +See also the +.b \-t +flag. +.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). +For LDAP maps this is an LDAP filter string +in which %s is replaced with the literal contents of the lookup key +and %0 is replaced with the LDAP escaped contents of the lookup key +according to RFC2254. +.ip "\-v\fIvalcol\fP" +The value column name (for NIS+) or number +(for text lookups). +For LDAP maps this is the name of one or more +attributes to be returned; +multiple attributes can be separated by commas. +If not specified, all attributes found in the match +will be returned. +.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. +For LDAP maps this is the separator character +to combine multiple values +into a single return string. +If not set, +the LDAP lookup will only return the first match found. +.ip "\-t" +Normally, when a map attempts to do a lookup +and the server fails +(e.g., +.i sendmail +couldn't contact any name server; +this is +.i not +the same as an entry not being found in the map), +the message being processed is queued for future processing. +The +.b \-t +flag turns off this behavior, +letting the temporary failure (server down) +act as though it were a permanent failure (entry not found). +It is particularly useful for DNS lookups, +where someone else's misconfigured name server can cause problems +on your machine. +However, care must be taken to ensure that you don't bounce mail +that would be resolved correctly if you tried again. +A common strategy is to forward such mail +to another, possibly better connected, mail server. +.ip "\-D" +Perform no lookup in deferred delivery mode. +This flag is set by default for the +.i host +map. +.ip "\-S\fIspacesub\fP +The character to use to replace space characters +after a successful map lookup (esp. useful for regex +and syslog maps). +.ip "\-s\fIspacesub\fP +For the dequote map only, +the character to use to replace space characters +after a successful dequote. +.ip "\-q" +Don't dequote the key before lookup. +.ip "\-L\fIlevel\fP +For the syslog map only, it specifies the level +to use for the syslog call. +.ip "\-A" +When rebuilding an alias file, +the +.b \-A +flag causes duplicate entries in the text version +to be merged. +For example, two entries: +.(b +list: user1, user2 +list: user3 +.)b +would be treated as though it were the single entry +.(b +list: user1, user2, user3 +.)b +in the presence of the +.b \-A +flag. +.pp +The following additional flags are present in the ldap map only: +.ip "\-R" +Do not auto chase referrals. sendmail must be compiled with +.b \-DLDAP_REFERRALS +to use this flag. +.ip "\-n" +Retrieve attribute names only. +.ip "\-r\fIderef\fP" +Set the alias dereference option to one of never, always, search, or find. +.ip "\-s\fIscope\fP" +Set search scope to one of base, one (one level), or sub (subtree). +.ip "\-h\fIhost\fP" +LDAP server hostname. +.ip "\-b\fIbase\fP" +LDAP search base. +.ip "\-p\fIport\fP" +LDAP service port. +.ip "\-l\fItimelimit\fP" +Time limit for LDAP queries. +.ip "\-Z\fIsizelimit\fP" +Size (number of matches) limit for LDAP queries. +.ip "\-d\fIdistinguished_name\fP" +The distinguished name to use to login to the LDAP server. +.ip "\-M\fImethod\fP" +The method to authenticate to the LDAP server. +Should be one of +.b LDAP_AUTH_NONE , +.b LDAP_AUTH_SIMPLE , +or +.b LDAP_AUTH_KRBV4 . +.ip "\-P\fIpasswordfile\fP" +The file containing the secret key for the +.b LDAP_AUTH_SIMPLE +authentication method +or the name of the Kerberos ticket file for +.b LDAP_AUTH_KRBV4 . +.ip "\-1" +Force LDAP searches to only succeed if a single match is found. +If multiple values are found, +the search is treated as if no match was found. +.pp +The +.i dbm +map appends the strings +.q \&.pag +and +.q \&.dir +to the given filename; +the +.i hash +and +.i btree +maps append +.q \&.db . +For example, the map specification +.(b +Kuucp dbm \-o \-N /etc/mail/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 +/etc/mail/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. +.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. +Other features are available which provide similar functionality, +e.g., virtual hosting and mapping local addresses into a +generic form as explained in cf/README. +.)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/mail/userdb . +To make the database version of the map, run the program: +.(b +makemap btree /etc/mail/userdb < /etc/mail/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/mail/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 devtools/OS/$oscf" +.pp +These parameters are intended to describe the compilation environment, +not site policy, +and should normally be defined in the operating system +configuration file. +.b "This section needs a complete rewrite." +.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 LDAPMAP +Compile in support for LDAP X500 queries. +Requires libldap and liblber +from the Umich LDAP 3.2 or 3.3 release +or equivalent libraries for other LDAP libraries +such as OpenLDAP. +.ip HESIOD +Compile in support for Hesiod. +.ip MAP_NSD +Compile in support for IRIX NSD lookups. +.ip MAP_REGEX +Compile in support for regular expression matching. +.ip PH_MAP +Compile in support for ph lookups. +.ip SASL +Compile in support for SASL, +a required component for SMTP Authentication support. +.ip TCPWRAPPERS +Compile in support for TCP Wrappers. +.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 sendmail/README +file for the latest scoop on these flags. +.sh 2 "Parameters in sendmail/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 sendmail/README or sendmail/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 [256]" +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 [1000]" +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 [100]" +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). +.ip "MAXDAEMONS [10]" +The maximum number of sockets sendmail will open for accepting connections +on different ports. +.ip "MAXMACNAMELEN [25]" +The maximum length of a macro name. +.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 NETINET6\(dg +If set, +support for IPv6 networking is compiled in. +.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 NETUNIX\(dg +If set, +support for UNIX domain sockets is compiled in. +This is used for control socket support. +.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\(dg +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\(dg +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 FAST_PID_RECYCLE +Set this if your system can possibly +reuse the same pid in the same second of time. +.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 ), +SFS_MOUNT (use the two argument statfs(2) syscall including ), +SFS_STATFS (use the two argument statfs(2) syscall including ), +SFS_STATVFS (use the two argument statfs(2) syscall including ), +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 sendmail/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 "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 *args) +.)b +The +.i map +is an internal data structure. +The +.i args +is a pointer to the portion of the configuration file line +following the map class name; +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[], char **av, int *statp) +.)b +The +.i map +defines the map internally. +The +.i buf +has 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 (RefuseLA > 0 && 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@Sendmail.ORG. +.)f +.sh 2 "Configuration in sendmail/daemon.c" +.pp +The file +.i sendmail/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 "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 +resulting in version 8.1 +should be credited to Bryan Costales of the +International Computer Science Institute. +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 +Gregory Neil Shapiro +of Worcester Polytechnic Institute +has become instrumental in all phases of +.i sendmail +support and development, +and was largely responsible for getting versions 8.8 and 8.9 +out the door. +.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 and organizations made notable contributions: +.(l +Claus Assmann +John Beck, Hewlett-Packard & Sun Microsystems +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 & InfoBeat +Pa\*:r (Pell) Emanuelsson +Craig Everhart, Transarc Corporation +Per Hedeland, Ericsson +Tom Ivar Helbekkmo, Norwegian School of Economics +Kari Hurtta, Finnish Meteorological Institute +Allan E. Johannesen, WPI +Jonathan Kamens, OpenVision Technologies, Inc. +Takahiro Kanbe, Fuji Xerox Information Systems Co., Ltd. +Brian Kantor, University of California, San Diego +John Kennedy, Cal State University, Chico +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 +Gregory Neil Shapiro, WPI +Eric Schnoebelen, Convex Computer Corp. +Eric Wassenaar, National Institute for Nuclear and High Energy Physics, Amsterdam +Randall Winchester, University of Maryland +Christophe Wolfhugel, Pasteur Institute & Herve Schauer Consultants (Paris) +Exactis.com, Inc. +.)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@Sendmail.ORG'' 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 in background +D Run as a daemon in foreground +t Run in test mode +v Just verify addresses, don't collect or deliver +i Initialize the alias database +p Print the mail queue +h Print the persistent host status database +H Purge expired entries from the persistent host status database +.)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 envelope sender address is set to +.i addr . +This address may also be used in the From: header +if that header is missing during initial submission. +The envelope sender address is used as the recipient +for delivery status notifications +and may also appear in a Return-Path: header. +.ip \-F\ \fIname\fP +Sets the full name of this user to +.i name . +.ip \-G +When accepting messages via the command line, +indicate that they are for relay (gateway) submission. +sendmail may complain about syntactically invalid messages, +e.g., unqualified host names, +rather than fixing them when this flag is set. +sendmail will not do any canonicalization in this mode. +.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 "\-L \fItag\fP" +Sets the identifier used for syslog. +Note that this identifier is set +as early as possible. +However, +.i sendmail +may be used +if problems arise +before the command line arguments +are processed. +.ip \-n +Don't do aliasing or forwarding. +.ip "\-N \fInotifications\fP" +Tag all addresses being sent as wanting the indicated +.i notifications , +which consists of the word +.q NEVER +or a comma-separated list of +.q SUCCESS , +.q FAILURE , +and +.q DELAY +for successful delivery, +failure, +and a message that is stuck in a queue somewhere. +The default is +.q FAILURE,DELAY . +.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 . +Multiple +.i \-q\fIX\fP +flags are permitted, +with items with the same key letter +.q or'ed +together, and items with different key letters +.q and'ed +together. +.ip "\-R ret" +What information you want returned if the message bounces; +.i ret +can be +.q HDRS +for headers only or +.q FULL +for headers plus body. +This is a request only; +the other end is not required to honor the parameter. +If +.q HDRS +is specified local bounces also return only the headers. +.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 "\-U" +Indicate that this is an initial User Agent submission. +This flag is deprecated. +Future releases will ignore this flag and +assume all submissions from the command line are +initial submissions. +.ip "\-V envid" +The indicated +.i envid +is passed with the envelope of the message +and returned if the message bounces. +.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. +The DSN related options +.q "\-N" , +.q "\-R" , +and +.q "\-V" +have no effects on +.i sendmail +running as daemon. +.+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 . +The individual qf, df, and xf files +may be stored in separate +.i qf/ , +.i df/ , +and +.i xf/ +subdirectories +if they are present in the queue directory. +.pp +To use multiple queues, +supply a value ending with an asterisk. +For example, +.i /var/spool/mqueue/q* +will use all of the directories or symbolic links to directories +beginning with `q' in +.i /var/spool/mqueue +as queue directories. +New messages will be randomly placed +into one of the queues. +Do not change the queue directory structure +while sendmail is running. +.pp +All queue files have the name +\fIx\fP\|\fBf\fP\fIYMDhmsNPPPPP\fP +where +.i YMDhmsNPPPPP +is the +.i id +for this message +and the +.i x +is a type. +The individual letters in the +.i id +are: +.nr ii 0.5i +.ip Y +Encoded year +.ip M +Encoded month +.ip D +Encoded day +.ip h +Encoded hour +.ip m +Encoded minute +.ip s +Encoded second +.ip N +Envelope number +.ip PPPPP +First five digits of the process ID +.pp +All files with the same id collectively define one message. +If memory-buffered files are available, +some of these files may never appear +on disk. +.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. +For 8.10 the version number is 3. +.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 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: +HReceived: by vangogh.CS.Berkeley.EDU (5.108/2.7) id AAA06703; + Fri, 17 Jul 1992 00:28:55 -0700 +HReceived: from mail.CS.Berkeley.EDU by vangogh.CS.Berkeley.EDU (5.108/2.7) + id AAA06698; Fri, 17 Jul 1992 00:28:54 -0700 +HReceived: from [128.32.31.21] by mail.CS.Berkeley.EDU (5.96/2.5) + id AA22777; Fri, 17 Jul 1992 03:29:14 -0400 +HReceived: by foo.bar.baz.de (5.57/Ultrix3.0-C) + id AA22757; Fri, 17 Jul 1992 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/mail/sendmail.cf +The configuration file, +in textual form. +.ip /etc/mail/helpfile +The SMTP help file. +.ip /etc/mail/statistics +A statistics file; need not be present. +.ip /etc/mail/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; +the second line contains the command line used to invoke the daemon, +and later versions of +.i sendmail +may add more information to subsequent lines. +.ip /etc/mail/aliases +The textual version of the alias file. +.ip /etc/mail/aliases.db +The alias file in +.i hash \|(3) +format. +.ip /etc/mail/aliases.{pag,dir} +The alias file in +.i ndbm \|(3) +format. +.ip /var/spool/mqueue +The directory in which the mail queue(s) +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. +.if o \ +\{\ +. bp +. rs +. sp |4i +. ce 2 +This page intentionally left blank; +replace it with a blank sheet for double-sided output. +.\} +.\".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 +.\".sp +.\"Version $Revision: 1.1.1.1 $ +.\".ce 0 +.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 +.if o \ +\{\ +. bp +. rs +. sp |4i +. ce 2 +This page intentionally left blank; +replace it with a blank sheet for double-sided output. +.\} diff --git a/gnu/usr.sbin/sendmail/doc/op/op.ps b/gnu/usr.sbin/sendmail/doc/op/op.ps new file mode 100644 index 00000000000..3aba7116fe4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/doc/op/op.ps @@ -0,0 +1,7608 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.11 +%%CreationDate: Thu Feb 3 21:07:49 2000 +%%DocumentNeededResources: font Times-Bold +%%+ font Times-Roman +%%+ font Times-Italic +%%+ font Symbol +%%DocumentSuppliedResources: procset grops 1.11 0 +%%Pages: 84 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.11 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 +/MANUAL{ +statusdict begin/manualfeed true store end +}bind 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)236.833 143.4 Q/F1 10/Times-Bold@0 SF +(TM)-8 I/F2 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/F3 10/Times-Roman@0 SF +(Eric Allman)263.42 196.2 Q(Sendmail, Inc.)258.975 208.2 Q +(eric@Sendmail.COM)244.37 220.2 Q -1.11(Ve)260.225 244.2 S(rsion 8.310) +1.11 E -.15(Fo)234.465 268.2 S 2.5(rS).15 G(endmail V)-2.5 E +(ersion 8.10)-1.11 E/F4 10/Times-Italic@0 SF(Sendmail)97 312.6 Q/F5 8 +/Times-Roman@0 SF(TM)-5 I F3 .1(implements a general purpose internetw) +2.6 5 N .1(ork mail routing f)-.1 F .1(acility under the UNIX\256 oper) +-.1 F(-)-.2 E .017(ating system.)72 324.6 R .017(It is not tied to an) +5.017 F 2.517(yo)-.15 G .017 +(ne transport protocol \212 its function may be lik)-2.517 F .017 +(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)-6.036 G 1.036 +(he process, it can do a limited amount of message)-3.536 F .604(header\ + editing to put the message into a format that is appropriate for the r\ +ecei)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 F4 +(sendmail)3.211 E F3 3.211(,t)C .71 +(he con\214guration \214le can seem some)-3.211 F .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-) +-2.893 F .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 \214le incrementally)72 412.8 Q(.)-.65 E F4(Sendmail)97 429 Q F3 +1.471(is based on RFC821 \(Simple Mail T)3.97 F 1.471 +(ransport Protocol\), RFC822 \(Internet Mail Headers)-.35 F -.15(Fo)72 +441 S 1.659(rmat\), RFC974 \(MX routing\), RFC1123 \(Internet Host Requ\ +irements\), RFC2045 \(MIME\), RFC1869).15 F .004(\(SMTP Service Extensi\ +ons\), RFC1652 \(SMTP 8BITMIME Extension\), RFC1870 \(SMTP SIZE Extensi\ +on\),)72 453 R 2.023(RFC1891 \(SMTP Deli)72 465 R -.15(ve)-.25 G 2.022(\ +ry Status Noti\214cations\), RFC1892 \(Multipart/Report\), RFC1893 \(Ma\ +il System).15 F .849(Status Codes\), RFC1894 \(Deli)72 477 R -.15(ve) +-.25 G .849(ry Status Noti\214cations\), RFC1985 \(SMTP Service Extensi\ +on for Remote).15 F 1.682 +(Message Queue Starting\), RFC2033 \(Local Message T)72 489 R 1.682 +(ransmission Protocol\), RFC2034 \(SMTP Service)-.35 F .815(Extension f\ +or Returning Enhanced Error Codes\), RFC2476 \(Message Submission\), an\ +d RFC2554 \(SMTP)72 501 R .758(Service Extension for Authentication\).) +72 513 R(Ho)5.758 E(we)-.25 E -.15(ve)-.25 G 1.558 -.4(r, s).15 H(ince) +.4 E F4(sendmail)3.258 E F3 .758(is designed to w)3.258 F .758 +(ork in a wider w)-.1 F .758(orld, in)-.1 F(man)72 525 Q 2.5(yc)-.15 G +(ases it can be con\214gured to e)-2.5 E(xceed these protocols.)-.15 E +(These cases are described herein.)5 E(Although)97 541.2 Q F4(sendmail) +3.547 E F3 1.048(is intended to run without the need for monitoring, it\ + has a number of features)3.547 F 1.972(that may be used to monitor or \ +adjust the operation under unusual circumstances.)72 553.2 R 1.972 +(These features are)6.972 F(described.)72 565.2 Q .816 +(Section one describes ho)97 581.4 R 3.316(wt)-.25 G 3.316(od)-3.316 G +3.316(oab)-3.316 G(asic)-3.316 E F4(sendmail)3.316 E F3 3.317 +(installation. Section)3.317 F(tw)3.317 E 3.317(oe)-.1 G .817 +(xplains the day-to-day)-3.467 F .283(information you should kno)72 +593.4 R 2.783(wt)-.25 G 2.783(om)-2.783 G .282 +(aintain your mail system.)-2.783 F .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 605.4 R .635 +(\214cient information for you to install)-.25 F F4(sendmail)3.135 E F3 +.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 617.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 629.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.) +-3.385 F(This)5.886 E .005 +(section is for masochists and people who must write their o)72 641.4 R +.004(wn con\214guration \214le.)-.25 F .004(Section six describes con-) +5.004 F .165(\214guration that can be done at compile time.)72 653.4 R +.165(The appendix)5.165 F .165(es gi)-.15 F .465 -.15(ve a b)-.25 H .165 +(rief b).15 F .165(ut detailed e)-.2 F .165(xplanation of a num-)-.15 F +(ber of features not described in the rest of the paper)72 665.4 Q(.) +-.55 E .32 LW 76 675 72 675 DL 80 675 76 675 DL 84 675 80 675 DL 88 675 +84 675 DL 92 675 88 675 DL 96 675 92 675 DL 100 675 96 675 DL 104 675 +100 675 DL 108 675 104 675 DL 112 675 108 675 DL 116 675 112 675 DL 120 +675 116 675 DL 124 675 120 675 DL 128 675 124 675 DL 132 675 128 675 DL +136 675 132 675 DL 140 675 136 675 DL 144 675 140 675 DL 148 675 144 675 +DL 152 675 148 675 DL 156 675 152 675 DL 160 675 156 675 DL 164 675 160 +675 DL 168 675 164 675 DL 172 675 168 675 DL 176 675 172 675 DL 180 675 +176 675 DL 184 675 180 675 DL 188 675 184 675 DL 192 675 188 675 DL 196 +675 192 675 DL 200 675 196 675 DL 204 675 200 675 DL 208 675 204 675 DL +212 675 208 675 DL 216 675 212 675 DL/F6 8/Times-Bold@0 SF(DISCLAIMER:) +93.6 687 Q F5(This documentation is under modi\214cation.)2 E +(Sendmail is a trademark of Sendmail, Inc.)93.6 699 Q F1 +(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-1)200.86 E EP +%%Page: 2 2 +%%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;)220.225 300 Q +(replace it with a blank sheet for double-sided output.)182.6 312 Q EP +%%Page: 7 3 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-7)200.86 E 2.5(1. B)72 96 R(ASIC INST)-.3 E(ALLA)-.9 E(TION)-.95 +E/F1 10/Times-Roman@0 SF .127(There are tw)112 112.2 R 2.627(ob)-.1 G +.126(asic steps to installing)-2.627 F/F2 10/Times-Italic@0 SF(sendmail) +2.626 E F1 5.126(.F)C .126(irst, you ha)-5.126 F .426 -.15(ve t)-.2 H +2.626(oc).15 G .126(ompile and install the binary)-2.626 F(.)-.65 E(If) +87 124.2 Q F2(sendmail)2.888 E F1 .388(has already been ported to your \ +operating system that should be simple.)2.888 F .389(Second, you must) +5.388 F -.2(bu)87 136.2 S .279(ild a run-time con\214guration \214le.).2 +F .278(This is a \214le that)5.279 F F2(sendmail)2.778 E F1 .278 +(reads when it starts up that describes the)2.778 F .531(mailers it kno) +87 148.2 R .531(ws about, ho)-.25 F 3.031(wt)-.25 G 3.031(op)-3.031 G +.531(arse addresses, ho)-3.031 F 3.031(wt)-.25 G 3.031(or)-3.031 G -.25 +(ew)-3.031 G .531(rite the message header).25 F 3.031(,a)-.4 G .532 +(nd the settings of)-3.031 F -.25(va)87 160.2 S .869(rious options.).25 +F .869(Although the con\214guration \214le can be quite comple)5.869 F +.868(x, a con\214guration can usually be)-.15 F -.2(bu)87 172.2 S +(ilt using an M4-based con\214guration language.).2 E .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 s\ +tandard installation parameters are acceptable.)-.15 F 1.431(All path-) +6.431 F .976(names and e)87 212.4 R .976(xamples are gi)-.15 F -.15(ve) +-.25 G 3.476(nf).15 G .976(rom the root of the)-3.476 F F2(sendmail) +3.476 E F1 .977(subtree, normally)3.476 F F2(/usr/sr)3.477 E(c/usr)-.37 +E(.sbin/send-)-1.11 E(mail)87 224.4 Q 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)-3.042 F .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.57 E F1 .07(source is in the)2.57 F F2(sendmail)2.571 E +F1(subdirectory)2.571 E 5.071(.T)-.65 G 2.571(oc)-5.871 G .071 +(ompile sendmail, \231cd\232 into the)-2.571 F F2(send-)2.571 E(mail)102 +304.8 Q F1(directory and type)2.5 E(./Build)142 321 Q 1.411 +(This will lea)102 337.2 R 1.711 -.15(ve t)-.2 H 1.411 +(he binary in an appropriately named subdirectory).15 F 3.911(,e)-.65 G +1.41(.g., obj.BSD-OS.2.1.i386.)-3.911 F(It)6.41 E -.1(wo)102 349.2 S +(rks for multiple object v).1 E +(ersions compiled out of the same directory)-.15 E(.)-.65 E F0 2.5 +(1.1.1. T)102 373.2 R(weaking the Build In)-.74 E -.1(vo)-.4 G(cation).1 +E F1 -1.1(Yo)142 389.4 S 2.904(uc)1.1 G .404(an gi)-2.904 F .704 -.15 +(ve p)-.25 H .404(arameters on the).15 F F2(Build)2.905 E F1 2.905 +(command. In)2.905 F .405(most cases these are only used when)2.905 F +(the)117 401.4 Q F2(obj.*)2.5 E F1(directory is \214rst created.)5 E +(These commands include:)5 E117 417.6 Q F2(libdir)2.5 E(s)-.1 E F1 +2.5(Al)153 429.6 S(ist of directories to search for libraries.)-2.5 E +117 445.8 Q F2(incdir)2.5 E(s)-.1 E F1 2.5(Al)153 457.8 S +(ist of directories to search for include \214les.)-2.5 E117 474 Q +F2(en)2.5 E(var)-.4 E F1(=)A F2(value)A F1(Set an en)153 486 Q +(vironment v)-.4 E(ariable to an indicated)-.25 E F2(value)2.5 E F1 +(before compiling.)2.5 E 23.42(\255c Create)117 502.2 R 2.5(an)2.5 G +-.25(ew)-2.5 G F2(obj.*)2.75 E F1(tree before running.)5 E117 +518.4 Q F2(sitecon\214g)2.5 E F1 2.193 +(Read the indicated site con\214guration \214le.)153 530.4 R 2.192 +(If this parameter is not speci\214ed,)7.193 F F2(Build)4.692 E F1 +(includes)153 542.4 Q F2(all)11.511 E F1 9.011(of the \214les)11.511 F +F2($B)11.512 E(UILDT)-.1 E(OOLS/Site/site)-.18 E(.$oscf)-.15 E(.m4)-.15 +E F1(and)11.512 E F2($B)11.512 E(UILD-)-.1 E -.18(TO)153 554.4 S +(OLS/Site/site).18 E(.con\214g)-.15 E(.m4)-.15 E F1 2.985(,w)C .485 +(here $B)-2.985 F(UILDT)-.1 E .485(OOLS is normally)-.18 F F2(../de) +2.985 E(vtools)-.15 E F1 .485(and $oscf is)2.985 F .678 +(the same name as used on the)153 566.4 R F2(obj.*)3.178 E F1(directory) +5.678 E 5.678(.S)-.65 G .678(ee belo)-5.678 F 3.178(wf)-.25 G .678 +(or a description of the site)-3.178 F(con\214guration \214le.)153 578.4 +Q 22.3(\255S Skip)117 594.6 R(auto-con\214guration.)4.421 E F2(Build) +6.921 E F1 1.921(will a)4.421 F -.2(vo)-.2 G 1.921 +(id auto-detecting libraries if this is set.).2 F(All)6.92 E(libraries \ +and map de\214nitions must be speci\214ed in the site con\214guration \ +\214le.)153 606.6 Q(An)117 622.8 Q 2.5(yo)-.15 G +(ther parameters are passed to the)-2.5 E F2(mak)2.5 E(e)-.1 E F1 +(program.)2.5 E F0 2.5(1.1.2. Cr)102 646.8 R +(eating a Site Con\214guration File)-.18 E F1 +(\(This section is not yet complete.)142 663 Q -.15(Fo)5 G 2.5(rn).15 G +-.25(ow)-2.5 G 2.5(,s)-.4 G(ee the \214le de)-2.5 E +(vtools/README for details.\))-.25 E F0 2.5(1.1.3. T)102 687 R +(weaking the Mak)-.74 E(e\214le)-.1 E F2(Sendmail)142 703.2 Q F1 2.18 +(supports tw)4.68 F 4.681(od)-.1 G(if)-4.681 E 2.181 +(ferent formats for the local \(on disk\) v)-.25 F 2.181 +(ersion of databases,)-.15 F(notably the)117 715.2 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 EP +%%Page: 8 4 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 198.36(SMM:08-8 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 39.5 +(NDBM The)117 96 R -.74(``)3.167 G(ne).74 E 3.167(wD)-.25 G(BM')-3.167 E +3.167('f)-.74 G .667(ormat, a)-3.167 F -.25(va)-.2 G .666 +(ilable on nearly all systems around today).25 F 5.666(.T)-.65 G(his) +-5.666 E -.1(wa)189 108 S 3.54(st).1 G 1.041 +(he preferred format prior to 4.4BSD.)-3.54 F 1.041(It allo)6.041 F +1.041(ws such comple)-.25 F 3.541(xt)-.15 G 1.041(hings as)-3.541 F +(multiple databases and closing a currently open database.)189 120 Q +32.84(NEWDB The)117 136.2 R(Berk)3.788 E(ele)-.1 E 3.788(yD)-.15 G 3.788 +(Bp)-3.788 G 3.788(ackage. If)-3.788 F 1.288(you ha)3.788 F 1.588 -.15 +(ve t)-.2 H 1.288(his, use it.).15 F 1.287(It allo)6.287 F 1.287 +(ws long records,)-.25 F 2.56 +(multiple open databases, real in-memory caching, and so forth.)189 +148.2 R -1.1(Yo)7.56 G 5.06(uc)1.1 G(an)-5.06 E .469 +(de\214ne this in conjunction with)189 160.2 R/F2 9/Times-Roman@0 SF +(NDBM)2.969 E F1 2.969(;i)C 2.968(fy)-2.969 G .468 +(ou do, old alias databases are read,)-2.968 F -.2(bu)189 172.2 S 3.108 +(tw).2 G .608(hen a ne)-3.108 F 3.108(wd)-.25 G .608 +(atabase is created it will be in NEWDB format.)-3.108 F .608 +(As a nasty)5.608 F 1.804(hack, if you ha)189 184.2 R 2.104 -.15(ve N) +-.2 H 1.804(EWDB, NDBM, and NIS de\214ned, and if the alias \214le).15 F +.123(name includes the substring \231/yp/\232,)189 196.2 R/F3 10 +/Times-Italic@0 SF(sendmail)2.623 E F1 .123(will create both ne)2.623 F +2.624(wa)-.25 G .124(nd old v)-2.624 F(er)-.15 E(-)-.2 E 1.08 +(sions of the alias \214le during a)189 208.2 R F3(ne)3.58 E(walias)-.15 +E F1 3.58(command. This)3.58 F 1.08(is required because)3.58 F .845 +(the Sun NIS/YP system reads the DBM v)189 220.2 R .845 +(ersion of the alias \214le.)-.15 F(It')5.845 E 3.345(su)-.55 G .845 +(gly as)-3.345 F(sin, b)189 232.2 Q(ut it w)-.2 E(orks.)-.1 E 1.112 +(If neither of these are de\214ned,)117 248.4 R F3(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.042(This can be slo)117 +260.4 R 3.542(wa)-.25 G 1.043(nd should be a)-3.542 F -.2(vo)-.2 G 3.543 +(ided. There).2 F 1.043(are also se)3.543 F -.15(ve)-.25 G 1.043 +(ral methods for remote database).15 F(access:)117 272.4 Q 53.39 +(NIS Sun')117 288.6 R 2.5(sN)-.55 G(etw)-2.5 E +(ork Information Services \(formerly YP\).)-.1 E 28.94(NISPLUS Sun')117 +304.8 R 2.5(sN)-.55 G(IS+ services.)-2.5 E 26.73(NETINFO NeXT')117 321 R +2.5(sN)-.55 G(etInfo service.)-2.5 E 32.84(HESIOD Hesiod)117 337.2 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 +353.4 R(to a ne)117 365.4 Q 2.5(we)-.25 G -.4(nv)-2.5 G(ironment.).4 E +F0 2.5(1.1.4. Compilation)102 389.4 R(and installation)2.5 E F1 .308 +(After making the local system con\214guration described abo)142 405.6 R +-.15(ve)-.15 G 2.809(,Y).15 G .309(ou should be able to com-)-3.909 F +(pile and install the system.)117 417.6 Q +(The script \231Build\232 is the best approach on most systems:)5 E +(./Build)157 433.8 Q(This will use)117 450 Q F3(uname)2.5 E F1 +(\(1\) to create a custom Mak)A(e\214le for your en)-.1 E(vironment.)-.4 +E(If you are installing in the standard places, you should be able to i\ +nstall using)142 466.2 Q(./Build install)157 482.4 Q 3.346(This should \ +install the binary in /usr/sbin and create links from /usr/bin/ne)117 +498.6 R -.1(wa)-.25 G 3.345(liases and).1 F 1.576 +(/usr/bin/mailq to /usr/sbin/sendmail.)117 510.6 R 1.577 +(On 4.4BSD systems it will also format and install man)6.576 F(pages.) +117 522.6 Q F0 2.5(1.2. Con\214guration)87 546.6 R(Files)2.5 E F3 +(Sendmail)127 562.8 Q F1 2.079 +(cannot operate without a con\214guration \214le.)4.58 F 2.079 +(The con\214guration de\214nes the mail)7.079 F(deli)102 574.8 Q -.15 +(ve)-.25 G .888(ry mechanisms understood at this site, ho).15 F 3.389 +(wt)-.25 G 3.389(oa)-3.389 G .889(ccess them, ho)-3.389 F 3.389(wt)-.25 +G 3.389(of)-3.389 G(orw)-3.389 E .889(ard email to remote)-.1 F .088 +(mail systems, and a number of tuning parameters.)102 586.8 R .088 +(This con\214guration \214le is detailed in the later por)5.088 F(-)-.2 +E(tion of this document.)102 598.8 Q(The)127 615 Q F3(sendmail)2.764 E +F1 .264(con\214guration can be daunting at \214rst.)2.764 F .264(The w) +5.264 F .264(orld is comple)-.1 F .264(x, and the mail con-)-.15 F .109 +(\214guration re\215ects that.)102 627 R .109(The distrib)5.109 F .108 +(ution includes an m4-based con\214guration package that hides a lot)-.2 +F(of the comple)102 639 Q(xity)-.15 E(.)-.65 E .47 +(These con\214guration \214les are simpler than old v)127 655.2 R .47 +(ersions lar)-.15 F .47(gely because the w)-.18 F .47(orld has become) +-.1 F 1.449(simpler; in particular)102 667.2 R 3.949(,t)-.4 G -.15(ex) +-3.949 G 1.449(t-based host \214les are of).15 F 1.448 +(\214cially eliminated, ob)-.25 F 1.448 +(viating the need to \231hide\232)-.15 F(hosts behind a re)102 679.2 Q +(gistered internet g)-.15 E(ate)-.05 E -.1(wa)-.25 G -.65(y.).1 G .092(\ +These \214les also assume that most of your neighbors use domain-based \ +UUCP addressing; that)127 695.4 R .361 +(is, instead of naming hosts as \231host!user\232 the)102 707.4 R 2.861 +(yw)-.15 G .361(ill use \231host.domain!user\232.)-2.861 F .36 +(The con\214guration \214les)5.36 F(can be customized to w)102 719.4 Q +(ork around this, b)-.1 E(ut it is more comple)-.2 E(x.)-.15 E EP +%%Page: 9 5 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-9)200.86 E/F1 10/Times-Roman@0 SF .657 +(Our con\214guration \214les are processed by)127 96 R/F2 10 +/Times-Italic@0 SF(m4)3.158 E F1 .658(to f)3.158 F .658 +(acilitate local customization; the directory)-.1 F F2(cf)3.158 E F1 +.397(of the)102 108 R F2(sendmail)2.897 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 .396(ral sub-).15 F +(directories:)102 120 Q 61.73(cf Both)102 136.2 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 148.2 +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 .535(descriptions \(such as \ +\231generic-solaris2.mc\232 as a general description of an SMTP-)174 +160.2 R 1.126(connected host running Solaris 2.x.)174 172.2 R 1.125 +(Files ending)6.126 F F0(.mc)3.625 E F1(\(`)3.625 E 1.125 +(`Master Con\214guration')-.74 F('\))-.74 E .516 +(are the input descriptions; the output is in the corresponding)174 +184.2 R F0(.cf)3.016 E F1 3.017(\214le. The)3.016 F(general)3.017 E +(structure of these \214les is described belo)174 196.2 Q -.65(w.)-.25 G +39.5(domain Site-dependent)102 212.4 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 .776(tion w)174 224.4 R .776 +(ants to do addressing.)-.1 F -.15(Fo)5.777 G 3.277(re).15 G(xample,) +-3.427 E F0(domain/CS.Berk)3.277 E(eley)-.1 E(.EDU)-.7 E(.m4)-.5 E F1 +.777(is our)3.277 F 1.188(description for hosts in the CS.Berk)174 236.4 +R(ele)-.1 E -.65(y.)-.15 G 1.188(EDU subdomain.).65 F 1.187 +(These are referenced)6.188 F(using the)174 248.4 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 264.6 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 276.6 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.763 +(use_cw_\214le \(which tells)174 288.6 R F2(sendmail)4.263 E F1 1.764 +(to read an /etc/mail/local-host-names \214le on)4.263 F +(startup to \214nd the set of local names\).)174 300.6 Q 50.62 +(hack Local)102 316.8 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 +328.8 Q(ving them here is to mak)-.2 E 2.5(ei)-.1 G 2.5(tc)-2.5 G +(lear that the)-2.5 E 2.5(ys)-.15 G(mell.)-2.5 E 56.72 +(m4 Site-independent)102 345 R F2(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 357 Q +(This can be thought of as a \231#include\232 directory)5 E(.)-.65 E +43.95(mailer De\214nitions)102 373.2 R .152 +(of mailers, referenced using the)2.653 F F3(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 385.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 397.2 S(ample, to include support for t\ +he UUCP-based mailers, use \231MAILER\(uucp\)\232.).15 E 43.39 +(ostype De\214nitions)102 413.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 425.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 441.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')-2.5 E 2.5(th)-.18 G -2.25 -.2(av e)-2.5 H(to mess with these.) +2.7 E 30.61(sitecon\214g Local)102 457.8 R .251(UUCP connecti)2.751 F +.251(vity information.)-.25 F .251 +(This directory has been supplanted by the)5.251 F 1.077 +(mailertable feature; an)174 469.8 R 3.577(yn)-.15 G 1.577 -.25(ew c) +-3.577 H 1.076(on\214gurations should use that feature to do UUCP).25 F +(\(and other\) routing.)174 481.8 Q .756(If you are in a ne)127 498 R +3.256(wd)-.25 G .756(omain \(e.g., a compan)-3.256 F .757 +(y\), you will probably w)-.15 F .757(ant to create a cf/domain)-.1 F +.051(\214le for your domain.)102 510 R .051 +(This consists primarily of relay de\214nitions and features you w)5.051 +F .05(ant enabled site-)-.1 F .915(wide: for e)102 522 R .915 +(xample, Berk)-.15 F(ele)-.1 E(y')-.15 E 3.415(sd)-.55 G .915 +(omain de\214nition de\214nes relays for BitNET and UUCP)-3.415 F 5.916 +(.T)-1.11 G .916(hese are)-5.916 F 1.52(speci\214c to Berk)102 534 R +(ele)-.1 E 2.819 -.65(y, a)-.15 H 1.519 +(nd should be fully-quali\214ed internet-style domain names.).65 F 1.519 +(Please check to)6.519 F(mak)102 546 Q 2.5(ec)-.1 G(ertain the)-2.5 E +2.5(ya)-.15 G(re reasonable for your domain.)-2.5 E 1.406 +(Subdomains at Berk)127 562.2 R(ele)-.1 E 3.906(ya)-.15 G 1.407 +(re also represented in the cf/domain directory)-3.906 F 6.407(.F)-.65 G +1.407(or e)-6.557 F 1.407(xample, the)-.15 F .356(domain CS.Berk)102 +574.2 R(ele)-.1 E -.65(y.)-.15 G .356 +(EDU is the Computer Science subdomain, EECS.Berk).65 F(ele)-.1 E -.65 +(y.)-.15 G .356(EDU is the Electri-).65 F 1.278 +(cal Engineering and Computer Sciences subdomain, and S2K.Berk)102 586.2 +R(ele)-.1 E -.65(y.)-.15 G 1.278(EDU is the Sequoia 2000).65 F 4.004 +(subdomain. Y)102 598.2 R 1.504(ou will probably ha)-1.1 F 1.804 -.15 +(ve t)-.2 H 4.004(oa).15 G 1.504 +(dd an entry to this directory to be appropriate for your)-4.004 F +(domain.)102 610.2 Q -1.1(Yo)127 626.4 S 4.372(uw)1.1 G 1.872(ill ha) +-4.372 F 2.172 -.15(ve t)-.2 H 4.372(ou).15 G 1.872(se or create)-4.372 +F 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 638.4 Q F0 2.5(1.3. Details)87 +662.4 R(of Installation Files)2.5 E F1 +(This subsection describes the \214les that comprise the)127 678.6 Q F2 +(sendmail)2.5 E F1(installation.)2.5 E EP +%%Page: 10 6 +%%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 2.5(1.3.1. /usr/sbin/sendmail) +102 96 R/F1 10/Times-Roman@0 SF .079(The binary for)142 114.2 R/F2 10 +/Times-Italic@0 SF(sendmail)2.579 E F1 .079(is located in /usr/sbin) +2.579 F/F3 7/Times-Roman@0 SF(1)-4 I F1 5.079(.I)4 K 2.579(ts)-5.079 G +.08(hould be setuid root.)-2.579 F -.15(Fo)5.08 G 2.58(rs).15 G .08 +(ecurity rea-)-2.58 F(sons, /, /usr)117 128.2 Q 2.5(,a)-.4 G +(nd /usr/sbin should be o)-2.5 E(wned by root, mode 755)-.25 E F3(2)-4 I +F1(.)4 I F0 2.5(1.3.2. /etc/mail/sendmail.cf)102 152.2 R F1 .966 +(This is the con\214guration \214le for)142 170.4 R F2(sendmail)3.466 E +F3(3)-4 I F1 5.966(.T)4 K .965 +(his is the only non-library \214le name com-)-5.966 F(piled into)117 +184.4 Q F2(sendmail)2.5 E F3(4)-4 I F1(.)4 I .721 +(The con\214guration \214le is normally created using the distrib)142 +200.6 R .721(ution \214les described abo)-.2 F -.15(ve)-.15 G 5.72(.I) +.15 G(f)-5.72 E .64(you ha)117 212.6 R .94 -.15(ve a p)-.2 H .64(articu\ +larly 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 sec\ +tions of this document.)117 224.6 Q F0 2.5(1.3.3. /usr/bin/newaliases) +102 248.6 R F1(The)142 264.8 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 281 Q -.1(wa)-.25 G(liases).1 E +(ln \255s /usr/sbin/sendmail /usr/bin/ne)157 293 Q -.1(wa)-.25 G(liases) +.1 E(This can be installed in whate)117 309.2 Q -.15(ve)-.25 G 2.5(rs) +.15 G(earch path you prefer for your system.)-2.5 E F0 2.5 +(1.3.4. /usr/bin/hoststat)102 333.2 R F1(The)142 349.4 Q F2(hoststat) +5.845 E F1 3.344(command should just be a link to)5.845 F F2(sendmail) +5.844 E F1 5.844(,i)C 5.844(naf)-5.844 G 3.344(ashion similar to)-5.944 +F F2(ne)117 361.4 Q(waliases)-.15 E F1 6.443(.T)C 1.444(his command lis\ +ts the status of the last mail transaction with all remote hosts.)-6.443 +F(The)117 373.4 Q F03.857 E F1 1.357(\215ag will pre)3.857 F -.15 +(ve)-.25 G 1.357(nt the status display from being truncated.).15 F 1.356 +(It functions only when the)6.356 F F0(HostStatusDir)117 385.4 Q(ectory) +-.18 E F1(option is set.)2.5 E F0 2.5(1.3.5. /usr/bin/pur)102 409.4 R +(gestat)-.1 E F1 .993(This command is also a link to)142 425.6 R F2 +(sendmail)3.493 E F1 5.993(.I)C 3.493<748d>-5.993 G .993 +(ushes all information that is stored in the)-3.493 F F0(HostStatusDir) +117 437.6 Q(ectory)-.18 E F1(tree.)2.5 E F0 2.5(1.3.6. /v)102 461.6 R +(ar/spool/mqueue)-.1 E F1 .218(The directory)142 477.8 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 489.8 Q(wned by root.)-.25 E .395 +(The actual path of this directory is de\214ned in the)142 506 R F0(Q) +2.895 E F1 .395(option of the)2.895 F F2(sendmail.cf)2.896 E F1 2.896 +(\214le. T)2.896 F 2.896(ou)-.8 G(se)-2.896 E 1.472 +(multiple queues, supply a v)117 518 R 1.472 +(alue ending with an asterisk.)-.25 F -.15(Fo)6.472 G 3.971(re).15 G +(xample,)-4.121 E F2(/var/spool/mqueue/q*)3.971 E F1 4.203 +(will use all of the directories or symbolic links to directories be)117 +530 R 4.203(ginning with `q' in)-.15 F F2(/var/spool/mqueue)117 542 Q F1 +2.083(as queue directories.)4.583 F 2.083 +(Do not change the queue directory structure while)7.083 F +(sendmail is running.)117 554 Q .897(If these directories ha)142 570.2 R +1.197 -.15(ve s)-.2 H .898 +(ubdirectories or symbolic links to directories named `qf).15 F .898 +(', `df).55 F(',).55 E 1.241(and `xf)117 582.2 R 1.241 +(', then these will be used for the dif).55 F 1.24 +(ferent queue \214le types.)-.25 F 1.24(That is, the data \214les are) +6.24 F .32 LW 76 591.8 72 591.8 DL 80 591.8 76 591.8 DL 84 591.8 80 +591.8 DL 88 591.8 84 591.8 DL 92 591.8 88 591.8 DL 96 591.8 92 591.8 DL +100 591.8 96 591.8 DL 104 591.8 100 591.8 DL 108 591.8 104 591.8 DL 112 +591.8 108 591.8 DL 116 591.8 112 591.8 DL 120 591.8 116 591.8 DL 124 +591.8 120 591.8 DL 128 591.8 124 591.8 DL 132 591.8 128 591.8 DL 136 +591.8 132 591.8 DL 140 591.8 136 591.8 DL 144 591.8 140 591.8 DL 148 +591.8 144 591.8 DL 152 591.8 148 591.8 DL 156 591.8 152 591.8 DL 160 +591.8 156 591.8 DL 164 591.8 160 591.8 DL 168 591.8 164 591.8 DL 172 +591.8 168 591.8 DL 176 591.8 172 591.8 DL 180 591.8 176 591.8 DL 184 +591.8 180 591.8 DL 188 591.8 184 591.8 DL 192 591.8 188 591.8 DL 196 +591.8 192 591.8 DL 200 591.8 196 591.8 DL 204 591.8 200 591.8 DL 208 +591.8 204 591.8 DL 212 591.8 208 591.8 DL 216 591.8 212 591.8 DL/F4 5 +/Times-Roman@0 SF(1)93.6 602.2 Q/F5 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)-2.385 F 4.384 +(.I)-.32 G .384(understand it is in /usr/ucblib on)-2 F +(System V Release 4.)72 615 Q F4(2)93.6 625.4 Q F5 .15(Some v)3.2 J .15 +(endors ship them o)-.12 F .15(wned by bin; this creates a security hol\ +e that is not actually related to)-.2 F/F6 8/Times-Italic@0 SF(sendmail) +2.15 E F5 4.15(.O)C .149(ther important di-)-4.15 F +(rectories that should ha)72 638.2 Q .24 -.12(ve r)-.16 H(estricti).12 E +.24 -.12(ve o)-.2 H(wnerships and permissions are /bin, /usr/bin, /etc,\ + /etc/mail, /usr/etc, /lib, and /usr/lib)-.08 E(.)-.32 E F4(3)93.6 648.6 +Q F5(Actually)3.2 I 2.332(,t)-.52 G .332(he pathname v)-2.332 F .332(ar\ +ies depending on the operating system; /etc/mail is the preferred direc\ +tory)-.2 F 4.332(.S)-.52 G .332(ome older systems in-)-4.332 F 1.487 +(stall it in)72 661.4 R/F7 8/Times-Bold@0 SF(/usr/lib/sendmail.cf)3.487 +E F5 3.487(,a)C 1.487(nd I')-3.487 F 1.727 -.12(ve a)-.4 H 1.486 +(lso seen it in).12 F F7(/usr/ucblib)3.486 E F5 5.486(.I)C 3.486(fy) +-5.486 G 1.486(ou w)-3.486 F 1.486(ant to mo)-.08 F 1.726 -.12(ve t)-.12 +H 1.486(his \214le, add -D_P).12 F -.888(AT)-.736 G(H_SENDMAIL-).888 E +.093(CF=\\"/\214le/name\\" to the \215ags passed to the C compiler)72 +671 R 4.093(.M)-.44 G -.12(ov)-4.093 G .093 +(ing this \214le is not recommended: other programs and scripts kno).12 +F 2.093(wo)-.2 G 2.093(ft)-2.093 G(his)-2.093 E(location.)72 680.6 Q F4 +(4)93.6 691 Q F5 .588 +(The system libraries can reference other \214les; in particular)3.2 J +2.589(,s)-.32 G .589(ystem library subroutines that)-2.589 F F6 +(sendmail)2.589 E F5 .589(calls probably reference)2.589 F F6 +(/etc/passwd)72 703.8 Q F5(and)2 E F6(/etc/r)2 E(esolv)-.296 E(.conf) +-.592 E F5(.)A EP +%%Page: 11 7 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-11)195.86 E/F1 10/Times-Roman@0 SF .246(stored in the `df)117 96 +R 2.746('s).55 G(ubdirectory)-2.746 E 2.746(,t)-.65 G .246 +(he transcript \214les are stored in the `xf)-2.746 F 2.747('s).55 G +(ubdirectory)-2.747 E 2.747(,a)-.65 G .247(nd all oth-)-2.747 F +(ers are stored in the `qf)117 108 Q 2.5('s).55 G(ubdirectory)-2.5 E(.) +-.65 E F0 2.5(1.3.7. /v)102 132 R(ar/spool/mqueue/.hoststat)-.1 E F1 +1.045(This is a typical v)142 148.2 R 1.045(alue for the)-.25 F F0 +(HostStatusDir)3.545 E(ectory)-.18 E F1 1.044 +(option, containing one \214le per host)3.545 F +(that this sendmail has chatted with recently)117 160.2 Q 5(.I)-.65 G +2.5(ti)-5 G 2.5(sn)-2.5 G(ormally a subdirectory of)-2.5 E/F2 10 +/Times-Italic@0 SF(mqueue)2.5 E F1(.)A F0 2.5(1.3.8. /etc/mail/aliases*) +102 184.2 R F1 .019 +(The system aliases are held in \231/etc/mail/aliases\232.)142 200.4 R +2.519(As)5.019 G .019(ample is gi)-2.519 F -.15(ve)-.25 G 2.52(ni).15 G +2.52<6e99>-2.52 G(sendmail/aliases\232)-2.52 E +(which includes some aliases which)117 212.4 Q F2(must)2.5 E F1 +(be de\214ned:)2.5 E(cp lib/aliases /etc/mail/aliases)157 228.6 Q F2 +(edit /etc/mail/aliases)157 240.6 Q F1 -1.1(Yo)117 256.8 S 2.5(us)1.1 G +(hould e)-2.5 E(xtend this \214le with an)-.15 E 2.5(ya)-.15 G +(liases that are apropos to your system.)-2.5 E(Normally)142 273 Q F2 +(sendmail)7.984 E F1 5.484(looks at a database v)7.984 F 5.483 +(ersion of the \214les, stored either in)-.15 F 1.089(\231/etc/mail/ali\ +ases.dir\232 and \231/etc/mail/aliases.pag\232 or \231/etc/mail/aliases\ +.db\232 depending on which)117 285 R .203 +(database package you are using.)117 297 R .202 +(The actual path of this \214le is de\214ned in the)5.203 F F0 +(AliasFile)2.702 E F1 .202(option of)2.702 F(the)117 309 Q F2 +(sendmail.cf)2.5 E F1(\214le.)2.5 E F0 2.5(1.3.9. /etc/r)102 333 R 2.5 +(co)-.18 G 2.5(r/)-2.5 G(etc/init.d/sendmail)-2.5 E F1 .155 +(It will be necessary to start up the)142 349.2 R F2(sendmail)2.655 E F1 +.156(daemon when your system reboots.)2.655 F .156(This dae-)5.156 F +1.538(mon performs tw)117 361.2 R 4.037(of)-.1 G 1.537 +(unctions: it listens on the SMTP sock)-4.037 F 1.537 +(et for connections \(to recei)-.1 F 1.837 -.15(ve m)-.25 H(ail).15 E +.442(from a remote system\) and it processes the queue periodically to \ +insure that mail gets deli)117 373.2 R -.15(ve)-.25 G(red).15 E +(when hosts come up.)117 385.2 Q .505(Add the follo)142 401.4 R .505(wi\ +ng lines to \231/etc/rc\232 \(or \231/etc/rc.local\232 as appropriate\)\ + in the area where it)-.25 F .375 +(is starting up the daemons on a BSD-base system, or on a System-V)117 +413.4 R .375(-based system in one of the)-1 F +(startup \214les, typically \231/etc/init.d/sendmail\232:)117 425.4 Q(i\ +f [ \255f /usr/sbin/sendmail \255a \255f /etc/mail/sendmail.cf ]; then) +157 441.6 Q(\(cd /v)193 453.6 Q(ar/spool/mqueue; rm \255f [lnx]f*\))-.25 +E(/usr/sbin/sendmail \255bd \255q30m &)193 465.6 Q +(echo \255n ' sendmail' >/de)193 477.6 Q(v/console)-.25 E<8c>157 489.6 Q +.174 +(The \231cd\232 and \231rm\232 commands insure that all lock \214les ha) +117 505.8 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 517.8 R .005 +(wn in the middle of processing a message.)-.25 F .005(The line that) +5.005 F 2.294(actually in)117 529.8 R -.2(vo)-.4 G -.1(ke).2 G(s).1 E F2 +(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)-4.794 F +(\231\255q30m\232 causes it to run the queue e)117 541.8 Q -.15(ve)-.25 +G(ry half hour).15 E(.)-.55 E .378(Some people use a more comple)142 558 +R 2.879(xs)-.15 G .379(tartup script, remo)-2.879 F .379 +(ving zero length qf \214les and df \214les)-.15 F 1.399 +(for which there is no qf \214le.)117 570 R -.15(Fo)6.398 G 3.898(re).15 +G 1.398(xample, see Figure 1 for an e)-4.048 F 1.398(xample of a comple) +-.15 F 3.898(xs)-.15 G(cript)-3.898 E(which does this clean up.)117 582 +Q .755(If you are not running a v)142 598.2 R .755 +(ersion of UNIX that supports Berk)-.15 F(ele)-.1 E 3.256(yT)-.15 G +(CP/IP)-3.256 E 3.256(,d)-1.11 G 3.256(on)-3.256 G .756(ot include) +-3.256 F(the)117 610.2 Q F0(\255bd)2.5 E F1(\215ag.)2.5 E F0 2.5 +(1.3.10. /etc/mail/help\214le)102 634.2 R F1 .161 +(This is the help \214le used by the SMTP)142 650.4 R F0(HELP)2.661 E F1 +2.66(command. It)2.661 F .16(should be copied from \231send-)2.66 F +(mail/help\214le\232:)117 662.4 Q +(cp sendmail/help\214le /etc/mail/help\214le)157 678.6 Q +(The actual path of this \214le is de\214ned in the)117 694.8 Q F0 +(HelpFile)2.5 E F1(option of the)2.5 E F2(sendmail.cf)2.5 E F1(\214le.) +2.5 E EP +%%Page: 12 8 +%%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(#!/bin/sh)72 132 Q 2.5 +(#r)72 144 S(emo)-2.5 E .3 -.15(ve z)-.15 H(ero length qf \214les).15 E +(for qf)72 156 Q(\214le in qf*)-.25 E(do)72 168 Q(if [ \255r $qf)108 180 +Q(\214le ])-.25 E(then)108 192 Q(if [ ! \255s $qf)144 204 Q(\214le ]) +-.25 E(then)144 216 Q(echo \255n " " > /de) +-.25 E(v/console)-.25 E(rm \255f $qf)180 240 Q(\214le)-.25 E<8c>144 252 +Q<8c>108 264 Q(done)72 276 Q 2.5(#r)72 288 S +(ename tf \214les to be qf if the qf does not e)-2.5 E(xist)-.15 E +(for tf)72 300 Q(\214le in tf*)-.25 E(do)72 312 Q(qf)108 324 Q +(\214le=`echo $tf)-.25 E(\214le | sed ')-.25 E(s/t/q/'`)-.55 E +(if [ \255r $tf)108 336 Q(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 +E(then)108 348 Q(echo \255n " " > /de)-.25 E(v/console)-.25 E(mv $tf)144 372 Q +(\214le $qf)-.25 E(\214le)-.25 E(else)108 384 Q(if [ \255f $tf)144 396 Q +(\214le ])-.25 E(then)144 408 Q(echo \255n " " > /de)-.25 E(v/console)-.25 E(rm \255f $tf)180 432 Q(\214le) +-.25 E<8c>144 444 Q<8c>108 456 Q(done)72 468 Q 2.5(#r)72 480 S(emo)-2.5 +E .3 -.15(ve d)-.15 H 2.5<668c>.15 G +(les with no corresponding qf \214les)-2.5 E(for df)72 492 Q +(\214le in df*)-.25 E(do)72 504 Q(qf)108 516 Q(\214le=`echo $df)-.25 E +(\214le | sed ')-.25 E(s/d/q/'`)-.55 E(if [ \255r $df)108 528 Q +(\214le \255a ! \255f $qf)-.25 E(\214le ])-.25 E(then)108 540 Q +(echo \255n " " > /de)-.25 E +(v/console)-.25 E(mv $df)144 564 Q(\214le `echo $df)-.25 E +(\214le | sed ')-.25 E(s/d/D/'`)-.55 E<8c>108 576 Q(done)72 588 Q 2.5 +(#a)72 600 S(nnounce \214les that ha)-2.5 E .3 -.15(ve b)-.2 H(een sa) +.15 E -.15(ve)-.2 G 2.5(dd).15 G(uring disaster reco)-2.5 E -.15(ve)-.15 +G(ry).15 E(for xf)72 612 Q(\214le in [A-Z]f*)-.25 E(do)72 624 Q +(if [ \255f $xf)108 636 Q(\214le ])-.25 E(then)108 648 Q +(echo \255n " " > /de)-.25 E(v/console)-.25 +E<8c>108 672 Q(done)72 684 Q(Figure 1 \212 A comple)214.47 708 Q 2.5(xs) +-.15 G(tartup script)-2.5 E 77 720 72 720 DL 79 720 74 720 DL 84 720 79 +720 DL 89 720 84 720 DL 94 720 89 720 DL 99 720 94 720 DL 104 720 99 720 +DL 109 720 104 720 DL 114 720 109 720 DL 119 720 114 720 DL 124 720 119 +720 DL 129 720 124 720 DL 134 720 129 720 DL 139 720 134 720 DL 144 720 +139 720 DL 149 720 144 720 DL 154 720 149 720 DL 159 720 154 720 DL 164 +720 159 720 DL 169 720 164 720 DL 174 720 169 720 DL 179 720 174 720 DL +184 720 179 720 DL 189 720 184 720 DL 194 720 189 720 DL 199 720 194 720 +DL 204 720 199 720 DL 209 720 204 720 DL 214 720 209 720 DL 219 720 214 +720 DL 224 720 219 720 DL 229 720 224 720 DL 234 720 229 720 DL 239 720 +234 720 DL 244 720 239 720 DL 249 720 244 720 DL 254 720 249 720 DL 259 +720 254 720 DL 264 720 259 720 DL 269 720 264 720 DL 274 720 269 720 DL +279 720 274 720 DL 284 720 279 720 DL 289 720 284 720 DL 294 720 289 720 +DL 299 720 294 720 DL 304 720 299 720 DL 309 720 304 720 DL 314 720 309 +720 DL 319 720 314 720 DL 324 720 319 720 DL 329 720 324 720 DL 334 720 +329 720 DL 339 720 334 720 DL 344 720 339 720 DL 349 720 344 720 DL 354 +720 349 720 DL 359 720 354 720 DL 364 720 359 720 DL 369 720 364 720 DL +374 720 369 720 DL 379 720 374 720 DL 384 720 379 720 DL 389 720 384 720 +DL 394 720 389 720 DL 399 720 394 720 DL 404 720 399 720 DL 409 720 404 +720 DL 414 720 409 720 DL 419 720 414 720 DL 424 720 419 720 DL 429 720 +424 720 DL 434 720 429 720 DL 439 720 434 720 DL 444 720 439 720 DL 449 +720 444 720 DL 454 720 449 720 DL 459 720 454 720 DL 464 720 459 720 DL +469 720 464 720 DL 474 720 469 720 DL 479 720 474 720 DL 484 720 479 720 +DL 489 720 484 720 DL 494 720 489 720 DL 499 720 494 720 DL 504 720 499 +720 DL EP +%%Page: 13 9 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-13)195.86 E 2.5(1.3.11. /etc/mail/statistics)102 96 R/F1 10 +/Times-Roman@0 SF 3.04 +(If you wish to collect statistics about your mail traf)142 112.2 R 3.04 +(\214c, you should create the \214le)-.25 F +(\231/etc/mail/statistics\232:)117 124.2 Q(cp /de)157 140.4 Q +(v/null /etc/mail/statistics)-.25 E(chmod 644 /etc/mail/statistics)157 +152.4 Q .716(This \214le does not gro)117 168.6 R 4.516 -.65(w. I)-.25 H +3.216(ti).65 G 3.216(sp)-3.216 G .716 +(rinted with the program \231mailstats/mailstats.c.)-3.216 F 5.715<9a54> +-.7 G .715(he actual path)-5.715 F(of this \214le is de\214ned in the) +117 180.6 Q F0(S)2.5 E F1(option of the)2.5 E/F2 10/Times-Italic@0 SF +(sendmail.cf)2.5 E F1(\214le.)2.5 E F0 2.5(1.3.12. /usr/bin/mailq)102 +204.6 R F1(If)142 220.8 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>-3.439 G(mailq,)-3.439 E +3.439<9a69>-.7 G 3.439(tw)-3.439 G .939(ill simulate the)-3.439 F 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 232.8 Q +2.5(w\). This)-.25 F(should be a link to /usr/sbin/sendmail.)2.5 E F0 +2.5(2. NORMAL)72 256.8 R(OPERA)2.5 E(TIONS)-.95 E 2.5(2.1. The)87 280.8 +R(System Log)2.5 E F1 1.511(The system log is supported by the)127 297 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 311 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)-4 I F1(.)4 I F0 2.5 +(2.1.1. F)102 335 R(ormat)-.25 E F1 .574(Each line in the system log co\ +nsists of a timestamp, the name of the machine that gener)142 351.2 R(-) +-.2 E .849(ated it \(for logging from se)117 363.2 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)-3.349 F .848(ork\), the w)-.1 F .848 +(ord \231sendmail:\232,)-.1 F(and a message)117 377.2 Q F4(6)-4 I F1 5 +(.M)4 K(ost messages are a sequence of)-5 E F2(name)2.5 E F1(=)A F2 +(value)A F1(pairs.)2.5 E .68(The tw)142 393.4 R 3.18(om)-.1 G .68 +(ost common lines are logged when a message is processed.)-3.18 F .68 +(The \214rst logs the)5.68 F .376(receipt of a message; there will be e) +117 405.4 R .376(xactly one of these per message.)-.15 F .376 +(Some \214elds may be omit-)5.376 F(ted if the)117 417.4 Q 2.5(yd)-.15 G +2.5(on)-2.5 G(ot contain interesting information.)-2.5 E(Fields are:)5 E +50.06(from The)117 433.6 R(en)2.5 E -.15(ve)-.4 G(lope sender address.) +.15 E 53.95(size The)117 449.8 R(size of the message in bytes.)2.5 E +50.06(class The)117 466 R +(class \(i.e., numeric precedence\) of the message.)2.5 E 58.39(pri The) +117 482.2 R(initial message priority \(used for queue sorting\).)2.5 E +45.06(nrcpts The)117 498.4 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 510.4 S(rding\).).1 E 45.05(msgid The)117 526.6 R +(message id of the message \(from the header\).)2.5 E 48.39(proto The) +117 542.8 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 559 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 575.2 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 587.2 Q +(Fields are:)5 E 61.72(to A)117 603.4 R +(comma-separated list of the recipients to this mailer)2.5 E(.)-.55 E +41.73(ctladdr The)117 619.6 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 631.6 Q -.15(ve)-.25 G(ry).15 E(.)-.65 E 47.84(delay The) +117 647.8 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) +-3.803 F -.1(wa)189 659.8 S 2.5(sd).1 G(eli)-2.5 E -.15(ve)-.25 G(red.) +.15 E .32 LW 76 669.4 72 669.4 DL 80 669.4 76 669.4 DL 84 669.4 80 669.4 +DL 88 669.4 84 669.4 DL 92 669.4 88 669.4 DL 96 669.4 92 669.4 DL 100 +669.4 96 669.4 DL 104 669.4 100 669.4 DL 108 669.4 104 669.4 DL 112 +669.4 108 669.4 DL 116 669.4 112 669.4 DL 120 669.4 116 669.4 DL 124 +669.4 120 669.4 DL 128 669.4 124 669.4 DL 132 669.4 128 669.4 DL 136 +669.4 132 669.4 DL 140 669.4 136 669.4 DL 144 669.4 140 669.4 DL 148 +669.4 144 669.4 DL 152 669.4 148 669.4 DL 156 669.4 152 669.4 DL 160 +669.4 156 669.4 DL 164 669.4 160 669.4 DL 168 669.4 164 669.4 DL 172 +669.4 168 669.4 DL 176 669.4 172 669.4 DL 180 669.4 176 669.4 DL 184 +669.4 180 669.4 DL 188 669.4 184 669.4 DL 192 669.4 188 669.4 DL 196 +669.4 192 669.4 DL 200 669.4 196 669.4 DL 204 669.4 200 669.4 DL 208 +669.4 204 669.4 DL 212 669.4 208 669.4 DL 216 669.4 212 669.4 DL/F5 5 +/Times-Roman@0 SF(5)93.6 679.8 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 693.4 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: 14 10 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-14 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 42.84 +(xdelay The)117 96 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)-2.616 E(speed of the connection\).)189 108 Q +43.95(mailer The)117 124.2 R(name of the mailer used to deli)2.5 E -.15 +(ve)-.25 G 2.5(rt).15 G 2.5(ot)-2.5 G(his recipient.)-2.5 E 49.51 +(relay The)117 140.4 R(name of the host that actually accepted \(or rej\ +ected\) this recipient.)2.5 E 55.61(stat The)117 156.6 R(deli)2.5 E -.15 +(ve)-.25 G(ry status.).15 E +(Not all \214elds are present in all messages; for e)117 172.8 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 196.8 R -.1(ve)-.15 G(ls).1 E F1 .205 +(If you ha)142 213 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 225 S(ar)-2.787 E .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 237 R .651(west le)-.25 F -.15(ve)-.25 G 3.151 +(lo).15 G .651(nly e)-3.151 F .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) +-3.15 E .825(most mundane and uninteresting e)117 249 R -.15(ve)-.25 G +.825(nts are recorded for posterity).15 F 5.826(.A)-.65 G 3.326(sac) +-5.826 G(on)-3.326 E -.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 261 R +-.15(ve)-.25 G .201(ls abo).15 F .501 -.15(ve 6)-.15 H 2.701(4a).15 G .2 +(re reserv)-2.701 F .2(ed for deb)-.15 F .2(ugging pur)-.2 F(-)-.2 E 2.5 +(poses. Le)117 273 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 289.2 S(omplete description of the log le)-2.5 E -.15 +(ve)-.25 G(ls is gi).15 E -.15(ve)-.25 G 2.5(ni).15 G 2.5(ns)-2.5 G +(ection 4.6.)-2.5 E F0 2.5(2.2. Dumping)87 313.2 R(State)2.5 E F1 -1.1 +(Yo)127 329.4 S 2.563(uc)1.1 G .063(an ask)-2.563 F F2(sendmail)2.563 E +F1 .064(to log a dump of the open \214les and the connection cache by s\ +ending it a)2.563 F/F3 9/Times-Roman@0 SF(SIGUSR1)102 341.4 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 365.4 R(Mail Queue)2.5 E +F1 1.283(Sometimes a host cannot handle a message immediately)127 381.6 +R 6.283(.F)-.65 G 1.283(or e)-6.433 F 1.283(xample, it may be do)-.15 F +1.282(wn or)-.25 F -.15(ove)102 393.6 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 405.6 Q -.15(ve)-.25 G 2.5 +(ri).15 G 2.5(tl)-2.5 G(ater)-2.5 E(.)-.55 E .568 +(Under normal conditions the mail queue will be processed transparently) +127 421.8 R 5.568(.H)-.65 G -.25(ow)-5.568 G -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 433.8 +R .993(ention is sometimes necessary)-.15 F 5.993(.F)-.65 G .993(or e) +-6.143 F .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 445.8 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)-4.199 E(when the host comes up, you may \ +\214nd performance unacceptably bad in the meantime.)102 457.8 Q F0 2.5 +(2.3.1. Printing)102 481.8 R(the queue)2.5 E F1 .526 +(The contents of the queue can be printed using the)142 498 R F2(mailq) +3.026 E F1 .526(command \(or by specifying the)3.026 F F0(\255bp)117 510 +Q F1(\215ag to)2.5 E F2(sendmail)2.5 E F1(\):)A(mailq)157 526.2 Q 1.673 +(This will produce a listing of the queue id')117 542.4 R 1.673 +(s, the size of the message, the date the message)-.55 F +(entered the queue, and the sender and recipients.)117 554.4 Q F0 2.5 +(2.3.2. F)102 578.4 R(or)-.25 E(cing the queue)-.18 E F2(Sendmail)142 +594.6 Q F1 .352(should run the queue automatically at interv)2.852 F +2.853(als. When)-.25 F .353(using multiple queues, a)2.853 F .517(separ\ +ate process will be created to run each of the queues unless the queue \ +run is initiated by a)117 606.6 R .723(user with the v)117 618.6 R .724 +(erbose \215ag.)-.15 F .724 +(The algorithm is to read and sort the queue, and then to attempt to) +5.724 F .37(process all jobs in order)117 630.6 R 5.37(.W)-.55 G .37 +(hen it attempts to run the job,)-5.37 F F2(sendmail)2.87 E F1 .37 +(\214rst checks to see if the job)2.87 F(is lock)117 642.6 Q 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 658.8 +R .338(xists at an)-.15 F 2.838(yt)-.15 G .339(ime, since there)-2.838 F +.095(is no guarantee that a job cannot tak)117 670.8 R 2.595(ef)-.1 G +(ore)-2.595 E -.15(ve)-.25 G 2.595(rt).15 G 2.595(op)-2.595 G .094 +(rocess \(ho)-2.595 F(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 682.8 R +3.587(,t)-.65 G 1.087(his violates RFC)-3.587 F .462(821, b)117 694.8 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 706.8 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)-3.586 E 1.386 -.15 +(ve r)-.25 H 1.086(ecipient host or a program recipient that).15 F(ne) +117 718.8 Q -.15(ve)-.25 G 5.343(rr).15 G 2.843 +(eturns can accumulate man)-5.343 F 5.343(yp)-.15 G 2.842 +(rocesses in your system.)-5.343 F(Unfortunately)7.842 E 5.342(,t)-.65 G +2.842(here is no)-5.342 F EP +%%Page: 15 11 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-15)195.86 E/F1 10/Times-Roman@0 SF(completely general w)117 96 Q +(ay to solv)-.1 E 2.5(et)-.15 G(his.)-2.5 E .082 +(In some cases, you may \214nd that a major host going do)142 112.2 R +.083(wn for a couple of days may create)-.25 F 2.925(ap)117 124.2 S +(rohibiti)-2.925 E -.15(ve)-.25 G .425(ly lar).15 F .425(ge queue.)-.18 +F .424(This will result in)5.425 F/F2 10/Times-Italic@0 SF(sendmail) +2.924 E F1 .424(spending an inordinate amount of time)2.924 F 1.084 +(sorting the queue.)117 136.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 148.2 R 2.523(wq)-.25 G 2.523(ueue. The) +-2.523 F .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 164.4 T 2.5 +(ot).8 G(his, it is acceptable to mo)-2.5 E .3 -.15(ve t)-.15 H +(he entire queue directory:).15 E(cd /v)157 180.6 Q(ar/spool)-.25 E +(mv mqueue omqueue; mkdir mqueue; chmod 700 mqueue)157 192.6 Q -1.1(Yo) +117 208.8 S 2.708(us)1.1 G .208(hould then kill the e)-2.708 F .209(xis\ +ting daemon \(since it will still be processing in the old queue direc-) +-.15 F(tory\) and create a ne)117 220.8 Q 2.5(wd)-.25 G(aemon.)-2.5 E +1.6 -.8(To r)142 237 T(un the old mail queue, run the follo).8 E +(wing command:)-.25 E(/usr/sbin/sendmail \255oQ/v)157 253.2 Q +(ar/spool/omqueue \255q)-.25 E(The)117 269.4 Q F0(\255oQ)2.868 E F1 .367 +(\215ag speci\214es an alternate queue directory and the)2.868 F F0 +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 281.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) +-3.093 H .593(rd v).25 F -.1(oy)-.2 G .593(eurism, you can use the).1 F +F03.094 E F1 .594(\215ag to w)3.094 F .594(atch what is)-.1 F +(going on.)117 293.4 Q +(When the queue is \214nally emptied, you can remo)142 309.6 Q .3 -.15 +(ve t)-.15 H(he directory:).15 E(rmdir /v)157 325.8 Q(ar/spool/omqueue) +-.25 E F0 2.5(2.4. Disk)87 354 R(Based Connection Inf)2.5 E(ormation) +-.25 E F2(Sendmail)127 370.2 Q F1 .597(stores a lar)3.097 F .596 +(ge amount of information about each remote system it has connected to) +-.18 F 1.127(in memory)102 382.2 R 3.627(.I)-.65 G 3.627(ti)-3.627 G +3.627(sn)-3.627 G 1.627 -.25(ow p)-3.627 H 1.127(ossible to preserv).25 +F 3.627(es)-.15 G 1.127 +(ome of this information on disk as well, by using the)-3.627 F F0 +(HostStatusDir)102 394.2 Q(ectory)-.18 E F1 1.705 +(option, so that it may be shared between se)4.205 F -.15(ve)-.25 G +1.705(ral in).15 F -.2(vo)-.4 G 1.705(cations of).2 F F2(sendmail)4.205 +E F1(.)A .283(This allo)102 406.2 R .283(ws mail to be queued immediate\ +ly or skipped during a queue run if there has been a recent)-.25 F -.1 +(fa)102 418.2 S(ilure in connecting to a remote machine.).1 E 1.439 +(Additionally enabling)127 434.4 R F0(SingleThr)3.939 E(eadDeli)-.18 E +-.1(ve)-.1 G(ry).1 E F1 1.439(has the added ef)3.939 F 1.439 +(fect of single-threading mail)-.25 F(deli)102 446.4 Q -.15(ve)-.25 G +1.61(ry to a destination.).15 F 1.611 +(This can be quite helpful if the remote machine is running an SMTP)6.61 +F(serv)102 458.4 Q 1.011(er that is easily o)-.15 F -.15(ve)-.15 G 1.011 +(rloaded or cannot accept more than a single connection at a time, b).15 +F 1.01(ut can)-.2 F .458 +(cause some messages to be punted to a future queue run.)102 470.4 R +.458(It also applies to)5.458 F F2(all)2.958 E F1 .458 +(hosts, so setting this)2.958 F .282(because you ha)102 482.4 R .582 +-.15(ve o)-.2 H .281(ne machine on site that runs some softw).15 F .281 +(are that is easily o)-.1 F -.15(ve)-.15 G .281(rrun can cause mail).15 +F .315(to other hosts to be slo)102 494.4 R .315(wed do)-.25 F 2.815 +(wn. If)-.25 F .315(this option is set, you probably w)2.815 F .315 +(ant to set the)-.1 F F0(MinQueueAge)2.815 E F1 .872 +(option as well and run the queue f)102 506.4 R .871 +(airly frequently; this w)-.1 F .871 +(ay jobs that are skipped because another)-.1 F F2(sendmail)102 518.4 Q +F1 .363(is talking to the same host will be tried ag)2.863 F .364 +(ain quickly rather than being delayed for a long)-.05 F(time.)102 530.4 +Q 1.099 +(The disk based host information is stored in a subdirectory of the)127 +546.6 R F0(mqueue)3.598 E F1 1.098(directory called)3.598 F F0 +(.hoststat)102 560.6 Q/F3 7/Times-Roman@0 SF(7)-4 I F1 6.749(.R)4 K(emo) +-6.749 E 1.749(ving this directory and its subdirectories has an ef)-.15 +F 1.75(fect similar to the)-.25 F F2(pur)4.25 E -.1(ge)-.37 G(stat).1 E +F1 .046(command and is completely safe.)102 572.6 R .045 +(The information in these directories can be perused with the)5.046 F F2 +(host-)2.545 E(stat)102 584.6 Q F1 .513(command, which will indicate th\ +e host name, the last access, and the status of that access.)3.012 F(An) +5.513 E .69(asterisk in the left most column indicates that a)102 596.6 +R F2(sendmail)3.19 E F1 .69(process currently has the host lock)3.19 F +.69(ed for)-.1 F(mail deli)102 608.6 Q -.15(ve)-.25 G(ry).15 E(.)-.65 E +.53(The disk based connection information is treated the same w)127 +624.8 R .53(ay as memory based connection)-.1 F .536 +(information for the purpose of timeouts.)102 636.8 R .536(By def)5.536 +F .536(ault, information about host f)-.1 F .536(ailures is v)-.1 F .536 +(alid for 30)-.25 F 2.5(minutes. This)102 648.8 R +(can be adjusted with the)2.5 E F0 -.18(Ti)2.5 G(meout.hoststatus).18 E +F1(option.)2.5 E .022 +(The connection information stored on disk may be pur)127 665 R .023 +(ged at an)-.18 F 2.523(yt)-.15 G .023(ime with the)-2.523 F F2(pur) +2.523 E -.1(ge)-.37 G(stat).1 E F1(com-)2.523 E .95(mand or by in)102 +677 R -.2(vo)-.4 G .949(king sendmail with the).2 F F0(\255bH)3.449 E F1 +3.449(switch. The)3.449 F .949(connection information may be vie)3.449 F +(wed)-.25 E .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(7)93.6 697 Q/F5 8/Times-Roman@0 SF +(This is the usual v)3.2 I(alue of the)-.2 E/F6 8/Times-Bold@0 SF +(HostStatusDir)2 E(ectory)-.144 E F5(option; it can, of course, go an)2 +E(ywhere you lik)-.12 E 2(ei)-.08 G 2(ny)-2 G(our \214lesystem.)-2 E EP +%%Page: 16 12 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-16 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(with the) +102 96 Q/F2 10/Times-Italic@0 SF(hoststat)2.5 E F1(command or by in)2.5 +E -.2(vo)-.4 G(king sendmail with the).2 E F0(\255bh)2.5 E F1(switch.) +2.5 E F0 2.5(2.5. The)87 120 R(Ser)2.5 E(vice Switch)-.1 E F1 1.416(The\ + implementation of certain system services such as host and user name l\ +ookup is con-)127 136.2 R .336(trolled by the service switch.)102 148.2 +R .336(If the host operating system supports such a switch)5.336 F F2 +(sendmail)2.835 E F1 .335(will use)2.835 F(the nati)102 162.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/F3 7/Times-Roman@0 SF(8)-4 I F1(.)4 I +.88(If the underlying operating system does not support a service switc\ +h \(e.g., SunOS 4.X, HP-)127 178.4 R .211(UX, BSD\) then)102 190.4 R F2 +(sendmail)2.711 E F1 .212(will pro)2.711 F .212 +(vide a stub implementation.)-.15 F(The)5.212 E F0(Ser)2.712 E +(viceSwitchFile)-.1 E F1 .212(option points)2.712 F .937 +(to the name of a \214le that has the service de\214nitions.)102 202.4 R +.937(Each line has the name of a service and the)5.937 F +(possible implementations of that service.)102 214.4 Q -.15(Fo)5 G 2.5 +(re).15 G(xample, the \214le:)-2.65 E 12.94(hosts dns)142 230.6 R +(\214les nis)2.5 E 6.84(aliases \214les)142 242.6 R(nis)2.5 E .328 +(will ask)102 258.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 .379 +(not found, it tries local \214les, and if that f)102 270.8 R .379 +(ails it tries NIS.)-.1 F(Similarly)5.379 E 2.879(,w)-.65 G .379 +(hen looking for aliases it will)-2.879 F +(try the local \214les \214rst follo)102 282.8 Q(wed by NIS.)-.25 E +1.269(Service switches are not completely inte)127 299 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 311 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)-2.793 F 1.398 +(system implementation of)102 323 R F2 -.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.) +-3.898 F 1.399(If there is enough demand)6.399 F F2(sendmail)102 335 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 347 Q(ould be necessary to mak)-.1 E 2.5(et)-.1 G +(his w)-2.5 E(ork seamlessly)-.1 E(.)-.65 E F0 2.5(2.6. The)87 371 R +(Alias Database)2.5 E F1 2.074(After recipient addresses are read from \ +the SMTP connection or command line the)127 387.2 R 4.574(ya)-.15 G(re) +-4.574 E .6(parsed by ruleset 0, which must resolv)102 399.2 R 3.1(et) +-.15 G 3.099(oa{)-3.1 G F2(mailer)-3.099 E F1(,)A F2(host)3.099 E F1(,)A +F2(addr)3.099 E(ess)-.37 E F1 3.099(}t)C 3.099(riple. If)-3.099 F .599 +(the \215ags selected by)3.099 F(the)102 411.2 Q F2(mailer)3.099 E F1 +.599(include the)3.099 F F0(A)3.099 E F1 .599(\(aliasable\) \215ag, the) +3.099 F F2(addr)3.099 E(ess)-.37 E F1 .6(part of the triple is look) +3.099 F .6(ed up as the k)-.1 F .9 -.15(ey \()-.1 H(i.e.,).15 E .636 +(the left hand side\) into the alias database.)102 423.2 R .636 +(If there is a match, the address is deleted from the send)5.636 F .776 +(queue and all addresses on the right hand side of the alias are added \ +in place of the alias that w)102 435.2 R(as)-.1 E 2.683(found. This)102 +447.2 R .183(is a recursi)2.683 F .483 -.15(ve o)-.25 H .183(peration, \ +so aliases found in the right hand side of the alias are similarly).15 F +-.15(ex)102 459.2 S(panded.).15 E 3.718(The alias database e)127 475.4 R +3.718(xists in tw)-.15 F 6.218(of)-.1 G 6.218(orms. One)-6.218 F 3.718 +(is a te)6.218 F 3.718(xt form, maintained in the \214le)-.15 F F2 +(/etc/mail/aliases.)102 487.4 Q F1(The aliases are of the form)5 E +(name: name1, name2, ...)142 503.6 Q +(Only local names may be aliased; e.g.,)102 519.8 Q(eric@prep.ai.MIT)142 +536 Q(.EDU: eric@CS.Berk)-.74 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E 1.088 +(will not ha)102 554.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')-3.588 F 3.587 +(tw)-.18 G 1.087(ant me\))-3.687 F F3(9)-4 I F1(.)4 I .986 +(Aliases may be continued by starting an)102 566.2 R 3.486(yc)-.15 G +.986(ontinuation lines with a space or a tab or by putting a)-3.486 F +.776(backslash directly before the ne)102 578.2 R 3.276(wline. Blank) +-.25 F .776(lines and lines be)3.276 F .776 +(ginning with a sharp sign \(\231#\232\) are)-.15 F(comments.)102 590.2 +Q .65(The second form is processed by the)127 608.4 R F2(ndbm)3.15 E F1 +(\(3\))1.666 E F3(10)-4 I F1 .65(or the Berk)3.15 4 N(ele)-.1 E 3.15(yD) +-.15 G 3.15(Bl)-3.15 G(ibrary)-3.15 E 5.651(.T)-.65 G .651 +(his form is in)-5.651 F .794(the \214le)102 620.4 R F2 +(/etc/mail/aliases.db)3.294 E F1 .794(\(if using NEWDB\) or)3.294 F F2 +(/etc/mail/aliases.dir)3.294 E F1(and)3.294 E F2(/etc/mail/aliases.pa) +3.294 E(g)-.1 E F1(\(if)3.294 E 1.126(using NDBM\).)102 632.4 R 1.126 +(This is the form that)6.126 F F2(sendmail)3.627 E F1 1.127 +(actually uses to resolv)3.627 F 3.627(ea)-.15 G 3.627(liases. This) +-3.627 F 1.127(technique is)3.627 F .32 LW 76 642 72 642 DL 80 642 76 +642 DL 84 642 80 642 DL 88 642 84 642 DL 92 642 88 642 DL 96 642 92 642 +DL 100 642 96 642 DL 104 642 100 642 DL 108 642 104 642 DL 112 642 108 +642 DL 116 642 112 642 DL 120 642 116 642 DL 124 642 120 642 DL 128 642 +124 642 DL 132 642 128 642 DL 136 642 132 642 DL 140 642 136 642 DL 144 +642 140 642 DL 148 642 144 642 DL 152 642 148 642 DL 156 642 152 642 DL +160 642 156 642 DL 164 642 160 642 DL 168 642 164 642 DL 172 642 168 642 +DL 176 642 172 642 DL 180 642 176 642 DL 184 642 180 642 DL 188 642 184 +642 DL 192 642 188 642 DL 196 642 192 642 DL 200 642 196 642 DL 204 642 +200 642 DL 208 642 204 642 DL 212 642 208 642 DL 216 642 212 642 DL/F4 5 +/Times-Roman@0 SF(8)93.6 652.4 Q/F5 8/Times-Roman@0 SF .107 +(HP-UX 10 has service switch support, b)3.2 J .108 +(ut since the APIs are apparently not a)-.16 F -.2(va)-.16 G .108 +(ilable in the libraries).2 F/F6 8/Times-Italic@0 SF(sendmail)2.108 E F5 +.108(does not use the)2.108 F(nati)72 665.2 Q .24 -.12(ve s)-.2 H +(ervice switch in this release.).12 E F4(9)93.6 675.6 Q F5(Actually)3.2 +I 2(,a)-.52 G .24 -.12(ny m)-2 H(ailer that has the `).12 E 1.776 -.888 +(A' m)-.64 H(ailer \215ag set will permit aliasing; this is normally li\ +mited to the local mailer).888 E(.)-.44 E F4(10)93.6 689.2 Q F5(The)3.2 +I F6(gdbm)2 E F5(package does not w)2 E(ork.)-.08 E EP +%%Page: 17 13 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-17)195.86 E/F1 10/Times-Roman@0 SF(used to impro)102 96 Q .3 +-.15(ve p)-.15 H(erformance.).15 E +(The control of search order is actually set by the service switch.)127 +112.2 Q(Essentially)5 E 2.5(,t)-.65 G(he entry)-2.5 E 2.5(OA)142 128.4 S +(liasFile=switch:aliases)-2.5 E .927(is al)102 144.6 R -.1(wa)-.1 G .927 +(ys added as the \214rst alias entry; also, the \214rst alias \214le na\ +me 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 156.6 R(`\214les') +-.74 E 2.769('e)-.74 G .269(ntry in the aliases switch.)-2.769 F -.15 +(Fo)5.269 G(r).15 E -.15(ex)102 168.6 S +(ample, if the con\214guration \214le contains).15 E 2.5(OA)142 184.8 S +(liasFile=/etc/mail/aliases)-2.5 E(and the service switch contains)102 +201 Q 6.84(aliases nis)142 217.2 R(\214les nisplus)2.5 E 1.164(then ali\ +ases will \214rst be searched in the NIS database, then in /etc/mail/al\ +iases, then in the NIS+)102 233.4 R(database.)102 245.4 Q -1.1(Yo)127 +261.6 S 2.5(uc)1.1 G(an also use)-2.5 E/F2 9/Times-Roman@0 SF(NIS)2.5 E +F1(-based alias \214les.)A -.15(Fo)5 G 2.5(re).15 G +(xample, the speci\214cation:)-2.65 E 2.5(OA)142 277.8 S +(liasFile=/etc/mail/aliases)-2.5 E 2.5(OA)142 289.8 S +(liasFile=nis:mail.aliases@my)-2.5 E(.nis.domain)-.65 E .143(will \214r\ +st search the /etc/mail/aliases \214le and then the map named \231mail.\ +aliases\232 in \231my)102 306 R(.nis.domain\232.)-.65 E -.8(Wa)102 318 S +.59(rning: if you b).8 F .59(uild your o)-.2 F(wn)-.25 E F2(NIS)3.09 E +F1 .589(-based alias \214les, be sure to pro)B .589(vide the)-.15 F F0 +3.089 E F1 .589(\215ag to)3.089 F/F3 10/Times-Italic@0 SF(mak) +3.089 E(edbm)-.1 E F1(\(8\))A .159(to map upper case letters in the k) +102 330 R -.15(ey)-.1 G 2.659(st).15 G 2.659(ol)-2.659 G -.25(ow)-2.659 +G .159(er case; otherwise, aliases with upper case letters in their).25 +F(names w)102 342 Q(on')-.1 E 2.5(tm)-.18 G(atch incoming addresses.) +-2.5 E(Additional \215ags can be added after the colon e)127 358.2 Q +(xactly lik)-.15 E 2.5(ea)-.1 G F0(K)A F1(line \212 for e)2.5 E(xample:) +-.15 E 2.5(OA)142 374.4 S(liasFile=nis:\255N mail.aliases@my)-2.5 E +(.nis.domain)-.65 E(will search the appropriate NIS map and al)102 390.6 +Q -.1(wa)-.1 G(ys include null bytes in the k).1 E -.15(ey)-.1 G 5(.A) +-.5 G(lso:)-5 E 2.5(OA)142 406.8 S(liasFile=nis:\255f mail.aliases@my) +-2.5 E(.nis.domain)-.65 E(will pre)102 423 Q -.15(ve)-.25 G +(nt sendmail from do).15 E(wncasing the k)-.25 E .3 -.15(ey b)-.1 H +(efore the alias lookup.).15 E F0 2.5(2.6.1. Reb)102 447 R +(uilding the alias database)-.2 E F1(The)142 463.2 Q F3(hash)3.08 E F1 +(or)3.08 E F3(dbm)3.08 E F1 -.15(ve)3.08 G .579 +(rsion of the database may be reb).15 F .579(uilt e)-.2 F .579 +(xplicitly by e)-.15 F -.15(xe)-.15 G .579(cuting the com-).15 F(mand) +117 475.2 Q(ne)157 491.4 Q -.1(wa)-.25 G(liases).1 E(This is equi)117 +507.6 Q -.25(va)-.25 G(lent to gi).25 E(ving)-.25 E F3(sendmail)2.5 E F1 +(the)2.5 E F0(\255bi)2.5 E F1(\215ag:)2.5 E(/usr/sbin/sendmail \255bi) +157 523.8 Q 2.29(If the)142 544.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,)-4.79 F F3(sendmail)4.79 E +F1(will)4.79 E(reb)117 556.2 Q .775(uild the alias database automatical\ +ly 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 568.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)-4.354 F(reb)117 580.2 Q 2.832(uild timeout \(option)-.2 F +F0(AliasW)5.332 E(ait)-.65 E F1 5.332(,o)C(ld)-5.332 E F0(a)5.332 E F1 +5.332(,w)C 2.831(hich is normally \214v)-5.332 F 5.331(em)-.15 G 2.831 +(inutes\) to reb)-5.331 F 2.831(uild the)-.2 F +(database, there is a chance that se)117 592.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 608.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 620.4 Q(xample, it can reb)-.15 E +(uild NDBM databases b)-.2 E(ut not NIS databases\).)-.2 E F0 2.5 +(2.6.2. P)102 644.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 660.6 R(The)6.13 E 3.63(ya)-.15 G 1.13(ll result)-3.63 F 1.103 +(from a)117 672.6 R F3(sendmail)3.603 E F1 1.103 +(process accessing the DBM v)3.603 F 1.103 +(ersion while it is only partially b)-.15 F 3.604(uilt. This)-.2 F(can) +3.604 E 1.249(happen under tw)117 684.6 R 3.749(oc)-.1 G 1.248(ircumsta\ +nces: One process accesses the database while another process is)-3.749 +F(reb)117 696.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 708.6 Q(uild.)-.2 E EP +%%Page: 18 14 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-18 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF .401 +(Sendmail has three techniques to try to relie)142 96 R .701 -.15(ve t) +-.25 H .401(hese problems.).15 F .4(First, it ignores interrupts)5.401 F +.045(while reb)117 108 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 120 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 132 R .812 +(ork o)-.1 F -.15(ve)-.15 G 3.312(rN).15 G .812 +(FS or if the \214le is unwritable.)-3.312 F .813 +(Third, at the end of the reb)5.813 F .813(uild it adds an)-.2 F +(alias of the form)117 144 Q(@: @)157 160.2 Q .336 +(\(which is not normally le)117 176.4 R -.05(ga)-.15 G 2.836 +(l\). Before).05 F/F2 10/Times-Italic@0 SF(sendmail)2.836 E F1 .336 +(will access the database, it checks to insure that)2.836 F +(this entry e)117 190.4 Q(xists)-.15 E/F3 7/Times-Roman@0 SF(11)-4 I F1 +(.)4 I F0 2.5(2.6.3. List)102 214.4 R -.1(ow)2.5 G(ners).1 E F1 .4 +(If an error occurs on sending to a certain address, say \231)142 230.6 +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 242.6 R(wner)-.25 E(-)-.2 E F2(x)A F1 +2.918<9a74>C 2.918(or)-2.918 G(ecei)-2.918 E .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 254.6 R -.15(ve)-.15 G 3.617 +(rt).15 G 1.117 +(he maintenance of the list itself; in this case the list)-3.617 F +(maintainer w)117 266.6 Q(ould be the o)-.1 E(wner of the list.)-.25 E +-.15(Fo)5 G 2.5(re).15 G(xample:)-2.65 E +(unix-wizards: eric@ucbarpa, wnj@monet, nosuchuser)157 282.8 Q(,)-.4 E +(sam@matisse)193 294.8 Q -.25(ow)157 306.8 S(ner).25 E +(-unix-wizards: unix-wizards-request)-.2 E +(unix-wizards-request: eric@ucbarpa)157 318.8 Q -.1(wo)117 335 S .689(u\ +ld cause \231eric@ucbarpa\232 to get the error that will occur when som\ +eone sends to unix-wiz-).1 F +(ards due to the inclusion of \231nosuchuser\232 on the list.)117 347 Q +.958(List o)142 363.2 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 375.2 S .429 +(ner alias are used if the).25 F 2.929(yp)-.15 G .429 +(oint to a single user)-2.929 F 2.928(,o)-.4 G .428 +(therwise the name of the alias itself is used.)-2.928 F -.15(Fo)117 +387.2 S 3.454(rt).15 G .954(his reason, and to obe)-3.454 F 3.454(yI) +-.15 G .954(nternet con)-3.454 F -.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 address; this causes messages to go out with the typic\ +al Internet con)117 399.2 R -.15(ve)-.4 G .503(ntion of using).15 F -.74 +(``)117 411.2 S F2(list).74 E F1(-request')A 2.5('a)-.74 G 2.5(st)-2.5 G +(he return address.)-2.5 E F0 2.5(2.7. User)87 435.2 R(Inf)2.5 E +(ormation Database)-.25 E F1 1.059(If you ha)127 451.4 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 +463.4 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 475.4 +Q F1(:maildrop entry)A 5(.I)-.65 G 2.5(ff)-5 G +(ound, the mail will be sent to the speci\214ed address.)-2.5 E F0 2.5 +(2.8. P)87 499.4 R(er)-.2 E(-User F)-.37 E(orwarding \(.f)-.25 E +(orward Files\))-.25 E F1 .12(As an alternati)127 515.6 R .42 -.15(ve t) +-.25 H 2.62(ot).15 G .12(he alias database, an)-2.62 F 2.62(yu)-.15 G +.121(ser may put a \214le with the name \231.forw)-2.62 F .121 +(ard\232 in his)-.1 F .205(or her home directory)102 527.6 R 5.205(.I) +-.65 G 2.705(ft)-5.205 G .205(his \214le e)-2.705 F(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 539.6 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) +-3.558 F(ard)-.1 E(\214le with contents:)102 551.6 Q(mckusick@ernie)142 +567.8 Q(kirk@calder)142 579.8 Q(then an)102 596 Q 2.5(ym)-.15 G +(ail arri)-2.5 E(ving for \231mckusick\232 will be redirected to the sp\ +eci\214ed accounts.)-.25 E(Actually)127 612.2 Q 3.375(,t)-.65 G .874(he\ + con\214guration \214le de\214nes a sequence of \214lenames to check.) +-3.375 F .874(By def)5.874 F .874(ault, this is)-.1 F .516(the user')102 +624.2 R 3.016(s.)-.55 G(forw)-3.016 E .517(ard \214le, b)-.1 F .517 +(ut can be de\214ned to be more generally using the)-.2 F F0 -.25(Fo) +3.017 G(rwardP).25 E(ath)-.1 E F1 3.017(option. If)3.017 F .183 +(you change this, you will ha)102 636.2 R .482 -.15(ve t)-.2 H 2.682(oi) +.15 G .182(nform your user base of the change; .forw)-2.682 F .182 +(ard is pretty well incor)-.1 F(-)-.2 E(porated into the collecti)102 +648.2 Q .3 -.15(ve s)-.25 H(ubconscious.).15 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(11)93.6 689.2 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.)-4 E EP +%%Page: 19 15 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-19)195.86 E 2.5(2.9. Special)87 96 R(Header Lines)2.5 E/F1 10 +/Times-Roman@0 SF(Se)127 112.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 124.2 Q 1.206 -.15(ve i)-.2 H .906 +(nterpretations b).15 F .906(uilt into)-.2 F/F2 10/Times-Italic@0 SF +(sendmail)3.406 E F1 .905 +(that cannot be changed without changing the code.)3.406 F(These)5.905 E +-.2(bu)102 136.2 S(iltins are described here.).2 E F0 2.5(2.9.1. Err)102 +160.2 R(ors-T)-.18 E(o:)-.92 E F1 .22(If errors occur an)142 176.4 R .22 +(ywhere during processing, this header will cause error messages to go \ +to)-.15 F(the listed addresses.)117 188.4 Q +(This is intended for mailing lists.)5 E .385(The Errors-T)142 204.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)-2.884 F .889(distinction between an en)117 216.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) +-3.39 E .81(passed as the en)117 228.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)-3.309 G .809 +(nly used if the)-3.309 F F0(UseErr)3.309 E(orsT)-.18 E(o)-.92 E F1 +(option is set.)117 240.6 Q(The Errors-T)142 256.8 Q(o: header is of)-.8 +E(\214cially deprecated and will go a)-.25 E -.1(wa)-.15 G 2.5(yi).1 G +2.5(naf)-2.5 G(uture release.)-2.5 E F0 2.5(2.9.2. A)102 280.8 R(ppar) +-.25 E(ently-T)-.18 E(o:)-.92 E F1 .044 +(RFC 822 requires at least one recipient \214eld \(T)142 297 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 309 +R F2(sendmail)3.062 E F1 .562(will adjust the header)3.062 F .085 +(based on the \231NoRecipientAction\232 option.)117 321 R .085 +(One of the possible actions is to add an \231)5.085 F(Apparently-)-.8 E +-.8(To)117 333 S(:\232 header line for an).8 E 2.5(yr)-.15 G +(ecipients it is a)-2.5 E -.1(wa)-.15 G(re of.).1 E(The Apparently-T)142 +349.2 Q(o: header is non-standard and is deprecated.)-.8 E F0 2.5 +(2.9.3. Pr)102 373.2 R(ecedence)-.18 E F1 .425(The Precedence: header c\ +an be used as a crude control of message priority)142 389.4 R 5.424(.I) +-.65 G 2.924(tt)-5.424 G .424(weaks the)-2.924 F(sort order in the queu\ +e and can be con\214gured to change the message timeout v)117 401.4 Q +(alues.)-.25 E F0 2.5(2.10. IDENT)87 425.4 R(Pr)2.5 E(otocol Support) +-.18 E F2(Sendmail)127 441.6 Q F1 .745 +(supports the IDENT protocol as de\214ned in RFC 1413.)3.245 F .746 +(Note that the RFC states a)5.745 F 1.361(client should w)102 453.6 R +1.361(ait at least 30 seconds for a response.)-.1 F 1.36(The def)6.361 F +1.36(ault T)-.1 F 1.36(imeout.ident is 5 seconds as)-.35 F(man)102 465.6 +Q 3.024(ys)-.15 G .524(ites ha)-3.024 F .824 -.15(ve a)-.2 H .524 +(dopted the practice of dropping IDENT queries.).15 F .524 +(This has lead to delays process-)5.524 F .452(ing mail.)102 477.6 R +.452(Although this enhances identi\214cation of the author of an email \ +message by doing a `)5.452 F(`call)-.74 E(back')102 489.6 Q 3.627('t) +-.74 G 3.627(ot)-3.627 G 1.127(he originating system to include the o) +-3.627 F 1.128(wner of a particular TCP connection in the audit)-.25 F +.164(trail it is in no sense perfect; a determined for)102 501.6 R .164 +(ger can easily spoof the IDENT protocol.)-.18 F .164(The follo)5.164 F +(w-)-.25 E(ing description is e)102 513.6 Q(xcerpted from RFC 1413:)-.15 +E 2.5(6. Security)127 529.8 R(Considerations)2.5 E .005 +(The information returned by this protocol is at most as trustw)127 546 +R(orth)-.1 E 2.506(ya)-.05 G 2.506(st)-2.506 G .006(he host pro)-2.506 F +.006(viding it OR)-.15 F .274(the or)127 558 R -.05(ga)-.18 G .274 +(nization operating the host.).05 F -.15(Fo)5.274 G 2.774(re).15 G .273 +(xample, a PC in an open lab has fe)-2.924 F 2.773(wi)-.25 G 2.773(fa) +-2.773 G .573 -.15(ny c)-2.773 H(ontrols).15 E .986(on it to pre)127 570 +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 .987 +(denti\214er the user w)-3.486 F 3.487(ants. Lik)-.1 F(e-)-.1 E 1.441(w\ +ise, if the host has been compromised the information returned may be c\ +ompletely erro-)127 582 R(neous and misleading.)127 594 Q .521(The Iden\ +ti\214cation Protocol is not intended as an authorization or access con\ +trol protocol.)127 610.2 R(At)5.521 E 1.037(best, it pro)127 622.2 R +1.037(vides some additional auditing information with respect to TCP co\ +nnections.)-.15 F(At)6.036 E -.1(wo)127 634.2 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 650.4 R 2.697 +(couraged. Speci\214cally)127 662.4 R 2.697(,u)-.65 G .197 +(sing Identi\214cation Protocol information to mak)-2.697 F 2.697(ea)-.1 +G .197(ccess control deci-)-2.697 F .514(sions - either as the primary \ +method \(i.e., no other checks\) or as an adjunct to other methods)127 +674.4 R(may result in a weak)127 686.4 Q(ening of normal host security) +-.1 E(.)-.65 E 1.779(An Identi\214cation serv)127 702.6 R 1.778 +(er may re)-.15 F -.15(ve)-.25 G 1.778 +(al information about users, entities, objects or processes).15 F .336 +(which might normally be considered pri)127 714.6 R -.25(va)-.25 G 2.836 +(te. An).25 F .337(Identi\214cation serv)2.836 F .337(er pro)-.15 F .337 +(vides service which)-.15 F EP +%%Page: 20 16 +%%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 .806 +(is a rough analog of the CallerID services pro)127 96 R .806 +(vided by some phone companies and man)-.15 F 3.306(yo)-.15 G(f)-3.306 E +1.397(the same pri)127 108 R -.25(va)-.25 G 1.697 -.15(cy c).25 H 1.397 +(onsiderations and ar).15 F 1.398 +(guments that apply to the CallerID service apply to)-.18 F 3.546 +(Identi\214cation. If)127 120 R 1.046(you w)3.546 F(ouldn')-.1 E 3.546 +(tr)-.18 G 1.045(un a "\214nger" serv)-3.546 F 1.045(er due to pri)-.15 +F -.25(va)-.25 G 1.345 -.15(cy c).25 H 1.045(onsiderations you may).15 F +(not w)127 132 Q(ant to run this protocol.)-.1 E .376 +(In some cases your system may not w)102 148.2 R .377 +(ork properly with IDENT support due to a b)-.1 F .377(ug in the TCP/IP) +-.2 F 3.675(implementation. The)102 160.2 R 1.175(symptoms will be that\ + for some hosts the SMTP connection will be closed)3.675 F .565 +(almost immediately)102 172.2 R 5.565(.I)-.65 G 3.065(ft)-5.565 G .565 +(his is true or if you do not w)-3.065 F .565(ant to use IDENT)-.1 F +3.066(,y)-.74 G .566(ou should set the IDENT)-3.066 F +(timeout to zero; this will disable the IDENT protocol.)102 184.2 Q F0 +2.5(3. ARGUMENTS)72 208.2 R F1 .018(The complete list of ar)112 224.4 R +.018(guments to)-.18 F/F2 10/Times-Italic@0 SF(sendmail)2.517 E F1 .017 +(is described in detail in Appendix A.)2.517 F .017(Some important)5.017 +F(ar)87 236.4 Q(guments are described here.)-.18 E F0 2.5(3.1. Queue)87 +260.4 R(Inter)2.5 E -.1(va)-.1 G(l).1 E F1 .455(The amount of time betw\ +een forking a process to run through the queue is de\214ned by the)127 +276.6 R F02.956 E F1 2.676(\215ag. If)102 288.6 R .176 +(you run with deli)2.676 F -.15(ve)-.25 G .176(ry mode set to).15 F F0 +(i)2.676 E F1(or)2.676 E F0(b)2.675 E F1 .175(this can be relati)2.675 F +-.15(ve)-.25 G .175(ly lar).15 F .175(ge, since it will only be rel-) +-.18 F -.25(eva)102 300.6 S .206(nt when a host that w).25 F .206(as do) +-.1 F .206(wn comes back up.)-.25 F .207(If you run in)5.206 F F0(q) +2.707 E F1 .207(mode it should be relati)2.707 F -.15(ve)-.25 G .207 +(ly short,).15 F 1.039(since it de\214nes the maximum amount of time th\ +at a message may sit in the queue.)102 312.6 R 1.038(\(See also the) +6.039 F(MinQueueAge option.\))102 324.6 Q 1.335 +(RFC 1123 section 5.3.1.1 says that this v)127 340.8 R 1.336 +(alue should be at least 30 minutes \(although that)-.25 F +(probably doesn')102 352.8 Q 2.5(tm)-.18 G(ak)-2.5 E 2.5(es)-.1 G +(ense if you use `)-2.5 E(`queue-only')-.74 E 2.5('m)-.74 G(ode\).)-2.5 +E F0 2.5(3.2. Daemon)87 376.8 R(Mode)2.5 E F1 .085(If you allo)127 393 R +2.585(wi)-.25 G .085(ncoming mail o)-2.585 F -.15(ve)-.15 G 2.585(ra).15 +G 2.585(nI)-2.585 G .085(PC connection, you should ha)-2.585 F .384 -.15 +(ve a d)-.2 H .084(aemon running.).15 F(This)5.084 E .069 +(should be set by your)102 405 R F2(/etc/r)2.569 E(c)-.37 E F1 .069 +(\214le using the)2.569 F F0(\255bd)2.569 E F1 2.57(\215ag. The)2.569 F +F0(\255bd)2.57 E F1 .07(\215ag and the)2.57 F F02.57 E F1 .07 +(\215ag may be combined)2.57 F(in one call:)102 417 Q +(/usr/sbin/sendmail \255bd \255q30m)142 433.2 Q .293(An alternati)127 +453.6 R .593 -.15(ve a)-.25 H .293(pproach is to in).15 F -.2(vo)-.4 G +.493 -.1(ke s).2 H .293(endmail from).1 F F2(inetd)2.793 E F1 .293 +(\(8\) \(use the)B F0(\255bs)2.792 E F1 .292(\215ag to ask sendmail) +2.792 F .255(to speak SMTP on its standard input and output\).)102 465.6 +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 477.6 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 489.6 T .555(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 .556(running to \215ush the)3.056 F(queue:)102 +501.6 Q(/usr/sbin/sendmail \255q30m)142 517.8 Q F0 2.5(3.3. F)87 546 R +(or)-.25 E(cing the Queue)-.18 E F1 .04(In some cases you may \214nd th\ +at the queue has gotten clogged for some reason.)127 562.2 R -1.1(Yo) +5.04 G 2.54(uc)1.1 G .04(an force)-2.54 F 3.184(aq)102 574.2 S .684 +(ueue run using the)-3.184 F F03.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 +F03.185 E F1 .685(\215ag \(v)3.185 F .685(erbose\) when)-.15 F +(this is done to w)102 586.2 Q(atch what happens:)-.1 E +(/usr/sbin/sendmail \255q \255v)142 602.4 Q -1.1(Yo)127 622.8 S 4.004 +(uc)1.1 G 1.504 +(an also limit the jobs to those with a particular queue identi\214er) +-4.004 F 4.004(,s)-.4 G(ender)-4.004 E 4.004(,o)-.4 G 4.004(rr)-4.004 G +(ecipient)-4.004 E .686(using one of the queue modi\214ers.)102 634.8 R +-.15(Fo)5.687 G 3.187(re).15 G .687(xample, \231\255qRberk)-3.337 F(ele) +-.1 E .687(y\232 restricts the queue run to jobs that)-.15 F(ha)102 +646.8 Q .526 -.15(ve t)-.2 H .226(he string \231berk).15 F(ele)-.1 E +.226(y\232 some)-.15 F .225(where in one of the recipient addresses.) +-.25 F(Similarly)5.225 E 2.725<2c99>-.65 G .225(\255qSstring\232 lim-) +-2.725 F(its the run to particular senders and \231\255qIstring\232 lim\ +its it to particular queue identi\214ers.)102 658.8 Q F0 2.5(3.4. Deb)87 +682.8 R(ugging)-.2 E F1 1.365(There are a f)127 699 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)-6.365 +F 1.365(ug \215ag has a)-.2 F 1.116(number and a le)102 711 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 .293(that le)102 723 R -.15(ve)-.25 G +.293(ls greater than nine are \231absurd,).15 F 2.794<9a69>-.7 G .294 +(.e., the)-2.794 F 2.794(yp)-.15 G .294 +(rint out so much information that you w)-2.794 F(ouldn')-.1 E(t)-.18 E +EP +%%Page: 21 17 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-21)195.86 E/F1 10/Times-Roman@0 SF .692(normally w)102 96 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 .691 +(ug \215ags are set)-.2 F(using the)102 108 Q F02.5 E F1 +(option; the syntax is:)2.5 E(deb)142 124.2 Q(ug-\215ag:)-.2 E F0 +12.78 E F1(deb)2.5 E(ug-list)-.2 E(deb)142 136.2 Q 13.05(ug-list: deb) +-.2 F(ug-option [ , deb)-.2 E(ug-option ]*)-.2 E(deb)142 148.2 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 160.2 Q 3.07(ug-range: inte)-.2 F(ger | inte)-.15 E +(ger \255 inte)-.15 E(ger)-.15 E(deb)142 172.2 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 188.4 Q 5(.F)-.65 G(or e) +-5.15 E(xample,)-.15 E 34.99(\255d12 Set)142 204.6 R(\215ag 12 to le)2.5 +E -.15(ve)-.25 G 2.5(l1).15 G 27.49(\255d12.3 Set)142 216.6 R +(\215ag 12 to le)2.5 E -.15(ve)-.25 G 2.5(l3).15 G 24.35 +(\255d3\25517 Set)142 228.6 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 240.6 R +(\215ags 3 through 17 to le)2.5 E -.15(ve)-.25 G 2.5(l4).15 G -.15(Fo) +102 256.8 S 4.065(rac).15 G 1.565(omplete list of the a)-4.065 F -.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.566(ook at the code \(the)-4.065 +F 4.066(ya)-.15 G 1.566(re too)-4.066 F(dynamic to k)102 268.8 Q +(eep this documentation up to date\).)-.1 E F0 2.5(3.5. Changing)87 +292.8 R(the V)2.5 E(alues of Options)-.92 E F1(Options can be o)127 309 +Q -.15(ve)-.15 G(rridden using the).15 E F02.5 E F1(or)2.5 E F0 +2.5 E F1(command line \215ags.)2.5 E -.15(Fo)5 G 2.5(re).15 G +(xample,)-2.65 E(/usr/sbin/sendmail \255oT2m)142 325.2 Q .021(sets the) +102 341.4 R F0(T)2.521 E F1 .021(\(timeout\) option to tw)2.521 F 2.521 +(om)-.1 G .021(inutes for this run only; the equi)-2.521 F -.25(va)-.25 +G .02(lent line using the long option).25 F(name is)102 353.4 Q +(/usr/sbin/sendmail -O)142 369.6 Q -.35(Ti)-.4 G(meout.queuereturn=2m) +.35 E .72(Some options ha)127 390 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 +(its setuid root permissions thereafter)102 404 Q/F2 7/Times-Roman@0 SF +(12)-4 I F1(.)4 I F0 2.5(3.6. T)87 428 R(rying a Differ)-.74 E +(ent Con\214guration File)-.18 E F1(An alternati)127 444.2 Q .3 -.15 +(ve c)-.25 H(on\214guration \214le can be speci\214ed using the).15 E F0 +2.5 E F1(\215ag; for e)2.5 E(xample,)-.15 E +(/usr/sbin/sendmail \255Ctest.cf \255oQ/tmp/mqueue)142 460.4 Q .68 +(uses the con\214guration \214le)102 476.6 R/F3 10/Times-Italic@0 SF +(test.cf)3.18 E F1 .68(instead of the def)3.18 F(ault)-.1 E F3 +(/etc/mail/sendmail.cf)3.18 E(.)-.15 E F1 .68(If the)5.68 F F03.18 +E F1 .68(\215ag has no)3.18 F -.25(va)102 488.6 S(lue it def).25 E +(aults to)-.1 E F3(sendmail.cf)2.5 E F1(in the current directory)2.5 E +(.)-.65 E F3(Sendmail)127 504.8 Q F1(gi)2.68 E -.15(ve)-.25 G 2.68(su) +.15 G 2.68(pi)-2.68 G .179(ts setuid root permissions when you use this\ + \215ag, so it is common to use a)-2.68 F .069(publicly writable direct\ +ory \(such as /tmp\) as the spool directory \(QueueDirectory or Q optio\ +n\) while)102 516.8 R(testing.)102 528.8 Q F0 2.5(3.7. Logging)87 552.8 +R -.74(Tr)2.5 G(af\214c).74 E F1(Man)127 569 Q 3.255(yS)-.15 G .754 +(MTP implementations do not fully implement the protocol.)-3.255 F -.15 +(Fo)5.754 G 3.254(re).15 G .754(xample, some per)-3.404 F(-)-.2 E 1.178 +(sonal computer based SMTPs do not understand continuation lines in rep\ +ly codes.)102 581 R 1.178(These can be)6.178 F -.15(ve)102 593 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 F02.63 E F1 2.63(\215ag. F)2.63 F +(or)-.15 E -.15(ex)102 605 S(ample,).15 E +(/usr/sbin/sendmail \255X /tmp/traf)142 621.2 Q(\214c \255bd)-.25 E +(will log all traf)102 637.4 Q(\214c in the \214le)-.25 E F3(/tmp/tr)2.5 +E(af)-.15 E<8c63>-.18 E F1(.)A .997(This logs a lot of data v)127 653.6 +R .997(ery quickly and should)-.15 F F0(NEVER)3.497 E F1 .998 +(be used during normal operations.)3.498 F .963(After starting up such \ +a daemon, force the errant implementation to send a message to your hos\ +t.)102 665.6 R .32 LW 76 675.2 72 675.2 DL 80 675.2 76 675.2 DL 84 675.2 +80 675.2 DL 88 675.2 84 675.2 DL 92 675.2 88 675.2 DL 96 675.2 92 675.2 +DL 100 675.2 96 675.2 DL 104 675.2 100 675.2 DL 108 675.2 104 675.2 DL +112 675.2 108 675.2 DL 116 675.2 112 675.2 DL 120 675.2 116 675.2 DL 124 +675.2 120 675.2 DL 128 675.2 124 675.2 DL 132 675.2 128 675.2 DL 136 +675.2 132 675.2 DL 140 675.2 136 675.2 DL 144 675.2 140 675.2 DL 148 +675.2 144 675.2 DL 152 675.2 148 675.2 DL 156 675.2 152 675.2 DL 160 +675.2 156 675.2 DL 164 675.2 160 675.2 DL 168 675.2 164 675.2 DL 172 +675.2 168 675.2 DL 176 675.2 172 675.2 DL 180 675.2 176 675.2 DL 184 +675.2 180 675.2 DL 188 675.2 184 675.2 DL 192 675.2 188 675.2 DL 196 +675.2 192 675.2 DL 200 675.2 196 675.2 DL 204 675.2 200 675.2 DL 208 +675.2 204 675.2 DL 212 675.2 208 675.2 DL 216 675.2 212 675.2 DL/F4 5 +/Times-Roman@0 SF(12)93.6 685.6 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)-2.497 F +(startup the root permissions will still be honored.)72 698.4 Q EP +%%Page: 22 18 +%%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 .608 +(All message traf)102 96 R .608(\214c in and out of)-.25 F/F2 10 +/Times-Italic@0 SF(sendmail)3.109 E F1 3.109(,i)C .609 +(ncluding the incoming SMTP traf)-3.109 F .609(\214c, will be logged in) +-.25 F(this \214le.)102 108 Q F0 2.5(3.8. T)87 132 R +(esting Con\214guration Files)-.92 E F1 .644(When you b)127 148.2 R .644 +(uild a con\214guration table, you can do a certain amount of testing u\ +sing the \231test)-.2 F(mode\232 of)102 160.2 Q F2(sendmail)2.5 E F1 5 +(.F)C(or e)-5.15 E(xample, you could in)-.15 E -.2(vo)-.4 G -.1(ke).2 G +F2(sendmail)2.6 E F1(as:)2.5 E(sendmail \255bt \255Ctest.cf)142 176.4 Q +.447(which w)102 192.6 R .447(ould read the con\214guration \214le \231\ +test.cf\232 and enter test mode.)-.1 F .448 +(In this mode, you enter lines)5.448 F(of the form:)102 204.6 Q +(rwset address)142 220.8 Q(where)102 237 Q F2(rwset)3.007 E F1 .507 +(is the re)3.007 F .507(writing set you w)-.25 F .507(ant to use and)-.1 +F F2(addr)3.006 E(ess)-.37 E F1 .506(is an address to apply the set to.) +3.006 F -.7(Te)5.506 G(st).7 E .793(mode sho)102 249 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 261 +S 3.332(um)1.1 G .832(ay use a comma separated list of rwsets for seque\ +ntial application of rules to an input.)-3.332 F -.15(Fo)5.831 G(r).15 E +-.15(ex)102 273 S(ample:).15 E(3,1,21,4 monet:bollard)142 289.2 Q .622 +(\214rst applies ruleset three to the input \231monet:bollard.)102 305.4 +R 5.622<9a52>-.7 G .622(uleset one is then applied to the output of) +-5.622 F(ruleset three, follo)102 317.4 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\255d21\232 \215ag to t\ +urn on more deb)127 333.6 R 3.584(ugging. F)-.2 F(or)-.15 E -.15(ex)102 +345.6 S(ample,).15 E(sendmail \255bt \255d21.99)142 361.8 Q .689 +(turns on an incredible amount of information; a single w)102 378 R .689 +(ord address is probably going to print out)-.1 F(se)102 390 Q -.15(ve) +-.25 G(ral pages w).15 E(orth of information.)-.1 E -1.1(Yo)127 406.2 S +2.575(us)1.1 G .075(hould be w)-2.575 F .075(arned that internally)-.1 F +(,)-.65 E F2(sendmail)2.575 E F1 .075 +(applies ruleset 3 to all addresses.)2.575 F .074(In test mode)5.074 F +(you will ha)102 418.2 Q .3 -.15(ve t)-.2 H 2.5(od).15 G 2.5(ot)-2.5 G +(hat manually)-2.5 E 5(.F)-.65 G(or e)-5.15 E(xample, older v)-.15 E +(ersions allo)-.15 E(wed you to use)-.25 E 2.5(0b)142 434.4 S +(ruce@broadcast.son)-2.5 E -.65(y.)-.15 G(com).65 E(This v)102 450.6 Q +(ersion requires that you use:)-.15 E(3,0 bruce@broadcast.son)142 466.8 +Q -.65(y.)-.15 G(com).65 E(As of v)127 487.2 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 503.4 S 1.666(Dxv)-5 G .327 +(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)-5.328 F .328(ugging rules that)-.2 F +(use the)115.5 515.4 Q F0($&)2.5 E F2(x)A F1(syntax.)2.5 E 5<832e>107 +527.4 S 1.666(Ccv)-5 G(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 539.4 S 1.666(Sr)-5 G +(uleset dumps the contents of the indicated ruleset.)-1.666 E 5<83ad>107 +551.4 S 1.666(dd)-5 G(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(3.9. P)87 575.4 R +(ersistent Host Status Inf)-.2 E(ormation)-.25 E F1(When)127 591.6 Q F0 +(HostStatusDir)2.57 E(ectory)-.18 E F1 .069 +(is enabled, information about the status of hosts is maintained on)2.57 +F .248(disk and can thus be shared between dif)102 603.6 R .249 +(ferent instantiations of)-.25 F F2(sendmail)2.749 E F1 5.249(.T)C .249 +(he status of the last con-)-5.249 F +(nection with each remote host may be vie)102 615.6 Q +(wed with the command:)-.25 E(sendmail \255bh)142 631.8 Q +(This information may be \215ushed with the command:)102 648 Q +(sendmail \255bH)142 664.2 Q 1.535(Flushing the information pre)102 +680.4 R -.15(ve)-.25 G 1.535(nts ne).15 F(w)-.25 E F2(sendmail)4.035 E +F1 1.535(processes from loading it, b)4.035 F 1.534(ut does not pre)-.2 +F -.15(ve)-.25 G(nt).15 E -.15(ex)102 692.4 S +(isting processes from using the status information that the).15 E 2.5 +(ya)-.15 G(lready ha)-2.5 E -.15(ve)-.2 G(.).15 E EP +%%Page: 23 19 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-23)195.86 E 2.5(4. TUNING)72 96 R/F1 10/Times-Roman@0 SF 1.922 +(There are a number of con\214guration parameters you may w)112 112.2 R +1.922(ant to change, depending on the)-.1 F .367 +(requirements of your site.)87 124.2 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,)-3.016 E +(the line \231O T)87 136.2 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\).)-2.5 E .735(Most of these options ha)112 152.4 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 164.4 R 2.546(yn)-.15 G .046 +(eed to tune them as appropriate for their mail load.)-2.546 F .045 +(In particular)5.045 F 2.545(,s)-.4 G .045(ites e)-2.545 F(xperi-)-.15 E +1.087(encing a lar)87 176.4 R 1.087(ge number of small messages, man) +-.18 F 3.587(yo)-.15 G 3.588(fw)-3.587 G 1.088(hich are deli)-3.588 F +-.15(ve)-.25 G 1.088(red to man).15 F 3.588(yr)-.15 G 1.088 +(ecipients, may \214nd)-3.588 F(that the)87 188.4 Q 2.5(yn)-.15 G +(eed to adjust the parameters dealing with queue priorities.)-2.5 E .524 +(All v)112 204.6 R .524(ersions of)-.15 F/F2 10/Times-Italic@0 SF +(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 216.6 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)-3.716 F(ha)87 228.6 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 244.8 R +.802(ely to w)-.1 F .801(ant to tweak; read section 5 for)-.1 F +(more details.)87 256.8 Q F0 2.5(4.1. T)87 280.8 R(imeouts)-.18 E F1 +.582(All time interv)127 297 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,)-3.233 F +(whereas \2312h30m\232 represents tw)102 309 Q 2.5(oa)-.1 G +(nd a half hours.)-2.5 E(The full set of scales is:)5 E 16.11(ss)142 +325.2 S(econds)-16.11 E 12.22(mm)142 337.2 S(inutes)-12.22 E 15(hh)142 +349.2 S(ours)-15 E 15(dd)142 361.2 S(ays)-15 E 12.78(ww)142 373.2 S +(eeks)-12.78 E F0 2.5(4.1.1. Queue)102 401.4 R(inter)2.5 E -.1(va)-.1 G +(l).1 E F1 .18(The ar)142 417.6 R .18(gument to the)-.18 F F02.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.)-2.68 F .18(This is)5.18 F .967 +(typically set to between \214fteen minutes and one hour)117 429.6 R +5.968(.R)-.55 G .968(FC 1123 section 5.3.1.1 recommends)-5.968 F +(that this be at least 30 minutes.)117 441.6 Q F0 2.5(4.1.2. Read)102 +465.6 R(timeouts)2.5 E F1 -.35(Ti)142 481.8 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 493.8 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 510 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 522 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 534 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 546 R .579(ernels that pro)-.1 +F .579(vide an absurdly long connection timeout \(90)-.15 F +(minutes in one case\).)189 558 Q 35.62(iconnect The)117 574.2 R .31 +(same as)2.81 F F2(connect,)2.81 E F1 -.15(ex)2.81 G .311 +(cept it applies only to the initial attempt to connect to).15 F 2.75 +(ah)189 586.2 S .25(ost for a gi)-2.75 F -.15(ve)-.25 G 2.75(nm).15 G +.25(essage [0, unspeci\214ed].)-2.75 F .25 +(The concept is that this should be)5.25 F -.15(ve)189 598.2 S .766 +(ry short \(a fe).15 F 3.266(ws)-.25 G .767 +(econds\); hosts that are well connected and responsi)-3.266 F 1.067 +-.15(ve w)-.25 H(ill).15 E .027(thus be serviced immediately)189 610.2 R +5.026(.H)-.65 G .026(osts that are slo)-5.026 F 2.526(ww)-.25 G .026 +(ill not hold up other deli)-2.526 F(v-)-.25 E +(eries in the initial deli)189 622.2 Q -.15(ve)-.25 G(ry attempt.).15 E +46.16(initial The)117 638.4 R -.1(wa)2.5 G +(it for the initial 220 greeting message [5m, 5m].).1 E 52.28(helo The) +117 654.6 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 666.6 R 2.6(em)-.15 G +.1(inutes is probably a reasonable)-2.6 F(minimum.)189 678.6 Q 46.72 +(mail\207 The)117 694.8 R -.1(wa)2.5 G +(it for a reply from a MAIL command [10m, 5m].).1 E 48.95(rcpt\207 The) +117 711 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 723 R 1.556 +(es a long time to e)-.1 F 1.556(xpand \(see)-.15 F EP +%%Page: 24 20 +%%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/F1 10/Times-Roman@0 SF(belo)189 +96 Q(w\).)-.25 E 34.5(datainit\207 The)117 112.2 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 20.62(datablock\207\210 The)117 128.4 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 140.4 R/F2 10/Times-Italic@0 SF(send-) +3.12 E(mail)189 152.4 Q F1(which ha)2.5 E .3 -.15(ve n)-.2 H 2.5(og).15 +G(uarantee of promptness.)-2.5 E 30.06(data\214nal\207 The)117 168.6 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 180.6 R -.15 +(ve)-.25 G 3.383(rt).15 G 3.383(od)-3.383 G(eli)-3.383 E -.15(ve)-.25 G +3.383(rt).15 G .883(he message,)-3.383 F(duplicates will be generated.) +189 192.6 Q(This is discussed in RFC 1047.)5 E 55.06(rset The)117 208.8 +R -.1(wa)2.5 G(it for a reply from a RSET command [5m, unspeci\214ed].) +.1 E 53.94(quit The)117 225 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 241.2 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 253.2 Q(erbose mode\).)-.15 E +([2m, unspeci\214ed].)5 E 20.06(command\207\210 In)117 269.4 R(serv)2.5 +E(er SMTP)-.15 E 2.5(,t)-1.11 G(he time to w)-2.5 E +(ait for another command.)-.1 E([1h, 5m].)5 E 44.5(ident\210 The)117 +287.6 R(timeout w)2.5 E(aiting for a reply to an IDENT query [30s)-.1 E +/F3 7/Times-Roman@0 SF(13)-4 I F1 2.5(,u)4 K(nspeci\214ed].)-2.5 E 32.28 +(\214leopen\210 The)117 303.8 R(timeout for opening .forw)2.5 E +(ard and :include: \214les [60s, none].)-.1 E 36.17(control\210 The)117 +320 R .241(timeout for a complete control sock)2.741 F .241 +(et transaction to complete [2m, none].)-.1 F 25.05(hoststatus\210 Ho) +117 336.2 R 4.141(wl)-.25 G 1.642 +(ong status information about a host \(e.g., host do)-4.141 F 1.642 +(wn\) will be cached)-.25 F +(before it is considered stale [30m, unspeci\214ed].)189 348.2 Q(resolv) +117 364.4 Q(er)-.15 E 8.28(.retrans The)-.55 F(resolv)4.275 E(er')-.15 E +4.275(sr)-.55 G 1.775(etransmission time interv)-4.275 F 1.774 +(al \(in seconds\) [v)-.25 F 4.274(aries]. Sets)-.25 F(both)4.274 E F2 +-.55(Ti)189 376.4 S(meout.r).55 E(esolver)-.37 E(.r)-1.11 E(etr)-.37 E +(ans.\214r)-.15 E(st)-.1 E F1(and)2.5 E F2 -.55(Ti)2.5 G(meout.r).55 E +(esolver)-.37 E(.r)-1.11 E(etr)-.37 E(ans.normal)-.15 E F1(.)A(resolv) +117 392.6 Q(er)-.15 E(.retrans.\214rst)-.55 E .317(The resolv)189 404.6 +R(er')-.15 E 2.817(sr)-.55 G .317(etransmission time interv)-2.817 F +.317(al \(in seconds\) for the \214rst attempt to)-.25 F(deli)189 416.6 +Q -.15(ve)-.25 G 2.5(ram).15 G(essage [v)-2.5 E(aries].)-.25 E(resolv) +117 432.8 Q(er)-.15 E(.retrans.normal)-.55 E 3.555(The resolv)189 444.8 +R(er')-.15 E 6.055(sr)-.55 G 3.555(etransmission time interv)-6.055 F +3.554(al \(in seconds\) for all resolv)-.25 F(er)-.15 E(lookups e)189 +456.8 Q(xcept the \214rst deli)-.15 E -.15(ve)-.25 G(ry attempt [v).15 E +(aries].)-.25 E(resolv)117 473 Q(er)-.15 E 16.61(.retry The)-.55 F 3.838 +(number of times to retransmit a resolv)6.338 F 3.838(er query)-.15 F +8.838(.S)-.65 G 3.839(ets both)-8.838 F F2 -.55(Ti)6.339 G(me-).55 E +(out.r)189 485 Q(esolver)-.37 E(.r)-1.11 E(etry)-.37 E(.\214r)-.55 E(st) +-.1 E F1(and)2.5 E F2 -.55(Ti)2.5 G(meout.r).55 E(esolver)-.37 E(.r) +-1.11 E(etry)-.37 E(.normal)-.55 E F1([v)2.5 E(aries].)-.25 E(resolv)117 +501.2 Q(er)-.15 E(.retry)-.55 E -.8(.\214rst The)-.65 F 1.66 +(number of times to retransmit a resolv)4.16 F 1.66 +(er query for the \214rst attempt to)-.15 F(deli)189 513.2 Q -.15(ve) +-.25 G 2.5(ram).15 G(essage [v)-2.5 E(aries].)-.25 E(resolv)117 529.4 Q +(er)-.15 E(.retry)-.55 E(.normal)-.65 E +(The number of times to retransmit a resolv)189 541.4 Q +(er query for all resolv)-.15 E(er lookups)-.15 E -.15(ex)191.5 553.4 S +(cept the \214rst deli).15 E -.15(ve)-.25 G(ry attempt [v).15 E(aries].) +-.25 E -.15(Fo)117 569.6 S 4.608(rc).15 G 2.108 +(ompatibility with old con\214guration \214les, if no)-4.608 F F2 +(suboption)4.609 E F1 2.109(is speci\214ed, all the timeouts)4.609 F +(mark)117 581.6 Q .059 +(ed with a dagger \(\207\) are set to the indicated v)-.1 F 2.559 +(alue. All)-.25 F -.2(bu)2.559 G 2.559(tt).2 G .059(hose mark)-2.559 F +.059(ed with a double dag-)-.1 F(ger \(\210\) apply to client SMTP)117 +593.6 Q(.)-1.11 E(Man)142 609.8 Q 2.5(yo)-.15 G 2.5(ft)-2.5 G +(he RFC 1123 minimum v)-2.5 E .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) +-2.501 F .712 +(the RFC 822 protocols, which did not specify read timeouts; hence, v) +117 621.8 R .711(ersions of)-.15 F F2(sendmail)3.211 E F1(prior)3.211 E +.864(to v)117 633.8 R .865 +(ersion 8.1 did not guarantee to reply to messages promptly)-.15 F 5.865 +(.I)-.65 G 3.365(np)-5.865 G(articular)-3.365 E 3.365(,a\231)-.4 G .865 +(RCPT\232 com-)-3.365 F .061(mand specifying a mailing list will e)117 +645.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)-2.56 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(13)93.6 +689.2 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)-2 E(.) +-.52 E EP +%%Page: 25 21 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-25)195.86 E/F1 10/Times-Roman@0 SF .436(may easily tak)117 98 R +2.936(em)-.1 G .436(ore than \214v)-2.936 F 2.936(em)-.15 G(inutes) +-2.936 E/F2 7/Times-Roman@0 SF(14)-4 I F1 5.436(.I)4 K .435 +(recommend a one hour timeout \212 since a commu-)-2.5 F 1.365 +(nications f)117 110 R 1.366(ailure during the RCPT phase is rare, a lo\ +ng timeout is not onerous and may ulti-)-.1 F(mately help reduce netw) +117 122 Q(ork load and duplicated messages.)-.1 E -.15(Fo)142 138.2 S +2.5(re).15 G(xample, the lines:)-2.65 E 2.5(OT)157 154.4 S +(imeout.command=25m)-2.85 E 2.5(OT)157 166.4 S(imeout.datablock=3h)-2.85 +E .344(sets the serv)117 182.6 R .344(er SMTP command timeout to 25 min\ +utes and the input data block timeout to three)-.15 F(hours.)117 194.6 Q +F0 2.5(4.1.3. Message)102 218.6 R(timeouts)2.5 E F1 .237 +(After sitting in the queue for a fe)142 234.8 R 2.737(wd)-.25 G .237 +(ays, a message will time out.)-2.737 F .238(This is to insure that at) +5.238 F .568(least the sender is a)117 246.8 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 258.8 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 .176(the queue longer than a fe)117 270.8 R 2.675(wh)-.25 G .175 +(ours \(assuming you normally ha)-2.675 F .475 -.15(ve g)-.2 H .175 +(ood connecti).15 F .175(vity; if your mes-)-.25 F .645 +(sages normally took se)117 282.8 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)-3.245 F(ouldn')-.1 E 3.145(tb)-.18 G(e) +-3.145 E .058(an unusual e)117 294.8 R -.15(ve)-.25 G 2.558(nt\). These) +.15 F .057(timeouts are set using the)2.557 F F0 -.18(Ti)2.557 G +(meout.queuer).18 E(etur)-.18 E(n)-.15 E F1(and)2.557 E F0 -.18(Ti)2.557 +G(meout.queue-).18 E(war)117 306.8 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 +1.367(If the message is submitted using the)142 323 R/F3 9/Times-Roman@0 +SF(NO)3.867 E 1.617(TIFY SMTP)-.36 F F1 -.15(ex)3.868 G 1.368 +(tension, w).15 F 1.368(arning messages will)-.1 F .888(only be sent if) +117 335 R F3(NO)3.388 E(TIFY=DELA)-.36 E(Y)-.945 E F1 .888 +(is speci\214ed.)3.388 F .888(The queuereturn and queue)5.888 F -.1(wa) +-.25 G .888(rn timeouts can be).1 F .669(further quali\214ed with a tag\ + based on the Precedence: \214eld in the message; the)117 347 R 3.17(ym) +-.15 G .67(ust be one of)-3.17 F(\231ur)117 359 Q .096 +(gent\232 \(indicating a positi)-.18 F .396 -.15(ve n)-.25 H .095(on-ze\ +ro precedence\) \231normal\232 \(indicating a zero precedence\), or).15 +F(\231non-ur)117 371 Q 5.541(gent\232 \(indicating ne)-.18 F -.05(ga) +-.15 G(ti).05 E 5.841 -.15(ve p)-.25 H 8.041(recedences\). F).15 F 5.542 +(or e)-.15 F 5.542(xample, setting \231T)-.15 F(imeout.queue-)-.35 E -.1 +(wa)117 383 S(rn.ur).1 E .486(gent=1h\232 sets the w)-.18 F .486 +(arning timeout for ur)-.1 F .486(gent messages only to one hour)-.18 F +5.485(.T)-.55 G .485(he def)-5.485 F .485(ault if)-.1 F 1.214 +(no precedence is indicated is to set the timeout for all precedences.) +117 395 R 1.215(The v)6.215 F 1.215(alue "no)-.25 F 1.215(w" can be)-.25 +F 2.067(used for -O T)117 407 R 2.066(imeout.queuereturn to return entr\ +ies immediately during a queue run, e.g., to)-.35 F +(bounce messages independent of their time in the queue.)117 419 Q .106 +(Since these options are global, and since you can not kno)142 435.2 R +(w)-.25 E/F4 10/Times-Italic@0 SF 2.606(ap)2.606 G(riori)-2.606 E F1(ho) +2.607 E 2.607(wl)-.25 G .107(ong another host)-2.607 F .476 +(outside your domain will be do)117 447.2 R .475(wn, a \214v)-.25 F +2.975(ed)-.15 G .475(ay timeout is recommended.)-2.975 F .475(This allo) +5.475 F .475(ws a recipient)-.25 F 1.579(to \214x the problem e)117 +459.2 R -.15(ve)-.25 G 4.079(ni).15 G 4.079(fi)-4.079 G 4.079(to)-4.079 +G 1.579(ccurs at the be)-4.079 F 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 471.2 Q +(`at least 4\2555 days')-.74 E('.)-.74 E(The)142 487.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 499.4 R +.845(arning message should be sent; the tw)-.1 F 3.346(ot)-.1 G .846 +(imeouts are separated by a slash.)-3.346 F -.15(Fo)5.846 G(r).15 E -.15 +(ex)117 511.4 S(ample, the line).15 E -.4(OT)157 527.6 S(5d/4h).4 E .972 +(causes email to f)117 543.8 R .971(ail after \214v)-.1 F 3.471(ed)-.15 +G .971(ays, b)-3.471 F .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 555.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 579.8 R(orking During Queue Runs)-.25 E F1 .848 +(By setting the)127 596 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,)-3.348 E F4(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 608 R .293(This will pre)5.293 F -.15(ve) +-.25 G(nt).15 E F4(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)-2.792 E 1.11 +(it may be useful in memory-poor en)102 620 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)-3.61 E F0 +-.25(Fo)3.61 G(rkEachJ).25 E(ob)-.15 E F1 1.11(option is not set,)3.61 F +F4(sendmail)102 632 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 644 Q(.)-.65 E(If the)127 660.2 Q F0 +-.25(Fo)2.5 G(rkEachJ).25 E(ob)-.15 E F1(option is set,)2.5 E F4 +(sendmail)2.5 E F1(can not use connection caching.)2.5 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/F5 5/Times-Roman@0 SF(14)93.6 +689.2 Q/F6 8/Times-Roman@0 SF .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: 26 22 +%%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 2.5(4.3. Queue)87 96 R +(Priorities)2.5 E/F1 10/Times-Roman@0 SF(Ev)127 112.2 Q 1.128(ery messa\ +ge is assigned a priority when it is \214rst instantiated, consisting o\ +f the message)-.15 F .286(size \(in bytes\) of)102 124.2 R .286(fset by\ + the message class \(which is determined from the Precedence: header\) \ +times)-.25 F .342(the \231w)102 136.2 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 148.2 R .073(Hig\ +her numbers for the priority mean that the message will be processed) +5.073 F(later when running the queue.)102 160.2 Q .328 +(The message size is included so that lar)127 176.4 R .329 +(ge messages are penalized relati)-.18 F .629 -.15(ve t)-.25 H 2.829(os) +.15 G .329(mall messages.)-2.829 F .285(The message class allo)102 188.4 +R .285(ws users to send \231high priority\232 messages by including a \ +\231Precedence:\232 \214eld)-.25 F .007(in their message; the v)102 +200.4 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 212.4 R 1.967(fect\ +s the amount of load a message presents to the system, this is also)-.25 +F(included into the priority)102 224.4 Q(.)-.65 E .53 +(The recipient and class f)127 240.6 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 252.6 Q F0(y)A F1 3.443(\)a)C +(nd)-3.443 E F0(ClassF)3.443 E(actor)-.25 E F1(\()3.442 E F0(z)A F1 +3.442(\)o)C .942(ptions respecti)-3.442 F -.15(ve)-.25 G(ly).15 E 5.942 +(.T)-.65 G(he)-5.942 E 3.442(yd)-.15 G(ef)-3.442 E .942 +(ault to 30000 \(for the recipient f)-.1 F .942(actor\) and)-.1 F +(1800 \(for the class f)102 264.6 Q 2.5(actor\). The)-.1 F +(initial priority is:)2.5 E/F2 10/Times-Italic@0 SF(pri)168.495 282.6 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 F32.47 E F0(ClassFactor\))2.2 E F3(+)2.2 E F1(\()2.2 E +F2(nrcpt).36 E F32.88 E F0(RecipientFactor\))2.2 E F1(\(Remember)102 +300.6 Q 3.328(,h)-.4 G .828(igher v)-3.328 F .828(alues for this parame\ +ter actually mean that the job will be treated with lo)-.25 F(wer)-.25 E +(priority)102 312.6 Q(.\))-.65 E 1.519(The priority of a job can also b\ +e adjusted each time it is processed \(that is, each time an)127 328.8 R +.235(attempt is made to deli)102 340.8 R -.15(ve)-.25 G 2.736(ri).15 G +.236(t\) using the \231w)-2.736 F .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)-2.736 F .367 +(is added to the priority)102 352.8 R 2.867(,s)-.65 G 2.867(oi)-2.867 G +2.867(tn)-2.867 G .366 +(ormally decreases the precedence of the job, on the grounds that jobs) +-2.867 F .137(that ha)102 364.8 R .437 -.15(ve f)-.2 H .137(ailed man) +.05 F 2.637(yt)-.15 G .137(imes will tend to f)-2.637 F .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 376.8 Q +F0 2.5(4.4. Load)87 400.8 R(Limiting)2.5 E F2(Sendmail)127 417 Q F1 .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 429 R F0(QueueLA)2.983 +E F1(\()2.983 E F0(x)A F1 2.983(\)o)C 2.983(ption. When)-2.983 F .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 F1(option,)2.984 E +.532(the deli)102 441 R -.15(ve)-.25 G .532(ry mode is set to).15 F F0 +(q)3.032 E F1 .532(\(queue only\) if the)3.032 F F0(QueueF)3.032 E +(actor)-.25 E F1(\()3.032 E F0(q)A F1 3.032(\)o)C .531(ption di)-3.032 F +.531(vided by the dif)-.25 F(ference)-.25 E .004(in the current load a) +102 453 R -.15(ve)-.2 G .004(rage and the).15 F F0(QueueLA)2.504 E F1 +.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 465 Q(f:)-.25 E F2(pri)251.425 +488.41 Q F1(>)3.16 E F0(QueueFactor)15.315 -7 M F2(LA)-66.835 14 M F3(-) +2.23 E F0(QueueLA)2.2 E F3(+)2.2 E .4 LW 354.625 485.81 275.895 485.81 +DL F1(1)349.625 495.41 Q(The)102 511.67 Q F0(QueueF)2.616 E(actor)-.25 E +F1 .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 523.67 Q -.15(ve)-.15 G(\).).15 E -.15 +(Fo)127 539.87 S 3.893(rd).15 G 1.393(rastic cases, the)-3.893 F F0 +(RefuseLA)3.893 E F1(\()3.893 E F0(X)A F1 3.893(\)o)C 1.394 +(ption de\214nes a load a)-3.893 F -.15(ve)-.2 G 1.394(rage at which).15 +F F2(sendmail)3.894 E F1(will)3.894 E .69(refuse to accept netw)102 +551.87 R .689(ork connections.)-.1 F .689 +(Locally generated mail \(including incoming UUCP mail\) is)5.689 F +(still accepted.)102 563.87 Q F0 2.5(4.5. Deli)87 587.87 R -.1(ve)-.1 G +(ry Mode).1 E F1 .253(There are a number of deli)127 604.07 R -.15(ve) +-.25 G .253(ry modes that).15 F F2(sendmail)2.753 E F1 .254 +(can operate in, set by the)2.753 F F0(Deli)2.754 E -.1(ve)-.1 G(ryMode) +.1 E F1(\()102 616.07 Q F0(d)A F1 3.599(\)c)C 1.099 +(on\214guration option.)-3.599 F 1.099(These modes specify ho)6.099 F +3.598(wq)-.25 G 1.098(uickly mail will be deli)-3.598 F -.15(ve)-.25 G +3.598(red. Le).15 F -.05(ga)-.15 G 3.598(lm).05 G(odes)-3.598 E(are:)102 +628.07 Q 17.22(id)142 644.27 S(eli)-17.22 E -.15(ve)-.25 G 2.5(ri).15 G +(nteracti)-2.5 E -.15(ve)-.25 G(ly \(synchronously\)).15 E 15(bd)142 +656.27 S(eli)-15 E -.15(ve)-.25 G 2.5(ri).15 G 2.5(nb)-2.5 G +(ackground \(asynchronously\))-2.5 E 15(qq)142 668.27 S +(ueue only \(don')-15 E 2.5(td)-.18 G(eli)-2.5 E -.15(ve)-.25 G(r\)).15 +E 15(dd)142 680.27 S(efer delv)-15 E(ery attempts \(don')-.15 E 2.5(td) +-.18 G(eli)-2.5 E -.15(ve)-.25 G(r\)).15 E 1.273(There are tradeof)102 +696.47 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)-3.773 F 1.273(est feedback, b) +-.1 F 1.274(ut may slo)-.2 F 3.774(wd)-.25 G -.25(ow)-3.774 G 3.774(ns) +.25 G(ome)-3.774 E .799(mailers and is hardly e)102 708.47 R -.15(ve) +-.25 G 3.299(rn).15 G(ecessary)-3.299 E 5.799(.M)-.65 G .799 +(ode \231b\232 deli)-5.799 F -.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 720.47 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)-2.724 F .224 +(\231q\232 minimizes the)2.724 F EP +%%Page: 27 23 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-27)195.86 E/F1 10/Times-Roman@0 SF .597(load on your machine, b) +102 96 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 108 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 120 R .086(`dial on demand')-.74 F 2.586('s)-.74 G +.085(ites where DNS lookups might cost real mone)-2.586 F 3.885 -.65 +(y. S)-.15 H .085(ome simple error).65 F .817 +(messages \(e.g., host unkno)102 132 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 144 Q(ault.)-.1 E .052(If \ +you run in mode \231q\232 \(queue only\), \231d\232 \(defer\), or \231b\ +\232 \(deli)127 160.2 R -.15(ve)-.25 G 2.552(ri).15 G 2.552(nb)-2.552 G +(ackground\))-2.552 E/F2 10/Times-Italic@0 SF(sendmail)2.551 E F1(will) +2.551 E 1.391(not e)102 172.2 R 1.392(xpand aliases and follo)-.15 F +3.892(w.)-.25 G(forw)-3.892 E 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 184.2 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 208.2 R(Le)2.5 E -.1(ve)-.15 G(l).1 E F1 .19(The le) +127 224.4 R -.15(ve)-.25 G 2.69(lo).15 G 2.69(fl)-2.69 G .19 +(ogging can be set for)-2.69 F F2(sendmail)2.689 E F1 5.189(.T)C .189 +(he def)-5.189 F .189(ault using a standard con\214guration table)-.1 F +(is le)102 236.4 Q -.15(ve)-.25 G 2.5(l9).15 G 5(.T)-2.5 G(he le)-5 E +-.15(ve)-.25 G(ls are as follo).15 E(ws:)-.25 E 31(0M)102 252.6 S +(inimal logging.)-31 E 31(1S)102 268.8 S(erious system f)-31 E +(ailures and potential security problems.)-.1 E 31(2L)102 285 S +(ost communications \(netw)-31 E(ork problems\) and protocol f)-.1 E +(ailures.)-.1 E 31(3O)102 301.2 S 1.237(ther serious f)-31 F 1.237 +(ailures, malformed addresses, transient forw)-.1 F 1.238 +(ard/include errors, connection)-.1 F(timeouts.)138 313.2 Q 31(4M)102 +329.4 S(inor f)-31 E(ailures, out of date alias databases, connection r\ +ejections via check_ rulesets.)-.1 E 31(5M)102 345.6 S +(essage collection statistics.)-31 E 31(6C)102 361.8 S +(reation of error messages, VRFY and EXPN commands.)-31 E 31(7D)102 378 +S(eli)-31 E -.15(ve)-.25 G(ry f).15 E(ailures \(host or user unkno)-.1 E +(wn, etc.\).)-.25 E 31(8S)102 394.2 S(uccessful deli)-31 E -.15(ve)-.25 +G(ries and alias database reb).15 E(uilds.)-.2 E 31(9M)102 410.4 S +(essages being deferred \(due to a host being do)-31 E(wn, etc.\).)-.25 +E 23.5(10 Database)102 426.6 R -.15(ex)2.5 G(pansion \(alias, forw).15 E +(ard, and userdb lookups\).)-.1 E 23.5(11 NIS)102 442.8 R +(errors and end of job processing.)2.5 E 23.5(12 Logs)102 459 R +(all SMTP connections.)2.5 E 23.5(13 Log)102 475.2 R(bad user shells, \ +\214les with improper permissions, and other questionable situations.) +2.5 E 23.5(14 Logs)102 491.4 R(refused connections.)2.5 E 23.5(15 Log) +102 507.6 R(all incoming and outgoing SMTP commands.)2.5 E 23.5(20 Logs) +102 523.8 R .603(attempts to run lock)3.103 F .603(ed queue \214les.)-.1 +F .603(These are not errors, b)5.603 F .603(ut can be useful to note if) +-.2 F(your queue appears to be clogged.)138 535.8 Q 23.5(30 Lost)102 552 +R(locks \(only if using lockf instead of \215ock\).)2.5 E(Additionally) +102 568.2 Q 2.716(,v)-.65 G .216(alues abo)-2.966 F .516 -.15(ve 6)-.15 +H 2.716(4a).15 G .216(re reserv)-2.716 F .216(ed for e)-.15 F .216 +(xtremely v)-.15 F .216(erbose deb)-.15 F .216(ugging output.)-.2 F .217 +(No normal site)5.216 F -.1(wo)102 580.2 S(uld e).1 E -.15(ve)-.25 G 2.5 +(rs).15 G(et these.)-2.5 E F0 2.5(4.7. File)87 604.2 R(Modes)2.5 E F1 +.264(The modes used for \214les depend on what functionality you w)127 +620.4 R .264(ant and the le)-.1 F -.15(ve)-.25 G 2.763(lo).15 G 2.763 +(fs)-2.763 G .263(ecurity you)-2.763 F 2.56(require. In)102 632.4 R(man) +2.56 E 2.56(yc)-.15 G(ases)-2.56 E F2(sendmail)2.56 E F1 .061 +(does careful checking of the modes of \214les and directories to a)2.56 +F -.2(vo)-.2 G(id).2 E 1.336(accidental compromise; if you w)102 644.4 R +1.336(ant to mak)-.1 F 3.836(ei)-.1 G 3.836(tp)-3.836 G 1.336 +(ossible to ha)-3.836 F 1.635 -.15(ve g)-.2 H 1.335 +(roup-writable support \214les you).15 F(may need to use the)102 656.4 Q +F0(DontBlameSendmail)2.5 E F1(option to turn of)2.5 E 2.5(fs)-.25 G +(ome of these checks.)-2.5 E F0 2.5(4.7.1. T)102 680.4 R 2.5(os)-.92 G +(uid or not to suid?)-2.5 E F2(Sendmail)142 696.6 Q F1 .66 +(is normally installed setuid to root.)3.16 F .66 +(At the point where it is about to)5.66 F F2 -.2(ex)3.161 G(ec).2 E F1 +.661(\(2\) a)1.666 F(mailer)117 708.6 Q 3.679(,i)-.4 G 3.679(tc)-3.679 G +1.178(hecks to see if the userid is zero \(root\); if so, it resets the\ + userid and groupid to a)-3.679 F(def)117 720.6 Q 1.391 +(ault \(set by the)-.1 F F0(U=)3.891 E F1 1.392 +(equate in the mailer line; if that is not set, the)3.891 F F0 +(DefaultUser)3.892 E F1 1.392(option is)3.892 F EP +%%Page: 28 24 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-28 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 2.848 +(used\). This)117 96 R .348(can be o)2.848 F -.15(ve)-.15 G .347 +(rridden by setting the).15 F F0(S)2.847 E F1 .347 +(\215ag to the mailer for mailers that are trusted and)2.847 F .541 +(must be called as root.)117 108 R(Ho)5.541 E(we)-.25 E -.15(ve)-.25 G +1.341 -.4(r, t).15 H .541 +(his will cause mail processing to be accounted \(using).4 F/F2 10 +/Times-Italic@0 SF(sa)3.041 E F1(\(8\)\))1.666 E +(to root rather than to the user sending the mail.)117 120 Q .339 +(If you don')142 136.2 R 2.839(tm)-.18 G(ak)-2.839 E(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 148.2 R -.25(va)-.25 G -.15(cy).25 G 2.507(,s)-.5 G .008(ince you') +-2.507 F .008(ll ha)-.1 F .308 -.15(ve t)-.2 H 2.508(om).15 G(ak)-2.508 +E 2.508(et)-.1 G .008(he queue directory w)-2.508 F .008(orld readable.) +-.1 F -1.1(Yo)5.008 G 2.508(uc)1.1 G(ould)-2.508 E .501(also mak)117 +160.2 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 172.2 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 184.2 R +3.142(tag)-.18 G .641(uarantee of security: for e)-3.142 F .641 +(xample, root occasionally sends mail, and the dae-)-.15 F .119 +(mon often runs as root.)117 196.2 R .119(Note ho)5.119 F(we)-.25 E -.15 +(ve)-.25 G 2.619(rt).15 G(hat)-2.619 E F2(sendmail)2.619 E F1 .12 +(must run as root or the trusted user in order)2.619 F +(to create the SMTP listener sock)117 208.2 Q(et.)-.1 E 2.839(Am)142 +224.4 S .339(iddle ground is to mak)-2.839 F(e)-.1 E F2(sendmail)2.839 E +F1 .339(setuid to root, b)2.839 F .338(ut set the)-.2 F F0(RunAsUser) +2.838 E F1 2.838(option. This)2.838 F(causes)117 236.4 Q F2(sendmail) +2.572 E F1 .072(to become the indicated user as soon as it has done the\ + startup that requires root)2.572 F(pri)117 248.4 Q(vile)-.25 E 1.226 +(ges \(primarily)-.15 F 3.726(,o)-.65 G 1.225(pening the)-3.726 F/F3 9 +/Times-Roman@0 SF(SMTP)3.725 E F1(sock)3.725 E 3.725(et\). If)-.1 F +1.225(you use)3.725 F F0(RunAsUser)3.725 E F1 3.725(,t)C 1.225 +(he queue directory)-3.725 F(\(normally)117 260.4 Q F2 +(/var/spool/mqueue)2.921 E F1 2.921(\)s)C .421(hould be o)-2.921 F .421 +(wned by that user)-.25 F 2.922(,a)-.4 G .422 +(nd all \214les and databases \(includ-)-2.922 F 1.175(ing user)117 +272.4 R F2(.forwar)3.675 E(d)-.37 E F1 1.175 +(\214les, alias \214les, :include: \214les, and e)3.675 F 1.175 +(xternal databases\) must be readable by)-.15 F .551(that user)117 284.4 +R 5.551(.A)-.55 G .551 +(lso, since sendmail will not be able to change it')-5.551 F 3.051(su) +-.55 G .551(id, deli)-3.051 F -.15(ve)-.25 G .552 +(ry to programs or \214les).15 F .502(will be mark)117 296.4 R .502 +(ed as unsafe, e.g., undeli)-.1 F -.15(ve)-.25 G .502(rable, in).15 F F2 +(.forwar)3.001 E(d)-.37 E F1 3.001(,a)C .501 +(liases, and :include: \214les.)-3.001 F(Adminis-)5.501 E 1.581 +(trators can o)117 308.4 R -.15(ve)-.15 G 1.581 +(rride this by setting the).15 F F0(DontBlameSendmail)4.082 E F1 1.582 +(option to the setting)4.082 F F0(NonRoot-)4.082 E(SafeAddr)117 320.4 Q +F1(.)A F0(RunAsUser)5.395 E F1 .395(is probably best suited for \214re) +2.895 F -.1(wa)-.25 G .395(ll con\214gurations that don').1 F 2.895(th) +-.18 G -2.25 -.2(av e)-2.895 H(re)3.095 E(gu-)-.15 E(lar user logins.) +117 332.4 Q F0 2.5(4.7.2. T)102 356.4 R(ur)-.92 E +(ning off security checks)-.15 E F2(Sendmail)142 372.6 Q F1 .648(is v) +3.148 F .648 +(ery particular about the modes of \214les that it reads or writes.)-.15 +F -.15(Fo)5.648 G 3.148(re).15 G(xample,)-3.298 E .251(by def)117 384.6 +R .251(ault it will refuse to read most \214les that are group writable\ + on the grounds that the)-.1 F 2.75(ym)-.15 G(ight)-2.75 E(ha)117 396.6 +Q 1.215 -.15(ve b)-.2 H .916 +(een tampered with by someone other than the o).15 F .916 +(wner; it will e)-.25 F -.15(ve)-.25 G 3.416(nr).15 G .916 +(efuse to read \214les in)-3.416 F(group writable directories.)117 408.6 +Q .438(If you are)142 424.8 R F2(quite)2.938 E F1 .438 +(sure that your con\214guration is safe and you w)2.938 F(ant)-.1 E F2 +(sendmail)2.937 E F1 .437(to a)2.937 F -.2(vo)-.2 G .437(id these).2 F +1.186(security checks, you can turn of)117 436.8 R 3.687(fc)-.25 G 1.187 +(ertain checks using the)-3.687 F F0(DontBlameSendmail)3.687 E F1 3.687 +(option. This)3.687 F 1.39(option tak)117 448.8 R 1.389 +(es one or more names that disable checks.)-.1 F 1.389 +(In the descriptions that follo)6.389 F 2.689 -.65(w, \231)-.25 H +(unsafe).65 E(directory\232 means a directory that is writable by an)117 +460.8 Q(yone other than the o)-.15 E(wner)-.25 E 5(.T)-.55 G(he v)-5 E +(alues are:)-.25 E 15.73(Safe No)117 477 R(special handling.)2.5 E +(AssumeSafeCho)117 493.2 Q(wn)-.25 E .769(Assume that the)153 505.2 R F2 +-.15(ch)3.269 G(own).15 E F1 .769(system call is restricted to root.) +3.269 F .77(Since some v)5.769 F .77(ersions of Unix)-.15 F .866 +(permit re)153 517.2 R .866(gular users to gi)-.15 F 1.166 -.15(ve aw) +-.25 H .866(ay their \214les to other users on some \214lesystems,).05 F +F2(send-)3.365 E(mail)153 529.2 Q F1 .456(often cannot assume that a gi) +2.956 F -.15(ve)-.25 G 2.956<6e8c>.15 G .456(le w)-2.956 F .457 +(as created by the o)-.1 F(wner)-.25 E 2.957(,p)-.4 G .457 +(articularly when)-2.957 F 1.475(it is in a writable directory)153 541.2 +R 6.475(.Y)-.65 G 1.475(ou can set this \215ag if you kno)-7.575 F 3.974 +(wt)-.25 G 1.474(hat \214le gi)-3.974 F -.15(ve)-.25 G -2.3 -.15(aw a) +.15 H 3.974(yi).15 G(s)-3.974 E(restricted on your system.)153 553.2 Q +(ClassFileInUnsafeDirP)117 569.4 Q(ath)-.15 E .493 +(When reading class \214les \(using the)153 581.4 R F0(F)2.993 E F1 .493 +(line in the con\214guration \214le\), allo)2.993 F 2.994<778c>-.25 G +.494(les that are)-2.994 F(in unsafe directories.)153 593.4 Q(DontW)117 +609.6 Q(arnF)-.8 E(orw)-.15 E(ardFileInUnsafeDirP)-.1 E(ath)-.15 E(Pre) +153 621.6 Q -.15(ve)-.25 G(nt logging of unsafe directory path w).15 E +(arnings for non-e)-.1 E(xistent forw)-.15 E(ard \214les.)-.1 E +(ErrorHeaderInUnsafeDirP)117 637.8 Q(ath)-.15 E(Allo)153 649.8 Q 2.5(wt) +-.25 G(he \214le named in the)-2.5 E F0(Err)2.5 E(orHeader)-.18 E F1 +(option to be in an unsafe directory)2.5 E(.)-.65 E(GroupWritableDirP) +117 666 Q(athSafe)-.15 E .224(Change the de\214nition of \231unsafe dir\ +ectory\232 to consider group-writable directories to be)153 678 R 2.5 +(safe. W)153 690 R(orld-writable directories are al)-.8 E -.1(wa)-.1 G +(ys unsafe.).1 E(GroupWritableF)117 706.2 Q(orw)-.15 E(ardFileSafe)-.1 E +(Accept group-writable)153 718.2 Q F2(.forwar)2.5 E(d)-.37 E F1 +(\214les.)2.5 E EP +%%Page: 29 25 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-29)195.86 E/F1 10/Times-Roman@0 SF(GroupWritableIncludeFileSafe) +117 96 Q(Accept group-writable)153 108 Q/F2 10/Times-Italic@0 SF +(:include:)2.5 E F1(\214les.)2.5 E(GroupWritableAliasFile)117 124.2 Q +(Allo)153 136.2 Q 2.5(wg)-.25 G(roup-writable alias \214les.)-2.5 E +(HelpFileInUnsafeDirP)117 152.4 Q(ath)-.15 E(Allo)153 164.4 Q 2.5(wt) +-.25 G(he \214le named in the)-2.5 E F0(HelpFile)2.5 E F1 +(option to be in an unsafe directory)2.5 E(.)-.65 E -.8(Wo)117 180.6 S +(rldWritableAliasFile).8 E(Accept w)153 192.6 Q +(orld-writable alias \214les.)-.1 E -.15(Fo)117 208.8 S(rw).15 E +(ardFileInGroupWritableDirP)-.1 E(ath)-.15 E(Allo)153 220.8 Q(w)-.25 E +F2(.forwar)2.5 E(d)-.37 E F1(\214les in group writable directories.)2.5 +E(IncludeFileInGroupWritableDirP)117 237 Q(ath)-.15 E(Allo)153 249 Q(w) +-.25 E F2(:include:)2.5 E F1(\214les in group writable directories.)2.5 +E -.15(Fo)117 265.2 S(rw).15 E(ardFileInUnsafeDirP)-.1 E(ath)-.15 E +(Allo)153 277.2 Q(w)-.25 E F2(.forwar)2.5 E(d)-.37 E F1 +(\214les in unsafe directories.)2.5 E(IncludeFileInUnsafeDirP)117 293.4 +Q(ath)-.15 E(Allo)153 305.4 Q(w)-.25 E F2(:include:)2.5 E F1 +(\214les in unsafe directories.)2.5 E -.15(Fo)117 321.6 S(rw).15 E +(ardFileInUnsafeDirP)-.1 E(athSafe)-.15 E(Allo)153 333.6 Q 2.612(wa)-.25 +G F2(.forwar)A(d)-.37 E F1 .112(\214le that is in an unsafe directory t\ +o include references to program and)2.612 F(\214les.)153 345.6 Q +(IncludeFileInUnsafeDirP)117 361.8 Q(athSafe)-.15 E(Allo)153 373.8 Q +3.706(wa)-.25 G F2(:include:)A F1 1.206 +(\214le that is in an unsafe directory to include references to program) +3.706 F(and \214les.)153 385.8 Q(MapInUnsafeDirP)117 402 Q(ath)-.15 E +(Allo)153 414 Q 2.5(wm)-.25 G(aps \(e.g.,)-2.5 E F2(hash)2.5 E F1(,)A F2 +(btr)2.5 E(ee)-.37 E F1 2.5(,a)C(nd)-2.5 E F2(dbm)2.5 E F1 +(\214les\) in unsafe directories.)2.5 E(Link)117 430.2 Q +(edAliasFileInWritableDir)-.1 E(Allo)153 442.2 Q 2.5(wa)-.25 G 2.5(na) +-2.5 G(lias \214le that is a link in a writable directory)-2.5 E(.)-.65 +E(Link)117 458.4 Q(edClassFileInWritableDir)-.1 E(Allo)153 470.4 Q 2.5 +(wc)-.25 G(lass \214les that are links in writable directories.)-2.5 E +(Link)117 486.6 Q(edF)-.1 E(orw)-.15 E(ardFileInWritableDir)-.1 E(Allo) +153 498.6 Q(w)-.25 E F2(.forwar)2.5 E(d)-.37 E F1 +(\214les that are links in writable directories.)2.5 E(Link)117 514.8 Q +(edIncludeFileInWritableDir)-.1 E(Allo)153 526.8 Q(w)-.25 E F2 +(:include:)2.5 E F1(\214les that are links in writable directories.)2.5 +E(Link)117 543 Q(edMapInWritableDir)-.1 E(Allo)153 555 Q 2.5(wm)-.25 G +(ap \214les that are links in writable directories.)-2.5 E(Link)117 +571.2 Q(edServiceSwitchFileInWritableDir)-.1 E(Allo)153 583.2 Q 2.5(wt) +-.25 G(he service switch \214le to be a link e)-2.5 E -.15(ve)-.25 G 2.5 +(ni).15 G 2.5(ft)-2.5 G(he directory is writable.)-2.5 E(FileDeli)117 +599.4 Q -.15(ve)-.25 G(ryT).15 E(oHardLink)-.8 E(Allo)153 611.4 Q 2.5 +(wd)-.25 G(eli)-2.5 E -.15(ve)-.25 G(ry to \214les that are hard links.) +.15 E(FileDeli)117 627.6 Q -.15(ve)-.25 G(ryT).15 E(oSymLink)-.8 E(Allo) +153 639.6 Q 2.5(wd)-.25 G(eli)-2.5 E -.15(ve)-.25 G +(ry to \214les that are symbolic links.).15 E(RunProgramInUnsafeDirP)117 +655.8 Q(ath)-.15 E +(Go ahead and run programs that are in writable directories.)153 667.8 Q +(RunWritableProgram)117 684 Q +(Go ahead and run programs that are group- or w)153 696 Q +(orld-writable.)-.1 E(WriteMapT)117 712.2 Q(oHardLink)-.8 E(Allo)153 +724.2 Q 2.5(ww)-.25 G(rites to maps that are hard links.)-2.5 E EP +%%Page: 30 26 +%%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 +(WriteMapT)117 96 Q(oSymLink)-.8 E(Allo)153 108 Q 2.5(ww)-.25 G +(rites to maps that are symbolic links.)-2.5 E(WriteStatsT)117 124.2 Q +(oHardLink)-.8 E(Allo)153 136.2 Q 2.5(wt)-.25 G +(he status \214le to be a hard link.)-2.5 E(WriteStatsT)117 152.4 Q +(oSymLink)-.8 E(Allo)153 164.4 Q 2.5(wt)-.25 G +(he status \214le to be a symbolic link.)-2.5 E -.35(Tr)117 180.6 S +(ustStick).35 E(yBit)-.15 E(Allo)153 192.6 Q 3.405(wg)-.25 G .905 +(roup or w)-3.405 F .905(orld writable directories if the stick)-.1 F +3.405(yb)-.15 G .906(it is set on the directory)-3.405 F 5.906(.D)-.65 G +(o)-5.906 E(not set this on systems which do not honor the stick)153 +204.6 Q 2.5(yb)-.15 G(it on directories.)-2.5 E(NonRootSafeAddr)117 +220.8 Q .485(Do not mark \214le and program deli)153 232.8 R -.15(ve) +-.25 G .484(ries as unsafe if sendmail is not running with root).15 F +(pri)153 244.8 Q(vile)-.25 E(ges.)-.15 E F0 2.5(4.8. Connection)87 268.8 +R(Caching)2.5 E F1 .642(When processing the queue,)127 285 R/F2 10 +/Times-Italic@0 SF(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) +-3.142 F -.2(avo)102 297 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 +313.2 R .286(If an open connection is found,)5.286 F 1.033 +(it is probed to see if it is still acti)102 325.2 R 1.333 -.15(ve b) +-.25 H 3.533(ys).15 G 1.033(ending a)-3.533 F/F3 9/Times-Roman@0 SF +(RSET)3.533 E F1 3.534(command. It)3.534 F 1.034 +(is not an error if this f)3.534 F(ails;)-.1 E +(instead, the connection is closed and reopened.)102 337.2 Q -1 -.8 +(Tw o)127 353.4 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)-2.908 F .145 +(the number of simultaneous open connections that will be permitted.)102 +365.4 R .145(If it is set to zero, connections)5.145 F .213 +(will be closed as quickly as possible.)102 377.4 R .212(The def)5.212 F +.212(ault is one.)-.1 F .212(This should be set as appropriate for your) +5.212 F .629 +(system size; it will limit the amount of system resources that)102 +389.4 R F2(sendmail)3.13 E F1 .63(will use during queue runs.)3.13 F(Ne) +102 401.4 Q -.15(ve)-.25 G 2.5(rs).15 G(et this higher than 4.)-2.5 E +(The)127 417.6 Q F0(ConnectionCacheT)2.741 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) +-2.741 F 2.741(yc)-.15 G .24(ached con-)-2.741 F .899 +(nection will be permitted to idle.)102 429.6 R .899 +(When the idle time e)5.899 F .9(xceeds this v)-.15 F .9 +(alue the connection is closed.)-.25 F .34 +(This number should be small \(under ten minutes\) to pre)102 441.6 R +-.15(ve)-.25 G .34(nt you from grabbing too man).15 F 2.84(yr)-.15 G +(esources)-2.84 E(from other hosts.)102 453.6 Q(The def)5 E +(ault is \214v)-.1 E 2.5(em)-.15 G(inutes.)-2.5 E F0 2.5(4.9. Name)87 +477.6 R(Ser)2.5 E -.1(ve)-.1 G 2.5(rA).1 G(ccess)-2.5 E F1 .103 +(Control of host address lookups is set by the)127 493.8 R F0(hosts) +2.604 E F1 .104(service entry in your service switch \214le.)2.604 F(If) +5.104 E .99(you are on a system that has b)102 505.8 R .99 +(uilt-in service switch support \(e.g., Ultrix, Solaris, or DEC OSF/1\)) +-.2 F .335(then your system is probably con\214gured properly already) +102 517.8 R 5.335(.O)-.65 G(therwise,)-5.335 E F2(sendmail)2.836 E F1 +.336(will consult the \214le)2.836 F F0(/etc/mail/ser)102 529.8 Q +(vice.switch)-.1 E F1 4.902(,w)C 2.402(hich should be created.)-4.902 F +F2(Sendmail)7.402 E F1 2.402(only uses tw)4.902 F 4.902(oe)-.1 G +(ntries:)-4.902 E F0(hosts)4.901 E F1(and)4.901 E F0(aliases)102 541.8 Q +F1 2.745(,a)C .246 +(lthough system routines may use other services \(notably the)-2.745 F +F0(passwd)2.746 E F1 .246(service for user name)2.746 F(lookups by)102 +553.8 Q F2 -.1(ge)2.5 G(tpwname).1 E F1(\).)A(Ho)127 570 Q(we)-.25 E +-.15(ve)-.25 G 1.511 -.4(r, s).15 H .711 +(ome systems \(such as SunOS 4.X\) will do DNS lookups re).4 F -.05(ga) +-.15 G .71(rdless of the setting).05 F 1.028 +(of the service switch entry)102 582 R 6.028(.I)-.65 G 3.529(np)-6.028 G +(articular)-3.529 E 3.529(,t)-.4 G 1.029(he system routine)-3.529 F F2 +-.1(ge)3.529 G(thostbyname).1 E F1 1.029(\(3\) is used to look up)B +1.869(host names, and man)102 594 R 4.369(yv)-.15 G 1.869(endor v)-4.519 +F 1.869(ersions try some combination of DNS, NIS, and \214le lookup in) +-.15 F 1.73(/etc/hosts without consulting a service switch.)102 606 R F2 +(Sendmail)6.731 E F1(mak)4.231 E 1.731(es no attempt to w)-.1 F 1.731 +(ork around this)-.1 F .368(problem, and the DNS lookup will be done an) +102 618 R(yw)-.15 E(ay)-.1 E 5.368(.I)-.65 G 2.868(fy)-5.368 G .367 +(ou do not ha)-2.868 F .667 -.15(ve a n)-.2 H(ameserv).15 E .367 +(er con\214gured at)-.15 F .464(all, such as at a UUCP-only site,)102 +630 R F2(sendmail)2.964 E F1 .464 +(will get a \231connection refused\232 message when it tries to)2.964 F +.424(connect to the name serv)102 642 R(er)-.15 E 5.424(.I)-.55 G 2.924 +(ft)-5.424 G(he)-2.924 E F0(hosts)2.924 E F1 .423 +(switch entry has the service \231dns\232 listed some)2.924 F .423 +(where in the)-.25 F(list,)102 654 Q F2(sendmail)3.312 E F1 .813 +(will interpret this to mean a temporary f)3.313 F .813 +(ailure and will queue the mail for later pro-)-.1 F +(cessing; otherwise, it ignores the name serv)102 666 Q(er data.)-.15 E +.673(The same technique is used to decide whether to do MX lookups.)127 +682.2 R .672(If you w)5.672 F .672(ant MX support,)-.1 F(you)102 694.2 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 710.4 Q F0(Resolv)3.869 E +(erOptions)-.1 E F1(\()3.869 E F0(I)A F1 3.869(\)o)C 1.369(ption allo) +-3.869 F 1.369(ws you to tweak name serv)-.25 F 1.369(er options.)-.15 F +1.37(The command)6.37 F .892(line tak)102 722.4 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 EP +%%Page: 31 27 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-31)195.86 E/F1 10/Times-Roman@0 SF +(can be preceded by an optional `+' or `)102 96 Q/F2 10/Symbol SF(-)A F1 +2.5('. F)B(or e)-.15 E(xample, the line)-.15 E 2.5(OR)142 112.2 S(esolv) +-2.5 E(erOptions=+AA)-.15 E(ONL)-.55 E(Y)-1 E F2(-)2.5 E F1(DNSRCH)A +.861(turns on the AA)102 128.4 R(ONL)-.55 E 3.361(Y\()-1 G .861 +(accept authoritati)-3.361 F 1.161 -.15(ve a)-.25 H .861 +(nswers only\) and turns of).15 F 3.362(ft)-.25 G .862 +(he DNSRCH \(search the)-3.362 F 2.039(domain path\) options.)102 140.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 152.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.973 +(card MX record matching your domain; this turns of)102 164.4 R 4.472 +(fM)-.25 G 4.472(Xm)-4.472 G 1.972(atching when canonifying names,) +-4.472 F(which can lead to inappropriate canoni\214cations.)102 176.4 Q +-1.11(Ve)127 192.6 S 2.256(rsion le)1.11 F -.15(ve)-.25 G 4.756(l1c).15 +G 2.256(on\214gurations turn DNSRCH and DEFN)-4.756 F 2.257(AMES of)-.35 +F 4.757(fw)-.25 G 2.257(hen doing deli)-4.757 F -.15(ve)-.25 G(ry).15 E +2.06(lookups, b)102 204.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/F3 10/Times-Italic@0 SF(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 +216.6 R -.1(wa)-.1 G .313(ys does the search.).1 F .313(If you don') +5.313 F 2.813(tw)-.18 G(ant)-2.913 E(to do automatic name e)102 228.6 Q +(xtension, don')-.15 E 2.5(tc)-.18 G(all $[ ... $].)-2.5 E .486 +(The search rules for $[ ... $] are some)127 244.8 R .485(what dif)-.25 +F .485(ferent than usual.)-.25 F .485(If the name being look)5.485 F +.485(ed up)-.1 F .109(has at least one dot, it al)102 256.8 R -.1(wa)-.1 +G .109(ys tries the unmodi\214ed name \214rst.).1 F .11(If that f)5.11 F +.11(ails, it tries the reduced search)-.1 F .124 +(path, and lastly tries the unmodi\214ed name \(b)102 268.8 R .124 +(ut only for names without a dot, since names with a dot)-.2 F(ha)102 +280.8 Q .788 -.15(ve a)-.2 H .488(lready been tried\).).15 F .488 +(This allo)5.488 F .489(ws names such as `)-.25 F(`utc.CS')-.74 E 2.989 +('t)-.74 G 2.989(om)-2.989 G .489(atch the site in Czechoslo)-2.989 F +-.25(va)-.15 G(kia).25 E 1.588 +(rather than the site in your local Computer Science department.)102 +292.8 R 1.587(It also prefers A and CN)6.587 F(AME)-.35 E .512 +(records o)102 304.8 R -.15(ve)-.15 G 3.012(rM).15 G 3.012(Xr)-3.012 G +.512(ecords \212 that is, if it \214nds an MX record it mak)-3.012 F +.513(es note of it, b)-.1 F .513(ut k)-.2 F .513(eeps looking.)-.1 F +1.542(This w)102 316.8 R(ay)-.1 E 4.042(,i)-.65 G 4.042(fy)-4.042 G +1.541(ou ha)-4.042 F 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 328.8 Q 3.453 -.8(To c)127 345 T 1.853 +(ompletely turn of).8 F 4.353(fa)-.25 G 1.853(ll name serv)-4.353 F +1.853(er access on systems without service switch support)-.15 F .942 +(\(such as SunOS 4.X\) you will ha)102 357 R 1.242 -.15(ve t)-.2 H 3.441 +(or).15 G .941(ecompile with \255DN)-3.441 F .941(AMED_BIND=0 and remo) +-.35 F 1.241 -.15(ve \255)-.15 H(lresolv).15 E +(from the list of libraries to be searched when linking.)102 369 Q F0 +2.5(4.10. Mo)87 393 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 409.2 R +3.272(sh)-.55 G .772(ome directory from a local disk on their w)-3.272 F +.772(orkstation, so that)-.1 F .576(local access is f)102 421.2 R 3.076 +(ast. Ho)-.1 F(we)-.25 E -.15(ve)-.25 G 1.376 -.4(r, t).15 H .575 +(he result is that .forw).4 F .575(ard \214le lookups are slo)-.1 F +4.375 -.65(w. I)-.25 H 3.075(ns).65 G .575(ome cases, mail)-3.075 F .216 +(can e)102 433.2 R -.15(ve)-.25 G 2.716(nb).15 G 2.716(ed)-2.716 G(eli) +-2.716 E -.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 445.2 Q(.) +-.55 E(The)127 461.4 Q F0 -.25(Fo)2.744 G(rwardP).25 E(ath)-.1 E F1(\() +2.744 E F0(J)A F1 2.743(\)o)C .243(ption allo)-2.743 F .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 .243(xample, the con-)-2.893 F(\214g \214le line) +102 473.4 Q 2.5(OF)142 489.6 S(orw)-2.65 E(ardP)-.1 E(ath=/v)-.15 E +(ar/forw)-.25 E(ard/$u:$z/.forw)-.1 E(ard.$w)-.1 E -.1(wo)102 505.8 S +.207(uld \214rst look for a \214le with the same name as the user').1 F +2.708(sl)-.55 G .208(ogin in /v)-2.708 F(ar/forw)-.25 E .208 +(ard; if that is not found)-.1 F 1.171 +(\(or is inaccessible\) the \214le `)102 517.8 R(`.forw)-.74 E(ard.)-.1 +E F3(mac)A(hinename)-.15 E F1 2.651 -.74('' i)D 3.671(nt).74 G 1.171 +(he user')-3.671 F 3.671(sh)-.55 G 1.17(ome directory is searched.) +-3.671 F(A)6.17 E(truly perv)102 529.8 Q +(erse site could also search by sender by using $r)-.15 E 2.5(,$)-.4 G +(s, or $f.)-2.5 E .69(If you create a directory such as /v)127 546 R +(ar/forw)-.25 E .69(ard, it should be mode 1777 \(that is, the stick)-.1 +F 3.19(yb)-.15 G(it)-3.19 E .135(should be set\).)102 558 R .135 +(Users should create the \214les mode 644.)5.135 F .134 +(Note that you must use the forw)5.134 F(ard\214leinun-)-.1 E 1.1 +(safedirpath and forw)102 570 R 1.1(ard\214leinunsafedirpathsafe \215ag\ +s with the DontBlameSendmail option to allo)-.1 F(w)-.25 E(forw)102 582 +Q 1.169(ard \214les in a w)-.1 F 1.169(orld writable directory)-.1 F +6.169(.T)-.65 G 1.169 +(his might also be used as a denial of service attack)-6.169 F .634 +(\(users could create forw)102 594 R .635 +(ard \214les for other users\); a better approach might be to create /v) +-.1 F(ar/forw)-.25 E(ard)-.1 E .661 +(mode 755 and create empty \214les for each user)102 606 R 3.161(,o)-.4 +G .661(wned by that user)-3.411 F 3.161(,m)-.4 G .661(ode 644.)-3.161 F +.661(If you do this, you)5.661 F(don')102 618 Q 2.5(th)-.18 G -2.25 -.2 +(av e)-2.5 H(to set the DontBlameSendmail options indicated abo)2.7 E +-.15(ve)-.15 G(.).15 E F0 2.5(4.11. Fr)87 642 R(ee Space)-.18 E F1 1.405 +(On systems that ha)127 658.2 R 1.705 -.15(ve o)-.2 H 1.405 +(ne of the system calls in the).15 F F3(statfs)3.906 E F1 1.406(\(2\) f) +B 1.406(amily \(including)-.1 F F3(statvfs)3.906 E F1(and)3.906 E F3 +(ustat)102 670.2 Q F1 .839(\), you can specify a minimum number of free\ + blocks on the queue \214lesystem using the)B F0(Min-)3.339 E(Fr)102 +682.2 Q(eeBlocks)-.18 E F1(\()2.553 E F0(b)A F1 2.553(\)o)C 2.553 +(ption. If)-2.553 F .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 694.2 R 1.355 +(er will reject mail with the 452 error code.)-.15 F(This)6.354 E(in)102 +706.2 Q(vites the SMTP client to try ag)-.4 E(ain later)-.05 E(.)-.55 E +EP +%%Page: 32 28 +%%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(Be)127 96 +Q -.1(wa)-.25 G .746(re of setting this option too high; it can cause r\ +ejection of email when that mail w).1 F(ould)-.1 E +(be processed without dif)102 108 Q(\214culty)-.25 E(.)-.65 E F0 2.5 +(4.12. Maximum)87 132 R(Message Size)2.5 E F1 2.078 -.8(To a)127 148.2 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 160.2 R 3.193(yo) +-.15 G .693(ne message.)-3.193 F .693(This will be adv)5.693 F .693 +(ertised in the ESMTP)-.15 F(dialogue and check)102 172.2 Q +(ed during message collection.)-.1 E F0 2.5(4.13. Pri)87 196.2 R -.1(va) +-.1 G(cy Flags).1 E F1(The)127 212.4 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)-2.96 F +.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)-2.96 E 2.96(yo)-.15 G(f)-2.96 E .533(them don')102 224.4 R 3.033 +(tg)-.18 G -2.15 -.25(iv e)-3.033 H .533(you an)3.283 F 3.034(ye)-.15 G +.534(xtra pri)-3.184 F -.25(va)-.25 G -.15(cy).25 G 3.034(,r)-.5 G .534 +(ather just insisting that client SMTP serv)-3.034 F .534 +(ers use the HELO)-.15 F 2.87 +(command before using certain commands or adding e)102 236.4 R 2.87 +(xtra headers to indicate possible spoof)-.15 F(attempts.)102 248.4 Q +.123(The option tak)127 264.6 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)-2.624 F .424 -.15(ve o) +-.25 H 2.624(ro).15 G 2.624(ft)-2.624 G .124(hose \215ags.)-2.624 F -.15 +(Fo)5.124 G(r).15 E -.15(ex)102 276.6 S(ample:).15 E 2.5(OP)142 292.8 S +(ri)-2.5 E -.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 309 R(ables the EXPN command.)102 +321 Q(The \215ags are detailed in section 5.6.)127 337.2 Q F0 2.5 +(4.14. Send)87 361.2 R(to Me T)2.5 E(oo)-.92 E F1(Be)127 377.4 Q 1.074 +(ginning with v)-.15 F 1.074(ersion 8.10,)-.15 F/F2 10/Times-Italic@0 SF +(sendmail)3.574 E F1 1.075(includes by def)3.574 F 1.075(ault the \(en) +-.1 F -.15(ve)-.4 G 1.075(lope\) sender in an).15 F 3.575(yl)-.15 G(ist) +-3.575 E -.15(ex)102 389.4 S 3.465(pansions. F).15 F .965(or e)-.15 F +.964(xample, if \231matt\232 sends to a list that contains \231matt\232\ + as one of the members he)-.15 F .227(will get a cop)102 401.4 R 2.727 +(yo)-.1 G 2.727(ft)-2.727 G .227(he message.)-2.727 F .227(If the)5.227 +F F0(MeT)2.728 E(oo)-.92 E F1 .228(option is set to)2.728 F/F3 9 +/Times-Roman@0 SF -.666(FA)2.728 G(LSE).666 E F1 .228 +(\(in the con\214guration \214le or via)2.728 F 1.023 +(the command line\), this beha)102 413.4 R 1.023 +(vior is changed, i.e., the \(en)-.2 F -.15(ve)-.4 G 1.022 +(lope\) sender is e).15 F 1.022(xcluded in list e)-.15 F(xpan-)-.15 E +(sions.)102 425.4 Q F0 2.5(5. THE)72 449.4 R +(WHOLE SCOOP ON THE CONFIGURA)2.5 E(TION FILE)-.95 E F1 +(This section describes the con\214guration \214le in detail.)112 465.6 +Q .648(There is one point that should be made clear immediately: the sy\ +ntax of the con\214guration \214le is)112 481.8 R 1.077 +(designed to be reasonably easy to parse, since this is done e)87 493.8 +R -.15(ve)-.25 G 1.076(ry time).15 F F2(sendmail)3.576 E F1 1.076 +(starts up, rather than)3.576 F(easy for a human to read or write.)87 +505.8 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 522 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 534 R .102 +(Lines be)5.102 F .102(ginning with a space or a tab are continuation) +-.15 F 1.322 +(lines \(although the semantics are not well de\214ned in man)87 546 R +3.823(yp)-.15 G 3.823(laces\). Blank)-3.823 F 1.323(lines and lines be) +3.823 F(ginning)-.15 E(with a sharp symbol \(`#'\) are comments.)87 558 +Q F0 2.5(5.1. R)87 582 R(and S \212 Rewriting Rules)2.5 E F1 .466 +(The core of address parsing are the re)127 598.2 R .466(writing rules.) +-.25 F .465(These are an ordered production system.)5.466 F F2(Sendmail) +102 610.2 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 622.2 Q(When a rule matches, the address is replaced by\ + the right hand side \(RHS\) of the rule.)5 E .922(There are se)127 +638.4 R -.15(ve)-.25 G .922(ral sets of re).15 F .921(writing rules.) +-.25 F .921(Some of the re)5.921 F .921 +(writing sets are used internally and)-.25 F .359(must ha)102 650.4 R +.659 -.15(ve s)-.2 H .359(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 .36 +(peci\214cally assigned semantics, and).15 F +(may be referenced by the mailer de\214nitions or by other re)102 662.4 +Q(writing sets.)-.25 E(The syntax of these tw)127 678.6 Q 2.5(oc)-.1 G +(ommands are:)-2.5 E F0(S)142 694.8 Q F2(n)A F1 .249 +(Sets the current ruleset being collected to)102 711 R F2(n)2.749 E F1 +5.249(.I)C 2.748(fy)-5.249 G .248(ou be)-2.748 F .248 +(gin a ruleset more than once it appends to the)-.15 F +(old de\214nition.)102 723 Q EP +%%Page: 33 29 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-33)195.86 E(R)142 96 Q/F1 10/Times-Italic@0 SF(lhs rhs comments) +A/F2 10/Times-Roman@0 SF 1.185(The \214elds must be separated by at lea\ +st one tab character; there may be embedded spaces in the)102 112.2 R +2.595(\214elds. The)102 124.2 R F1(lhs)2.595 E F2 .095 +(is a pattern that is applied to the input.)2.595 F .095 +(If it matches, the input is re)5.095 F .094(written to the)-.25 F F1 +(rhs)2.594 E F2(.)A(The)102 136.2 Q F1(comments)2.5 E F2(are ignored.) +2.5 E .755(Macro e)127 152.4 R .755(xpansions of the form)-.15 F F0($) +3.255 E F1(x)A F2 .755 +(are performed when the con\214guration \214le is read.)3.255 F(Expan-) +5.755 E .577(sions of the form)102 164.4 R F0($&)3.077 E F1(x)A F2 .577 +(are performed at run time using a some)3.077 F .577 +(what less general algorithm.)-.25 F .577(This is)5.577 F +(intended only for referencing internally de\214ned macros such as)102 +176.4 Q F0($h)2.5 E F2(that are changed at runtime.)2.5 E F0 2.5 +(5.1.1. The)102 200.4 R(left hand side)2.5 E F2 2.77 +(The left hand side of re)142 216.6 R 2.771 +(writing rules contains a pattern.)-.25 F 2.771(Normal w)7.771 F 2.771 +(ords are simply)-.1 F(matched directly)117 228.6 Q 5(.M)-.65 G +(etasyntax is introduced using a dollar sign.)-5 E(The metasymbols are:) +5 E F0($*)157 244.8 Q F2(Match zero or more tok)10.14 E(ens)-.1 E F0($+) +157 256.8 Q F2(Match one or more tok)9.44 E(ens)-.1 E F0<24ad>157 268.8 +Q F2(Match e)9.44 E(xactly one tok)-.15 E(en)-.1 E F0($=)157 280.8 Q F1 +(x)A F2(Match an)5 E 2.5(yp)-.15 G(hrase in class)-2.5 E F1(x)2.5 E F0 +($~)157 292.8 Q F1(x)A F2(Match an)7.37 E 2.5(yw)-.15 G +(ord not in class)-2.6 E F1(x)2.5 E F2 .132(If an)117 309 R 2.632(yo) +-.15 G 2.632(ft)-2.632 G .132(hese match, the)-2.632 F 2.632(ya)-.15 G +.132(re assigned to the symbol)-2.632 F F0($)2.632 E F1(n)A F2 .131 +(for replacement on the right hand side,)2.632 F(where)117 321 Q F1(n) +2.5 E F2(is the inde)2.5 E 2.5(xi)-.15 G 2.5(nt)-2.5 G(he LHS.)-2.5 E +-.15(Fo)5 G 2.5(re).15 G(xample, if the LHS:)-2.65 E($\255:$+)157 337.2 +Q(is applied to the input:)117 353.4 Q(UCB)157 369.6 Q(ARP)-.35 E +(A:eric)-.92 E(the rule will match, and the v)117 385.8 Q +(alues passed to the RHS will be:)-.25 E 7.5($1 UCB)157 402 R(ARP)-.35 E +(A)-.92 E 7.5($2 eric)157 414 R(Additionally)142 434.4 Q 2.704(,t)-.65 G +.204(he LHS can include)-2.704 F F0($@)2.704 E F2 .204 +(to match zero tok)2.704 F 2.704(ens. This)-.1 F(is)2.704 E F1(not)2.704 +E F2 .204(bound to a)2.704 F F0($)2.705 E F1(n)A F2(on)2.705 E(the RHS,\ + and is normally only used when it stands alone in order to match the n\ +ull input.)117 446.4 Q F0 2.5(5.1.2. The)102 470.4 R(right hand side)2.5 +E F2 .649(When the left hand side of a re)142 486.6 R .649 +(writing rule matches, the input is deleted and replaced by)-.25 F 1.036 +(the right hand side.)117 498.6 R -.8(To)6.036 G -.1(ke).8 G 1.036 +(ns are copied directly from the RHS unless the).1 F 3.537(yb)-.15 G +-.15(eg)-3.537 G 1.037(in with a dollar).15 F 2.5(sign. Metasymbols)117 +510.6 R(are:)2.5 E F0($)157 526.8 Q F1(n)A F2 +(Substitute inde\214nite tok)40.55 E(en)-.1 E F1(n)2.5 E F2(from LHS)2.5 +E F0($[)157 538.8 Q F1(name)A F0($])A F2(Canonicalize)12.23 E F1(name) +2.5 E F0($\()157 550.8 Q F1(map k)A -.3(ey)-.1 G F0($@)2.8 E F1(ar)A +(guments)-.37 E F0($:)2.5 E F1(default)A F0($\))2.5 E F2(Generalized k) +207.55 562.8 Q -.15(ey)-.1 G(ed mapping function).15 E F0($>)157 574.8 Q +F1(n)A F2(\231Call\232 ruleset)34.85 E F1(n)2.5 E F0($#)157 586.8 Q F1 +(mailer)A F2(Resolv)14.44 E 2.5(et)-.15 G(o)-2.5 E F1(mailer)2.5 E F0 +($@)157 598.8 Q F1(host)A F2(Specify)19.58 E F1(host)2.5 E F0($:)157 +610.8 Q F1(user)A F2(Specify)25 E F1(user)2.5 E F2(The)142 631.2 Q F0($) +3.137 E F1(n)A F2 .637(syntax substitutes the corresponding v)3.137 F +.637(alue from a)-.25 F F0($+)3.137 E F2(,)A F0<24ad>3.137 E F2(,)A F0 +($*)3.137 E F2(,)A F0($=)3.137 E F2 3.137(,o)C(r)-3.137 E F0($~)3.137 E +F2 .636(match on)3.136 F(the LHS.)117 643.2 Q(It may be used an)5 E +(ywhere.)-.15 E 2.705(Ah)142 659.4 S .205(ost name enclosed between) +-2.705 F F0($[)2.705 E F2(and)2.705 E F0($])2.706 E F2 .206(is look) +2.706 F .206(ed up in the host database\(s\) and replaced)-.1 F EP +%%Page: 34 30 +%%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 1.683 +(by the canonical name)117 98 R/F2 7/Times-Roman@0 SF(15)-4 I F1 6.683 +(.F)4 K 1.683(or e)-6.833 F 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 3.17 +(\231$[[128.32.130.2]$]\232 w)117 110 R 3.17(ould become \231v)-.1 F +(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU.).65 E<9a>-.7 E/F3 +10/Times-Italic@0 SF(Sendmail)8.17 E F1 3.17(recognizes its)5.67 F +(numeric IP address without calling the name serv)117 122 Q +(er and replaces it with its canonical name.)-.15 E(The)142 138.2 Q F0 +($\()3.004 E F1(...)3.004 E F0($\))5.504 E F1 .503(syntax is a more gen\ +eral form of lookup; it uses a named map instead of an)3.003 F .809 +(implicit map.)117 150.2 R .809(If no lookup is found, the indicated) +5.809 F F3(default)3.309 E F1 .81(is inserted; if no def)3.309 F .81 +(ault is speci\214ed)-.1 F .776(and no lookup matches, the v)117 162.2 R +.776(alue is left unchanged.)-.25 F(The)5.776 E F3(ar)3.276 E(guments) +-.37 E F1 .775(are passed to the map for)3.275 F(possible use.)117 174.2 +Q(The)142 190.4 Q F0($>)2.619 E F3(n)A F1 .119(syntax causes the remain\ +der of the line to be substituted as usual and then passed)2.619 F .587 +(as the ar)117 202.4 R .587(gument to ruleset)-.18 F F3(n)3.087 E F1 +5.587(.T)C .587(he \214nal v)-5.587 F .586(alue of ruleset)-.25 F F3(n) +3.086 E F1 .586(then becomes the substitution for this)3.086 F 3.758 +(rule. The)117 214.4 R F0($>)3.758 E F1 1.258(syntax e)3.758 F 1.258 +(xpands e)-.15 F -.15(ve)-.25 G 1.259 +(rything after the ruleset name to the end of the replacement).15 F .976 +(string and then passes that as the initial input to the ruleset.)117 +226.4 R(Recursi)5.976 E 1.276 -.15(ve c)-.25 H .976(alls are allo).15 F +3.476(wed. F)-.25 F(or)-.15 E -.15(ex)117 238.4 S(ample,).15 E +($>0 $>3 $1)157 254.6 Q -.15(ex)117 270.8 S(pands $1, passes that to ru\ +leset 3, and then passes the result of ruleset 3 to ruleset 0.).15 E +(The)142 287 Q F0($#)2.507 E F1 .007(syntax should)2.507 F F3(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 299 S .685 +(luation of the ruleset to terminate immediately).25 F 3.184(,a)-.65 G +.684(nd signals to)-3.184 F F3(sendmail)3.184 E F1 .684 +(that the address has)3.184 F(completely resolv)117 311 Q 2.5(ed. The) +-.15 F(complete syntax is:)2.5 E F0($#)157 327.2 Q F3(mailer)A F0($@)2.5 +E F3(host)A F0($:)2.5 E F3(user)A F1 1.394(This speci\214es the {mailer) +117 343.4 R 3.894(,h)-.4 G 1.394 +(ost, user} 3-tuple necessary to direct the mailer)-3.894 F 6.394(.I) +-.55 G 3.894(ft)-6.394 G 1.394(he mailer is)-3.894 F .774 +(local the host part may be omitted)117 357.4 R F2(16)-4 I F1 5.774(.T)4 +K(he)-5.774 E F3(mailer)3.274 E F1 .775(must be a single w)3.274 F .775 +(ord, b)-.1 F .775(ut the)-.2 F F3(host)3.275 E F1(and)3.275 E F3(user) +3.275 E F1 .253(may be multi-part.)117 369.4 R .253(If the)5.253 F F3 +(mailer)2.753 E F1 .253(is the b)2.753 F .253(uiltin IPC mailer)-.2 F +2.753(,t)-.4 G(he)-2.753 E F3(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 381.4 R .5 +(orking address \(e)-.1 F .5(xactly lik)-.15 F 3(eM)-.1 G 3(Xr)-3 G 3 +(ecords\). The)-3 F F3(user)117 393.4 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 .162 +(As a special case, if the mailer speci\214ed has the)117 405.4 R F0 +(F=@)2.662 E F1 .163 +(\215ag speci\214ed and the \214rst character of the)2.662 F F0($:)117 +417.4 Q F1 -.25(va)3.377 G .877 +(lue is \231@\232, the \231@\232 is stripped of).25 F .876 +(f, and a \215ag is set in the address descriptor that causes)-.25 F +(sendmail to not do ruleset 5 processing.)117 429.4 Q(Normally)142 445.6 +Q 3.251(,ar)-.65 G .751 +(ule that matches is retried, that is, the rule loops until it f)-3.251 +F 3.252(ails. A)-.1 F .752(RHS may)3.252 F 1.086(also be preceded by a) +117 457.6 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($@)-2.5 E F1 +1.085(pre\214x causes the ruleset to)3.585 F 1.46 +(return with the remainder of the RHS as the v)117 469.6 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 481.6 Q 3.756(,b)-.65 G 1.256 +(ut the ruleset to continue; this can be used to a)-3.956 F -.2(vo)-.2 G +1.256(id continued application of a).2 F 2.5(rule. The)117 493.6 R +(pre\214x is stripped before continuing.)2.5 E(The)142 509.8 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 526 R +($>7 $1)2.5 E 1.256(matches an)117 542.2 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 554.2 Q 1.205 +(Substitution occurs in the order described, that is, parameters from t\ +he LHS are substi-)142 570.4 R .219(tuted, hostnames are canonicalized,\ + \231subroutines\232 are called, and \214nally)117 582.4 R F0($#)2.719 E +F1(,)A F0($@)2.719 E F1 2.72(,a)C(nd)-2.72 E F0($:)2.72 E F1 .22 +(are pro-)2.72 F(cessed.)117 594.4 Q F0 2.5(5.1.3. Semantics)102 618.4 R +(of r)2.5 E(ewriting rule sets)-.18 E F1 1.848(There are six re)142 +634.6 R 1.847(writing sets that ha)-.25 F 2.147 -.15(ve s)-.2 H 1.847 +(peci\214c semantics.).15 F(Fi)6.847 E 2.147 -.15(ve o)-.25 H 4.347(ft) +.15 G 1.847(hese are related as)-4.347 F(depicted by \214gure 1.)117 +646.6 Q .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(15)93.6 675.6 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(16)93.6 689.2 Q F5 -.88(Yo)3.2 K 2.726(um).88 G .726(ay w)-2.726 F +.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 f\ +or local use.)72 702 Q EP +%%Page: 35 31 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-35)195.86 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(addr)91.915 202.6 Q 133.2 200.4 111.6 +200.4 DL 133.2 200.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL 133.2 200.4 MT -7.2 +1.8 RL 0 -3.6 RL CL ST 154.8 211.2 MT 0 -21.6 RL -21.6 0 RL 0 21.6 RL CL +ST(3)141.5 202.6 Q 176.4 200.4 154.8 200.4 DL 176.4 200.4 MT -7.2 1.8 RL +0 -3.6 RL CL BL 176.4 200.4 MT -7.2 1.8 RL 0 -3.6 RL CL ST 198 211.2 MT +0 -21.6 RL -21.6 0 RL 0 21.6 RL CL ST(D)183.59 202.6 Q 219.6 200.4 198 +200.4 DL 277.2 182.4 255.6 182.4 DL 277.2 182.4 MT -7.2 1.8 RL 0 -3.6 RL +CL BL 277.2 182.4 MT -7.2 1.8 RL 0 -3.6 RL CL ST 298.8 193.2 MT 0 -21.6 +RL -21.6 0 RL 0 21.6 RL CL ST(1)285.5 184.6 Q 320.4 182.4 298.8 182.4 DL +320.4 182.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL 320.4 182.4 MT -7.2 1.8 RL 0 +-3.6 RL CL ST 342 193.2 MT 0 -21.6 RL -21.6 0 RL 0 21.6 RL CL ST(S) +328.42 184.6 Q 363.6 182.4 342 182.4 DL 277.2 218.4 255.6 218.4 DL 277.2 +218.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL 277.2 218.4 MT -7.2 1.8 RL 0 -3.6 +RL CL ST 298.8 229.2 MT 0 -21.6 RL -21.6 0 RL 0 21.6 RL CL ST(2)285.5 +220.6 Q 320.4 218.4 298.8 218.4 DL 320.4 218.4 MT -7.2 1.8 RL 0 -3.6 RL +CL BL 320.4 218.4 MT -7.2 1.8 RL 0 -3.6 RL CL ST 342 229.2 MT 0 -21.6 RL +-21.6 0 RL 0 21.6 RL CL ST(R)327.865 220.6 Q 363.6 218.4 342 218.4 DL +421.2 200.4 399.6 200.4 DL 421.2 200.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL +421.2 200.4 MT -7.2 1.8 RL 0 -3.6 RL CL ST 442.8 211.2 MT 0 -21.6 RL +-21.6 0 RL 0 21.6 RL CL ST(4)429.5 202.6 Q 464.4 200.4 442.8 200.4 DL +464.4 200.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL 464.4 200.4 MT -7.2 1.8 RL 0 +-3.6 RL CL ST(msg)466.865 202.6 Q 255.6 182.4 219.6 200.4 DL 255.6 218.4 +219.6 200.4 DL 399.6 200.4 363.6 182.4 DL 399.6 200.4 363.6 218.4 DL +208.8 146.4 187.2 146.4 DL 208.8 146.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL +208.8 146.4 MT -7.2 1.8 RL 0 -3.6 RL CL ST 230.4 157.2 MT 0 -21.6 RL +-21.6 0 RL 0 21.6 RL CL ST(0)217.1 148.6 Q 252 146.4 230.4 146.4 DL 252 +146.4 MT -7.2 1.8 RL 0 -3.6 RL CL BL 252 146.4 MT -7.2 1.8 RL 0 -3.6 RL +CL ST(resolv)265.69 148.6 Q(ed address)-.15 E 187.2 146.4 162 200.4 DL +(Figure 1 \212 Re)216.045 248.4 Q(writing set semantics)-.25 E 2.5 +(D\212s)209.35 260.4 S(ender domain addition)-2.5 E 2.5(S\212m)209.35 +272.4 S(ailer)-2.5 E(-speci\214c sender re)-.2 E(writing)-.25 E 2.5 +(R\212m)209.35 284.4 S(ailer)-2.5 E(-speci\214c recipient re)-.2 E +(writing)-.25 E 77 296.4 72 296.4 DL 79 296.4 74 296.4 DL 84 296.4 79 +296.4 DL 89 296.4 84 296.4 DL 94 296.4 89 296.4 DL 99 296.4 94 296.4 DL +104 296.4 99 296.4 DL 109 296.4 104 296.4 DL 114 296.4 109 296.4 DL 119 +296.4 114 296.4 DL 124 296.4 119 296.4 DL 129 296.4 124 296.4 DL 134 +296.4 129 296.4 DL 139 296.4 134 296.4 DL 144 296.4 139 296.4 DL 149 +296.4 144 296.4 DL 154 296.4 149 296.4 DL 159 296.4 154 296.4 DL 164 +296.4 159 296.4 DL 169 296.4 164 296.4 DL 174 296.4 169 296.4 DL 179 +296.4 174 296.4 DL 184 296.4 179 296.4 DL 189 296.4 184 296.4 DL 194 +296.4 189 296.4 DL 199 296.4 194 296.4 DL 204 296.4 199 296.4 DL 209 +296.4 204 296.4 DL 214 296.4 209 296.4 DL 219 296.4 214 296.4 DL 224 +296.4 219 296.4 DL 229 296.4 224 296.4 DL 234 296.4 229 296.4 DL 239 +296.4 234 296.4 DL 244 296.4 239 296.4 DL 249 296.4 244 296.4 DL 254 +296.4 249 296.4 DL 259 296.4 254 296.4 DL 264 296.4 259 296.4 DL 269 +296.4 264 296.4 DL 274 296.4 269 296.4 DL 279 296.4 274 296.4 DL 284 +296.4 279 296.4 DL 289 296.4 284 296.4 DL 294 296.4 289 296.4 DL 299 +296.4 294 296.4 DL 304 296.4 299 296.4 DL 309 296.4 304 296.4 DL 314 +296.4 309 296.4 DL 319 296.4 314 296.4 DL 324 296.4 319 296.4 DL 329 +296.4 324 296.4 DL 334 296.4 329 296.4 DL 339 296.4 334 296.4 DL 344 +296.4 339 296.4 DL 349 296.4 344 296.4 DL 354 296.4 349 296.4 DL 359 +296.4 354 296.4 DL 364 296.4 359 296.4 DL 369 296.4 364 296.4 DL 374 +296.4 369 296.4 DL 379 296.4 374 296.4 DL 384 296.4 379 296.4 DL 389 +296.4 384 296.4 DL 394 296.4 389 296.4 DL 399 296.4 394 296.4 DL 404 +296.4 399 296.4 DL 409 296.4 404 296.4 DL 414 296.4 409 296.4 DL 419 +296.4 414 296.4 DL 424 296.4 419 296.4 DL 429 296.4 424 296.4 DL 434 +296.4 429 296.4 DL 439 296.4 434 296.4 DL 444 296.4 439 296.4 DL 449 +296.4 444 296.4 DL 454 296.4 449 296.4 DL 459 296.4 454 296.4 DL 464 +296.4 459 296.4 DL 469 296.4 464 296.4 DL 474 296.4 469 296.4 DL 479 +296.4 474 296.4 DL 484 296.4 479 296.4 DL 489 296.4 484 296.4 DL 494 +296.4 489 296.4 DL 499 296.4 494 296.4 DL 504 296.4 499 296.4 DL 1.029 +(Ruleset three should turn the address into \231canonical form.)142 +332.4 R 6.029<9a54>-.7 G 1.03(his form should ha)-6.029 F 1.33 -.15 +(ve t)-.2 H(he).15 E(basic syntax:)117 344.4 Q +(local-part@host-domain-spec)157 360.6 Q(Ruleset three is applied by)117 +376.8 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.)-2.5 E .302 +(If no \231@\232 sign is speci\214ed, then the host-domain-spec)142 393 +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 405 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 417 Q F1(mailer\).)2.5 E 1.021(Ruleset zero is applied\ + after ruleset three to addresses that are going to actually specify)142 +433.2 R 2.818(recipients. It)117 445.2 R .318(must resolv)2.818 F 2.818 +(et)-.15 G 2.819(oa)-2.818 G F2({mailer)A 2.819(,h)-1.11 G .319 +(ost, addr)-2.819 F(ess})-.37 E F1 2.819(triple. The)2.819 F F2(mailer) +2.819 E F1 .319(must be de\214ned in the)2.819 F .752 +(mailer de\214nitions from the con\214guration \214le.)117 457.2 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 469.2 Q(gv e)-.18 E +(xpansion of the speci\214ed mailer)-.15 E(.)-.55 E .452 +(Rulesets one and tw)142 485.4 R 2.952(oa)-.1 G .452 +(re applied to all sender and recipient addresses respecti)-2.952 F -.15 +(ve)-.25 G(ly).15 E 5.453(.T)-.65 G(he)-5.453 E(y)-.15 E +(are applied before an)117 497.4 Q 2.5(ys)-.15 G +(peci\214cation in the mailer de\214nition.)-2.5 E(The)5 E 2.5(ym)-.15 G +(ust ne)-2.5 E -.15(ve)-.25 G 2.5(rr).15 G(esolv)-2.5 E(e.)-.15 E 1.266 +(Ruleset four is applied to all addresses in the message.)142 513.6 R +1.265(It is typically used to translate)6.265 F(internal to e)117 525.6 +Q(xternal form.)-.15 E .652(In addition, ruleset 5 is applied to all lo\ +cal addresses \(speci\214cally)142 541.8 R 3.153(,t)-.65 G .653 +(hose that resolv)-3.153 F 3.153(et)-.15 G 3.153(oa)-3.153 G .296 +(mailer with the `F=5' \215ag set\) that do not ha)117 553.8 R .596 -.15 +(ve a)-.2 H 2.796(liases. This).15 F(allo)2.796 E .296 +(ws a last minute hook for local)-.25 F(names.)117 565.8 Q F0 2.5 +(5.1.4. Ruleset)102 589.8 R(hooks)2.5 E F1 3.814(Af)142 606 S 1.814 -.25 +(ew e)-3.814 H 1.315(xtra rulesets are de\214ned as \231hooks\232 that \ +can be de\214ned to get special features.).1 F(The)117 618 Q 3.468(ya) +-.15 G .968(re all named rulesets.)-3.468 F .968 +(The \231check_*\232 forms all gi)5.968 F 1.268 -.15(ve a)-.25 H .968 +(ccept/reject status; f).15 F .967(alling of)-.1 F 3.467(ft)-.25 G(he) +-3.467 E .502(end or returning normally is an accept, and resolving to) +117 630 R F0($#err)3.002 E(or)-.18 E F1 .502(is a reject.)3.002 F(Man) +5.502 E 3.002(yo)-.15 G 3.002(ft)-3.002 G .502(hese can)-3.002 F .944 +(also resolv)117 642 R 3.444(et)-.15 G 3.444(ot)-3.444 G .944 +(he special mailer name)-3.444 F F0($#discard)3.443 E F1 3.443(;t)C .943 +(his accepts the message as though it were)-3.443 F .397(successful b) +117 654 R .397(ut then discards it without deli)-.2 F -.15(ve)-.25 G(ry) +.15 E 5.397(.N)-.65 G .398 +(ote, this mailer can not be chosen as a mailer)-5.397 F(in ruleset 0.) +117 666 Q F0 2.5(5.1.4.1. check_r)117 690 R(elay)-.18 E F1(The)157 706.2 +Q F2 -.15(ch)2.5 G(ec).15 E(k_r)-.2 E(elay)-.37 E F1 +(ruleset is called after a connection is accepted.)2.5 E(It is passed)5 +E EP +%%Page: 36 32 +%%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 +(client.host.name $| client.host.address)172 96 Q(where)132 112.2 Q F0 +($|)4.017 E F1 1.517(is a metacharacter separating the tw)4.017 F 4.017 +(op)-.1 G 4.017(arts. This)-4.017 F 1.517 +(ruleset can reject connections)4.017 F(from v)132 124.2 Q +(arious locations.)-.25 E F0 2.5(5.1.4.2. check_mail)117 148.2 R F1(The) +157 164.4 Q/F2 10/Times-Italic@0 SF -.15(ch)3.722 G(ec).15 E(k_mail)-.2 +E F1 1.223(ruleset is passed the user name parameter of the)3.722 F/F3 9 +/Times-Roman@0 SF 1.223(SMTP MAIL)3.723 F F1(com-)3.723 E 2.5(mand. It) +132 176.4 R(can accept or reject the address.)2.5 E F0 2.5 +(5.1.4.3. check_r)117 200.4 R(cpt)-.18 E F1(The)157 216.6 Q F2 -.15(ch) +3.918 G(ec).15 E(k_r)-.2 E(cpt)-.37 E F1 1.417 +(ruleset is passed the user name parameter of the)3.918 F F3 1.417 +(SMTP RCPT)3.917 F F1(com-)3.917 E 2.5(mand. It)132 228.6 R +(can accept or reject the address.)2.5 E F0 2.5(5.1.4.4. check_compat) +117 252.6 R F1(The)157 268.8 Q F2 -.15(ch)2.5 G(ec).15 E(k_compat)-.2 E +F1(ruleset is passed)2.5 E(sender)172 285 Q +(-address $| recipient-address)-.2 E(where)132 301.2 Q F0($|)3.725 E F1 +1.225(is a metacharacter separating the addresses.)3.725 F 1.225 +(It can accept or reject mail transfer)6.225 F(between these tw)132 +313.2 Q 2.5(oa)-.1 G(ddresses much lik)-2.5 E 2.5(et)-.1 G(he)-2.5 E F2 +-.15(ch)2.5 G(ec).15 E(kcompat\(\))-.2 E F1(function.)2.5 E F0 2.5 +(5.1.4.5. check_eoh)117 337.2 R F1(The)157 353.4 Q F2 -.15(ch)2.5 G(ec) +.15 E(k_eoh)-.2 E F1(ruleset is passed)2.5 E(number)172 369.6 Q +(-of-headers $| size-of-headers)-.2 E(where)132 385.8 Q F0($|)3.803 E F1 +1.303(is a metacharacter separating the numbers.)3.803 F 1.303 +(These numbers can be used for size)6.303 F .588(comparisons with the) +132 397.8 R F0(arith)3.088 E F1 3.088(map. The)3.088 F .588 +(ruleset is triggered after all of the headers ha)3.088 F .888 -.15 +(ve b)-.2 H(een).15 E 3.262(read. It)132 409.8 R .762 +(can be used to correlate information g)3.262 F .761 +(athered from those headers using the)-.05 F F0(macr)3.261 E(o)-.18 E F1 +(storage map.)132 421.8 Q +(One possible use is to check for a missing header)5 E 5(.F)-.55 G(or e) +-5.15 E(xample:)-.15 E(Kstorage macro)172 438 Q +(HMessage-Id: $>CheckMessageId)172 450 Q(SCheckMessageId)172 474 Q 2.5 +(#R)172 486 S(ecord the presence of the header)-2.5 E 88.83(R$* $:)172 +498 R($\(storage {MessageIdCheck} $@ OK $\) $1)2.5 E(R< $+ @ $+ >)172 +510 Q($@ OK)49.56 E 88.83(R$* $#error)172 522 R($: 553 Header Error)2.5 +E(Scheck_eoh)172 546 Q 2.5(#C)172 558 S(heck the macro)-2.5 E 88.83 +(R$* $:)172 570 R 2.5(<$)2.5 G(&{MessageIdCheck} >)-2.5 E 2.5(#C)172 582 +S(lear the macro for the ne)-2.5 E(xt message)-.15 E 88.83(R$* $:)172 +594 R($\(storage {MessageIdCheck} $\) $1)2.5 E 2.5(#H)172 606 S +(as a Message-Id: header)-2.5 E(R< $+ >)172 618 Q($@ OK)74.41 E 2.5(#A) +172 630 S(llo)-2.5 E 2.5(wm)-.25 G(issing Message-Id: from local mail) +-2.5 E 88.83(R$* $:)172 642 R 2.5(<$)2.5 G(&{client_name} >)-2.5 E(R< >) +172 654 Q($@ OK)87.55 E(R< $=w >)172 666 Q($@ OK)67.19 E 2.5(#O)172 678 +S(therwise, reject the mail)-2.5 E 88.83(R$* $#error)172 690 R +($: 553 Header Error)2.5 E -.25(Ke)132 706.2 S .459(ep in mind the Mess\ +age-Id: header is not a required header and is not a guaranteed spam).25 +F(indicator)132 718.2 Q 5(.T)-.55 G(his ruleset is an e)-5 E +(xample and should probably not be used in production.)-.15 E EP +%%Page: 37 33 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-37)195.86 E 2.5(5.1.4.6. check_etr)117 96 R(n)-.15 E/F1 10 +/Times-Roman@0 SF(The)157 112.2 Q/F2 10/Times-Italic@0 SF -.15(ch)3.385 +G(ec).15 E(k_etrn)-.2 E F1 .885(ruleset is passed the parameter of the) +3.385 F/F3 9/Times-Roman@0 SF .885(SMTP ETRN)3.385 F F1 3.384 +(command. It)3.385 F(can)3.384 E(accept or reject the command.)132 124.2 +Q F0 2.5(5.1.4.7. check_expn)117 148.2 R F1(The)157 164.4 Q F2 -.15(ch) +3.614 G(ec).15 E(k_e)-.2 E(xpn)-.2 E F1 1.115 +(ruleset is passed the user name parameter of the)3.614 F F3 1.115 +(SMTP EXPN)3.615 F F1(com-)3.615 E 2.5(mand. It)132 176.4 R +(can accept or reject the address.)2.5 E F0 2.5(5.1.4.8. check_vrfy)117 +200.4 R F1(The)157 216.6 Q F2 -.15(ch)3.817 G(ec).15 E(k_vrfy)-.2 E F1 +1.317(ruleset is passed the user name parameter of the)3.817 F F3 1.316 +(SMTP VRFY)3.817 F F1(com-)3.816 E 2.5(mand. It)132 228.6 R +(can accept or reject the command.)2.5 E F0 2.5(5.1.4.9. trust_auth)117 +252.6 R F1(The)157 268.8 Q F2(trust_auth)3.044 E F1 .545 +(ruleset is passed the A)3.044 F .545(UTH= parameter of the)-.55 F F3 +.545(SMTP MAIL)3.045 F F1(command.)3.045 E .636 +(It is used to determine whether this v)132 280.8 R .635 +(alue should be trusted. In order to mak)-.25 F 3.135(et)-.1 G .635 +(his decision,)-3.135 F .153(the ruleset may mak)132 292.8 R 2.653(eu) +-.1 G .154(se of the v)-2.653 F(arious)-.25 E F0(${auth_*})2.654 E F1 +2.654(macros. If)2.654 F .154(the ruleset does resolv)2.654 F 2.654(et) +-.15 G 2.654(ot)-2.654 G(he)-2.654 E .019(\231error\232 mailer the A)132 +304.8 R .019 +(UTH= parameter is not trusted and hence not passed on to the ne)-.55 F +.018(xt relay)-.15 F(.)-.65 E F0 2.5(5.1.5. IPC)102 328.8 R(mailers)2.5 +E F1 1.332(Some special processing occurs if the ruleset zero resolv)142 +345 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 357 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 1.178(after \231$@\232 has MX e)117 +369 R 1.178(xpansion performed if not deli)-.15 F -.15(ve)-.25 G 1.178 +(ring via a named sock).15 F 1.178(et; this looks the)-.1 F +(name up in DNS to \214nd alternate deli)117 381 Q -.15(ve)-.25 G +(ry sites.).15 E(The host name can also be pro)142 397.2 Q +(vided as a dotted quad in square brack)-.15 E(ets; for e)-.1 E(xample:) +-.15 E([128.32.149.78])157 413.4 Q(This causes direct con)117 429.6 Q +-.15(ve)-.4 G(rsion of the numeric v).15 E(alue to an IP host address.) +-.25 E .214(The host name passed in after the \231$@\232 may also be a \ +colon-separated list of hosts.)142 445.8 R(Each)5.213 E .484 +(is separately MX e)117 457.8 R .484 +(xpanded and the results are concatenated to mak)-.15 F 2.985(e\()-.1 G +.485(essentially\) one long MX)-2.985 F 3.465(list. The)117 469.8 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 481.8 Q(orks.)-.1 E +(As a \214nal special case, the host name can be passed in as a te)142 +498 Q(xt string in square brack)-.15 E(ets:)-.1 E([ucb)157 514.2 Q -.25 +(va)-.15 G(x.berk).25 E(ele)-.1 E -.65(y.)-.15 G(edu]).65 E .312 +(This form a)117 530.4 R -.2(vo)-.2 G .312(ids the MX mapping.).2 F F0 +(N.B.:)5.312 E F2 .313(This is intended only for situations wher)2.812 F +2.813(ey)-.37 G .313(ou have a)-2.813 F .338(network \214r)117 542.4 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 554.4 S +(cor).37 E 3.958(dp)-.37 G 1.458(oints to a gate)-3.958 F 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 566.4 R .09(Use of this featur)5.09 F +2.59(ed)-.37 G(ir)-2.59 E .09 +(ectly violates RFC 1123 section 5.3.5: it should)-.37 F +(not be used lightly)117 578.4 Q(.)-.55 E F0 2.5(5.2. D)87 602.4 R 2.5 +<8a44>2.5 G(e\214ne Macr)-2.5 E(o)-.18 E F1 .081 +(Macros are named with a single character or with a w)127 618.6 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 630.6 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 642.6 R 5.446(.L)-.65 G -.25(ow)-5.446 G +.446(er case letters and special symbols are used internally).25 F 5.446 +(.L)-.65 G .446(ong names)-5.446 F(be)102 654.6 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 666.6 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 682.8 Q F0(D)142 699 Q F2 +1.666(xv)C(al)-1.666 E F1(where)102 715.2 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 EP +%%Page: 38 34 +%%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 .479 +(the v)102 96 R .479(alue it should ha)-.25 F -.15(ve)-.2 G 5.479(.T).15 +G .478(here should be no spaces gi)-5.479 F -.15(ve)-.25 G 2.978(nt).15 +G .478(hat do not actually belong in the macro)-2.978 F -.25(va)102 108 +S(lue.).25 E .494(Macros are interpolated using the construct)127 124.2 +R F0($)2.994 E/F2 10/Times-Italic@0 SF(x)A F1 2.994(,w)C(here)-2.994 E +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 136.2 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 148.2 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 164.4 Q($?x te) +142 180.6 Q(xt1 $| te)-.15 E(xt2 $.)-.15 E 1.561(This interpolates)102 +196.8 R F2(te)4.061 E(xt1)-.2 E F1 1.562(if the macro)4.062 F F0($x) +4.062 E F1 1.562(is set and non-null, and)4.062 F F2(te)4.062 E(xt2)-.2 +E F1 4.062(otherwise. The)4.062 F 1.562(\231else\232 \()4.062 F F0($|)A +F1(\))A(clause may be omitted.)102 208.8 Q(Lo)127 225 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 237 R F2(sendmail)4.06 E F1 4.06(,a)C 1.561 +(nd special characters are reserv)-4.06 F 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 249 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)-2.5 E +(ed for con\214guration \214le authors.)-.15 E 1.303(The follo)127 265.2 +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(ar)102 279.2 Q +(gv')-.18 E 2.792(sf)-.55 G .292(or mailers or for other conte)-2.792 F +2.793(xts. The)-.15 F .293(ones mark)2.793 F .293 +(ed \207 are information passed into sendmail)-.1 F/F3 7/Times-Roman@0 +SF(17)-4 I F1(,)4 I .036(the ones mark)102 291.2 R .036(ed \210 are inf\ +ormation passed both in and out of sendmail, and the unmark)-.1 F .035 +(ed macros are)-.1 F(passed out of sendmail b)102 303.2 Q +(ut are not otherwise used internally)-.2 E 5(.T)-.65 G +(hese macros are:)-5 E 13.06($a The)102 319.4 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 335.6 R +(current date in RFC 822 format.)2.5 E 13.06($c The)102 351.8 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 +2.503 E F1(com-)2.503 E(mand line \215ag.)127 363.8 Q 12.5($d The) +102 380 R(current date in UNIX \(ctime\) format.)2.5 E 8.06 +($e\207 \(Obsolete;)102 396.2 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 408.2 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 420.2 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 +432.2 Q(ersion number)-.15 E 2.5(,e)-.4 G +(.g., \231$j Sendmail $v/$Z ready at $b\232)-2.5 E 14.17($f The)102 +448.4 R(en)2.5 E -.15(ve)-.4 G(lope sender \(from\) address.).15 E 12.5 +($g The)102 464.6 R .017(sender address relati)2.517 F .317 -.15(ve t) +-.25 H 2.517(ot).15 G .017(he recipient.)-2.517 F -.15(Fo)5.017 G 2.517 +(re).15 G .018(xample, if)-2.667 F 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 +476.6 Q -.15(ve)-.25 G 2.5(ri).15 G 2.5(sa)-2.5 G +(ppropriate for the recei)-2.5 E(ving mailer)-.25 E(.)-.55 E 12.5 +($h The)102 492.8 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 509 R(queue id, e.g., \231HAA12345\232.)2.5 E 9.72 +($j\210 The)102 525.2 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 537.2 R F2(must)3.093 E F1 .594(be rede\214ned to b\ +e the fully quali\214ed domain name if your system is not con-)3.093 F +(\214gured so that information can \214nd it automatically)127 549.2 Q +(.)-.65 E 12.5($k The)102 565.4 R +(UUCP node name \(from the uname system call\).)2.5 E 9.72 +($l\207 \(Obsolete;)102 581.6 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 593.6 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 605.6 Q($d\232.)5 E 9.72 +($m The)102 621.8 R .719(domain part of the)3.219 F F2 -.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 633.8 Q F0($w)2.5 E(.$m)-.7 E F1(.)A 7.5($n\207 The) +102 650 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 +666.2 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)-3.151 F 2.504(characters which will be considered tok)127 +678.2 R 2.504(ens and which will separate tok)-.1 F 2.504 +(ens when doing)-.1 F .32 LW 76 687.8 72 687.8 DL 80 687.8 76 687.8 DL +84 687.8 80 687.8 DL 88 687.8 84 687.8 DL 92 687.8 88 687.8 DL 96 687.8 +92 687.8 DL 100 687.8 96 687.8 DL 104 687.8 100 687.8 DL 108 687.8 104 +687.8 DL 112 687.8 108 687.8 DL 116 687.8 112 687.8 DL 120 687.8 116 +687.8 DL 124 687.8 120 687.8 DL 128 687.8 124 687.8 DL 132 687.8 128 +687.8 DL 136 687.8 132 687.8 DL 140 687.8 136 687.8 DL 144 687.8 140 +687.8 DL 148 687.8 144 687.8 DL 152 687.8 148 687.8 DL 156 687.8 152 +687.8 DL 160 687.8 156 687.8 DL 164 687.8 160 687.8 DL 168 687.8 164 +687.8 DL 172 687.8 168 687.8 DL 176 687.8 172 687.8 DL 180 687.8 176 +687.8 DL 184 687.8 180 687.8 DL 188 687.8 184 687.8 DL 192 687.8 188 +687.8 DL 196 687.8 192 687.8 DL 200 687.8 196 687.8 DL 204 687.8 200 +687.8 DL 208 687.8 204 687.8 DL 212 687.8 208 687.8 DL 216 687.8 212 +687.8 DL/F4 5/Times-Roman@0 SF(17)93.6 698.2 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)-2 G(e\214ned.)-2 E +EP +%%Page: 39 35 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-39)195.86 E/F1 10/Times-Roman@0 SF 2.961(parsing. F)127 96 R +.461(or e)-.15 F .462(xample, if \231@\232 were in the)-.15 F F0($o) +2.962 E F1 .462(macro, then the input \231a@b\232 w)2.962 F .462 +(ould be scanned)-.1 F .591(as three tok)127 108 R .591(ens: \231a,)-.1 +F 3.091<9a99>-.7 G(@,)-3.091 E 3.091<9a61>-.7 G .591(nd \231b)-3.091 F +4.491 -.7(.\232 D)-.4 H(ef).7 E .59 +(aults to \231.:@[]\232, which is the minimum set necessary)-.1 F .16(t\ +o do RFC 822 parsing; a richer set of operators is \231.:%@!/[]\232, wh\ +ich adds support for UUCP)127 120 R(,)-1.11 E +(the %-hack, and X.400 addresses.)127 132 Q 12.5($p Sendmail')102 148.2 +R 2.5(sp)-.55 G(rocess id.)-2.5 E 7.5($q\207 Def)102 164.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)-2.903 G .403 +(ddress should appear in a)-2.903 F 1.18(message when it is def)127 +176.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 188.4 +Q 5<9a6f>-.7 G 2.5<7299>-5 G($g$?x \($x\)$.)-2.5 E +(\232, corresponding to the follo)-.7 E(wing tw)-.25 E 2.5(of)-.1 G +(ormats:)-2.5 E(Eric Allman ).65 E(eric@CS.Berk)167 216.6 Q(ele)-.1 E -.65(y.)-.15 G +(EDU \(Eric Allman\)).65 E/F2 10/Times-Italic@0 SF(Sendmail)127 232.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 249 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 F03.476 E F1 .976 +(command line \215ag or by the SMTP)3.476 F(serv)127 261 Q(er code.)-.15 +E 13.61($s Sender')102 277.2 R 2.5(sh)-.55 G(ost name.)-2.5 E +(Set from the)5 E F02.5 E F1 +(command line \215ag or by the SMTP serv)2.5 E(er code.)-.15 E 14.72 +($t A)102 293.4 R(numeric representation of the current time.)2.5 E 12.5 +($u The)102 309.6 R(recipient user)2.5 E(.)-.55 E 12.5($v The)102 325.8 +R -.15(ve)2.5 G(rsion number of the).15 E F2(sendmail)2.5 E F1(binary) +2.5 E(.)-.65 E 5.28($w\210 The)102 342 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)-2.5 E -.15(ve)-.2 G(ats\).).15 E 12.5($x The)102 358.2 R +(full name of the sender)2.5 E(.)-.55 E 13.06($z The)102 374.4 R +(home directory of the recipient.)2.5 E 12.5($_ The)102 390.6 R -.25(va) +2.5 G(lidated sender address.).25 E(${auth_authen})102 406.8 Q 1.222 +(The client')127 418.8 R 3.722(sa)-.55 G 1.223(uthentication credential\ +s as determined by authentication \(only set if success-)-3.722 F +(ful\).)127 430.8 Q(${auth_author})102 447 Q 1.302 +(The authorization identity)127 459 R 3.802(,i)-.65 G 1.302(.e. the A) +-3.802 F 1.301(UTH= parameter of the)-.55 F/F3 9/Times-Roman@0 SF 1.301 +(SMTP MAIL)3.801 F F1 1.301(command if sup-)3.801 F(plied.)127 471 Q +(${auth_type})102 487.2 Q +(The mechanism used for authentication \(only set if successful\).)127 +499.2 Q(${bodytype})102 515.4 Q +(The message body type \(7BIT or 8BITMIME\), as determined from the en) +127 527.4 Q -.15(ve)-.4 G(lope.).15 E(${client_addr})102 543.6 Q +(The IP address of the SMTP client.)127 555.6 Q +(De\214ned in the SMTP serv)5 E(er only)-.15 E(.)-.65 E(${client_name}) +102 571.8 Q .24(The host name of the SMTP client.)127 583.8 R .241 +(This may be the client')5.24 F 2.741(sb)-.55 G(rack)-2.741 E .241 +(eted IP address in the form)-.1 F 2.665([n)127 595.8 S .165 +(nn.nnn.nnn.nnn ] if the client')-2.665 F 2.665(sI)-.55 G 2.664(Pa) +-2.665 G .164(ddress is not resolv)-2.664 F .164(able, or if the resolv) +-.25 F .164(ed name doesn')-.15 F(t)-.18 E(match ${client_name}.)127 +607.8 Q(De\214ned in the SMTP serv)5 E(er only)-.15 E(.)-.65 E +(${client_port})102 624 Q(The port number of the SMTP client.)127 636 Q +(De\214ned in the SMTP serv)5 E(er only)-.15 E(.)-.65 E(${client_resolv) +102 652.2 Q(e})-.15 E 2.46(Holds the result of the resolv)127 664.2 R +4.961(ec)-.15 G 2.461(all for)-4.961 F F0(${client_name})4.961 E F1 +4.961(:O)4.961 G 2.461(K, F)-4.961 F 2.461(AIL, FORGED, TEMP)-.74 F(.) +-1.11 E(De\214ned in the SMTP serv)127 676.2 Q(er only)-.15 E(.)-.65 E +(${currHeader})102 692.4 Q(Header v)127 704.4 Q +(alue as quoted string \(possibly truncated to)-.25 E F0(MAXN)2.5 E(AME) +-.2 E F1(\).)A EP +%%Page: 40 36 +%%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 +(${daemon_addr})102 96 Q .927 +(The IP address the daemon is listening on for connections.)127 108 R +(Unless)5.926 E F0(DaemonP)3.426 E(ortOptions)-.2 E F1(is)3.426 E +(set, this will be \2310.0.0.0\232.)127 120 Q(${daemon_f)102 136.2 Q +(amily})-.1 E .355(The netw)127 148.2 R .355(ork f)-.1 F .356 +(amily if the daemon is accepting netw)-.1 F .356(ork connections.)-.1 F +.356(Possible v)5.356 F .356(alues include)-.25 F +(\231inet\232, \231inet6\232, \231iso\232, \231ns\232, \231x.25\232)127 +160.2 Q(${daemon_\215ags})102 176.4 Q .103 +(The \215ags for the daemon as speci\214ed by the Modi\214er= part of) +127 188.4 R F0(DaemonP)2.603 E(ortOptions)-.2 E F1(whereby)2.603 E .548 +(the \215ags are separated from each other by spaces, and upper case \ +\215ags are doubled.)127 200.4 R .549(That is,)5.549 F .37 +(Modi\214er=Ea will be represented as "EE a" in)127 212.4 R F0 +(${daemon_\215ags})2.87 E F1 2.87(,w)C .37(hich is required for testing) +-2.87 F(the \215ags in rulesets.)127 224.4 Q(${daemon_info})102 240.6 Q +4.763(Some information about a daemon as a te)127 252.6 R 4.764 +(xt string.)-.15 F -.15(Fo)9.764 G 7.264(re).15 G 4.764 +(xample, \231SMTP+queue-)-7.414 F(ing@00:30:00\232.)127 264.6 Q +(${daemon_name})102 280.8 Q .734(The name of the daemon from)127 292.8 R +F0(DaemonP)3.234 E(ortOptions)-.2 E F1 .734(Name= suboption.)3.234 F +.734(If this suboption is)5.734 F +(not set, "Daemon#", where # is the daemon number)127 304.8 Q 2.5(,i)-.4 +G 2.5(su)-2.5 G(sed.)-2.5 E(${daemon_port})102 321 Q 1.459 +(The port the daemon is accepting connection on.)127 333 R(Unless)6.459 +E F0(DaemonP)3.959 E(ortOptions)-.2 E F1 1.46(is set, this)3.959 F +(will most lik)127 345 Q(ely be \23125\232.)-.1 E(${deli)102 361.2 Q +-.15(ve)-.25 G(ryMode}).15 E .806(The current deli)127 373.2 R -.15(ve) +-.25 G .806(ry mode sendmail is using.).15 F .806 +(It is initially set to the v)5.806 F .805(alue of the)-.25 F F0(Deli) +3.305 E -.1(ve)-.1 G(ry-).1 E(Mode)127 385.2 Q F1(option.)2.5 E(${en)102 +401.4 Q(vid})-.4 E(The en)127 413.4 Q -.15(ve)-.4 G +(lope id passed to sendmail as part of the en).15 E -.15(ve)-.4 G(lope.) +.15 E(${hdrlen})102 429.6 Q .339(The length of the header v)127 441.6 R +.339 +(alue which is stored in ${currHeader} \(before possible truncation\).) +-.25 F(If this v)127 453.6 Q(alue is greater than or equal)-.25 E F0 +(MAXN)2.5 E(AME)-.2 E F1(the header has been truncated.)2.5 E +(${hdr_name})102 469.8 Q .167(The name of the header \214eld for which \ +the current header check ruleset has been called.)127 481.8 R(This)5.166 +E(is useful for a def)127 493.8 Q +(ault header check ruleset to get the name of the header)-.1 E(.)-.55 E +(${if_addr})102 510 Q(The IP address of the interf)127 522 Q +(ace of an incoming connection unless it is in the loopback net.)-.1 E +(${if_name})102 538.2 Q 1.46(The name of the interf)127 550.2 R 1.46 +(ace of an incoming connection.)-.1 F 1.46 +(This macro can be used for Smtp-)6.46 F 2.189 +(GreetingMessage and HRecei)127 562.2 R -.15(ve)-.25 G 4.689(df).15 G +2.189(or virtual hosting.)-4.689 F -.15(Fo)7.189 G 4.689(re).15 G 2.189 +(xample: O SmtpGreetingMes-)-4.839 F +(sage=$?{if_name}${if_name}$|$j$. Sendmail $v/$Z; $b)127 574.2 Q +(${mail_addr})102 590.4 Q 1.239(The address part of the resolv)127 602.4 +R 1.239(ed triple of the address gi)-.15 F -.15(ve)-.25 G 3.739(nf).15 G +1.239(or the)-3.739 F/F2 9/Times-Roman@0 SF 1.24(SMTP MAIL)3.739 F F1 +(command.)3.74 E(De\214ned in the SMTP serv)127 614.4 Q(er only)-.15 E +(.)-.65 E(${mail_host})102 630.6 Q .146(The host from the resolv)127 +642.6 R .146(ed triple of the address gi)-.15 F -.15(ve)-.25 G 2.646(nf) +.15 G .146(or the)-2.646 F F2 .145(SMTP MAIL)2.646 F F1 2.645 +(command. De\214ned)2.645 F(in the SMTP serv)127 654.6 Q(er only)-.15 E +(.)-.65 E(${mail_mailer})102 670.8 Q 2.14(The mailer from the resolv)127 +682.8 R 2.14(ed triple of the address gi)-.15 F -.15(ve)-.25 G 4.641(nf) +.15 G 2.141(or the)-4.641 F F2 2.141(SMTP MAIL)4.641 F F1(command.)4.641 +E(De\214ned in the SMTP serv)127 694.8 Q(er only)-.15 E(.)-.65 E +(${ntries})102 711 Q(The number of deli)127 723 Q -.15(ve)-.25 G +(ry attempts.).15 E EP +%%Page: 41 37 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-41)195.86 E/F1 10/Times-Roman@0 SF(${opMode})102 96 Q +(The current operation mode \(from the)127 108 Q F02.5 E F1 +(\215ag\).)2.5 E(${queue_interv)102 124.2 Q(al})-.25 E .362 +(The queue run interv)127 136.2 R .362(al gi)-.25 F -.15(ve)-.25 G 2.862 +(nb).15 G 2.862(yt)-2.862 G(he)-2.862 E F02.861 E F1 2.861 +(\215ag. F)2.861 F .361(or e)-.15 F(xample,)-.15 E F0(\255q30m)2.861 E +F1 -.1(wo)2.861 G .361(uld set).1 F F0(${queue_inter)2.861 E(-)-.37 E +-.1(va)127 148.2 S(l}).1 E F1(to \23100:30:00\232.)2.5 E(${rcpt_addr}) +102 164.4 Q 1.271(The address part of the resolv)127 176.4 R 1.272 +(ed triple of the address gi)-.15 F -.15(ve)-.25 G 3.772(nf).15 G 1.272 +(or the)-3.772 F/F2 9/Times-Roman@0 SF 1.272(SMTP RCPT)3.772 F F1 +(command.)3.772 E(De\214ned in the SMTP serv)127 188.4 Q(er only)-.15 E +(.)-.65 E(${rcpt_host})102 204.6 Q .179(The host from the resolv)127 +216.6 R .178(ed triple of the address gi)-.15 F -.15(ve)-.25 G 2.678(nf) +.15 G .178(or the)-2.678 F F2 .178(SMTP RCPT)2.678 F F1 2.678 +(command. De\214ned)2.678 F(in the SMTP serv)127 228.6 Q(er only)-.15 E +(.)-.65 E(${rcpt_mailer})102 244.8 Q 2.175(The mailer from the resolv) +127 256.8 R 2.175(ed triple of the address gi)-.15 F -.15(ve)-.25 G +4.675(nf).15 G 2.175(or the)-4.675 F F2 2.176(SMTP RCPT)4.676 F F1 +(command.)4.676 E(De\214ned in the SMTP serv)127 268.8 Q(er only)-.15 E +(.)-.65 E .749(There are three types of dates that can be used.)127 285 +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 297 Q F0($a)3.213 E +F1 .713(is the time as e)3.213 F .714 +(xtracted from the \231Date:\232 line of the message \(if there w)-.15 F +.714(as one\), and)-.1 F F0($b)3.214 E F1(is)3.214 E .057 +(the current date and time \(used for postmarks\).)102 309 R .056 +(If no \231Date:\232 line is found in the incoming message,)5.057 F F0 +($a)102 321 Q F1 .304(is set to the current time also.)2.804 F(The)5.304 +E F0($d)2.804 E F1 .305(macro is equi)2.804 F -.25(va)-.25 G .305 +(lent to the).25 F F0($b)2.805 E F1 .305(macro in UNIX \(ctime\) for) +2.805 F(-)-.2 E(mat.)102 333 Q .239(The macros)127 349.2 R F0($w)2.739 E +F1(,)A F0($j)2.739 E F1 2.739(,a)C(nd)-2.739 E F0($m)2.739 E F1 .238 +(are set to the identity of this host.)2.739 F/F3 10/Times-Italic@0 SF +(Sendmail)5.238 E F1 .238(tries to \214nd the fully)2.738 F .334(quali\ +\214ed name of the host if at all possible; it does this by calling)102 +361.2 R F3 -.1(ge)2.835 G(thostname).1 E F1 .335 +(\(2\) to get the current)B .457(hostname and then passing that to)102 +373.2 R F3 -.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 +.278(sion of that host name.)102 387.2 R/F4 7/Times-Roman@0 SF(18)-4 I +F1 .278(Assuming this is successful,)2.778 4 N F0($j)2.778 E F1 .279 +(is set to the fully quali\214ed name and)2.778 F F0($m)2.779 E F1(is) +2.779 E .706(set to the domain part of the name \(e)102 399.2 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 411.2 S +.358(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)-2.858 G .359 +(igher con\214guration \214le; otherwise, it)-2.858 F .405 +(is set to the same v)102 423.2 R .405(alue as)-.25 F F0($j)2.905 E F1 +5.405(.I)C 2.905(ft)-5.405 G .405 +(he canoni\214cation is not successful, it is imperati)-2.905 F .704 +-.15(ve t)-.25 H .404(hat the con\214g).15 F(\214le set)102 437.2 Q F0 +($j)2.5 E F1(to the fully quali\214ed domain name)2.5 E F4(19)-4 I F1(.) +4 I(The)127 453.4 Q F0($f)2.832 E F1 .333(macro is the id of the sender\ + as originally determined; when mailing to a speci\214c host)2.833 F +(the)102 465.4 Q F0($g)3.225 E F1 .725 +(macro is set to the address of the sender)3.225 F F3 -.37(re)3.224 G +.724(lative to the r).37 F(ecipient.)-.37 E F1 -.15(Fo)5.724 G 3.224(re) +.15 G .724(xample, if I send to)-3.374 F(\231bollard@matisse.CS.Berk)102 +477.4 Q(ele)-.1 E -.65(y.)-.15 G .424(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.925 E F1(macro)2.925 E(will be \231eric\232 and the)102 489.4 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 505.6 Q F0($x)2.563 E +F1 .062(macro is set to the full name of the sender)2.563 F 5.062(.T) +-.55 G .062(his can be determined in se)-5.062 F -.15(ve)-.25 G .062 +(ral w).15 F 2.562(ays. It)-.1 F .629(can be passed as \215ag to)102 +517.6 R F3(sendmail)3.129 E F1 5.629(.I)C 3.129(tc)-5.629 G .629 +(an be de\214ned in the)-3.129 F F2 -.315(NA)3.13 G(ME).315 E F1(en)3.13 +E .63(vironment v)-.4 F 3.13(ariable. The)-.25 F(third)3.13 E .949 +(choice is the v)102 529.6 R .949 +(alue of the \231Full-Name:\232 line in the header if it e)-.25 F .948 +(xists, and the fourth choice is the)-.15 F .526 +(comment \214eld of a \231From:\232 line.)102 541.6 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 553.6 Q(ed up in the)-.1 E F3(/etc/passwd)2.5 +E F1(\214le.)2.5 E 1.321(When sending, the)127 569.8 R F0($h)3.821 E F1 +(,)A F0($u)3.821 E F1 3.821(,a)C(nd)-3.821 E F0($z)3.821 E F1 1.321 +(macros get set to the host, user)3.821 F 3.82(,a)-.4 G 1.32 +(nd home directory \(if)-3.82 F .516(local\) of the recipient.)102 581.8 +R .516(The \214rst tw)5.516 F 3.016(oa)-.1 G .516(re set from the)-3.016 +F F0($@)3.016 E F1(and)3.016 E F0($:)3.016 E F1 .517(part of the re) +3.017 F .517(writing rules, respec-)-.25 F(ti)102 593.8 Q -.15(ve)-.25 G +(ly).15 E(.)-.65 E(The)127 610 Q F0($p)3.806 E F1(and)3.806 E F0($t) +3.806 E F1 1.306(macros are used to create unique strings \(e.g., for t\ +he \231Message-Id:\232 \214eld\).)3.806 F(The)102 622 Q F0($i)3.251 E F1 +.751(macro is set to the queue id on this host; if put into the timesta\ +mp line it can be e)3.251 F(xtremely)-.15 E .165 +(useful for tracking messages.)102 634 R(The)5.165 E F0($v)2.665 E F1 +.164(macro is set to be the v)2.665 F .164(ersion number of)-.15 F F3 +(sendmail)2.664 E F1 2.664(;t)C .164(his is nor)-2.664 F(-)-.2 E +(mally put in timestamps and has been pro)102 646 Q -.15(ve)-.15 G 2.5 +(ne).15 G(xtremely useful for deb)-2.65 E(ugging.)-.2 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(18)93.6 +675.6 Q/F6 8/Times-Roman@0 SF -.12(Fo)3.2 K 2(re).12 G +(xample, on some systems)-2.12 E/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(19)93.6 689.2 Q F6(Older v)3.2 I +(ersions of sendmail didn')-.12 E 2(tp)-.144 G(re-de\214ne)-2 E/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: 42 38 +%%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(The)127 +96 Q F0($c)3.547 E F1 1.048(\214eld is set to the \231hop count,)3.547 F +3.548<9a69>-.7 G 1.048 +(.e., the number of times this message has been pro-)-3.548 F 2.857 +(cessed. This)102 108 R .357(can be determined by the)2.857 F F0 +2.857 E F1 .356 +(\215ag on the command line or by counting the timestamps)2.857 F +(in the message.)102 120 Q(The)127 136.2 Q F0($r)2.832 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 10 +/Times-Italic@0 SF(sendmail)2.833 E F1 .333(and the send-)2.833 F .195 +(ing hostname.)102 148.2 R(The)5.195 E 2.694(yc)-.15 G .194 +(an be set together using the)-2.694 F F02.694 E F1 .194 +(command line \215ag or separately using the)2.694 F F02.694 E F1 +(or)102 160.2 Q F0(\255oM)2.5 E F1(\215ags.)2.5 E(The)127 176.4 Q F0($_) +2.966 E F1 .466(is set to a v)2.966 F .467(alidated sender host name.) +-.25 F .467(If the sender is running an RFC 1413 compli-)5.467 F .385 +(ant IDENT serv)102 188.4 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)-2.884 F +(on that host.)102 200.4 Q(The)127 216.6 Q F0(${client_name})5.98 E F1 +(,)A F0(${client_addr})5.98 E F1 5.98(,a)C(nd)-5.98 E F0(${client_port}) +5.98 E F1 3.48(macros are set to the name,)5.98 F .786 +(address, and port number of the SMTP client who is in)102 228.6 R -.2 +(vo)-.4 G(king).2 E F2(sendmail)3.286 E F1 .786(as a serv)3.286 F(er) +-.15 E 5.786(.T)-.55 G .785(hese can be)-5.786 F(used in the)102 240.6 Q +F2 -.15(ch)2.5 G(ec).15 E(k_*)-.2 E F1(rulesets \(using the)2.5 E F0($&) +2.5 E F1(deferred e)2.5 E -.25(va)-.25 G(luation form, of course!\).).25 +E F0 2.5(5.3. C)87 264.6 R(and F \212 De\214ne Classes)2.5 E F1 .659(Cl\ +asses of phrases may be de\214ned to match on the left hand side of re) +127 280.8 R .66(writing rules, where a)-.25 F .465(\231phrase\232 is a \ +sequence of characters that does not contain space characters.)102 292.8 +R -.15(Fo)5.464 G 2.964(re).15 G .464(xample a class of)-3.114 F .654(a\ +ll local names for this site might be created so that attempts to send \ +to oneself can be eliminated.)102 304.8 R .041(These can either be de\ +\214ned directly in the con\214guration \214le or read in from another \ +\214le.)102 316.8 R .04(Classes are)5.04 F .649 +(named as a single letter or a w)102 328.8 R .649(ord in {braces}.)-.1 F +.649(Class names be)5.649 F .649(ginning with lo)-.15 F .649 +(wer case letters and)-.25 F .639(special characters are reserv)102 +340.8 R .639(ed for system use.)-.15 F .638 +(Classes de\214ned in con\214g \214les may be gi)5.639 F -.15(ve)-.25 G +3.138(nn).15 G(ames)-3.138 E 1.05 +(from the set of upper case letters for short names or be)102 352.8 R +1.05(ginning with an upper case letter for long)-.15 F(names.)102 364.8 +Q(The syntax is:)127 381 Q F0(C)142 397.2 Q F2 1.666(cp)C(hr)-1.666 E +(ase1 phr)-.15 E(ase2...)-.15 E F0(F)142 409.2 Q F2 1.666<638c>C(le) +-1.666 E F1 .036(The \214rst form de\214nes the class)102 425.4 R F2(c) +2.535 E F1 .035(to match an)2.535 F 2.535(yo)-.15 G 2.535(ft)-2.535 G +.035(he named w)-2.535 F 2.535(ords. If)-.1 F F2(phr)2.535 E(ase1)-.15 E +F1(or)2.535 E F2(phr)2.535 E(ase2)-.15 E F1 .035(is another)2.535 F .746 +(class, e.g.,)102 437.4 R F2($=S)3.246 E F1 3.246(,t)C .746 +(he contents of class)-3.246 F F2(S)3.246 E F1 .746(are added to class) +3.246 F F2(c)3.246 E F1 5.746(.I)C 3.247(ti)-5.746 G 3.247(sp)-3.247 G +.747(ermissible to split them among)-3.247 F(multiple lines; for e)102 +449.4 Q(xample, the tw)-.15 E 2.5(of)-.1 G(orms:)-2.5 E +(CHmonet ucbmonet)142 465.6 Q(and)102 481.8 Q(CHmonet)142 498 Q +(CHucbmonet)142 510 Q(are equi)102 526.2 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)-2.5 E 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 542.4 R F0($=) +3.839 E F1(or)3.839 E F0($~)3.839 E F1 6.339(.T)C(he)-6.339 E F0($~) +3.839 E F1 1.338(\(match entries not in)3.839 F +(class\) only matches a single w)102 554.4 Q(ord; multi-w)-.1 E +(ord entries in the class are ignored in this conte)-.1 E(xt.)-.15 E +(Some classes ha)127 570.6 Q .3 -.15(ve i)-.2 H(nternal meaning to).15 E +F2(sendmail)2.5 E F1(:)A 18.42($=e contains)102 586.8 R .561 +(the Content-T)3.061 F(ransfer)-.35 E .561(-Encodings that can be 8)-.2 +F/F3 10/Symbol SFA F1 3.062(7b)C .562(it encoded.)-3.062 F .562 +(It is prede\214ned to)5.562 F +(contain \2317bit\232, \2318bit\232, and \231binary\232.)138 598.8 Q +17.86($=k set)102 615 R(to be the same as)2.5 E F0($k)2.5 E F1 2.5(,t)C +(hat is, the UUCP node name.)-2.5 E 15.08($=m set)102 631.2 R +(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 17.86($=n can)102 647.4 R +.581(be set to the set of MIME body types that can ne)3.081 F -.15(ve) +-.25 G 3.08(rb).15 G 3.08(ee)-3.08 G .58(ight to se)-3.08 F -.15(ve)-.25 +G 3.08(nb).15 G .58(it encoded.)-3.08 F(It)5.58 E(def)138 659.4 Q 1.81 +(aults to \231multipart/signed\232.)-.1 F 1.81 +(Message types \231message/*\232 and \231multipart/*\232 are ne)6.81 F +-.15(ve)-.25 G(r).15 E 1.853(encoded directly)138 671.4 R 6.853(.M)-.65 +G 1.853(ultipart messages are al)-6.853 F -.1(wa)-.1 G 1.853 +(ys handled recursi).1 F -.15(ve)-.25 G(ly).15 E 6.853(.T)-.65 G 1.853 +(he handling of)-6.853 F(message/* messages are controlled by class)138 +683.4 Q F0($=s)2.5 E F1(.)A 17.86($=q A)102 699.6 R .711 +(set of Content-T)3.211 F .712(ypes that will ne)-.8 F -.15(ve)-.25 G +3.212(rb).15 G 3.212(ee)-3.212 G .712(ncoded as base64 \(if the)-3.212 F +3.212(yh)-.15 G -2.25 -.2(av e)-3.212 H .712(to be encoded,)3.412 F(the) +138 711.6 Q 3.358(yw)-.15 G .858(ill be encoded as quoted-printable\).) +-3.358 F .858(It can ha)5.858 F 1.158 -.15(ve p)-.2 H .858 +(rimary types \(e.g., \231te).15 F .857(xt\232\) or full)-.15 F +(types \(such as \231te)138 723.6 Q 2.5(xt/plain\232\). The)-.15 F +(class is initialized to ha)2.5 E .3 -.15(ve \231)-.2 H(te).15 E +(xt/plain\232 only)-.15 E(.)-.65 E EP +%%Page: 43 39 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-43)195.86 E/F1 10/Times-Roman@0 SF 18.97($=s contains)102 96 R +.648(the set of subtypes of message that can be treated recursi)3.148 F +-.15(ve)-.25 G(ly).15 E 5.648(.B)-.65 G 3.148(yd)-5.648 G(ef)-3.148 E +.648(ault it con-)-.1 F .97(tains only \231rfc822\232.)138 108 R .969 +(Other \231message/*\232 types cannot be 8)5.97 F/F2 10/Symbol SFA +F1 3.469(7b)C .969(it encoded.)-3.469 F .969(If a message)5.969 F 1.045 +(containing eight bit data is sent to a se)138 120 R -.15(ve)-.25 G +3.545(nb).15 G 1.045(it host, and that message cannot be encoded)-3.545 +F(into se)138 132 Q -.15(ve)-.25 G 2.5(nb).15 G +(its, it will be stripped to 7 bits.)-2.5 E 20.08($=t set)102 148.2 R +.372(to the set of trusted users by the)2.873 F F0(T)2.872 E F1 .372 +(con\214guration line.)2.872 F .372(If you w)5.372 F .372 +(ant to read trusted users)-.1 F(from a \214le, use)138 160.2 Q F0(Ft) +2.5 E/F3 10/Times-Italic@0 SF(/\214le/name)A F1(.)A 15.64($=w set)102 +176.4 R .513(to be the set of all names this host is kno)3.013 F .513 +(wn by)-.25 F 5.513(.T)-.65 G .513(his can be used to match local host-) +-5.513 F(names.)138 188.4 Q($={persistentMacros})102 204.6 Q 1.052 +(set to the macros w)138 216.6 R 1.052(ould should be sa)-.1 F -.15(ve) +-.2 G 3.552(da).15 G 1.052(cross queue runs.)-3.552 F 1.052 +(Care should be tak)6.052 F 1.052(en when)-.1 F +(adding macro names to this class.)138 228.6 Q F3(Sendmail)127 244.8 Q +F1 .182(can be compiled to allo)2.682 F 2.682(wa)-.25 G F3(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 256.8 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)-3.205 F F3 +(/etc/passwd)3.054 E F1 .554(\214le into a)3.054 F(class, use)102 268.8 +Q(FL/etc/passwd %[^:])142 285 Q(which reads e)102 301.2 Q -.15(ve)-.25 G +(ry line up to the \214rst colon.).15 E F0 2.5(5.4. M)87 325.2 R 2.5 +<8a44>2.5 G(e\214ne Mailer)-2.5 E F1(Programs and interf)127 341.4 Q +(aces to mailers are de\214ned in this line.)-.1 E(The format is:)5 E F0 +(M)142 357.6 Q F3(name)A F1 2.5(,{)C F3(\214eld)-2.5 E F1(=)A F3(value)A +F1(}*)1.666 E(where)102 373.8 Q F3(name)4.244 E F1 1.744(is the name of\ + the mailer \(used internally only\) and the \231\214eld=name\232 pairs\ + de\214ne)4.244 F(attrib)102 385.8 Q(utes of the mailer)-.2 E 5(.F)-.55 +G(ields are:)-5 E -.15(Pa)142 402 S 51.87(th The).15 F +(pathname of the mailer)2.5 E 47.83(Flags Special)142 414 R +(\215ags for this mailer)2.5 E 41.73(Sender Re)142 426 R +(writing set\(s\) for sender addresses)-.25 E 31.17(Recipient Re)142 438 +R(writing set\(s\) for recipient addresses)-.25 E(Ar)142 450 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 462 R(end-of-line string for this mailer)2.5 E 35.62 +(Maxsize The)142 474 R(maximum message length to this mailer)2.5 E 14.51 +(maxmessages The)142 486 R(maximum message deli)2.5 E -.15(ve)-.25 G +(ries per connection).15 E 32.27(Linelimit The)142 498 R +(maximum line length in the message body)2.5 E 31.18(Directory The)142 +510 R -.1(wo)2.5 G(rking directory for the mailer).1 E 42.84(Userid The) +142 522 R(def)2.5 E(ault user and group id to run as)-.1 E 50.62 +(Nice The)142 534 R(nice\(2\) increment for the mailer)2.5 E 38.95 +(Charset The)142 546 R(def)2.5 E +(ault character set for 8-bit characters)-.1 E -.8(Ty)142 558 S 49.75 +(pe T).8 F(ype information for DSN diagnostics)-.8 E -.8(Wa)142 570 S +50.86(it The).8 F(maximum time to w)2.5 E(ait for the mailer)-.1 E 69.22 +(/T)142 582 S(he root directory for the mailer)-69.22 E +(Only the \214rst character of the \214eld name is check)102 598.2 Q +(ed.)-.1 E .397(The follo)127 614.4 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)-2.896 F .075(to c\ +onditionally assign headers to messages destined for particular mailers\ +.)102 626.4 R .075(Flags mark)5.075 F .075(ed with \207 are)-.1 F 1.193 +(not interpreted by the)102 638.4 R F3(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 650.4 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 662.4 Q 15.56(aR)102 678.6 S .987 +(un Extended SMTP \(ESMTP\) protocol \(de\214ned in RFCs 1869, 1652, an\ +d 1870\).)-15.56 F .986(This \215ag)5.987 F(def)122 690.6 Q +(aults on if the SMTP greeting message includes the w)-.1 E +(ord \231ESMTP\232.)-.1 E 12.78(AL)102 706.8 S .762 +(ook up the user part of the address in the alias database.)-12.78 F +.763(Normally this is only set for local)5.762 F(mailers.)122 718.8 Q EP +%%Page: 44 40 +%%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 15(bF)102 +96 S .456(orce a blank line on the end of a message.)-15.15 F .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 +108 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 120 Q(ork mail.)-.1 E 15.56(cD)102 136.2 S +2.663(on)-15.56 G .163(ot include comments in addresses.)-2.663 F .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)-2.763 F 1.846 +(remote mailer that gets confused by comments.)122 148.2 R 1.846 +(This strips addresses of the form \231Phrase)6.846 F +(
\232 or \231address \(Comment\)\232 do)122 160.2 Q +(wn to just \231address\232.)-.25 E 5.83(C\210 If)102 176.4 R .214 +(mail is)2.714 F/F2 10/Times-Italic@0 SF -.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)-2.713 F -.15(ve)-.2 G .97 +(an at sign \(\231@\232\) after being re)122 188.4 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 200.4 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 216.6 Q +-.8(To)162 228.6 S 2.5(:u).8 G(serb@hostb, userc)-2.5 E(to be re)122 +244.8 Q(written as:)-.25 E(From: usera@hosta)162 261 Q -.8(To)162 273 S +2.5(:u).8 G(serb@hostb, userc@hosta)-2.5 E(automatically)122 289.2 Q 5 +(.H)-.65 G -.25(ow)-5 G -2.15 -.25(ev e).25 H .8 -.4(r, i).25 H 2.5(td) +.4 G(oesn')-2.5 E 2.5(tr)-.18 G(eally w)-2.5 E(ork reliably)-.1 E(.)-.65 +E 15(dD)102 305.4 S 2.56(on)-15 G .06(ot include angle brack)-2.56 F .06 +(ets around route-address syntax addresses.)-.1 F .06 +(This is useful on mailers)5.06 F .187(that are going to pass addresses\ + to a shell that might interpret angle brack)122 317.4 R .188 +(ets as I/O redirection.)-.1 F(Ho)122 329.4 Q(we)-.25 E -.15(ve)-.25 G +1.621 -.4(r, i).15 H 3.321(td).4 G .821(oes not protect ag)-3.321 F .821 +(ainst other shell metacharacters.)-.05 F .821 +(Therefore, passing addresses)5.821 F +(to a shell should not be considered secure.)122 341.4 Q 5.28 +(D\207 This)102 357.6 R(mailer w)2.5 E +(ants a \231Date:\232 header line.)-.1 E 15.56(eT)102 373.8 S .173 +(his mailer is e)-15.56 F(xpensi)-.15 E .473 -.15(ve t)-.25 H 2.673(oc) +.15 G .173(onnect to, so try to a)-2.673 F -.2(vo)-.2 G .174 +(id connecting normally; an).2 F 2.674(yn)-.15 G .174(ecessary con-) +-2.674 F(nection will occur during a queue run.)122 385.8 Q +(See also option)5 E F0(HoldExpensi)2.5 E -.1(ve)-.1 G F1(.).1 E 13.89 +(EE)102 402 S(scape lines be)-13.89 E(ginning with \231From)-.15 E 2.5 +<9a69>5 G 2.5(nt)-2.5 G(he message with a `>' sign.)-2.5 E 16.67(fT)102 +418.2 S .19(he mailer w)-16.67 F .19(ants a)-.1 F F02.69 E F2(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 430.2 Q .3 -.15(ve a)-.25 H 2.5(ne).15 G(rror if the e)-2.5 +E -.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 446.4 R(mailer w)2.5 E +(ants a \231From:\232 header line.)-.1 E 15(gN)102 462.6 S(ormally)-15 E +(,)-.65 E F2(sendmail)4.892 E F1 2.393(sends internally generated email\ + \(e.g., error messages\) using the null)4.892 F 1.327 +(return address as required by RFC 1123.)122 474.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.327(ccept a null return)-3.827 F 3.31(address. If)122 486.6 +R(necessary)3.31 E 3.31(,y)-.65 G .81(ou can set the)-3.31 F F0(g)3.311 +E F1 .811(\215ag to pre)3.311 F -.15(ve)-.25 G(nt).15 E F2(sendmail) +3.311 E F1 .811(from obe)3.311 F .811(ying the standards;)-.15 F 1.57 +(error messages will be sent as from the MAILER-D)122 498.6 R 1.57 +(AEMON \(actually)-.4 F 4.07(,t)-.65 G 1.57(he v)-4.07 F 1.57 +(alue of the)-.25 F F0($n)4.07 E F1(macro\).)122 510.6 Q 15(hU)102 526.8 +S(pper case should be preserv)-15 E(ed in host names for this mailer) +-.15 E(.)-.55 E 17.22(iD)102 543 S 2.5(oU)-17.22 G(ser Database re)-2.5 +E(writing on en)-.25 E -.15(ve)-.4 G(lope sender address.).15 E 16.67 +(IT)102 559.2 S .474(his mailer will be speaking SMTP to another)-16.67 +F F2(sendmail)2.974 E F1 2.974<8a61>2.974 G 2.975(ss)-2.974 G .475 +(uch it can use special protocol)-2.975 F 3.633(features. This)122 571.2 +R 1.133(option is not required \(i.e., if this option is omitted the tr\ +ansmission will still)3.633 F(operate successfully)122 583.2 Q 2.5(,a) +-.65 G(lthough perhaps not as ef)-2.5 E(\214ciently as possible\).)-.25 +E 17.22(jD)102 599.4 S 2.5(oU)-17.22 G(ser Database re)-2.5 E +(writing on recipients as well as senders.)-.25 E 15(kN)102 615.6 S +1.029(ormally when)-15 F F2(sendmail)3.529 E F1 1.029 +(connects to a host via SMTP)3.529 F 3.529(,i)-1.11 G 3.529(tc)-3.529 G +1.03(hecks to mak)-3.529 F 3.53(es)-.1 G 1.03(ure that this isn')-3.53 F +(t)-.18 E .562(accidently the same host name as might happen if)122 +627.6 R F2(sendmail)3.062 E F1 .562 +(is miscon\214gured or if a long-haul)3.062 F(netw)122 639.6 Q 1.073 +(ork interf)-.1 F 1.073(ace is set in loopback mode.)-.1 F 1.074 +(This \215ag disables the loopback check.)6.074 F 1.074(It should)6.074 +F(only be used under v)122 651.6 Q(ery unusual circumstances.)-.15 E +12.78(KC)102 667.8 S(urrently unimplemented.)-12.78 E(Reserv)5 E +(ed for chunking.)-.15 E 17.22(lT)102 684 S +(his mailer is local \(i.e., \214nal deli)-17.22 E -.15(ve)-.25 G +(ry will be performed\).).15 E 13.89(LL)102 700.2 S .82 +(imit the line lengths as speci\214ed in RFC821.)-13.89 F .819 +(This deprecated option should be replaced by)5.819 F(the)122 712.2 Q F0 +(L=)2.5 E F1(mail declaration.)2.5 E -.15(Fo)5 G 2.5(rh).15 G +(istoric reasons, the)-2.5 E F0(L)2.5 E F1(\215ag also sets the)2.5 E F0 +(7)2.5 E F1(\215ag.)2.5 E EP +%%Page: 45 41 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-45)195.86 E/F1 10/Times-Roman@0 SF 12.22(mT)102 96 S .463(his m\ +ailer can send to multiple users on the same host in one transaction.) +-12.22 F .464(When a)5.464 F F0($u)2.964 E F1(macro)2.964 E .732 +(occurs in the)122 108 R/F2 10/Times-Italic@0 SF(ar)3.232 E(gv)-.37 E F1 +.732(part of the mailer de\214nition, that \214eld will be repeated as \ +necessary for all)3.232 F(qualifying users.)122 120 Q 3.61(M\207 This) +102 136.2 R(mailer w)2.5 E(ants a \231Message-Id:\232 header line.)-.1 E +15(nD)102 152.4 S 2.5(on)-15 G +(ot insert a UNIX-style \231From\232 line on the front of the message.) +-2.5 E 15(oA)102 168.6 S -.1(lwa)-15 G .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 180.6 R +2.698(,t)-.65 G .198(he user speci\214ed in the)-2.698 F F0(u)2.698 E F1 +.198(option\) when deli)2.698 F(v-)-.25 E 1.337(ering netw)122 192.6 R +1.337(ork mail.)-.1 F 1.338(The normal beha)6.338 F 1.338 +(vior is required by most local mailers, which will not)-.2 F(allo)122 +204.6 Q 2.521(wt)-.25 G .021(he en)-2.521 F -.15(ve)-.4 G .021 +(lope sender address to be set unless the mailer is running as daemon.) +.15 F .02(This \215ag is)5.02 F(ignored if the)122 216.6 Q F0(S)2.5 E F1 +(\215ag is set.)2.5 E 15(pU)102 232.8 S .497(se the route-addr style re) +-15 F -.15(ve)-.25 G .498(rse-path in the SMTP \231MAIL FR).15 F .498 +(OM:\232 command rather than just)-.4 F .385(the return address; althou\ +gh this is required in RFC821 section 3.1, man)122 244.8 R 2.885(yh)-.15 +G .385(osts do not process)-2.885 F(re)122 256.8 Q -.15(ve)-.25 G +(rse-paths properly).15 E 5(.R)-.65 G -2.15 -.25(ev e)-5 H +(rse-paths are of).25 E(\214cially discouraged by RFC 1123.)-.25 E 6.94 +(P\207 This)102 273 R(mailer w)2.5 E(ants a \231Return-P)-.1 E +(ath:\232 line.)-.15 E 15(qW)102 289.2 S .068 +(hen an address that resolv)-15 F .069(es to this mailer is v)-.15 F +.069(eri\214ed \(SMTP VRFY command\), generate 250)-.15 F +(responses instead of 252 responses.)122 301.2 Q +(This will imply that the address is local.)5 E 16.67(rS)102 317.4 S +(ame as)-16.67 E F0(f)2.5 E F1 2.5(,b)C(ut sends a)-2.7 E F02.5 E +F1(\215ag.)2.5 E 13.33(RO)102 333.6 S .67 +(pen SMTP connections from a \231secure\232 port.)-13.33 F .669 +(Secure ports aren')5.669 F 3.169(t\()-.18 G .669(secure, that is\) e) +-3.169 F .669(xcept on)-.15 F +(UNIX machines, so it is unclear that this adds an)122 345.6 Q(ything.) +-.15 E 16.11(sS)102 361.8 S(trip quote characters \(" and \\\) of)-16.11 +E 2.5(fo)-.25 G 2.5(ft)-2.5 G(he address before calling the mailer)-2.5 +E(.)-.55 E 14.44(SD)102 378 S(on')-14.44 E 3.331(tr)-.18 G .831 +(eset the userid before calling the mailer)-3.331 F 5.831(.T)-.55 G .831 +(his w)-5.831 F .832(ould be used in a secure en)-.1 F(vironment)-.4 E +(where)122 390 Q F2(sendmail)3.318 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 .817 +(\214eld is)3.317 F(also speci\214ed, this \215ag causes the ef)122 402 +Q(fecti)-.25 E .3 -.15(ve u)-.25 H(ser id to be set to that user).15 E +(.)-.55 E 15(uU)102 418.2 S(pper case should be preserv)-15 E +(ed in user names for this mailer)-.15 E(.)-.55 E 12.78(UT)102 434.4 S +(his mailer w)-12.78 E(ants UUCP-style \231From\232 lines with the ugly\ + \231remote from \232 on the end.)-.1 E 12.78(wT)102 450.6 S .565 +(he user must ha)-12.78 F .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 462.6 Q +(This is required to get \231.forw)5 E(ard\232 capability)-.1 E(.)-.65 E +7.5(x\207 This)102 478.8 R(mailer w)2.5 E +(ants a \231Full-Name:\232 header line.)-.1 E 12.78(XT)102 495 S .972 +(his mailer w)-12.78 F .972(ant to use the hidden dot algorithm as spec\ +i\214ed in RFC821; basically)-.1 F 3.472(,a)-.65 G 1.272 -.15(ny l) +-3.472 H(ine).15 E(be)122 507 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\).)-3.446 F(This) +5.797 E(insures that lines in the message containing a dot will not ter\ +minate the message prematurely)122 519 Q(.)-.65 E 15.56(zR)102 535.2 S +.965(un Local Mail T)-15.56 F .965(ransfer Protocol \(LMTP\) between) +-.35 F F2(sendmail)3.465 E F1 .965(and the local mailer)3.465 F 5.965 +(.T)-.55 G .965(his is a)-5.965 F -.25(va)122 547.2 S .167(riant on SMT\ +P de\214ned in RFC 2033 that is speci\214cally designed for deli).25 F +-.15(ve)-.25 G .167(ry to a local mail-).15 F(box.)122 559.2 Q 15(0D)102 +575.4 S(on')-15 E 2.5(tl)-.18 G +(ook up MX records for hosts sent via SMTP)-2.5 E(.)-1.11 E 15(3E)102 +591.6 S .002(xtend the list of characters con)-15 F -.15(ve)-.4 G .001 +(rted to =XX notation when con).15 F -.15(ve)-.4 G .001 +(rting to Quoted-Printable to).15 F .977(include those that don')122 +603.6 R 3.478(tm)-.18 G .978(ap cleanly between ASCII and EBCDIC.)-3.478 +F .978(Useful if you ha)5.978 F 1.278 -.15(ve I)-.2 H(BM).15 E +(mainframes on site.)122 615.6 Q 15(5I)102 631.8 S 2.717(fn)-15 G 2.717 +(oa)-2.717 G .217(liases are found for this address, pass the address t\ +hrough ruleset 5 for possible alternate)-2.717 F 2.5(resolution. This) +122 643.8 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(6S)102 660 S(trip headers to se) +-15 E -.15(ve)-.25 G 2.5(nb).15 G(its.)-2.5 E 15(7S)102 676.2 S 1.14 +(trip all output to se)-15 F -.15(ve)-.25 G 3.64(nb).15 G 3.64 +(its. This)-3.64 F 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 688.2 R .295 +(\214cient to get full eight bit data passed through)-.25 F F2(sendmail) +2.795 E F1 5.295(.I)C 2.795(ft)-5.295 G(he)-2.795 E F0(7)2.795 E F1 .295 +(option is set,)2.795 F .716(this is essentially al)122 700.2 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 712.2 Q 2.5(th)-.18 G -2.25 +-.2(av e)-2.5 H(8)2.7 E/F3 10/Symbol SFA F1 2.5(7b)C(it MIME con) +-2.5 E -.15(ve)-.4 G(rsions performed.).15 E EP +%%Page: 46 42 +%%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 15(8I)102 +96 S 3.783(fs)-15 G 1.283(et, it is acceptable to send eight bit data t\ +o this mailer; the usual attempt to do 8)-3.783 F/F2 10/Symbol SFA +F1 3.782(7b)C(it)-3.782 E(MIME con)122 108 Q -.15(ve)-.4 G +(rsions will be bypassed.).15 E 15(9I)102 124.2 S 2.704(fs)-15 G .204 +(et, do)-2.704 F/F3 10/Times-Italic@0 SF(limited)2.704 E F1(7)2.704 E F2 +A F1 2.704(8b)C .204(it MIME con)-2.704 F -.15(ve)-.4 G 2.704 +(rsions. These).15 F(con)2.704 E -.15(ve)-.4 G .205 +(rsions are limited to te).15 F .205(xt/plain data.)-.15 F 17.22(:C)102 +140.4 S .982(heck addresses to see if the)-17.22 F 3.482(yb)-.15 G -.15 +(eg)-3.482 G .982(in \231:include:\232; if the).15 F 3.482(yd)-.15 G +.982(o, con)-3.482 F -.15(ve)-.4 G .982 +(rt them to the \231*include*\232).15 F(mailer)122 152.4 Q(.)-.55 E 18 +(|C)102 168.6 S(heck addresses to see if the)-18 E 2.5(yb)-.15 G -.15 +(eg)-2.5 G(in with a `|'; if the).15 E 2.5(yd)-.15 G(o, con)-2.5 E -.15 +(ve)-.4 G(rt them to the \231prog\232 mailer).15 E(.)-.55 E 17.22(/C)102 +184.8 S(heck addresses to see if the)-17.22 E 2.5(yb)-.15 G -.15(eg)-2.5 +G(in with a `/'; if the).15 E 2.5(yd)-.15 G(o, con)-2.5 E -.15(ve)-.4 G +(rt them to the \231*\214le*\232 mailer).15 E(.)-.55 E 10.79(@L)102 201 +S(ook up addresses in the user database.)-10.79 E 11.67(%D)102 217.2 S +3.382(on)-11.67 G .882(ot attempt deli)-3.382 F -.15(ve)-.25 G .883(ry \ +on initial recipient of a message or on queue runs unless the queued).15 +F(message is selected using one of the -qI/-qR/-qS queue run modi\214er\ +s or an ETRN request.)122 229.2 Q .268 +(Con\214guration \214les prior to le)127 245.4 R -.15(ve)-.25 G 2.768 +(l6a).15 G .268(ssume the `)-2.768 F -1.11(A')-.8 G 2.768(,`)1.11 G .268 +(w', `5', `:', `|', `/', and `@' options on the)-2.768 F +(mailer named \231local\232.)102 257.4 Q .306(The mailer with the speci\ +al name \231error\232 can be used to generate a user error)127 273.6 R +5.306(.T)-.55 G .306(he \(optional\))-5.306 F .324(host \214eld is an e) +102 285.6 R .323(xit status to be returned, and the user \214eld is a m\ +essage 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 297.6 R .891(alues USA)-.25 +F .891(GE, NOUSER, NOHOST)-.4 F 3.391(,U)-.74 G -.35(NA)-3.391 G -1.35 +(VA)-1 G .891(ILABLE, SOFT)1.35 F(-)-.92 E -1.2(WA)102 309.6 S 1.142 +(RE, TEMPF)1.2 F 1.142(AIL, PR)-.74 F -1.88 -.4(OT O)-.4 H 1.142 +(COL, or CONFIG to return the corresponding EX_ e).4 F 1.141 +(xit code, or an)-.15 F .288 +(enhanced error code as described in RFC 1893,)102 321.6 R F3 .288 +(Enhanced Mail System Status Codes.)2.788 F F1 -.15(Fo)5.288 G 2.788(re) +.15 G(xample,)-2.938 E(the entry:)102 333.6 Q +($#error $@ NOHOST $: Host unkno)142 349.8 Q(wn in this domain)-.25 E +.145(on the RHS of a rule will cause the speci\214ed error to be genera\ +ted and the \231Host unkno)102 366 R .145(wn\232 e)-.25 F .145(xit sta-) +-.15 F .491(tus to be returned if the LHS matches.)102 378 R .491 +(This mailer is only functional in rulesets 0, 5, or one of the)5.491 F +(check_* rulesets.)102 390 Q .257 +(The mailer with the special name \231discard\232 causes an)127 406.2 R +2.756(ym)-.15 G .256(ail sent to it to be discarded b)-2.756 F .256 +(ut oth-)-.2 F 1.075(erwise treated as though it were successfully deli) +102 418.2 R -.15(ve)-.25 G 3.575(red. This).15 F 1.075 +(mailer can not be used in ruleset 0,)3.575 F(only in the v)102 430.2 Q +(arious address checking rulesets.)-.25 E .468 +(The mailer named \231local\232)127 446.4 R F3(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 +458.4 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,)-2.75 F .942(\231\ +*\214le*\232, and \231*include*\232 may be de\214ned to tune the deli) +102 470.4 R -.15(ve)-.25 G .942 +(ry of messages to programs, \214les, and).15 F +(:include: lists respecti)102 482.4 Q -.15(ve)-.25 G(ly).15 E 5(.T)-.65 +G(he)-5 E 2.5(yd)-.15 G(ef)-2.5 E(ault to:)-.1 E +(Mprog, P=/bin/sh, F=lsoDq9, T=DNS/RFC822/X-Unix, A=sh \255c $u)142 +498.6 Q +(M*\214le*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE $u)142 +510.6 Q(M*include*, P=/de)142 522.6 Q(v/null, F=su, A=INCLUDE $u)-.25 E +.615(The Sender and Recipient re)127 543 R .615 +(writing sets may either be a simple ruleset id or may be tw)-.25 F +3.116(oi)-.1 G(ds)-3.116 E .576 +(separated by a slash; if so, the \214rst re)102 555 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 567 Q +(Setting an)5 E 2.5(yv)-.15 G(alue zero disables corresponding mailer) +-2.75 E(-speci\214c re)-.2 E(writing.)-.25 E .196 +(The Directory is actually a colon-separated path of directories to try) +127 583.2 R 5.197(.F)-.65 G .197(or e)-5.347 F .197 +(xample, the de\214ni-)-.15 F .104 +(tion \231D=$z:/\232 \214rst tries to e)102 595.2 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)-2.604 F -.25(va)-.2 G .103 +(ilable, it tries to).25 F -.15(exe)102 607.2 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)-3.317 E .368(some shells \(such as)102 619.2 R F3 +(csh)2.868 E F1 2.868(\)r)C .368(efuse to e)-2.868 F -.15(xe)-.15 G .368 +(cute if the).15 F 2.868(yc)-.15 G .367(annot read the home directory) +-2.868 F 5.367(.S)-.65 G .367(ince the queue)-5.367 F +(directory is not normally readable by unpri)102 631.2 Q(vile)-.25 E +(ged users)-.15 E F3(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 647.4 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 .098(option \(q.v)102 659.4 +R 2.598(.\). If)-.65 F(the)2.598 E F0(S)2.598 E F1 .098(mailer \215ag i\ +s also speci\214ed, this user and group will be set as the ef)2.598 F +(fecti)-.25 E .398 -.15(ve u)-.25 H(id).15 E .693 +(and gid for the process.)102 671.4 R .694(This may be gi)5.693 F -.15 +(ve)-.25 G 3.194(na).15 G(s)-3.194 E F3(user:gr)3.194 E(oup)-.45 E F1 +.694(to set both the user and group id; either)3.194 F .127 +(may be an inte)102 683.4 R .127(ger or a symbolic name to be look)-.15 +F .127(ed up in the)-.1 F F3(passwd)2.627 E F1(and)2.627 E F3(gr)2.627 E +(oup)-.45 E F1 .126(\214les respecti)2.626 F -.15(ve)-.25 G(ly).15 E +5.126(.I)-.65 G(f)-5.126 E .782 +(only a symbolic user name is speci\214ed, the group id in the)102 695.4 +R F3(passwd)3.282 E F1 .782(\214le for that user is used as the)3.282 F +(group id.)102 707.4 Q EP +%%Page: 47 43 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-47)195.86 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 .465 +(in the Content-T)102 108 R .465(ype: header)-.8 F 5.465(.I)-.55 G 2.965 +(ft)-5.465 G .465(his is not set, the)-2.965 F F0(DefaultCharset)2.966 E +F1 .466(option is used, and if that is not)2.966 F .258(set, the v)102 +120 R .258(alue \231unkno)-.25 F .258(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.757(sm)-.55 G(ailer) +-2.757 E 2.757(,n)-.4 G .257(ot the)-2.757 F(recipient')102 132 Q 2.701 +(sm)-.55 G(ailer)-2.701 E 5.201(.F)-.55 G .201(or e)-5.351 F .201 +(xample, if the en)-.15 F -.15(ve)-.4 G .202 +(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)-2.5 E(xternal netw)-.15 E(ork mailer)-.1 E(.)-.55 E +.794(The T)127 172.2 R .795(ype= \214eld sets the type information used\ + in MIME error messages as de\214ned by RFC)-.8 F 2.805(1894. It)102 +184.2 R .305(is actually three v)2.805 F .305 +(alues separated by slashes: the MT)-.25 F .305 +(A-type \(that is, the description of ho)-.93 F(w)-.25 E .083(hosts are\ + named\), the address type \(the description of e-mail addresses\), and\ + the diagnostic type \(the)102 196.2 R .143 +(description of error diagnostic codes\).)102 208.2 R .143 +(Each of these must be a re)5.143 F .142(gistered v)-.15 F .142 +(alue or be)-.25 F .142(gin with \231X\255\232.)-.15 F(The def)102 220.2 +Q(ault is \231dns/rfc822/smtp\232.)-.1 E 1.175(The m= \214eld speci\214\ +es the maximum number of messages to attempt to deli)127 236.4 R -.15 +(ve)-.25 G 3.675(ro).15 G 3.675(nas)-3.675 G(ingle)-3.675 E +(SMTP or LMTP connection.)102 248.4 Q 1.052 +(The /= \214eld speci\214es a ne)127 264.6 R 3.552(wr)-.25 G 1.052 +(oot directory for the mailer)-3.552 F 6.052(.T)-.55 G 1.052 +(he path is macro e)-6.052 F 1.051(xpanded and)-.15 F .512 +(then passed to the \231chroot\232 system call.)102 276.6 R .512 +(The root directory is changed before the Directory \214eld is)5.512 F +(consulted or the uid is changed.)102 288.6 Q .561(The W)127 304.8 R +.561(ait= \214eld speci\214es the maximum time to w)-.8 F .56 +(ait for the mailer to return after sending all)-.1 F(data to it.)102 +316.8 Q(This applies to mailers that ha)5 E .3 -.15(ve b)-.2 H(een fork) +.15 E(ed by)-.1 E/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1(.)A F0 2.5 +(5.5. H)87 340.8 R 2.5<8a44>2.5 G(e\214ne Header)-2.5 E F1 1.135 +(The format of the header lines that)127 357 R F2(sendmail)3.636 E F1 +1.136(inserts into the message are de\214ned by the)3.636 F F0(H)3.636 E +F1 2.5(line. The)102 369 R(syntax of this line is one of the follo)2.5 E +(wing:)-.25 E F0(H)142 385.2 Q F2(hname)A F0(:)A F2(htemplate)2.5 E F0 +(H)142 405.6 Q F1([)A F0(?)A F2(m\215a)A(gs)-.1 E F0(?])A F2(hname)A F0 +(:)A F2(htemplate)2.5 E F0(H)142 426 Q F1([)A F0(?)A F2(${macr)A(o})-.45 +E F0(?])A F2(hname)A F0(:)A F2(htemplate)2.5 E F1 1.058(Continuation li\ +nes in this spec are re\215ected directly into the outgoing message.)102 +442.2 R(The)6.058 E F2(htemplate)3.557 E F1(is)3.557 E(macro-e)102 454.2 +Q 1.12(xpanded before insertion into the message.)-.15 F 1.12(If the) +6.12 F F2(m\215a)3.62 E(gs)-.1 E F1 1.12 +(\(surrounded by question marks\))3.62 F .161(are speci\214ed, at least\ + one of the speci\214ed \215ags must be stated in the mailer de\214niti\ +on for this header)102 466.2 R .857(to be automatically output.)102 +478.2 R .858(If a)5.858 F F2(${macr)3.358 E(o})-.45 E F1 .858 +(\(surrounded by question marks\) is speci\214ed, the header)3.358 F +1.264(will be automatically output if the macro is set.)102 490.2 R +1.264(The macro may be set using an)6.264 F 3.764(yo)-.15 G 3.763(ft) +-3.764 G 1.263(he normal)-3.763 F .232(methods, including using the)102 +502.2 R F0(macr)2.732 E(o)-.18 E F1 .232(storage map in a ruleset.)2.732 +F .232(If one of these headers is in the input)5.232 F +(it is re\215ected to the output re)102 514.2 Q -.05(ga)-.15 G +(rdless of these \215ags or macros.).05 E(Some headers ha)127 530.4 Q .3 +-.15(ve s)-.2 H(pecial semantics that will be described later).15 E(.) +-.55 E 2.711(As)127 546.6 S .211(econdary syntax allo)-2.711 F .211 +(ws v)-.25 F .211(alidation of headers as the)-.25 F 2.711(ya)-.15 G +.211(re being read.)-2.711 F 1.81 -.8(To e)5.21 H .21(nable v).8 F +(alidation,)-.25 E(use:)102 558.6 Q F0(H)142 574.8 Q F2(Header)A F0 2.5 +(:$)C(>)-2.5 E F2(Ruleset)A F0(H)142 586.8 Q F2(Header)A F0 2.5(:$)C(>+) +-2.5 E F2(Ruleset)A F1 .715(The indicated)102 603 R F2(Ruleset)3.215 E +F1 .715(is called for the speci\214ed)3.215 F F2(Header)3.216 E F1 3.216 +(,a)C .716(nd can return)-3.216 F F0($#err)3.216 E(or)-.18 E F1 .716 +(to reject the mes-)3.216 F 1.972(sage or)102 615 R F0($#discard)4.472 E +F1 1.971(to discard the message \(as with the other)4.472 F F0(check_) +4.471 E F1 4.471(*r)C 4.471(ulesets\). The)-4.471 F 1.971(header is) +4.471 F .249(treated as a structured \214eld, that is, comments \(in pa\ +rentheses\) are deleted before processing, unless)102 627 R +(the second form)102 639 Q F0($>+)2.5 E F1(is used.)2.5 E -.15(Fo)127 +655.2 S 2.5(re).15 G(xample, the con\214guration lines:)-2.65 E EP +%%Page: 48 44 +%%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 +(HMessage-Id: $>CheckMessageId)142 96 Q(SCheckMessageId)142 120 Q +(R< $+ @ $+)142 132 Q 11.06(>$)5 G 2.5(@O)-11.06 G(K)-2.5 E 52.83 +(R$* $#error)142 144 R($: Ille)2.5 E -.05(ga)-.15 G 2.5(lM).05 G +(essage-Id header)-2.5 E -.1(wo)102 160.2 S(uld refuse an).1 E 2.5(ym) +-.15 G(essage that had a Message-Id: header of an)-2.5 E 2.5(yo)-.15 G +2.5(ft)-2.5 G(he follo)-2.5 E(wing forms:)-.25 E(Message-Id: <>)142 +176.4 Q(Message-Id: some te)142 188.4 Q(xt)-.15 E(Message-Id: e).15 E +(xtra crud)-.15 E 3.069(Ad)102 216.6 S(ef)-3.069 E .569 +(ault ruleset that is called for headers which don')-.1 F 3.069(th)-.18 +G -2.25 -.2(av e)-3.069 H 3.069(as)3.269 G .568 +(peci\214c ruleset de\214ned for them can)-3.069 F(be speci\214ed by:) +102 228.6 Q F0(H)142 244.8 Q/F2 10/Times-Italic@0 SF(*)A F0 2.5(:$)C(>) +-2.5 E F2(Ruleset)A F1(or)102 261 Q F0(H)142 277.2 Q F2(*)A F0 2.5(:$)C +(>+)-2.5 E F2(Ruleset)A F0 2.5(5.6. O)87 305.4 R 2.5<8a53>2.5 G +(et Option)-2.5 E F1 .962(There are a number of global options that can\ + be set from a con\214guration \214le.)127 321.6 R .963(Options are) +5.963 F .86(represented by full w)102 333.6 R .86(ords; some are also r\ +epresentable as single characters for back compatibility)-.1 F(.)-.65 E +(The syntax of this line is:)102 345.6 Q F0(O)142 361.8 Q F2(option)7.5 +E F0(=)A F2(value)A F1 .562(This sets option)102 378 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)-5.562 F F2(must)3.062 E F1 .562 +(be a space between the letter `O' and the)3.062 F(name of the option.) +102 390 Q(An older v)5 E(ersion is:)-.15 E F0(O)142 406.2 Q F2 1.666(ov) +C(alue)-1.666 E F1 .13(where the option)102 422.4 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,)-5.13 F 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 434.4 S +(oolean \(with le)-2.5 E -.05(ga)-.15 G 2.5(lv).05 G +(alues \231t\232, \231T\232, \231f\232, or \231F\232; the def)-2.75 E +(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 +450.6 Q(ets\) are:)-.1 E(AliasFile=)102 466.8 Q F2(spec, spec, ...)A F1 +.439([A] Specify possible alias \214le\(s\).)174 478.8 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 490.8 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 502.8 R .187(alid\ + classes are \231implicit\232 \(search through a compiled-in list of al\ +ias)-.25 F 2.055 +(\214le types, for back compatibility\), \231hash\232 \(if)174 514.8 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 526.8 Q F1 1.588 +(is speci\214ed\), \231stab\232 \(internal symbol table \212 not normal\ +ly used unless)4.088 F .075(you ha)174 538.8 R .375 -.15(ve n)-.2 H +2.575(oo).15 G .075(ther database lookup\), or \231nis\232 \(if)-2.575 F +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 550.8 Q(vided,)-.15 E F2(sendmail) +2.5 E F1(searches them in order)2.5 E(.)-.55 E(AliasW)102 567 Q(ait=)-.8 +E F2(timeout)A F1 .14([a] If set, w)174 579 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 591 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 603 S 3.21(lr).25 G(eb)-3.21 E .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 615 S(rning.).1 E(Allo)102 631.2 Q(wBogusHELO)-.25 E 1.104 +([no short name] If set, allo)174 643.2 R 3.604(wH)-.25 G 1.104 +(ELO SMTP commands that don')-3.604 F 3.604(ti)-.18 G 1.103 +(nclude a host)-3.604 F 2.881(name. Setting)174 655.2 R .382 +(this violates RFC 1123 section 5.2.5, b)2.881 F .382 +(ut is necessary to interoper)-.2 F(-)-.2 E .061(ate with se)174 667.2 R +-.15(ve)-.25 G .061(ral SMTP clients.).15 F .061(If there is a v)5.061 F +.06(alue, it is still check)-.25 F .06(ed for le)-.1 F(gitimac)-.15 E +-.65(y.)-.15 G -1.05(AuthMechanisms [no)102 683.4 R 2.672 +(short name] List of authentication mechanisms for A)5.172 F 2.672 +(UTH \(separated by)-.55 F 2.853(spaces\). The)174 695.4 R(adv)2.853 E +.353(ertised list of authentication mechanisms will be the intersection) +-.15 F .271(of this list and the list of a)174 707.4 R -.25(va)-.2 G +.272(ilable mechanisms as determined by the Cyrus SASL).25 F(library)174 +719.4 Q(.)-.65 E EP +%%Page: 49 45 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-49)195.86 E/F1 10/Times-Roman@0 SF 17.83(AuthOptions [no)102 96 +R .863(short name] When to use the A)3.363 F .862 +(UTH= parameter for the MAIL FR)-.55 F .862(OM com-)-.4 F(mand;)174 108 +Q 2.5(AO)214 124.2 S(nly when authentication succeeded.)-2.5 E(The def) +174 140.4 Q(ault is to try whene)-.1 E -.15(ve)-.25 G 2.5(rS).15 G +(MTP A)-2.5 E(UTH is a)-.55 E -.25(va)-.2 G(ilable.).25 E(AutoReb)102 +156.6 Q(uildAliases)-.2 E 1.061([D] If set, reb)174 168.6 R 1.062 +(uild the alias database if necessary and possible.)-.2 F 1.062(The reb) +6.062 F 1.062(uild will)-.2 F .381(happen the ne)174 180.6 R .381 +(xt time an alias is look)-.15 F .381(ed up.)-.1 F .38 +(If this option is not set,)5.381 F/F2 10/Times-Italic@0 SF(sendmail) +2.88 E F1(will)2.88 E(ne)174 192.6 Q -.15(ve)-.25 G 4.27(rr).15 G(eb) +-4.27 E 1.77(uild the alias database unless e)-.2 F 1.77 +(xplicitly requested using)-.15 F F0(\255bi)4.27 E F1(.)A F0(NO)6.77 E +(TE)-.4 E F1(:)A .346 +(There is a potential for a denial of service attack if this is set.)174 +204.6 R .345(This option is dep-)5.346 F(recated and will be remo)174 +216.6 Q -.15(ve)-.15 G 2.5(df).15 G(rom a future v)-2.5 E(ersion.)-.15 E +(BlankSub=)102 232.8 Q F2(c)A F1 1.255 +([B] Set the blank substitution character to)22.47 F F2(c)3.755 E F1 +6.255(.U)C 1.255(nquoted spaces in addresses are)-6.255 F +(replaced by this character)174 244.8 Q 5(.D)-.55 G(ef)-5 E +(aults to space \(i.e., no change is made\).)-.1 E 14.51 +(CheckAliases [n])102 261 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 277.2 Q(al=)-.25 E F2(N)A F1 1.297 +([C] Checkpoints the queue e)174 289.2 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.296 +(If your system)6.296 F .746(crashes during deli)174 301.2 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.247(yb)-.15 G .747(ut the)-3.447 +F(last recipients.)174 313.2 Q(ClassF)102 329.4 Q(actor=)-.15 E F2(fact) +A F1 1.625([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 .718 +(Precedence: \214eld in the user header and the)174 341.4 R F0(P)3.219 E +F1 .719(lines in the con\214guration \214le\) and)3.219 F 2.638 +(subtracted from the priority)174 353.4 R 7.637(.T)-.65 G 2.637 +(hus, messages with a higher Priority: will be)-7.637 F -.1(fa)174 365.4 +S -.2(vo)-.1 G 2.5(red. Def).2 F(aults to 1800.)-.1 E +(ClientPortOptions=)102 381.6 Q F2(options)A F1 .355 +([O] Set client SMTP options.)174 393.6 R .355(The options are)5.355 F +F2 -.1(ke)2.855 G(y=value)-.2 E F1 .355(pairs separated by com-)2.855 F +2.5(mas. Kno)174 405.6 R(wn k)-.25 E -.15(ey)-.1 G 2.5(sa).15 G(re:)-2.5 +E 52.83(Port Name/number)214 421.8 R +(of source port for connection \(def)2.5 E(aults to an)-.1 E 2.5(yf)-.15 +G(ree port\))-2.5 E 48.95(Addr Address)214 433.8 R(mask \(def)2.5 E +(aults IN)-.1 E(ADDR_ANY\))-.35 E -.15(Fa)214 445.8 S 41.31 +(mily Address).15 F -.1(fa)2.5 G(mily \(def).1 E(aults to INET\))-.1 E +21.72(SndBufSize Size)214 457.8 R(of TCP send b)2.5 E(uf)-.2 E(fer)-.25 +E 21.17(RcvBufSize Size)214 469.8 R(of TCP recei)2.5 E .3 -.15(ve b)-.25 +H(uf)-.05 E(fer)-.25 E 34.5(Modi\214er Options)214 481.8 R +(\(\215ags\) for the daemon)2.5 E(The)174 498 Q F2(Addr)3.166 E F1 .666 +(ess mask may be a numeric address in dot notation or a netw)B .665 +(ork name.)-.1 F F2(Modi\214er)174 510 Q F1(can be the follo)2.5 E +(wing character:)-.25 E 67(hu)214 526.2 S(se name of interf)-67 E +(ace for HELO command)-.1 E .763(If `)174 542.4 R(`h')-.74 E 3.263('i) +-.74 G 3.263(ss)-3.263 G .763 +(et, the name corresponding to the outgoing interf)-3.263 F .764 +(ace address \(whether)-.1 F .431 +(chosen via the Connection parameter or the def)174 554.4 R .431 +(ault\) is used for the HELO/EHLO)-.1 F(command.)174 566.4 Q 3.95 +(ColonOkInAddr [no)102 582.6 R 4.679 +(short name] If set, colons are acceptable in e-mail addresses \(e.g.,) +7.179 F 3.54(\231host:user\232\). If)174 594.6 R 1.04 +(not set, colons indicate the be)3.54 F 1.04 +(ginning of a RFC 822 group con-)-.15 F 1.987 +(struct \(\231groupname: member1, member2, ... memberN;\232\).)174 606.6 +R 1.988(Doubled colons are)6.988 F(al)174 618.6 Q -.1(wa)-.1 G 2.215(ys\ + acceptable \(\231nodename::user\232\) and proper route-addr nesting is\ + under).1 F(-)-.2 E 1.036(stood \(\231<@relay:user@host>\232\).)174 +630.6 R 1.037(Furthermore, this option def)6.036 F 1.037 +(aults on if the con-)-.1 F .854(\214guration v)174 642.6 R .854 +(ersion le)-.15 F -.15(ve)-.25 G 3.354(li).15 G 3.354(sl)-3.354 G .853 +(ess than 6 \(for back compatibility\).)-3.354 F(Ho)5.853 E(we)-.25 E +-.15(ve)-.25 G 1.653 -.4(r, i).15 H 3.353(tm).4 G(ust)-3.353 E(be of)174 +654.6 Q 2.5(ff)-.25 G(or full compatibility with RFC 822.)-2.5 E +(ConnectionCacheSize=)102 670.8 Q F2(N)A F1 .242([k] The maximum number\ + of open connections that will be cached at a time.)174 682.8 R(The) +5.243 E(def)174 694.8 Q .386(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.191(tion of)174 706.8 R F2(sendmail)3.691 E F1 +1.191(needs to connect to another host or it terminates.)3.691 F 1.192 +(Setting it to)6.192 F 2.047(zero def)174 718.8 R 2.047 +(aults to the old beha)-.1 F(vior)-.2 E 4.546(,t)-.4 G 2.046 +(hat is, connections are closed immediately)-4.546 F(.)-.65 E EP +%%Page: 50 46 +%%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 .266(Sin\ +ce this consumes \214le descriptors, the connection cache should be k) +174 96 R .266(ept small: 4)-.1 F(is probably a practical maximum.)174 +108 Q(ConnectionCacheT)102 124.2 Q(imeout=)-.35 E/F2 10/Times-Italic@0 +SF(timeout)A F1 .708([K] The maximum amount of time a cached connection\ + will be permitted to idle)174 136.2 R 1.082(without acti)174 148.2 R +(vity)-.25 E 6.082(.I)-.65 G 3.582(ft)-6.082 G 1.083(his time is e) +-3.582 F 1.083(xceeded, the connection is immediately closed.)-.15 F +.418(This v)174 160.2 R .418 +(alue should be small \(on the order of ten minutes\).)-.25 F(Before) +5.418 E F2(sendmail)2.918 E F1 .417(uses a)2.917 F .507 +(cached connection, it al)174 172.2 R -.1(wa)-.1 G .508 +(ys sends a RSET command to check the connection; if).1 F .402(this f) +174 184.2 R .402(ails, it reopens the connection.)-.1 F .401(This k) +5.402 F .401(eeps your end from f)-.1 F .401(ailing if the other)-.1 F +1.544(end times out.)174 196.2 R 1.545 +(The point of this option is to be a good netw)6.544 F 1.545 +(ork neighbor and)-.1 F -.2(avo)174 208.2 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.)-2.5 E(ConnectOnlyT)102 224.4 +Q(o=)-.8 E F2(addr)A(ess)-.37 E F1 .862 +([no short name] This can be used to o)174 236.4 R -.15(ve)-.15 G .861 +(rride the connection address \(for testing).15 F(purposes\).)174 248.4 +Q(ConnectionRateThrottle=)102 264.6 Q F2(N)A F1 .21 +([no short name] If set to a positi)174 276.6 R .511 -.15(ve v)-.25 H +.211(alue, allo)-.1 F 2.711(wn)-.25 G 2.711(om)-2.711 G .211(ore than) +-2.711 F F2(N)2.711 E F1 .211(incoming daemon)2.711 F 1.776 +(connections in a one second period.)174 288.6 R 1.776 +(This is intended to \215atten out peaks and)6.776 F(allo)174 300.6 Q +2.5(wt)-.25 G(he load a)-2.5 E -.15(ve)-.2 G(rage checking to cut in.) +.15 E(Def)5 E(aults to zero \(no limits\).)-.1 E(ControlSock)102 316.8 Q +(etName=)-.1 E F2(name)A F1 .476 +([no short name] Name of the control sock)174 328.8 R .477 +(et for daemon management.)-.1 F 2.977(Ar)5.477 G(unning)-2.977 E F2 +(sendmail)174 340.8 Q F1 1.225 +(daemon can be controlled through this named sock)3.725 F 3.725(et. A) +-.1 F -.25(va)-.74 G 1.225(ilable com-).25 F .994(mands are:)174 352.8 R +F2 .994(help, r)3.494 F .994(estart, shutdown,)-.37 F F1(and)3.494 E F2 +(status.)3.495 E F1(The)5.995 E F2(status)3.495 E F1 .995 +(command returns the)3.495 F 1.228(current number of daemon children, t\ +he maximum number of daemon children,)174 364.8 R .517 +(the free disk space \(in blocks\) of the queue directory)174 376.8 R +3.017(,a)-.65 G .518(nd the load a)-3.017 F -.15(ve)-.2 G .518 +(rage of the).15 F 1.117(machine e)174 388.8 R 1.117 +(xpressed as an inte)-.15 F(ger)-.15 E 6.117(.I)-.55 G 3.617(fn)-6.117 G +1.117(ot set, no control sock)-3.617 F 1.117(et will be a)-.1 F -.25(va) +-.2 G(ilable.).25 E(Solaris and pre-4.4BSD k)174 400.8 Q +(ernel users should see the note in sendmail/README .)-.1 E +(DaemonPortOptions=)102 417 Q F2(options)A F1([O] Set serv)174 429 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:) +-2.5 E 45.62(Name User)214 445.2 R +(-de\214nable name for the daemon \(def)-.2 E(aults to "Daemon#"\))-.1 E +52.83(Port Name/number)214 457.2 R(of listening port \(def)2.5 E +(aults to "smtp"\))-.1 E 48.95(Addr Address)214 469.2 R(mask \(def)2.5 E +(aults IN)-.1 E(ADDR_ANY\))-.35 E -.15(Fa)214 481.2 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 493.2 R(of listen queue \(def)2.5 E(aults to 10\)) +-.1 E 34.5(Modi\214er Options)214 505.2 R(\(\215ags\) for the daemon)2.5 +E 21.72(SndBufSize Size)214 517.2 R(of TCP send b)2.5 E(uf)-.2 E(fer) +-.25 E 21.17(RcvBufSize Size)214 529.2 R(of TCP recei)2.5 E .3 -.15 +(ve b)-.25 H(uf)-.05 E(fer)-.25 E(The)174 545.4 Q F2(Name)3.336 E F1 +.837(\214eld is used for error messages and logging.)3.337 F(The)5.837 E +F2(Addr)3.337 E F1 .837(ess mask may)B 2.194 +(be a numeric address in dot notation or a netw)174 557.4 R 2.194 +(ork name.)-.1 F F2(Modi\214er)7.194 E F1 2.194(can be a)4.694 F +(sequence \(without an)174 569.4 Q 2.5(yd)-.15 G +(elimiters\) of the follo)-2.5 E(wing characters:)-.25 E 67.56(ar)214 +585.6 S(equire authentication)-67.56 E 67(bb)214 597.6 S(ind to interf) +-67 E(ace through which mail has been recei)-.1 E -.15(ve)-.25 G(d).15 E +67.56(cp)214 609.6 S(erform hostname canoni\214cation \(.cf\))-67.56 E +68.67(fr)214 621.6 S(equire fully quali\214ed hostname \(.cf\))-68.67 E +67(ua)214 633.6 S(llo)-67 E 2.5(wu)-.25 G +(nquali\214ed addresses \(.cf\))-2.5 E 65.33(Cd)214 645.6 S(on')-65.33 E +2.5(tp)-.18 G(erform hostname canoni\214cation)-2.5 E 65.89(Ed)214 657.6 +S(isallo)-65.89 E 2.5(wE)-.25 G(TRN \(see RFC 2476\))-2.5 E 2.025 +(That is, one w)174 673.8 R 2.026 +(ay to specify a message submission agent \(MSA\) that requires)-.1 F +(authentication is:)174 685.8 Q 2.5(OD)214 702 S +(aemonPortOptions=Name=MSA, Port=587, M=Ea)-2.5 E 2.834 +(The modi\214ers that are mark)174 718.2 R 2.833(ed with "\(.cf\)" ha) +-.1 F 3.133 -.15(ve o)-.2 H 2.833(nly ef).15 F 2.833 +(fect in the standard)-.25 F EP +%%Page: 51 47 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-51)195.86 E/F1 10/Times-Roman@0 SF 1.636 +(con\214guration \214le, in which the)174 96 R 4.136(ya)-.15 G 1.636 +(re a)-4.136 F -.25(va)-.2 G 1.636(ilable via).25 F F0 +(${daemon_\215ags})4.136 E F1 6.636(.T)C 1.636(he \215ags)-6.636 F -.74 +(``)174 108 S(c').74 E 4.198('a)-.74 G 1.698(nd `)-4.198 F(`C')-.74 E +4.198('c)-.74 G 1.698(an change the def)-4.198 F 1.697 +(ault for hostname canoni\214cation in the)-.1 F/F2 10/Times-Italic@0 SF +(send-)4.197 E(mail.cf)174 120 Q F1 2.758(\214le. See)2.758 F .258 +(the rele)2.758 F -.25(va)-.25 G .258(nt documentation for).25 F/F3 9 +/Times-Roman@0 SF(FEA)2.758 E(TURE\(nocanonify\))-.999 E F1 5.259(.T)C +.259(he modi-)-5.259 F 1.68(\214er `)174 132 R -1.95(`f ')-.74 F 4.179 +('d)-.74 G(isallo)-4.179 E 1.679(ws addresses of the form)-.25 F F0 +(user@host)4.179 E F1 1.679(unless the)4.179 F 4.179(ya)-.15 G 1.679 +(re submitted)-4.179 F(directly)174 144 Q 5.505(.T)-.65 G .505 +(he \215ag `)-5.505 F(`u')-.74 E 3.005('a)-.74 G(llo)-3.005 E .505 +(ws unquali\214ed sender addresses.)-.25 F -.74(``)5.505 G(b').74 E +3.005('f)-.74 G .505(orces sendmail)-3.005 F .398(to bind to the interf) +174 156 R .398(ace through which the e-mail has been recei)-.1 F -.15 +(ve)-.25 G 2.898(df).15 G .397(or the outgo-)-2.898 F 2.697 +(ing connection.)174 168 R F0 -1.2(WA)7.697 G(RNING:)1.2 E F1 2.697 +(Use `)5.197 F(`b')-.74 E 5.197('o)-.74 G 2.697 +(nly if outgoing mail can be routed)-5.197 F .163 +(through the incoming connection')174 180 R 2.663(si)-.55 G(nterf)-2.663 +E .163(ace to its destination. No attempt is made)-.1 F .502 +(to catch problems due to a miscon\214guration of this parameter)174 192 +R 3.002(,u)-.4 G .502(se it only for vir)-3.002 F(-)-.2 E 1.113 +(tual hosting where each virtual interf)174 204 R 1.113 +(ace can connect to e)-.1 F -.15(ve)-.25 G 1.112(ry possible location.) +.15 F .859(This will also o)174 216 R -.15(ve)-.15 G .859 +(rride possible settings via).15 F F0(ClientP)3.359 E(ortOptions.)-.2 E +F1(Note,)5.859 E F2(sendmail)3.359 E F1 .636(will listen on a ne)174 228 +R 3.136(ws)-.25 G(ock)-3.136 E .636 +(et for each occurence of the DaemonPortOptions option)-.1 F +(in a con\214guration \214le.)174 240 Q(Def)102 256.2 Q 2.95 +(aultAuthInfo [no)-.1 F .181(short name] Filename that contains def) +2.681 F .181(ault authentication information for out-)-.1 F 1.738(going\ + connections. This \214le must contain the user id, the authorization i\ +d, the)174 268.2 R(passw)174 280.2 Q .28(ord \(plain te)-.1 F .281 +(xt\), and the realm to use on separate lines and must be readable)-.15 +F(by root \(or the trusted user\) only)174 292.2 Q 5(.I)-.65 G 2.5(fn)-5 +G 2.5(or)-2.5 G(ealm is speci\214ed,)-2.5 E F0($j)2.5 E F1(is used.)2.5 +E(Def)102 308.4 Q(aultCharSet=)-.1 E F2 -.15(ch)C(ar).15 E(set)-.1 E F1 +.161([no short name] When a message that has 8-bit characters b)174 +320.4 R .16(ut is not in MIME for)-.2 F(-)-.2 E .494(mat is con)174 +332.4 R -.15(ve)-.4 G .495 +(rted to MIME \(see the EightBitMode option\) a character set must be) +.15 F .488(included in the Content-T)174 344.4 R .488(ype: header)-.8 F +5.488(.T)-.55 G .487(his character set is normally set from the)-5.488 F +.133(Charset= \214eld of the mailer descriptor)174 356.4 R 5.133(.I)-.55 +G 2.633(ft)-5.133 G .133(hat is not set, the v)-2.633 F .133 +(alue of this option is)-.25 F 2.5(used. If)174 368.4 R +(this option is not set, the v)2.5 E(alue \231unkno)-.25 E +(wn-8bit\232 is used.)-.25 E(DataFileBuf)102 384.6 Q(ferSize=)-.25 E F2 +(thr)A(eshold)-.37 E F1 .012([no short name] Set the)174 396.6 R F2(thr) +2.512 E(eshold)-.37 E F1 2.512(,i)C 2.512(nb)-2.512 G .011 +(ytes, before a memory-based queue data \214le)-2.512 F +(becomes disk-based.)174 408.6 Q(The def)5 E(ault is 4096 bytes.)-.1 E +(DeadLetterDrop=)102 424.8 Q F2(\214le)A F1 .535([no short name] De\214\ +nes the location of the system-wide dead.letter \214le, formerly)174 +436.8 R .744(hardcoded to /usr/tmp/dead.letter)174 448.8 R 5.744(.I)-.55 +G 3.244(ft)-5.744 G .744(his option is not set \(the def)-3.244 F .743 +(ault\), sendmail)-.1 F 1.2(will not attempt to sa)174 460.8 R 1.5 -.15 +(ve t)-.2 H 3.7(oas).15 G 1.2(ystem-wide dead.letter \214le in the e) +-3.7 F -.15(ve)-.25 G 1.2(nt it can not).15 F .575 +(bounce the mail to the user or postmaster)174 472.8 R 5.575(.I)-.55 G +.575(nstead, it will rename the qf \214le as it)-5.575 F +(has in the past when the dead.letter \214le could not be opened.)174 +484.8 Q(Def)102 501 Q(aultUser=)-.1 E F2(user:gr)A(oup)-.45 E F1 .013 +([u] Set the def)174 513 R .013(ault userid for mailers to)-.1 F F2 +(user:gr)2.513 E(oup)-.45 E F1 5.013(.I)C(f)-5.013 E 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 525 S 1.807 +(ser name \(as opposed to a numeric user id\) the def)-4.307 F 1.806 +(ault group listed in the)-.1 F 1.153 +(/etc/passwd \214le for that user is used as the def)174 537 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 549 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 563 R 5.142(.D)-.55 G(ef)-5.142 E .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)-2.642 G .142(ymbolic user name.)-2.642 F/F4 7 +/Times-Roman@0 SF(20)-4 I F1(Deli)102 579.2 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)-2.5 G(ode) +-2.5 E F2(x)2.5 E F1 5(.L)C -2.25 -.15(eg a)-5 H 2.5(lm).15 G(odes are:) +-2.5 E 17.22(iD)214 595.4 S(eli)-17.22 E -.15(ve)-.25 G 2.5(ri).15 G +(nteracti)-2.5 E -.15(ve)-.25 G(ly \(synchronously\)).15 E 15(bD)214 +607.4 S(eli)-15 E -.15(ve)-.25 G 2.5(ri).15 G 2.5(nb)-2.5 G +(ackground \(asynchronously\))-2.5 E 15(qJ)214 619.4 S +(ust queue the message \(deli)-15 E -.15(ve)-.25 G 2.5(rd).15 G +(uring queue run\))-2.5 E 15(dD)214 631.4 S(efer deli)-15 E -.15(ve)-.25 +G(ry and all map lookups \(deli).15 E -.15(ve)-.25 G 2.5(rd).15 G +(uring queue run\))-2.5 E(Def)174 647.6 Q .712(aults to `)-.1 F(`b')-.74 +E 3.212('i)-.74 G 3.212(fn)-3.212 G 3.211(oo)-3.212 G .711 +(ption is speci\214ed, `)-3.211 F(`i')-.74 E 3.211('i)-.74 G 3.211(fi) +-3.211 G 3.211(ti)-3.211 G 3.211(ss)-3.211 G .711(peci\214ed b)-3.211 F +.711(ut gi)-.2 F -.15(ve)-.25 G 3.211(nn).15 G 3.211(oa)-3.211 G -.18 +(rg)-3.211 G(u-).18 E .094(ment \(i.e., `)174 659.6 R(`Od')-.74 E 2.594 +('i)-.74 G 2.594(se)-2.594 G(qui)-2.594 E -.25(va)-.25 G .094(lent to `) +.25 F(`Odi')-.74 E 2.594('\). The)-.74 F F02.594 E F1 .094 +(command line \215ag sets this to)2.594 F F0(i)2.594 E F1(.)A .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/F5 5/Times-Roman@0 SF(20)93.6 +689.2 Q/F6 8/Times-Roman@0 SF(The old)3.2 I/F7 8/Times-Bold@0 SF(g)2 E +F6(option has been combined into the)2 E F7(DefaultUser)2 E F6(option.)2 +E EP +%%Page: 52 48 +%%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 +(DialDelay=)102 96 Q/F2 10/Times-Italic@0 SF(sleeptime)A F1 .799 +([no short name] Dial-on-demand netw)174 108 R .798 +(ork connections can see timeouts if a con-)-.1 F .665 +(nection is opened before the call is set up.)174 120 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 132 R +F2(sendmail)3.242 E F1 .742(will sleep for)3.242 F .31 +(this amount of time and try ag)174 144 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 156 R(vider)-.15 E +6.543(.U)-.55 G 1.543(nits def)-6.543 F 1.542 +(ault to seconds, so \231DialDe-)-.1 F(lay=5\232 uses a \214v)174 168 Q +2.5(es)-.15 G(econd delay)-2.5 E 5(.D)-.65 G(ef)-5 E +(aults to zero \(no retry\).)-.1 E(DontBlameSendmail=)102 184.2 Q F2 +(option,option,...)A F1 .064([no short name] In order to a)174 196.2 R +-.2(vo)-.2 G .065(id possible cracking attempts caused by w).2 F .065 +(orld- and)-.1 F .255(group-writable \214les and directories,)174 208.2 +R F2(sendmail)2.755 E F1 .254(does paranoid checking when open-)2.754 F +.297(ing most of its support \214les.)174 220.2 R .298 +(If for some reason you absolutely must run with, for)5.297 F -.15(ex) +174 232.2 S .177(ample, a group-writable).15 F F2(/etc)2.677 E F1 +(directory)2.677 E 2.677(,t)-.65 G .177(hen you will ha)-2.677 F .477 +-.15(ve t)-.2 H 2.677(ot).15 G .177(urn of)-2.677 F 2.677(ft)-.25 G .176 +(his check-)-2.677 F .125 +(ing \(at the cost of making your system more vulnerable to attack\).) +174 244.2 R .125(The ar)5.125 F(guments)-.18 E(are indi)174 256.2 Q +(vidual options that turn of)-.25 E 2.5(fc)-.25 G(hecking:)-2.5 E(Safe) +214 272.4 Q(AssumeSafeCho)214 284.4 Q(wn)-.25 E(ClassFileInUnsafeDirP) +214 296.4 Q(ath)-.15 E(DontW)214 308.4 Q(arnF)-.8 E(orw)-.15 E +(ardFileInUnsafeDirP)-.1 E(ath)-.15 E(ErrorHeaderInUnsafeDirP)214 320.4 +Q(ath)-.15 E(FileDeli)214 332.4 Q -.15(ve)-.25 G(ryT).15 E(oHardLink)-.8 +E(FileDeli)214 344.4 Q -.15(ve)-.25 G(ryT).15 E(oSymLink)-.8 E -.15(Fo) +214 356.4 S(rw).15 E(ardFileInUnsafeDirP)-.1 E(ath)-.15 E -.15(Fo)214 +368.4 S(rw).15 E(ardFileInUnsafeDirP)-.1 E(athSafe)-.15 E -.15(Fo)214 +380.4 S(rw).15 E(ardFileIngroupWritableDirP)-.1 E(ath)-.15 E +(GroupWritableAliasFile)214 392.4 Q(GroupWritableDirP)214 404.4 Q +(athSafe)-.15 E(GroupWritableF)214 416.4 Q(orw)-.15 E(ardFileSafe)-.1 E +(GroupWritableIncludeFileSafe)214 428.4 Q(HelpFileinUnsafeDirP)214 440.4 +Q(ath)-.15 E(IncludeFileInUnsafeDirP)214 452.4 Q(ath)-.15 E +(IncludeFileInUnsafeDirP)214 464.4 Q(athSafe)-.15 E +(IncludeFileIngroupWritableDirP)214 476.4 Q(ath)-.15 E(Link)214 488.4 Q +(edAliasFileInWritableDir)-.1 E(Link)214 500.4 Q +(edClassFileInWritableDir)-.1 E(Link)214 512.4 Q(edF)-.1 E(orw)-.15 E +(ardFileInWritableDir)-.1 E(Link)214 524.4 Q(edIncludeFileInWritableDir) +-.1 E(Link)214 536.4 Q(edMapInWritableDir)-.1 E(Link)214 548.4 Q +(edServiceSwitchFileInWritableDir)-.1 E(MapInUnsafeDirP)214 560.4 Q(ath) +-.15 E(NonRootSafeAddr)214 572.4 Q(RunProgramInUnsafeDirP)214 584.4 Q +(ath)-.15 E(RunWritableProgram)214 596.4 Q -.35(Tr)214 608.4 S(ustStick) +.35 E(yBit)-.15 E -.8(Wo)214 620.4 S(rldWritableAliasFile).8 E +(WriteMapT)214 632.4 Q(oHardLink)-.8 E(WriteMapT)214 644.4 Q(oSymLink) +-.8 E(WriteStatsT)214 656.4 Q(oHardLink)-.8 E(WriteStatsT)214 668.4 Q +(oSymLink)-.8 E F0(Safe)174 684.6 Q F1 1.224(is the def)3.724 F 3.724 +(ault. The)-.1 F 1.224(details of these \215ags are described abo)3.724 +F -.15(ve)-.15 G(.).15 E F0 1.223(Use of this)6.223 F(option is not r) +174 696.6 Q(ecommended.)-.18 E F1(DontExpandCnames)102 712.8 Q .559([no\ + short name] The standards say that all host addresses used in a mail m\ +essage)174 724.8 R EP +%%Page: 53 49 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-53)195.86 E/F1 10/Times-Roman@0 SF 1.408 +(must be fully canonical.)174 96 R -.15(Fo)6.407 G 3.907(re).15 G 1.407 +(xample, if your host is named \231Cruft.F)-4.057 F(oo.ORG\232)-.15 E +1.462(and also has an alias of \231FTP)174 108 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 120 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 ignore\ +d and the \231wrong\232 thing is done.)174 132 R(Ho)5.662 E(we)-.25 E +-.15(ve)-.25 G -.4(r,).15 G .872(the IETF is mo)174 144 R .872(ving to) +-.15 F -.1(wa)-.25 G .872(rd changing this standard, so the beha).1 F +.871(vior may become)-.2 F 3.009(acceptable. Please)174 156 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 168 Q(we) +-.25 E -.15(ve)-.25 G -.55(r.).15 G 6.17(DontInitGroups [no)102 184.2 R +.25(short name] If set,)2.75 F/F2 10/Times-Italic@0 SF(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(run\ +ning NIS, this causes a sequential scan of the groups.byname map, which\ + can)174 196.2 R .436(cause your NIS serv)174 208.2 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 +220.2 R(passw)174 232.2 Q 1.189(ord \214le\), which will mak)-.1 F 3.689 +<658c>-.1 G 1.189(le access permissions some)-3.689 F 1.189 +(what more restric-)-.25 F(ti)174 244.2 Q -.15(ve)-.25 G 5(.H).15 G +(as no ef)-5 E(fect on systems that don')-.25 E 2.5(th)-.18 G -2.25 -.2 +(av e)-2.5 H(group lists.)2.7 E(DontProbeInterf)102 260.4 Q(aces)-.1 E +1.712([no short name])174 272.4 R F2(Sendmail)4.212 E F1 1.713 +(normally \214nds the names of all interf)4.212 F 1.713(aces acti)-.1 F +2.013 -.15(ve o)-.25 H(n).15 E 1.103 +(your machine when it starts up and adds their name to the)174 284.4 R +F0($=w)3.602 E F1 1.102(class of kno)3.602 F(wn)-.25 E 1.835 +(host aliases.)174 296.4 R 1.835(If you ha)6.835 F 2.136 -.15(ve a l)-.2 +H(ar).15 E 1.836(ge number of virtual interf)-.18 F 1.836 +(aces or if your DNS)-.1 F(in)174 308.4 Q -.15(ve)-.4 G .959 +(rse lookups are slo).15 F 3.459(wt)-.25 G .959 +(his can be time consuming.)-3.459 F .958(This option turns of)5.958 F +3.458(ft)-.25 G(hat)-3.458 E 2.973(probing. Ho)174 320.4 R(we)-.25 E +-.15(ve)-.25 G 1.273 -.4(r, y).15 H .474 +(ou will need to be certain to include all v).4 F .474 +(ariant names in the)-.25 F F0($=w)174 332.4 Q F1 +(class by some other mechanism.)2.5 E -1.61(DontPruneRoutes [R])102 +348.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)-3.905 +F 1.405(xplicit routes when)-.15 F .154 +(sending an error message \(as discussed in RFC 1123 \247 5.2.6\).)174 +360.6 R -.15(Fo)5.155 G 2.655(re).15 G .155(xample, when)-2.805 F +(sending an error message to)174 372.6 Q(<@kno)214 388.8 Q(wn1,@kno)-.25 +E(wn2,@kno)-.25 E(wn3:user@unkno)-.25 E(wn>)-.25 E F2(sendmail)174 405 Q +F1 1.155(will strip of)3.655 F 3.655(ft)-.25 G 1.155(he \231@kno)-3.655 +F(wn1,@kno)-.25 E 1.155(wn2\232 in order to mak)-.25 F 3.655(et)-.1 G +1.155(he route as)-3.655 F .812(direct as possible.)174 417 R(Ho)5.812 E +(we)-.25 E -.15(ve)-.25 G 1.612 -.4(r, i).15 H 3.312(ft).4 G(he)-3.312 E +F0(R)3.313 E F1 .813(option is set, this will be disabled, and the)3.313 +F .01(mail will be sent to the \214rst address in the route, e)174 429 R +-.15(ve)-.25 G 2.509(ni).15 G 2.509(fl)-2.509 G .009 +(ater addresses are kno)-2.509 F(wn.)-.25 E +(This may be useful if you are caught behind a \214re)174 441 Q -.1(wa) +-.25 G(ll.).1 E(DoubleBounceAddress=)102 457.2 Q F2(err)A(or)-.45 E +(-addr)-.2 E(ess)-.37 E F1 .504([no short name] If an error occurs when\ + sending an error message, send the error)174 469.2 R 1.999(report \(te\ +rmed a \231double bounce\232 because it is an error \231bounce\232 that\ + occurs)174 481.2 R .053(when trying to send another error \231bounce\ +\232\) to the indicated address.)174 493.2 R .054(The address)5.054 F +(is macro e)174 505.2 Q(xpanded at the time of deli)-.15 E -.15(ve)-.25 +G(ry).15 E 5(.I)-.65 G 2.5(fn)-5 G(ot set, def)-2.5 E +(aults to \231postmaster\232.)-.1 E(EightBitMode=)102 521.4 Q F2(action) +A F1 1.956([8] Set handling of eight-bit data.)174 533.4 R 1.955 +(There are tw)6.955 F 4.455(ok)-.1 G 1.955(inds of eight-bit data: that) +-4.455 F 3.334(declared as such using the)174 545.4 R F0(BOD)5.834 E +(Y=8BITMIME)-.4 E F1 3.335(ESMTP declaration or the)5.835 F F0 +(\255B8BITMIME)174 557.4 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 569.4 R 1.18 +(There are three basic operations that can happen:)6.18 F .996 +(undeclared 8-bit data can be automatically con)174 581.4 R -.15(ve)-.4 +G .995(rted to 8BITMIME, undeclared).15 F .887 +(8-bit data can be passed as-is without con)174 593.4 R -.15(ve)-.4 G +.887(rsion to MIME \(`).15 F .887(`just send 8')-.74 F .887('\), and) +-.74 F 1.794(declared 8-bit data can be con)174 605.4 R -.15(ve)-.4 G +1.794(rted to 7-bits for transmission to a non-8BIT).15 F(-)-.92 E +(MIME mailer)174 617.4 Q 5(.T)-.55 G(he possible)-5 E F2(action)2.5 E F1 +2.5(sa)C(re:)-2.5 E 11.11(sR)219 633.6 S +(eject undeclared 8-bit data \(`)-11.11 E(`strict')-.74 E('\))-.74 E +7.22(mC)219 645.6 S(on)-7.22 E -.15(ve)-.4 G +(rt undeclared 8-bit data to MIME \(`).15 E(`mime')-.74 E('\))-.74 E 10 +(pP)219 657.6 S(ass undeclared 8-bit data \(`)-10.15 E(`pass')-.74 E +('\))-.74 E 2.227 +(In all cases properly declared 8BITMIME data will be con)174 673.8 R +-.15(ve)-.4 G 2.228(rted to 7BIT as).15 F(needed.)174 685.8 Q +(ErrorHeader=)102 702 Q F2(\214le-or)A(-messa)-.2 E -.1(ge)-.1 G F1 .486 +([E] Prepend error messages with the indicated message.)174 714 R .486 +(If it be)5.486 F .486(gins with a slash,)-.15 F EP +%%Page: 54 50 +%%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 .246(it \ +is assumed to be the pathname of a \214le containing a message \(this i\ +s the recom-)174 96 R .86(mended setting\).)174 108 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, a\ +nd/or phone number of a local postmaster who could)174 120 R(pro)174 132 +Q .827(vide assistance to end users.)-.15 F .827 +(If the option is missing or null, or if it names a)5.827 F +(\214le which does not e)174 144 Q +(xist or which is not readable, no message is printed.)-.15 E +(ErrorMode=)102 160.2 Q/F2 10/Times-Italic@0 SF(x)A F1 +([e] Dispose of errors using mode)17.49 E F2(x)2.5 E F1 5(.T)C(he v)-5 E +(alues for)-.25 E F2(x)2.5 E F1(are:)2.5 E 15(pP)214 176.4 S +(rint error messages \(def)-15 E(ault\))-.1 E 15(qN)214 188.4 S 2.5(om) +-15 G(essages, just gi)-2.5 E .3 -.15(ve ex)-.25 H(it status).15 E 12.22 +(mM)214 200.4 S(ail back errors)-12.22 E 12.78(wW)214 212.4 S +(rite back errors \(mail if user not logged in\))-12.78 E 15.56(eM)214 +224.4 S(ail back errors and gi)-15.56 E .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 244.8 S +(llbackMXhost=).15 E F2(fallbac)A(khost)-.2 E F1 .796 +([V] If speci\214ed, the)174 256.8 R F2(fallbac)3.296 E(khost)-.2 E F1 +.796(acts lik)3.296 F 3.296(eav)-.1 G .797(ery lo)-3.446 F 3.297(wp)-.25 +G .797(riority MX on e)-3.297 F -.15(ve)-.25 G .797(ry host.).15 F 1.382 +(This is intended to be used by sites with poor netw)174 268.8 R 1.381 +(ork connecti)-.1 F(vity)-.25 E 6.381(.M)-.65 G(essages)-6.381 E .264 +(which are undeli)174 280.8 R -.15(ve)-.25 G .264 +(rable due to temporary address f).15 F .265(ailures \(e.g., DNS f)-.1 F +.265(ailure\) also)-.1 F(go to the F)174 292.8 Q(allBackMX host.)-.15 E +-.15(Fo)102 309 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.)-3.208 F(Use) +5.707 E .274(this option if you are short of memory)174 321 R 2.774(,s) +-.65 G .274(ince the def)-2.774 F .275(ault tends to consume consid-)-.1 +F(erable amounts of memory while the queue is being processed.)174 333 Q +-.15(Fo)102 349.2 S(rw).15 E(ardP)-.1 E(ath=)-.15 E F2(path)A F1 1.512 +([J] Set the path for searching for users' .forw)174 361.2 R 1.511 +(ard \214les.)-.1 F 1.511(The def)6.511 F 1.511(ault is \231$z/.for)-.1 +F(-)-.2 E -.1(wa)174 373.2 S 5.799(rd\232. Some).1 F 3.299 +(sites that use the automounter may prefer to change this to)5.799 F +(\231/v)174 385.2 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 397.2 Q +5.487(.I)-.65 G 2.987(tc)-5.487 G .488 +(an also be set to a sequence of paths separated by colons;)-2.987 F F2 +(sendmail)2.988 E F1 .831 +(stops at the \214rst \214le it can successfully and safely open.)174 +409.2 R -.15(Fo)5.83 G 3.33(re).15 G .83(xample, \231/v)-3.48 F(ar/for) +-.25 E(-)-.2 E -.1(wa)174 421.2 S(rd/$u:$z/.forw).1 E .276 +(ard\232 will search \214rst in /v)-.1 F(ar/forw)-.25 E(ard/)-.1 E F2 +(username)A F1 .277(and then in)2.777 F F2(~user)2.777 E(-)-.2 E(name) +174 433.2 Q F1(/.forw)A(ard \(b)-.1 E +(ut only if the \214rst \214le does not e)-.2 E(xist\).)-.15 E +(HelpFile=)102 449.4 Q F2(\214le)A F1 .18 +([H] Specify the help \214le for SMTP)19.14 F 5.18(.I)-1.11 G 2.68(fn) +-5.18 G 2.68<6f8c>-2.68 G .18 +(le name is speci\214ed, "help\214le" is used.)-2.68 F(HoldExpensi)102 +465.6 Q 8.54 -.15(ve [)-.25 H 1.393(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.894(,d).15 G +(on')-3.894 E 3.894(tc)-.18 G 1.394(onnect immedi-)-3.894 F(ately)174 +477.6 Q 5.268(.T)-.65 G .268(his requires that queueing be compiled in,\ + since it will depend on a queue)-5.268 F +(run process to actually send the mail.)174 489.6 Q(HostsFile=)102 505.8 +Q F2(path)A F1 .026([no short name] The path to the hosts database, nor\ +mally \231/etc/hosts\232.)10.24 F .026(This option)5.026 F 1.417(is onl\ +y consulted when sendmail is canonifying addresses, and then only when) +174 517.8 R .783 +(\231\214les\232 is in the \231hosts\232 service switch entry)174 529.8 +R 5.784(.I)-.65 G 3.284(np)-5.784 G(articular)-3.284 E 3.284(,t)-.4 G +.784(his \214le is)-3.284 F F2(ne)3.284 E(ver)-.15 E F1(used)3.284 E +.202(when looking up host addresses; that is under the control of the s\ +ystem)174 541.8 R F2 -.1(ge)2.702 G(thostby-).1 E(name)174 553.8 Q F1 +(\(3\) routine.)A(HostStatusDirectory=)102 570 Q F2(path)A F1 .43 +([no short name] The location of the long term host status information.) +174 582 R .43(When set,)5.43 F 1.39 +(information about the status of hosts \(e.g., host do)174 594 R 1.39 +(wn or not accepting connec-)-.25 F .162 +(tions\) will be shared between all)174 606 R F2(sendmail)2.663 E F1 +.163(processes; normally)2.663 F 2.663(,t)-.65 G .163 +(his information is)-2.663 F .123(only held within a single queue run.) +174 618 R .123(This option requires a connection cache of at)5.123 F +.688(least 1 to function.)174 630 R .688(If the option be)5.688 F .688 +(gins with a leading `/', it is an absolute path-)-.15 F .617 +(name; otherwise, it is relati)174 642 R .917 -.15(ve t)-.25 H 3.117(ot) +.15 G .617(he mail queue directory)-3.117 F 5.617(.A)-.65 G .617 +(suggested v)-2.5 F .616(alue for)-.25 F .558(sites desiring persistent\ + host status is \231.hoststat\232 \(i.e., a subdirectory of the queue) +174 654 R(directory\).)174 666 Q 24.51(IgnoreDots [i])102 682.2 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 694.2 Q -.1 +(wa)-.1 G(ys accepted\) when reading SMTP mail.).1 E(LD)102 710.4 Q +(APDef)-.4 E(aultSpec=)-.1 E F2(spec)A F1 2.057 +([no short name] Sets a def)174 722.4 R 2.058 +(ault map speci\214cation for LD)-.1 F 2.058(AP maps.)-.4 F 2.058(The v) +7.058 F(alue)-.25 E EP +%%Page: 55 51 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-55)195.86 E/F1 10/Times-Roman@0 SF .674(should only contain LD) +174 96 R .674 +(AP speci\214c settings such as \231-h host -p port -d bindDN\232.)-.4 F +.501(The settings will be used for all LD)174 108 R .501 +(AP maps unless the indi)-.4 F .501(vidual map speci\214ca-)-.25 F 1.5 +(tion o)174 120 R -.15(ve)-.15 G 1.5(rrides a setting.).15 F 1.5 +(This option should be set before an)6.5 F 4(yL)-.15 G -.4(DA)-4 G 4(Pm) +.4 G 1.5(aps are)-4 F(de\214ned.)174 132 Q(LogLe)102 148.2 Q -.15(ve) +-.25 G(l=).15 E/F2 10/Times-Italic@0 SF(n)A F1([L] Set the log le)22.88 +E -.15(ve)-.25 G 2.5(lt).15 G(o)-2.5 E F2(n)2.5 E F1 5(.D)C(ef)-5 E +(aults to 9.)-.1 E(M)102 164.4 Q F2 1.666(xv)C(alue)-1.666 E F1 .255 +([no long v)35.344 F .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)-5.255 F(command line.)174 176.4 +Q(The)5 E F02.5 E F1(\215ag is preferred.)2.5 E 11.17 +(MatchGECOS [G])102 192.6 R(Allo)3.334 E 3.334(wf)-.25 G .834 +(uzzy matching on the GECOS \214eld.)-3.334 F .833 +(If this \215ag is set, and the usual)5.833 F .867(user name lookups f) +174 204.6 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 216.6 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 228.6 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 240.6 Q(MaxAliasRecursion=)102 +256.8 Q F2(N)A F1 +([no short name] The maximum depth of alias recursion \(def)174 268.8 Q +(ault: 10\).)-.1 E(MaxDaemonChildren=)102 285 Q F2(N)A F1 .54 +([no short name] If set,)174 297 R F2(sendmail)3.039 E F1 .539 +(will refuse connections when it has more than)3.039 F F2(N)3.039 E F1 +1.086(children processing incoming mail.)174 309 R 1.087 +(This does not limit the number of outgoing)6.086 F 3.37 +(connections. If)174 321 R .87 +(not set, there is no limit to the number of children -- that is, the) +3.37 F(system load a)174 333 Q -.15(ve)-.2 G(raging controls this.).15 E +(MaxHeadersLength=)102 349.2 Q F2(N)A F1 .17 +([no short name] The maximum length of the sum of all headers.)174 361.2 +R .17(This can be used)5.17 F(to pre)174 373.2 Q -.15(ve)-.25 G +(nt a denial of service attack.).15 E(The def)5 E(ault is no limit.)-.1 +E(MaxHopCount=)102 389.4 Q F2(N)A F1 1.238([h] The maximum hop count.) +174 401.4 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 413.4 Q(Def)5 E +(aults to 25.)-.1 E(MaxMessageSize=)102 429.6 Q F2(N)A F1 2.562 +([no short name] Specify the maximum message size to be adv)174 441.6 R +2.563(ertised in the)-.15 F(ESMTP EHLO response.)174 453.6 Q +(Messages lar)5 E(ger than this will be rejected.)-.18 E +(MaxMimeHeaderLength=)102 469.8 Q F2(N[/M])A F1 .343([no short name] Se\ +ts the maximum length of certain MIME header \214eld v)174 481.8 R .343 +(alues to)-.25 F F2(N)174 493.8 Q F1 3.943(characters. F)3.943 F 1.444 +(or some of these headers which tak)-.15 F 3.944(ep)-.1 G 1.444 +(arameters, the maximum)-3.944 F .102 +(length of each parameter is set to)174 505.8 R F2(M)2.602 E F1 .102 +(if speci\214ed.)2.602 F(If)5.102 E F2(/M)2.602 E F1 .101 +(is not speci\214ed, one half of)2.602 F F2(N)174 517.8 Q F1 +(will be used.)2.5 E(By def)5 E(ault, these v)-.1 E +(alues are 0, meaning no checks are done.)-.25 E(MaxQueueRunSize=)102 +534 Q F2(N)A F1 .677([no short name] The maximum number of jobs that wi\ +ll be processed in a single)174 546 R .502(queue run.)174 558 R .501 +(If not set, there is no limit on the size.)5.502 F .501(If you ha)5.501 +F .801 -.15(ve ve)-.2 H .501(ry lar).15 F .501(ge queues)-.18 F .445 +(or a v)174 570 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 582 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 594 R -.2(vo)-.2 G .136 +(id \231losing\232 jobs that happen to f).2 F .137(all late)-.1 F +(in the queue directory)174 606 Q(.)-.65 E(MaxRecipientsPerMessage=)102 +622.2 Q F2(N)A F1 1.672([no short name] The maximum number of recipient\ +s that will be accepted per)174 634.2 R 1.458 +(message in an SMTP transaction.)174 646.2 R 1.458 +(Note: setting this too lo)6.458 F 3.959(wc)-.25 G 1.459 +(an interfere with)-3.959 F .049(sending mail from MU)174 658.2 R .049 +(As that use SMTP for initial submission.)-.4 F .048 +(If not set, there is)5.048 F +(no limit on the number of recipients per en)174 670.2 Q -.15(ve)-.4 G +(lope.).15 E(MeT)102 686.4 Q 40.86(oo [m])-.8 F .367(Send to me too, e) +2.866 F -.15(ve)-.25 G 2.867(ni).15 G 2.867(fIa)-2.867 G 2.867(mi)-2.867 +G 2.867(na)-2.867 G 2.867(na)-2.867 G .367(lias e)-2.867 F 2.867 +(xpansion. This)-.15 F .367(option is deprecated)2.867 F +(and will be remo)174 698.4 Q -.15(ve)-.15 G 2.5(df).15 G +(rom a future v)-2.5 E(ersion.)-.15 E EP +%%Page: 56 52 +%%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 +(MinFreeBlocks=)102 96 Q/F2 10/Times-Italic@0 SF(N)A F1 1.539 +([b] Insist on at least)174 108 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 120 R 5.846(.I)-1.11 G 3.346 +(ft)-5.846 G .846(here is insuf)-3.346 F .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 132 Q(This in)5 E +(vites the sender to try ag)-.4 E(ain later)-.05 E(.)-.55 E +(MinQueueAge=age)102 148.2 Q .887([no short name] Don')174 160.2 R 3.387 +(tp)-.18 G .887(rocess an)-3.387 F 3.387(yq)-.15 G .886 +(ueued jobs that ha)-3.387 F 1.186 -.15(ve b)-.2 H .886 +(een in the queue less).15 F 1.899(than the indicated time interv)174 +172.2 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-)-4.399 F(si)174 184.2 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 196.2 Q(The def)5 E +(ault units are minutes.)-.1 E(MustQuoteChars=)102 212.4 Q F2(s)A F1 +1.252([no short name] Sets the list of characters that must be quoted i\ +f used in a full)174 224.4 R 1.217 +(name that is in the phrase part of a `)174 236.4 R 1.217 +(`phrase
')-.74 F 3.717('s)-.74 G 3.717(yntax. The)-3.717 F +(def)3.717 E 1.217(ault is)-.1 F -.74(``)174 248.4 S.74 E -.74('') +-.7 G 5(.T).74 G(he characters `)-5 E(`@,;:\\\(\)[]')-.74 E 2.5('a)-.74 +G(re al)-2.5 E -.1(wa)-.1 G(ys added to this list.).1 E +(NoRecipientAction)102 264.6 Q .554([no short name] The action to tak) +174 276.6 R 3.055(ew)-.1 G .555(hen you recei)-3.055 F .855 -.15(ve a m) +-.25 H .555(essage that has no v).15 F(alid)-.25 E .625 +(recipient headers \(T)174 288.6 R .625(o:, Cc:, Bcc:, or Apparently-T) +-.8 F .625(o: \212 the last included for back)-.8 F .108 +(compatibility with old)174 300.6 R F2(sendmail)2.608 E F1 2.608 +(s\). It)B .108(can be)2.608 F F0(None)2.608 E F1 .109 +(to pass the message on unmod-)2.609 F .297 +(i\214ed, which violates the protocol,)174 312.6 R F0(Add-T)2.796 E(o) +-.92 E F1 .296(to add a T)2.796 F .296(o: header with an)-.8 F 2.796(yr) +-.15 G(ecipients)-2.796 E 1.638(it can \214nd in the en)174 324.6 R -.15 +(ve)-.4 G 1.638(lope \(which might e).15 F 1.638 +(xpose Bcc: recipients\),)-.15 F F0(Add-A)4.139 E(ppar)-.25 E(-)-.37 E +(ently-T)174 336.6 Q(o)-.92 E F1 .338(to add an Apparently-T)2.838 F +.337(o: header \(this is only for back-compatibility and)-.8 F .841 +(is of)174 348.6 R .841(\214cially deprecated\),)-.25 F F0(Add-T)3.341 E +(o-Undisclosed)-.92 E F1 .841(to add a header \231T)3.341 F .842 +(o: undisclosed-)-.8 F .398(recipients:;\232 to mak)174 360.6 R 2.898 +(et)-.1 G .397(he header le)-2.898 F -.05(ga)-.15 G 2.897(lw).05 G .397 +(ithout disclosing an)-2.897 F .397(ything, or)-.15 F F0(Add-Bcc)2.897 E +F1(to)2.897 E(add an empty Bcc: header)174 372.6 Q(.)-.55 E 1.18 +(OldStyleHeaders [o])102 388.8 R 1.713(Assume that the headers may be i\ +n old format, i.e., spaces delimit names.)4.213 F 1.069 +(This actually turns on an adapti)174 400.8 R 1.368 -.15(ve a)-.25 H +1.068(lgorithm: if an).15 F 3.568(yr)-.15 G 1.068 +(ecipient address contains a)-3.568 F 1.681 +(comma, parenthesis, or angle brack)174 412.8 R 1.681 +(et, it will be assumed that commas already)-.1 F -.15(ex)174 424.8 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 436.8 Q(Def)5 E(aults to of)-.1 +E(f.)-.25 E(OperatorChars=)102 453 Q F2 -.15(ch)C(arlist).15 E F1 1.438 +([$o macro] The list of characters that are considered to be \231operat\ +ors\232, that is,)174 465 R .82(characters that delimit tok)174 477 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 489 R 2.578 +(ens. White)-.1 F .078(space characters sep-)2.578 F .27(arate tok)174 +501 R .27(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 .269 +(AAA.BBB\232 has three)-.8 F(tok)174 513 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 525 Q 3.566(,t)-.65 G 1.066 +(he characters \231\()-3.566 F 1.666(\)<>,;)1.666 G 3.566<9a61>-1.666 G +1.066(re al)-3.566 F -.1(wa)-.1 G 1.065(ys operators.).1 F 1.065 +(Note that Operator)6.065 F(-)-.2 E +(Chars must be set in the con\214guration \214le before an)174 537 Q 2.5 +(yr)-.15 G(ulesets.)-2.5 E(PidFile=)102 553.2 Q F2(\214lename)A F1 1.3 +([no short name] Filename of the pid \214le.)3.58 F(\(def)6.3 E 1.3 +(ault is _P)-.1 F -1.11(AT)-.92 G(H_SENDMAILPID\).)1.11 E(The)174 565.2 +Q F2(\214lename)2.5 E F1(is macro-e)2.5 E(xpanded before it is opened.) +-.15 E(PostmasterCop)102 581.4 Q(y=)-.1 E F2(postmaster)A F1 .003 +([P] If set, copies of error messages will be sent to the named)174 +593.4 R F2(postmaster)2.503 E F1 5.003(.O)C .003(nly the)-5.003 F .626 +(header of the f)174 605.4 R .626(ailed message is sent.)-.1 F .627 +(Since most errors are user problems, this is)5.626 F .453 +(probably not a good idea on lar)174 617.4 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(violations, b)174 629.4 R .101 +(ut it seems to be popular with certain operating systems v)-.2 F 2.601 +(endors. The)-.15 F 1.919(address is macro e)174 641.4 R 1.918 +(xpanded at the time of deli)-.15 F -.15(ve)-.25 G(ry).15 E 6.918(.D) +-.65 G(ef)-6.918 E 1.918(aults to no postmaster)-.1 F(copies.)174 653.4 +Q(Pri)102 669.6 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 681.6 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)-3.692 F 3.692(yo)-.15 G 3.692(ft)-3.692 G 1.192 +(hese are)-3.692 F .929(just a w)174 693.6 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 705.6 Q EP +%%Page: 57 53 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-57)195.86 E/F1 10/Times-Roman@0 SF 40.26(public Allo)214 96 R +2.5(wo)-.25 G(pen access)-2.5 E 11.38(needmailhelo Insist)214 108 R +(on HELO or EHLO command before MAIL)2.5 E(neede)214 120 Q 9.87 +(xpnhelo Insist)-.15 F(on HELO or EHLO command before EXPN)2.5 E(noe)214 +132 Q 35.97(xpn Disallo)-.15 F 2.5(wE)-.25 G(XPN entirely)-2.5 E 12.5 +(needvrfyhelo Insist)214 144 R(on HELO or EHLO command before VRFY)2.5 E +(no)214 156 Q 38.75(vrfy Disallo)-.15 F 2.5(wV)-.25 G(RFY entirely)-2.5 +E 39.71(noetrn Disallo)214 168 R 2.5(wE)-.25 G(TRN entirely)-2.5 E(no) +214 180 Q -.15(ve)-.15 G 37.79(rb Disallo).15 F 2.5(wV)-.25 G +(ERB entirely)-2.5 E 14.71(restrictmailq Restrict)214 192 R +(mailq command)2.5 E 19.16(restrictqrun Restrict)214 204 R +(\255q command line \215ag)2.5 E 24.16(noreceipts Don')214 218 R 2.5(tr) +-.18 G(eturn success DSNs)-2.5 E/F2 7/Times-Roman@0 SF(21)-4 I F1 11.38 +(nobodyreturn Don')214 230 R 2.5(tr)-.18 G +(eturn the body of a message with DSNs)-2.5 E(goa)214 242 Q -.1(wa)-.15 +G 36.91(yD).1 G(isallo)-36.91 E 2.5(we)-.25 G +(ssentially all SMTP status queries)-2.5 E(authw)214 254 Q 11.48 +(arnings Put)-.1 F(X-Authentication-W)2.5 E(arning: headers in messages) +-.8 E 2.976(The \231goa)174 270.2 R -.1(wa)-.15 G 2.976 +(y\232 pseudo-\215ag sets all \215ags e).1 F 2.977 +(xcept \231noreceipts\232, \231restrictmailq\232,)-.15 F .035 +(\231restrictqrun\232, \231noetrn\232, and \231nobodyreturn\232.)174 +282.2 R .035(If mailq is restricted, only people in)5.035 F 1.752 +(the same group as the queue directory can print the queue.)174 294.2 R +1.753(If queue runs are)6.752 F 2.013(restricted, only root and the o) +174 306.2 R 2.012(wner of the queue directory can run the queue.)-.25 F +.224(Authentication W)174 318.2 R .224(arnings add w)-.8 F .224 +(arnings about v)-.1 F .225(arious conditions that may indicate)-.25 F +.335(attempts to spoof the mail system, such as using an non-standard q\ +ueue directory)174 330.2 R(.)-.65 E(ProcessT)102 346.4 Q(itlePre\214x=) +-.35 E/F3 10/Times-Italic@0 SF(string)A F1 1.195 +([no short name] Pre\214x the process title sho)174 358.4 R 1.196 +(wn on 'ps' listings with)-.25 F F3(string)3.696 E F1 6.196(.T)C(he) +-6.196 E F3(string)174 370.4 Q F1(will be macro processed.)2.5 E +(QueueDirectory=)102 386.6 Q F3(dir)A F1 .842([Q] Use the named)174 +398.6 R F3(dir)3.342 E F1 .841(as the queue directory)3.342 F 5.841(.T) +-.65 G 3.341(ou)-6.641 G .841(se multiple queues, supply a)-3.341 F -.25 +(va)174 410.6 S .608(lue ending with an asterisk.).25 F -.15(Fo)5.608 G +3.108(re).15 G(xample,)-3.258 E F3(/var/spool/mqueue/q*)3.108 E F1 .609 +(will use all of)3.108 F 6.572 +(the directories or symbolic links to directories be)174 422.6 R 6.572 +(ginning with)-.15 F F3(q)9.072 E F1(in)9.072 E F3(/var/spool/mqueue)174 +434.6 Q F1 .285(as queue directories.)2.785 F .285 +(Do not change the queue directory struc-)5.285 F +(ture while sendmail is running.)174 446.6 Q(QueueF)102 462.8 Q(actor=) +-.15 E F3(factor)A F1 .614([q] Use)174 474.8 R F3(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 486.8 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 498.8 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 510.8 Q(Def)5 E +(aults to 600000.)-.1 E(QueueLA=)102 527 Q F3(LA)A F1 .164 +([x] When the system load a)15.26 F -.15(ve)-.2 G .165(rage e).15 F +(xceeds)-.15 E F3(LA)2.665 E F1 2.665(,j)C .165 +(ust queue messages \(i.e., don')-2.665 F 2.665(tt)-.18 G(ry)-2.665 E +.168(to send them\).)174 539 R(Def)5.168 E .168 +(aults to 8 multiplied by the number of processors online on the)-.1 F +(system \(if that can be determined\).)174 551 Q(QueueSortOrder=)102 +567.2 Q F3(algorithm)A F1 .096([no short name] Sets the)174 579.2 R F3 +(algorithm)2.596 E F1 .096(used for sorting the queue.)2.596 F .097 +(Only the \214rst char)5.097 F(-)-.2 E 1.022(acter of the v)174 591.2 R +1.022(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)-3.771 F 1.73 +(\214rst host name of the \214rst recipient\), \231\214lename\232 \(to \ +order by the name of the)174 603.2 R 1.809(queue \214le name\), \231tim\ +e\232 \(to order by the submission time\), and \231priority\232 \(to)174 +615.2 R 1.858(order by message priority\).)174 627.2 R 1.858 +(Host ordering mak)6.858 F 1.858(es better use of the connection)-.1 F +.312(cache, b)174 639.2 R .312(ut may tend to process lo)-.2 F 2.812(wp) +-.25 G .312(riority messages that go to a single host o)-2.812 F -.15 +(ve)-.15 G(r).15 E .879(high priority messages that go to se)174 651.2 R +-.15(ve)-.25 G .879(ral hosts; it probably shouldn').15 F 3.38(tb)-.18 G +3.38(eu)-3.38 G .88(sed on)-3.38 F(slo)174 663.2 Q 3.7(wn)-.25 G(etw) +-3.7 E 1.2(ork links.)-.1 F 1.199(Filename ordering sa)6.199 F -.15(ve) +-.2 G 3.699(st).15 G 1.199(he o)-3.699 F -.15(ve)-.15 G 1.199 +(rhead of reading all of the).15 F .196 +(queued items before starting the queue run.)174 675.2 R -.35(Ti)5.196 G +.196(me ordering is almost al).35 F -.1(wa)-.1 G .197(ys a bad).1 F .32 +LW 76 684.8 72 684.8 DL 80 684.8 76 684.8 DL 84 684.8 80 684.8 DL 88 +684.8 84 684.8 DL 92 684.8 88 684.8 DL 96 684.8 92 684.8 DL 100 684.8 96 +684.8 DL 104 684.8 100 684.8 DL 108 684.8 104 684.8 DL 112 684.8 108 +684.8 DL 116 684.8 112 684.8 DL 120 684.8 116 684.8 DL 124 684.8 120 +684.8 DL 128 684.8 124 684.8 DL 132 684.8 128 684.8 DL 136 684.8 132 +684.8 DL 140 684.8 136 684.8 DL 144 684.8 140 684.8 DL 148 684.8 144 +684.8 DL 152 684.8 148 684.8 DL 156 684.8 152 684.8 DL 160 684.8 156 +684.8 DL 164 684.8 160 684.8 DL 168 684.8 164 684.8 DL 172 684.8 168 +684.8 DL 176 684.8 172 684.8 DL 180 684.8 176 684.8 DL 184 684.8 180 +684.8 DL 188 684.8 184 684.8 DL 192 684.8 188 684.8 DL 196 684.8 192 +684.8 DL 200 684.8 196 684.8 DL 204 684.8 200 684.8 DL 208 684.8 204 +684.8 DL 212 684.8 208 684.8 DL 216 684.8 212 684.8 DL/F4 5 +/Times-Roman@0 SF(21)93.6 695.2 Q/F5 8/Times-Roman@0 SF(N.B.: the)3.2 I +/F6 8/Times-Bold@0 SF(nor)2 E(eceipts)-.144 E F5(\215ag turns of)2 E 2 +(fs)-.2 G(upport for RFC 1891 \(Deli)-2 E -.12(ve)-.2 G +(ry Status Noti\214cation\).).12 E EP +%%Page: 58 54 +%%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/F1 10/Times-Roman@0 SF .845 +(idea, since it allo)174 96 R .845(ws lar)-.25 F .844(ge, b)-.18 F .844 +(ulk mail to go out before smaller)-.2 F 3.344(,p)-.4 G .844 +(ersonal mail, b)-3.344 F(ut)-.2 E .707(may ha)174 108 R 1.007 -.15 +(ve a)-.2 H .707(pplicability on some hosts with v).15 F .707(ery f)-.15 +F .708(ast connections.)-.1 F .708(Priority order)5.708 F(-)-.2 E +(ing is the def)174 120 Q(ault.)-.1 E(QueueT)102 136.2 Q(imeout=)-.35 E +/F2 10/Times-Italic@0 SF(timeout)A F1 .356([T] A synon)174 148.2 R .356 +(ym for \231T)-.15 F 2.856(imeout.queuereturn\232. Use)-.35 F .355 +(that form instead of the \231Queue-)2.855 F -.35(Ti)174 160.2 S +(meout\232 form.).35 E(Resolv)102 176.4 Q(erOptions=)-.15 E F2(options)A +F1 .127([I] Set resolv)174 188.4 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 F02.628 E F2<8d61>A(g)-.1 E F1 +2.628(;t)C(he)-2.628 E F2<8d61>174 200.4 Q(g)-.1 E F1 5.014(sc)C 2.514 +(an be \231deb)-5.014 F 2.513(ug\232, \231aaonly\232, \231use)-.2 F +2.513(vc\232, \231primary\232, \231igntc\232, \231recurse\232, \231def-) +-.25 F .867(names\232, \231stayopen\232, or \231dnsrch\232.)174 212.4 R +.867(The string \231HasW)5.867 F .867(ildcardMX\232 \(without a)-.4 F F0 +(+)3.367 E F1(or)3.367 E F0174 224.4 Q F1 3.82(\)c)C 1.32 +(an be speci\214ed to turn of)-3.82 F 3.82(fm)-.25 G 1.32(atching ag) +-3.82 F 1.32(ainst MX records when doing name)-.05 F(canoni\214cations.) +174 236.4 Q F0(N.B.)5.917 E F1 .918 +(Prior to 8.7, this option indicated that the name serv)5.917 F .918 +(er be)-.15 F 1.025(responding in order to accept addresses.)174 248.4 R +1.025(This has been replaced by checking to)6.025 F .078(see if the \ +\231dns\232 method is listed in the service switch entry for the \231ho\ +sts\232 service.)174 260.4 R 10.61(RrtImpliesDsn [R])102 276.6 R 1.52 +(If this option is set, a \231Return-Receipt-T)4.02 F 1.52 +(o:\232 header causes the request of a)-.8 F 1.271 +(DSN, which is sent to the en)174 288.6 R -.15(ve)-.4 G 1.272 +(lope sender as required by RFC1891, not to the).15 F(address gi)174 +300.6 Q -.15(ve)-.25 G 2.5(ni).15 G 2.5(nt)-2.5 G(he header)-2.5 E(.) +-.55 E(RunAsUser=)102 316.8 Q F2(user)A F1 3.753([no short name] The) +2.48 F F2(user)6.253 E F1 3.752(parameter may be a user name \(look) +6.252 F 3.752(ed up in)-.1 F F2(/etc/passwd)174 328.8 Q F1 3.045(\)o)C +-5.544 3.045(ra n)-3.045 H .546(umeric user id; either form can ha) +-3.045 F .846 -.15(ve \231)-.2 H .546(:group\232 attached \(where).15 F +.966(group can be numeric or symbolic\).)174 340.8 R .965 +(If set to a non-zero \(non-root\) v)5.965 F(alue,)-.25 E F2(send-)3.465 +E(mail)174 354.8 Q F1 .483 +(will change to this user id shortly after startup)2.983 F/F3 7 +/Times-Roman@0 SF(22)-4 I F1 5.484(.T)4 K .484(his a)-5.484 F -.2(vo)-.2 +G .484(ids a certain class).2 F 1.844(of security problems.)174 366.8 R +(Ho)6.844 E(we)-.25 E -.15(ve)-.25 G 2.644 -.4(r, t).15 H 1.844 +(his means that all \231.forw).4 F 1.844(ard\232 and \231:include:\232) +-.1 F 1.428(\214les must be readable by the indicated)174 378.8 R F2 +(user)3.928 E F1 1.428(and all \214les to be written must be)3.928 F +.043(writable by)174 390.8 R F2(user)2.543 E F1 .042 +(Also, all \214le and program deli)2.543 F -.15(ve)-.25 G .042 +(ries will be mark).15 F .042(ed unsafe unless)-.1 F 2.101(the option) +174 402.8 R F0(DontBlameSendmail=NonRootAddrSafe)4.601 E F1 2.101 +(is set, in which case the)4.601 F(deli)174 414.8 Q -.15(ve)-.25 G .778 +(ry will be done as).15 F F2(user)3.278 E F1 5.778(.I)C 3.277(ti)-5.778 +G 3.277(sa)-3.277 G .777(lso incompatible with the)-3.277 F F0 +(SafeFileEn)3.277 E(vir)-.4 E(on-)-.18 E(ment)174 426.8 Q F1 2.62 +(option. In)2.62 F .12(other w)2.62 F .121 +(ords, it may not actually add much to security on an a)-.1 F -.15(ve) +-.2 G -.2(r-).15 G .593(age system, and may in f)174 438.8 R .592 +(act detract from security \(because other \214le permissions)-.1 F +1.579(must be loosened\).)174 450.8 R(Ho)6.579 E(we)-.25 E -.15(ve)-.25 +G 2.379 -.4(r, i).15 H 4.079(ts).4 G 1.579(hould be useful on \214re) +-4.079 F -.1(wa)-.25 G 1.58(lls and other places).1 F(where users don') +174 462.8 Q 2.5(th)-.18 G -2.25 -.2(av e)-2.5 H +(accounts and the aliases \214le is well constrained.)2.7 E(RecipientF) +102 479 Q(actor=)-.15 E F2(fact)A F1 .638([y] The indicated)174 491 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 503 R .231 +(alue penalizes jobs with lar)-.25 F .231(ge numbers of recipi-)-.18 F +2.5(ents. Def)174 515 R(aults to 30000.)-.1 E(RefuseLA=)102 531.2 Q F2 +(LA)A F1 1.012([X] When the system load a)13.59 F -.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-)-3.512 F 2.658(tions. Def)174 543.2 R .158 +(aults to 12 multiplied by the number of processors online on the syste\ +m)-.1 F(\(if that can be determined\).)174 555.2 Q(RetryF)102 571.4 Q +(actor=)-.15 E F2(fact)A F1 .772([Z] The)3.74 F F2(fact)3.272 E F1 .772 +(or is added to the priority e)B -.15(ve)-.25 G .771 +(ry time a job is processed.).15 F .771(Thus, each)5.771 F .994(time a \ +job is processed, its priority will be decreased by the indicated v)174 +583.4 R 3.494(alue. In)-.25 F 1.108(most en)174 595.4 R 1.108 +(vironments this should be positi)-.4 F -.15(ve)-.25 G 3.608(,s).15 G +1.108(ince hosts that are do)-3.608 F 1.107(wn are all too)-.25 F +(often do)174 607.4 Q(wn for a long time.)-.25 E(Def)5 E +(aults to 90000.)-.1 E(SafeFileEn)102 623.6 Q(vironment=)-.4 E F2(dir)A +F1 .021([no short name] If this option is set,)174 635.6 R F2(sendmail) +2.521 E F1 .021(will do a)2.521 F F2 -.15(ch)2.521 G -.45(ro).15 G(ot) +.45 E F1 .022(\(2\) call into the indi-)B(cated)174 647.6 Q F2(dir)2.833 +E F1 .333(ectory before doing an)B 2.833<798c>-.15 G .333(le writes.) +-2.833 F .333(If the \214le name speci\214ed by the user)5.333 F(be)174 +659.6 Q .587(gins with)-.15 F F2(dir)3.087 E F1 3.087(,t)C .587 +(hat partial path name will be stripped of)-3.087 F 3.087(fb)-.25 G .588 +(efore writing, so \(for)-3.087 F -.15(ex)174 671.6 S 2.225 +(ample\) if the SafeFileEn).15 F 2.225(vironment v)-.4 F 2.224 +(ariable is set to \231/safe\232 then aliases of)-.25 F .32 LW 76 681.2 +72 681.2 DL 80 681.2 76 681.2 DL 84 681.2 80 681.2 DL 88 681.2 84 681.2 +DL 92 681.2 88 681.2 DL 96 681.2 92 681.2 DL 100 681.2 96 681.2 DL 104 +681.2 100 681.2 DL 108 681.2 104 681.2 DL 112 681.2 108 681.2 DL 116 +681.2 112 681.2 DL 120 681.2 116 681.2 DL 124 681.2 120 681.2 DL 128 +681.2 124 681.2 DL 132 681.2 128 681.2 DL 136 681.2 132 681.2 DL 140 +681.2 136 681.2 DL 144 681.2 140 681.2 DL 148 681.2 144 681.2 DL 152 +681.2 148 681.2 DL 156 681.2 152 681.2 DL 160 681.2 156 681.2 DL 164 +681.2 160 681.2 DL 168 681.2 164 681.2 DL 172 681.2 168 681.2 DL 176 +681.2 172 681.2 DL 180 681.2 176 681.2 DL 184 681.2 180 681.2 DL 188 +681.2 184 681.2 DL 192 681.2 188 681.2 DL 196 681.2 192 681.2 DL 200 +681.2 196 681.2 DL 204 681.2 200 681.2 DL 208 681.2 204 681.2 DL 212 +681.2 208 681.2 DL 216 681.2 212 681.2 DL/F4 5/Times-Roman@0 SF(22)93.6 +691.6 Q/F5 8/Times-Roman@0 SF(When running as a daemon, it changes to t\ +his user after accepting a connection b)3.2 I(ut before reading an)-.16 +E(y)-.12 E F3(SMTP)2 E F5(commands.)2 E EP +%%Page: 59 55 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-59)195.86 E/F1 10/Times-Roman@0 SF 1.557(\231/safe/logs/\214le\ +\232 and \231/logs/\214le\232 actually indicate the same \214le.)174 96 +R(Additionally)6.557 E 4.057(,i)-.65 G(f)-4.057 E(this option is set,) +174 108 Q/F2 10/Times-Italic@0 SF(sendmail)2.5 E F1(refuses to deli)2.5 +E -.15(ve)-.25 G 2.5(rt).15 G 2.5(os)-2.5 G(ymbolic links.)-2.5 E(Sa)102 +124.2 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)-4.908 E +(assumed redundant and discarded.)174 136.2 Q .62(SendMimeErrors [j])102 +152.4 R .815(If set, send error messages in MIME format \(see RFC2045 a\ +nd RFC1344 for)3.315 F 2.915(details\). If)174 164.4 R(disabled,)2.915 E +F2(sendmail)2.915 E F1 .415(will not return the DSN k)2.915 F -.15(ey) +-.1 G -.1(wo).15 G .414(rd in response to an).1 F 1.731 +(EHLO and will not do Deli)174 176.4 R -.15(ve)-.25 G 1.731 +(ry Status Noti\214cation processing as described in).15 F(RFC1891.)174 +188.4 Q(ServiceSwitchFile=)102 204.6 Q F2(\214lename)A F1 1.533([no sho\ +rt name] If your host operating system has a service switch abstraction) +174 216.6 R .003(\(e.g., /etc/nsswitch.conf on Solaris or /etc/svc.conf\ + on Ultrix and DEC OSF/1\) that)174 228.6 R .814 +(service will be consulted and this option is ignored.)174 240.6 R .814 +(Otherwise, this is the name)5.814 F 1.082(of a \214le that pro)174 +252.6 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 264.6 R 3.569(ords. The)-.1 F(\214rst)3.569 E -.1(wo)174 276.6 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 288.6 +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)-6.61 F 1.754(\231dns\232, \231nis\232, \ +\231nisplus\232, or \231\214les\232 \(with the ca)174 300.6 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 312.6 R +.79(If ServiceSwitchFile)5.791 F .925(is not speci\214ed, it def)174 +324.6 R .925(aults to /etc/mail/service.switch.)-.1 F .925 +(If that \214le does not e)5.925 F(xist,)-.15 E(the def)174 336.6 Q +(ault switch is:)-.1 E 38.6(aliases \214les)214 352.8 R 44.7(hosts dns) +214 364.8 R(nis \214les)2.5 E(The def)174 381 Q +(ault \214le is \231/etc/mail/service.switch\232.)-.1 E(Se)102 397.2 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.)-2.822 F .321(This shouldn') +5.321 F 2.821(tb)-.18 G(e)-2.821 E(necessary)174 409.2 Q(.)-.65 E +(SingleLineFromHeader)102 425.4 Q .958 +([no short name] If set, From: lines that ha)174 437.4 R 1.259 -.15 +(ve e)-.2 H .959(mbedded ne).15 F .959(wlines are unwrapped)-.25 F .243 +(onto one line.)174 449.4 R .243 +(This is to get around a botch in Lotus Notes that apparently cannot) +5.243 F(understand le)174 461.4 Q -.05(ga)-.15 G +(lly wrapped RFC822 headers.).05 E(SingleThreadDeli)102 477.6 Q -.15(ve) +-.25 G(ry).15 E .333([no short name] If set, a client machine will ne) +174 489.6 R -.15(ve)-.25 G 2.833(rt).15 G .334(ry to open tw)-2.833 F +2.834(oS)-.1 G .334(MTP connec-)-2.834 F 1.712(tions to a single serv) +174 501.6 R 1.712(er machine at the same time, e)-.15 F -.15(ve)-.25 G +4.211(ni).15 G 4.211(nd)-4.211 G(if)-4.211 E 1.711(ferent processes.) +-.25 F .952(That is, if another)174 513.6 R F2(sendmail)3.452 E F1 .952 +(is already talking to some host a ne)3.452 F(w)-.25 E F2(sendmail)3.453 +E F1(will)3.453 E 2.388(not open another connection.)174 525.6 R 2.387 +(This property is of mix)7.387 F 2.387(ed v)-.15 F 2.387 +(alue; although this)-.25 F .386(reduces the load on the other machine,\ + it can cause mail to be delayed \(for e)174 537.6 R(xam-)-.15 E .719 +(ple, if one)174 549.6 R F2(sendmail)3.219 E F1 .719(is deli)3.219 F +-.15(ve)-.25 G .718(ring a huge message, other).15 F F2(sendmail)3.218 E +F1 3.218(sw)C(on')-3.318 E 3.218(tb)-.18 G 3.218(ea)-3.218 G(ble)-3.218 +E 1.542(to send e)174 561.6 R -.15(ve)-.25 G 4.042(ns).15 G 1.542 +(mall messages\).)-4.042 F 1.543 +(Also, it requires another \214le descriptor \(for the)6.542 F .997 +(lock \214le\) per connection, so you may ha)174 573.6 R 1.296 -.15 +(ve t)-.2 H 3.496(or).15 G .996(educe the)-3.496 F F0 +(ConnectionCacheSize)3.496 E F1 .234(option to a)174 585.6 R -.2(vo)-.2 +G .234(id running out of per).2 F .235(-process \214le descriptors.)-.2 +F .235(Requires the)5.235 F F0(HostSta-)2.735 E(tusDir)174 597.6 Q +(ectory)-.18 E F1(option.)2.5 E(SmtpGreetingMessage=)102 613.8 Q F2 +(messa)A -.1(ge)-.1 G F1 .345 +([$e macro] The message printed when the SMTP serv)174 625.8 R .344 +(er starts up.)-.15 F(Def)5.344 E .344(aults to \231$j)-.1 F +(Sendmail $v ready at $b\232.)174 637.8 Q(StatusFile=)102 654 Q F2 +(\214le)A F1 .523([S] Log summary statistics in the named)14.13 F F2 +(\214le)3.024 E F1 5.524(.I)C 3.024(fn)-5.524 G 3.024<6f8c>-3.024 G .524 +(le name is speci\214ed, "statis-)-3.024 F .548(tics" is used.)174 666 R +.547(If not set, no summary statistics are sa)5.548 F -.15(ve)-.2 G +3.047(d. This).15 F .547(\214le does not gro)3.047 F(w)-.25 E(in size.) +174 678 Q(It can be printed using the)5 E F2(mailstats)2.5 E F1 +(\(8\) program.)A 28.4(SuperSafe [s])102 694.2 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 706.2 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 1.509 +(queue \214le before returning control to the client under an)174 718.2 +R 4.009(yc)-.15 G 4.01(ircumstances. This)-4.009 F EP +%%Page: 60 56 +%%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/F1 10/Times-Roman@0 SF +(should really)174 96 Q/F2 10/Times-Italic@0 SF(always)2.5 E F1(be set.) +2.5 E -.7(Te)102 112.2 S(mpFileMode=).7 E F2(mode)A F1 .332 +([F] The \214le mode for queue \214les.)174 124.2 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 136.2 Q -.35(Ti)102 152.4 S(meout.).35 E F2 +(type)A F1(=)A F2(timeout)1.666 E F1 .417 +([r; subsumes old T option as well] Set timeout v)174 164.4 R 2.917 +(alues. F)-.25 F .417(or more information, see)-.15 F(section 4.1.)174 +176.4 Q -.35(Ti)102 192.6 S(meZoneSpec=).35 E F2(tzinfo)A F1 .218 +([t] Set the local time zone info to)174 204.6 R F2(tzinfo)2.718 E F1 +2.718<8a66>2.718 G .218(or e)-2.718 F .218(xample, \231PST8PDT\232.)-.15 +F(Actually)5.217 E 2.717(,i)-.65 G(f)-2.717 E 1.345 +(this is not set, the TZ en)174 216.6 R 1.346(vironment v)-.4 F 1.346 +(ariable is cleared \(so the system def)-.25 F 1.346(ault is)-.1 F .209 +(used\); if set b)174 228.6 R .208(ut null, the user')-.2 F 2.708(sT) +-.55 G 2.708(Zv)-2.708 G .208 +(ariable is used, and if set and non-null the TZ)-2.958 F -.25(va)174 +240.6 S(riable is set to this v).25 E(alue.)-.25 E -.35(Tr)102 256.8 S +(ustedUser=).35 E F2(user)A F1 3.752([no short name] The).06 F F2(user) +6.252 E F1 3.752(parameter may be a user name \(look)6.252 F 3.753 +(ed up in)-.1 F F2(/etc/passwd)174 268.8 Q F1 2.743(\)o)C 2.743(ran) +-2.743 G .243(umeric user id.)-2.743 F -.35(Tr)5.242 G .242 +(usted user for \214le o).35 F .242(wnership and starting the)-.25 F +3.779(daemon. If)174 280.8 R 1.279 +(set, generated alias databases and the control sock)3.779 F 1.279 +(et \(if con\214gured\))-.1 F(will automatically be o)174 292.8 Q +(wned by this user)-.25 E(.)-.55 E -.35(Tr)102 309 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)-2.613 F 1.168(con\214guration rules should normally detect t\ +his situation and treat that condition)174 321 R .258(specially by forw) +174 333 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 345 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) +-3.385 F -.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 +357 R .07(Setting this option)5.07 F(causes)174 369 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 381 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 393 Q(This option is disrecommended.)5 E +(UnixFromLine=)102 409.2 Q F2(fr)A(omline)-.45 E F1 .236 +([$l macro] De\214nes the format used when)174 421.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 433.2 R 1.325 +(ginning \231Fromuser\232\).)-.15 F(Def)6.324 E 1.324 +(aults to \231From $g)-.1 F($d\232.)6.324 E(Don')174 445.2 Q 2.645(tc) +-.18 G .146(hange this unless your system uses a dif)-2.645 F .146 +(ferent UNIX mailbox format \(v)-.25 F(ery)-.15 E(unlik)174 457.2 Q +(ely\).)-.1 E(UnsafeGroupWrites)102 473.4 Q .212 +([no short name] If set, :include: and .forw)174 485.4 R .211 +(ard \214les that are group writable are con-)-.1 F .366 +(sidered \231unsafe\232, that is, the)174 497.4 R 2.867(yc)-.15 G .367 +(annot reference programs or write directly to \214les.)-2.867 F -.8(Wo) +174 509.4 S(rld writable :include: and .forw).8 E(ard \214les are al)-.1 +E -.1(wa)-.1 G(ys unsafe..).1 E(UseErrorsT)102 525.6 Q 21.15(o[)-.8 G +.826(l] If there is an \231Errors-T)-21.15 F .826(o:\232 header)-.8 F +3.326(,s)-.4 G .826(end error messages to the addresses listed)-3.326 F +3.134(there. The)174 537.6 R 3.134(yn)-.15 G .634(ormally go to the en) +-3.134 F -.15(ve)-.4 G .635(lope sender).15 F 5.635(.U)-.55 G .635 +(se of this option causes)-5.635 F F2(send-)3.135 E(mail)174 549.6 Q F1 +(to violate RFC 1123.)2.5 E +(This option is disrecommended and deprecated.)5 E(UserDatabaseSpec=)102 +565.8 Q F2(udbspec)A F1([U] The user database speci\214cation.)174 577.8 +Q -1.11(Ve)102 594 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 606 Q F0(c)2.635 E F1 2.635(\)a)C(nd)-2.635 E 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)-2.635 G .135(hat all mail is deli)-2.635 F -.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 618 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 630 Q(ver)-.15 E F1(be set in the con\214gura\ +tion \214le; it is intended for command line use only)2.5 E(.)-.65 E +(XscriptFileBuf)102 646.2 Q(ferSize=)-.25 E F2(thr)A(eshold)-.37 E F1 +1.1([no short name] Set the)174 658.2 R F2(thr)3.601 E(eshold)-.37 E F1 +3.601(,i)C 3.601(nb)-3.601 G 1.101 +(ytes, before a memory-based queue tran-)-3.601 F +(script \214le becomes disk-based.)174 670.2 Q(The def)5 E +(ault is 4096 bytes.)-.1 E .109(All options can be speci\214ed on the c\ +ommand line using the \255O or \255o \215ag, b)102 686.4 R .108 +(ut most will cause)-.2 F F2(send-)2.608 E(mail)102 698.4 Q F1 .271 +(to relinquish its setuid permissions.)2.771 F .271 +(The options that will not cause this are Se)5.271 F -.15(ve)-.25 G .272 +(nBitInput [7],).15 F .981 +(EightBitMode [8], MinFreeBlocks [b], CheckpointInterv)102 710.4 R .981 +(al [C], Deli)-.25 F -.15(ve)-.25 G .981(ryMode [d], ErrorMode [e],).15 +F 6.66(IgnoreDots [i], SendMimeErrors [j], LogLe)102 722.4 R -.15(ve) +-.25 G 9.16(l[).15 G 6.66(L], MeT)-9.16 F 6.66 +(oo [m], OldStyleHeaders [o],)-.8 F EP +%%Page: 61 57 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-61)195.86 E/F1 10/Times-Roman@0 SF(Pri)102 96 Q -.25(va)-.25 G +-.15(cy).25 G 1.378(Options [p], SuperSafe [s], V).15 F 1.377 +(erbose [v], QueueSortOrder)-1.11 F 3.877(,M)-.4 G 1.377 +(inQueueAge, Def)-3.877 F(aultCharSet,)-.1 E .723(Dial Delay)102 108 R +3.223(,N)-.65 G .723(oRecipientAction, ColonOkInAddr)-3.223 F 3.223(,M) +-.4 G .724(axQueueRunSize, SingleLineFromHeader)-3.223 F 3.224(,a)-.4 G +(nd)-3.224 E(Allo)102 120 Q 3.921(wBogusHELO. Actually)-.25 F 3.921(,P) +-.65 G(ri)-3.921 E -.25(va)-.25 G -.15(cy).25 G 1.421(Options [p] gi).15 +F -.15(ve)-.25 G 3.921(no).15 G 3.921(nt)-3.921 G 1.421 +(he command line are added to those)-3.921 F 1.697 +(already speci\214ed in the)102 132 R/F2 10/Times-Italic@0 SF +(sendmail.cf)4.197 E F1 1.697(\214le, i.e., the)4.197 F 4.197(yc)-.15 G +(an')-4.197 E 4.197(tb)-.18 G 4.197(er)-4.197 G 4.198(eset. Also,)-4.197 +F 4.198(M\()4.198 G 1.698(de\214ne macro\) when)-4.198 F +(de\214ning the r or s macros is also considered \231safe\232.)102 144 Q +F0 2.5(5.7. P)87 168 R 2.5<8a50>2.5 G -.18(re)-2.5 G +(cedence De\214nitions).18 E F1 -1.11(Va)127 184.2 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 .163 +(The syntax of this)5.163 F(\214eld is:)102 196.2 Q F0(P)142 212.4 Q F2 +(name)A F0(=)A F2(num)A F1 .383(When the)102 228.6 R F2(name)2.883 E F1 +.384 +(is found in a \231Precedence:\232 \214eld, the message class is set to) +2.883 F F2(num)2.884 E F1 5.384(.H)C .384(igher numbers)-5.384 F .85 +(mean higher precedence.)102 240.6 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 retur\ +ned; this is e)102 252.6 R 1.552(xpected to be used for)-.15 F<9962>102 +264.6 Q .462(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.961(re).15 G .461(xample, our list of)-3.111 F(precedences is:)102 +276.6 Q(P\214rst-class=0)142 292.8 Q(Pspecial-deli)142 304.8 Q -.15(ve) +-.25 G(ry=100).15 E(Plist=\25530)142 316.8 Q(Pb)142 328.8 Q(ulk=\25560) +-.2 E(Pjunk=\255100)142 340.8 Q 1.058(People writing mailing list e)102 +357 R 1.058(xploders are encouraged to use \231Precedence: list\232.) +-.15 F 1.059(Older v)6.059 F 1.059(ersions of)-.15 F F2(sendmail)102 369 +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,)-3.69 F(gi)102 381 Q .598(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 +393 Q 2.5(wv)-.25 G(ersions of)-2.65 E F2(sendmail)2.5 E F1(.)A F0 2.5 +(5.8. V)87 417 R 2.5<8a43>2.5 G(on\214guration V)-2.5 E(ersion Le)-1 E +-.1(ve)-.15 G(l).1 E F1 3.182 -.8(To p)127 433.2 T(ro).8 E 1.582 +(vide compatibility with old con\214guration \214les, the)-.15 F F0(V) +4.081 E F1 1.581(line has been added to de\214ne)4.081 F 1.11(some v)102 +445.2 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 .034 +(ports; rather)102 457.2 R 2.533(,t)-.4 G(he)-2.533 E 2.533(yd)-.15 G +.033(escribe compatibility features which will probably be remo)-2.533 F +-.15(ve)-.15 G 2.533(di).15 G 2.533(nf)-2.533 G .033(uture releases.) +-2.533 F F0(N.B.:)127 473.4 Q F1 .196(these v)2.696 F(ersion)-.15 E F2 +(le)2.696 E(vels)-.15 E F1(ha)2.696 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 .197 +(on the \214les.)2.696 F -.15(Fo)5.197 G 2.697(re).15 G(xam-)-2.847 E +(ple, as of this writing v)102 485.4 Q +(ersion 8 con\214g \214les \(speci\214cally)-.15 E 2.5(,8)-.65 G +(.10\) used v)-2.5 E(ersion le)-.15 E -.15(ve)-.25 G 2.5(l9c).15 G +(on\214gurations.)-2.5 E 1.102 +(\231Old\232 con\214guration \214les are de\214ned as v)127 501.6 R +1.102(ersion le)-.15 F -.15(ve)-.25 G 3.602(lo).15 G 3.602(ne. V)-3.602 +F 1.102(ersion le)-1.11 F -.15(ve)-.25 G 3.602(lt).15 G 1.302 -.1 +(wo \214)-3.602 H 1.102(les mak).1 F 3.602(et)-.1 G(he)-3.602 E(follo) +102 513.6 Q(wing changes:)-.25 E 12.5(\(1\) Host)107 529.8 R .727(name \ +canoni\214cation \($[ ... $]\) appends a dot if the name is recognized;\ + this gi)3.226 F -.15(ve)-.25 G 3.227(st).15 G(he)-3.227 E 1.975 +(con\214g \214le a w)133.66 541.8 R 1.974(ay of \214nding out if an)-.1 +F 1.974(ything matched.)-.15 F(\(Actually)6.974 E 4.474(,t)-.65 G 1.974 +(his just initializes the)-4.474 F .738 +(\231host\232 map with the \231\255a.)133.66 553.8 R 5.739<9a8d>-.7 G +.739(ag \212 you can reset it to an)-5.739 F .739 +(ything you prefer by declaring the)-.15 F(map e)133.66 565.8 Q +(xplicitly)-.15 E(.\))-.65 E 12.5(\(2\) Def)107 582 R .385 +(ault host name e)-.1 F .385 +(xtension is consistent throughout processing; v)-.15 F .384(ersion le) +-.15 F -.15(ve)-.25 G 2.884(lo).15 G .384(ne con\214gu-)-2.884 F .83 +(rations turned of)133.66 594 R 3.33(fd)-.25 G .83(omain e)-3.33 F .83 +(xtension \(that is, adding the local domain name\) during certain)-.15 +F .4(points in processing.)133.66 606 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)-2.9 H .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 618 Q 12.5 +(\(3\) Local)107 634.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)-2.572 F .072(e; this can)-.15 F +.14(be used to append a local relay)133.66 646.2 R 5.139(.T)-.65 G .139 +(his beha)-5.139 F .139(vior can be pre)-.2 F -.15(ve)-.25 G .139 +(nted by resolving the local name).15 F .993(with an initial `@'.)133.66 +658.2 R .993(That is, something that resolv)5.993 F .993 +(es to a local mailer and a user name of)-.15 F .602 +(\231vikki\232 will be passed through ruleset \214v)133.66 670.2 R .601 +(e, b)-.15 F .601(ut a user name of \231@vikki\232 will ha)-.2 F .901 +-.15(ve t)-.2 H .601(he `@').15 F .919 +(stripped, will not be passed through ruleset \214v)133.66 682.2 R .919 +(e, b)-.15 F .92(ut will otherwise be treated the same as)-.2 F .63 +(the prior e)133.66 694.2 R 3.13(xample. The)-.15 F -.15(ex)3.13 G .629 +(pectation is that this might be used to implement a polic).15 F 3.129 +(yw)-.15 G(here)-3.129 E .734(mail sent to \231vikki\232 w)133.66 706.2 +R .734(as handled by a central hub, b)-.1 F .734 +(ut mail sent to \231vikki@localhost\232 w)-.2 F(as)-.1 E(deli)133.66 +718.2 Q -.15(ve)-.25 G(red directly).15 E(.)-.65 E EP +%%Page: 62 58 +%%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 -1.11(Ve) +127 96 S 1.383(rsion le)1.11 F -.15(ve)-.25 G 3.883(lt).15 G 1.383 +(hree \214les allo)-3.883 F 3.882(w#i)-.25 G 1.382 +(nitiated comments on all lines.)-3.882 F 1.382 +(Exceptions are backslash)6.382 F(escaped # marks and the $# syntax.)102 +108 Q -1.11(Ve)127 124.2 S 1.207(rsion le)1.11 F -.15(ve)-.25 G 3.707 +(lf).15 G 1.207(our con\214gurations are completely equi)-3.707 F -.25 +(va)-.25 G 1.208(lent to le).25 F -.15(ve)-.25 G 3.708(lt).15 G 1.208 +(hree for historical rea-)-3.708 F(sons.)102 136.2 Q -1.11(Ve)127 152.4 +S 1.234(rsion le)1.11 F -.15(ve)-.25 G 3.734<6c8c>.15 G 1.534 -.15(ve c) +-3.734 H 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 164.4 Q +-1.11(Ve)127 180.6 S 1.588(rsion le)1.11 F -.15(ve)-.25 G 4.088(ls).15 G +1.588(ix con\214guration \214les change man)-4.088 F 4.088(yo)-.15 G +4.089(ft)-4.088 G 1.589(he local processing options \(such as)-4.089 F +.481(aliasing and matching the be)102 192.6 R .481(ginning of the addre\ +ss for `|' characters\) to be mailer \215ags; this allo)-.15 F(ws)-.25 E +1.344(\214ne-grained control o)102 204.6 R -.15(ve)-.15 G 3.844(rt).15 G +1.344(he special local processing.)-3.844 F(Le)6.345 E -.15(ve)-.25 G +3.845(ls).15 G 1.345(ix con\214guration \214les may also use)-3.845 F +1.222(long option names.)102 216.6 R(The)6.222 E F0(ColonOkInAddr)3.722 +E F1 1.222(option \(to allo)3.722 F 3.721(wc)-.25 G 1.221 +(olons in the local-part of addresses\))-3.721 F(def)102 228.6 Q(aults) +-.1 E F0(on)3.44 E F1 .94(for lo)3.44 F .94(wer numbered con\214guratio\ +n \214les; the con\214guration \214le requires some additional)-.25 F +(intelligence to properly handle the RFC 822 group construct.)102 240.6 +Q -1.11(Ve)127 256.8 S 1.97(rsion le)1.11 F -.15(ve)-.25 G 4.47(ls).15 G +-2.15 -.25(ev e)-4.47 H 4.47(nc).25 G 1.97 +(on\214guration \214les used ne)-4.47 F 4.47(wo)-.25 G 1.97 +(ption names to replace old macros \()-4.47 F F0($e)A F1(became)102 +268.8 Q F0(SmtpGr)5.547 E(eetingMessage)-.18 E F1(,)A F0($l)5.547 E F1 +(became)5.547 E F0(UnixFr)5.547 E(omLine)-.18 E F1 5.548(,a)C(nd)-5.548 +E F0($o)5.548 E F1(became)5.548 E F0(OperatorChars)5.548 E F1(.)A .087 +(Also, prior to v)102 280.8 R .087(ersion se)-.15 F -.15(ve)-.25 G .087 +(n, the).15 F F0(F=q)2.587 E F1 .087 +(\215ag \(use 250 instead of 252 return v)2.587 F .086(alue for)-.25 F +/F2 9/Times-Roman@0 SF .086(SMTP VRFY)2.586 F F1(com-)2.586 E(mands\) w) +102 292.8 Q(as assumed.)-.1 E -1.11(Ve)127 309 S(rsion le)1.11 E -.15 +(ve)-.25 G 2.5(le).15 G(ight con\214guration \214les allo)-2.5 E(w)-.25 +E F0($#)2.5 E F1(on the left hand side of ruleset lines.)2.5 E -1.11(Ve) +127 325.2 S .422(rsion le)1.11 F -.15(ve)-.25 G 2.922(ln).15 G .423 +(ine con\214guration \214les allo)-2.922 F 2.923(wp)-.25 G .423 +(arentheses in rulesets, i.e. the)-2.923 F 2.923(ya)-.15 G .423 +(re not treated as)-2.923 F(comments and hence remo)102 337.2 Q -.15(ve) +-.15 G(d.).15 E(The)127 353.4 Q F0(V)2.678 E F1 .178(line may ha)2.678 F +.478 -.15(ve a)-.2 H 2.677(no).15 G(ptional)-2.677 E F0(/)2.677 E/F3 10 +/Times-Italic@0 SF(vendor)A F1 .177 +(to indicate that this con\214guration \214le uses modi\214ca-)2.677 F +.866(tions speci\214c to a particular v)102 367.4 R(endor)-.15 E/F4 7 +/Times-Roman@0 SF(23)-4 I F1 5.866(.Y)4 K .866(ou may use \231/Berk) +-6.966 F(ele)-.1 E .865(y\232 to emphasize that this con\214gura-)-.15 F +(tion \214le uses the Berk)102 379.4 Q(ele)-.1 E 2.5(yd)-.15 G +(ialect of)-2.5 E F3(sendmail)2.5 E F1(.)A F0 2.5(5.9. K)87 403.4 R 2.5 +<8a4b>2.5 G(ey File Declaration)-2.75 E F1 +(Special maps can be de\214ned using the line:)127 419.6 Q +(Kmapname mapclass ar)142 435.8 Q(guments)-.18 E(The)102 452 Q F3 +(mapname)2.75 E F1 .251 +(is the handle by which this map is referenced in the re)2.75 F .251 +(writing rules.)-.25 F(The)5.251 E F3(mapclass)2.751 E F1(is)2.751 E +1.889(the name of a type of map; these are compiled in to)102 464 R F3 +(sendmail)4.389 E F1 6.888(.T)C(he)-6.888 E F3(ar)4.388 E(guments)-.37 E +F1 1.888(are interpreted)4.388 F .79(depending on the class; typically) +102 476 R 3.29(,t)-.65 G .791(here w)-3.29 F .791(ould be a single ar) +-.1 F .791(gument naming the \214le containing the)-.18 F(map.)102 488 Q +(Maps are referenced using the syntax:)127 504.2 Q($\()142 520.4 Q F3 +(map k)2.5 E -.3(ey)-.1 G F1($@)2.8 E F3(ar)2.5 E(guments)-.37 E F1($:) +2.5 E F3(default)2.5 E F1($\))2.5 E .641(where either or both of the)102 +536.6 R F3(ar)3.141 E(guments)-.37 E F1(or)3.141 E F3(default)3.141 E F1 +.64(portion may be omitted.)3.141 F(The)5.64 E F3 .64($@ ar)3.14 F +(guments)-.37 E F1(may)3.14 E 1.276(appear more than once.)102 548.6 R +1.276(The indicated)6.276 F F3 -.1(ke)3.776 G(y)-.2 E F1(and)3.776 E F3 +(ar)3.776 E(guments)-.37 E F1 1.277 +(are passed to the appropriate mapping)3.777 F 3.253(function. If)102 +560.6 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 +F3(default)3.253 E F1(is)3.253 E(speci\214ed, the)102 572.6 Q F3 +(default)2.5 E F1(replaces the input.)2.5 E +(Otherwise, the input is unchanged.)5 E(The)127 588.8 Q F3(ar)4.063 E +(guments)-.37 E F1 1.563(are passed to the map for arbitrary use.)4.063 +F 1.564(Most map classes can interpolate)6.564 F .883(these ar)102 600.8 +R .883(guments into their v)-.18 F .883(alues using the syntax \231%) +-.25 F F3(n)A F1 3.382<9a28>C(where)-3.382 E F3(n)3.382 E F1 .882 +(is a digit\) to indicate the corre-)3.382 F(sponding)102 612.8 Q F3(ar) +2.5 E(gument)-.37 E F1 5(.A)C -.18(rg)-5 G +(ument \231%0\232 indicates the database k).18 E -.15(ey)-.1 G 5(.F)-.5 +G(or e)-5.15 E(xample, the rule)-.15 E(R$\255 ! $+)142 629 Q +($: $\(uucp $1 $@ $2 $: %1 @ %0 . UUCP $\))71.72 E 1.269(Looks up the U\ +UCP name in a \(user de\214ned\) UUCP map; if not found it turns it int\ +o \231.UUCP\232)102 645.2 R 2.5(form. The)102 657.2 R +(database might contain records lik)2.5 E(e:)-.1 E .32 LW 76 669.2 72 +669.2 DL 80 669.2 76 669.2 DL 84 669.2 80 669.2 DL 88 669.2 84 669.2 DL +92 669.2 88 669.2 DL 96 669.2 92 669.2 DL 100 669.2 96 669.2 DL 104 +669.2 100 669.2 DL 108 669.2 104 669.2 DL 112 669.2 108 669.2 DL 116 +669.2 112 669.2 DL 120 669.2 116 669.2 DL 124 669.2 120 669.2 DL 128 +669.2 124 669.2 DL 132 669.2 128 669.2 DL 136 669.2 132 669.2 DL 140 +669.2 136 669.2 DL 144 669.2 140 669.2 DL 148 669.2 144 669.2 DL 152 +669.2 148 669.2 DL 156 669.2 152 669.2 DL 160 669.2 156 669.2 DL 164 +669.2 160 669.2 DL 168 669.2 164 669.2 DL 172 669.2 168 669.2 DL 176 +669.2 172 669.2 DL 180 669.2 176 669.2 DL 184 669.2 180 669.2 DL 188 +669.2 184 669.2 DL 192 669.2 188 669.2 DL 196 669.2 192 669.2 DL 200 +669.2 196 669.2 DL 204 669.2 200 669.2 DL 208 669.2 204 669.2 DL 212 +669.2 208 669.2 DL 216 669.2 212 669.2 DL/F5 5/Times-Roman@0 SF(23)93.6 +679.6 Q/F6 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/F7 8/Times-Italic@0 SF(setvendor) +2.214 E F6(in)2.214 E F7(conf)72 692.4 Q(.c)-.12 E F6 4(.P)C +(lease send e-mail to sendmail@Sendmail.ORG to re)-4 E(gister your v) +-.12 E(endor dialect.)-.12 E EP +%%Page: 63 59 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-63)195.86 E/F1 10/Times-Roman@0 SF(decv)142 96 Q 77.43 +(ax %1@%0.DEC.COM)-.25 F 72.19(research %1@%0.A)142 108 R(TT)-1.11 E +(.COM)-.74 E(Note that)102 124.2 Q/F2 10/Times-Italic@0 SF(default)2.5 E +F1(clauses ne)2.5 E -.15(ve)-.25 G 2.5(rd).15 G 2.5(ot)-2.5 G +(his mapping.)-2.5 E .742(The b)127 140.4 R .741(uilt in map with both \ +name and class \231host\232 is the host name canonicalization lookup.) +-.2 F(Thus, the syntax:)102 152.4 Q($\(host)142 168.6 Q F2(hostname)2.5 +E F1($\))A(is equi)102 184.8 Q -.25(va)-.25 G(lent to:).25 E($[)142 201 +Q F2(hostname)A F1($])A(There are man)127 221.4 Q 2.5(yd)-.15 G +(e\214ned classes.)-2.5 E 51.72(dbm Database)102 237.6 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 249.6 Q F1 +(de\214ned.)2.5 E 49.51(btree Database)102 265.8 R .678 +(lookups using the btree interf)3.178 F .677(ace to the Berk)-.1 F(ele) +-.1 E 3.177(yD)-.15 G 3.177(Bl)-3.177 G(ibrary)-3.177 E(.)-.65 E F2 +(Sendmail)5.677 E F1(must be compiled with)174 277.8 Q F0(NEWDB)2.5 E F1 +(de\214ned.)2.5 E 51.17(hash Database)102 294 R .828 +(lookups using the hash interf)3.328 F .828(ace to the Berk)-.1 F(ele) +-.1 E 3.328(yD)-.15 G 3.329(Bl)-3.328 G(ibrary)-3.329 E(.)-.65 E F2 +(Sendmail)5.829 E F1(must be compiled with)174 306 Q F0(NEWDB)2.5 E F1 +(de\214ned.)2.5 E 57.83(nis NIS)102 322.2 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 338.4 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 350.4 R +F02.995 E F1(and)2.995 E F02.995 E F1 .495(\215ags may be) +2.995 F(used to set the k)174 362.4 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 378.6 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 52.28 +(ldap LD)102 394.8 R 1.784(AP X500 directory lookups.)-.4 F F2(Sendmail) +6.783 E F1 1.783(must be compiled with)4.283 F F0(LD)4.283 E(APMAP)-.35 +E F1 2.965(de\214ned. The)174 406.8 R .465 +(map supports most of the standard ar)2.965 F .466 +(guments and most of the com-)-.18 F .3(mand line ar)174 418.8 R .3 +(guments of the)-.18 F F2(ldapsear)2.8 E -.15(ch)-.37 G F1 2.8 +(program. Note)2.95 F .3(that, by def)2.8 F .3(ault, if a single)-.1 F +.628(query matches multiple v)174 430.8 R .628 +(alues, only the \214rst v)-.25 F .629(alue will be returned unless the) +-.25 F F03.129 E F1(\(v)174 442.8 Q .249 +(alue separator\) map \215ag is set.)-.25 F .249(Also, the)5.249 F F0 +2.749 E F1 .248(map \215ag will treat a multiple v)2.749 F(alue) +-.25 E(return as if there were no matches.)174 454.8 Q 41.17 +(netinfo NeXT)102 471 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 +487.2 Q 54.65(xt T)-.15 F -.15(ex)-.7 G 2.917<748c>.15 G .417 +(le lookups.)-2.917 F .417(The format of the te)5.417 F .418 +(xt \214le is de\214ned by the)-.15 F F02.918 E F1(\(k)2.918 E +.718 -.15(ey \214)-.1 H .418(eld num-).15 F(ber\),)174 499.2 Q F0 +2.5 E F1(\(v)2.5 E(alue \214eld number\), and)-.25 E F02.5 E F1 +(\(\214eld delimiter\) \215ags.)2.5 E 59.5(ph PH)102 515.4 R 1.394 +(query map.)3.894 F(Contrib)6.394 E 1.394 +(uted and supported by Mark Roth, roth@uiuc.edu.)-.2 F -.15(Fo)6.394 G +(r).15 E 4.45(more information, consult the web site \231http://www-wsg\ +.cso.uiuc.edu/send-)174 527.4 R(mail/sendmail-phmap/\232.)174 539.4 Q +55.61(nsd nsd)102 555.6 R 1.599(map for IRIX 6.5 and later)4.1 F 6.599 +(.C)-.55 G(ontrib)-6.599 E 1.599(uted and supported by Bob Mende of)-.2 +F(SGI, mende@sgi.com.)174 567.6 Q 53.39(stab Internal)102 583.8 R +(symbol table lookups.)2.5 E(Used internally for aliasing.)5 E 38.38 +(implicit Really)102 600 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 612 Q +(ault if no class is speci\214ed for alias \214les.)-.1 E 52.84 +(user Looks)102 628.2 R .477(up users using)2.977 F F2 -.1(ge)2.977 G +(tpwnam).1 E F1 2.977(\(3\). The)B F02.977 E F1 .476 +(\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 640.2 R +.142(xistence of)-.15 F 2.5(au)174 652.2 S(ser\).)-2.5 E 52.83 +(host Canoni\214es)102 668.4 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)-2.7 F .2 +(er to \214nd)-.15 F(the canonical name for that host.)174 680.4 Q 40.61 +(bestmx Returns)102 696.6 R 2.478(the best MX record for a host name gi) +4.978 F -.15(ve)-.25 G 4.979(na).15 G 4.979(st)-4.979 G 2.479(he k) +-4.979 F -.15(ey)-.1 G 7.479(.T)-.5 G 2.479(he current)-7.479 F .722 +(machine is al)174 708.6 R -.1(wa)-.1 G .721 +(ys preferred \212 that is, if the current machine is one of the hosts) +.1 F .218(listed as a lo)174 720.6 R .219 +(west-preference MX record, then it will be guaranteed to be returned.) +-.25 F EP +%%Page: 64 60 +%%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 .961 +(This can be used to \214nd out if this machine is the tar)174 96 R .961 +(get for an MX record, and)-.18 F .313 +(mail can be accepted on that basis.)174 108 R .313(If the)5.313 F F0 +2.813 E F1 .313(\215ag is gi)2.813 F -.15(ve)-.25 G .313 +(n, then all MX names are).15 F(returned, separated by the gi)174 120 Q +-.15(ve)-.25 G 2.5(nd).15 G(elimiter)-2.5 E(.)-.55 E 32.85(sequence The) +102 136.2 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 148.2 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)-5.589 F(xample,)-.15 E +(if the k)174 160.2 Q .3 -.15(ey d)-.1 H(e\214nition is:).15 E +(Kmap1 ...)214 176.4 Q(Kmap2 ...)214 188.4 Q(Kseqmap sequence map1 map2) +214 200.4 Q .968(then a lookup ag)174 216.6 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 228.6 Q 5(.O)-.65 +G(therwise, the same k)-5 E .3 -.15(ey i)-.1 H 2.5(su).15 G +(sed for map2.)-2.5 E 43.94(syslog the)102 244.8 R -.1(ke)2.5 G 2.5(yi) +-.05 G 2.5(sl)-2.5 G(ogged via)-2.5 E/F2 10/Times-Italic@0 SF(syslo)2.5 +E(gd)-.1 E F1 2.5(\(8\). The)1.666 F(lookup returns the empty string.) +2.5 E 43.39(switch Much)102 261 R(lik)2.8 E 2.8(et)-.1 G .3 +(he \231sequence\232 map e)-2.8 F .301 +(xcept that the order of maps is determined by the)-.15 F .392 +(service switch.)174 273 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 285 R 3.993(wm)-.25 G(ap)-3.993 E 2.5(names. F)174 297 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 313.2 Q +(together with the service switch entry:)174 329.4 Q 78.84(aliases nis) +214 345.6 R(\214les)2.5 E 1.633(This causes a query ag)174 361.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 373.8 Q(.)-.55 E 37.84 +(dequote Strip)102 390 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 402 R .172 +(ould contain unscannable syntax \(that is, basic)-.1 F .386(errors lik) +174 414 R 2.886(eu)-.1 G .386(nbalanced angle brack)-2.886 F .386 +(ets; more sophisticated errors such as unkno)-.1 F(wn)-.25 E .252 +(hosts are not check)174 426 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 438 Q +("49ers::ubell")214 454.2 Q 2.5(At)174 470.4 S +(ypical usage is probably something lik)-2.5 E(e:)-.1 E +(Kdequote dequote)214 486.6 Q(...)214 510.6 Q 88.19(R$\255 $:)214 534.6 +R($\(dequote $1 $\))2.5 E(R$\255 $+)214 546.6 Q($: $>3 $1 $2)77.55 E +(Care must be tak)174 562.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 579 Q 1.31(will ha)174 595.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 +607.2 S(rtunately these cases are rare.).15 E(re)102 623.4 Q(ge)-.15 E +50.09(xT)-.15 G .489(he map de\214nition on the)-50.09 F F0(K)2.989 E F1 +.489(line contains a re)2.989 F .488(gular e)-.15 F 2.988(xpression. An) +-.15 F 2.988(yk)-.15 G .788 -.15(ey i)-3.088 H .488(nput is).15 F 1.454 +(compared to that e)174 635.4 R 1.454(xpression using the POSIX re)-.15 +F 1.454(gular e)-.15 F 1.454(xpressions routines re)-.15 F(g-)-.15 E +.291(comp\(\), re)174 647.4 R .291(gerr\(\), and re)-.15 F(ge)-.15 E +-.15(xe)-.15 G 2.791(c\(\). Refer).15 F .291 +(to the documentation for those routines for)2.791 F .355 +(more information about the re)174 659.4 R .355(gular e)-.15 F .355 +(xpression matching.)-.15 F .356(No re)5.356 F .356(writing of the k) +-.25 F -.15(ey)-.1 G .075(is done if the)174 671.4 R F02.575 E F1 +.075(\215ag is used.)2.575 F -.4(Wi)5.075 G .075(thout it, the k).4 F +.374 -.15(ey i)-.1 H 2.574(sd).15 G .074(iscarded or if)-2.574 F F0 +2.574 E F1 .074(if used, it is)2.574 F .905 +(substituted by the substring matches, delimited by)174 683.4 R F0($|) +3.405 E F1 .905(or the string speci\214ed with)3.405 F(the the)174 695.4 +Q F02.5 E F1 2.5(\215ag. The)2.5 F(\215ags a)2.5 E -.25(va)-.2 G +(ilable for the map are).25 E EP +%%Page: 65 61 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-65)195.86 E/F1 10/Times-Roman@0 SF 97.17(-n not)214 96 R 98.84 +(-f case)214 108 R(sensiti)2.5 E -.15(ve)-.25 G 97.17(-b basic)214 120 R +(re)2.5 E(gular e)-.15 E(xpressions)-.15 E(\(def)322 132 Q(ault is e)-.1 +E(xtended\))-.15 E 98.28(-s substring)214 144 R(match)2.5 E 97.17 +(-d set)214 156 R(the delimiter used for -s)2.5 E 97.73(-a append)214 +168 R(string to k)2.5 E -.15(ey)-.1 G 94.39(-m match)214 180 R(only)2.5 +E 2.5(,d)-.65 G 2.5(on)-2.5 G(ot)-2.5 E(replace/discard v)322 192 Q +(alue)-.25 E 94.95(-D perform)214 204 R(no lookup in deferred deli)2.5 E +-.15(ve)-.25 G(ry mode.).15 E(The)174 220.2 Q F02.551 E F1 .051(\ +\215ag can include an optional parameter which can be used to select th\ +e sub-)2.551 F(strings in the result of the lookup.)174 232.2 Q -.15(Fo) +5 G 2.5(re).15 G(xample,)-2.65 E(-s1,3,4)214 248.4 Q 35.62(program The) +102 268.8 R(ar)2.544 E .044(guments on the)-.18 F F0(K)2.544 E F1 .045 +(line are the pathname to a program and an)2.544 F 2.545(yi)-.15 G .045 +(nitial param-)-2.545 F .176(eters to be passed.)174 280.8 R .176 +(When the map is called, the k)5.176 F .475 -.15(ey i)-.1 H 2.675(sa).15 +G .175(dded to the initial parame-)-2.675 F .112 +(ters and the program is in)174 292.8 R -.2(vo)-.4 G -.1(ke).2 G 2.612 +(da).1 G 2.612(st)-2.612 G .112(he def)-2.612 F .112 +(ault user/group id.)-.1 F .112(The \214rst line of stan-)5.112 F .508 +(dard output is returned as the v)174 304.8 R .508(alue of the lookup.) +-.25 F .508(This has man)5.508 F 3.007(yp)-.15 G .507(otential secu-) +-3.007 F 1.277(rity problems, and has terrible performance; it should b\ +e used only when abso-)174 316.8 R(lutely necessary)174 328.8 Q(.)-.65 E +44.51(macro Set)102 345 R .32(or clear a macro v)2.82 F 2.82(alue. T) +-.25 F 2.82(os)-.8 G .32(et a macro, pass the v)-2.82 F .32 +(alue as the \214rst ar)-.25 F .32(gument in)-.18 F .938 +(the map lookup.)174 357 R 2.538 -.8(To c)5.938 H .939 +(lear a macro, do not pass an ar).8 F .939(gument in the map lookup.) +-.18 F(The map al)174 369 Q -.1(wa)-.1 G(ys returns the empty string.).1 +E(Example of typical usage include:)5 E(Kstorage macro)214 385.2 Q(...) +214 409.2 Q 2.5(#s)214 433.2 S(et macro ${MyMacro} to the ruleset match) +-2.5 E 88.19(R$+ $:)214 445.2 R($\(storage {MyMacro} $@ $1 $\) $1)2.5 E +2.5(#s)214 457.2 S(et macro ${MyMacro} to an empty string)-2.5 E 88.83 +(R$* $:)214 469.2 R($\(storage {MyMacro} $@ $\) $1)2.5 E 2.5(#c)214 +481.2 S(lear macro ${MyMacro})-2.5 E 88.19(R$\255 $:)214 493.2 R +($\(storage {MyMacro} $\) $1)2.5 E 51.17(arith Perform)102 513.6 R .494 +(simple arithmetic operations.)2.994 F .494(The operation is gi)5.494 F +-.15(ve)-.25 G 2.993(na).15 G 2.993(sk)-2.993 G -.15(ey)-3.093 G 2.993 +(,c)-.5 G .493(urrently +,)-2.993 F .383 +(-, *, /, l \(for less than\), and = are supported.)174 525.6 R .383 +(The tw)5.383 F 2.883(oo)-.1 G .383(perands are gi)-2.883 F -.15(ve)-.25 +G 2.883(na).15 G 2.883(sa)-2.883 G -.18(rg)-2.883 G(u-).18 E 2.911 +(ments. The)174 537.6 R .41 +(lookup returns the result of the computation, i.e.)2.911 F/F2 9 +/Times-Roman@0 SF(TR)5.41 E(UE)-.36 E F1(or)2.91 E F2 -.666(FA)2.91 G +(LSE).666 E F1(for)2.91 E 1.072(comparisons, inte)174 549.6 R 1.072 +(ger v)-.15 F 1.072(alues otherwise.)-.25 F 1.072 +(All options which are possible for maps)6.072 F(are ignored.)174 561.6 +Q 2.5(As)5 G(imple e)-2.5 E(xample is:)-.15 E(Kcomp arith)214 577.8 Q +(...)214 601.8 Q(Scheck_etrn)214 625.8 Q 88.83(R$* $:)214 637.8 R +($\(comp l $@ $&{load_a)2.5 E(vg} $@ 7 $\) $1)-.2 E(RF)214 649.8 Q 69.01 +(ALSE $#)-.74 F(error ...)2.5 E .488(Most of these accept as ar)127 +670.2 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 tha\ +t \231.db\232 or some other e)102 682.2 R .31(xtension appropriate)-.15 +F +(for the database type will be added to get the actual database name\).) +102 694.2 Q(Kno)5 E(wn \215ags are:)-.25 E 58.86(\255o Indicates)102 +710.4 R 1.147(that this map is optional \212 that is, if it cannot be o\ +pened, no error is)3.648 F(produced, and)174 722.4 Q/F3 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)-2.5 G(he map e)-2.5 E(xisted b)-.15 E(ut w)-.2 E +(as empty)-.1 E(.)-.65 E EP +%%Page: 66 62 +%%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 +(\255N, \255O)102 96 Q .696(If neither)41.28 F F03.197 E F1(or) +3.197 E F03.197 E F1 .697(are speci\214ed,)3.197 F/F2 10 +/Times-Italic@0 SF(sendmail)3.197 E F1 .697(uses an adapti)3.197 F .997 +-.15(ve a)-.25 H .697(lgorithm to decide).15 F .108 +(whether or not to look for null bytes on the end of k)174 108 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 120 R 3.319(yk)-.15 G 1.119 -.15(ey w)-3.419 H .819 +(ith a null byte it ne).15 F -.15(ve)-.25 G 3.319(rt).15 G .82(ries ag) +-3.319 F .82(ain without a null byte and vice)-.05 F -.15(ve)174 132 S +2.828(rsa. If).15 F F02.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) +-2.828 F F02.827 E F1 .327(is speci\214ed it)2.827 F(ne)174 144 Q +-.15(ve)-.25 G 2.886(rt).15 G .386(ries with a null byte.)-2.886 F .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 156 Q 5.546(.I)-.65 G 3.046(fb) +-5.546 G(oth)-3.046 E F03.046 E F1(and)3.046 E F03.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)-3.045 F 3.045(ym)-.15 G +(atches)-3.045 E(at all \212 that is, e)174 168 Q -.15(ve)-.25 G +(rything will appear to f).15 E(ail.)-.1 E102 184.2 Q F2(x)A F1 +1.356(Append the string)57.48 F 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)-4.007 F(ault)-.1 E F2(host)3.857 E F1(map)3.857 E +(appends a dot on successful matches.)174 196.2 Q102 212.4 Q F2(x) +A F1 .021(Append the string)55.81 F F2(x)2.521 E F1 .021(on temporary f) +2.521 F 2.521(ailures. F)-.1 F .021(or e)-.15 F(xample,)-.15 E F2(x) +2.521 E F1 -.1(wo)2.521 G .02(uld be appended if a).1 F .72 +(DNS lookup returned \231serv)174 224.4 R .72(er f)-.15 F .72 +(ailed\232 or an NIS lookup could not locate a serv)-.1 F(er)-.15 E(.) +-.55 E(See also the)174 236.4 Q F02.5 E F1(\215ag.)2.5 E 60.53 +(\255f Do)102 252.6 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 268.8 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 280.8 S 5.107 -.15(ey a)-7.406 H 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 292.8 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 304.8 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 316.8 Q(en if the match f)-.1 E(ails.)-.1 E102 333 +Q F2 -.1(ke)C(ycol)-.2 E F1 .52(The k)36.22 F .82 -.15(ey c)-.1 H .519 +(olumn name \(for NIS+\) or number \(for te).15 F .519(xt lookups\).) +-.15 F -.15(Fo)5.519 G 3.019(rL).15 G -.4(DA)-3.019 G 3.019(Pm).4 G(aps) +-3.019 E .972(this is an LD)174 345 R .973(AP \214lter string in which \ +%s is replaced with the literal contents of)-.4 F .249(the lookup k)174 +357 R .549 -.15(ey a)-.1 H .249(nd %0 is replaced with the LD).15 F .248 +(AP escaped contents of the lookup)-.4 F -.1(ke)174 369 S 2.5(ya)-.05 G +(ccording to RFC2254.)-2.5 E102 385.2 Q F2(valcol)A F1 1.928 +(The v)36.92 F 1.928(alue column name \(for NIS+\) or number \(for te) +-.25 F 1.929(xt lookups\).)-.15 F -.15(Fo)6.929 G 4.429(rL).15 G -.4(DA) +-4.429 G(P).4 E .467(maps this is the name of one or more attrib)174 +397.2 R .467(utes to be returned; multiple attrib)-.2 F(utes)-.2 E 1.216 +(can be separated by commas.)174 409.2 R 1.216 +(If not speci\214ed, all attrib)6.216 F 1.216(utes found in the match) +-.2 F(will be returned.)174 421.2 Q102 437.4 Q F2(delim)A F1 .219 +(The column delimiter \(for te)39.7 F .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 449.4 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)-6.826 G(mitted)-4.326 E +(entirely)174 461.4 Q 3.891(,t)-.65 G 1.391(he column separator is an) +-3.891 F 3.891(ys)-.15 G 1.391(equence of whitespace.)-3.891 F -.15(Fo) +6.391 G 3.891(rL).15 G -.4(DA)-3.891 G 3.89(Pm).4 G(aps)-3.89 E 2.061 +(this is the separator character to combine multiple v)174 473.4 R 2.062 +(alues into a single return)-.25 F 2.5(string. If)174 485.4 R +(not set, the LD)2.5 E +(AP lookup will only return the \214rst match found.)-.4 E 61.08 +(\255t Normally)102 501.6 R 2.727(,w)-.65 G .227 +(hen a map attempts to do a lookup and the serv)-2.727 F .226(er f)-.15 +F .226(ails \(e.g.,)-.1 F F2(sendmail)2.726 E F1(couldn')174 513.6 Q +2.776(tc)-.18 G .276(ontact an)-2.776 F 2.776(yn)-.15 G .276(ame serv) +-2.776 F .276(er; this is)-.15 F F2(not)2.776 E F1 .276 +(the same as an entry not being found)2.776 F .251(in the map\), the me\ +ssage being processed is queued for future processing.)174 525.6 R(The) +5.25 E F02.75 E F1 2.039(\215ag turns of)174 537.6 R 4.539(ft)-.25 +G 2.039(his beha)-4.539 F(vior)-.2 E 4.539(,l)-.4 G 2.039 +(etting the temporary f)-4.539 F 2.039(ailure \(serv)-.1 F 2.039(er do) +-.15 F 2.04(wn\) act as)-.25 F .676(though it were a permanent f)174 +549.6 R .675(ailure \(entry not found\).)-.1 F .675 +(It is particularly useful for)5.675 F .772 +(DNS lookups, where someone else')174 561.6 R 3.272(sm)-.55 G .772 +(iscon\214gured name serv)-3.272 F .772(er can cause prob-)-.15 F 1.646 +(lems on your machine.)174 573.6 R(Ho)6.646 E(we)-.25 E -.15(ve)-.25 G +2.446 -.4(r, c).15 H 1.645(are must be tak).4 F 1.645 +(en to ensure that you don')-.1 F(t)-.18 E .262(bounce mail that w)174 +585.6 R .262(ould be resolv)-.1 F .262(ed correctly if you tried ag)-.15 +F 2.763(ain. A)-.05 F .263(common strat-)2.763 F -.15(eg)174 597.6 S 2.5 +(yi).15 G 2.5(st)-2.5 G 2.5(of)-2.5 G(orw)-2.5 E +(ard such mail to another)-.1 E 2.5(,p)-.4 G +(ossibly better connected, mail serv)-2.5 E(er)-.15 E(.)-.55 E 56.64 +(\255D Perform)102 613.8 R .833(no lookup in deferred deli)3.333 F -.15 +(ve)-.25 G .833(ry mode.).15 F .833(This \215ag is set by def)5.833 F +.832(ault for the)-.1 F F2(host)174 625.8 Q F1(map.)2.5 E102 642 Q +F2(spacesub)A F1 1.537(The character to use to replace space characters\ + after a successful map lookup)24.14 F(\(esp. useful for re)174 654 Q +(ge)-.15 E 2.5(xa)-.15 G(nd syslog maps\).)-2.5 E102 670.2 Q F2 +(spacesub)A F1 -.15(Fo)25.81 G 3.101(rt).15 G .601(he dequote map only) +-3.101 F 3.101(,t)-.65 G .601 +(he character to use to replace space characters after a)-3.101 F +(successful dequote.)174 682.2 Q 58.86(\255q Don')102 698.4 R 2.5(td) +-.18 G(equote the k)-2.5 E .3 -.15(ey b)-.1 H(efore lookup.).15 E EP +%%Page: 67 63 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-67)195.86 E/F1 10/Times-Roman@0 SF102 96 Q/F2 10 +/Times-Italic@0 SF(le)A(vel)-.15 E F1 -.15(Fo)41.52 G 2.5(rt).15 G +(he syslog map only)-2.5 E 2.5(,i)-.65 G 2.5(ts)-2.5 G +(peci\214es the le)-2.5 E -.15(ve)-.25 G 2.5(lt).15 G 2.5(ou)-2.5 G +(se for the syslog call.)-2.5 E 56.64(\255A When)102 112.2 R(reb)3 E .5 +(uilding an alias \214le, the)-.2 F F03 E F1 .5 +(\215ag causes duplicate entries in the te)3 F .5(xt v)-.15 F(er)-.15 E +(-)-.2 E(sion to be mer)174 124.2 Q 2.5(ged. F)-.18 F(or e)-.15 E +(xample, tw)-.15 E 2.5(oe)-.1 G(ntries:)-2.5 E 90.49(list: user1,)214 +140.4 R(user2)2.5 E 90.49(list: user3)214 152.4 R -.1(wo)174 168.6 S +(uld be treated as though it were the single entry).1 E 90.49 +(list: user1,)214 184.8 R(user2, user3)2.5 E(in the presence of the)174 +201 Q F02.5 E F1(\215ag.)2.5 E(The follo)127 217.2 Q +(wing additional \215ags are present in the ldap map only:)-.25 E 57.19 +(\255R Do)102 233.4 R .025(not auto chase referrals.)2.525 F .025 +(sendmail must be compiled with)5.025 F F0(\255DLD)2.525 E(AP_REFER-) +-.35 E(RALS)174 245.4 Q F1(to use this \215ag.)2.5 E 58.86(\255n Retrie) +102 261.6 R .3 -.15(ve a)-.25 H(ttrib).15 E(ute names only)-.2 E(.)-.65 +E102 277.8 Q F2(der)A(ef)-.37 E F1 +(Set the alias dereference option to one of ne)42.85 E -.15(ve)-.25 G .8 +-.4(r, a).15 H -.1(lwa).4 G(ys, search, or \214nd.).1 E102 294 Q +F2(scope)A F1(Set search scope to one of base, one \(one le)39.7 E -.15 +(ve)-.25 G(l\), or sub \(subtree\).).15 E102 310.2 Q F2(host)A F1 +(LD)44.69 E(AP serv)-.4 E(er hostname.)-.15 E102 326.4 Q F2(base)A +F1(LD)43.03 E(AP search base.)-.4 E102 342.6 Q F2(port)A F1(LD) +44.69 E(AP service port.)-.4 E102 358.8 Q F2(timelimit)A F1 -.35 +(Ti)28.02 G(me limit for LD).35 E(AP queries.)-.4 E102 375 Q F2 +(sizelimit)A F1(Size \(number of matches\) limit for LD)26.91 E +(AP queries.)-.4 E102 391.2 Q F2(distinguished_name)A F1 +(The distinguished name to use to login to the LD)174 403.2 Q(AP serv) +-.4 E(er)-.15 E(.)-.55 E102 419.4 Q F2(method)A F1 5.987 +(The method to authenticate to the LD)28.03 F 5.987(AP serv)-.4 F(er) +-.15 E 10.987(.S)-.55 G 5.988(hould be one of)-10.987 F F0(LD)174 431.4 +Q(AP_A)-.35 E(UTH_NONE)-.5 E F1(,)A F0(LD)2.5 E(AP_A)-.35 E(UTH_SIMPLE) +-.5 E F1 2.5(,o)C(r)-2.5 E F0(LD)2.5 E(AP_A)-.35 E(UTH_KRBV4)-.5 E F1(.) +A102 447.6 Q F2(passwor)A(d\214le)-.37 E F1 .342 +(The \214le containing the secret k)10.61 F .642 -.15(ey f)-.1 H .342 +(or the).15 F F0(LD)2.842 E(AP_A)-.35 E(UTH_SIMPLE)-.5 E F1 +(authentication)2.842 E(method or the name of the K)174 459.6 Q +(erberos tick)-.25 E(et \214le for)-.1 E F0(LD)2.5 E(AP_A)-.35 E +(UTH_KRBV4)-.5 E F1(.)A 58.86(\2551 F)102 475.8 R .457(orce LD)-.15 F +.458(AP searches to only succeed if a single match is found.)-.4 F .458 +(If multiple v)5.458 F(al-)-.25 E +(ues are found, the search is treated as if no match w)174 487.8 Q +(as found.)-.1 E(The)127 504 Q F2(dbm)2.99 E F1 .489 +(map appends the strings \231.pag\232 and \231.dir\232 to the gi)2.99 F +-.15(ve)-.25 G 2.989<6e8c>.15 G .489(lename; the)-2.989 F F2(hash)2.989 +E F1(and)2.989 E F2(btr)2.989 E(ee)-.37 E F1(maps append \231.db\232.) +102 516 Q -.15(Fo)5 G 2.5(re).15 G(xample, the map speci\214cation)-2.65 +E -.15(Ku)142 532.2 S(ucp dbm \255o \255N /etc/mail/uucpmap).15 E .21(s\ +peci\214es an optional map named \231uucp\232 of class \231dbm\232; it \ +al)102 548.4 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 /etc/mail/uucpmap.{dir)102 560.4 Q +(,pag}.)-.4 E 1.095(The program)127 576.6 R F2(mak)3.595 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)-3.594 G 1.094(he three database-oriented maps.)-3.594 F(It)6.094 E +(tak)102 588.6 Q(es the follo)-.1 E(wing \215ags:)-.25 E 60.53(\255f Do) +102 604.8 R(not fold upper to lo)2.5 E(wer case in the map.)-.25 E 56.64 +(\255N Include)102 621 R(null bytes in k)2.5 E -.15(ey)-.1 G(s.).15 E +58.86(\255o Append)102 637.2 R(to an e)2.5 E(xisting \(old\) \214le.) +-.15 E 60.53(\255r Allo)102 653.4 R 3.668(wr)-.25 G 1.168 +(eplacement of e)-3.668 F 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)-3.668 F 1.168 +(xisting k)-.15 F 1.469 -.15(ey i)-.1 H 3.669(sa).15 G(n)-3.669 E(error) +174 665.4 Q(.)-.55 E 58.86(\255v Print)102 681.6 R(what is happening.) +2.5 E(The)102 697.8 Q F2(sendmail)3.606 E F1 1.106(daemon does not ha) +3.606 F 1.406 -.15(ve t)-.2 H 3.606(ob).15 G 3.606(er)-3.606 G 1.106 +(estarted to read the ne)-3.606 F 3.605(wm)-.25 G 1.105 +(aps as long as you change)-3.605 F +(them in place; \214le locking is used so that the maps w)102 709.8 Q +(on')-.1 E 2.5(tb)-.18 G 2.5(er)-2.5 G(ead while the)-2.5 E 2.5(ya)-.15 +G(re being updated.)-2.5 E EP +%%Page: 68 64 +%%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(Ne)127 96 +Q 2.5(wc)-.25 G(lasses can be added in the routine)-2.5 E 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 120 R(User Database)2.5 E F1 .108(If you ha)127 136.2 R +.408 -.15(ve a ve)-.2 H .109(rsion of).15 F/F2 10/Times-Italic@0 SF +(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 148.2 Q +(The location of this database is controlled with the)127 164.4 Q F0 +(UserDatabaseSpec)2.5 E F1(option.)2.5 E F0 2.5(5.10.1. Structur)102 +188.4 R 2.5(eo)-.18 G 2.5(ft)-2.5 G(he user database)-2.5 E F1 +(The database is a sorted \(BT)142 204.6 Q(ree-based\) structure.)-.35 E +(User records are stored with the k)5 E -.15(ey)-.1 G(:).15 E F2(user) +157 220.8 Q(-name)-.2 E F0(:)A F2(\214eld-name)A F1 .128(The sorted dat\ +abase format ensures that user records are clustered together)117 237 R +5.128(.M)-.55 G .128(eta-information is)-5.128 F(al)117 249 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 265.2 Q +2.5(alue. De\214ned)-.25 F(\214elds include:)2.5 E 33.39(maildrop The) +117 281.4 R(deli)4.872 E -.15(ve)-.25 G 2.372(ry address for this user) +.15 F 7.372(.T)-.55 G 2.373(here may be multiple v)-7.372 F 2.373 +(alues of this)-.25 F 2.675(record. In)189 293.4 R(particular)2.675 E +2.675(,m)-.4 G .175(ailing lists will ha)-2.675 F .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 305.4 Q 30.06(mailname The)117 321.6 R 1.026 +(outgoing mailname for this user)3.526 F 6.026(.F)-.55 G 1.027 +(or each outgoing name, there should)-6.176 F .08(be an appropriate)189 +333.6 R F2(maildr)2.58 E(op)-.45 E F1 .08(record for that name to allo) +2.58 F 2.58(wr)-.25 G .08(eturn mail.)-2.58 F .08(See also)5.08 F F2 +(:default:mailname)189 345.6 Q F1(.)A 25.62(mailsender Changes)117 361.8 +R(an)3.447 E 3.447(ym)-.15 G .947(ail sent to this address to ha)-3.447 +F 1.248 -.15(ve t)-.2 H .948(he indicated en).15 F -.15(ve)-.4 G .948 +(lope sender).15 F(.)-.55 E .498(This is intended for mailing lists, an\ +d will normally be the name of an appro-)189 373.8 R .754 +(priate -request address.)189 385.8 R .754(It is v)5.754 F .755 +(ery similar to the o)-.15 F(wner)-.25 E(-)-.2 E F2(list)A F1 .755 +(syntax in the alias)3.255 F(\214le.)189 397.8 Q 33.95(fullname The)117 +414 R(full name of the user)2.5 E(.)-.55 E(of)117 430.2 Q 13.66 +(\214ce-address The)-.25 F(of)2.5 E(\214ce address for this user)-.25 E +(.)-.55 E(of)117 446.4 Q 19.21(\214ce-phone The)-.25 F(of)2.5 E +(\214ce phone number for this user)-.25 E(.)-.55 E(of)117 462.6 Q +(\214ce-f)-.25 E 30.98(ax The)-.1 F(of)2.5 E(\214ce F)-.25 E +(AX number for this user)-.74 E(.)-.55 E 13.96(home-address The)117 +478.8 R(home address for this user)2.5 E(.)-.55 E 19.51(home-phone The) +117 495 R(home phone number for this user)2.5 E(.)-.55 E(home-f)117 +511.2 Q 31.28(ax The)-.1 F(home F)2.5 E(AX number for this user)-.74 E +(.)-.55 E 41.73(project A)117 527.4 R .856 +(\(short\) description of the project this person is af)3.356 F .855 +(\214liated with.)-.25 F .855(In the Uni-)5.855 F -.15(ve)189 539.4 S +(rsity this is often just the name of their graduate advisor).15 E(.) +-.55 E 52.28(plan A)117 555.6 R +(pointer to a \214le from which plan information can be g)2.5 E +(athered.)-.05 E .924(As of this writing, only a fe)142 571.8 R 3.424 +(wo)-.25 G 3.424(ft)-3.424 G .925 +(hese \214elds are actually being used by)-3.424 F F2(sendmail)3.425 E +F1(:)A F2(mail-)3.425 E(dr)117 583.8 Q(op)-.45 E F1(and)2.5 E F2 +(mailname)2.5 E F1 5(.A)C F2(\214ng)-2.5 E(er)-.1 E F1 +(program that uses the other \214elds is planned.)2.5 E F0 2.5 +(5.10.2. User)102 607.8 R(database semantics)2.5 E F1 .996(When the re) +142 624 R .995(writing rules submit an address to the local mailer)-.25 +F 3.495(,t)-.4 G .995(he user name is passed)-3.495 F .78 +(through the alias \214le.)117 636 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 648 R +2.077 -.15(ey i)-.1 H 4.277(nt).15 G 1.777(he user database.)-4.277 F +1.777(If no match)6.777 F +(occurs \(or if the maildrop points at the same address\), forw)117 660 +Q(arding is tried.)-.1 E .55(If the \214rst tok)142 676.2 R .551(en of \ +the user name returned by ruleset 0 is an \231@\232 sign, the user data\ +base)-.1 F .626(lookup is skipped.)117 688.2 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 700.2 R 1.533 +(vision\); mail sent to a speci\214c machine should ignore)-.25 F +(these def)117 712.2 Q(aults.)-.1 E EP +%%Page: 69 65 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-69)195.86 E/F1 10/Times-Roman@0 SF .351 +(When mail is sent, the name of the sending user is look)142 96 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 108 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)-2.691 F(might ha)117 120 Q .3 +-.15(ve a r)-.2 H(ecord:).15 E 48.29(eric:mailname Eric.Allman@CS.Berk) +157 136.2 R(ele)-.1 E -.65(y.)-.15 G(EDU).65 E(This w)117 152.4 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 168.6 R 3.019(,b)-.4 G +.519(ut no corresponding \231mailname\232 record e)-3.219 F .519 +(xists, the)-.15 F 1.127(record \231:def)117 180.6 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 192.6 R -.15(Fo)5.625 G 3.125 +(re).15 G .625(xample, in our case we w)-3.275 F .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 204.6 Q +.881(yone kno)-.15 F .882(wn in the database gets their outgoing mail s\ +tamped as \231user@CS.Berk)-.25 F(ele)-.1 E -.65(y.)-.15 G(EDU\232,).65 +E -.2(bu)117 216.6 S 2.5(tp).2 G +(eople not listed in the database use the local hostname.)-2.5 E F0 2.5 +(5.10.3. Cr)102 242.6 R(eating the database)-.18 E/F2 7/Times-Bold@0 SF +(24)-4 I F1 .375(The user database is b)142 258.8 R .375(uilt from a te) +-.2 F .375(xt \214le using the)-.15 F/F3 10/Times-Italic@0 SF(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 270.8 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 282.8 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)-4.089 G 1.589 +(ys in the format).1 F(described abo)117 294.8 Q .3 -.15(ve \212 f)-.15 +H(or e).15 E(xample:)-.15 E(eric:maildrop)157 311 Q 3.984 +(This \214le is normally installed in a system directory; for e)117 +327.2 R 3.984(xample, it might be called)-.15 F F3(/etc/mail/user)117 +339.2 Q(db)-.37 E F1 5(.T)C 2.5(om)-5.8 G(ak)-2.5 E 2.5(et)-.1 G +(he database v)-2.5 E(ersion of the map, run the program:)-.15 E(mak)157 +355.4 Q(emap btree /etc/mail/userdb < /etc/mail/userdb)-.1 E .077 +(Then create a con\214g \214le that uses this.)117 371.6 R -.15(Fo)5.077 +G 2.577(re).15 G .077 +(xample, using the V8 M4 con\214guration, include the)-2.727 F(follo)117 +383.6 Q(wing line in your .mc \214le:)-.25 E +(de\214ne\(\222confUSERDB_SPEC\264, /etc/mail/userdb)157 399.8 Q(.db\)) +-.4 E F0 2.5(6. O)72 428 R(THER CONFIGURA)-.4 E(TION)-.95 E F1 .907 +(There are some con\214guration changes that can be made by recompiling) +112 444.2 R F3(sendmail)3.407 E F1 5.907(.T)C .906(his section)-5.907 F +1.139(describes what changes can be made and what has to be modi\214ed \ +to mak)87 456.2 R 3.639(et)-.1 G 3.639(hem. In)-3.639 F 1.139 +(most cases this)3.639 F(should be unnecessary unless you are porting)87 +468.2 Q F3(sendmail)2.5 E F1(to a ne)2.5 E 2.5(we)-.25 G -.4(nv)-2.5 G +(ironment.).4 E F0 2.5(6.1. P)87 492.2 R(arameters in de)-.1 E +(vtools/OS/$oscf)-.15 E F1 .92 +(These parameters are intended to describe the compilation en)127 508.4 +R .92(vironment, not site polic)-.4 F 2.22 -.65(y, a)-.15 H(nd).65 E +.739(should normally be de\214ned in the operating system con\214gurati\ +on \214le.)102 520.4 R F0 .74(This section needs a com-)5.739 F(plete r) +102 532.4 Q(ewrite.)-.18 E F1 39.5(NDBM If)102 548.6 R .665(set, the ne) +3.165 F 3.165(wv)-.25 G .664(ersion of the DBM library that allo)-3.315 +F .664(ws multiple databases will be)-.25 F 2.542(used. If)174 560.6 R +.042(neither NDBM nor NEWDB are set, a much less ef)2.542 F .043 +(\214cient method of alias)-.25 F(lookup is used.)174 572.6 Q 32.84 +(NEWDB If)102 588.8 R .142(set, use the ne)2.642 F 2.642(wd)-.25 G .142 +(atabase package from Berk)-2.642 F(ele)-.1 E 2.641(y\()-.15 G .141 +(from 4.4BSD\).)-2.641 F .141(This package)5.141 F .266 +(is substantially f)174 600.8 R .267(aster than DBM or NDBM.)-.1 F .267 +(If NEWDB and NDBM are both set,)5.267 F F3(sendmail)174 612.8 Q F1 +(will read DBM \214les, b)2.5 E(ut will create and use NEWDB \214les.) +-.2 E 53.39(NIS Include)102 629 R .12(support for NIS.)2.62 F .119 +(If set together with)5.119 F F3(both)2.619 E F1 .119(NEWDB and NDBM,) +2.619 F F3(sendmail)2.619 E F1 .947(will create both DBM and NEWDB \214\ +les if and only if an alias \214le includes the)174 641 R 3.409 +(substring \231/yp/\232 in the name.)174 653 R 3.409 +(This is intended for compatibility with Sun)8.409 F(Microsystems')174 +665 Q F3(mkalias)2.5 E F1(program used on YP masters.)2.5 E .32 LW 76 +674.6 72 674.6 DL 80 674.6 76 674.6 DL 84 674.6 80 674.6 DL 88 674.6 84 +674.6 DL 92 674.6 88 674.6 DL 96 674.6 92 674.6 DL 100 674.6 96 674.6 DL +104 674.6 100 674.6 DL 108 674.6 104 674.6 DL 112 674.6 108 674.6 DL 116 +674.6 112 674.6 DL 120 674.6 116 674.6 DL 124 674.6 120 674.6 DL 128 +674.6 124 674.6 DL 132 674.6 128 674.6 DL 136 674.6 132 674.6 DL 140 +674.6 136 674.6 DL 144 674.6 140 674.6 DL 148 674.6 144 674.6 DL 152 +674.6 148 674.6 DL 156 674.6 152 674.6 DL 160 674.6 156 674.6 DL 164 +674.6 160 674.6 DL 168 674.6 164 674.6 DL 172 674.6 168 674.6 DL 176 +674.6 172 674.6 DL 180 674.6 176 674.6 DL 184 674.6 180 674.6 DL 188 +674.6 184 674.6 DL 192 674.6 188 674.6 DL 196 674.6 192 674.6 DL 200 +674.6 196 674.6 DL 204 674.6 200 674.6 DL 208 674.6 204 674.6 DL 212 +674.6 208 674.6 DL 216 674.6 212 674.6 DL/F4 5/Times-Roman@0 SF(24)93.6 +685 Q/F5 8/Times-Roman@0 SF .473(These instructions are kno)3.2 J .473 +(wn to be incomplete.)-.2 F .472(Other features are a)4.473 F -.2(va) +-.16 G .472(ilable which pro).2 F .472(vide similar functionality)-.12 F +2.472(,e)-.52 G .472(.g., virtual)-2.472 F +(hosting and mapping local addresses into a generic form as e)72 697.8 Q +(xplained in cf/README.)-.12 E EP +%%Page: 70 66 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-70 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 28.94 +(NISPLUS Compile)102 96 R(in support for NIS+.)2.5 E 26.73 +(NETINFO Compile)102 112.2 R(in support for NetInfo \(NeXT stations\).) +2.5 E(LD)102 128.4 Q 22.12(APMAP Compile)-.4 F 1.225(in support for LD) +3.725 F 1.225(AP X500 queries.)-.4 F 1.226 +(Requires libldap and liblber from)6.226 F 2.799(the Umich LD)174 140.4 +R 2.798(AP 3.2 or 3.3 release or equi)-.4 F -.25(va)-.25 G 2.798 +(lent libraries for other LD).25 F(AP)-.4 E(libraries such as OpenLD)174 +152.4 Q(AP)-.4 E(.)-1.11 E 32.84(HESIOD Compile)102 168.6 R +(in support for Hesiod.)2.5 E 22.83(MAP_NSD Compile)102 184.8 R +(in support for IRIX NSD lookups.)2.5 E 9.5(MAP_REGEX Compile)102 201 R +(in support for re)2.5 E(gular e)-.15 E(xpression matching.)-.15 E 30.05 +(PH_MAP Compile)102 217.2 R(in support for ph lookups.)2.5 E 45.05 +(SASL Compile)102 233.4 R 1.474 +(in support for SASL, a required component for SMTP Authentication)3.974 +F(support.)174 245.4 Q -1.63(TCPWRAPPERS Compile)102 261.6 R +(in support for TCP Wrappers.)2.5 E(_P)102 277.8 Q -1.11(AT)-.92 G +(H_SENDMAILCF)1.11 E(The pathname of the sendmail.cf \214le.)174 289.8 Q +(_P)102 306 Q -1.11(AT)-.92 G(H_SENDMAILPID)1.11 E +(The pathname of the sendmail.pid \214le.)174 318 Q 1.44 +(There are also se)127 334.2 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 346.2 R +(the sendmail/README \214le for the latest scoop on these \215ags.)2.5 E +F0 2.5(6.2. P)87 370.2 R(arameters in sendmail/conf)-.1 E(.h)-.15 E F1 +-.15(Pa)127 386.4 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 398.4 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 410.4 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 compilati\ +on \215ags in conf.h \212 see)127 426.6 R +(sendmail/README or sendmail/conf.h itself.)102 438.6 Q(MAXLINE [2048]) +102 454.8 Q 2.069(The maximum line length of an)11.14 F 4.568(yi)-.15 G +2.068(nput line.)-4.568 F 2.068(If message lines e)7.068 F 2.068 +(xceed this)-.15 F .575(length the)188.4 466.8 R 3.075(yw)-.15 G .575 +(ill still be processed correctly; ho)-3.075 F(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 478.8 Q(MAXN)102 495 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.)-2.5 E +(MAXPV [256])102 511.2 Q .25(The maximum number of parameters to an) +26.13 F 2.75(ym)-.15 G(ailer)-2.75 E 5.25(.T)-.55 G .25 +(his limits the number of)-5.25 F .375 +(recipients that may be passed in one transaction.)188.4 523.2 R .376 +(It can be set to an)5.376 F 2.876(ya)-.15 G(rbitrary)-2.876 E .876 +(number abo)188.4 535.2 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 547.2 R 3.386(Ah)5.886 G .887 +(igher number may reduce load on your system, ho)-3.386 F(w-)-.25 E +-2.15 -.25(ev e)188.4 559.2 T -.55(r.).25 G(MAXA)102 575.4 Q -.18(TO) +-1.11 G 2.5(M[).18 G 3.26(1000] The)-2.5 F .064 +(maximum number of atoms \(tok)2.564 F .063(ens\) in a single address.) +-.1 F -.15(Fo)5.063 G 2.563(re).15 G .063(xample, the)-2.713 F +(address \231eric@CS.Berk)188.4 587.4 Q(ele)-.1 E -.65(y.)-.15 G +(EDU\232 is se).65 E -.15(ve)-.25 G 2.5(na).15 G(toms.)-2.5 E +(MAXMAILERS [25])102 603.6 Q .122(The maximum number of mailers that ma\ +y be de\214ned in the con\214guration \214le.).02 F(MAXR)102 619.8 Q +(WSETS [200])-.55 E .432(The maximum number of re).01 F .432 +(writing sets that may be de\214ned.)-.25 F .431(The \214rst half of) +5.431 F .034(these are reserv)188.4 631.8 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 643.8 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 655.8 Q(`S99')-.74 E 2.5('w)-.74 G +(ill succeed, b)-2.5 E(ut `)-.2 E(`S100')-.74 E 2.5('w)-.74 G(ill f)-2.5 +E(ail.)-.1 E(MAXPRIORITIES [25])102 672 Q 2.481(The maximum number of v) +188.4 684 R 2.482(alues for the \231Precedence:\232 \214eld that may be) +-.25 F(de\214ned \(using the)188.4 696 Q F0(P)2.5 E F1 +(line in sendmail.cf\).)2.5 E(MAXUSERENVIR)102 712.2 Q(ON [100])-.4 E +.399(The maximum number of items in the user en)188.4 724.2 R .399 +(vironment that will be passed to)-.4 F EP +%%Page: 71 67 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-71)195.86 E/F1 10/Times-Roman@0 SF(subordinate mailers.)188.4 96 +Q(MAXMXHOSTS [100])102 112.2 Q +(The maximum number of MX records we will accept for an)188.4 124.2 Q +2.5(ys)-.15 G(ingle host.)-2.5 E(MAXALIASDB [12])102 140.4 Q .767 +(The maximum number of alias databases that can be open at an).58 F +3.267(yt)-.15 G 3.267(ime. Note)-3.267 F +(that there may also be an open \214le limit.)188.4 152.4 Q(MAXMAPST)102 +168.6 Q -.4(AC)-.93 G 2.5(K[).4 G(12])-2.5 E 1.65 +(The maximum number of maps that may be "stack)188.4 180.6 R 1.65 +(ed" in a)-.1 F F0(sequence)4.15 E F1(class)4.15 E(map.)188.4 192.6 Q +(MAXMIMEARGS [20])102 208.8 Q .718(The maximum number of ar)188.4 220.8 +R .718(guments in a MIME Content-T)-.18 F .718(ype: header; addi-)-.8 F +(tional ar)188.4 232.8 Q(guments will be ignored.)-.18 E +(MAXMIMENESTING [20])102 249 Q .4(The maximum depth to which MIME messa\ +ges may be nested \(that is, nested)188.4 261 R 1.344(Message or Multip\ +art documents; this does not limit the number of compo-)188.4 273 R +(nents in a single Multipart document\).)188.4 285 Q(MAXD)102 301.2 Q +(AEMONS [10])-.4 E 1.353(The maximum number of sock)188.4 313.2 R 1.353 +(ets sendmail will open for accepting connec-)-.1 F(tions on dif)188.4 +325.2 Q(ferent ports.)-.25 E(MAXMA)102 341.4 Q(CN)-.4 E(AMELEN [25])-.35 +E(The maximum length of a macro name.)188.4 353.4 Q 2.85(An)102 369.6 S +.35(umber of other compilation options e)-2.85 F 2.851(xist. These)-.15 +F .351(specify whether or not speci\214c code should be)2.851 F +(compiled in.)102 381.6 Q(Ones mark)5 E(ed with \207 are 0/1 v)-.1 E +(alued.)-.25 E 36.69(NETINET\207 If)102 397.8 R .829 +(set, support for Internet protocol netw)3.33 F .829 +(orking is compiled in.)-.1 F(Pre)5.829 E .829(vious v)-.25 F(er)-.15 E +(-)-.2 E .177(sions of)188.4 409.8 R/F2 10/Times-Italic@0 SF(sendmail) +2.677 E F1 .177(referred to this as)2.677 F/F3 9/Times-Roman@0 SF -.36 +(DA)2.678 G(EMON).36 E F1 2.678(;t)C .178(his old usage is no)-2.678 F +2.678(wi)-.25 G(ncorrect.)-2.678 E(Def)188.4 421.8 Q 1.87 +(aults on; turn it of)-.1 F 4.37(fi)-.25 G 4.37(nt)-4.37 G 1.87(he Mak) +-4.37 F 1.87(e\214le if your system doesn')-.1 F 4.37(ts)-.18 G 1.87 +(upport the)-4.37 F(Internet protocols.)188.4 433.8 Q 31.69 +(NETINET6\207 If)102 450 R(set, support for IPv6 netw)2.5 E +(orking is compiled in.)-.1 E 43.35(NETISO\207 If)102 466.2 R .142 +(set, support for ISO protocol netw)2.642 F .143 +(orking is compiled in \(it may be appropri-)-.1 F +(ate to #de\214ne this in the Mak)188.4 478.2 Q +(e\214le instead of conf.h\).)-.1 E 34.47(NETUNIX\207 If)102 494.4 R .39 +(set, support for UNIX domain sock)2.89 F .39(ets is compiled in.)-.1 F +.39(This is used for con-)5.39 F(trol sock)188.4 506.4 Q(et support.)-.1 +E 63.35(LOG If)102 522.6 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 534.6 R +.504(es a higher priority log)-.1 F .052 +(record for internal system errors.)188.4 546.6 R F0(STR)5.052 E(ONGL) +-.3 E 2.552(YR)-.92 G(ECOMMENDED)-2.552 E F1 2.553<8a69>2.552 G 2.553 +(fy)-2.553 G(ou)-2.553 E -.1(wa)188.4 558.6 S(nt no logging, turn it of) +.1 E 2.5(fi)-.25 G 2.5(nt)-2.5 G(he con\214guration \214le.)-2.5 E(MA) +102 574.8 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)-6.055 G 3.555(he GECOS \214eld in)-6.055 F 2.5 +(/etc/passwd. This)188.4 586.8 R(also requires that the)2.5 E F0 +(MatchGECOS)2.5 E F1(option be turned on.)2.5 E -.35(NA)102 603 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)-2.913 F .413 +(er to)-.15 F(resolv)188.4 615 Q 2.5(eT)-.15 G(CP/IP host names.)-2.5 E +(NO)102 631.2 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-) +-2.747 E(cial processing of UNIX-style \231From \232 lines.)188.4 643.2 +Q -.1(QU)102 659.4 S 45.12(EUE\207 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 671.4 Q(.)-.55 E 52.78 +(SMTP\207 If)102 687.6 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 699.6 R(means most machines e)188.4 711.6 Q -.15(ve)-.25 G +(rywhere\).).15 E EP +%%Page: 72 68 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-72 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF 39.45 +(USERDB\207 Include)102 96 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.)-3.449 F(This)5.948 E .27(adds a ne) +188.4 108 R 2.77(wl)-.25 G -2.15 -.25(ev e)-2.77 H 2.77(lo).25 G 2.77 +(fl)-2.77 G .27(ocal name e)-2.77 F .27 +(xpansion between aliasing and forw)-.15 F 2.77(arding. It)-.1 F +(also uses the NEWDB package.)188.4 120 Q +(This may change in future releases.)5 E(The follo)102 136.2 Q +(wing options are normally turned on in per)-.25 E +(-operating-system clauses in conf.h.)-.2 E(IDENTPR)102 152.4 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.)-19.61 F .375 +(This def)5.375 F .375(aults on for)-.1 F 1.053(all systems e)188.4 +164.4 R 1.053(xcept Ultrix, which apparently has the interesting \231fe\ +ature\232 that)-.15 F .83(when it recei)188.4 176.4 R -.15(ve)-.25 G +3.33(sa\231).15 G .83 +(host unreachable\232 message it closes all open connections)-3.33 F +1.921(to that host.)188.4 188.4 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 por\ +t \(such as 113, used by IDENT\), Ultrix cannot)188.4 200.4 R(recei) +188.4 212.4 Q .3 -.15(ve e)-.25 H(mail from such hosts.).15 E 39.45 +(SYSTEM5 Set)102 228.6 R +(all of the compilation parameters appropriate for System V)2.5 E(.) +-1.29 E 26.12(HASFLOCK\207 Use)102 244.8 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 256.8 +R F0(lockf)2.684 E F1 2.684(,t)C .184(his should al)-2.684 F -.1(wa)-.1 +G(ys).1 E(be used if at all possible.)188.4 268.8 Q(HASINITGR)102 285 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 297 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 309 Q(HASUN)102 325.2 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 337.2 R(by def)2.5 E(ault if SYSTEM5 is set.)-.1 E(HASGETDT)102 +353.4 Q(ABLESIZE)-.93 E(Set this if you ha)188.4 365.4 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 381.6 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 -.74 +(FA)102 397.8 S(ST_PID_RECYCLE).74 E .542(Set this if your system can p\ +ossibly reuse the same pid in the same second of)188.4 409.8 R(time.) +188.4 421.8 Q 37.22(SFS_TYPE The)102 438 R .517 +(mechanism that can be used to get \214le system capacity information.) +3.016 F(The)5.517 E -.25(va)188.4 450 S .215(lues can be one of SFS_UST) +.25 F 2.435 -1.11(AT \()-.93 H .214 +(use the ustat\(2\) syscall\), SFS_4ARGS \(use)1.11 F .415(the four ar) +188.4 462 R .415(gument statfs\(2\) syscall\), SFS_VFS \(use the tw)-.18 +F 2.915(oa)-.1 G -.18(rg)-2.915 G .415(ument statfs\(2\)).18 F .716 +(syscall including \), SFS_MOUNT \(use the tw)188.4 474 R +3.216(oa)-.1 G -.18(rg)-3.216 G .716(ument statfs\(2\)).18 F 4.32 +(syscall including \), SFS_ST)188.4 486 R -1.11(AT)-.93 G +4.32(FS \(use the tw)1.11 F 6.82(oa)-.1 G -.18(rg)-6.82 G(ument).18 E +1.109(statfs\(2\) syscall including \), SFS_ST)188.4 498 R +-1.11(AT)-.93 G 1.109(VFS \(use the tw)1.11 F 3.608(oa)-.1 G -.18(rg) +-3.608 G(u-).18 E 1.511(ment statfs\(2\) syscall including \), or SFS_NONE \(no w)188.4 510 R 1.512(ay to)-.1 F +(get this information\).)188.4 522 Q 40.57(LA_TYPE The)102 538.2 R +(load a)2.5 E -.15(ve)-.2 G(rage type.).15 E(Details are described belo) +5 E -.65(w.)-.25 G .343(The are se)102 554.4 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 .342 +(tries to auto-con\214gure them)2.842 F .266 +(based on imperfect guesses; you can select one using the)102 566.4 R F2 +(cc)2.767 E F1(option)2.767 E F0(\255DLA_TYPE=)2.767 E F2(type)A F1 +2.767(,w)C(here)-2.767 E F2(type)2.767 E F1(is:)102 578.4 Q 48.91 +(LA_INT The)102 594.6 R -.1(ke)3.453 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 +606.6 Q(alues are scaled by a f)-.25 E(actor FSCALE \(def)-.1 E +(ault 256\).)-.1 E(LA_SHOR)102 622.8 Q 35.89(TT)-.6 G .793(he k)-35.89 F +.793(ernel stores the load a)-.1 F -.15(ve)-.2 G .794(rage in the k).15 +F .794(ernel as an array of short inte)-.1 F(gers.)-.15 E(The actual v) +188.4 634.8 Q(alues are scaled by a f)-.25 E(actor FSCALE \(def)-.1 E +(ault 256\).)-.1 E(LA_FLO)102 651 Q 37.03 -1.11(AT T)-.35 H .089(he k) +1.11 F .089(ernel stores the load a)-.1 F -.15(ve)-.2 G .089 +(rage in the k).15 F .088(ernel as an array of double precision)-.1 F +(\215oats.)188.4 663 Q(LA_MA)102 679.2 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 +695.4 R(the)2.5 E F2 -.1(ge)2.5 G(tloadavg).1 E F1 +(routine to get the load a)2.5 E -.15(ve)-.2 G +(rage as an array of doubles.).15 E(LA_ZER)102 711.6 Q 42.36(OA)-.4 G +-.1(lwa)-42.36 G(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 EP +%%Page: 73 69 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-73)195.86 E/F1 10/Times-Roman@0 SF .493(If type)102 96 R/F2 9 +/Times-Roman@0 SF(LA_INT)2.993 E F1(,)A F2(LA_SHOR)2.993 E(T)-.54 E F1 +2.993(,o)C(r)-2.993 E F2(LA_FLO)2.993 E -.999(AT)-.315 G F1 .493 +(is speci\214ed, you may also need to specify)3.992 F F2(_P)2.994 E +-.999(AT)-.828 G(H_UNIX).999 E F1 .949 +(\(the path to your system binary\) and)102 108 R F2(LA_A)3.448 E(VENR) +-1.215 E(UN)-.36 E F1 .948(\(the name of the v)3.448 F .948 +(ariable containing the load)-.25 F -2.25 -.2(av e)102 120 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 144 R(in sendmail/conf)2.5 E(.c)-.15 E F1 +(The follo)127 160.2 Q(wing changes can be made in conf.c.)-.25 E F0 2.5 +(6.3.1. Built-in)102 184.2 R(Header Semantics)2.5 E F1 1.248 +(Not all header semantics are de\214ned in the con\214guration \214le.) +142 200.4 R 1.248(Header lines that should)6.248 F .305(only be include\ +d by certain mailers \(as well as other more obscure semantics\) must b\ +e speci\214ed)117 212.4 R .046(in the)117 224.4 R/F3 10/Times-Italic@0 +SF(HdrInfo)2.546 E F1 .046(table in)2.546 F F3(conf)2.546 E(.c)-.15 E F1 +5.046(.T)C .047 +(his table contains the header name \(which should be in all lo)-5.046 F +(wer)-.25 E(case\) and a set of header control \215ags \(described belo) +117 236.4 Q(w\), The \215ags are:)-.25 E(H_A)117 252.6 Q 30.97 +(CHECK Normally)-.4 F .007 +(when the check is made to see if a header line is compatible with)2.508 +F 2.94(am)203.4 264.6 S(ailer)-2.94 E(,)-.4 E F3(sendmail)2.94 E F1 .441 +(will not delete an e)2.94 F .441(xisting line.)-.15 F .441 +(If this \215ag is set,)5.441 F F3(send-)2.941 E(mail)203.4 276.6 Q F1 +.152(will delete e)2.652 F -.15(ve)-.25 G 2.652(ne).15 G .152 +(xisting header lines.)-2.802 F .152 +(That is, if this bit is set and the)5.152 F 1.425(mailer does not ha) +203.4 288.6 R 1.725 -.15(ve \215)-.2 H 1.425 +(ag bits set that intersect with the required mailer).15 F 2.204 +(\215ags in the header de\214nition in sendmail.cf, the header line is) +203.4 300.6 R F3(always)4.703 E F1(deleted.)203.4 312.6 Q 51.13 +(H_EOH If)117 328.8 R .206(this header \214eld is set, treat it lik) +2.705 F 2.706(eab)-.1 G .206(lank line, i.e., it will signal the end) +-2.706 F(of the header and the be)203.4 340.8 Q +(ginning of the message te)-.15 E(xt.)-.15 E 39.45(H_FORCE Add)117 357 R +2.039(this header entry e)4.539 F -.15(ve)-.25 G 4.539(ni).15 G 4.539 +(fo)-4.539 G 2.038(ne e)-4.539 F 2.038(xisted in the message before.) +-.15 F 2.038(If a)7.038 F 2.188(header entry does not ha)203.4 369 R +2.488 -.15(ve t)-.2 H 2.188(his bit set,).15 F F3(sendmail)4.688 E F1 +2.189(will not add another)4.689 F .62 +(header line if a header line of this name already e)203.4 381 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 393 Q -.15(ve)-.25 G +(ryone who handled it.).15 E(H_TRA)117 409.2 Q 39.3(CE If)-.4 F 1.043 +(set, this is a timestamp \(trace\) \214eld.)3.543 F 1.044 +(If the number of trace \214elds in a)6.043 F .706(message e)203.4 421.2 +R .705(xceeds a preset amount the message is returned on the assump-) +-.15 F(tion that it has an aliasing loop.)203.4 433.2 Q 46.67(H_RCPT If) +117 449.4 R .332(set, this \214eld contains recipient addresses.)2.832 F +.332(This is used by the)5.332 F F02.832 E F1 .333(\215ag to)2.833 +F 1.349(determine who to send to when it is collecting recipients from \ +the mes-)203.4 461.4 R(sage.)203.4 473.4 Q(H_FR)117 489.6 Q 43.74 +(OM This)-.4 F 1.673 +(\215ag indicates that this \214eld speci\214es a sender)4.173 F 6.674 +(.T)-.55 G 1.674(he order of these)-6.674 F .898(\214elds in the)203.4 +501.6 R F3(HdrInfo)3.398 E F1 .898(table speci\214es)3.398 F F3 +(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 513.6 Q(H_ERR)117 529.8 Q(ORST) +-.4 E 22.53(OA)-.18 G(ddresses in this header should recei)-22.53 E .3 +-.15(ve e)-.25 H(rror messages.).15 E 52.79(H_CTE This)117 546 R +(header is a Content-T)2.5 E(ransfer)-.35 E(-Encoding header)-.2 E(.) +-.55 E 40.01(H_CTYPE This)117 562.2 R(header is a Content-T)2.5 E +(ype header)-.8 E(.)-.55 E(H_STRIPV)117 578.4 Q 25.25(AL Strip)-1.35 F +(the v)2.5 E(alue from the header \(for Bcc:\).)-.25 E(Let')117 594.6 Q +2.5(sl)-.55 G(ook at a sample)-2.5 E F3(HdrInfo)2.5 E F1 +(speci\214cation:)2.5 E EP +%%Page: 74 70 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-74 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF +(struct hdrinfo)157 96 Q(HdrInfo[] =)84.6 E({)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.162 +(addresses. An)117 412.2 R 3.162<7999>-.15 G .661(Full-Name:\232 \214el\ +d will be deleted unless the required mailer \215ag \(indicated in) +-3.162 F .245(the con\214guration \214le\) is speci\214ed.)117 424.2 R +.245(The \231Message:\232 and \231T)5.245 F -.15(ex)-.7 G .246 +(t:\232 \214elds will terminate the header;).15 F 1.936 +(these are used by random dissenters around the netw)117 436.2 R 1.936 +(ork w)-.1 F 4.436(orld. The)-.1 F(\231Recei)4.436 E -.15(ve)-.25 G +1.936(d:\232 \214eld will).15 F(al)117 448.2 Q -.1(wa)-.1 G +(ys be added, and can be used to trace messages.).1 E .445 +(There are a number of important points here.)142 464.4 R .446 +(First, header \214elds are not added automati-)5.446 F .657 +(cally just because the)117 476.4 R 3.157(ya)-.15 G .657(re in the) +-3.157 F/F2 10/Times-Italic@0 SF(HdrInfo)3.157 E F1 .657(structure; the) +3.157 F 3.157(ym)-.15 G .656(ust be speci\214ed in the con\214guration) +-3.157 F .727(\214le in order to be added to the message.)117 488.4 R +(An)5.728 E 3.228(yh)-.15 G .728 +(eader \214elds mentioned in the con\214guration \214le)-3.228 F -.2(bu) +117 500.4 S 3.24(tn).2 G .74(ot mentioned in the)-3.24 F 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)-3.24 E +1.374(added unless the)117 512.4 R 3.874(yw)-.15 G 1.374 +(ere in the message already)-3.874 F 6.375(.S)-.65 G 1.375(econd, the) +-6.375 F F2(HdrInfo)3.875 E F1 1.375(structure only speci\214es)3.875 F +.324(cliched processing; certain headers are processed specially by ad \ +hoc code re)117 524.4 R -.05(ga)-.15 G .324(rdless of the sta-).05 F .48 +(tus speci\214ed in)117 536.4 R F2(HdrInfo)2.98 E F1 5.48(.F)C .481 +(or e)-5.63 F .481 +(xample, the \231Sender:\232 and \231From:\232 \214elds are al)-.15 F +-.1(wa)-.1 G .481(ys scanned on).1 F(ARP)117 550.4 Q .75 +(ANET mail to determine the sender)-.92 F/F3 7/Times-Roman@0 SF(25)-4 I +F1 3.251(;t)4 K .751 +(his is used to perform the \231return to sender\232 func-)-3.251 F +2.977(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.977 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 .149 +(If it is necessary to restrict mail through a relay)142 614.6 R 2.649 +(,t)-.65 G(he)-2.649 E F2 -.15(ch)2.65 G(ec).15 E(kcompat)-.2 E F1 .15 +(routine can be modi\214ed.)2.65 F .163(This routine is called for e)117 +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 .264(later try) +117 650.6 R 2.764(,a)-.65 G .264(nd other v)-2.764 F .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.)-2.764 F .263 +(It is up to)5.264 F F2 -.15(ch)2.763 G(ec).15 E(k-)-.2 E(compat)117 +662.6 Q F1 2.477(to print an error message \(using)4.977 F F2(usr)4.977 +E(err)-.37 E F1 4.977(\)i)C 4.977(ft)-4.977 G 2.477 +(he message is rejected.)-4.977 F -.15(Fo)7.478 G 4.978(re).15 G +(xample,)-5.128 E .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(25)93.6 682.6 Q/F6 8/Times-Roman@0 SF +(Actually)3.2 I 2.632(,t)-.52 G .632 +(his is no longer true in SMTP; this information is contained in the en) +-2.632 F -.12(ve)-.32 G 2.631(lope. The).12 F .631(older ARP)2.631 F +.631(ANET protocols did)-.736 F(not completely distinguish en)72 695.4 Q +-.12(ve)-.32 G(lope from header).12 E(.)-.44 E EP +%%Page: 75 71 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-75)195.86 E/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)-2.25 E -.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 .97(This w)117 354 R .969 +(ould reject messages greater than 50000 bytes unless the)-.1 F 3.469 +(yw)-.15 G .969(ere local.)-3.469 F(The)5.969 E F1(EF_NORE-)3.469 E +(TURN)117 366 Q F2 .651(\215ag can be set in)3.151 F F1(e)3.151 E/F4 10 +/Symbol SFA F1(e_\215a)A(gs)-.1 E F2 .652 +(to suppress the return of the actual body of the message in)3.152 F +.656(the error return.)117 378 R .655(The actual use of this routine is\ + highly dependent on the implementation, and)5.656 F +(use should be limited.)117 390 Q F0 2.5(6.3.3. New)102 414 R +(Database Map Classes)2.5 E F2(Ne)142 430.2 Q 2.875(wk)-.25 G .675 -.15 +(ey m)-2.975 H .375(aps can be added by creating a class initialization\ + function and a lookup func-).15 F 2.5(tion. These)117 442.2 R +(are then added to the routine)2.5 E F1(setupmaps.)2.5 E F2 +(The initialization function is called as)142 458.4 Q F1(xxx)157 474.6 Q +F2(_map_init\(MAP *map, char *ar)A(gs\))-.18 E(The)117 490.8 Q F1(map) +3.28 E F2 .78(is an internal data structure.)3.28 F(The)5.78 E F1(ar) +3.279 E(gs)-.37 E F2 .779 +(is a pointer to the portion of the con\214guration)3.279 F .396 +(\214le line follo)117 502.8 R .396 +(wing the map class name; \215ags and \214lenames can be e)-.25 F .397 +(xtracted from this line.)-.15 F(The)5.397 E +(initialization function must return)117 514.8 Q F3(TR)2.5 E(UE)-.36 E +F2(if it successfully opened the map,)2.5 E F3 -.666(FA)2.5 G(LSE).666 E +F2(otherwise.)2.5 E(The lookup function is called as)142 531 Q F1(xxx) +157 547.2 Q F2(_map_lookup\(MAP *map, char b)A(uf[], char **a)-.2 E 1.3 +-.65(v, i)-.2 H(nt *statp\)).65 E(The)117 563.4 Q F1(map)2.773 E F2 .273 +(de\214nes the map internally)2.773 F 5.273(.T)-.65 G(he)-5.273 E F1 -.2 +(bu)2.773 G(f).2 E F2 .273(has the input k)2.773 F -.15(ey)-.1 G 5.273 +(.T)-.5 G .272(his may be \(and often is\) used)-5.273 F(destructi)117 +575.4 Q -.15(ve)-.25 G(ly).15 E 5.151(.T)-.65 G(he)-5.151 E F1(av)2.651 +E F2 .151(is a list of ar)2.651 F .151(guments passed in from the re) +-.18 F .152(write line.)-.25 F .152(The lookup function)5.152 F .322 +(should return a pointer to the ne)117 587.4 R 2.822(wv)-.25 G 2.822 +(alue. If)-3.072 F .322(the map lookup f)2.822 F(ails,)-.1 E F1(*statp) +2.822 E F2 .322(should be set to an e)2.822 F(xit)-.15 E .301 +(status code; in particular)117 599.4 R 2.801(,i)-.4 G 2.801(ts)-2.801 G +.302(hould be set to)-2.801 F F3(EX_TEMPF)2.802 E(AIL)-.666 E F2 .302 +(if reco)2.802 F -.15(ve)-.15 G .302(ry is to be attempted by the).15 F +(higher le)117 611.4 Q -.15(ve)-.25 G 2.5(lc).15 G(ode.)-2.5 E F0 2.5 +(6.3.4. Queueing)102 635.4 R(Function)2.5 E F2 .783(The routine)142 +651.6 R F1(shouldqueue)3.283 E F2 .783 +(is called to decide if a message should be queued or processed)3.283 F +(immediately)117 663.6 Q 6.618(.T)-.65 G 1.618 +(ypically this compares the message priority to the current load a) +-7.418 F -.15(ve)-.2 G 4.119(rage. The).15 F(def)117 675.6 Q +(ault de\214nition is:)-.1 E EP +%%Page: 76 72 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-76 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(bool)157 +96 Q(shouldqueue\(pri, ctime\))157 108 Q(long pri;)175 120 Q +(time_t ctime;)175 132 Q({)157 144 Q(if \(CurrentLA < QueueLA\))175 156 +Q(return \(F)193 168 Q(ALSE\);)-.74 E(return \(pri > \(QueueF)175 180 Q +(actor / \(CurrentLA \255 QueueLA + 1\)\)\);)-.15 E(})157 192 Q 2.063 +(If the current load a)117 208.2 R -.15(ve)-.2 G 2.062(rage \(global v) +.15 F(ariable)-.25 E/F2 10/Times-Italic@0 SF(Curr)4.562 E(entLA)-.37 E +F1 4.562(,w)C 2.062(hich is set before this function is)-4.562 F 1.057 +(called\) is less than the lo)117 220.2 R 3.558(wt)-.25 G 1.058 +(hreshold load a)-3.558 F -.15(ve)-.2 G 1.058(rage \(option).15 F F0(x) +3.558 E F1 3.558(,v)C(ariable)-3.808 E F2(QueueLA)3.558 E F1(\),)A F2 +(shouldqueue)3.558 E F1(returns)117 232.2 Q/F3 9/Times-Roman@0 SF -.666 +(FA)2.587 G(LSE).666 E F1 .086(immediately \(that is, it should)2.587 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 .086(rage e).15 F .086(xceeds the)-.15 F .587 +(high threshold load a)117 244.2 R -.15(ve)-.2 G .587(rage \(option).15 +F F0(X)3.087 E F1 3.087(,v)C(ariable)-3.337 E F2(RefuseLA)3.087 E F1 +(\),)A F2(shouldqueue)3.088 E F1(returns)3.088 E F3(TR)3.088 E(UE)-.36 E +F1(immedi-)3.088 E(ately)117 256.2 Q 7.126(.O)-.65 G 2.125 +(therwise, it computes the function based on the message priority)-7.126 +F 4.625(,t)-.65 G 2.125(he queue f)-4.625 F(actor)-.1 E(\(option)117 +268.2 Q F0(q)2.5 E F1 2.5(,g)C(lobal v)-2.5 E(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.066(An implementation wishing to tak)142 284.4 +R 3.566(et)-.1 G 1.067 +(he actual age of the message into account can also)-3.566 F 1.41 +(use the)117 296.4 R F2(ctime)3.91 E F1(parameter)3.91 E 3.91(,w)-.4 G +1.41(hich is the time that the message w)-3.91 F 1.41 +(as \214rst submitted to)-.1 F F2(sendmail)3.91 E F1(.)A .928 +(Note that the)117 308.4 R F2(pri)3.428 E F1 .928(parameter is already \ +weighted by the number of times the message has been)3.428 F .395 +(tried \(although this tends to lo)117 320.4 R .395 +(wer the priority of the message with time\); the e)-.25 F .395 +(xpectation is that)-.15 F(the)117 332.4 Q F2(ctime)2.674 E F1 -.1(wo) +2.674 G .174 +(uld be used as an \231escape clause\232 to ensure that messages are e) +.1 F -.15(ve)-.25 G .174(ntually processed.).15 F F0 2.5 +(6.3.5. Refusing)102 356.4 R(Incoming SMTP Connections)2.5 E F1 1.149 +(The function)142 372.6 R F2 -.37(re)3.648 G(fuseconnections).37 E F1 +(returns)3.648 E F3(TR)3.648 E(UE)-.36 E F1 1.148 +(if incoming SMTP connections should be)3.648 F 3.563(refused. The)117 +384.6 R 1.063(current implementation is based e)3.563 F(xclusi)-.15 E +-.15(ve)-.25 G 1.063(ly on the current load a).15 F -.15(ve)-.2 G 1.063 +(rage and the).15 F(refuse load a)117 396.6 Q -.15(ve)-.2 G +(rage option \(option).15 E F0(X)2.5 E F1 2.5(,g)C(lobal v)-2.5 E +(ariable)-.25 E F2(RefuseLA)2.5 E F1(\):)A(bool)157 412.8 Q +(refuseconnections\(\))157 424.8 Q({)157 436.8 Q +(return \(RefuseLA > 0 && CurrentLA >= RefuseLA\);)175 448.8 Q(})157 +460.8 Q 2.5(Am)117 477 S(ore cle)-2.5 E -.15(ve)-.25 G 2.5(ri).15 G +(mplementation could look at more system resources.)-2.5 E F0 2.5 +(6.3.6. Load)102 501 R -.6 -1(Av e)2.5 H(rage Computation)1 E F1 .244 +(The routine)142 517.2 R F2 -.1(ge)2.743 G(tla).1 E F1 .243 +(returns the current load a)2.743 F -.15(ve)-.2 G .243 +(rage \(as a rounded inte).15 F 2.743(ger\). The)-.15 F(distrib)2.743 E +(ution)-.2 E 1.156(includes se)117 529.2 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)-3.657 G 1.157(ironment you may).4 F +(need to add some ne)117 543.2 Q 2.5(wt)-.25 G(weaks.)-2.5 E/F4 7 +/Times-Roman@0 SF(26)-4 I F0 2.5(6.4. Con\214guration)87 567.2 R +(in sendmail/daemon.c)2.5 E F1 .128(The \214le)127 583.4 R F2 +(sendmail/daemon.c)2.628 E F1 .128 +(contains a number of routines that are dependent on the local net-) +2.628 F -.1(wo)102 595.4 S(rking en).1 E 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 611.6 R 2.16 +(vious releases, we recommended that you modify the routine)-.25 F F2 +(maphostname)4.66 E F1 2.16(if you)4.66 F -.1(wa)102 623.6 S 1.919 +(nted to generalize).1 F F0($[)4.418 E F1(...)4.418 E F0($])4.418 E F1 +4.418(lookups. W)4.418 F 4.418(en)-.8 G 2.418 -.25(ow r)-4.418 H 1.918 +(ecommend that you create a ne).25 F 4.418(wk)-.25 G -.15(ey)-4.518 G +1.918(ed map).15 F(instead.)102 635.6 Q .32 LW 76 678.8 72 678.8 DL 80 +678.8 76 678.8 DL 84 678.8 80 678.8 DL 88 678.8 84 678.8 DL 92 678.8 88 +678.8 DL 96 678.8 92 678.8 DL 100 678.8 96 678.8 DL 104 678.8 100 678.8 +DL 108 678.8 104 678.8 DL 112 678.8 108 678.8 DL 116 678.8 112 678.8 DL +120 678.8 116 678.8 DL 124 678.8 120 678.8 DL 128 678.8 124 678.8 DL 132 +678.8 128 678.8 DL 136 678.8 132 678.8 DL 140 678.8 136 678.8 DL 144 +678.8 140 678.8 DL 148 678.8 144 678.8 DL 152 678.8 148 678.8 DL 156 +678.8 152 678.8 DL 160 678.8 156 678.8 DL 164 678.8 160 678.8 DL 168 +678.8 164 678.8 DL 172 678.8 168 678.8 DL 176 678.8 172 678.8 DL 180 +678.8 176 678.8 DL 184 678.8 180 678.8 DL 188 678.8 184 678.8 DL 192 +678.8 188 678.8 DL 196 678.8 192 678.8 DL 200 678.8 196 678.8 DL 204 +678.8 200 678.8 DL 208 678.8 204 678.8 DL 212 678.8 208 678.8 DL 216 +678.8 212 678.8 DL/F5 5/Times-Roman@0 SF(26)93.6 689.2 Q/F6 8 +/Times-Roman@0 SF +(If you do, please send updates to sendmail@Sendmail.ORG.)3.2 I EP +%%Page: 77 73 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-77)195.86 E 2.5(7. A)72 96 R(CKNO)-.55 E(WLEDGEMENTS)-.5 E/F1 10 +/Times-Roman@0 SF(I')112 112.2 Q 2.036 -.15(ve w)-.5 H(ork).05 E 1.737 +(ed on)-.1 F/F2 10/Times-Italic@0 SF(sendmail)4.237 E F1 1.737(for man) +4.237 F 4.237(yy)-.15 G 1.737(ears, and man)-4.237 F 4.237(ye)-.15 G +(mplo)-4.237 E 1.737(yers ha)-.1 F 2.037 -.15(ve b)-.2 H 1.737 +(een remarkably patient).15 F .404(about letting me w)87 124.2 R .404 +(ork on a lar)-.1 F .404(ge project that w)-.18 F .403 +(as not part of my of)-.1 F .403(\214cial job)-.25 F 5.403(.T)-.4 G .403 +(his includes time on the)-5.403 F .281(INGRES Project at the Uni)87 +136.2 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)-2.782 F +.282(ain on the Mammoth)-.05 F(and T)87 148.2 Q(itan Projects at Berk) +-.35 E(ele)-.1 E -.65(y.)-.15 G .79(Much of the second w)112 164.4 R +-2.25 -.2(av e)-.1 H .789(of impro)3.49 F -.15(ve)-.15 G .789 +(ments resulting in v).15 F .789(ersion 8.1 should be credited to Bryan) +-.15 F .545(Costales of the International Computer Science Institute.)87 +176.4 R .545(As he passed me drafts of his book on)5.545 F F2(send-) +3.045 E(mail)87 188.4 Q F1 2.5(Iw)2.5 G(as inspired to start w)-2.6 E +(orking on things ag)-.1 E 2.5(ain. Bryan)-.05 F -.1(wa)2.5 G 2.5(sa).1 +G(lso a)-2.5 E -.25(va)-.2 G(ilable to bounce ideas of).25 E 2.5(fo)-.25 +G(f.)-2.5 E(Gre)112 204.6 Q .168(gory Neil Shapiro of W)-.15 F .168(orc\ +ester Polytechnic Institute has become instrumental in all phases of)-.8 +F F2(sendmail)87 216.6 Q F1 .34(support and de)2.84 F -.15(ve)-.25 G .34 +(lopment, and w).15 F .34(as lar)-.1 F .34 +(gely responsible for getting v)-.18 F .34(ersions 8.8 and 8.9 out the) +-.15 F(door)87 228.6 Q(.)-.55 E(Man)112 244.8 Q 2.857 -.65(y, m)-.15 H +(an).65 E 4.057(yp)-.15 G 1.557(eople contrib)-4.057 F 1.556 +(uted chunks of code and ideas to)-.2 F F2(sendmail)4.056 E F1 6.556(.I) +C 4.056(th)-6.556 G 1.556(as pro)-4.056 F -.15(ve)-.15 G 4.056(nt).15 G +4.056(ob)-4.056 G 4.056(ea)-4.056 G .405(group netw)87 256.8 R .405 +(ork ef)-.1 F 2.905(fort. V)-.25 F .405(ersion 8 in particular w)-1.11 F +.405(as a group project.)-.1 F .406(The follo)5.406 F .406 +(wing people and or)-.25 F -.05(ga)-.18 G(niza-).05 E +(tions made notable contrib)87 268.8 Q(utions:)-.2 E(Claus Assmann)127 +285 Q(John Beck, He)127 297 Q(wlett-P)-.25 E(ackard & Sun Microsystems) +-.15 E -.25(Ke)127 309 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 321 Q 2.5 +(wC)-.25 G(heng, Sun Microsystems)-2.5 E(Michael J. Corrig)127 333 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 & InfoBeat)127 +345 Q -.15(Pa)127 357 S -.5(..)-4.402 -6 O 2.5(r\().552 6 O +(Pell\) Emanuelsson)-2.5 E(Craig Ev)127 369 Q(erhart, T)-.15 E +(ransarc Corporation)-.35 E(Per Hedeland, Ericsson)127 381 Q -.8(To)127 +393 S 2.5(mI).8 G -.25(va)-2.5 G 2.5(rH).25 G(elbekkmo, Norwe)-2.5 E +(gian School of Economics)-.15 E +(Kari Hurtta, Finnish Meteorological Institute)127 405 Q +(Allan E. Johannesen, WPI)127 417 Q(Jonathan Kamens, OpenV)127 429 Q +(ision T)-.6 E(echnologies, Inc.)-.7 E -.8(Ta)127 441 S +(kahiro Kanbe, Fuji Xerox Information Systems Co., Ltd.).8 E +(Brian Kantor)127 453 Q 2.5(,U)-.4 G(ni)-2.5 E -.15(ve)-.25 G +(rsity of California, San Die).15 E(go)-.15 E(John K)127 465 Q(ennedy) +-.25 E 2.5(,C)-.65 G(al State Uni)-2.5 E -.15(ve)-.25 G(rsity).15 E 2.5 +(,C)-.65 G(hico)-2.5 E(Murray S. K)127 477 Q(uchera)-.15 E(wy)-.15 E 2.5 +(,H)-.65 G(ookUp Communication Corp.)-2.5 E(Bruce Lilly)127 489 Q 2.5 +(,S)-.65 G(on)-2.5 E 2.5(yU)-.15 G(.S.)-2.5 E(Karl London)127 501 Q +(Motonori Nakamura, Ritsumeikan Uni)127 513 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 525 Q(gie Mellon Uni)-.15 E -.15(ve)-.25 +G(rsity).15 E(Neil Rick)127 537 Q(ert, Northern Illinois Uni)-.1 E -.15 +(ve)-.25 G(rsity).15 E(Gre)127 549 Q(gory Neil Shapiro, WPI)-.15 E +(Eric Schnoebelen, Con)127 561 Q .3 -.15(vex C)-.4 H(omputer Corp.).15 E +(Eric W)127 573 Q(assenaar)-.8 E 2.5(,N)-.4 G +(ational Institute for Nuclear and High Ener)-2.5 E(gy Ph)-.18 E +(ysics, Amsterdam)-.05 E(Randall W)127 585 Q(inchester)-.4 E 2.5(,U)-.4 +G(ni)-2.5 E -.15(ve)-.25 G(rsity of Maryland).15 E(Christophe W)127 597 +Q(olfhugel, P)-.8 E(asteur Institute & Herv)-.15 E 2.5(eS)-.15 G +(chauer Consultants \(P)-2.5 E(aris\))-.15 E(Exactis.com, Inc.)127 609 Q +3.22(Ia)87 625.2 S .72(pologize for an)-3.22 F .72(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 .719(At this point, I)5.719 F 1.092 +(suspect that at least a hundred people ha)87 637.2 R 1.393 -.15(ve c) +-.2 H(ontrib).15 E 1.093(uted code, and man)-.2 F 3.593(ym)-.15 G 1.093 +(ore ha)-3.593 F 1.393 -.15(ve c)-.2 H(ontrib).15 E 1.093(uted ideas,) +-.2 F 1.534(comments, and encouragement.)87 649.2 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.533 +(TES in the distrib)-.4 F(ution)-.2 E(directory)87 661.2 Q 5(.I)-.65 G +(appreciate their contrib)-2.5 E(ution as well.)-.2 E .742 +(Special thanks are reserv)112 677.4 R .742(ed for Michael Corrig)-.15 F +.743(an and Christophe W)-.05 F .743(olfhugel, who besides being)-.8 F +-.1(wo)87 689.4 S 2.1(nderful guinea pigs and contrib).1 F 2.1(utors ha) +-.2 F 2.4 -.15(ve a)-.2 H 2.1(lso consented to be added to the `).15 F +(`sendmail@Send-)-.74 E(mail.ORG')87 701.4 Q 3.61('l)-.74 G 1.11 +(ist and, by answering the b)-3.61 F 1.111 +(ulk of the questions sent to that list, ha)-.2 F 1.411 -.15(ve f)-.2 H +1.111(reed me up to do).15 F(other w)87 713.4 Q(ork.)-.1 E EP +%%Page: 78 74 +%%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 E72 217.2 Q/F2 10/Times-Italic@0 SF(x)A F1 +(Set operation mode to)56.92 E F2(x)2.5 E F1 5(.O)C(peration modes are:) +-5 E 12.22(mD)184 233.4 S(eli)-12.22 E -.15(ve)-.25 G 2.5(rm).15 G +(ail \(def)-2.5 E(ault\))-.1 E 16.11(sS)184 245.4 S +(peak SMTP on input side)-16.11 E 8.06(a\207 `)184 257.4 R -.8(`A)-.74 G +(rpanet').8 E 2.5('m)-.74 G(ode \(get en)-2.5 E -.15(ve)-.4 G +(lope sender information from header\)).15 E 15(dR)184 269.4 S +(un as a daemon in background)-15 E 12.78(DR)184 281.4 S +(un as a daemon in fore)-12.78 E(ground)-.15 E 17.22(tR)184 293.4 S +(un in test mode)-17.22 E 15(vJ)184 305.4 S(ust v)-15 E +(erify addresses, don')-.15 E 2.5(tc)-.18 G(ollect or deli)-2.5 E -.15 +(ve)-.25 G(r).15 E 17.22(iI)184 317.4 S(nitialize the alias database) +-17.22 E 15(pP)184 329.4 S(rint the mail queue)-15 E 15(hP)184 341.4 S +(rint the persistent host status database)-15 E 12.78(HP)184 353.4 S(ur) +-12.78 E(ge e)-.18 E +(xpired entries from the persistent host status database)-.15 E72 +373.8 Q F2(type)A F1(Indicate body type.)43.03 E72 390 Q F2 +(\214le)A F1 .947(Use a dif)47.47 F .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 402 Q72 418.2 Q F2(le)A(vel) +-.15 E F1(Set deb)42.63 E(ugging le)-.2 E -.15(ve)-.25 G(l.).15 E +72 434.4 Q F2(addr)2.5 E F1 .627(The en)41.64 F -.15(ve)-.4 G .627 +(lope sender address is set to).15 F F2(addr)3.127 E F1 5.627(.T)C .628 +(his address may also be used in the From:)-5.627 F .153 +(header if that header is missing during initial submission.)144 446.4 R +.152(The en)5.152 F -.15(ve)-.4 G .152(lope sender address is).15 F +1.263(used as the recipient for deli)144 458.4 R -.15(ve)-.25 G 1.263 +(ry status noti\214cations and may also appear in a Return-).15 F -.15 +(Pa)144 470.4 S(th: header).15 E(.)-.55 E72 486.6 Q F2(name)2.5 E +F1(Sets the full name of this user to)36.64 E F2(name)2.5 E F1(.)A 56.64 +(\255G When)72 502.8 R 1.176 +(accepting messages via the command line, indicate that the)3.677 F +3.676(ya)-.15 G 1.176(re for relay \(g)-3.676 F(ate-)-.05 E -.1(wa)144 +514.8 S 2.215(y\) submission.).1 F 2.216 +(sendmail may complain about syntactically in)7.215 F -.25(va)-.4 G +2.216(lid messages, e.g.,).25 F .037(unquali\214ed host names, rather t\ +han \214xing them when this \215ag is set.)144 526.8 R .037 +(sendmail will not do)5.037 F(an)144 538.8 Q 2.5(yc)-.15 G +(anonicalization in this mode.)-2.5 E72 555 Q F2(cnt)2.5 E F1 .725 +(Sets the \231hop count\232 to)46.64 F F2(cnt)3.225 E F1 5.725(.T)C .726 +(his represents the number of times this message has been)-5.725 F .02 +(processed by)144 567 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 reac\ +hes MAXHOP \(currently 30\))144 579 R F2(sendmail)4.021 E F1(thro)144 +591 Q(ws a)-.25 E -.1(wa)-.15 G 2.5(yt).1 G(he message with an error) +-2.5 E(.)-.55 E72 607.2 Q F2(ta)2.5 E(g)-.1 E F1 1.483 +(Sets the identi\214er used for syslog.)45.07 F 1.482 +(Note that this identi\214er is set as early as possible.)6.483 F(Ho)144 +619.2 Q(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G F2(sendmail)2.915 E F1 +.015(may be used if problems arise before the command line ar)2.515 F +.016(guments are)-.18 F(processed.)144 631.2 Q 58.86(\255n Don')72 647.4 +R 2.5(td)-.18 G 2.5(oa)-2.5 G(liasing or forw)-2.5 E(arding.)-.1 E +72 663.6 Q F2(noti\214cations)2.5 E F1 -.8(Ta)7.19 G 3.128(ga).8 G .628 +(ll addresses being sent as w)-3.128 F .628(anting the indicated)-.1 F +F2(noti\214cations)3.128 E F1 3.127(,w)C .627(hich consists of the) +-3.127 F -.1(wo)144 675.6 S .474 +(rd \231NEVER\232 or a comma-separated list of \231SUCCESS\232, \231F).1 +F .474(AILURE\232, and \231DELA)-.74 F<599a>-1.05 E .32 LW 76 685.2 72 +685.2 DL 80 685.2 76 685.2 DL 84 685.2 80 685.2 DL 88 685.2 84 685.2 DL +92 685.2 88 685.2 DL 96 685.2 92 685.2 DL 100 685.2 96 685.2 DL 104 +685.2 100 685.2 DL 108 685.2 104 685.2 DL 112 685.2 108 685.2 DL 116 +685.2 112 685.2 DL 120 685.2 116 685.2 DL 124 685.2 120 685.2 DL 128 +685.2 124 685.2 DL 132 685.2 128 685.2 DL 136 685.2 132 685.2 DL 140 +685.2 136 685.2 DL 144 685.2 140 685.2 DL 148 685.2 144 685.2 DL 152 +685.2 148 685.2 DL 156 685.2 152 685.2 DL 160 685.2 156 685.2 DL 164 +685.2 160 685.2 DL 168 685.2 164 685.2 DL 172 685.2 168 685.2 DL 176 +685.2 172 685.2 DL 180 685.2 176 685.2 DL 184 685.2 180 685.2 DL 188 +685.2 184 685.2 DL 192 685.2 188 685.2 DL 196 685.2 192 685.2 DL 200 +685.2 196 685.2 DL 204 685.2 200 685.2 DL 208 685.2 204 685.2 DL 212 +685.2 208 685.2 DL 216 685.2 212 685.2 DL/F3 8/Times-Roman@0 SF +(\207Deprecated.)93.6 697.2 Q/F4 10/Times-Bold@0 SF 193.36 +(SMM:08-78 Sendmail)72 756 R(Installation and Operation Guide)2.5 E EP +%%Page: 79 75 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-79)195.86 E/F1 10/Times-Roman@0 SF .86(for successful deli)144 +96 R -.15(ve)-.25 G(ry).15 E 3.36(,f)-.65 G .86 +(ailure, and a message that is stuck in a queue some)-3.46 F 3.36 +(where. The)-.25 F(def)144 108 Q(ault is \231F)-.1 E(AILURE,DELA)-.74 E +(Y\232.)-1.05 E72 124.2 Q/F2 10/Times-Italic@0 SF(addr)2.5 E F1 +(An obsolete form of)41.64 E F02.5 E F1(.)A72 140.4 Q F2 +1.666(xv)C(alue)-1.666 E F1(Set option)33.594 E 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.)-5 E72 156.6 Q F2 +(option)A F0(=)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 168.6 Q72 184.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)-2.5 G +(he speci\214ed value)-2.5 E(.)-.15 E F172 201 Q F2(pr)A(otocol) +-.45 E F1 .401(Set the sending protocol.)27.92 F .401 +(Programs are encouraged to set this.)5.401 F .4 +(The protocol \214eld can be)5.401 F .114(in the form)144 213 R F2(pr) +2.614 E(otocol)-.45 E F0(:)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,)-2.765 E 2.147(\231\255pUUCP:uunet\232 s\ +ets the sending protocol to UUCP and the sending host to uunet.)144 225 +R .973(\(Some e)144 237 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 249 Q +72 265.2 Q F2(time)A F1 -.35(Tr)44.14 G 3.168(yt).35 G 3.167(op)-3.168 G +.667(rocess the queued up mail.)-3.167 F .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 277.2 +Q(al to deli)-.25 E -.15(ve)-.25 G 2.5(rq).15 G +(ueued mail; otherwise, it only runs once.)-2.5 E72 293.4 Q F2 +(Xstring)A F1 .312 +(Run the queue once, limiting the jobs to those matching)31.91 F F2 +(Xstring)2.813 E F1 5.313(.T)C .313(he k)-5.313 F .613 -.15(ey l)-.1 H +(etter).15 E F2(X)2.813 E F1 .313(can be)2.813 F F0(I)144 305.4 Q F1 +.671(to limit based on queue identi\214er)3.171 F(,)-.4 E F0(R)3.171 E +F1 .67(to limit based on recipient, or)3.171 F F0(S)3.17 E F1 .67 +(to limit based on)3.17 F(sender)144 317.4 Q 6.053(.A)-.55 G 1.054(part\ +icular queued job is accepted if one of the corresponding addresses con\ +-)-2.5 F .033(tains the indicated)144 329.4 R F2(string)2.533 E F1 5.033 +(.M)C(ultiple)-5.033 E F2(\255qX)2.533 E F1 .033 +(\215ags are permitted, with items with the same k)2.533 F -.15(ey)-.1 G +(letter \231or'ed\232 together)144 341.4 Q 2.5(,a)-.4 G +(nd items with dif)-2.5 E(ferent k)-.25 E .3 -.15(ey l)-.1 H +(etters \231and'ed\232 together).15 E(.)-.55 E(\255R ret)72 357.6 Q +1.687(What information you w)46.64 F 1.687 +(ant returned if the message bounces;)-.1 F F2 -.37(re)4.187 G(t).37 E +F1 1.687(can be \231HDRS\232 for)4.187 F .878 +(headers only or \231FULL\232 for headers plus body)144 369.6 R 5.878 +(.T)-.65 G .877(his is a request only; the other end is)-5.878 F 1.308 +(not required to honor the parameter)144 381.6 R 6.308(.I)-.55 G 3.808 +<6699>-6.308 G 1.309(HDRS\232 is speci\214ed local bounces also return) +-3.808 F(only the headers.)144 393.6 Q 61.08(\255t Read)72 409.8 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 421.8 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)-2.539 F .04(gument v)-.18 F +(ec-)-.15 E(tor will be deleted from the send list.)144 433.8 Q 56.64 +(\255U Indicate)72 450 R 1.476 +(that this is an initial User Agent submission.)3.977 F 1.476 +(This \215ag is deprecated.)6.476 F(Future)6.476 E .558(releases will i\ +gnore this \215ag and assume all submissions from the command line are \ +ini-)144 462 R(tial submissions.)144 474 Q(\255V en)72 490.2 Q 32.32 +(vid The)-.4 F(indicated)3.18 E F2(en)3.18 E(vid)-.4 E F1 .68 +(is passed with the en)3.18 F -.15(ve)-.4 G .679 +(lope of the message and returned if the mes-).15 F(sage bounces.)144 +502.2 Q72 518.4 Q F2(lo)2.5 E(g\214le)-.1 E F1 .724(Log all traf) +31.74 F .724(\214c in and out of)-.25 F F2(sendmail)3.225 E F1 .725 +(in the indicated)3.225 F F2(lo)3.225 E(g\214le)-.1 E F1 .725(for deb) +3.225 F .725(ugging mailer prob-)-.2 F 2.5(lems. This)144 530.4 R +(produces a lot of data v)2.5 E +(ery quickly and should be used sparingly)-.15 E(.)-.65 E .638 +(There are a number of options that may be speci\214ed as primiti)97 +546.6 R .937 -.15(ve \215)-.25 H 3.137(ags. These).15 F .637 +(are the e, i, m, and v)3.137 F 3.784(options. Also,)72 558.6 R 1.284 +(the f option may be speci\214ed as the)3.784 F F03.784 E F1 3.785 +(\215ag. The)3.785 F 1.285 +(DSN related options \231\255N\232, \231\255R\232, and)3.785 F +<99ad569a206861>72 570.6 Q .3 -.15(ve n)-.2 H 2.5(oe).15 G -.25(ff)-2.5 +G(ects on).25 E F2(sendmail)2.5 E F1(running as daemon.)2.5 E EP +%%Page: 80 76 +%%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)-2.792 F/F2 10/Times-Bold@0 SF(Q)72 213 Q +F1 .002(option in the)2.502 F/F3 10/Times-Italic@0 SF(sendmail.cf)2.503 +E F1 .003(\214le, usually)2.503 F F3(/var/spool/mqueue)2.503 E F1(or) +2.503 E F3(/usr/spool/mqueue)2.503 E F1 5.003(.T)C .003(he indi)-5.003 F +.003(vidual qf, df, and)-.25 F(xf \214les may be stored in separate)72 +225 Q F3(qf/)2.5 E F1(,)A F3(df/)2.5 E F1 2.5(,a)C(nd)-2.5 E F3(xf/)2.5 +E F1(subdirectories if the)2.5 E 2.5(ya)-.15 G +(re present in the queue directory)-2.5 E(.)-.65 E 2.181 -.8(To u)97 +241.2 T .581(se multiple queues, supply a v).8 F .581 +(alue ending with an asterisk.)-.25 F -.15(Fo)5.58 G 3.08(re).15 G +(xample,)-3.23 E F3(/var/spool/mqueue/q*)3.08 E F1 1.004 +(will use all of the directories or symbolic links to directories be)72 +253.2 R 1.005(ginning with `q' in)-.15 F F3(/var/spool/mqueue)3.505 E F1 +(as)3.505 E 1.639(queue directories.)72 265.2 R(Ne)6.639 E 4.139(wm)-.25 +G 1.639(essages will be randomly placed into one of the queues.)-4.139 F +1.638(Do not change the)6.638 F +(queue directory structure while sendmail is running.)72 277.2 Q .806 +(All queue \214les ha)97 293.4 R 1.106 -.15(ve t)-.2 H .807(he name).15 +F F3(x)3.307 E F2(f)1.666 E F3(YMDhmsNPPPPP)A F1(where)3.307 E F3 +(YMDhmsNPPPPP)3.307 E F1 .807(is the)3.307 F F3(id)3.307 E F1 .807 +(for this mes-)3.307 F(sage and the)72 305.4 Q F3(x)2.5 E F1(is a type.) +2.5 E(The indi)5 E(vidual letters in the)-.25 E F3(id)2.5 E F1(are:)2.5 +E 28.78(YE)72 321.6 S(ncoded year)-28.78 E 27.11(ME)72 337.8 S +(ncoded month)-27.11 E 28.78(DE)72 354 S(ncoded day)-28.78 E 31(hE)72 +370.2 S(ncoded hour)-31 E 28.22(mE)72 386.4 S(ncoded minute)-28.22 E +32.11(sE)72 402.6 S(ncoded second)-32.11 E 28.78(NE)72 418.8 S -1.85 -.4 +(nv e)-28.78 H(lope number).4 E 5.7(PPPPP First)72 435 R<8c76>2.5 E 2.5 +(ed)-.15 G(igits of the process ID)-2.5 E 1.174 +(All \214les with the same id collecti)97 451.2 R -.15(ve)-.25 G 1.174 +(ly de\214ne one message.).15 F 1.173(If memory-b)6.173 F(uf)-.2 E 1.173 +(fered \214les are a)-.25 F -.25(va)-.2 G(ilable,).25 E +(some of these \214les may ne)72 463.2 Q -.15(ve)-.25 G 2.5(ra).15 G +(ppear on disk.)-2.5 E(The types are:)97 479.4 Q 31(dT)72 495.6 S +(he data \214le.)-31 E(The message body \(e)5 E +(xcluding the header\) is k)-.15 E(ept in this \214le.)-.1 E 31(qT)72 +511.8 S(he queue control \214le.)-31 E +(This \214le contains the information necessary to process the job)5 E +(.)-.4 E 33.22(tA)72 528 S .344(temporary \214le.)-30.376 F .344 +(These are an image of the)5.344 F F2(qf)2.844 E F1 .344 +(\214le when it is being reb)2.844 F 2.845(uilt. It)-.2 F .345 +(should be renamed)2.845 F(to a)108 540 Q F2(qf)2.5 E F1(\214le v)2.5 E +(ery quickly)-.15 E(.)-.65 E 31(xA)72 556.2 S .567(transcript \214le, e) +-27.933 F .567(xisting during the life of a session sho)-.15 F .566 +(wing e)-.25 F -.15(ve)-.25 G .566(rything that happens during that).15 +F(session.)108 568.2 Q(The)97 584.4 Q F2(qf)3.333 E F1 .833 +(\214le is structured as a series of lines each be)3.333 F .834 +(ginning with a code letter)-.15 F 5.834(.T)-.55 G .834 +(he lines are as fol-)-5.834 F(lo)72 596.4 Q(ws:)-.25 E 28.78(VT)72 +612.6 S .82(he v)-28.78 F .82 +(ersion number of the queue \214le format, used to allo)-.15 F 3.319(wn) +-.25 G -.25(ew)-3.319 G F3(sendmail)3.569 E F1 .819 +(binaries to read queue)3.319 F .003(\214les created by older v)108 +624.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 -.15(Fo)108 +636.6 S 2.5(r8).15 G(.10 the v)-2.5 E(ersion number is 3.)-.15 E 28.78 +(HA)72 652.8 S .33(header de\214nition.)-25.95 F .33(There may be an) +5.33 F 2.829(yn)-.15 G .329(umber of these lines.)-2.829 F .329 +(The order is important: the)5.329 F 2.829(yr)-.15 G(epre-)-2.829 E .046 +(sent the order in the \214nal message.)108 664.8 R .046 +(These use the same syntax as header de\214nitions in the con\214gu-) +5.046 F(ration \214le.)108 676.8 Q 29.33(CT)72 693 S .575 +(he controlling address.)-29.33 F .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 705 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 2.247(/etc/passwd \214le\);)108 717 R F3 +(aliasname)4.747 E F1 2.247(is the name of the alias that e)4.747 F +2.246(xpanded to this address \(used for)-.15 F F2 193.36 +(SMM:08-80 Sendmail)72 756 R(Installation and Operation Guide)2.5 E EP +%%Page: 81 77 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-81)195.86 E/F1 10/Times-Roman@0 SF(printing messages\).)108 96 Q +28.78(QT)72 112.2 S .797(he `)-28.78 F .797(`original recipient')-.74 F +.798(', speci\214ed by the ORCPT= \214eld in an ESMTP transaction.)-.74 +F .798(Used e)5.798 F(xclu-)-.15 E(si)108 124.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 140.4 S .705(recipient address.)-26.125 F .705 +(This will normally be completely aliased, b)5.705 F .705 +(ut is actually realiased when the)-.2 F .492(job is processed.)108 +152.4 R .492(There will be one line for each recipient.)5.492 F -1.11 +(Ve)5.492 G .493(rsion 1 qf \214les also include a lead-)1.11 F .689(in\ +g colon-terminated list of \215ags, which can be `S' to return a messag\ +e on successful \214nal deli)108 164.4 R(v-)-.25 E(ery)108 176.4 Q 3.327 +(,`)-.65 G .828(F' to return a message on f)-3.327 F .828 +(ailure, `D' to return a message if the message is delayed, `B' to)-.1 F +.941(indicate that the body should be returned, `N' to suppress returni\ +ng the body)108 188.4 R 3.44(,a)-.65 G .94(nd `P' to declare)-3.44 F +(this as a `)108 200.4 Q(`primary')-.74 E 2.5('\()-.74 G +(command line or SMTP-session\) address.)-2.5 E 30.44(ST)72 216.6 S +(he sender address.)-30.44 E(There may only be one of these lines.)5 E +29.89(TT)72 232.8 S(he job creation time.)-29.89 E +(This is used to compute when to time out the job)5 E(.)-.4 E 30.44(PT) +72 249 S .113(he current message priority)-30.44 F 5.113(.T)-.65 G .113 +(his is used to order the queue.)-5.113 F .114(Higher numbers mean lo) +5.114 F .114(wer priori-)-.25 F 3.677(ties. The)108 261 R 1.176 +(priority changes as the message sits in the queue.)3.677 F 1.176 +(The initial priority depends on the)6.176 F +(message class and the size of the message.)108 273 Q 27.11(MA)72 289.2 +S 2.703(message. This)-24.407 F .203(line is printed by the)2.703 F/F2 +10/Times-Italic@0 SF(mailq)2.703 E F1 .204 +(command, and is generally used to store status infor)2.704 F(-)-.2 E +2.5(mation. It)108 301.2 R(can contain an)2.5 E 2.5(yt)-.15 G -.15(ex) +-2.5 G(t.).15 E 30.44(FF)72 317.4 S .044 +(lag bits, represented as one letter per \215ag.)-30.44 F .043 +(De\214ned \215ag bits are)5.043 F F0(r)2.543 E F1 .043 +(indicating that this is a response)2.543 F .142(message and)108 329.4 R +F0(w)2.642 E F1 .142(indicating that a w)2.642 F .143 +(arning message has been sent announcing that the mail has been)-.1 F +(delayed.)108 341.4 Q 28.78(NT)72 357.6 S(he total number of deli)-28.78 +E -.15(ve)-.25 G(ry attempts.).15 E 28.78(KT)72 373.8 S +(he time \(as seconds since January 1, 1970\) of the last deli)-28.78 E +-.15(ve)-.25 G(ry attempt.).15 E 32.67(IT)72 390 S .725 +(he i-number of the data \214le; this can be used to reco)-32.67 F -.15 +(ve)-.15 G 3.224(ry).15 G .724(our mail queue after a disastrous disk) +-3.224 F(crash.)108 402 Q 31($A)72 418.2 S .829(macro de\214nition.) +-27.671 F .829(The v)5.829 F .829 +(alues of certain macros \(as of this writing, only)-.25 F F0($r)3.33 E +F1(and)3.33 E F0($s)3.33 E F1 3.33(\)a)C .83(re passed)-3.33 F +(through to the queue run phase.)108 430.2 Q 29.33(BT)72 446.4 S .925 +(he body type.)-29.33 F .925(The remainder of the line is a te)5.925 F +.925(xt string de\214ning the body type.)-.15 F .924(If this \214eld is) +5.924 F .009(missing, the body type is assumed to be \231unde\214ned\ +\232 and no special processing is attempted.)108 458.4 R(Le)5.009 E -.05 +(ga)-.15 G(l).05 E -.25(va)108 470.4 S +(lues are \2317BIT\232 and \2318BITMIME\232.).25 E 29.89(ZT)72 486.6 S +(he original en)-29.89 E -.15(ve)-.4 G +(lope id \(from the ESMTP transaction\).).15 E -.15(Fo)5 G 2.5(rD).15 G +(eli)-2.5 E -.15(ve)-.25 G 2.5(rS).15 G(tatus Noti\214cations only)-2.5 +E(.)-.65 E 4.073(As an e)97 502.8 R 4.073(xample, the follo)-.15 F 4.072 +(wing is a queue \214le sent to \231eric@mammoth.Berk)-.25 F(ele)-.1 E +-.65(y.)-.15 G 4.072(EDU\232 and).65 F(\231bostic@ok)72 516.8 Q(eef)-.1 +E(fe.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU\232).65 E/F3 7 +/Times-Roman@0 SF(1)-4 I F1(:)4 I .32 LW 76 669.2 72 669.2 DL 80 669.2 +76 669.2 DL 84 669.2 80 669.2 DL 88 669.2 84 669.2 DL 92 669.2 88 669.2 +DL 96 669.2 92 669.2 DL 100 669.2 96 669.2 DL 104 669.2 100 669.2 DL 108 +669.2 104 669.2 DL 112 669.2 108 669.2 DL 116 669.2 112 669.2 DL 120 +669.2 116 669.2 DL 124 669.2 120 669.2 DL 128 669.2 124 669.2 DL 132 +669.2 128 669.2 DL 136 669.2 132 669.2 DL 140 669.2 136 669.2 DL 144 +669.2 140 669.2 DL 148 669.2 144 669.2 DL 152 669.2 148 669.2 DL 156 +669.2 152 669.2 DL 160 669.2 156 669.2 DL 164 669.2 160 669.2 DL 168 +669.2 164 669.2 DL 172 669.2 168 669.2 DL 176 669.2 172 669.2 DL 180 +669.2 176 669.2 DL 184 669.2 180 669.2 DL 188 669.2 184 669.2 DL 192 +669.2 188 669.2 DL 196 669.2 192 669.2 DL 200 669.2 196 669.2 DL 204 +669.2 200 669.2 DL 208 669.2 204 669.2 DL 212 669.2 208 669.2 DL 216 +669.2 212 669.2 DL/F4 5/Times-Roman@0 SF(1)93.6 679.6 Q/F5 8 +/Times-Roman@0 SF .718(This e)3.2 J .718(xample is contri)-.12 F -.12 +(ve)-.2 G 2.718(da).12 G .718(nd probably inaccurate for your en)-2.718 +F 2.719(vironment. Glance)-.32 F -.12(ove)2.719 G 2.719(ri).12 G 2.719 +(tt)-2.719 G 2.719(og)-2.719 G .719(et an idea; nothing can replace) +-2.719 F(looking at what your o)72 692.4 Q(wn system generates.)-.2 E EP +%%Page: 82 78 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-82 Sendmail)72 60 R +(Installation and Operation Guide)2.5 E/F1 10/Times-Roman@0 SF(P835771) +112 96 Q(T404261372)112 108 Q(Seric)112 120 Q(Ceric:sendmail@v)112 132 Q +(angogh.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 G(EDU).65 E +(Reric@mammoth.Berk)112 144 Q(ele)-.1 E -.65(y.)-.15 G(EDU).65 E +(Rbostic@ok)112 156 Q(eef)-.1 E(fe.CS.Berk)-.25 E(ele)-.1 E -.65(y.)-.15 +G(EDU).65 E(H?P?Return-path: ).65 E(HRecei)112 +180 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 1992 00:28:55 -0700)132 192 Q(HRecei)112 204 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 1992 00:28:54 -0700)132 216 Q(HRecei)112 228 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 1992 03:29:14 -0400)132 240 Q(HRecei)112 252 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 1992 09:31:25 GMT)132 264 Q +(H?F?From: eric@foo.bar)112 276 Q(.baz.de \(Eric Allman\))-.55 E +(H?x?Full-name: Eric Allman)112 288 Q +(HMessage-id: <9207170931.AA22757@foo.bar)112 300 Q(.baz.de>)-.55 E(HT) +112 312 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 324 Q(xample message)-.15 E +.658(This sho)72 340.2 R .658(ws the person who sent the message, the s\ +ubmission time \(in seconds since January 1, 1970\), the)-.25 F +(message priority)72 352.2 Q 2.5(,t)-.65 G +(he message class, the recipients, and the headers for the message.)-2.5 +E EP +%%Page: 83 79 +%%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)-3 G(UPPOR)-3 E 3(TF)-.48 G(ILES)-3 E/F1 10 +/Times-Roman@0 SF 1.519(This is a summary of the support \214les that)97 +201 R/F2 10/Times-Italic@0 SF(sendmail)4.019 E F1 1.52 +(creates or generates.)4.019 F(Man)6.52 E 4.02(yo)-.15 G 4.02(ft)-4.02 G +1.52(hese can be)-4.02 F(changed by editing the sendmail.cf \214le; che\ +ck 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.735(Al)144 269.4 S 1.235 +(ink to /usr/sbin/sendmail; causes the alias database to be reb)-3.735 F +3.734(uilt. Running)-.2 F 1.234(this pro-)3.734 F +(gram is completely equi)144 281.4 Q -.25(va)-.25 G(lent to gi).25 E +(ving)-.25 E F2(sendmail)2.5 E F1(the)2.5 E/F3 10/Times-Bold@0 SF +(\255bi)2.5 E F1(\215ag.)2.5 E 13.38(/usr/bin/mailq Prints)72 297.6 R +3.702(al)3.702 G 1.202(isting of the mail queue.)-3.702 F 1.203 +(This program is equi)6.202 F -.25(va)-.25 G 1.203(lent to using the).25 +F F3(\255bp)3.703 E F1 1.203(\215ag to)3.703 F F2(sendmail)144 309.6 Q +F1(.)A(/etc/mail/sendmail.cf)72 325.8 Q +(The con\214guration \214le, in te)144 337.8 Q(xtual form.)-.15 E 1.72 +(/etc/mail/help\214le The)72 354 R(SMTP help \214le.)2.5 E +(/etc/mail/statistics)72 370.2 Q 2.5(As)144 382.2 S +(tatistics \214le; need not be present.)-2.5 E(/etc/mail/sendmail.pid)72 +398.4 Q .318(Created in daemon mode; it contains the process id of the \ +current SMTP daemon.)144 410.4 R .318(If you)5.318 F 1.047 +(use this in scripts; use `)144 422.4 R 1.047(`head \2551')-.74 F 3.548 +('t)-.74 G 3.548(og)-3.548 G 1.048 +(et just the \214rst line; the second line contains the)-3.548 F .68 +(command line used to in)144 434.4 R -.2(vo)-.4 G .879 -.1(ke t).2 H +.679(he daemon, and later v).1 F .679(ersions of)-.15 F F2(sendmail) +3.179 E F1 .679(may add more)3.179 F(information to subsequent lines.) +144 446.4 Q 5.06(/etc/mail/aliases The)72 462.6 R(te)2.5 E(xtual v)-.15 +E(ersion of the alias \214le.)-.15 E(/etc/mail/aliases.db)72 478.8 Q +(The alias \214le in)144 490.8 Q F2(hash)2.5 E F1(\(3\) format.)1.666 E +(/etc/mail/aliases.{pag,dir})72 507 Q(The alias \214le in)144 519 Q F2 +(ndbm)2.5 E F1(\(3\) format.)1.666 E(/v)72 535.2 Q(ar/spool/mqueue)-.25 +E(The directory in which the mail queue\(s\) and temporary \214les resi\ +de.)144 547.2 Q(/v)72 563.4 Q(ar/spool/mqueue/qf*)-.25 E +(Control \(queue\) \214les for messages.)144 575.4 Q(/v)72 591.6 Q +(ar/spool/mqueue/df*)-.25 E(Data \214les.)144 603.6 Q(/v)72 619.8 Q +(ar/spool/mqueue/tf*)-.25 E -.7(Te)144 631.8 S(mporary v).7 E +(ersions of the qf \214les, used during queue \214le reb)-.15 E(uild.) +-.2 E(/v)72 648 Q(ar/spool/mqueue/xf*)-.25 E 2.5(At)144 660 S +(ranscript of the current session.)-2.5 E F3 +(Sendmail Installation and Operation Guide)72 756 Q(SMM:08-83)195.86 E +EP +%%Page: 84 80 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF 193.36(SMM:08-84 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 81 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-3)200.86 E/F1 12/Times-Roman@0 SF -1.116(TA)263.226 98.4 S +(BLE OF CONTENTS)1.116 E/F2 10/Times-Roman@0 SF 2.5(1. B)72 124.8 R +(ASIC INST)-.35 E(ALLA)-.93 E 1.18(TION ...............................\ +.......................................................................\ +.........)-1.11 F(7)31 E 2.5(1.1. Compiling)87 139.2 R .43(Sendmail ...\ +.......................................................................\ +....................................)2.5 F(7)31 E 2.5(1.1.1. T)102 153.6 +R(weaking the Build In)-.8 E -.2(vo)-.4 G .19(cation ..................\ +...................................................................).2 F +(7)31 E 2.5(1.1.2. Creating)102 168 R 2.5(aS)2.5 G +(ite Con\214guration File)-2.5 E 28.5(.................................\ +............................................... 7)2.94 F 2.5(1.1.3. T) +102 182.4 R(weaking the Mak)-.8 E 1.64(e\214le ........................\ +.......................................................................\ +..)-.1 F(7)31 E 2.5(1.1.4. Compilation)102 196.8 R(and installation)2.5 +E 28.5(................................................................\ +........................ 8)4.6 F 2.5(1.2. Con\214guration)87 211.2 R .99 +(Files ................................................................\ +................................................)2.5 F(8)31 E 2.5 +(1.3. Details)87 225.6 R(of Installation Files)2.5 E 28.5(.............\ +.......................................................................\ +............... 9)4.89 F 2.5(1.3.1. /usr/sbin/sendmail)102 240 R 23.5(.\ +.......................................................................\ +................................. 10)2.66 F 2.5 +(1.3.2. /etc/mail/sendmail.cf)102 254.4 R 23.5(........................\ +.......................................................................\ +..... 10)4.34 F 2.5(1.3.3. /usr/bin/ne)102 268.8 R -.1(wa)-.25 G 2.19(l\ +iases .................................................................\ +......................................).1 F(10)26 E 2.5 +(1.3.4. /usr/bin/hoststat)102 283.2 R 23.5(............................\ +.......................................................................\ +......... 10)4.6 F 2.5(1.3.5. /usr/bin/pur)102 297.6 R 1.18(gestat ....\ +.......................................................................\ +...............................)-.18 F(10)26 E 2.5(1.3.6. /v)102 312 R +1.81(ar/spool/mqueue ..................................................\ +......................................................)-.25 F(10)26 E +2.5(1.3.7. /v)102 326.4 R .97(ar/spool/mqueue/.hoststat ...............\ +.......................................................................\ +....)-.25 F(11)26 E 2.5(1.3.8. /etc/mail/aliases*)102 340.8 R 23.5(....\ +.......................................................................\ +............................... 11)4.06 F 2.5(1.3.9. /etc/rc)102 355.2 R +(or /etc/init.d/sendmail)2.5 E 23.5(...................................\ +..................................................... 11)3.23 F 2.5 +(1.3.10. /etc/mail/help\214le)102 369.6 R 23.5(........................\ +.......................................................................\ +.......... 11)3.22 F 2.5(1.3.11. /etc/mail/statistics)102 384 R 23.5(..\ +.......................................................................\ +.............................. 13)3.77 F 2.5(1.3.12. /usr/bin/mailq)102 +398.4 R 23.5(..........................................................\ +................................................... 13)4.88 F 2.5 +(2. NORMAL)72 412.8 R(OPERA)2.5 E 1.56(TIONS ..........................\ +.......................................................................\ +............)-1.11 F(13)26 E 2.5(2.1. The)87 427.2 R(System Log)2.5 E +23.5(..................................................................\ +.................................................. 13)4.89 F 2.5 +(2.1.1. F)102 441.6 R 2.26(ormat ......................................\ +.......................................................................\ +.............)-.15 F(13)26 E 2.5(2.1.2. Le)102 456 R -.15(ve)-.25 G 2.24 +(ls ...................................................................\ +........................................................).15 F(14)26 E +2.5(2.2. Dumping)87 470.4 R .72(State .................................\ +.......................................................................\ +...............)2.5 F(14)26 E 2.5(2.3. The)87 484.8 R(Mail Queue)2.5 E +23.5(..................................................................\ +................................................... 14)2.96 F 2.5 +(2.3.1. Printing)102 499.2 R(the queue)2.5 E 23.5(.....................\ +.......................................................................\ +............. 14)2.67 F 2.5(2.3.2. F)102 513.6 R(orcing the queue)-.15 E +23.5(..................................................................\ +....................................... 14)3.94 F 2.5(2.4. Disk)87 528 R +(Based Connection Information)2.5 E 23.5(..............................\ +....................................................... 15)3.79 F 2.5 +(2.5. The)87 542.4 R(Service Switch)2.5 E 23.5(........................\ +.......................................................................\ +................. 16)2.68 F 2.5(2.6. The)87 556.8 R(Alias Database)2.5 E +23.5(..................................................................\ +.............................................. 16)2.69 F 2.5(2.6.1. Reb) +102 571.2 R(uilding the alias database)-.2 E 23.5(.....................\ +.................................................................. 17) +4.27 F 2.5(2.6.2. Potential)102 585.6 R .72(problems ..................\ +.......................................................................\ +...............)2.5 F(17)26 E 2.5(2.6.3. List)102 600 R -.25(ow)2.5 G +1.81(ners .............................................................\ +......................................................).25 F(18)26 E 2.5 +(2.7. User)87 614.4 R(Information Database)2.5 E 23.5(.................\ +.......................................................................\ +............ 18)2.7 F 2.5(2.8. Per)87 628.8 R(-User F)-.2 E(orw)-.15 E +(arding \(.forw)-.1 E(ard Files\))-.1 E 23.5(..........................\ +......................................................... 18)4.09 F 2.5 +(2.9. Special)87 643.2 R(Header Lines)2.5 E 23.5(......................\ +.......................................................................\ +................ 19)2.97 F 2.5(2.9.1. Errors-T)102 657.6 R 2.09(o: ....\ +.......................................................................\ +..........................................)-.8 F(19)26 E 2.5 +(2.9.2. Apparently-T)102 672 R 2.09(o: ................................\ +.......................................................................\ +......)-.8 F(19)26 E 2.5(2.9.3. Precedence)102 686.4 R 23.5(...........\ +.......................................................................\ +.................................. 19)2.97 F 2.5(2.10. IDENT)87 700.8 R +(Protocol Support)2.5 E 23.5(..........................................\ +........................................................... 19)2.95 F +2.5(3. ARGUMENTS)72 715.2 R 23.5(......................................\ +.......................................................................\ +.................. 20)3.78 F EP +%%Page: 4 82 +%%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.1. Queue)87 96 R(Interv)2.5 E 1.55(al ..............................\ +.......................................................................\ +..................)-.25 F(20)26 E 2.5(3.2. Daemon)87 110.4 R 1.29(Mode \ +.......................................................................\ +................................................)2.5 F(20)26 E 2.5 +(3.3. F)87 124.8 R(orcing the Queue)-.15 E 23.5(.......................\ +.......................................................................\ +................... 20)4.22 F 2.5(3.4. Deb)87 139.2 R 1.76(ugging .....\ +.......................................................................\ +.................................................)-.2 F(20)26 E 2.5 +(3.5. Changing)87 153.6 R(the V)2.5 E(alues of Options)-1.11 E 23.5(...\ +.......................................................................\ +.................. 21)3.23 F 2.5(3.6. T)87 168 R(rying a Dif)-.35 E +(ferent Con\214guration File)-.25 E 23.5(..............................\ +..................................................... 21)4.67 F 2.5 +(3.7. Logging)87 182.4 R -.35(Tr)2.5 G(af).35 E .5(\214c ..............\ +.......................................................................\ +.................................)-.25 F(21)26 E 2.5(3.8. T)87 196.8 R +(esting Con\214guration Files)-.7 E 23.5(..............................\ +..................................................................... 2\ +2)4.19 F 2.5(3.9. Persistent)87 211.2 R(Host Status Information)2.5 E +23.5(..................................................................\ +...................... 22)3.5 F 2.5(4. TUNING)72 225.6 R 23.5(.........\ +.......................................................................\ +......................................................... 23)2.68 F 2.5 +(4.1. T)87 240 R 1.07(imeouts .........................................\ +.......................................................................\ +................)-.35 F(23)26 E 2.5(4.1.1. Queue)102 254.4 R(interv)2.5 +E 2.1(al ..............................................................\ +................................................)-.25 F(23)26 E 2.5 +(4.1.2. Read)102 268.8 R 1(timeouts ...................................\ +.......................................................................\ +.....)2.5 F(23)26 E 2.5(4.1.3. Message)102 283.2 R 1.56(timeouts ......\ +.......................................................................\ +............................)2.5 F(25)26 E 2.5(4.2. F)87 297.6 R +(orking During Queue Runs)-.15 E 23.5(.................................\ +................................................................ 25)4.49 +F 2.5(4.3. Queue)87 312 R .73(Priorities ..............................\ +.......................................................................\ +................)2.5 F(26)26 E 2.5(4.4. Load)87 326.4 R .44(Limiting ..\ +.......................................................................\ +...............................................)2.5 F(26)26 E 2.5 +(4.5. Deli)87 340.8 R -.15(ve)-.25 G(ry Mode).15 E 23.5(...............\ +.......................................................................\ +................................. 26)3.08 F 2.5(4.6. Log)87 355.2 R(Le) +2.5 E -.15(ve)-.25 G 2.52(l.).15 G 23.5(...............................\ +.......................................................................\ +........................ 27)-2.52 F 2.5(4.7. File)87 369.6 R .72(Modes \ +.......................................................................\ +......................................................)2.5 F(27)26 E 2.5 +(4.7.1. T)102 384 R 2.5(os)-.8 G(uid or not to suid?)-2.5 E 23.5(......\ +.......................................................................\ +.................... 27)6.52 F 2.5(4.7.2. T)102 398.4 R(urning of)-.45 E +2.5(fs)-.25 G(ecurity checks)-2.5 E 23.5(..............................\ +............................................................ 28)3.95 F +2.5(4.8. Connection)87 412.8 R 1.56(Caching ...........................\ +.......................................................................\ +............)2.5 F(30)26 E 2.5(4.9. Name)87 427.2 R(Serv)2.5 E +(er Access)-.15 E 23.5(................................................\ +.............................................................. 30)2.85 F +2.5(4.10. Mo)87 441.6 R(ving the Per)-.15 E(-User F)-.2 E(orw)-.15 E +(ard Files)-.1 E 23.5(.................................................\ +................................... 31)3.84 F 2.5(4.11. Free)87 456 R +1.85(Space ............................................................\ +...............................................................)2.5 F +(31)26 E 2.5(4.12. Maximum)87 470.4 R(Message Size)2.5 E 23.5(.........\ +.......................................................................\ +..................... 32)4.62 F 2.5(4.13. Pri)87 484.8 R -.25(va)-.25 G +.3 -.15(cy F).25 H 1.93(lags ..........................................\ +.......................................................................\ +......).15 F(32)26 E 2.5(4.14. Send)87 499.2 R(to Me T)2.5 E 2.08(oo ..\ +.......................................................................\ +..........................................)-.8 F(32)26 E 2.5(5. THE)72 +513.6 R(WHOLE SCOOP ON THE CONFIGURA)2.5 E(TION FILE)-1.11 E 23.5 +(........................................................ 32)4.64 F 2.5 +(5.1. R)87 528 R(and S \212 Re)2.5 E(writing Rules)-.25 E 23.5(........\ +.......................................................................\ +................... 32)4.3 F 2.5(5.1.1. The)102 542.4 R(left hand side) +2.5 E 23.5(............................................................\ +............................................. 33)4.07 F 2.5(5.1.2. The) +102 556.8 R(right hand side)2.5 E 23.5(................................\ +.......................................................................\ + 33)3.51 F 2.5(5.1.3. Semantics)102 571.2 R(of re)2.5 E +(writing rule sets)-.25 E 23.5(........................................\ +........................................... 34)4.6 F 2.5(5.1.4. Ruleset) +102 585.6 R 2.11(hooks ................................................\ +...............................................................)2.5 F +(35)26 E 2.5(5.1.4.1. check_relay)117 600 R 23.5(......................\ +.......................................................................\ +............. 35)2.69 F 2.5(5.1.4.2. check_mail)117 614.4 R 23.5(......\ +.......................................................................\ +............................. 36)4.9 F 2.5(5.1.4.3. check_rcpt)117 628.8 +R 23.5(................................................................\ +........................................... 36)4.63 F 2.5 +(5.1.4.4. check_compat)117 643.2 R 23.5(...............................\ +.......................................................................\ + 36)3.24 F 2.5(5.1.4.5. check_eoh)117 657.6 R 23.5(....................\ +.......................................................................\ +................. 36)3.24 F 2.5(5.1.4.6. check_etrn)117 672 R 23.5(....\ +.......................................................................\ +................................ 37)4.63 F 2.5(5.1.4.7. check_e)117 +686.4 R .89(xpn .......................................................\ +...................................................)-.15 F(37)26 E 2.5 +(5.1.4.8. check_vrfy)117 700.8 R 23.5(.................................\ +.......................................................................\ +... 37)3.52 F 2.5(5.1.4.9. trust_auth)117 715.2 R 23.5(................\ +.......................................................................\ +...................... 37)3.5 F EP +%%Page: 5 83 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Bold@0 SF(Sendmail Installation and Operation Guide)72 60 Q +(SMM:08-5)200.86 E/F1 10/Times-Roman@0 SF 2.5(5.1.5. IPC)102 96 R 1(mai\ +lers ..................................................................\ +.................................................)2.5 F(37)26 E 2.5 +(5.2. D)87 110.4 R 2.5<8a44>2.5 G(e\214ne Macro)-2.5 E 23.5(...........\ +.......................................................................\ +.............................. 37)3.52 F 2.5(5.3. C)87 124.8 R +(and F \212 De\214ne Classes)2.5 E 23.5(...............................\ +...................................................................... \ +42)2.67 F 2.5(5.4. M)87 139.2 R 2.5<8a44>2.5 G(e\214ne Mailer)-2.5 E +23.5(..................................................................\ +............................................. 43)3.79 F 2.5(5.5. H)87 +153.6 R 2.5<8a44>2.5 G(e\214ne Header)-2.5 E 23.5(.....................\ +.......................................................................\ +................... 47)3.25 F 2.5(5.6. O)87 168 R 2.5<8a53>2.5 G +(et Option)-2.5 E 23.5(................................................\ +..................................................................... 4\ +8)3.22 F 2.5(5.7. P)87 182.4 R 2.5<8a50>2.5 G(recedence De\214nitions) +-2.5 E 23.5(...........................................................\ +....................................... 61)2.96 F 2.5(5.8. V)87 196.8 R +2.5<8a43>2.5 G(on\214guration V)-2.5 E(ersion Le)-1.11 E -.15(ve)-.25 G +2.8(l.).15 G 23.5(.....................................................\ +................................... 61)-2.8 F 2.5(5.9. K)87 211.2 R 2.5 +<8a4b>2.5 G .3 -.15(ey F)-2.75 H(ile Declaration).15 E 23.5(...........\ +.......................................................................\ +................... 62)2.81 F 2.5(5.10. The)87 225.6 R(User Database)2.5 +E 23.5(................................................................\ +.............................................. 68)4.92 F 2.5 +(5.10.1. Structure)102 240 R(of the user database)2.5 E 23.5(..........\ +.......................................................................\ +.... 68)2.7 F 2.5(5.10.2. User)102 254.4 R(database semantics)2.5 E 23.5 +(......................................................................\ +....................... 68)3.25 F 2.5(5.10.3. Creating)102 270.8 R +(the database)2.5 E/F2 7/Times-Roman@0 SF(24)-4 I F1 23.5(.............\ +.......................................................................\ +........... 69)2.91 4 N 2.5(6. O)72 285.2 R(THER CONFIGURA)-.4 E 1.97(T\ +ION ...................................................................\ +......................................)-1.11 F(69)26 E 2.5(6.1. P)87 +299.6 R(arameters in de)-.15 E .3(vtools/OS/$oscf .....................\ +......................................................................) +-.25 F(69)26 E 2.5(6.2. P)87 314 R(arameters in sendmail/conf.h)-.15 E +23.5(..................................................................\ +............................ 70)4.78 F 2.5(6.3. Con\214guration)87 328.4 +R(in sendmail/conf.c)2.5 E 23.5(.......................................\ +................................................... 73)4.06 F 2.5 +(6.3.1. Built-in)102 342.8 R(Header Semantics)2.5 E 23.5(..............\ +.......................................................................\ +...... 73)4.9 F 2.5(6.3.2. Restricting)102 357.2 R(Use of Email)2.5 E +23.5(..................................................................\ +............................ 74)4.34 F 2.5(6.3.3. Ne)102 371.6 R 2.5(wD) +-.25 G(atabase Map Classes)-2.5 E 23.5(................................\ +......................................................... 75)4.89 F 2.5 +(6.3.4. Queueing)102 386 R 1.56(Function ..............................\ +.......................................................................\ +..)2.5 F(75)26 E 2.5(6.3.5. Refusing)102 400.4 R +(Incoming SMTP Connections)2.5 E 23.5(.................................\ +...................................... 76)2.94 F 2.5(6.3.6. Load)102 +414.8 R -1.17 -.74(Av e)2.5 H(rage Computation).74 E 23.5(.............\ +.......................................................................\ +...... 76)2.74 F 2.5(6.4. Con\214guration)87 429.2 R +(in sendmail/daemon.c)2.5 E 23.5(......................................\ +............................................... 76)2.67 F 2.5(7. A)72 +443.6 R(CKNO)-.4 E .1(WLEDGEMENTS .....................................\ +.......................................................................) +-.35 F(77)26 E(Appendix A.)72 458 Q(COMMAND LINE FLA)5 E 1.97(GS ......\ +.......................................................................\ +............)-.4 F(78)26 E(Appendix B.)72 472.4 Q -.1(QU)5 G +(EUE FILE FORMA).1 E 1.38(TS ..........................................\ +..................................................)-1.11 F(80)26 E +(Appendix C.)72 486.8 Q(SUMMAR)5 E 2.5(YO)-.65 G 2.5(FS)-2.5 G(UPPOR) +-2.5 E 2.5(TF)-.6 G 1.12(ILES .........................................\ +.....................................)-2.5 F(83)26 E EP +%%Page: 6 84 +%%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 +(This page intentionally left blank;)256.225 300 Q +(replace it with a blank sheet for double-sided output.)218.6 312 Q EP +%%Trailer +end +%%EOF diff --git a/gnu/usr.sbin/sendmail/include/libmilter/mfapi.h b/gnu/usr.sbin/sendmail/include/libmilter/mfapi.h new file mode 100644 index 00000000000..1a51cbaf78d --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/libmilter/mfapi.h @@ -0,0 +1,419 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: mfapi.h,v 8.13 2000/02/26 19:13:36 gshapiro Exp $ + */ + +/* +** MFAPI.H -- Global definitions for mail filter library and mail filters. +*/ + +#ifndef _LIBMILTER_MFAPI_H +# define _LIBMILTER_MFAPI_H 1 + +/* +** Access common MTA/libmilter constants +*/ + +# include "libmilter/milter.h" + +/* +** Currently this is a C-fied version of ~eric/public_html/mfapi.html +** It does not (yet) conform with the coding standard... +*/ + +/* +** status codes +*/ + +/* XXX maybe use enum? */ + +/* +** Continue processing message/connection. +*/ + +#define SMFIS_CONTINUE 0 + +/* +** Reject the message/connection. +** No further routines will be called for this message +** (or connection, if returned from a connection-oriented routine). +*/ + +#define SMFIS_REJECT 1 + +/* +** Accept the message, +** but silently discard the message. +** No further routines will be called for this message. +** This is only meaningful from message-oriented routines. +*/ + +#define SMFIS_DISCARD 2 + +/* +** Accept the message/connection. +** No further routines will be called for this message +** (or connection, if returned from a connection-oriented routine; +** in this case, it causes all messages on this connection +** to be accepted without filtering). +*/ + +#define SMFIS_ACCEPT 3 + +/* +** Return a temporary failure, i.e., +** the corresponding SMTP command will return a 4xx status code. +** In some cases this may prevent further routines from +** being called on this message or connection, +** although in other cases (e.g., when processing an envelope +** recipient) processing of the message will continue. +*/ +#define SMFIS_TEMPFAIL 4 + +/* type to store return value */ +typedef int sfsistat; + +/* for now ... */ +#if SOCKADDRHACK +# ifndef _SOCK_ADDR +# define _SOCK_ADDR struct sockaddr_in +# endif /* !_SOCK_ADDR */ +#else /* SOCKADDRHACK */ +# define NOT_SENDMAIL 1 +# include "sendmail.h" +# define _SOCK_ADDR SOCKADDR +#endif /* SOCKADDRHACK */ + +#include + +#ifndef MI_SUCCESS +# define MI_SUCCESS 0 +#endif /* MI_SUCCESS */ +#ifndef MI_FAILURE +# define MI_FAILURE (-1) +#endif /* MI_FAILURE */ + +/* "forward" declarations */ +typedef struct smfi_str SMFICTX; +typedef struct smfi_str *SMFICTX_PTR; + +typedef struct smfiDesc smfiDesc_str; +typedef struct smfiDesc * smfiDesc_ptr; + +# define MAX_MACROS_ENTRIES 4 /* max size of macro pointer array */ + +/* +** context for milter +** implementation hint: +** macros are stored in mac_buf[] as sequence of: +** macro_name \0 macro_value +** (just as read from the MTA) +** mac_ptr is a list of pointers into mac_buf to the beginning of each +** entry, i.e., macro_name, macro_value, ... +*/ + +struct smfi_str +{ + pthread_t ctx_id; /* thread id */ + int ctx_fd; /* filedescriptor */ + int ctx_dbg; /* debug level */ + time_t ctx_timeout; /* timeout */ + int ctx_state; /* state */ + smfiDesc_ptr ctx_smfi; /* filter description */ + char **ctx_mac_ptr[MAX_MACROS_ENTRIES]; + char *ctx_mac_buf[MAX_MACROS_ENTRIES]; + char *ctx_reply; /* reply code */ + void *ctx_privdata; /* private data */ +}; + +/* +** structure describing one milter +*/ + +struct smfiDesc +{ + char *xxfi_name; /* filter name */ + int xxfi_version; /* version code -- do not change */ + u_long xxfi_flags; /* flags */ + + /* connection info filter */ + sfsistat (*xxfi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); + + /* SMTP HELO command filter */ + sfsistat (*xxfi_helo) __P((SMFICTX *, char *)); + + /* envelope sender filter */ + sfsistat (*xxfi_envfrom) __P((SMFICTX *, char **)); + + /* envelope recipient filter */ + sfsistat (*xxfi_envrcpt) __P((SMFICTX *, char **)); + + /* header filter */ + sfsistat (*xxfi_header) __P((SMFICTX *, char *, char *)); + + /* end of header */ + sfsistat (*xxfi_eoh) __P((SMFICTX *)); + + /* body block */ + sfsistat (*xxfi_body) __P((SMFICTX *, u_char *, size_t)); + + /* end of message */ + sfsistat (*xxfi_eom) __P((SMFICTX *)); + + /* message aborted */ + sfsistat (*xxfi_abort) __P((SMFICTX *)); + + /* connection cleanup */ + sfsistat (*xxfi_close) __P((SMFICTX *)); +}; + +#if 0 +simple example what a filter program should do: + +int +main(argc, argv) + int argc; + char **argv; +{ + struct smfiDesc XxFilterDesc; + + /* fill in elements */ + smfi_register(XxFilterDesc); + smfi_main(); + /* NOTREACHED */ +} +#endif /* 0 */ + +extern int smfi_register __P((smfiDesc_str)); +extern int smfi_main __P((void)); +extern int smfi_setdbg __P((int)); +extern int smfi_settimeout __P((int)); +extern int smfi_setconn __P((char *)); + +/* +** Filter Routine Details +*/ + +#if 0 +/* connection info filter */ +extern sfsistat xxfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); + +/* +** xxfi_connect(ctx, hostname, hostaddr) Invoked on each connection +** +** char *hostname; Host domain name, as determined by a reverse lookup +** on the host address. +** _SOCK_ADDR *hostaddr; Host address, as determined by a getpeername +** call on the SMTP socket. +*/ + +/* SMTP HELO command filter */ +extern sfsistat xxfi_helo __P((SMFICTX *, char *)); + +/* +** xxfi_helo(ctx, helohost) Invoked on SMTP HELO/EHLO command +** +** char *helohost; Value passed to HELO/EHLO command, which should be +** the domain name of the sending host (but is, in practice, +** anything the sending host wants to send). +*/ + +/* envelope sender filter */ +extern sfsistat xxfi_envfrom __P((SMFICTX *, char **)); + +/* +** xxfi_envfrom(ctx, argv) Invoked on envelope from +** +** char **argv; Null-terminated SMTP command arguments; +** argv[0] is guaranteed to be the sender address. +** Later arguments are the ESMTP arguments. +*/ + +/* envelope recipient filter */ +extern sfsistat xxfi_envrcpt __P((SMFICTX *, char **)); + +/* +** xxfi_envrcpt(ctx, argv) Invoked on each envelope recipient +** +** char **argv; Null-terminated SMTP command arguments; +** argv[0] is guaranteed to be the recipient address. +** Later arguments are the ESMTP arguments. +*/ + +/* header filter */ +extern sfsistat xxfi_header __P((SMFICTX *, char *, char *)); + +/* +** xxfi_header(ctx, headerf, headerv) Invoked on each message header. The +** content of the header may have folded white space (that is, multiple +** lines with following white space) included. +** +** char *headerf; Header field name +** char *headerv; Header field value +*/ + +/* end of header */ +extern sfsistat xxfi_eoh __P((SMFICTX *)); + +/* +** xxfi_eoh(ctx) Invoked at end of header +*/ +#endif /* 0 */ + +/* body block */ +extern sfsistat xxfi_body __P((SMFICTX *, u_char *, size_t)); + +/* +** xxfi_body(ctx, bodyp, bodylen) Invoked for each body chunk. There may +** be multiple body chunks passed to the filter. End-of-lines are +** represented as received from SMTP (normally Carriage-Return/Line-Feed). +** +** u_char *bodyp; Pointer to body data +** size_t bodylen; Length of body data +*/ + +/* end of message */ +extern sfsistat xxfi_eom __P((SMFICTX *)); + +/* +** xxfi_eom(ctx) Invoked at end of message. This routine can perform +** special operations such as modifying the message header, body, or +** envelope. +*/ + +/* message aborted */ +extern sfsistat xxfi_abort __P((SMFICTX *)); + +/* +** xxfi_abort(ctx) Invoked if message is aborted outside of the control of +** the filter, for example, if the SMTP sender issues an RSET command. If +** xxfi_abort is called, xxfi_eom will not be called and vice versa. +*/ + +/* connection cleanup */ +extern sfsistat xxfi_close __P((SMFICTX *)); + +/* +** xxfi_close(ctx) Invoked at end of the connection. This is called on +** close even if the previous mail transaction was aborted. +*/ + + +/* +** Additional information is passed in to the vendor filter routines using +** symbols. Symbols correspond closely to sendmail macros. The symbols +** defined depend on the context. The value of a symbol is accessed using: +*/ + +/* Return the value of a symbol. */ +extern char * smfi_getsymval __P((SMFICTX *, char *)); + +/* +** Return the value of a symbol. +** +** SMFICTX *ctx; Opaque context structure +** char *symname; The name of the symbol to access. +*/ + +/* +** Vendor filter routines that want to pass additional information back to +** the MTA for use in SMTP replies may call smfi_setreply before returning. +*/ + +extern int smfi_setreply __P((SMFICTX *, char *, char *, char *)); + +/* +** Set the specific reply code to be used in response to the active +** command. If not specified, a generic reply code is used. +** +** SMFICTX *ctx; Opaque context structure +** char *rcode; The three-digit (RFC 821) SMTP reply code to be +** returned, e.g., ``551''. +** char *xcode; The extended (RFC 2034) reply code, e.g., ``5.7.6''. +** char *message; The text part of the SMTP reply. +*/ + +/* +** The xxfi_eom routine is called at the end of a message (essentially, +** after the final DATA dot). This routine can call some special routines +** to modify the envelope, header, or body of the message before the +** message is enqueued. These routines must not be called from any vendor +** routine other than xxfi_eom. +*/ + +extern int smfi_addheader __P((SMFICTX *, char *, char *)); + +/* +** Add a header to the message. This header is not passed to other +** filters. It is not checked for standards compliance; the mail filter +** must ensure that no protocols are violated as a result of adding this +** header. +** +** SMFICTX *ctx; Opaque context structure +** char *headerf; Header field name +** char *headerv; Header field value +*/ + +extern int smfi_addrcpt __P((SMFICTX *, char *)); + +/* +** Add a recipient to the envelope +** +** SMFICTX *ctx; Opaque context structure +** char *rcpt; Recipient to be added +*/ + +extern int smfi_delrcpt __P((SMFICTX *, char *)); + +/* +** Delete a recipient from the envelope +** +** SMFICTX *ctx; Opaque context structure +** char *rcpt; Envelope recipient to be deleted. This should be in +** exactly the form passed to xxfi_envrcpt or the address may +** not be deleted. +*/ + +extern int smfi_replacebody __P((SMFICTX *, u_char *, int)); + +/* +** Replace the body of the message. This routine may be called multiple +** times if the body is longer than convenient to send in one call. End of +** line should be represented as Carriage-Return/Line Feed. +** +** char *bodyp; Pointer to block of body information to insert +** int bodylen; Length of data pointed at by bodyp +*/ + +/* +** If the message is aborted (for example, if the SMTP sender sends the +** envelope but then does a QUIT or RSET before the data is sent), +** xxfi_abort is called. This can be used to reset state. +*/ + + +/* +** Connection-private data (specific to an SMTP connection) can be +** allocated using the smfi_setpriv routine; routines can access private +** data using smfi_getpriv. +*/ + +extern int smfi_setpriv __P((SMFICTX *, void *)); + +/* +** Set the private data pointer +** +** SMFICTX *ctx; Opaque context structure +** void *privatedata; Pointer to private data area +*/ + +extern void *smfi_getpriv __P((SMFICTX *)); + +#endif /* !_LIBMILTER_MFAPI_H */ diff --git a/gnu/usr.sbin/sendmail/include/libmilter/milter.h b/gnu/usr.sbin/sendmail/include/libmilter/milter.h new file mode 100644 index 00000000000..77da2e92f50 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/libmilter/milter.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: milter.h,v 8.24 1999/11/28 05:54:20 gshapiro Exp $ + */ + +/* +** MILTER.H -- Global definitions for mail filter and MTA. +*/ + +#ifndef _LIBMILTER_MILTER_H +# define _LIBMILTER_MILTER_H 1 + +/* Shared protocol constants */ +# define MILTER_LEN_BYTES 4 /* length of 32 bit integer in bytes */ +# define MILTER_CHUNK_SIZE 65535 /* body chunk size */ +# define SMFI_VERSION 1 /* version number */ + +/* address families */ +# define SMFIA_UNKNOWN 'U' /* unknown */ +# define SMFIA_UNIX 'L' /* unix/local */ +# define SMFIA_INET '4' /* inet */ +# define SMFIA_INET6 '6' /* inet6 */ + +/* commands: don't use anything smaller than ' ' */ +# define SMFIC_ABORT 'A' /* Abort */ +# define SMFIC_BODY 'B' /* Body chunk */ +# define SMFIC_CONNECT 'C' /* Connection information */ +# define SMFIC_MACRO 'D' /* Define macro */ +# define SMFIC_BODYEOB 'E' /* final body chunk (End) */ +# define SMFIC_HELO 'H' /* HELO/EHLO */ +# define SMFIC_HEADER 'L' /* Header */ +# define SMFIC_MAIL 'M' /* MAIL from */ +# define SMFIC_EOH 'N' /* EOH */ +# define SMFIC_OPTNEG 'O' /* Option negotiation */ +# define SMFIC_QUIT 'Q' /* QUIT */ +# define SMFIC_RCPT 'R' /* RCPT to */ + +/* actions (replies) */ +# define SMFIR_ADDRCPT '+' /* add recipient */ +# define SMFIR_DELRCPT '-' /* remove recipient */ +# define SMFIR_ACCEPT 'a' /* accept */ +# define SMFIR_REPLBODY 'b' /* replace body (chunk) */ +# define SMFIR_CONTINUE 'c' /* continue */ +# define SMFIR_DISCARD 'd' /* discard */ +# define SMFIR_PROGRESS 'p' /* progress */ +# define SMFIR_REJECT 'r' /* reject */ +# define SMFIR_TEMPFAIL 't' /* tempfail */ +# define SMFIR_ADDHEADER 'h' /* add header */ +# define SMFIR_REPLYCODE 'y' /* reply code etc */ + +/* values for filter negotiation flags */ +# define SMFIF_MODHDRS 0x00000001L /* filter may add headers */ +# define SMFIF_MODBODY 0x00000002L /* filter may replace body */ +# define SMFIF_ADDRCPT 0x00000004L /* filter may add recipients */ +# define SMFIF_DELRCPT 0x00000008L /* filter may delete recipients */ +# define SMFIF_NOCONNECT 0x00000010L /* MTA should not send connect info */ +# define SMFIF_NOHELO 0x00000020L /* MTA should not send HELO info */ +# define SMFIF_NOMAIL 0x00000040L /* MTA should not send MAIL info */ +# define SMFIF_NORCPT 0x00000080L /* MTA should not send RCPT info */ +# define SMFIF_NOBODY 0x00000100L /* MTA should not send body */ +# define SMFIF_NOHDRS 0x00000200L /* MTA should not send headers */ + +#endif /* !_LIBMILTER_MILTER_H */ diff --git a/gnu/usr.sbin/sendmail/include/libsmdb/smdb.h b/gnu/usr.sbin/sendmail/include/libsmdb/smdb.h new file mode 100644 index 00000000000..0503fa36582 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/libsmdb/smdb.h @@ -0,0 +1,371 @@ +/* +** Copyright (c) 1999 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** By using this file, you agree to the terms and conditions set +** forth in the LICENSE file which can be found at the top level of +** the sendmail distribution. +** +** $Sendmail: smdb.h,v 8.26 2000/03/02 09:03:05 msk Exp $ +*/ + +#ifndef _SMDB_H_ +# define _SMDB_H_ + +# include +# include +# ifndef __P +# include "sendmail/cdefs.h" +# endif /* __P */ + +# ifdef NDBM +# include +# endif /* NDBM */ + +# ifdef NEWDB +# include +# ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +# endif /* ! DB_VERSION_MAJOR */ +# endif /* NEWDB */ + +/* +** Some size constants +*/ +#define SMDB_MAX_USER_NAME_LEN 1024 +#define SMDB_MAX_NAME_LEN 1024 + +/* +** This file defines the abstraction for database lookups. It is pretty +** much a copy of the db2 interface with the exception that every function +** returns 0 on success and non-zero on failure. The non-zero return code +** is meaningful. +** +** I'm going to put the function comments in this file since the interface +** MUST be the same for all inheritors of this interface. +*/ + +typedef struct database_struct SMDB_DATABASE; +typedef struct cursor_struct SMDB_CURSOR; +typedef union database_entity_union SMDB_DBENT; + + +/* +** DB_CLOSE_FUNC -- close the database +** +** Parameters: +** db -- The database to close. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_close_func) __P((SMDB_DATABASE *db)); + + + +/* +** DB_DEL_FUNC -- removes a key and data pair from the database +** +** Parameters: +** db -- The database to close. +** key -- The key to remove. +** flags -- delete options. There are currently no defined +** flags for delete. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_del_func) __P((SMDB_DATABASE *db, + SMDB_DBENT *key, u_int flags)); + + + +/* +** DB_FD_FUNC -- Returns a pointer to a file used for the database. +** +** Parameters: +** db -- The database to close. +** fd -- A pointer to store the returned fd in. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_fd_func) __P((SMDB_DATABASE *db, int* fd)); + + + +/* +** DB_GET_FUNC -- Gets the data associated with a key. +** +** Parameters: +** db -- The database to close. +** key -- The key to access. +** data -- A place to store the returned data. +** flags -- get options. There are currently no defined +** flags for get. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_get_func) __P((SMDB_DATABASE *db, + SMDB_DBENT *key, + SMDB_DBENT *data, u_int flags)); + + + +/* +** DB_PUT_FUNC -- Sets some data according to the key. +** +** Parameters: +** db -- The database to close. +** key -- The key to use. +** data -- The data to store. +** flags -- put options: +** SMDBF_NO_OVERWRITE - Return an error if key alread +** exists. +** SMDBF_ALLOW_DUP - Allow duplicates in btree maps. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_put_func) __P((SMDB_DATABASE *db, + SMDB_DBENT *key, + SMDB_DBENT *data, u_int flags)); + + +/* +** DB_SYNC_FUNC -- Flush any cached information to disk. +** +** Parameters: +** db -- The database to sync. +** flags -- sync options: +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_sync_func) __P((SMDB_DATABASE *db, u_int flags)); + + +/* +** DB_SET_OWNER_FUNC -- Set the owner and group of the database files. +** +** Parameters: +** db -- The database to set. +** uid -- The UID for the new owner (-1 for no change) +** gid -- The GID for the new owner (-1 for no change) +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_set_owner_func) __P((SMDB_DATABASE *db, uid_t uid, + gid_t gid)); + + +/* +** DB_CURSOR -- Obtain a cursor for sequential access +** +** Parameters: +** db -- The database to use. +** cursor -- The address of a cursor pointer. +** flags -- sync options: +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_cursor_func) __P((SMDB_DATABASE *db, + SMDB_CURSOR **cursor, u_int flags)); + + +struct database_struct +{ + db_close_func smdb_close; + db_del_func smdb_del; + db_fd_func smdb_fd; + db_get_func smdb_get; + db_put_func smdb_put; + db_sync_func smdb_sync; + db_set_owner_func smdb_set_owner; + db_cursor_func smdb_cursor; + void *smdb_impl; +}; + + + +/* +** DB_CURSOR_CLOSE -- Close a cursor +** +** Parameters: +** cursor -- The cursor to close. +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_cursor_close_func) __P((SMDB_CURSOR *cursor)); + + +/* +** DB_CURSOR_DEL -- Delete the key/value pair of this cursor +** +** Parameters: +** cursor -- The cursor. +** flags -- flags +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_cursor_del_func) __P((SMDB_CURSOR *cursor, u_int flags)); + + +/* +** DB_CURSOR_GET -- Get the key/value of this cursor. +** +** Parameters: +** cursor -- The cursor. +** key -- The current key. +** value -- The current value +** flags -- flags +** +** Returns: +** 0 - Success, otherwise errno. +** SMDBE_LAST_ENTRY - This is a success condition that +** gets returned when the end of the +** database is hit. +** +*/ +typedef int (*db_cursor_get_func) __P((SMDB_CURSOR *cursor, + SMDB_DBENT *key, + SMDB_DBENT *data, + u_int flags)); + +/* +** Flags for DB_CURSOR_GET +*/ +#define SMDB_CURSOR_GET_FIRST 0 +#define SMDB_CURSOR_GET_LAST 1 +#define SMDB_CURSOR_GET_NEXT 2 + + +/* +** DB_CURSOR_PUT -- Put the key/value at this cursor. +** +** Parameters: +** cursor -- The cursor. +** key -- The current key. +** value -- The current value +** flags -- flags +** +** Returns: +** 0 - Success, otherwise errno. +** +*/ +typedef int (*db_cursor_put_func) __P((SMDB_CURSOR *cursor, + SMDB_DBENT *key, + SMDB_DBENT *data, + u_int flags)); + + + +struct cursor_struct +{ + db_cursor_close_func smdbc_close; + db_cursor_del_func smdbc_del; + db_cursor_get_func smdbc_get; + db_cursor_put_func smdbc_put; + void *smdbc_impl; +}; + + +struct database_params_struct +{ + u_int smdbp_num_elements; + u_int smdbp_cache_size; + bool smdbp_allow_dup; +}; + +typedef struct database_params_struct SMDB_DBPARAMS; + +struct database_user_struct +{ + uid_t smdbu_id; + gid_t smdbu_group_id; + char smdbu_name[SMDB_MAX_USER_NAME_LEN]; +}; + +typedef struct database_user_struct SMDB_USER_INFO; + +union database_entity_union +{ +# ifdef NDBM + datum dbm; +# endif /* NDBM */ +# ifdef NEWDB + DBT db; +# endif /* NEWDB */ + struct + { + char *data; + size_t size; + } data; +}; + + +typedef char *SMDB_DBTYPE; +typedef u_int SMDB_FLAG; + +/* +** These are types of databases. +*/ + +# define SMDB_TYPE_DEFAULT NULL +# define SMDB_TYPE_DEFAULT_LEN 0 +# define SMDB_TYPE_HASH "hash" +# define SMDB_TYPE_HASH_LEN 5 +# define SMDB_TYPE_BTREE "btree" +# define SMDB_TYPE_BTREE_LEN 6 +# define SMDB_TYPE_NDBM "dbm" +# define SMDB_TYPE_NDBM_LEN 4 + +/* +** These are flags +*/ +/* Flags for put */ +# define SMDBF_NO_OVERWRITE 0x00000001 +# define SMDBF_ALLOW_DUP 0x00000002 + + +extern SMDB_DATABASE *smdb_malloc_database __P((void)); +extern void smdb_free_database __P((SMDB_DATABASE *)); +extern int smdb_open_database __P((SMDB_DATABASE **, char *, int, + int, int, SMDB_DBTYPE, + SMDB_USER_INFO *, + SMDB_DBPARAMS *)); +# ifdef NEWDB +extern int smdb_db_open __P((SMDB_DATABASE **, char *, int, int, + int, SMDB_DBTYPE, SMDB_USER_INFO *, + SMDB_DBPARAMS *)); +# endif /* NEWDB */ +# ifdef NDBM +extern int smdb_ndbm_open __P((SMDB_DATABASE **, char *, int, int, + int, SMDB_DBTYPE, SMDB_USER_INFO *, + SMDB_DBPARAMS *)); +# endif /* NDBM */ +extern int smdb_add_extension __P((char *, int, char *, char *)); +extern int smdb_setup_file __P((char *, char *, int, int, + SMDB_USER_INFO *, struct stat *)); +extern int smdb_lock_file __P((int *, char *, int, int, char *)); +extern int smdb_unlock_file __P((int)); +extern int smdb_filechanged __P((char *, char *, int, + struct stat *)); +extern void smdb_print_available_types __P((void)); +extern char *smdb_db_definition __P((SMDB_DBTYPE)); +#endif /* ! _SMDB_H_ */ diff --git a/gnu/usr.sbin/sendmail/include/sendmail/cdefs.h b/gnu/usr.sbin/sendmail/include/sendmail/cdefs.h new file mode 100644 index 00000000000..3b4691c6924 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/cdefs.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: cdefs.h,v 8.5 1999/06/02 22:32:17 gshapiro Exp $ + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + */ + +#ifndef _CDEFS_H_ +# define _CDEFS_H_ + +# if defined(__cplusplus) +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS }; +# else /* defined(__cplusplus) */ +# define __BEGIN_DECLS +# define __END_DECLS +# endif /* defined(__cplusplus) */ + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ +# if defined(__STDC__) || defined(__cplusplus) +# define __P(protos) protos /* full-blown ANSI C */ +# ifndef __CONCAT +# define __CONCAT(x,y) x ## y +# endif /* ! __CONCAT */ +# define __STRING(x) #x + +# ifndef __const +# define __const const /* define reserved names to standard */ +# endif /* ! __const */ +# define __signed signed +# define __volatile volatile +# if defined(__cplusplus) +# define __inline inline /* convert to C++ keyword */ +# else /* defined(__cplusplus) */ +# ifndef __GNUC__ +# define __inline /* delete GCC keyword */ +# endif /* ! __GNUC__ */ +# endif /* defined(__cplusplus) */ + +# else /* defined(__STDC__) || defined(__cplusplus) */ +# define __P(protos) () /* traditional C preprocessor */ +# ifndef __CONCAT +# define __CONCAT(x,y) x/**/y +# endif /* ! __CONCAT */ +# define __STRING(x) "x" + +# ifndef __GNUC__ +# define __const /* delete pseudo-ANSI C keywords */ +# define __inline +# define __signed +# define __volatile +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * When using a compiler other than gcc, programs using the ANSI C keywords + * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. + * When using "gcc -traditional", we assume that this is the intent; if + * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. + */ +# ifndef NO_ANSI_KEYWORDS +# define const /* delete ANSI C keywords */ +# define inline +# define signed +# define volatile +# endif /* ! NO_ANSI_KEYWORDS */ +# endif /* ! __GNUC__ */ +# endif /* defined(__STDC__) || defined(__cplusplus) */ + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +# if !defined(__GNUC__) || __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +# define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +# if defined(__GNUC__) && !defined(__STRICT_ANSI__) +# define __dead __volatile +# define __pure __const +# endif /* defined(__GNUC__) && !defined(__STRICT_ANSI__) */ +# endif /* !defined(__GNUC__) || __GNUC__ < 2 || \ */ + +/* Delete pseudo-keywords wherever they are not available or needed. */ +# ifndef __dead +# define __dead +# define __pure +# endif /* ! __dead */ + +#endif /* ! _CDEFS_H_ */ diff --git a/gnu/usr.sbin/sendmail/include/sendmail/errstring.h b/gnu/usr.sbin/sendmail/include/sendmail/errstring.h new file mode 100644 index 00000000000..56a5ff2753c --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/errstring.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: errstring.h,v 8.6 2000/02/26 01:32:11 gshapiro Exp $ + */ + +/* +** ERRSTRING.H -- Error codes. +*/ + +#include + +extern int errno; + +/* +** 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 /* ! E_PSEUDOBASE */ + +#define E_SM_OPENTIMEOUT (E_PSEUDOBASE + 0) /* Timeout on file open */ +#define E_SM_NOSLINK (E_PSEUDOBASE + 1) /* Symbolic links not allowed */ +#define E_SM_NOHLINK (E_PSEUDOBASE + 2) /* Hard links not allowed */ +#define E_SM_REGONLY (E_PSEUDOBASE + 3) /* Regular files only */ +#define E_SM_ISEXEC (E_PSEUDOBASE + 4) /* Executable files not allowed */ +#define E_SM_WWDIR (E_PSEUDOBASE + 5) /* World writable directory */ +#define E_SM_GWDIR (E_PSEUDOBASE + 6) /* Group writable directory */ +#define E_SM_FILECHANGE (E_PSEUDOBASE + 7) /* File changed after open */ +#define E_SM_WWFILE (E_PSEUDOBASE + 8) /* World writable file */ +#define E_SM_GWFILE (E_PSEUDOBASE + 9) /* Group writable file */ +#define E_SM_GRFILE (E_PSEUDOBASE + 10) /* g readable file */ +#define E_SM_WRFILE (E_PSEUDOBASE + 11) /* o readable file */ +#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */ +#define E_SMDBBASE (E_PSEUDOBASE + 40) /* base for libsmdb errors */ +#define E_LDAPBASE (E_PSEUDOBASE + 70) /* base for LDAP errors */ + +/* libsmdb */ +#define SMDBE_OK 0 +#define SMDBE_MALLOC (E_SMDBBASE + 1) +#define SMDBE_GDBM_IS_BAD (E_SMDBBASE + 2) +#define SMDBE_UNSUPPORTED (E_SMDBBASE + 3) +#define SMDBE_DUPLICATE (E_SMDBBASE + 4) +#define SMDBE_BAD_OPEN (E_SMDBBASE + 5) +#define SMDBE_NOT_FOUND (E_SMDBBASE + 6) +#define SMDBE_UNKNOWN_DB_TYPE (E_SMDBBASE + 7) +#define SMDBE_UNSUPPORTED_DB_TYPE (E_SMDBBASE + 8) +#define SMDBE_INCOMPLETE (E_SMDBBASE + 9) +#define SMDBE_KEY_EMPTY (E_SMDBBASE + 10) +#define SMDBE_KEY_EXIST (E_SMDBBASE + 11) +#define SMDBE_LOCK_DEADLOCK (E_SMDBBASE + 12) +#define SMDBE_LOCK_NOT_GRANTED (E_SMDBBASE + 13) +#define SMDBE_LOCK_NOT_HELD (E_SMDBBASE + 14) +#define SMDBE_RUN_RECOVERY (E_SMDBBASE + 15) +#define SMDBE_IO_ERROR (E_SMDBBASE + 16) +#define SMDBE_READ_ONLY (E_SMDBBASE + 17) +#define SMDBE_DB_NAME_TOO_LONG (E_SMDBBASE + 18) +#define SMDBE_INVALID_PARAMETER (E_SMDBBASE + 19) +#define SMDBE_ONLY_SUPPORTS_ONE_CURSOR (E_SMDBBASE + 20) +#define SMDBE_NOT_A_VALID_CURSOR (E_SMDBBASE + 21) +#define SMDBE_LAST_ENTRY (E_SMDBBASE + 22) +#define SMDBE_OLD_VERSION (E_SMDBBASE + 23) + +extern const char *errstring __P((int)); diff --git a/gnu/usr.sbin/sendmail/include/sendmail/mailstats.h b/gnu/usr.sbin/sendmail/include/sendmail/mailstats.h new file mode 100644 index 00000000000..5dc69b563a9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/mailstats.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: mailstats.h,v 8.13 1999/05/22 02:29:10 ca Exp $ + */ + +#define STAT_VERSION 3 +#define STAT_MAGIC 0x1B1DE + +/* +** Statistics structure. +*/ + +struct statistics +{ + int stat_magic; /* magic number */ + int stat_version; /* stat file version */ + time_t stat_itime; /* file initialization time */ + short stat_size; /* size of this structure */ + long stat_cf; /* # from connections */ + long stat_ct; /* # to connections */ + long stat_cr; /* # rejected connections */ + long stat_nf[MAXMAILERS]; /* # msgs from each mailer */ + long stat_bf[MAXMAILERS]; /* kbytes from each mailer */ + long stat_nt[MAXMAILERS]; /* # msgs to each mailer */ + long stat_bt[MAXMAILERS]; /* kbytes to each mailer */ + long stat_nr[MAXMAILERS]; /* # rejects by each mailer */ + long stat_nd[MAXMAILERS]; /* # discards by each mailer */ +}; diff --git a/gnu/usr.sbin/sendmail/include/sendmail/pathnames.h b/gnu/usr.sbin/sendmail/include/sendmail/pathnames.h new file mode 100644 index 00000000000..2e68adaac1e --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/pathnames.h @@ -0,0 +1,34 @@ +/*- + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: pathnames.h,v 8.16 2000/02/01 05:49:50 gshapiro Exp $ + */ + +#ifndef _PATH_SENDMAILCF +# if defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) +# define _PATH_SENDMAILCF _PATH_VENDOR_CF +# else /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ +# define _PATH_SENDMAILCF "/etc/mail/sendmail.cf" +# endif /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ +#endif /* ! _PATH_SENDMAILCF */ + +#ifndef _PATH_SENDMAILPID +# ifdef BSD4_4 +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# else /* BSD4_4 */ +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* BSD4_4 */ +#endif /* ! _PATH_SENDMAILPID */ + +#ifndef _PATH_HOSTS +# define _PATH_HOSTS "/etc/hosts" +#endif /* ! _PATH_HOSTS */ + diff --git a/gnu/usr.sbin/sendmail/include/sendmail/sendmail.h b/gnu/usr.sbin/sendmail/include/sendmail/sendmail.h new file mode 100644 index 00000000000..1deb635b362 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/sendmail.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: sendmail.h,v 8.33 2000/02/17 21:30:34 ca Exp $ + */ + +/* +** SENDMAIL.H -- Global definitions for sendmail. +*/ + +# include +#include +#include "conf.h" +#include "sendmail/errstring.h" +#include "sendmail/useful.h" + + +/********************************************************************** +** Table sizes, etc.... +** There shouldn't be much need to change these.... +**********************************************************************/ +#ifndef MAXMAILERS +# define MAXMAILERS 25 /* maximum mailers known to system */ +#endif /* ! MAXMAILERS */ + +/* +** 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 BITMAPBITS 256 /* number of bits in a bit map */ +#define BYTEBITS 8 /* number of bits in a byte */ +#define BITMAPBYTES (BITMAPBITS / BYTEBITS) /* number of bytes in bit map */ + +/* internal macros */ +#define _BITWORD(bit) ((bit) / (BYTEBITS * sizeof (int))) +#define _BITBIT(bit) ((unsigned int)1 << ((bit) % (BYTEBITS * sizeof (int)))) + +typedef unsigned int BITMAP256[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) memset((char *) map, '\0', BITMAPBYTES) + + +/* +** Utility macros +*/ + +/* return number of bytes left in a buffer */ +#define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) +/* +** Flags passed to safefile/safedirpath. +*/ + +#define SFF_ANYFILE 0L /* no special restrictions */ +#define SFF_MUSTOWN 0x00000001L /* user must own this file */ +#define SFF_NOSLINK 0x00000002L /* file cannot be a symbolic link */ +#define SFF_ROOTOK 0x00000004L /* ok for root to own this file */ +#define SFF_RUNASREALUID 0x00000008L /* if no ctladdr, run as real uid */ +#define SFF_NOPATHCHECK 0x00000010L /* don't bother checking dir path */ +#define SFF_SETUIDOK 0x00000020L /* setuid files are ok */ +#define SFF_CREAT 0x00000040L /* ok to create file if necessary */ +#define SFF_REGONLY 0x00000080L /* regular files only */ +#define SFF_SAFEDIRPATH 0x00000100L /* no writable directories allowed */ +#define SFF_NOHLINK 0x00000200L /* file cannot have hard links */ +#define SFF_NOWLINK 0x00000400L /* links only in non-writable dirs */ +#define SFF_NOGWFILES 0x00000800L /* disallow world writable files */ +#define SFF_NOWWFILES 0x00001000L /* disallow group writable files */ +#define SFF_NOGRFILES 0x00008000L /* disallow g readable files */ +#define SFF_NOWRFILES 0x00010000L /* disallow o readable files */ +#define SFF_NORFILES (SFF_NOGRFILES|SFF_NOWRFILES) + +/* flags that are actually specific to safeopen/safefopen/dfopen */ +#define SFF_OPENASROOT 0x00002000L /* open as root instead of real user */ +#define SFF_NOLOCK 0x00004000L /* don't lock the file */ +#define SFF_NOTEXCL 0x00010000L /* creates don't need to be exclusive */ +#define SFF_EXECOK 0x00020000L /* executable files are ok (E_SM_ISEXEC) */ + +/* pseudo-flags */ +#define SFF_NOLINK (SFF_NOHLINK|SFF_NOSLINK) + +/* functions */ +extern int safefile __P((char *, UID_T, GID_T, char *, long, int, struct stat *)); +extern int safedirpath __P((char *, UID_T, GID_T, char *, long, int, int)); +extern int safeopen __P((char *, int, int, long)); +extern FILE *safefopen __P((char *, int, int, long)); +extern int dfopen __P((char *, int, int, long)); +extern bool filechanged __P((char *, int, struct stat *)); + +/* +** DontBlameSendmail options +** +** Hopefully nobody uses these. +*/ +#define DBS_SAFE 0 +#define DBS_ASSUMESAFECHOWN 1 +#define DBS_GROUPWRITABLEDIRPATHSAFE 2 +#define DBS_GROUPWRITABLEFORWARDFILESAFE 3 +#define DBS_GROUPWRITABLEINCLUDEFILESAFE 4 +#define DBS_GROUPWRITABLEALIASFILE 5 +#define DBS_WORLDWRITABLEALIASFILE 6 +#define DBS_FORWARDFILEINUNSAFEDIRPATH 7 +#define DBS_MAPINUNSAFEDIRPATH 8 +#define DBS_LINKEDALIASFILEINWRITABLEDIR 9 +#define DBS_LINKEDCLASSFILEINWRITABLEDIR 10 +#define DBS_LINKEDFORWARDFILEINWRITABLEDIR 11 +#define DBS_LINKEDINCLUDEFILEINWRITABLEDIR 12 +#define DBS_LINKEDMAPINWRITABLEDIR 13 +#define DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR 14 +#define DBS_FILEDELIVERYTOHARDLINK 15 +#define DBS_FILEDELIVERYTOSYMLINK 16 +#define DBS_WRITEMAPTOHARDLINK 17 +#define DBS_WRITEMAPTOSYMLINK 18 +#define DBS_WRITESTATSTOHARDLINK 19 +#define DBS_WRITESTATSTOSYMLINK 20 +#define DBS_FORWARDFILEINGROUPWRITABLEDIRPATH 21 +#define DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH 22 +#define DBS_CLASSFILEINUNSAFEDIRPATH 23 +#define DBS_ERRORHEADERINUNSAFEDIRPATH 24 +#define DBS_HELPFILEINUNSAFEDIRPATH 25 +#define DBS_FORWARDFILEINUNSAFEDIRPATHSAFE 26 +#define DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE 27 +#define DBS_RUNPROGRAMINUNSAFEDIRPATH 28 /* Not used yet */ +#define DBS_RUNWRITABLEPROGRAM 29 +#define DBS_INCLUDEFILEINUNSAFEDIRPATH 30 +#define DBS_NONROOTSAFEADDR 31 +#define DBS_TRUSTSTICKYBIT 32 +#define DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH 33 +#if _FFR_UNSAFE_SASL +#define DBS_GROUPREADABLESASLFILE 34 +#endif /* _FFR_UNSAFE_SASL */ + +/* struct defining such things */ +struct dbsval +{ + char *dbs_name; /* name of DontBlameSendmail flag */ + u_char dbs_flag; /* numeric level */ +}; + +#if _FFR_DPRINTF +extern void dprintf __P((const char *, ...)); +extern int dflush __P((void)); +#else /* _FFR_DPRINTF */ +#define dprintf printf +#define dflush() fflush(stdout) +#endif /* _FFR_DPRINTF */ + +#if !HASSNPRINTF +extern int snprintf __P((char *, size_t, const char *, ...)); +extern int vsnprintf __P((char *, size_t, const char *, va_list)); +#endif /* !HASSNPRINTF */ +extern char *quad_to_string __P((QUAD_T)); + +extern size_t strlcpy __P((char *, const char *, size_t)); +extern size_t strlcat __P((char *, const char *, size_t)); diff --git a/gnu/usr.sbin/sendmail/include/sendmail/useful.h b/gnu/usr.sbin/sendmail/include/sendmail/useful.h new file mode 100644 index 00000000000..10f35a12707 --- /dev/null +++ b/gnu/usr.sbin/sendmail/include/sendmail/useful.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: useful.h,v 8.18 1999/07/13 15:05:57 ca Exp $ + */ + +#ifndef _USEFUL_H +# define _USEFUL_H + +# include + +/* support for bool type */ +typedef int bool; +# ifndef TRUE +# define TRUE 1 +# define FALSE 0 +# endif /* ! TRUE */ + +# 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 /* ! max */ + +/* 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 /* __STDC__ */ +# define SCCSID(arg) static char SccsId[] = "arg"; +# endif /* __STDC__ */ +# else /* ! lint */ +# define SCCSID(arg) +# endif /* ! lint */ +#endif /* ! _USEFUL_H */ diff --git a/gnu/usr.sbin/sendmail/libmilter/Build b/gnu/usr.sbin/sendmail/libmilter/Build new file mode 100644 index 00000000000..2c5643c1a9d --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.3 2000/01/20 21:51:50 geir Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/libmilter/Makefile b/gnu/usr.sbin/sendmail/libmilter/Makefile new file mode 100644 index 00000000000..6cc9156fafc --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 1.1 1999/11/04 00:03:40 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/libmilter/Makefile.m4 b/gnu/usr.sbin/sendmail/libmilter/Makefile.m4 new file mode 100644 index 00000000000..9ac7760da2c --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/Makefile.m4 @@ -0,0 +1,15 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +define(`confMT', `true') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`library', `libmilter') +define(`bldSOURCES', `main.c engine.c listener.c handler.c comm.c smfi.c signal.c sm_gethost.c ') +bldPUSH_SMLIB(`smutil') +bldPRODUCT_END +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/libmilter/README b/gnu/usr.sbin/sendmail/libmilter/README new file mode 100644 index 00000000000..d5cc134b464 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/README @@ -0,0 +1,378 @@ +This directory contains the source files for libmilter. + +The sendmail Mail Filter API (Milter) is designed to allow third-party +programs access to mail messages as they are being processed in order to +filter meta-information and content. + +This README file describes the steps needed to compile and run a filter, +through reference to a sample filter which is attached at the end of this +file. It is necessary to first build libmilter.a, which can be done by +issuing the './Build' command in SRCDIR/libmilter . + + ++-------------------+ +| BUILDING A FILTER | ++-------------------+ + +The following command presumes that the sample code from the end of this +README is saved to a file named 'sample.c' and built in the local platform- +specific build subdirectory (SRCDIR/obj.*/libmilter). + + cc -I../../sendmail -I../../include -o sample sample.c -L. -lmilter -pthread + +It is recommended that you build your filters in a location outside of +the sendmail source tree. Modify the compiler include references (-I) +and linker library locations (-L) accordingly. + +Filters must be thread-safe! Many operating systems now provide support for +POSIX threads in the standard C libraries. The compiler flag to link with +threading support differs according to the compiler and linker used. Check +the Makefile in your appropriate obj.*/libmilter build subdirectory if you +are unsure of the local flag used. + + ++----------------------------------------+ +| SPECIFYING FILTERS IN SENDMAIL CONFIGS | ++----------------------------------------+ + +Filters are specified with a key letter ``X'' (for ``eXternal''). + +For example: + + Xfilter1, S=unix:/var/run/f1.sock, F=R + Xfilter2, S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m + Xfilter3, S=inet:3333@localhost + +specifies three filters. Filters can be specified in your .mc file using +the following: + + INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R') + INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m') + INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') + +The first attaches to a Unix-domain socket in the /var/run directory; the +second uses an IPv6 socket on port 999 of localhost, and the third uses an +IPv4 socket on port 3333 of localhost. The current flags (F=) are: + + R Reject connection if filter unavailable + T Temporary fail connection if filter unavailable + +Finally, you can override the default timeouts used by sendmail when +talking to the filters using the T= equate. There are three fields inside +of the T= equate: + +Letter Meaning + S Timeout for sending information from the MTA to a filter + R Timeout for reading reply from the filter + E Overall timeout between sending end-of-message to filter + and waiting for the final acknowledgment + +Note the separator between each is a ';' as a ',' already separates equates +and therefore can't separate timeouts. The default values (if not set in the config) are: + +T=S:10s;R:10s;E:5m + +where 's' is seconds and 'm' is minutes. + +Actual sequencing is handled by the InputMailFilters option which is set +automatically according to the order of the INPUT_MAIL_FILTER commands +in your .mc file. Alternatively, you can reset it's value by setting +confINPUT_MAIL_FILTERS in your .mc file. This options causes the three +filters to be called in the same order they were specified. It allows +for possible future filtering on output (although this is not intended +for this release). + +Also note that a filter can be defined without adding it to the input +filter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your +.mc file. + +To test sendmail with the sample filter, the following might be added (in +the appropriate locations) to your .mc file: + + INPUT_MAIL_FILTER(`sample', `S=unix:/var/run/f1.sock') + + ++------------------+ +| TESTING A FILTER | ++------------------+ + +Once you have compiled a filter, modified your .mc file and restarted +the sendmail process, you will want to test that the filter performs as +intended. + +The sample filter takes one argument -p, which indicates the local port +on which to create a listening socket for the filter. Maintaining +consistency with the suggested options for sendmail.cf, this would be the +UNIX domain socket located in /var/run/f1.sock. + + % ./sample -p unix:/var/run/f1.sock + +If the sample filter returns immediately to a command line, there was either +an error with your command or a problem creating the specified socket. +Further logging can be captured through the syslogd daemon. Using the +'netstat -a' command can ensure that your filter process is listening on +the appropriate local socket. + +Email messages must be injected via SMTP to be filtered. There are two +simple means of doing this; either using the 'sendmail -bs' command, or +by telnetting to port 25 of the machine configured for milter. Once +connected via one of these options, the session can be continued through +the use of standard SMTP commands. + +% sendmail -bs +220 test.sendmail.com ESMTP Sendmail 8.10.0.Beta8/8.10.0.Beta8; Mon, 6 Dec 1999 19:34:23 -0800 (PST) +HELO localhost +250 test.sendmail.com Hello testy@localhost, pleased to meet you +MAIL From: +250 2.1.0 ... Sender ok +RCPT To: +250 2.1.5 ... Recipient ok +DATA +354 Enter mail, end with "." on a line by itself +From: testy@test.sendmail.com +To: root@test.sendmail.com +Subject: testing sample filter + +Sample body +. +250 2.0.0 dB73Zxi25236 Message accepted for delivery +QUIT +221 2.0.0 test.sendmail.com closing connection + +In the above example, the lines beginning with numbers are output by the +mail server, and those without are your input. If everything is working +properly, you will find a file in /tmp by the name of msg.XXXXXXXX (where +the Xs represent any combination of letters and numbers). This file should +contain the message body and headers from the test email entered above. + +If the sample filter did not log your test email, there are a number of +methods to narrow down the source of the problem. Check your system +logs written by syslogd and see if there are any pertinent lines. You +may need to reconfigure syslogd to capture all relevant data. Additionally, +the logging level of sendmail can be raised with the LogLevel option. +See the sendmail(8) manual page for more information. + + ++--------------------------+ +| SOURCE FOR SAMPLE FILTER | ++--------------------------+ + +/* A trivial filter that logs all email to a file. */ + +#include "libmilter/mfapi.h" + +struct mlfiPriv +{ + char *mlfi_fname; + FILE *mlfi_fp; +}; + +#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) + +extern sfsistat mlfi_cleanup(SMFICTX *, bool); + +sfsistat +mlfi_envfrom(ctx, envfrom) + SMFICTX *ctx; + char *envfrom; +{ + struct mlfiPriv *priv; + int fd; + + /* allocate some private memory */ + priv = malloc(sizeof *priv); + if (priv == NULL) + { + /* can't accept this message right now */ + return SMFIS_TEMPFAIL; + } + memset(priv, '\0', sizeof *priv); + + /* open a file to store this message */ + priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX"); + if (priv->mlfi_fname == NULL) + { + free(priv); + return SMFIS_TEMPFAIL; + } + if ((fd = mkstemp(priv->mlfi_fname)) < 0 || + (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) + { + free(priv->mlfi_fname); + free(priv); + return SMFIS_TEMPFAIL; + } + + /* save the private data */ + smfi_setpriv(ctx, priv); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_header(ctx, headerf, headerv) + SMFICTX *ctx; + char *headerf; + u_char *headerv; +{ + /* write the header to the log file */ + fprintf(MLFIPRIV->mlfi_fp, "%s: %s\n", headerf, headerv); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_eoh(ctx) + SMFICTX *ctx; +{ + /* output the blank line between the header and the body */ + fprintf(MLFIPRIV->mlfi_fp, "\n"); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_body(ctx, bodyp, bodylen) + SMFICTX *ctx; + u_char *bodyp; + size_t bodylen; +{ + /* output body block to log file */ + if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0) + { + /* write failed */ + (void) mlfi_cleanup(ctx, FALSE); + return SMFIS_TEMPFAIL; + } + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_eom(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, TRUE); +} + +sfsistat +mlfi_close(ctx) + SMFICTX *ctx; +{ + return SMFIS_ACCEPT; +} + +sfsistat +mlfi_abort(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, FALSE); +} + +sfsistat +mlfi_cleanup(ctx, ok) + SMFICTX *ctx; + bool ok; +{ + sfsistat rstat = SMFIS_CONTINUE; + struct mlfiPriv *priv = MLFIPRIV; + char *p; + char host[512]; + char hbuf[1024]; + + if (priv == NULL) + return rstat; + + /* close the archive file */ + if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) + { + /* failed; we have to wait until later */ + rstat = SMFIS_TEMPFAIL; + (void) unlink(priv->mlfi_fname); + } + else if (ok) + { + /* add a header to the message announcing our presence */ + if (gethostname(host, sizeof host) < 0) + strlcpy(host, "localhost", sizeof host); + p = strrchr(priv->mlfi_fname, '/'); + if (p == NULL) + p = priv->mlfi_fname; + else + p++; + snprintf(hbuf, sizeof hbuf, "%s@%s", p, host); + smfi_addheader(ctx, "X-Archived", hbuf); + } + else + { + /* message was aborted -- delete the archive file */ + (void) unlink(priv->mlfi_fname); + } + + /* release private memory */ + free(priv->mlfi_fname); + free(priv); + smfi_setpriv(ctx, NULL); + + /* return status */ + return rstat; +} + +struct smfiDesc smfilter = +{ + "SampleFilter", /* filter name */ + SMFI_VERSION, /* version code -- do not change */ + SMFIF_MODHDRS, /* flags */ + NULL, /* connection info filter */ + NULL, /* SMTP HELO command filter */ + mlfi_envfrom, /* envelope sender filter */ + NULL, /* envelope recipient filter */ + mlfi_header, /* header filter */ + mlfi_eoh, /* end of header */ + mlfi_body, /* body block filter */ + mlfi_eom, /* end of message */ + mlfi_abort, /* message aborted */ + mlfi_close /* connection cleanup */ +}; + + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char c; + const char *args = "p:"; + + /* Process command line options */ + while ((c = getopt(argc, argv, args)) != -1) + { + switch (c) + { + case 'p': + if (optarg == NULL || *optarg == '\0') + { + (void) fprintf(stderr, "Illegal conn: %s\n", + optarg); + exit(EX_USAGE); + } + (void) smfi_setconn(optarg); + break; + + } + } + if (smfi_register(smfilter) == MI_FAILURE) + { + fprintf(stderr, "smfi_register failed\n"); + exit(EX_UNAVAILABLE); + } + return smfi_main(); +} + +/* eof */ + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:58 $ diff --git a/gnu/usr.sbin/sendmail/libmilter/comm.c b/gnu/usr.sbin/sendmail/libmilter/comm.c new file mode 100644 index 00000000000..9e8702807ba --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/comm.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: comm.c,v 8.30 2000/02/11 00:12:29 ca Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include "libmilter.h" + +#define FD_Z FD_ZERO(&readset); \ + FD_SET(fd, &readset); \ + FD_ZERO(&excset); \ + FD_SET(fd, &excset) + +/* +** MI_RD_CMD -- read a command +** +** Parameters: +** fd -- file descriptor +** timeout -- maximum time to wait +** cmd -- single character command read from fd +** rlen -- pointer to length of result +** name -- name of milter +** +** Returns: +** buffer with rest of command +** (malloc()ed here, should be free()d) +** hack: encode error in cmd +*/ + +char * +mi_rd_cmd(fd, timeout, cmd, rlen, name) + int fd; + struct timeval *timeout; + char *cmd; + size_t *rlen; + char *name; +{ + ssize_t len; + mi_int32 expl; + ssize_t i; + fd_set readset, excset; + int ret; + int save_errno; + char *buf; + char data[MILTER_LEN_BYTES + 1]; + + *cmd = '\0'; + *rlen = 0; + if (fd >= FD_SETSIZE) + { + smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", + name, fd, FD_SETSIZE); + *cmd = SMFIC_SELECT; + return NULL; + } + FD_Z; + i = 0; + while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) >= 1) + { + if (FD_ISSET(fd, &excset)) + { + *cmd = SMFIC_SELECT; + return NULL; + } + if ((len = read(fd, data + i, sizeof data - i)) < 0) + { + smi_log(SMI_LOG_ERR, + "%s, mi_rd_cmd: read returned %d: %s", + name, len, strerror(errno)); + *cmd = SMFIC_RECVERR; + return NULL; + } + if (len == 0) + { + *cmd = SMFIC_EOF; + return NULL; + } + if (len >= sizeof data - i) + break; + i += len; + FD_Z; + } + if (ret == 0) + { + *cmd = SMFIC_TIMEOUT; + return NULL; + } + else if (ret < 0) + { + smi_log(SMI_LOG_ERR, + "%s: mi_rd_cmd: select returned %d: %s", + name, ret, strerror(errno)); + *cmd = SMFIC_RECVERR; + return NULL; + } + + *cmd = data[MILTER_LEN_BYTES]; + data[MILTER_LEN_BYTES] = '\0'; + (void) memcpy((void *) &expl, (void *) &(data[0]), MILTER_LEN_BYTES); + expl = ntohl(expl) - 1; + if (expl <= 0) + return NULL; + if (expl > MILTER_CHUNK_SIZE) + { + *cmd = SMFIC_TOOBIG; + return NULL; + } + buf = malloc(expl); + if (buf == NULL) + { + *cmd = SMFIC_MALLOC; + return NULL; + } + + i = 0; + FD_Z; + while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) == 1) + { + if (FD_ISSET(fd, &excset)) + { + *cmd = SMFIC_SELECT; + free(buf); + return NULL; + } + if ((len = read(fd, buf + i, expl - i)) < 0) + { + smi_log(SMI_LOG_ERR, + "%s: mi_rd_cmd: read returned %d: %s", + name, len, strerror(errno)); + ret = -1; + break; + } + if (len == 0) + { + *cmd = SMFIC_EOF; + free(buf); + return NULL; + } + if (len > expl - i) + { + *cmd = SMFIC_RECVERR; + free(buf); + return NULL; + } + if (len >= expl - i) + { + *rlen = expl; + return buf; + } + i += len; + FD_Z; + } + + save_errno = errno; + free(buf); + + /* select returned 0 (timeout) or < 0 (error) */ + if (ret == 0) + { + *cmd = SMFIC_TIMEOUT; + return NULL; + } + if (ret < 0) + { + smi_log(SMI_LOG_ERR, + "%s: mi_rd_cmd: select returned %d: %s", + name, ret, strerror(save_errno)); + *cmd = SMFIC_RECVERR; + return NULL; + } + *cmd = SMFIC_UNKNERR; + return NULL; +} + /* +** MI_WR_CMD -- write a cmd to fd +** +** Parameters: +** fd -- file descriptor +** timeout -- maximum time to wait (currently unused) +** cmd -- single character command to write +** buf -- buffer with further data +** len -- length of buffer (without cmd!) +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_wr_cmd(fd, timeout, cmd, buf, len) + int fd; + struct timeval *timeout; + int cmd; + char *buf; + size_t len; +{ + size_t sl, i; + ssize_t l; + mi_int32 nl; + int ret; + fd_set wrtset; + char data[MILTER_LEN_BYTES + 1]; + + if (len > MILTER_CHUNK_SIZE) + return MI_FAILURE; + nl = htonl(len + 1); /* add 1 for the cmd char */ + (void) memcpy(data, (void *) &nl, MILTER_LEN_BYTES); + data[MILTER_LEN_BYTES] = (char) cmd; + i = 0; + sl = MILTER_LEN_BYTES + 1; + + do { + FD_ZERO(&wrtset); + FD_SET(fd, &wrtset); + if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + return MI_FAILURE; + } while (ret < 0 && errno == EINTR); + if (ret < 0) + return MI_FAILURE; + + /* use writev() instead to send the whole stuff at once? */ + while ((l = write(fd, (void *) (data + i), sl - i)) < sl) + { + if (l < 0) + return MI_FAILURE; + i += l; + sl -= l; + } + + if (len > 0 && buf == NULL) + return MI_FAILURE; + if (len == 0 || buf == NULL) + return MI_SUCCESS; + i = 0; + sl = len; + do { + FD_ZERO(&wrtset); + FD_SET(fd, &wrtset); + if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + return MI_FAILURE; + } while (ret < 0 && errno == EINTR); + if (ret < 0) + return MI_FAILURE; + while ((l = write(fd, (void *) (buf + i), sl - i)) < sl) + { + if (l < 0) + return MI_FAILURE; + i += l; + sl -= l; + } + return MI_SUCCESS; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/engine.c b/gnu/usr.sbin/sendmail/libmilter/engine.c new file mode 100644 index 00000000000..ffad361f7ab --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/engine.c @@ -0,0 +1,1071 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: engine.c,v 8.65 2000/02/17 17:52:14 ca Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include "libmilter.h" +#include "sendmail/useful.h" + +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + +/* length of options: two 32bit integers */ +#define MILTER_OPTLEN 8 + +/* generic argument for functions in the command table */ +struct arg_struct +{ + size_t a_len; /* length of buffer */ + char *a_buf; /* argument string */ + int a_idx; /* index for macro array */ + SMFICTX_PTR a_ctx; /* context */ +}; + +typedef struct arg_struct genarg; + +/* structure for commands received from MTA */ +struct cmdfct_t +{ + char cm_cmd; /* command */ + int cm_argt; /* type of arguments expected */ + int cm_next; /* next state */ + int cm_todo; /* what to do next */ + int cm_macros; /* index for macros */ + int (*cm_fct) __P((genarg *)); /* function to execute */ +}; + +typedef struct cmdfct_t cmdfct; + +/* possible values for cm_argt */ +#define CM_ARG0 0 /* no args */ +#define CM_ARG1 1 /* one arg (string) */ +#define CM_ARG2 2 /* two args (strings) */ +#define CM_ARGA 4 /* one string and _SOCK_ADDR */ +#define CM_ARGO 5 /* two integers */ +#define CM_ARGV 8 /* \0 separated list of args, NULL-terminated */ +#define CM_ARGN 9 /* \0 separated list of args (strings) */ + +/* possible values for cm_todo */ +#define CT_CONT 0x0000 /* continue reading commands */ +#define CT_IGNO 0x0001 /* continue even when error */ + +/* not needed right now, done via return code instead */ +#define CT_KEEP 0x0004 /* keep buffer (contains symbols) */ +#define CT_END 0x0008 /* start replying */ + +/* index in macro array: macros only for these commands */ +#define CI_NONE (-1) +#define CI_CONN 0 +#define CI_HELO 1 +#define CI_MAIL 2 +#define CI_RCPT 3 +#if CI_RCPT >= MAX_MACROS_ENTRIES +ERROR: do not compile with CI_RCPT >= MAX_MACROS_ENTRIES +#endif + +/* function prototypes */ +static int st_abortfct __P((genarg *)); +static int st_macros __P((genarg *)); +static int st_optionneg __P((genarg *)); +static int st_bodychunk __P((genarg *)); +static int st_connectinfo __P((genarg *)); +static int st_bodyend __P((genarg *)); +static int st_helo __P((genarg *)); +static int st_header __P((genarg *)); +static int st_sender __P((genarg *)); +static int st_rcpt __P((genarg *)); +static int st_eoh __P((genarg *)); +static int st_quit __P((genarg *)); +static int sendreply __P((sfsistat, int, struct timeval *, SMFICTX_PTR)); +static void fix_stm __P((SMFICTX_PTR)); +static bool trans_ok __P((int, int)); +static char **dec_argv __P((char *, size_t)); +static int dec_arg2 __P((char *, size_t, char **, char **)); + +/* states */ +#define ST_NONE (-1) +#define ST_INIT 0 /* initial state */ +#define ST_OPTS 1 /* option negotiation */ +#define ST_CONN 2 /* connection info */ +#define ST_HELO 3 /* helo */ +#define ST_MAIL 4 /* mail from */ +#define ST_RCPT 5 /* rcpt to */ +#define ST_HDRS 6 /* headers */ +#define ST_EOHS 7 /* end of headers */ +#define ST_BODY 8 /* body */ +#define ST_ENDM 9 /* end of message */ +#define ST_QUIT 10 /* quit */ +#define ST_ABRT 11 /* abort */ +#define ST_LAST ST_ABRT +#define ST_SKIP 15 /* not a state but required for the state table */ + +/* +** set of next states +** each state (ST_*) corresponds to bit in an int value (1 << state) +** each state has a set of allowed transitions ('or' of bits of states) +** so a state transition is valid if the mask of the next state +** is set in the NX_* value +** this function is coded in trans_ok(), see below. +*/ +#define MASK(x) (0x0001 << (x)) /* generate a bit "mask" for a state */ +#define NX_INIT (MASK(ST_OPTS)) +#define NX_OPTS (MASK(ST_CONN)) +#define NX_CONN (MASK(ST_HELO) | MASK(ST_MAIL)) +#define NX_HELO (MASK(ST_MAIL)) +#define NX_MAIL (MASK(ST_RCPT) | MASK(ST_ABRT)) +#define NX_RCPT (MASK(ST_HDRS) | MASK(ST_EOHS) | MASK(ST_RCPT) | MASK(ST_ABRT)) +#define NX_HDRS (MASK(ST_EOHS) | MASK(ST_HDRS) | MASK(ST_ABRT)) +#define NX_EOHS (MASK(ST_BODY) | MASK(ST_ENDM) | MASK(ST_ABRT)) +#define NX_BODY (MASK(ST_ENDM) | MASK(ST_BODY) | MASK(ST_ABRT)) +#define NX_ENDM (MASK(ST_QUIT) | MASK(ST_MAIL)) +#define NX_QUIT 0 +#define NX_ABRT 0 +#define NX_SKIP MASK(ST_SKIP) + +static int next_states[] = +{ + NX_INIT, + NX_OPTS, + NX_CONN, + NX_HELO, + NX_MAIL, + NX_RCPT, + NX_HDRS, + NX_EOHS, + NX_BODY, + NX_ENDM, + NX_QUIT, + NX_ABRT +}; + +/* commands received by milter */ +static cmdfct cmds[] = +{ +{SMFIC_ABORT, CM_ARG0, ST_ABRT, CT_CONT, CI_NONE, st_abortfct }, +{SMFIC_MACRO, CM_ARGV, ST_NONE, CT_KEEP, CI_NONE, st_macros }, +{SMFIC_BODY, CM_ARG1, ST_BODY, CT_CONT, CI_NONE, st_bodychunk }, +{SMFIC_CONNECT, CM_ARG2, ST_CONN, CT_CONT, CI_CONN, st_connectinfo }, +{SMFIC_BODYEOB, CM_ARG1, ST_ENDM, CT_CONT, CI_NONE, st_bodyend }, +{SMFIC_HELO, CM_ARG1, ST_HELO, CT_CONT, CI_HELO, st_helo }, +{SMFIC_HEADER, CM_ARG2, ST_HDRS, CT_CONT, CI_NONE, st_header }, +{SMFIC_MAIL, CM_ARGV, ST_MAIL, CT_CONT, CI_MAIL, st_sender }, +{SMFIC_OPTNEG, CM_ARGO, ST_OPTS, CT_CONT, CI_NONE, st_optionneg }, +{SMFIC_EOH, CM_ARG0, ST_EOHS, CT_CONT, CI_NONE, st_eoh }, +{SMFIC_QUIT, CM_ARG0, ST_QUIT, CT_END, CI_NONE, st_quit }, +{SMFIC_RCPT, CM_ARGV, ST_RCPT, CT_IGNO, CI_RCPT, st_rcpt } +}; + +/* additional (internal) reply codes */ +#define _SMFIS_KEEP 20 +#define _SMFIS_ABORT 21 +#define _SMFIS_OPTIONS 22 +#define _SMFIS_NOREPLY 23 +#define _SMFIS_FAIL (-1) + + /* +** MI_ENGINE -- receive commands and process them +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_FAILURE/MI_SUCCESS +*/ +int +mi_engine(ctx) + SMFICTX_PTR ctx; +{ + size_t len; + int i, fd; + int ret = MI_SUCCESS; + int ncmds = sizeof(cmds) / sizeof(cmdfct); + int curstate = ST_INIT; + int newstate; + sfsistat r; + char cmd; + char *buf = NULL; + genarg arg; + struct timeval timeout; + int (*f) __P((genarg *)); + sfsistat (*fi_abort) __P((SMFICTX *)); + + arg.a_ctx = ctx; + fd = ctx->ctx_fd; + fi_abort = ctx->ctx_smfi->xxfi_abort; + mi_clr_macros(ctx, 0); + fix_stm(ctx); + do { + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + if (mi_stop() == MILTER_ABRT) + { + if (ctx->ctx_dbg > 3) + dprintf("[%d] milter_abort\n", + (int) ctx->ctx_id); + ret = MI_FAILURE; + break; + } + if ((buf = mi_rd_cmd(fd, &timeout, &cmd, &len, + ctx->ctx_smfi->xxfi_name)) == NULL && + cmd < SMFIC_VALIDCMD) + { + if (ctx->ctx_dbg > 5) + dprintf("[%d] error (%x)\n", + (int) ctx->ctx_id, (int) cmd); + + /* + ** eof is currently treated as failure -> + ** abort() instead of close(), otherwise use: + ** if (cmd != SMFIC_EOF) + */ + + ret = MI_FAILURE; + break; + } + if (ctx->ctx_dbg > 4) + dprintf("[%d] got cmd '%c' len %d\n", + (int) ctx->ctx_id, cmd, len); + for (i = 0; i < ncmds; i++) + { + if (cmd == cmds[i].cm_cmd) + break; + } + if (i >= ncmds) + { + /* unknown command */ + if (ctx->ctx_dbg > 1) + dprintf("[%d] cmd '%c' unknown\n", + (int) ctx->ctx_id, cmd); + ret = MI_FAILURE; + break; + } + if ((f = cmds[i].cm_fct) == NULL) + { + /* stop for now */ + if (ctx->ctx_dbg > 1) + dprintf("[%d] cmd '%c' not impl\n", + (int) ctx->ctx_id, cmd); + ret = MI_FAILURE; + break; + } + + /* is new state ok? */ + newstate = cmds[i].cm_next; + if (ctx->ctx_dbg > 5) + dprintf("[%d] cur %x new %x nextmask %x\n", + (int) ctx->ctx_id, + curstate, newstate, next_states[curstate]); + + if (newstate != ST_NONE && !trans_ok(curstate, newstate)) + { + if (ctx->ctx_dbg > 1) + dprintf("[%d] abort: cur %d (%x) new %d (%x) next %x\n", + (int) ctx->ctx_id, + curstate, MASK(curstate), + newstate, MASK(newstate), + next_states[curstate]); + if (fi_abort != NULL) + (void) (*fi_abort)(ctx); + + /* + ** try to reach the new state from HELO + ** if it can't be reached, ignore the command. + */ + + curstate = ST_HELO; + if (!trans_ok(curstate, newstate)) + continue; + } + arg.a_len = len; + arg.a_buf = buf; + if (newstate != ST_NONE) + { + curstate = newstate; + ctx->ctx_state = curstate; + } + arg.a_idx = cmds[i].cm_macros; + + /* call function to deal with command */ + r = (*f)(&arg); + if (r != _SMFIS_KEEP && buf != NULL) + { + free(buf); + buf = NULL; + } + if (sendreply(r, fd, &timeout, ctx) != MI_SUCCESS) + { + ret = MI_FAILURE; + break; + } + + if (r == SMFIS_ACCEPT) + { + /* accept mail, no further actions taken */ + curstate = ST_HELO; + } + else if (r == SMFIS_REJECT || r == SMFIS_DISCARD || + r == SMFIS_TEMPFAIL) + { + /* + ** further actions depend on current state + ** if the IGNO bit is set: "ignore" the error, + ** i.e., stay in the current state + */ + if (!bitset(CT_IGNO, cmds[i].cm_todo)) + curstate = ST_HELO; + } + else if (r == _SMFIS_ABORT) + { + if (ctx->ctx_dbg > 5) + dprintf("[%d] function returned abort\n", + (int) ctx->ctx_id); + ret = MI_FAILURE; + break; + } + } while (!bitset(CT_END, cmds[i].cm_todo)); + + if (ret != MI_SUCCESS) + { + if (fi_abort != NULL) + (void) (*fi_abort)(ctx); + } + else + { + sfsistat (*fi_close) __P((SMFICTX *)); + + if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) + (void) (*fi_close)(ctx); + } + if (buf != NULL) + free(buf); + mi_clr_macros(ctx, 0); + return ret; +} + /* +** SENDREPLY -- send a reply to the MTA +** +** Parameters: +** r -- reply code +** fd -- file descriptor +** timeout_ptr -- (ptr to) timeout to use for sending +** ctx -- context structure +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +static int +sendreply(r, fd, timeout_ptr, ctx) + sfsistat r; + int fd; + struct timeval *timeout_ptr; + SMFICTX_PTR ctx; +{ + int ret = MI_SUCCESS; + + switch(r) + { + case SMFIS_CONTINUE: + ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); + break; + case SMFIS_TEMPFAIL: + case SMFIS_REJECT: + if (ctx->ctx_reply != NULL) + { + ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_REPLYCODE, + ctx->ctx_reply, strlen(ctx->ctx_reply)); + free(ctx->ctx_reply); + ctx->ctx_reply = NULL; + } + else + { + ret = mi_wr_cmd(fd, timeout_ptr, r == SMFIS_REJECT ? + SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); + } + break; + case SMFIS_DISCARD: + ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_DISCARD, NULL, 0); + break; + case SMFIS_ACCEPT: + ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); + break; + case _SMFIS_OPTIONS: + { + char buf[MILTER_OPTLEN]; + mi_int32 v; + + v = htonl(ctx->ctx_smfi->xxfi_version); + (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES); + v = htonl(ctx->ctx_smfi->xxfi_flags); + (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, + MILTER_LEN_BYTES); + ret = mi_wr_cmd(fd, timeout_ptr, SMFIC_OPTNEG, buf, + MILTER_OPTLEN); + } + break; + default: /* don't send a reply */ + break; + } + return ret; +} + +/* +** CLR_MACROS -- clear set of macros starting from a given index +** +** Parameters: +** ctx -- context structure +** m -- index from which to clear all macros +** +** Returns: +** None. +*/ +void +mi_clr_macros(ctx, m) + SMFICTX_PTR ctx; + int m; +{ + int i; + + for (i = m; i < MAX_MACROS_ENTRIES; i++) + { + if (ctx->ctx_mac_ptr[i] != NULL) + { + free(ctx->ctx_mac_ptr[i]); + ctx->ctx_mac_ptr[i] = NULL; + } + if (ctx->ctx_mac_buf[i] != NULL) + { + free(ctx->ctx_mac_buf[i]); + ctx->ctx_mac_buf[i] = NULL; + } + } +} + /* +** ST_OPTIONNEG -- negotiate options +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** abort/send options/continue +*/ + +static int +st_optionneg(g) + genarg *g; +{ + mi_int32 i, version; + + if (g == NULL || g->a_ctx->ctx_smfi == NULL) + return SMFIS_CONTINUE; + mi_clr_macros(g->a_ctx, g->a_idx + 1); + if (g->a_len != MILTER_OPTLEN) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: len mismatch %d != %d", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, g->a_len, + MILTER_OPTLEN); + return _SMFIS_ABORT; + } + + (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), + MILTER_LEN_BYTES); + version = ntohl(i); + if (version != g->a_ctx->ctx_smfi->xxfi_version) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: version mismatch %d != %d", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, (int) version, + g->a_ctx->ctx_smfi->xxfi_version); + return _SMFIS_ABORT; + } + +#if 0 + /* flags are currently ignored */ + (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), + MILTER_LEN_BYTES); + flags = ntohl(i); +#endif /* 0 */ + + return _SMFIS_OPTIONS; +} + /* +** ST_CONNECTINFO -- receive connection information +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_connectinfo(g) + genarg *g; +{ + size_t l; + int i; + char *s, family; + u_short port; + _SOCK_ADDR sockaddr; + sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); + + if (g == NULL) + return _SMFIS_ABORT; + mi_clr_macros(g->a_ctx, g->a_idx + 1); + if (g->a_ctx->ctx_smfi == NULL || + (fi_connect = g->a_ctx->ctx_smfi->xxfi_connect) == NULL) + return SMFIS_CONTINUE; + + s = g->a_buf; + i = 0; + l = g->a_len; + while (s[i] != '\0' && i <= l) + ++i; + if (i >= l) + return _SMFIS_ABORT; + family = s[++i]; + memset(&sockaddr, '\0', sizeof sockaddr); + if (family != SMFIA_UNKNOWN) + { + (void) memcpy((void *) &port, (void *) (s + i), + sizeof port); + port = ntohs(port); + if ((i += 2) >= l) + { + smi_log(SMI_LOG_ERR, + "%s: connect[%d]: wrong len %d >= %d", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, i, l); + return _SMFIS_ABORT; + } +# if NETINET + if (family == SMFIA_INET) + { + if (inet_aton(s + i, (struct in_addr *) &sockaddr) + == INADDR_NONE) + { + smi_log(SMI_LOG_ERR, + "%s: connect[%d]: inet_aton failed", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id); + return _SMFIS_ABORT; + } + sockaddr.sa.sa_family = AF_INET; + } + else +# endif /* NETINET */ +# if NETINET6 + if (family == SMFIA_INET6) + { + if (inet_pton(AF_INET6, s + i, + &sockaddr.sin6.sin6_addr) != 1) + { + smi_log(SMI_LOG_ERR, + "%s: connect[%d]: inet_pton failed", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id); + return _SMFIS_ABORT; + } + sockaddr.sa.sa_family = AF_INET6; + } + else +# endif /* NETINET6 */ +# if NETUNIX + if (family == SMFIA_UNIX) + { + if (strlcpy(sockaddr.sunix.sun_path, s + i, + sizeof sockaddr.sunix.sun_path) >= + sizeof sockaddr.sunix.sun_path) + { + smi_log(SMI_LOG_ERR, + "%s: connect[%d]: path too long", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id); + return _SMFIS_ABORT; + } + sockaddr.sunix.sun_family = AF_UNIX; + } + else +# endif /* NETUNIX */ + { + smi_log(SMI_LOG_ERR, + "%s: connect[%d]: unknown family %d", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, family); + return _SMFIS_ABORT; + } + } + return (*fi_connect)(g->a_ctx, g->a_buf, + family != SMFIA_UNKNOWN ? &sockaddr : NULL); +} + /* +** ST_EOH -- end of headers +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_eoh(g) + genarg *g; +{ + sfsistat (*fi_eoh) __P((SMFICTX *)); + + if (g == NULL) + return _SMFIS_ABORT; + if (g->a_ctx->ctx_smfi != NULL && + (fi_eoh = g->a_ctx->ctx_smfi->xxfi_eoh) != NULL) + return (*fi_eoh)(g->a_ctx); + return SMFIS_CONTINUE; +} + /* +** ST_HELO -- helo/ehlo command +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ +static int +st_helo(g) + genarg *g; +{ + sfsistat (*fi_helo) __P((SMFICTX *, char *)); + + if (g == NULL) + return _SMFIS_ABORT; + mi_clr_macros(g->a_ctx, g->a_idx + 1); + if (g->a_ctx->ctx_smfi != NULL && + (fi_helo = g->a_ctx->ctx_smfi->xxfi_helo) != NULL) + return (*fi_helo)(g->a_ctx, g->a_buf); + return SMFIS_CONTINUE; +} + /* +** ST_HEADER -- header line +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_header(g) + genarg *g; +{ + char *hf, *hv; + sfsistat (*fi_header) __P((SMFICTX *, char *, char *)); + + if (g == NULL) + return _SMFIS_ABORT; + if (g->a_ctx->ctx_smfi == NULL || + (fi_header = g->a_ctx->ctx_smfi->xxfi_header) == NULL) + return SMFIS_CONTINUE; + if (dec_arg2(g->a_buf, g->a_len, &hf, &hv) == MI_SUCCESS) + return (*fi_header)(g->a_ctx, hf, hv); + else + return _SMFIS_ABORT; +} + +#define ARGV_FCT(lf, rf, idx) \ + char **argv; \ + sfsistat (*lf) __P((SMFICTX *, char **)); \ + int r; \ + \ + if (g == NULL) \ + return _SMFIS_ABORT; \ + mi_clr_macros(g->a_ctx, g->a_idx + 1); \ + if (g->a_ctx->ctx_smfi == NULL || \ + (lf = g->a_ctx->ctx_smfi->rf) == NULL) \ + return SMFIS_CONTINUE; \ + if ((argv = dec_argv(g->a_buf, g->a_len)) == NULL) \ + return _SMFIS_ABORT; \ + r = (*lf)(g->a_ctx, argv); \ + free(argv); \ + return r; + + /* +** ST_SENDER -- MAIL FROM command +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_sender(g) + genarg *g; +{ + ARGV_FCT(fi_envfrom, xxfi_envfrom, CI_MAIL) +} + /* +** ST_RCPT -- RCPT TO command +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_rcpt(g) + genarg *g; +{ + ARGV_FCT(fi_envrcpt, xxfi_envrcpt, CI_RCPT) +} + /* +** ST_MACROS -- deal with macros received from the MTA +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue/keep +** +** Side effects: +** set pointer in macro array to current values. +*/ + +static int +st_macros(g) + genarg *g; +{ + int i; + char **argv; + + if (g == NULL || g->a_len < 1) + return _SMFIS_FAIL; + if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) + return _SMFIS_FAIL; + switch(g->a_buf[0]) + { + case SMFIC_CONNECT: + i = CI_CONN; + break; + case SMFIC_HELO: + i = CI_HELO; + break; + case SMFIC_MAIL: + i = CI_MAIL; + break; + case SMFIC_RCPT: + i = CI_RCPT; + break; + default: + free(argv); + return _SMFIS_FAIL; + } + if (g->a_ctx->ctx_mac_ptr[i] != NULL) + free(g->a_ctx->ctx_mac_ptr[i]); + if (g->a_ctx->ctx_mac_buf[i] != NULL) + free(g->a_ctx->ctx_mac_buf[i]); + g->a_ctx->ctx_mac_ptr[i] = argv; + g->a_ctx->ctx_mac_buf[i] = g->a_buf; + return _SMFIS_KEEP; +} + /* +** ST_QUIT -- quit command +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** noreply +*/ + +static int +st_quit(g) + genarg *g; +{ + return _SMFIS_NOREPLY; +} + /* +** ST_BODYCHUNK -- deal with a piece of the mail body +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +*/ + +static int +st_bodychunk(g) + genarg *g; +{ + sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t)); + + if (g == NULL) + return _SMFIS_ABORT; + if (g->a_ctx->ctx_smfi != NULL && + (fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL) + return (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len); + return SMFIS_CONTINUE; +} + /* +** ST_BODYEND -- deal with the last piece of the mail body +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** continue or filter-specified value +** +** Side effects: +** sends a reply for the body part (if non-empty). +*/ + +static int +st_bodyend(g) + genarg *g; +{ + sfsistat r; + sfsistat (*fi_body) __P((SMFICTX *, u_char *, size_t)); + sfsistat (*fi_eom) __P((SMFICTX *)); + + if (g == NULL) + return _SMFIS_ABORT; + r = SMFIS_CONTINUE; + if (g->a_ctx->ctx_smfi != NULL) + { + if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && + g->a_len > 0) + { + int fd; + struct timeval timeout; + + timeout.tv_sec = g->a_ctx->ctx_timeout; + timeout.tv_usec = 0; + fd = g->a_ctx->ctx_fd; + r = (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len); + if (r != SMFIS_CONTINUE && + sendreply(r, fd, &timeout, g->a_ctx) != MI_SUCCESS) + return _SMFIS_ABORT; + } + } + if (r == SMFIS_CONTINUE && + (fi_eom = g->a_ctx->ctx_smfi->xxfi_eom) != NULL) + return (*fi_eom)(g->a_ctx); + return r; +} + /* +** ST_ABORTFCT -- deal with aborts +** +** Parameters: +** g -- generic argument structure +** +** Returns: +** abort or filter-specified value +*/ + +static int +st_abortfct(g) + genarg *g; +{ + sfsistat (*fi_abort) __P((SMFICTX *)); + + if (g == NULL) + return _SMFIS_ABORT; + if (g != NULL && g->a_ctx->ctx_smfi != NULL && + (fi_abort = g->a_ctx->ctx_smfi->xxfi_abort) != NULL) + (void) (*fi_abort)(g->a_ctx); + return _SMFIS_NOREPLY; +} + /* +** TRANS_OK -- is the state transition ok? +** +** Parameters: +** old -- old state +** new -- new state +** +** Returns: +** state transition ok +*/ + +static bool +trans_ok(old, new) + int old, new; +{ + int s, n; + + s = old; + do { + /* is this state transition allowed? */ + if ((MASK(new) & next_states[s]) != 0) + return TRUE; + + /* + ** no: try next state; + ** this works since the relevant states are ordered + ** strict sequentially + */ + n = s + 1; + + /* + ** can we actually "skip" this state? + ** see fix_stm() which sets this bit for those + ** states which the filter program is not interested in + */ + if (bitset(NX_SKIP, next_states[n])) + s = n; + else + return FALSE; + } while (s <= ST_LAST); + return FALSE; +} + /* +** FIX_STM -- add "skip" bits to the state transition table +** +** Parameters: +** ctx -- context structure +** +** Returns: +** None. +** +** Side effects: +** may change state transition table. +*/ + +static void +fix_stm(ctx) + SMFICTX_PTR ctx; +{ + u_long fl; + + if (ctx == NULL || ctx->ctx_smfi == NULL) + return; + fl = ctx->ctx_smfi->xxfi_flags; + if (bitset(SMFIF_NOCONNECT, fl)) + next_states[ST_CONN] |= NX_SKIP; + if (bitset(SMFIF_NOHELO, fl)) + next_states[ST_HELO] |= NX_SKIP; + if (bitset(SMFIF_NOMAIL, fl)) + next_states[ST_MAIL] |= NX_SKIP; + if (bitset(SMFIF_NORCPT, fl)) + next_states[ST_RCPT] |= NX_SKIP; + if (bitset(SMFIF_NOHDRS, fl)) + { + next_states[ST_HDRS] |= NX_SKIP; + next_states[ST_EOHS] |= NX_SKIP; + } + if (bitset(SMFIF_NOBODY, fl)) + next_states[ST_BODY] |= NX_SKIP; +} + /* +** DEC_ARGV -- split a buffer into a list of strings, NULL terminated +** +** Parameters: +** buf -- buffer with several strings +** len -- length of buffer +** +** Returns: +** array of pointers to the individual strings +*/ + +static char ** +dec_argv(buf, len) + char *buf; + size_t len; +{ + char **s; + size_t i; + int elem, nelem; + + nelem = 0; + for (i = 0; i < len; i++) + { + if (buf[i] == '\0') + ++nelem; + } + if (nelem == 0) + return NULL; + + /* last entry is only for the name */ + s = (char **)malloc((nelem + 1) * (sizeof *s)); + if (s == NULL) + return NULL; + s[0] = buf; + for (i = 0, elem = 0; i < len && elem < nelem; i++) + { + if (buf[i] == '\0') + s[++elem] = &(buf[i + 1]); + } + + /* overwrite last entry */ + s[elem] = NULL; + return (s); +} + /* +** DEC_ARG2 -- split a buffer into two strings +** +** Parameters: +** buf -- buffer with two strings +** len -- length of buffer +** s1,s2 -- pointer to result strings +** +** Returns: +** MI_FAILURE/MI_SUCCESS +*/ + +static int +dec_arg2(buf, len, s1, s2) + char *buf; + size_t len; + char **s1; + char **s2; +{ + int i; + + *s1 = buf; + for (i = 1; i < len && buf[i] != '\0'; i++) + continue; + if (i >= len - 1) + return MI_FAILURE; + *s2 = buf + i + 1; + return MI_SUCCESS; +} + /* +** SENDOK -- is it ok for the filter to send stuff to the MTA? +** +** Parameters: +** ctx -- context structure +** flag -- flag to check +** +** Returns: +** sending allowed (in current state) +*/ + +bool +mi_sendok(ctx, flag) + SMFICTX_PTR ctx; + int flag; +{ + if (ctx == NULL || ctx->ctx_smfi == NULL) + return FALSE; + if (flag != 0 && !bitset(flag, ctx->ctx_smfi->xxfi_flags)) + return FALSE; + return ctx->ctx_state == ST_ENDM; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/handler.c b/gnu/usr.sbin/sendmail/libmilter/handler.c new file mode 100644 index 00000000000..0a805b75752 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/handler.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: handler.c,v 8.19 2000/02/11 00:12:29 ca Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include "libmilter.h" + +/* +** HANDLE_SESSION -- Handle a connected session in it's own context +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_handle_session(ctx) + SMFICTX_PTR ctx; +{ + int ret; + + if (ctx == NULL) + return MI_FAILURE; + ctx->ctx_id = pthread_self(); + + /* + ** detach so resources are free when the thread returns + ** if we ever "wait" for threads, this call must be removed + */ + if (pthread_detach(ctx->ctx_id) != 0) + return MI_FAILURE; + ret = mi_engine(ctx); + if (ctx->ctx_fd >= 0) + (void) close(ctx->ctx_fd); + if (ctx->ctx_reply != NULL) + free(ctx->ctx_reply); + if (ctx->ctx_privdata != NULL) + { + smi_log(SMI_LOG_WARN, + "%s: private data not NULL", + ctx->ctx_smfi->xxfi_name); + } + mi_clr_macros(ctx, 0); + free(ctx); + ctx = NULL; + return ret; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/libmilter.h b/gnu/usr.sbin/sendmail/libmilter/libmilter.h new file mode 100644 index 00000000000..eaf581d760a --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/libmilter.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +/* +** MILTER.H -- include file for mail filter library functions +*/ + +#ifndef _LIBMILTER_H +# define _LIBMILTER_H 1 +#ifdef _DEFINE +# define EXTERN +# define INIT(x) = x +# ifndef lint +static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 gshapiro Exp $"; +# endif /* ! lint */ +#else /* _DEFINE */ +# define EXTERN extern +# define INIT(x) +#endif /* _DEFINE */ + +#include "libmilter/milter.h" +#include "libmilter/mfapi.h" + +#ifndef __P +# include "sendmail/cdefs.h" +#endif /* ! __P */ +#include "sendmail/useful.h" + +#include + +/* version info */ +#define MILTER_PRODUCT_NAME "libmilter" +#define MILTER_VERSION 100 + +/* some defaults */ +#define MI_TIMEOUT 1800 /* default timeout for read/write */ +#define MI_CHK_TIME 5 /* checking whether to terminate */ + +/* maximum number of repeated failures in mi_listener() */ +#define MAX_FAILS_M 16 /* malloc() */ +#define MAX_FAILS_T 16 /* thread creation */ + +/* internal "commands", i.e., error codes */ +#define SMFIC_TIMEOUT ((char) 1) /* timeout */ +#define SMFIC_SELECT ((char) 2) /* select error */ +#define SMFIC_MALLOC ((char) 3) /* malloc error */ +#define SMFIC_RECVERR ((char) 4) /* recv() error */ +#define SMFIC_EOF ((char) 5) /* eof */ +#define SMFIC_UNKNERR ((char) 6) /* unknown error */ +#define SMFIC_TOOBIG ((char) 7) /* body chunk too big */ +#define SMFIC_VALIDCMD ' ' /* first valid command */ + +/* hack */ +#define smi_log syslog +#define milter_ret int +#define SMI_LOG_ERR LOG_ERR +#define SMI_LOG_FATAL LOG_ERR +#define SMI_LOG_WARN LOG_WARNING +#define SMI_LOG_INFO LOG_INFO +#define SMI_LOG_DEBUG LOG_DEBUG + +#define MI_INVALID_SOCKET (-1) + +/* stop? */ +#define MILTER_CONT 0 +#define MILTER_STOP 1 +#define MILTER_ABRT 2 + +/* functions */ +extern int mi_handle_session __P((SMFICTX_PTR)); +extern int mi_engine __P((SMFICTX_PTR)); +extern int mi_listener __P((char *, int, smfiDesc_ptr, time_t)); +extern void mi_clr_macros __P((SMFICTX_PTR, int)); +extern int mi_stop __P((void)); +extern int mi_control_startup __P((char *)); +extern void mi_stop_milters __P((int)); +extern void mi_clean_signals __P((void)); +extern struct hostent *mi_gethostbyname __P((char *, int)); + +/* communication functions */ +extern char *mi_rd_cmd __P((int, struct timeval *, char *, size_t *, char *)); +extern int mi_wr_cmd __P((int, struct timeval *, int, char *, size_t)); +extern bool mi_sendok __P((SMFICTX_PTR, int)); + +#endif /* !_LIBMILTER_H */ diff --git a/gnu/usr.sbin/sendmail/libmilter/listener.c b/gnu/usr.sbin/sendmail/libmilter/listener.c new file mode 100644 index 00000000000..3ee18045a40 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/listener.c @@ -0,0 +1,579 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: listener.c,v 8.38 2000/02/11 00:12:30 ca Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +/* +** listener.c -- threaded network listener +*/ + +#include "libmilter.h" + +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + + /* +** MI_MILTEROPEN -- setup socket to listen on +** +** Parameters: +** conn -- connection description +** backlog -- listen backlog +** socksize -- socksize of created socket +** +** Returns: +** socket upon success, error code otherwise. +*/ + +static int +mi_milteropen(conn, backlog, socksize, name) + char *conn; + int backlog; + SOCKADDR_LEN_T *socksize; + char *name; +{ + int sock = 0; + int sockopt = 1; + char *p; + char *colon; + char *at; + struct hostent *hp = NULL; + SOCKADDR addr; + + if (conn == NULL || conn[0] == '\0') + { + smi_log(SMI_LOG_ERR, "%s: empty or missing socket information", + name); + return MI_INVALID_SOCKET; + } + (void) memset(&addr, '\0', sizeof addr); + + /* protocol:filename or protocol:port@host */ + p = conn; + colon = strchr(p, ':'); + if (colon != NULL) + { + *colon = '\0'; + + if (*p == '\0') + { +#if NETUNIX + /* default to AF_UNIX */ + addr.sa.sa_family = AF_UNIX; + *socksize = sizeof (struct sockaddr_un); +#else /* NETUNIX */ +# if NETINET + /* default to AF_INET */ + addr.sa.sa_family = AF_INET; + *socksize = sizeof addr.sin; +# else /* NETINET */ +# if NETINET6 + /* default to AF_INET6 */ + addr.sa.sa_family = AF_INET6; + *socksize = sizeof addr.sin6; +# else /* NETINET6 */ + /* no protocols available */ + smi_log(SMI_LOG_ERR, + "%s: no valid socket protocols available", + name); + return MI_INVALID_SOCKET; +# endif /* NETINET6 */ +# endif /* NETINET */ +#endif /* NETUNIX */ + } +#if NETUNIX + else if (strcasecmp(p, "unix") == 0 || + strcasecmp(p, "local") == 0) + { + addr.sa.sa_family = AF_UNIX; + *socksize = sizeof (struct sockaddr_un); + } +#endif /* NETUNIX */ +#if NETINET + else if (strcasecmp(p, "inet") == 0) + { + addr.sa.sa_family = AF_INET; + *socksize = sizeof addr.sin; + } +#endif /* NETINET */ +#if NETINET6 + else if (strcasecmp(p, "inet6") == 0) + { + addr.sa.sa_family = AF_INET6; + *socksize = sizeof addr.sin6; + } +#endif /* NETINET6 */ + else + { + smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", + name, p); + return MI_INVALID_SOCKET; + } + *colon++ = ':'; + } + else + { + colon = p; +#if NETUNIX + /* default to AF_UNIX */ + addr.sa.sa_family = AF_UNIX; + *socksize = sizeof (struct sockaddr_un); +#else /* NETUNIX */ +# if NETINET + /* default to AF_INET */ + addr.sa.sa_family = AF_INET; + *socksize = sizeof addr.sin; +# else /* NETINET */ +# if NETINET6 + /* default to AF_INET6 */ + addr.sa.sa_family = AF_INET6; + *socksize = sizeof addr.sin6; +# else /* NETINET6 */ + smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", + name, p); + return MI_INVALID_SOCKET; +# endif /* NETINET6 */ +# endif /* NETINET */ +#endif /* NETUNIX */ + } + +#if NETUNIX + if (addr.sa.sa_family == AF_UNIX) + { +# if 0 + long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN; +# endif /* 0 */ + + at = colon; + if (strlcpy(addr.sunix.sun_path, colon, + sizeof addr.sunix.sun_path) >= + sizeof addr.sunix.sun_path) + { + errno = EINVAL; + smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long", + name, colon); + return MI_INVALID_SOCKET; + } +# if 0 + errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, + S_IRUSR|S_IWUSR, NULL); + + /* if not safe, don't create */ + if (errno != 0) + { + smi_log(SMI_LOG_ERR, + "%s: UNIX socket name %s unsafe", + name, colon); + return MI_INVALID_SOCKET; + } +# endif /* 0 */ + + } +#endif /* NETUNIX */ + +#if NETINET || NETINET6 + if ( +# if NETINET + addr.sa.sa_family == AF_INET +# endif /* NETINET */ +# if NETINET && NETINET6 + || +# endif /* NETINET && NETINET6 */ +# if NETINET6 + addr.sa.sa_family == AF_INET6 +# endif /* NETINET6 */ + ) + { + u_short port; + + /* Parse port@host */ + at = strchr(colon, '@'); + if (at == NULL) + { + switch (addr.sa.sa_family) + { +# if NETINET + case AF_INET: + addr.sin.sin_addr.s_addr = INADDR_ANY; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + addr.sin6.sin6_addr = in6addr_any; + break; +# endif /* NETINET6 */ + } + } + else + *at = '\0'; + + if (isascii(*colon) && isdigit(*colon)) + port = htons(atoi(colon)); + else + { +# ifdef NO_GETSERVBYNAME + smi_log(SMI_LOG_ERR, "%s: invalid port number %s", + name, colon); + return MI_INVALID_SOCKET; +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(colon, "tcp"); + if (sp == NULL) + { + smi_log(SMI_LOG_ERR, + "%s: unknown port name %s", + name, colon); + return MI_INVALID_SOCKET; + } + port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + if (at != NULL) + { + *at++ = '@'; + if (*at == '[') + { + char *end; + + end = strchr(at, ']'); + if (end != NULL) + { + bool found = FALSE; +# if NETINET + unsigned long hid = INADDR_NONE; +# endif /* NETINET */ +# if NETINET6 + struct sockaddr_in6 hid6; +# endif /* NETINET6 */ + + *end = '\0'; +# if NETINET + if (addr.sa.sa_family == AF_INET && + (hid = inet_addr(&at[1])) != + INADDR_NONE) + { + addr.sin.sin_addr.s_addr = hid; + addr.sin.sin_port = port; + found = TRUE; + } +# endif /* NETINET */ +# if NETINET6 + (void) memset(&hid6, '\0', sizeof hid6); + if (addr.sa.sa_family == AF_INET6 && + inet_pton(AF_INET6, &at[1], + &hid6.sin6_addr) == 1) + { + addr.sin6.sin6_addr = hid6.sin6_addr; + addr.sin6.sin6_port = port; + found = TRUE; + } +# endif /* NETINET6 */ + *end = ']'; + if (!found) + { + smi_log(SMI_LOG_ERR, + "%s: Invalid numeric domain spec \"%s\"", + name, at); + return MI_INVALID_SOCKET; + } + } + else + { + smi_log(SMI_LOG_ERR, + "%s: Invalid numeric domain spec \"%s\"", + name, at); + return MI_INVALID_SOCKET; + } + } + else + { + hp = mi_gethostbyname(at, addr.sa.sa_family); + if (hp == NULL) + { + smi_log(SMI_LOG_ERR, + "%s: Unknown host name %s", + name, at); + return MI_INVALID_SOCKET; + } + addr.sa.sa_family = hp->h_addrtype; + switch (hp->h_addrtype) + { +# if NETINET + case AF_INET: + memmove(&addr.sin.sin_addr, + hp->h_addr, + INADDRSZ); + addr.sin.sin_port = port; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + hp->h_addr, + IN6ADDRSZ); + addr.sin6.sin6_port = port; + break; +# endif /* NETINET6 */ + + default: + smi_log(SMI_LOG_ERR, + "%s: Unknown protocol for %s (%d)", + name, at, hp->h_addrtype); + return MI_INVALID_SOCKET; + } + } + } + else + { + switch (addr.sa.sa_family) + { +# if NETINET + case AF_INET: + addr.sin.sin_port = port; + break; +# endif /* NETINET */ +# if NETINET6 + case AF_INET6: + addr.sin6.sin6_port = port; + break; +# endif /* NETINET6 */ + } + } + } +#endif /* NETINET || NETINET6 */ + + sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); + if (sock < 0) + { + smi_log(SMI_LOG_ERR, + "%s: Unable to create new socket: %s", + name, strerror(errno)); + return MI_INVALID_SOCKET; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt, + sizeof(sockopt)) == -1) + { + smi_log(SMI_LOG_ERR, + "%s: Unable to setsockopt: %s", name, strerror(errno)); + (void) close(sock); + return MI_INVALID_SOCKET; + } + + if (bind(sock, &addr.sa, *socksize) < 0) + { + smi_log(SMI_LOG_ERR, + "%s: Unable to bind to port %s: %s", + name, conn, strerror(errno)); + (void) close(sock); + return MI_INVALID_SOCKET; + } + + if (listen(sock, backlog) < 0) + { + smi_log(SMI_LOG_ERR, + "%s: listen call failed: %s", name, strerror(errno)); + (void) close(sock); + return MI_INVALID_SOCKET; + } + + return sock; +} + /* +** MI_THREAD_HANDLE_WRAPPER -- small wrapper to handle session +** +** Parameters: +** arg -- argument to pass to mi_handle_session() +** +** Returns: +** results from mi_handle_session() +*/ + +void * +mi_thread_handle_wrapper(arg) + void *arg; +{ + return (void *) mi_handle_session(arg); +} + + /* +** MI_MILTER_LISTENER -- Generic listener harness +** +** Open up listen port +** Wait for connections +** +** Parameters: +** conn -- connection description +** dbg -- debug level +** smfi -- filter structure to use +** timeout -- timeout for reads/writes +** +** Returns: +** MI_SUCCESS -- Exited normally +** (session finished or we were told to exit) +** MI_FAILURE -- Network initialization failed. +*/ + +int +mi_listener(conn, dbg, smfi, timeout) + char *conn; + int dbg; + smfiDesc_ptr smfi; + time_t timeout; +{ + int connfd = -1; + int listenfd = -1; + int clilen; + int sockopt = 1; + int r; + int ret = MI_SUCCESS; + int cnt_m = 0; + int cnt_t = 0; + pthread_t thread_id; + _SOCK_ADDR cliaddr; + SOCKADDR_LEN_T socksize; + SMFICTX_PTR ctx; + fd_set readset, excset; + struct timeval chktime; + + if (dbg > 0) + smi_log(SMI_LOG_DEBUG, + "%s: Opening listen socket on conn %s", + smfi->xxfi_name, conn); + if ((listenfd = mi_milteropen(conn, SOMAXCONN, &socksize, + smfi->xxfi_name)) < 0) + { + smi_log(SMI_LOG_FATAL, + "%s: Unable to create listening socket on conn %s", + smfi->xxfi_name, conn); + return MI_FAILURE; + } + clilen = socksize; + if (listenfd >= FD_SETSIZE) + { + smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", + smfi->xxfi_name, listenfd, FD_SETSIZE); + return MI_FAILURE; + } + + while (mi_stop() == MILTER_CONT) + { + /* select on interface ports */ + FD_ZERO(&readset); + FD_SET(listenfd, &readset); + FD_ZERO(&excset); + FD_SET(listenfd, &excset); + chktime.tv_sec = MI_CHK_TIME; + chktime.tv_usec = 0; + r = select(listenfd + 1, &readset, NULL, &excset, &chktime); + if (r == 0) /* timeout */ + continue; /* just check mi_stop() */ + if (r < 0) + { + if (errno == EINTR) + continue; + ret = MI_FAILURE; + break; + } + if (!FD_ISSET(listenfd, &readset)) + { + /* some error: just stop for now... */ + ret = MI_FAILURE; + break; + } + + connfd = accept(listenfd, (struct sockaddr *) &cliaddr, + &clilen); + + if (connfd < 0) + { + smi_log(SMI_LOG_ERR, + "%s: accept() returned invalid socket", + smfi->xxfi_name); + continue; + } + + if (setsockopt(connfd, SOL_SOCKET, SO_KEEPALIVE, + (void *) &sockopt, sizeof sockopt) < 0) + { + smi_log(SMI_LOG_WARN, "%s: setsockopt() failed", + smfi->xxfi_name); + /* XXX: continue? */ + } + if ((ctx = (SMFICTX_PTR) malloc(sizeof *ctx)) == NULL) + { + (void) close(connfd); + smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed", + smfi->xxfi_name); + sleep(++cnt_m); + if (cnt_m >= MAX_FAILS_M) + { + ret = MI_FAILURE; + break; + } + continue; + } + cnt_m = 0; + memset(ctx, '\0', sizeof *ctx); + ctx->ctx_fd = connfd; + ctx->ctx_dbg = dbg; + ctx->ctx_timeout = timeout; + ctx->ctx_smfi = smfi; +#if 0 + if (smfi->xxfi_eoh == NULL) + if (smfi->xxfi_eom == NULL) + if (smfi->xxfi_abort == NULL) + if (smfi->xxfi_close == NULL) +#endif /* 0 */ + if (smfi->xxfi_connect == NULL) + smfi->xxfi_flags |= SMFIF_NOCONNECT; + if (smfi->xxfi_helo == NULL) + smfi->xxfi_flags |= SMFIF_NOHELO; + if (smfi->xxfi_envfrom == NULL) + smfi->xxfi_flags |= SMFIF_NOMAIL; + if (smfi->xxfi_envrcpt == NULL) + smfi->xxfi_flags |= SMFIF_NORCPT; + if (smfi->xxfi_header == NULL) + smfi->xxfi_flags |= SMFIF_NOHDRS; + if (smfi->xxfi_body == NULL) + smfi->xxfi_flags |= SMFIF_NOBODY; + + if ((r = pthread_create(&thread_id, NULL, + mi_thread_handle_wrapper, + (void *) ctx)) != 0) + { + smi_log(SMI_LOG_ERR, + "%s: pthread_create() failed: %d", + smfi->xxfi_name, r); + sleep(++cnt_t); + (void) close(connfd); + free(ctx); + if (cnt_t >= MAX_FAILS_T) + { + ret = MI_FAILURE; + break; + } + continue; + } + cnt_t = 0; + } + if (ret != MI_SUCCESS) + mi_stop_milters(MILTER_ABRT); + if (listenfd >= 0) + (void) close(listenfd); + return ret; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/main.c b/gnu/usr.sbin/sendmail/libmilter/main.c new file mode 100644 index 00000000000..cf0bbcd2831 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/main.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: main.c,v 8.34 2000/02/11 02:43:45 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#define _DEFINE 1 +#include "libmilter.h" +#include +#include + +static smfiDesc_ptr smfi = NULL; + +/* +** SMFI_REGISTER -- register a filter description +** +** Parameters: +** smfilter -- description of filter to register +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_register(smfilter) + smfiDesc_str smfilter; +{ + size_t len; + + if (smfi == NULL) + { + smfi = (smfiDesc_ptr) malloc(sizeof *smfi); + if (smfi == NULL) + return MI_FAILURE; + } + (void)memcpy(smfi, &smfilter, sizeof *smfi); + if (smfilter.xxfi_name == NULL) + smfilter.xxfi_name = "Unknown"; + + len = strlen(smfilter.xxfi_name) + 1; + smfi->xxfi_name = (char *) malloc(len); + if (smfi->xxfi_name == NULL) + return MI_FAILURE; + (void) strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len); + return MI_SUCCESS; +} + +static int dbg = 0; +static char *conn = NULL; +static int timeout = MI_TIMEOUT; + +int +smfi_setdbg(odbg) + int odbg; +{ + dbg = odbg; + return MI_SUCCESS; +} + +int +smfi_settimeout(otimeout) + int otimeout; +{ + timeout = otimeout; + return MI_SUCCESS; +} + +int +smfi_setconn(oconn) + char *oconn; +{ + size_t l; + + if (oconn == NULL || *oconn == '\0') + return MI_FAILURE; + l = strlen(oconn) + 1; + if ((conn = (char *) malloc(l)) == NULL) + return MI_FAILURE; + if (strlcpy(conn, oconn, l) >= l) + return MI_FAILURE; + return MI_SUCCESS; +} + +int +smfi_main() +{ + signal(SIGPIPE, SIG_IGN); + if (conn == NULL) + { + smi_log(SMI_LOG_FATAL, "%s: missing connection information", + smfi->xxfi_name); + exit(EX_DATAERR); + } + + (void) atexit(mi_clean_signals); + if (mi_control_startup(smfi->xxfi_name) != MI_SUCCESS) + { + smi_log(SMI_LOG_FATAL, + "%s: Couldn't start signal thread", + smfi->xxfi_name); + exit(EX_OSERR); + } + + /* Startup the listener */ + if (mi_listener(conn, dbg, smfi, timeout) != MI_SUCCESS) + return(MI_FAILURE); + + return(MI_SUCCESS); +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/signal.c b/gnu/usr.sbin/sendmail/libmilter/signal.c new file mode 100644 index 00000000000..00ddd9fdcd4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/signal.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: signal.c,v 8.10 2000/02/26 01:32:14 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include "libmilter.h" + +/* +** thread to handle signals +*/ + +typedef pthread_mutex_t smutex_t; +#define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) +#define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) +#define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) +#define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) +#define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) + +static smutex_t M_Mutex; + +static int MilterStop = MILTER_CONT; + + +/* +** MI_STOP -- return value of MilterStop +** +** Parameters: +** none. +** +** Returns: +** value of MilterStop +*/ + +int +mi_stop() +{ + return(MilterStop); +} + + +/* +** MI_STOP_MILTERS -- set value of MilterStop +** +** Parameters: +** v -- new value for MilterStop. +** +** Returns: +** none. +*/ + +void +mi_stop_milters(v) + int v; +{ + (void) smutex_lock(&M_Mutex); + if (MilterStop < v) + MilterStop = v; + (void) smutex_unlock(&M_Mutex); +} + +/* +** MI_CLEAN_SIGNALS -- clean up signal handler thread +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +mi_clean_signals() +{ + (void) smutex_destroy(&M_Mutex); +} + +/* +** MI -- thread to deal with signals +** +** Parameters: +** name -- name of milter +** +** Returns: +** NULL +*/ + +static void * +mi_signal_thread(name) + void *name; +{ + int sig, errs; + sigset_t set; + + sigemptyset(&set); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGTERM); + + /* Handle Ctrl-C gracefully for debugging */ + sigaddset(&set, SIGINT); + errs = 0; + + while (TRUE) + { + sig = 0; +#ifdef SOLARIS + if ((sig = sigwait(&set)) < 0) +#else /* SOLARIS */ + if (sigwait(&set, &sig) != 0) +#endif /* SOLARIS */ + { + smi_log(SMI_LOG_ERR, + "%s: sigwait returned error: %s", + (char *)name, strerror(errno)); + if (++errs > MAX_FAILS_T) + { + mi_stop_milters(MILTER_ABRT); + return NULL; + } + continue; + } + errs = 0; + + switch (sig) + { + case SIGHUP: + case SIGTERM: + mi_stop_milters(MILTER_STOP); + return NULL; + case SIGINT: + mi_stop_milters(MILTER_ABRT); + return NULL; + default: + smi_log(SMI_LOG_ERR, + "%s: sigwait returned unmasked signal: %d", + (char *)name, sig); + break; + } + } +} + +/* +** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals +** +** Parameters: +** name -- name of milter +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +static int +mi_spawn_signal_thread(name) + char *name; +{ + sigset_t set; + pthread_t tid; + + /* Mask HUP and KILL signals */ + sigemptyset(&set); + sigaddset(&set, SIGHUP); + sigaddset(&set, SIGTERM); + sigaddset(&set, SIGINT); + + if (pthread_sigmask(SIG_BLOCK, &set, NULL) != 0) + { + smi_log(SMI_LOG_ERR, + "%s: Couldn't mask HUP and KILL signals", name); + return MI_FAILURE; + } + if (pthread_create(&tid, NULL, mi_signal_thread, (void *)name) + != MI_SUCCESS) + { + smi_log(SMI_LOG_ERR, + "%s: Couldn't start signal thread", name); + return MI_FAILURE; + } + return MI_SUCCESS; +} + +/* +** MI_CONTROL_STARTUP -- startup for thread to handle signals +** +** Parameters: +** name -- name of milter +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_control_startup(name) + char *name; +{ + + if (!smutex_init(&M_Mutex)) + { + smi_log(SMI_LOG_ERR, + "%s: Couldn't initialize control pipe mutex", name); + return MI_FAILURE; + } + + /* + ** spawn_signal_thread must happen before other threads are spawned + ** off so that it can mask the right signals and other threads + ** will inherit that mask. + */ + if (mi_spawn_signal_thread(name) == MI_FAILURE) + { + smi_log(SMI_LOG_ERR, + "%s: Couldn't spawn signal thread", name); + (void) smutex_destroy(&M_Mutex); + return MI_FAILURE; + } + return MI_SUCCESS; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c b/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c new file mode 100644 index 00000000000..9ee76a5f76e --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7 2000/01/20 21:51:52 geir Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + + /* +** MI_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. +** +** Support IPv6 as well as IPv4. +*/ + +#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 + +# ifndef AI_V4MAPPED +# define AI_V4MAPPED 0 /* dummy */ +# endif /* ! AI_V4MAPPED */ +# ifndef AI_ALL +# define AI_ALL 0 /* dummy */ +# endif /* ! AI_ALL */ + +static struct hostent * +mi_getipnodebyname(name, family, flags, err) + char *name; + int family; + int flags; + int *err; +{ + bool resv6 = TRUE; + struct hostent *h; + + if (family == AF_INET6) + { + /* From RFC2133, section 6.1 */ + resv6 = bitset(RES_USE_INET6, _res.options); + _res.options |= RES_USE_INET6; + } + h_errno = 0; + h = gethostbyname(name); + *err = h_errno; + if (family == AF_INET6 && !resv6) + _res.options &= ~RES_USE_INET6; + return h; +} +#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ + +struct hostent * +mi_gethostbyname(name, family) + char *name; + int family; +{ + struct hostent *h = NULL; +#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) +# if SOLARIS == 20300 || SOLARIS == 203 + static struct hostent hp; + static char buf[1000]; + extern struct hostent *_switch_gethostbyname_r(); + + h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); +# else /* SOLARIS == 20300 || SOLARIS == 203 */ + extern struct hostent *__switch_gethostbyname(); + + h = __switch_gethostbyname(name); +# endif /* SOLARIS == 20300 || SOLARIS == 203 */ +#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ +# if NETINET6 + int err; +# endif /* NETINET6 */ + +# if NETINET6 + h = mi_getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); + h_errno = err; +# else /* NETINET6 */ + h = gethostbyname(name); +# endif /* NETINET6 */ + +#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ + return h; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libmilter/smfi.c b/gnu/usr.sbin/sendmail/libmilter/smfi.c new file mode 100644 index 00000000000..5496e35318a --- /dev/null +++ b/gnu/usr.sbin/sendmail/libmilter/smfi.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smfi.c,v 8.28 2000/02/26 01:32:15 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER +#include "libmilter.h" +#include "sendmail/useful.h" + +/* +** SMFI_ADDHEADER -- send a new header to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** headerf -- Header field name +** headerv -- Header field value +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_addheader(ctx, headerf, headerv) + SMFICTX *ctx; + char *headerf; + char *headerv; +{ + /* do we want to copy the stuff or have a special mi_wr_cmd call? */ + size_t len, l1, l2; + int r; + char *buf; + struct timeval timeout; + + if (headerf == NULL || headerv == NULL) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_MODHDRS)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + l1 = strlen(headerf); + l2 = strlen(headerv); + len = l1 + l2 + 2; + buf = malloc(len); + if (buf == NULL) + return MI_FAILURE; + (void) memcpy(buf, headerf, l1 + 1); + (void) memcpy(buf + l1 + 1, headerv, l2 + 1); + r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDHEADER, buf, len); + free(buf); + return r; +} + /* +** SMFI_ADDRCPT -- send an additional recipient to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** rcpt -- recipient address +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_addrcpt(ctx, rcpt) + SMFICTX *ctx; + char *rcpt; +{ + size_t len; + struct timeval timeout; + + if (rcpt == NULL) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_ADDRCPT)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + len = strlen(rcpt) + 1; + return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDRCPT, rcpt, len); +} + /* +** SMFI_DELRCPT -- send a recipient to be removed to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** rcpt -- recipient address +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_delrcpt(ctx, rcpt) + SMFICTX *ctx; + char *rcpt; +{ + size_t len; + struct timeval timeout; + + if (rcpt == NULL) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_DELRCPT)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + len = strlen(rcpt) + 1; + return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_DELRCPT, rcpt, len); +} + /* +** SMFI_REPLACEBODY -- send a body chunk to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** bodyp -- body chunk +** bodylen -- length of body chunk +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_replacebody(ctx, bodyp, bodylen) + SMFICTX *ctx; + u_char *bodyp; + int bodylen; +{ + int len, off, r; + struct timeval timeout; + + if (bodyp == NULL && bodylen > 0) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_MODBODY)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + + /* split body chunk if necessary */ + off = 0; + while (bodylen > 0) + { + len = (bodylen >= MILTER_CHUNK_SIZE) ? MILTER_CHUNK_SIZE : + bodylen; + if ((r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_REPLBODY, + (char *) (bodyp + off), len)) != MI_SUCCESS) + return r; + off += len; + bodylen -= len; + } + return MI_SUCCESS; +} + /* +** MYISENHSC -- check whether a string contains an enhanced status code +** +** Parameters: +** s -- string with possible enhanced status code. +** delim -- delim for enhanced status code. +** +** Returns: +** 0 -- no enhanced status code. +** >4 -- length of enhanced status code. +** +** Side Effects: +** none. +*/ +static int +myisenhsc(s, delim) + const char *s; + int delim; +{ + int l, h; + + if (s == NULL) + return 0; + if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) + return 0; + h = 0; + l = 2; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + ++h; + if (h == 0 || s[l + h] != '.') + return 0; + l += h + 1; + h = 0; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + ++h; + if (h == 0 || s[l + h] != delim) + return 0; + return l + h; +} + /* +** SMFI_SETREPLY -- set the reply code for the next reply to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** rcode -- The three-digit (RFC 821) SMTP reply code. +** xcode -- The extended (RFC 2034) reply code. +** message -- The text part of the SMTP reply. +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_setreply(ctx, rcode, xcode, message) + SMFICTX *ctx; + char *rcode; + char *xcode; + char *message; +{ + size_t len, l1, l2, l3; + char *buf; + + if (rcode == NULL || ctx == NULL) + return MI_FAILURE; + l1 = strlen(rcode) + 1; + if (l1 != 4) + return MI_FAILURE; + if ((rcode[0] != '4' && rcode[0] != '5') || + !isascii(rcode[1]) || !isdigit(rcode[1]) || + !isascii(rcode[2]) || !isdigit(rcode[2])) + return MI_FAILURE; + l2 = xcode == NULL ? 1 : strlen(xcode) + 1; + if (xcode != NULL && !myisenhsc(xcode, '\0')) + return MI_FAILURE; + l3 = message == NULL ? 1 : strlen(message) + 1; + len = l1 + l2 + l3; + buf = malloc(len); + if (buf == NULL) + return MI_FAILURE; /* oops */ + (void) snprintf(buf, len, "%s %s %s", rcode, + xcode == NULL ? "" : xcode, + message == NULL ? "" : message); + if (ctx->ctx_reply != NULL) + free(ctx->ctx_reply); + ctx->ctx_reply = buf; + return MI_SUCCESS; +} + /* +** SMFI_SETPRIV -- set private data +** +** Parameters: +** ctx -- Opaque context structure +** privatedata -- pointer to private data +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_setpriv(ctx, privatedata) + SMFICTX *ctx; + void *privatedata; +{ + if (ctx == NULL) + return MI_FAILURE; + ctx->ctx_privdata = privatedata; + return MI_SUCCESS; +} + /* +** SMFI_GETPRIV -- get private data +** +** Parameters: +** ctx -- Opaque context structure +** +** Returns: +** pointer to private data +*/ + +void * +smfi_getpriv(ctx) + SMFICTX *ctx; +{ + if (ctx == NULL) + return NULL; + return ctx->ctx_privdata; +} + /* +** SMFI_GETSYMVAL -- get the value of a macro +** +** See explanation in mfapi.h about layout of the structures. +** +** Parameters: +** ctx -- Opaque context structure +** symname -- name of macro +** +** Returns: +** value of macro (NULL in case of failure) +*/ + +char * +smfi_getsymval(ctx, symname) + SMFICTX *ctx; + char *symname; +{ + int i; + char **s; + + if (ctx == NULL || symname == NULL || *symname == '\0') + return NULL; + + /* search backwards through the macro array */ + for (i = MAX_MACROS_ENTRIES - 1 ; i >= 0; --i) + { + if ((s = ctx->ctx_mac_ptr[i]) == NULL || + ctx->ctx_mac_buf[i] == NULL) + continue; + while (s != NULL && *s != NULL) + { + if (strcmp(*s, symname) == 0) + return *++s; + ++s; /* skip over macro value */ + ++s; /* points to next macro name */ + } + } + return NULL; +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/libsmdb/Build b/gnu/usr.sbin/sendmail/libsmdb/Build new file mode 100644 index 00000000000..fd7d1add2d4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.1 1999/03/10 23:18:41 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/libsmdb/Makefile b/gnu/usr.sbin/sendmail/libsmdb/Makefile new file mode 100644 index 00000000000..95fd54f1f79 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 1.2 1999/09/23 22:36:29 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/libsmdb/Makefile.m4 b/gnu/usr.sbin/sendmail/libsmdb/Makefile.m4 new file mode 100644 index 00000000000..f24c0a0d63c --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/Makefile.m4 @@ -0,0 +1,13 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`library', `libsmdb') +define(`bldSOURCES', `smdb.c smdb1.c smdb2.c smndbm.c ') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/libsmdb/smdb.c b/gnu/usr.sbin/sendmail/libsmdb/smdb.c new file mode 100644 index 00000000000..59632ba6b26 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/smdb.c @@ -0,0 +1,410 @@ +/* +** Copyright (c) 1999 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** By using this file, you agree to the terms and conditions set +** forth in the LICENSE file which can be found at the top level of +** the sendmail distribution. +*/ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1983, 1987, 1993\n\ + The Regents of the University of California. All rights reserved.\n\ + Copyright (c) 1983 Eric P. Allman. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smdb.c,v 8.33 1999/10/13 06:17:07 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include + +#include +#include + + /* +** SMDB_MALLOC_DATABASE -- Allocates a database structure. +** +** Parameters: +** None +** +** Returns: +** An pointer to an allocated SMDB_DATABASE structure or +** NULL if it couldn't allocate the memory. +*/ + +SMDB_DATABASE * +smdb_malloc_database() +{ + SMDB_DATABASE *db; + + db = (SMDB_DATABASE *) malloc(sizeof(SMDB_DATABASE)); + + if (db != NULL) + memset(db, '\0', sizeof(SMDB_DATABASE)); + + return db; +} + + + /* +** SMDB_FREE_DATABASE -- Unallocates a database structure. +** +** Parameters: +** database -- a SMDB_DATABASE pointer to deallocate. +** +** Returns: +** None +*/ + +void +smdb_free_database(database) + SMDB_DATABASE *database; +{ + if (database != NULL) + free(database); +} + + + /* +** SMDB_OPEN_DATABASE -- Opens a database. +** +** This opens a database. If type is SMDB_DEFAULT it tries to +** use a DB1 or DB2 hash. If that isn't available, it will try +** to use NDBM. If a specific type is given it will try to open +** a database of that type. +** +** Parameters: +** database -- An pointer to a SMDB_DATABASE pointer where the +** opened database will be stored. This should +** be unallocated. +** db_name -- The name of the database to open. Do not include +** the file name extension. +** mode -- The mode to set on the database file or files. +** mode_mask -- Mode bits that must match on an opened database. +** sff -- Flags to safefile. +** type -- The type of database to open. Supported types +** vary depending on what was compiled in. +** user_info -- Information on the user to use for file +** permissions. +** params -- Params specific to the database being opened. +** Only supports some DB hash options right now +** (see smdb_db_open() for details). +** +** Returns: +** SMDBE_OK -- Success. +** Anything else is an error. Look up more info about the +** error in the comments for the specific open() used. +*/ + +int +smdb_open_database(database, db_name, mode, mode_mask, sff, type, user_info, + params) + SMDB_DATABASE **database; + char *db_name; + int mode; + int mode_mask; + int sff; + SMDB_DBTYPE type; + SMDB_USER_INFO *user_info; + SMDB_DBPARAMS *params; +{ + int result; + +#ifdef NEWDB + if (type == SMDB_TYPE_DEFAULT) + type = SMDB_TYPE_HASH; +#endif /* NEWDB */ +#ifdef NDBM + if (type == SMDB_TYPE_DEFAULT) + type = SMDB_TYPE_NDBM; +#endif /* NDBM */ + + if (type == SMDB_TYPE_DEFAULT) + return SMDBE_UNKNOWN_DB_TYPE; + + if (strncmp(type, SMDB_TYPE_NDBM, SMDB_TYPE_NDBM_LEN) == 0) + { +#ifdef NDBM + result = smdb_ndbm_open(database, db_name, mode, mode_mask, + sff, type, user_info, params); + return result; +#else /* NDBM */ + return SMDBE_UNSUPPORTED_DB_TYPE; +#endif /* NDBM */ + } + + if ((strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) || + (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0)) + { +#ifdef NEWDB + result = smdb_db_open(database, db_name, mode, mode_mask, sff, + type, user_info, params); + return result; +#else /* NEWDB */ + return SMDBE_UNSUPPORTED_DB_TYPE; +#endif /* NEWDB */ + } + + return SMDBE_UNKNOWN_DB_TYPE; +} + + /* +** SMDB_ADD_EXTENSION -- Adds an extension to a file name. +** +** Just adds a . followed by a string to a db_name if there +** is room and the db_name does not already have that extension. +** +** Parameters: +** full_name -- The final file name. +** max_full_name_len -- The max length for full_name. +** db_name -- The name of the db. +** extension -- The extension to add. +** +** Returns: +** SMDBE_OK -- Success. +** Anything else is an error. Look up more info about the +** error in the comments for the specific open() used. +*/ + +int +smdb_add_extension(full_name, max_full_name_len, db_name, extension) + char *full_name; + int max_full_name_len; + char *db_name; + char *extension; +{ + int extension_len; + int db_name_len; + + if (full_name == NULL || db_name == NULL || extension == NULL) + return SMDBE_INVALID_PARAMETER; + + extension_len = strlen(extension); + db_name_len = strlen(db_name); + + if (extension_len + db_name_len + 2 > max_full_name_len) + return SMDBE_DB_NAME_TOO_LONG; + + if (db_name_len < extension_len || + strcmp(&db_name[db_name_len - extension_len], extension) != 0) + snprintf(full_name, max_full_name_len, "%s.%s", db_name, + extension); + else + (void) strlcpy(full_name, db_name, max_full_name_len); + + return SMDBE_OK; +} + + /* +** SMDB_LOCK_FILE -- Locks the database file. +** +** Locks the actual database file. +** +** Parameters: +** lock_fd -- The resulting descriptor for the locked file. +** db_name -- The name of the database without extension. +** mode -- The open mode. +** sff -- Flags to safefile. +** extension -- The extension for the file. +** +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_lock_file(lock_fd, db_name, mode, sff, extension) + int *lock_fd; + char *db_name; + int mode; + int sff; + char *extension; +{ + int result; + char file_name[SMDB_MAX_NAME_LEN]; + + result = smdb_add_extension(file_name, SMDB_MAX_NAME_LEN, db_name, + extension); + if (result != SMDBE_OK) + return result; + + *lock_fd = safeopen(file_name, mode & ~O_TRUNC, 0644, sff); + if (*lock_fd < 0) + return errno; + + return SMDBE_OK; +} + + /* +** SMDB_UNLOCK_FILE -- Unlocks a file +** +** Unlocks a file. +** +** Parameters: +** lock_fd -- The descriptor for the locked file. +** +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_unlock_file(lock_fd) + int lock_fd; +{ + int result; + + result = close(lock_fd); + if (result != 0) + return errno; + + return SMDBE_OK; +} + + /* +** SMDB_SETUP_FILE -- Gets db file ready for use. +** +** Makes sure permissions on file are safe and creates it if it +** doesn't exist. +** +** Parameters: +** db_name -- The name of the database without extension. +** extension -- The extension. +** sff -- Flags to safefile. +** mode_mask -- Mode bits that must match. +** user_info -- Information on the user to use for file +** permissions. +** stat_info -- A place to put the stat info for the file. +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_setup_file(db_name, extension, mode_mask, sff, user_info, stat_info) + char *db_name; + char *extension; + int mode_mask; + int sff; + SMDB_USER_INFO *user_info; + struct stat *stat_info; +{ + int st; + int result; + char db_file_name[SMDB_MAX_NAME_LEN]; + + result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, + extension); + if (result != SMDBE_OK) + return result; + + st = safefile(db_file_name, user_info->smdbu_id, + user_info->smdbu_group_id, user_info->smdbu_name, + sff, mode_mask, stat_info); + if (st != 0) + return st; + + return SMDBE_OK; +} + + /* +** SMDB_FILECHANGED -- Checks to see if a file changed. +** +** Compares the passed in stat_info with a current stat on +** the passed in file descriptor. Check filechanged for +** return values. +** +** Parameters: +** db_name -- The name of the database without extension. +** extension -- The extension. +** db_fd -- A file descriptor for the database file. +** stat_info -- An old stat_info. +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_filechanged(db_name, extension, db_fd, stat_info) + char *db_name; + char *extension; + int db_fd; + struct stat *stat_info; +{ + int result; + char db_file_name[SMDB_MAX_NAME_LEN]; + + result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, db_name, + extension); + if (result != SMDBE_OK) + return result; + + result = filechanged(db_file_name, db_fd, stat_info); + + return result; +} + /* +** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types. +** +** Parameters: +** None +** +** Returns: +** None +*/ + +void +smdb_print_available_types() +{ +#ifdef NDBM + printf("dbm\n"); +#endif /* NDBM */ +#ifdef NEWDB + printf("hash\n"); + printf("btree\n"); +#endif /* NEWDB */ +} + /* +** SMDB_DB_DEFINITION -- Given a database type, return database definition +** +** Reads though a structure making an association with the database +** type and the required cpp define from sendmail/README. +** List size is dynamic and must be NULL terminated. +** +** Parameters: +** type -- The name of the database type. +** +** Returns: +** definition for type, otherwise NULL. +*/ + +typedef struct +{ + SMDB_DBTYPE type; + char *dbdef; +} dbtype; + +static dbtype DatabaseDefs[] = +{ + { SMDB_TYPE_HASH, "NEWDB" }, + { SMDB_TYPE_BTREE, "NEWDB" }, + { SMDB_TYPE_NDBM, "NDBM" }, + { NULL, "OOPS" } +}; + +char * +smdb_db_definition(type) + SMDB_DBTYPE type; +{ + dbtype *ptr = DatabaseDefs; + + while (ptr != NULL && ptr->type != NULL) + { + if (strcmp(type, ptr->type) == 0) + return ptr->dbdef; + ptr++; + } + return NULL; +} diff --git a/gnu/usr.sbin/sendmail/libsmdb/smdb1.c b/gnu/usr.sbin/sendmail/libsmdb/smdb1.c new file mode 100644 index 00000000000..27de7a6c8f2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/smdb1.c @@ -0,0 +1,504 @@ +/* +** Copyright (c) 1999 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** By using this file, you agree to the terms and conditions set +** forth in the LICENSE file which can be found at the top level of +** the sendmail distribution. +*/ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smdb1.c,v 8.40 1999/11/23 08:42:53 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include + +#include +#include + +#if (DB_VERSION_MAJOR == 1) + +# define SMDB1_FILE_EXTENSION "db" + +struct smdb_db1_struct +{ + DB *smdb1_db; + int smdb1_lock_fd; + bool smdb1_cursor_in_use; +}; +typedef struct smdb_db1_struct SMDB_DB1_DATABASE; + +struct smdb_db1_cursor +{ + SMDB_DB1_DATABASE *db; +}; +typedef struct smdb_db1_cursor SMDB_DB1_CURSOR; + + /* +** SMDB_TYPE_TO_DB1_TYPE -- Translates smdb database type to db1 type. +** +** Parameters: +** type -- The type to translate. +** +** Returns: +** The DB1 type that corresponsds to the passed in SMDB type. +** Returns -1 if there is no equivalent type. +** +*/ + +DBTYPE +smdb_type_to_db1_type(type) + SMDB_DBTYPE type; +{ + if (type == SMDB_TYPE_DEFAULT) + return DB_HASH; + + if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) + return DB_HASH; + + if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0) + return DB_BTREE; + + /* Should never get here thanks to test in smdb_db_open() */ + return DB_HASH; +} + + + /* +** SMDB_PUT_FLAGS_TO_DB1_FLAGS -- Translates smdb put flags to db1 put flags. +** +** Parameters: +** flags -- The flags to translate. +** +** Returns: +** The db1 flags that are equivalent to the smdb flags. +** +** Notes: +** Any invalid flags are ignored. +** +*/ + +u_int +smdb_put_flags_to_db1_flags(flags) + SMDB_FLAG flags; +{ + int return_flags; + + return_flags = 0; + + if (bitset(SMDBF_NO_OVERWRITE, flags)) + return_flags |= R_NOOVERWRITE; + + return return_flags; +} + + /* +** SMDB_CURSOR_GET_FLAGS_TO_SMDB1 +** +** Parameters: +** flags -- The flags to translate. +** +** Returns: +** The db1 flags that are equivalent to the smdb flags. +** +** Notes: +** Returns -1 if we don't support the flag. +** +*/ + +int +smdb_cursor_get_flags_to_smdb1(flags) + SMDB_FLAG flags; +{ + switch(flags) + { + case SMDB_CURSOR_GET_FIRST: + return R_FIRST; + + case SMDB_CURSOR_GET_LAST: + return R_LAST; + + case SMDB_CURSOR_GET_NEXT: + return R_NEXT; + + default: + return -1; + } +} + +SMDB_DB1_DATABASE * +smdb1_malloc_database() +{ + SMDB_DB1_DATABASE *db1; + + db1 = (SMDB_DB1_DATABASE *) malloc(sizeof(SMDB_DB1_DATABASE)); + + if (db1 != NULL) + { + db1->smdb1_lock_fd = -1; + db1->smdb1_cursor_in_use = FALSE; + } + + return db1; +} + +/* +** The rest of these function correspond to the interface laid out +** in smdb.h. +*/ + +int +smdb1_close(database) + SMDB_DATABASE *database; +{ + SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + if (db1->smdb1_lock_fd != -1) + (void) close(db1->smdb1_lock_fd); + + free(db1); + database->smdb_impl = NULL; + + return db->close(db); +} + +int +smdb1_del(database, key, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + u_int flags; +{ + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + return db->del(db, &key->db, flags); +} + +int +smdb1_fd(database, fd) + SMDB_DATABASE *database; + int *fd; +{ + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + *fd = db->fd(db); + if (*fd == -1) + return errno; + + return SMDBE_OK; +} + +int +smdb1_get(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + int result; + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + result = db->get(db, &key->db, &data->db, flags); + if (result != 0) + { + if (result == 1) + return SMDBE_NOT_FOUND; + return errno; + } + return SMDBE_OK; +} + +int +smdb1_put(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + return db->put(db, &key->db, &data->db, + smdb_put_flags_to_db1_flags(flags)); +} + +int +smdb1_set_owner(database, uid, gid) + SMDB_DATABASE *database; + uid_t uid; + gid_t gid; +{ +# if HASFCHOWN + int fd; + int result; + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + fd = db->fd(db); + if (fd == -1) + return errno; + + result = fchown(fd, uid, gid); + if (result < 0) + return errno; +# endif /* HASFCHOWN */ + + return SMDBE_OK; +} + +int +smdb1_sync(database, flags) + SMDB_DATABASE *database; + u_int flags; +{ + DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + + return db->sync(db, flags); +} + +int +smdb1_cursor_close(cursor) + SMDB_CURSOR *cursor; +{ + SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; + SMDB_DB1_DATABASE *db1 = db1_cursor->db; + + if (!db1->smdb1_cursor_in_use) + return SMDBE_NOT_A_VALID_CURSOR; + + db1->smdb1_cursor_in_use = FALSE; + free(cursor); + + return SMDBE_OK; +} + +int +smdb1_cursor_del(cursor, flags) + SMDB_CURSOR *cursor; + u_int flags; +{ + SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; + SMDB_DB1_DATABASE *db1 = db1_cursor->db; + DB *db = db1->smdb1_db; + + return db->del(db, NULL, R_CURSOR); +} + +int +smdb1_cursor_get(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + int db1_flags; + int result; + SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; + SMDB_DB1_DATABASE *db1 = db1_cursor->db; + DB *db = db1->smdb1_db; + + db1_flags = smdb_cursor_get_flags_to_smdb1(flags); + result = db->seq(db, &key->db, &value->db, db1_flags); + if (result == -1) + return errno; + if (result == 1) + return SMDBE_LAST_ENTRY; + return SMDBE_OK; +} + +int +smdb1_cursor_put(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; + SMDB_DB1_DATABASE *db1 = db1_cursor->db; + DB *db = db1->smdb1_db; + + return db->put(db, &key->db, &value->db, R_CURSOR); +} + +int +smdb1_cursor(database, cursor, flags) + SMDB_DATABASE *database; + SMDB_CURSOR **cursor; + u_int flags; +{ + SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; + SMDB_CURSOR *cur; + SMDB_DB1_CURSOR *db1_cursor; + + if (db1->smdb1_cursor_in_use) + return SMDBE_ONLY_SUPPORTS_ONE_CURSOR; + + db1->smdb1_cursor_in_use = TRUE; + db1_cursor = (SMDB_DB1_CURSOR *) malloc(sizeof(SMDB_DB1_CURSOR)); + db1_cursor->db = db1; + + cur = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR)); + + if (cur == NULL) + return SMDBE_MALLOC; + + cur->smdbc_impl = db1_cursor; + cur->smdbc_close = smdb1_cursor_close; + cur->smdbc_del = smdb1_cursor_del; + cur->smdbc_get = smdb1_cursor_get; + cur->smdbc_put = smdb1_cursor_put; + *cursor = cur; + + return SMDBE_OK; +} + + /* +** SMDB_DB_OPEN -- Opens a db1 database. +** +** Parameters: +** database -- An unallocated database pointer to a pointer. +** db_name -- The name of the database without extension. +** mode -- File permisions on the database if created. +** mode_mask -- Mode bits that must match on an existing database. +** sff -- Flags for safefile. +** type -- The type of database to open +** See smdb_type_to_db1_type for valid types. +** user_info -- Information on the user to use for file +** permissions. +** db_params -- +** An SMDB_DBPARAMS struct including params. These +** are processed according to the type of the +** database. Currently supported params (only for +** HASH type) are: +** num_elements +** cache_size +** +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, + db_params) + SMDB_DATABASE **database; + char *db_name; + int mode; + int mode_mask; + int sff; + SMDB_DBTYPE type; + SMDB_USER_INFO *user_info; + SMDB_DBPARAMS *db_params; +{ + int db_fd; + int lock_fd; + int result; + void *params; + SMDB_DATABASE *smdb_db; + SMDB_DB1_DATABASE *db1; + DB *db; + HASHINFO hash_info; + BTREEINFO btree_info; + DBTYPE db_type; + struct stat stat_info; + char db_file_name[SMDB_MAX_NAME_LEN]; + + if (type == NULL || + (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) != 0 && + strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) != 0)) + return SMDBE_UNKNOWN_DB_TYPE; + + result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, + db_name, SMDB1_FILE_EXTENSION); + if (result != SMDBE_OK) + return result; + + result = smdb_setup_file(db_name, SMDB1_FILE_EXTENSION, mode_mask, + sff, user_info, &stat_info); + if (result != SMDBE_OK) + return result; + + lock_fd = -1; +# if O_EXLOCK + mode |= O_EXLOCK; +# else /* O_EXLOCK */ + result = smdb_lock_file(&lock_fd, db_name, mode, sff, + SMDB1_FILE_EXTENSION); + if (result != SMDBE_OK) + return result; +# endif /* O_EXLOCK */ + + *database = NULL; + + smdb_db = smdb_malloc_database(); + db1 = smdb1_malloc_database(); + if (smdb_db == NULL || db1 == NULL) + return SMDBE_MALLOC; + db1->smdb1_lock_fd = lock_fd; + + params = NULL; + if (db_params != NULL && + (strncmp(SMDB_TYPE_HASH, type, SMDB_TYPE_HASH_LEN) == 0)) + { + memset(&hash_info, '\0', sizeof hash_info); + hash_info.nelem = db_params->smdbp_num_elements; + hash_info.cachesize = db_params->smdbp_cache_size; + params = &hash_info; + } + + if (db_params != NULL && + (strncmp(SMDB_TYPE_BTREE, type, SMDB_TYPE_BTREE_LEN) == 0)) + { + memset(&btree_info, '\0', sizeof btree_info); + btree_info.cachesize = db_params->smdbp_cache_size; + if (db_params->smdbp_allow_dup) + btree_info.flags |= R_DUP; + params = &btree_info; + } + + db_type = smdb_type_to_db1_type(type); + db = dbopen(db_file_name, mode, 0644, db_type, params); + if (db != NULL) + { + db_fd = db->fd(db); + result = smdb_filechanged(db_name, SMDB1_FILE_EXTENSION, db_fd, + &stat_info); + } + else + { + if (errno == 0) + result = SMDBE_BAD_OPEN; + else + result = errno; + } + + if (result == SMDBE_OK) + { + /* Everything is ok. Setup driver */ + db1->smdb1_db = db; + + smdb_db->smdb_close = smdb1_close; + smdb_db->smdb_del = smdb1_del; + smdb_db->smdb_fd = smdb1_fd; + smdb_db->smdb_get = smdb1_get; + smdb_db->smdb_put = smdb1_put; + smdb_db->smdb_set_owner = smdb1_set_owner; + smdb_db->smdb_sync = smdb1_sync; + smdb_db->smdb_cursor = smdb1_cursor; + smdb_db->smdb_impl = db1; + + *database = smdb_db; + return SMDBE_OK; + } + + if (db != NULL) + (void) db->close(db); + + /* Error opening database */ + (void) smdb_unlock_file(db1->smdb1_lock_fd); + free(db1); + smdb_free_database(smdb_db); + + return result; +} + +#endif /* (DB_VERSION_MAJOR == 1) */ diff --git a/gnu/usr.sbin/sendmail/libsmdb/smdb2.c b/gnu/usr.sbin/sendmail/libsmdb/smdb2.c new file mode 100644 index 00000000000..658d0a35194 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/smdb2.c @@ -0,0 +1,631 @@ +/* +** Copyright (c) 1999 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** By using this file, you agree to the terms and conditions set +** forth in the LICENSE file which can be found at the top level of +** the sendmail distribution. +*/ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smdb2.c,v 8.48 1999/11/23 08:42:54 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include + +#include +#include + +#if (DB_VERSION_MAJOR >= 2) + +# define SMDB2_FILE_EXTENSION "db" + +struct smdb_db2_database +{ + DB *smdb2_db; + int smdb2_lock_fd; +}; +typedef struct smdb_db2_database SMDB_DB2_DATABASE; + + /* +** SMDB_TYPE_TO_DB2_TYPE -- Translates smdb database type to db2 type. +** +** Parameters: +** type -- The type to translate. +** +** Returns: +** The DB2 type that corresponsds to the passed in SMDB type. +** Returns -1 if there is no equivalent type. +** +*/ + +DBTYPE +smdb_type_to_db2_type(type) + SMDB_DBTYPE type; +{ + if (type == SMDB_TYPE_DEFAULT) + return DB_HASH; + + if (strncmp(type, SMDB_TYPE_HASH, SMDB_TYPE_HASH_LEN) == 0) + return DB_HASH; + + if (strncmp(type, SMDB_TYPE_BTREE, SMDB_TYPE_BTREE_LEN) == 0) + return DB_BTREE; + + return DB_UNKNOWN; +} + + + /* +** DB2_ERROR_TO_SMDB -- Translates db2 errors to smdbe errors +** +** Parameters: +** error -- The error to translate. +** +** Returns: +** The SMDBE error corresponding to the db2 error. +** If we don't have a corresponding error, it returs errno. +** +*/ + +int +db2_error_to_smdb(error) + int error; +{ + int result; + + switch (error) + { +# ifdef DB_INCOMPLETE + case DB_INCOMPLETE: + result = SMDBE_INCOMPLETE; + break; +# endif /* DB_INCOMPLETE */ + +# ifdef DB_NOTFOUND + case DB_NOTFOUND: + result = SMDBE_NOT_FOUND; + break; +# endif /* DB_NOTFOUND */ + +# ifdef DB_KEYEMPTY + case DB_KEYEMPTY: + result = SMDBE_KEY_EMPTY; + break; +# endif /* DB_KEYEMPTY */ + +# ifdef DB_KEYEXIST + case DB_KEYEXIST: + result = SMDBE_KEY_EXIST; + break; +# endif /* DB_KEYEXIST */ + +# ifdef DB_LOCK_DEADLOCK + case DB_LOCK_DEADLOCK: + result = SMDBE_LOCK_DEADLOCK; + break; +# endif /* DB_LOCK_DEADLOCK */ + +# ifdef DB_LOCK_NOTGRANTED + case DB_LOCK_NOTGRANTED: + result = SMDBE_LOCK_NOT_GRANTED; + break; +# endif /* DB_LOCK_NOTGRANTED */ + +# ifdef DB_LOCK_NOTHELD + case DB_LOCK_NOTHELD: + result = SMDBE_LOCK_NOT_HELD; + break; +# endif /* DB_LOCK_NOTHELD */ + +# ifdef DB_RUNRECOVERY + case DB_RUNRECOVERY: + result = SMDBE_RUN_RECOVERY; + break; +# endif /* DB_RUNRECOVERY */ + +# ifdef DB_OLD_VERSION + case DB_OLD_VERSION: + result = SMDBE_OLD_VERSION; + break; +# endif /* DB_OLD_VERSION */ + + case 0: + result = SMDBE_OK; + break; + + default: + result = errno; + } + return result; +} + + /* +** SMDB_PUT_FLAGS_TO_DB2_FLAGS -- Translates smdb put flags to db2 put flags. +** +** Parameters: +** flags -- The flags to translate. +** +** Returns: +** The db2 flags that are equivalent to the smdb flags. +** +** Notes: +** Any invalid flags are ignored. +** +*/ + +u_int +smdb_put_flags_to_db2_flags(flags) + SMDB_FLAG flags; +{ + int return_flags; + + return_flags = 0; + + if (bitset(SMDBF_NO_OVERWRITE, flags)) + return_flags |= DB_NOOVERWRITE; + + return return_flags; +} + + /* +** SMDB_CURSOR_GET_FLAGS_TO_DB2 -- Translates smdb cursor get flags to db2 +** getflags. +** +** Parameters: +** flags -- The flags to translate. +** +** Returns: +** The db2 flags that are equivalent to the smdb flags. +** +** Notes: +** -1 is returned if flag is unknown. +** +*/ + +int +smdb_cursor_get_flags_to_db2(flags) + SMDB_FLAG flags; +{ + switch (flags) + { + case SMDB_CURSOR_GET_FIRST: + return DB_FIRST; + + case SMDB_CURSOR_GET_LAST: + return DB_LAST; + + case SMDB_CURSOR_GET_NEXT: + return DB_NEXT; + + default: + return -1; + } +} + +SMDB_DB2_DATABASE * +smdb2_malloc_database() +{ + SMDB_DB2_DATABASE *db2; + + db2 = (SMDB_DB2_DATABASE *) malloc(sizeof(SMDB_DB2_DATABASE)); + if (db2 != NULL) + db2->smdb2_lock_fd = -1; + + return db2; +} + + +/* +** Except for smdb_db_open, the rest of these function correspond to the +** interface laid out in smdb.h. +*/ + +int +smdb2_close(database) + SMDB_DATABASE *database; +{ + SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl; + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + if (db2->smdb2_lock_fd != -1) + close(db2->smdb2_lock_fd); + + free(db2); + database->smdb_impl = NULL; + + return db2_error_to_smdb(db->close(db, 0)); +} + +int +smdb2_del(database, key, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + u_int flags; +{ + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + return db2_error_to_smdb(db->del(db, NULL, &key->db, flags)); +} + +int +smdb2_fd(database, fd) + SMDB_DATABASE *database; + int *fd; +{ + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + return db2_error_to_smdb(db->fd(db, fd)); +} + +int +smdb2_get(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + return db2_error_to_smdb(db->get(db, NULL, &key->db, &data->db, flags)); +} + +int +smdb2_put(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + return db2_error_to_smdb(db->put(db, NULL, &key->db, &data->db, + smdb_put_flags_to_db2_flags(flags))); +} + + +int +smdb2_set_owner(database, uid, gid) + SMDB_DATABASE *database; + uid_t uid; + gid_t gid; +{ +# if HASFCHOWN + int fd; + int result; + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + result = db->fd(db, &fd); + if (result != 0) + return result; + + result = fchown(fd, uid, gid); + if (result < 0) + return errno; +# endif /* HASFCHOWN */ + + return SMDBE_OK; +} + +int +smdb2_sync(database, flags) + SMDB_DATABASE *database; + u_int flags; +{ + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + + return db2_error_to_smdb(db->sync(db, flags)); +} + +int +smdb2_cursor_close(cursor) + SMDB_CURSOR *cursor; +{ + DBC *dbc = (DBC *) cursor->smdbc_impl; + + return db2_error_to_smdb(dbc->c_close(dbc)); +} + +int +smdb2_cursor_del(cursor, flags) + SMDB_CURSOR *cursor; + SMDB_FLAG flags; +{ + DBC *dbc = (DBC *) cursor->smdbc_impl; + + return db2_error_to_smdb(dbc->c_del(dbc, 0)); +} + +int +smdb2_cursor_get(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + int db2_flags; + int result; + DBC *dbc = (DBC *) cursor->smdbc_impl; + + db2_flags = smdb_cursor_get_flags_to_db2(flags); + result = dbc->c_get(dbc, &key->db, &value->db, db2_flags); + if (result == DB_NOTFOUND) + return SMDBE_LAST_ENTRY; + return db2_error_to_smdb(result); +} + +int +smdb2_cursor_put(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + DBC *dbc = (DBC *) cursor->smdbc_impl; + + return db2_error_to_smdb(dbc->c_put(dbc, &key->db, &value->db, 0)); +} + +int +smdb2_cursor(database, cursor, flags) + SMDB_DATABASE *database; + SMDB_CURSOR **cursor; + SMDB_FLAG flags; +{ + int result; + DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + DBC *db2_cursor; + +# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 + result = db->cursor(db, NULL, &db2_cursor, 0); +# else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */ + result = db->cursor(db, NULL, &db2_cursor); +# endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */ + if (result != 0) + return db2_error_to_smdb(result); + + *cursor = (SMDB_CURSOR *) malloc(sizeof(SMDB_CURSOR)); + if (*cursor == NULL) + return SMDBE_MALLOC; + + (*cursor)->smdbc_close = smdb2_cursor_close; + (*cursor)->smdbc_del = smdb2_cursor_del; + (*cursor)->smdbc_get = smdb2_cursor_get; + (*cursor)->smdbc_put = smdb2_cursor_put; + (*cursor)->smdbc_impl = db2_cursor; + + return SMDBE_OK; +} + +# if DB_VERSION_MAJOR == 2 +static int +smdb_db_open_internal(db_name, db_type, db_flags, db_params, db) + char *db_name; + DBTYPE db_type; + int db_flags; + SMDB_DBPARAMS *db_params; + DB **db; +{ + void *params; + DB_INFO db_info; + + params = NULL; + memset(&db_info, '\0', sizeof db_info); + if (db_params != NULL) + { + db_info.db_cachesize = db_params->smdbp_cache_size; + if (db_type == DB_HASH) + db_info.h_nelem = db_params->smdbp_num_elements; + if (db_params->smdbp_allow_dup) + db_info.flags |= DB_DUP; + params = &db_info; + } + return db_open(db_name, db_type, db_flags, 0644, NULL, params, db); +} +# endif /* DB_VERSION_MAJOR == 2 */ + +# if DB_VERSION_MAJOR > 2 +static int +smdb_db_open_internal(db_name, db_type, db_flags, db_params, db) + char *db_name; + DBTYPE db_type; + int db_flags; + SMDB_DBPARAMS *db_params; + DB **db; +{ + int result; + + result = db_create(db, NULL, 0); + if (result != 0 || *db == NULL) + return result; + + if (db_params != NULL) + { + result = (*db)->set_cachesize(*db, 0, + db_params->smdbp_cache_size, 0); + if (result != 0) + { + (void) (*db)->close((*db), 0); + *db = NULL; + return db2_error_to_smdb(result); + } + if (db_type == DB_HASH) + { + result = (*db)->set_h_nelem(*db, db_params->smdbp_num_elements); + if (result != 0) + { + (void) (*db)->close(*db, 0); + *db = NULL; + return db2_error_to_smdb(result); + } + } + if (db_params->smdbp_allow_dup) + { + result = (*db)->set_flags(*db, DB_DUP); + if (result != 0) + { + (void) (*db)->close(*db, 0); + *db = NULL; + return db2_error_to_smdb(result); + } + } + } + + result = (*db)->open(*db, db_name, NULL, db_type, db_flags, 0644); + if (result != 0) + { + (void) (*db)->close(*db, 0); + *db = NULL; + } + return db2_error_to_smdb(result); +} +# endif /* DB_VERSION_MAJOR > 2 */ + /* +** SMDB_DB_OPEN -- Opens a db database. +** +** Parameters: +** database -- An unallocated database pointer to a pointer. +** db_name -- The name of the database without extension. +** mode -- File permisions for a created database. +** mode_mask -- Mode bits that must match on an opened database. +** sff -- Flags for safefile. +** type -- The type of database to open +** See smdb_type_to_db2_type for valid types. +** user_info -- User information for file permissions. +** db_params -- +** An SMDB_DBPARAMS struct including params. These +** are processed according to the type of the +** database. Currently supported params (only for +** HASH type) are: +** num_elements +** cache_size +** +** Returns: +** SMDBE_OK -- Success, other errno: +** SMDBE_MALLOC -- Cannot allocate memory. +** SMDBE_BAD_OPEN -- db_open didn't return an error, but +** somehow the DB pointer is NULL. +** Anything else: translated error from db2 +*/ + +int +smdb_db_open(database, db_name, mode, mode_mask, sff, type, user_info, db_params) + SMDB_DATABASE **database; + char *db_name; + int mode; + int mode_mask; + int sff; + SMDB_DBTYPE type; + SMDB_USER_INFO *user_info; + SMDB_DBPARAMS *db_params; +{ + int result; + int db_flags; + int lock_fd; + int db_fd; + SMDB_DATABASE *smdb_db; + SMDB_DB2_DATABASE *db2; + DB *db; + DBTYPE db_type; + struct stat stat_info; + char db_file_name[SMDB_MAX_NAME_LEN]; + + *database = NULL; + + result = smdb_add_extension(db_file_name, SMDB_MAX_NAME_LEN, + db_name, SMDB2_FILE_EXTENSION); + if (result != SMDBE_OK) + return result; + + result = smdb_setup_file(db_name, SMDB2_FILE_EXTENSION, + mode_mask, sff, user_info, &stat_info); + if (result != SMDBE_OK) + return result; + + lock_fd = -1; + + result = smdb_lock_file(&lock_fd, db_name, mode, sff, + SMDB2_FILE_EXTENSION); + if (result != SMDBE_OK) + return result; + + smdb_db = smdb_malloc_database(); + if (smdb_db == NULL) + return SMDBE_MALLOC; + + db2 = smdb2_malloc_database(); + if (db2 == NULL) + return SMDBE_MALLOC; + + db2->smdb2_lock_fd = lock_fd; + + db_type = smdb_type_to_db2_type(type); + + db = NULL; + + db_flags = 0; + if (O_CREAT & mode) + db_flags |= DB_CREATE; + if (O_TRUNC & mode) + db_flags |= DB_TRUNCATE; + if (O_RDONLY == mode) + db_flags |= DB_RDONLY; +# if !HASFLOCK && defined(DB_FCNTL_LOCKING) + db_flags |= DB_FCNTL_LOCKING; +# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ + + result = smdb_db_open_internal(db_file_name, db_type, + db_flags, db_params, &db); + + if (result == 0 && db != NULL) + { + result = db->fd(db, &db_fd); + if (result == 0) + result = SMDBE_OK; + } + else + { + /* Try and narrow down on the problem */ + if (result != 0) + result = db2_error_to_smdb(result); + else + result = SMDBE_BAD_OPEN; + } + + if (result == SMDBE_OK) + result = smdb_filechanged(db_name, SMDB2_FILE_EXTENSION, db_fd, + &stat_info); + + if (result == SMDBE_OK) + { + /* Everything is ok. Setup driver */ + db2->smdb2_db = db; + + smdb_db->smdb_close = smdb2_close; + smdb_db->smdb_del = smdb2_del; + smdb_db->smdb_fd = smdb2_fd; + smdb_db->smdb_get = smdb2_get; + smdb_db->smdb_put = smdb2_put; + smdb_db->smdb_set_owner = smdb2_set_owner; + smdb_db->smdb_sync = smdb2_sync; + smdb_db->smdb_cursor = smdb2_cursor; + smdb_db->smdb_impl = db2; + + *database = smdb_db; + + return SMDBE_OK; + } + + if (db != NULL) + db->close(db, 0); + + smdb_unlock_file(db2->smdb2_lock_fd); + free(db2); + smdb_free_database(smdb_db); + + return result; +} + +#endif /* (DB_VERSION_MAJOR >= 2) */ diff --git a/gnu/usr.sbin/sendmail/libsmdb/smndbm.c b/gnu/usr.sbin/sendmail/libsmdb/smndbm.c new file mode 100644 index 00000000000..51e964aed1f --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmdb/smndbm.c @@ -0,0 +1,576 @@ +/* +** Copyright (c) 1999 Sendmail, Inc. and its suppliers. +** All rights reserved. +** +** By using this file, you agree to the terms and conditions set +** forth in the LICENSE file which can be found at the top level of +** the sendmail distribution. +*/ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smndbm.c,v 8.37 1999/10/28 01:58:36 eric Exp $"; +#endif /* ! lint */ + +#include +#include +#include + +#include +#include + +#ifdef NDBM + +# define SMNDB_DIR_FILE_EXTENSION "dir" +# define SMNDB_PAG_FILE_EXTENSION "pag" + +struct smdb_dbm_database_struct +{ + DBM *smndbm_dbm; + int smndbm_lock_fd; + bool smndbm_cursor_in_use; +}; +typedef struct smdb_dbm_database_struct SMDB_DBM_DATABASE; + +struct smdb_dbm_cursor_struct +{ + SMDB_DBM_DATABASE *smndbmc_db; + datum smndbmc_current_key; +}; +typedef struct smdb_dbm_cursor_struct SMDB_DBM_CURSOR; + + /* +** SMDB_PUT_FLAGS_TO_NDBM_FLAGS -- Translates smdb put flags to ndbm put flags. +** +** Parameters: +** flags -- The flags to translate. +** +** Returns: +** The ndbm flags that are equivalent to the smdb flags. +** +** Notes: +** Any invalid flags are ignored. +** +*/ + +int +smdb_put_flags_to_ndbm_flags(flags) + SMDB_FLAG flags; +{ + int return_flags; + + return_flags = 0; + if (bitset(SMDBF_NO_OVERWRITE, flags)) + return_flags = DBM_INSERT; + else + return_flags = DBM_REPLACE; + + return return_flags; +} + + /* +** smdbm_malloc_database -- Create and initialize SMDB_DBM_DATABASE +** +** Parameters: +** None +** +** Returns: +** A pointer to an allocated SMDB_DBM_DATABASE or NULL +** +*/ + +SMDB_DBM_DATABASE * +smdbm_malloc_database() +{ + SMDB_DBM_DATABASE *db; + + db = (SMDB_DBM_DATABASE *) malloc(sizeof(SMDB_DBM_DATABASE)); + if (db != NULL) + { + db->smndbm_dbm = NULL; + db->smndbm_lock_fd = -1; + db->smndbm_cursor_in_use = FALSE; + } + + return db; +} + +/* +** Except for smdb_ndbm_open, the rest of these function correspond to the +** interface laid out in smdb.h. +*/ + +int +smdbm_close(database) + SMDB_DATABASE *database; +{ + SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + dbm_close(dbm); + if (db->smndbm_lock_fd != -1) + close(db->smndbm_lock_fd); + + free(db); + database->smdb_impl = NULL; + + return SMDBE_OK; +} + +int +smdbm_del(database, key, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + u_int flags; +{ + int result; + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + errno = 0; + result = dbm_delete(dbm, key->dbm); + if (result != 0) + { + int save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_NOT_FOUND; + } + return SMDBE_OK; +} + +int +smdbm_fd(database, fd) + SMDB_DATABASE *database; + int *fd; +{ + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + *fd = dbm_dirfno(dbm); + if (*fd <= 0) + return EINVAL; + + return SMDBE_OK; +} + +int +smdbm_get(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + errno = 0; + data->dbm = dbm_fetch(dbm, key->dbm); + if (data->dbm.dptr == NULL) + { + int save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_NOT_FOUND; + } + + return SMDBE_OK; +} + +int +smdbm_put(database, key, data, flags) + SMDB_DATABASE *database; + SMDB_DBENT *key; + SMDB_DBENT *data; + u_int flags; +{ + int result; + int save_errno; + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + errno = 0; + result = dbm_store(dbm, key->dbm, data->dbm, + smdb_put_flags_to_ndbm_flags(flags)); + switch (result) + { + case 1: + return SMDBE_DUPLICATE; + + case 0: + return SMDBE_OK; + + default: + save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_IO_ERROR; + } + /* NOTREACHED */ +} + +int +smndbm_set_owner(database, uid, gid) + SMDB_DATABASE *database; + uid_t uid; + gid_t gid; +{ +# if HASFCHOWN + int fd; + int result; + DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + + fd = dbm_dirfno(dbm); + if (fd <= 0) + return EINVAL; + + result = fchown(fd, uid, gid); + if (result < 0) + return errno; + + fd = dbm_pagfno(dbm); + if (fd <= 0) + return EINVAL; + + result = fchown(fd, uid, gid); + if (result < 0) + return errno; +# endif /* HASFCHOWN */ + + return SMDBE_OK; +} + +int +smdbm_sync(database, flags) + SMDB_DATABASE *database; + u_int flags; +{ + return SMDBE_UNSUPPORTED; +} + +int +smdbm_cursor_close(cursor) + SMDB_CURSOR *cursor; +{ + SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; + SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; + + if (!db->smndbm_cursor_in_use) + return SMDBE_NOT_A_VALID_CURSOR; + + db->smndbm_cursor_in_use = FALSE; + free(dbm_cursor); + free(cursor); + + return SMDBE_OK; +} + +int +smdbm_cursor_del(cursor, flags) + SMDB_CURSOR *cursor; + u_int flags; +{ + int result; + SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; + SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; + DBM *dbm = db->smndbm_dbm; + + errno = 0; + result = dbm_delete(dbm, dbm_cursor->smndbmc_current_key); + if (result != 0) + { + int save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_NOT_FOUND; + } + return SMDBE_OK; +} + +int +smdbm_cursor_get(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; + SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; + DBM *dbm = db->smndbm_dbm; + + if (dbm_cursor->smndbmc_current_key.dptr == NULL) + { + dbm_cursor->smndbmc_current_key = dbm_firstkey(dbm); + if (dbm_cursor->smndbmc_current_key.dptr == NULL) + { + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + return SMDBE_LAST_ENTRY; + } + } + else + { + dbm_cursor->smndbmc_current_key = dbm_nextkey(dbm); + if (dbm_cursor->smndbmc_current_key.dptr == NULL) + { + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + return SMDBE_LAST_ENTRY; + } + } + + errno = 0; + value->dbm = dbm_fetch(dbm, dbm_cursor->smndbmc_current_key); + if (value->dbm.dptr == NULL) + { + int save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_NOT_FOUND; + } + key->dbm = dbm_cursor->smndbmc_current_key; + + return SMDBE_OK; +} + +int +smdbm_cursor_put(cursor, key, value, flags) + SMDB_CURSOR *cursor; + SMDB_DBENT *key; + SMDB_DBENT *value; + SMDB_FLAG flags; +{ + int result; + int save_errno; + SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; + SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; + DBM *dbm = db->smndbm_dbm; + + errno = 0; + result = dbm_store(dbm, dbm_cursor->smndbmc_current_key, value->dbm, + smdb_put_flags_to_ndbm_flags(flags)); + switch (result) + { + case 1: + return SMDBE_DUPLICATE; + + case 0: + return SMDBE_OK; + + default: + save_errno = errno; + + if (dbm_error(dbm)) + return SMDBE_IO_ERROR; + + if (save_errno != 0) + return save_errno; + + return SMDBE_IO_ERROR; + } + /* NOTREACHED */ +} + +int +smdbm_cursor(database, cursor, flags) + SMDB_DATABASE *database; + SMDB_CURSOR **cursor; + SMDB_FLAG flags; +{ + SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; + SMDB_CURSOR *cur; + SMDB_DBM_CURSOR *dbm_cursor; + + if (db->smndbm_cursor_in_use) + return SMDBE_ONLY_SUPPORTS_ONE_CURSOR; + + db->smndbm_cursor_in_use = TRUE; + dbm_cursor = (SMDB_DBM_CURSOR *) malloc(sizeof(SMDB_DBM_CURSOR)); + dbm_cursor->smndbmc_db = db; + dbm_cursor->smndbmc_current_key.dptr = NULL; + dbm_cursor->smndbmc_current_key.dsize = 0; + + cur = (SMDB_CURSOR*) malloc(sizeof(SMDB_CURSOR)); + if (cur == NULL) + return SMDBE_MALLOC; + + cur->smdbc_impl = dbm_cursor; + cur->smdbc_close = smdbm_cursor_close; + cur->smdbc_del = smdbm_cursor_del; + cur->smdbc_get = smdbm_cursor_get; + cur->smdbc_put = smdbm_cursor_put; + *cursor = cur; + + return SMDBE_OK; +} + + /* +** SMDB_NDBM_OPEN -- Opens a ndbm database. +** +** Parameters: +** database -- An unallocated database pointer to a pointer. +** db_name -- The name of the database without extension. +** mode -- File permisions on a created database. +** mode_mask -- Mode bits that much match on an opened database. +** sff -- Flags to safefile. +** type -- The type of database to open. +** Only SMDB_NDBM is supported. +** user_info -- Information on the user to use for file +** permissions. +** db_params -- +** No params are supported. +** +** Returns: +** SMDBE_OK -- Success, otherwise errno: +** SMDBE_MALLOC -- Cannot allocate memory. +** SMDBE_UNSUPPORTED -- The type is not supported. +** SMDBE_GDBM_IS_BAD -- We have detected GDBM and we don't +** like it. +** SMDBE_BAD_OPEN -- dbm_open failed and errno was not set. +** Anything else: errno +*/ + +int +smdb_ndbm_open(database, db_name, mode, mode_mask, sff, type, user_info, + db_params) + SMDB_DATABASE **database; + char *db_name; + int mode; + int mode_mask; + int sff; + SMDB_DBTYPE type; + SMDB_USER_INFO *user_info; + SMDB_DBPARAMS *db_params; +{ + int result; + int lock_fd; + SMDB_DATABASE *smdb_db; + SMDB_DBM_DATABASE *db; + DBM *dbm = NULL; + struct stat dir_stat_info; + struct stat pag_stat_info; + + result = SMDBE_OK; + *database = NULL; + + if (type == NULL) + return SMDBE_UNKNOWN_DB_TYPE; + + result = smdb_setup_file(db_name, SMNDB_DIR_FILE_EXTENSION, mode_mask, + sff, user_info, &dir_stat_info); + if (result != SMDBE_OK) + return result; + + result = smdb_setup_file(db_name, SMNDB_PAG_FILE_EXTENSION, mode_mask, + sff, user_info, &pag_stat_info); + if (result != SMDBE_OK) + return result; + + lock_fd = -1; +# if O_EXLOCK + mode |= O_EXLOCK; +# else /* O_EXLOCK */ + result = smdb_lock_file(&lock_fd, db_name, mode, sff, + SMNDB_DIR_FILE_EXTENSION); + if (result != SMDBE_OK) + return result; +# endif /* O_EXLOCK */ + + smdb_db = smdb_malloc_database(); + if (smdb_db == NULL) + result = SMDBE_MALLOC; + + db = smdbm_malloc_database(); + if (db == NULL) + result = SMDBE_MALLOC; + + /* Try to open database */ + if (result == SMDBE_OK) + { + db->smndbm_lock_fd = lock_fd; + + errno = 0; + dbm = dbm_open(db_name, mode, 0644); + if (dbm == NULL) + { + if (errno == 0) + result = SMDBE_BAD_OPEN; + else + result = errno; + } + db->smndbm_dbm = dbm; + } + + /* Check for GDBM */ + if (result == SMDBE_OK) + { + if (dbm_dirfno(dbm) == dbm_pagfno(dbm)) + result = SMDBE_GDBM_IS_BAD; + } + + /* Check for filechanged */ + if (result == SMDBE_OK) + { + result = smdb_filechanged(db_name, SMNDB_DIR_FILE_EXTENSION, + dbm_dirfno(dbm), &dir_stat_info); + if (result == SMDBE_OK) + { + result = smdb_filechanged(db_name, + SMNDB_PAG_FILE_EXTENSION, + dbm_pagfno(dbm), + &pag_stat_info); + } + } + + /* XXX Got to get fchown stuff in here */ + + /* Setup driver if everything is ok */ + if (result == SMDBE_OK) + { + *database = smdb_db; + + smdb_db->smdb_close = smdbm_close; + smdb_db->smdb_del = smdbm_del; + smdb_db->smdb_fd = smdbm_fd; + smdb_db->smdb_get = smdbm_get; + smdb_db->smdb_put = smdbm_put; + smdb_db->smdb_set_owner = smndbm_set_owner; + smdb_db->smdb_sync = smdbm_sync; + smdb_db->smdb_cursor = smdbm_cursor; + + smdb_db->smdb_impl = db; + + return SMDBE_OK; + } + + /* If we're here, something bad happened, clean up */ + if (dbm != NULL) + dbm_close(dbm); + + smdb_unlock_file(db->smndbm_lock_fd); + free(db); + smdb_free_database(smdb_db); + + return result; +} +#endif /* NDBM */ diff --git a/gnu/usr.sbin/sendmail/libsmutil/Build b/gnu/usr.sbin/sendmail/libsmutil/Build new file mode 100644 index 00000000000..d316a3787f4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.1 1999/05/21 22:56:21 gshapiro Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/libsmutil/Makefile b/gnu/usr.sbin/sendmail/libsmutil/Makefile new file mode 100644 index 00000000000..c0635422312 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 1.2 1999/09/23 22:36:32 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/libsmutil/Makefile.m4 b/gnu/usr.sbin/sendmail/libsmutil/Makefile.m4 new file mode 100644 index 00000000000..93a344c48ce --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/Makefile.m4 @@ -0,0 +1,13 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`library', `libsmutil') +define(`bldSOURCES', `debug.c errstring.c lockfile.c safefile.c snprintf.c strl.c ') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/libsmutil/debug.c b/gnu/usr.sbin/sendmail/libsmutil/debug.c new file mode 100644 index 00000000000..ced594e0299 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/debug.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: debug.c,v 8.2 1999/07/26 04:04:09 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +u_char tTdvect[100]; /* trace vector */ + +#if _FFR_DPRINTF_ +void +/*VARARGS1*/ +#ifdef __STDC__ +dprintf(const char *fmt, ...) +#else /* __STDC__ */ +dprintf(fmt, va_alist) + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + VA_LOCAL_DECL; + + (void) vfprintf(stdout, fmt, ap); +} + +int +dflush() +{ + return fflush(stdout); +} +#endif /* _FFR_DPRINTF_ */ diff --git a/gnu/usr.sbin/sendmail/libsmutil/errstring.c b/gnu/usr.sbin/sendmail/libsmutil/errstring.c new file mode 100644 index 00000000000..e38891538ef --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/errstring.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: errstring.c,v 8.8 2000/02/26 01:32:16 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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; +{ +#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) + extern char *sys_errlist[]; + extern int sys_nerr; +#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ + + /* + ** Handle special network error codes. + ** + ** These are 4.2/4.3bsd specific; they should be in daemon.c. + */ + + switch (errnum) + { + case EPERM: + /* SunOS gives "Not owner" -- this is the POSIX message */ + return "Operation not permitted"; + + /* + ** Error messages used internally in sendmail. + */ + + case E_SM_OPENTIMEOUT: + return "Timeout on file open"; + + case E_SM_NOSLINK: + return "Symbolic links not allowed"; + + case E_SM_NOHLINK: + return "Hard links not allowed"; + + case E_SM_REGONLY: + return "Regular files only"; + + case E_SM_ISEXEC: + return "Executable files not allowed"; + + case E_SM_WWDIR: + return "World writable directory"; + + case E_SM_GWDIR: + return "Group writable directory"; + + case E_SM_FILECHANGE: + return "File changed after open"; + + case E_SM_WWFILE: + return "World writable file"; + + case E_SM_GWFILE: + return "Group writable file"; + + case E_SM_GRFILE: + return "Group readable file"; + + case E_SM_WRFILE: + return "World readable file"; + + /* + ** DNS error messages. + */ + +#if NAMED_BIND + case HOST_NOT_FOUND + E_DNSBASE: + return "Name server: host not found"; + + case TRY_AGAIN + E_DNSBASE: + return "Name server: host name lookup failure"; + + case NO_RECOVERY + E_DNSBASE: + return "Name server: non-recoverable error"; + + case NO_DATA + E_DNSBASE: + return "Name server: no data known"; +#endif /* NAMED_BIND */ + + /* + ** libsmdb error messages. + */ + + case SMDBE_MALLOC: + return "Memory allocation failed"; + + case SMDBE_GDBM_IS_BAD: + return "GDBM is not supported"; + + case SMDBE_UNSUPPORTED: + return "Unsupported action"; + + case SMDBE_DUPLICATE: + return "Key already exists"; + + case SMDBE_BAD_OPEN: + return "Database open failed"; + + case SMDBE_NOT_FOUND: + return "Key not found"; + + case SMDBE_UNKNOWN_DB_TYPE: + return "Unknown database type"; + + case SMDBE_UNSUPPORTED_DB_TYPE: + return "Support for database type not compiled into this program"; + + case SMDBE_INCOMPLETE: + return "DB sync did not finish"; + + case SMDBE_KEY_EMPTY: + return "Key is empty"; + + case SMDBE_KEY_EXIST: + return "Key already exists"; + + case SMDBE_LOCK_DEADLOCK: + return "Locker killed to resolve deadlock"; + + case SMDBE_LOCK_NOT_GRANTED: + return "Lock unavailable"; + + case SMDBE_LOCK_NOT_HELD: + return "Lock not held by locker"; + + case SMDBE_RUN_RECOVERY: + return "Database panic, run recovery"; + + case SMDBE_IO_ERROR: + return "I/O error"; + + case SMDBE_READ_ONLY: + return "Database opened read-only"; + + case SMDBE_DB_NAME_TOO_LONG: + return "Name too long"; + + case SMDBE_INVALID_PARAMETER: + return "Invalid parameter"; + + case SMDBE_ONLY_SUPPORTS_ONE_CURSOR: + return "Only one cursor allowed"; + + case SMDBE_NOT_A_VALID_CURSOR: + return "Invalid cursor"; + + case SMDBE_OLD_VERSION: + return "Berkeley DB file is an old version, recreate it"; + } + + /* + ** LDAP error messages. + */ + +#ifdef LDAPMAP + if (errnum >= E_LDAPBASE) + return ldap_err2string(errnum - E_LDAPBASE); +#endif /* LDAPMAP */ + +#if HASSTRERROR + return strerror(errnum); +#else /* HASSTRERROR */ + if (errnum > 0 && errnum < sys_nerr) + return sys_errlist[errnum]; + else + { + static char buf[MAXLINE]; + + (void) snprintf(buf, sizeof buf, "Error %d", errnum); + return buf; + } +#endif /* HASSTRERROR */ +} diff --git a/gnu/usr.sbin/sendmail/libsmutil/lockfile.c b/gnu/usr.sbin/sendmail/libsmutil/lockfile.c new file mode 100644 index 00000000000..50038213aee --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/lockfile.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: lockfile.c,v 8.3 1999/08/31 15:38:27 ca Exp $"; +#endif /* ! lint */ + +#include + + /* +** 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). [unused] +** ext -- the filename extension. [unused] +** 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; + extern int errno; + + memset(&lfd, '\0', 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 (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, type) >= 0) + return TRUE; + +#endif /* !HASFLOCK */ + + return FALSE; +} diff --git a/gnu/usr.sbin/sendmail/libsmutil/safefile.c b/gnu/usr.sbin/sendmail/libsmutil/safefile.c new file mode 100644 index 00000000000..63084c1f541 --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/safefile.c @@ -0,0 +1,947 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: safefile.c,v 8.81 2000/02/26 01:32:17 gshapiro Exp $"; +#endif /* ! lint */ + +#include + /* +** 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. +** user -- 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. +*/ + +int +safefile(fn, uid, gid, user, flags, mode, st) + char *fn; + UID_T uid; + GID_T gid; + char *user; + long flags; + int mode; + struct stat *st; +{ + register char *p; + register struct group *gr = NULL; + int file_errno = 0; + bool checkpath; + struct stat stbuf; + struct stat fstbuf; + char fbuf[MAXPATHLEN + 1]; + + if (tTd(44, 4)) + dprintf("safefile(%s, uid=%d, gid=%d, flags=%lx, mode=%o):\n", + fn, (int) uid, (int) gid, flags, mode); + errno = 0; + if (st == NULL) + st = &fstbuf; + if (strlcpy(fbuf, fn, sizeof fbuf) >= sizeof fbuf) + { + if (tTd(44, 4)) + dprintf("\tpathname too long\n"); + return ENAMETOOLONG; + } + fn = fbuf; + + /* ignore SFF_SAFEDIRPATH if we are debugging */ + if (RealUid != 0 && RunAsUid == RealUid) + flags &= ~SFF_SAFEDIRPATH; + + /* first check to see if the file exists at all */ +#if HASLSTAT + if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st) + : stat(fn, st)) < 0) +#else /* HASLSTAT */ + if (stat(fn, st) < 0) +#endif /* HASLSTAT */ + { + 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 /* SUID_ROOT_FILES_OK */ + if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0 && + st->st_uid != TrustedUid) +#endif /* SUID_ROOT_FILES_OK */ + { + uid = st->st_uid; + user = NULL; + } +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISGID, st->st_mode)) +#else /* SUID_ROOT_FILES_OK */ + if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0) +#endif /* SUID_ROOT_FILES_OK */ + gid = st->st_gid; + } + + checkpath = !bitset(SFF_NOPATHCHECK, flags) || + (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags)); + if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags)) + { + int ret; + + /* check the directory */ + p = strrchr(fn, '/'); + if (p == NULL) + { + ret = safedirpath(".", uid, gid, user, + flags|SFF_SAFEDIRPATH, 0, 0); + } + else + { + *p = '\0'; + ret = safedirpath(fn, uid, gid, user, + flags|SFF_SAFEDIRPATH, 0, 0); + *p = '/'; + } + if (ret == 0) + { + /* directory is safe */ + checkpath = FALSE; + } + else + { +#if HASLSTAT + /* Need lstat() information if called stat() before */ + if (!bitset(SFF_NOSLINK, flags) && lstat(fn, st) < 0) + { + ret = errno; + if (tTd(44, 4)) + dprintf("\t%s\n", errstring(ret)); + return ret; + } +#endif /* HASLSTAT */ + /* directory is writable: disallow links */ + flags |= SFF_NOLINK; + } + } + + if (checkpath) + { + int ret; + + p = strrchr(fn, '/'); + if (p == NULL) + { + ret = safedirpath(".", uid, gid, user, flags, 0, 0); + } + else + { + *p = '\0'; + ret = safedirpath(fn, uid, gid, user, flags, 0, 0); + *p = '/'; + } + if (ret != 0) + return ret; + } + + /* + ** If the target file doesn't exist, check the directory to + ** ensure that it is writable by this user. + */ + + if (file_errno != 0) + { + int ret = file_errno; + char *dir = fn; + + if (tTd(44, 4)) + dprintf("\t%s\n", errstring(ret)); + + errno = 0; + if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT) + return ret; + + /* check to see if legal to create the file */ + p = strrchr(dir, '/'); + if (p == NULL) + dir = "."; + else if (p == dir) + dir = "/"; + else + *p = '\0'; + if (stat(dir, &stbuf) >= 0) + { + int md = S_IWRITE|S_IEXEC; + + if (stbuf.st_uid == uid) + /* EMPTY */ + ; + else if (uid == 0 && stbuf.st_uid == TrustedUid) + /* EMPTY */ + ; + else + { + md >>= 3; + if (stbuf.st_gid == gid) + /* EMPTY */ + ; +#ifndef NO_GROUP_SET + else if (user != NULL && !DontInitGroups && + ((gr != NULL && + gr->gr_gid == stbuf.st_gid) || + (gr = getgrgid(stbuf.st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; *gp != NULL; gp++) + if (strcmp(*gp, user) == 0) + break; + if (*gp == NULL) + md >>= 3; + } +#endif /* ! NO_GROUP_SET */ + else + md >>= 3; + } + if ((stbuf.st_mode & md) != md) + errno = EACCES; + } + ret = errno; + if (tTd(44, 4)) + dprintf("\t[final dir %s uid %d mode %lo] %s\n", + dir, (int) stbuf.st_uid, (u_long) stbuf.st_mode, + errstring(ret)); + if (p != NULL) + *p = '/'; + st->st_mode = ST_MODE_NOFILE; + return ret; + } + +#ifdef S_ISLNK + if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[slink mode %lo]\tE_SM_NOSLINK\n", + (u_long) st->st_mode); + return E_SM_NOSLINK; + } +#endif /* S_ISLNK */ + if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[non-reg mode %lo]\tE_SM_REGONLY\n", + (u_long) st->st_mode); + return E_SM_REGONLY; + } + if (bitset(SFF_NOGWFILES, flags) && + bitset(S_IWGRP, st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[write bits %lo]\tE_SM_GWFILE\n", + (u_long) st->st_mode); + return E_SM_GWFILE; + } + if (bitset(SFF_NOWWFILES, flags) && + bitset(S_IWOTH, st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[write bits %lo]\tE_SM_WWFILE\n", + (u_long) st->st_mode); + return E_SM_WWFILE; + } + if (bitset(SFF_NOGRFILES, flags) && bitset(S_IRGRP, st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[read bits %lo]\tE_SM_GRFILE\n", + (u_long) st->st_mode); + return E_SM_GRFILE; + } + if (bitset(SFF_NOWRFILES, flags) && bitset(S_IROTH, st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[read bits %lo]\tE_SM_WRFILE\n", + (u_long) st->st_mode); + return E_SM_WRFILE; + } + if (!bitset(SFF_EXECOK, flags) && + bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) && + bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[exec bits %lo]\tE_SM_ISEXEC]\n", + (u_long) st->st_mode); + return E_SM_ISEXEC; + } + if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1) + { + if (tTd(44, 4)) + dprintf("\t[link count %d]\tE_SM_NOHLINK\n", + (int) st->st_nlink); + return E_SM_NOHLINK; + } + + if (uid == 0 && bitset(SFF_OPENASROOT, flags)) + /* EMPTY */ + ; + else if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + mode >>= 6; + else if (st->st_uid == uid) + /* EMPTY */ + ; + else if (uid == 0 && st->st_uid == TrustedUid) + /* EMPTY */ + ; + else + { + mode >>= 3; + if (st->st_gid == gid) + /* EMPTY */ + ; +#ifndef NO_GROUP_SET + else if (user != NULL && !DontInitGroups && + ((gr != NULL && gr->gr_gid == st->st_gid) || + (gr = getgrgid(st->st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; *gp != NULL; gp++) + if (strcmp(*gp, user) == 0) + break; + if (*gp == NULL) + mode >>= 3; + } +#endif /* ! NO_GROUP_SET */ + else + mode >>= 3; + } + if (tTd(44, 4)) + dprintf("\t[uid %d, nlink %d, stat %lo, mode %lo] ", + (int) st->st_uid, (int) st->st_nlink, + (u_long) st->st_mode, (u_long) mode); + if ((st->st_uid == uid || st->st_uid == 0 || + st->st_uid == TrustedUid || + !bitset(SFF_MUSTOWN, flags)) && + (st->st_mode & mode) == mode) + { + if (tTd(44, 4)) + dprintf("\tOK\n"); + return 0; + } + if (tTd(44, 4)) + dprintf("\tEACCES\n"); + return EACCES; +} + /* +** SAFEDIRPATH -- check to make sure a path to a directory is safe +** +** Safe means not writable and owned by the right folks. +** +** Parameters: +** fn -- filename to check. +** uid -- user id to compare against. +** gid -- group id to compare against. +** user -- user name to compare against (used for group +** sets). +** flags -- modifiers: +** SFF_ROOTOK -- ok to use root permissions to open. +** SFF_SAFEDIRPATH -- writable directories are considered +** to be fatal errors. +** level -- symlink recursive level. +** offset -- offset into fn to start checking from. +** +** Returns: +** 0 -- if the directory path is "safe". +** else -- an error number associated with the path. +*/ + +int +safedirpath(fn, uid, gid, user, flags, level, offset) + char *fn; + UID_T uid; + GID_T gid; + char *user; + long flags; + int level; + int offset; +{ + int ret = 0; + int mode = S_IWOTH; + char save = '\0'; + char *saveptr = NULL; + char *p, *enddir; + register struct group *gr = NULL; + char s[MAXLINKPATHLEN + 1]; + struct stat stbuf; + + /* make sure we aren't in a symlink loop */ + if (level > MAXSYMLINKS) + return ELOOP; + + /* special case root directory */ + if (*fn == '\0') + fn = "/"; + + if (tTd(44, 4)) + dprintf("safedirpath(%s, uid=%ld, gid=%ld, flags=%lx, level=%d, offset=%d):\n", + fn, (long) uid, (long) gid, flags, level, offset); + + if (!bitnset(DBS_GROUPWRITABLEDIRPATHSAFE, DontBlameSendmail)) + mode |= S_IWGRP; + + /* Make a modifiable copy of the filename */ + if (strlcpy(s, fn, sizeof s) >= sizeof s) + return EINVAL; + + p = s + offset; + while (p != NULL) + { + /* put back character */ + if (saveptr != NULL) + { + *saveptr = save; + saveptr = NULL; + p++; + } + + if (*p == '\0') + break; + + p = strchr(p, '/'); + + /* Special case for root directory */ + if (p == s) + { + save = *(p + 1); + saveptr = p + 1; + *(p + 1) = '\0'; + } + else if (p != NULL) + { + save = *p; + saveptr = p; + *p = '\0'; + } + + /* Heuristic: . and .. have already been checked */ + enddir = strrchr(s, '/'); + if (enddir != NULL && + (strcmp(enddir, "/..") == 0 || + strcmp(enddir, "/.") == 0)) + continue; + + if (tTd(44, 20)) + dprintf("\t[dir %s]\n", s); + +#if HASLSTAT + ret = lstat(s, &stbuf); +#else /* HASLSTAT */ + ret = stat(s, &stbuf); +#endif /* HASLSTAT */ + if (ret < 0) + { + ret = errno; + break; + } + +#ifdef S_ISLNK + /* Follow symlinks */ + if (S_ISLNK(stbuf.st_mode)) + { + char *target; + char buf[MAXPATHLEN + 1]; + + memset(buf, '\0', sizeof buf); + if (readlink(s, buf, sizeof buf) < 0) + { + ret = errno; + break; + } + + offset = 0; + if (*buf == '/') + { + target = buf; + + /* If path is the same, avoid rechecks */ + while (s[offset] == buf[offset] && + s[offset] != '\0') + offset++; + + if (s[offset] == '\0' && buf[offset] == '\0') + { + /* strings match, symlink loop */ + return ELOOP; + } + + /* back off from the mismatch */ + if (offset > 0) + offset--; + + /* Make sure we are at a directory break */ + if (offset > 0 && + s[offset] != '/' && + s[offset] != '\0') + { + while (buf[offset] != '/' && + offset > 0) + offset--; + } + if (offset > 0 && + s[offset] == '/' && + buf[offset] == '/') + { + /* Include the trailing slash */ + offset++; + } + } + else + { + char *sptr; + char fullbuf[MAXLINKPATHLEN + 1]; + + sptr = strrchr(s, '/'); + if (sptr != NULL) + { + *sptr = '\0'; + offset = sptr + 1 - s; + if ((strlen(s) + 1 + + strlen(buf) + 1) > sizeof fullbuf) + { + ret = EINVAL; + break; + } + snprintf(fullbuf, sizeof fullbuf, + "%s/%s", s, buf); + *sptr = '/'; + } + else + { + if (strlen(buf) + 1 > sizeof fullbuf) + { + ret = EINVAL; + break; + } + (void) strlcpy(fullbuf, buf, + sizeof fullbuf); + } + target = fullbuf; + } + ret = safedirpath(target, uid, gid, user, flags, + level + 1, offset); + if (ret != 0) + break; + + /* Don't check permissions on the link file itself */ + continue; + } +#endif /* S_ISLNK */ + + if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) && +#ifdef S_ISVTX + !(bitnset(DBS_TRUSTSTICKYBIT, DontBlameSendmail) && + bitset(S_ISVTX, stbuf.st_mode)) && +#endif /* S_ISVTX */ + bitset(mode, stbuf.st_mode)) + { + if (tTd(44, 4)) + dprintf("\t[dir %s] mode %lo ", + s, (u_long) stbuf.st_mode); + if (bitset(SFF_SAFEDIRPATH, flags)) + { + if (bitset(S_IWOTH, stbuf.st_mode)) + ret = E_SM_WWDIR; + else + ret = E_SM_GWDIR; + if (tTd(44, 4)) + dprintf("FATAL\n"); + break; + } + if (tTd(44, 4)) + dprintf("WARNING\n"); + if (Verbose > 1) + message("051 WARNING: %s writable directory %s", + bitset(S_IWOTH, stbuf.st_mode) + ? "World" + : "Group", + s); + } + if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags)) + { + if (bitset(S_IXOTH, stbuf.st_mode)) + continue; + ret = EACCES; + break; + } + + /* + ** Let OS determine access to file if we are not + ** running as a privileged user. This allows ACLs + ** to work. Also, if opening as root, assume we can + ** scan the directory. + */ + if (geteuid() != 0 || bitset(SFF_OPENASROOT, flags)) + continue; + + if (stbuf.st_uid == uid && + bitset(S_IXUSR, stbuf.st_mode)) + continue; + if (stbuf.st_gid == gid && + bitset(S_IXGRP, stbuf.st_mode)) + continue; +#ifndef NO_GROUP_SET + if (user != NULL && !DontInitGroups && + ((gr != NULL && gr->gr_gid == stbuf.st_gid) || + (gr = getgrgid(stbuf.st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++) + if (strcmp(*gp, user) == 0) + break; + if (gp != NULL && *gp != NULL && + bitset(S_IXGRP, stbuf.st_mode)) + continue; + } +#endif /* ! NO_GROUP_SET */ + if (!bitset(S_IXOTH, stbuf.st_mode)) + { + ret = EACCES; + break; + } + } + if (tTd(44, 4)) + dprintf("\t[dir %s] %s\n", fn, + ret == 0 ? "OK" : errstring(ret)); + return ret; +} + /* +** SAFEOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as open. +*/ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif /* ! O_ACCMODE */ + +int +safeopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + long sff; +{ + int rval; + int fd; + int smode; + struct stat stb; + + if (tTd(44, 10)) + printf("safeopen: fn=%s, omode=%x, cmode=%x, sff=%lx\n", + fn, omode, cmode, sff); + + if (bitset(O_CREAT, omode)) + sff |= SFF_CREAT; + omode &= ~O_CREAT; + smode = 0; + switch (omode & O_ACCMODE) + { + case O_RDONLY: + smode = S_IREAD; + break; + + case O_WRONLY: + smode = S_IWRITE; + break; + + case O_RDWR: + smode = S_IREAD|S_IWRITE; + break; + + default: + smode = 0; + break; + } + if (bitset(SFF_OPENASROOT, sff)) + rval = safefile(fn, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &stb); + else + rval = safefile(fn, RealUid, RealGid, RealUserName, + sff, smode, &stb); + if (rval != 0) + { + errno = rval; + return -1; + } + if (stb.st_mode == ST_MODE_NOFILE && bitset(SFF_CREAT, sff)) + omode |= O_CREAT | (bitset(SFF_NOTEXCL, sff) ? 0 : O_EXCL); + else if (bitset(SFF_CREAT, sff) && bitset(O_EXCL, omode)) + { + /* The file exists so an exclusive create would fail */ + errno = EEXIST; + return -1; + } + + fd = dfopen(fn, omode, cmode, sff); + if (fd < 0) + return fd; + if (filechanged(fn, fd, &stb)) + { + syserr("554 5.3.0 cannot open: file %s changed after open", fn); + (void) close(fd); + errno = E_SM_FILECHANGE; + return -1; + } + return fd; +} + /* +** SAFEFOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as fopen. +*/ + +FILE * +safefopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + long sff; +{ + int fd; + int save_errno; + FILE *fp; + char *fmode; + + switch (omode & O_ACCMODE) + { + case O_RDONLY: + fmode = "r"; + break; + + case O_WRONLY: + if (bitset(O_APPEND, omode)) + fmode = "a"; + else + fmode = "w"; + break; + + case O_RDWR: + if (bitset(O_TRUNC, omode)) + fmode = "w+"; + else if (bitset(O_APPEND, omode)) + fmode = "a+"; + else + fmode = "r+"; + break; + + default: + syserr("554 5.3.5 safefopen: unknown omode %o", omode); + fmode = "x"; + } + fd = safeopen(fn, omode, cmode, sff); + if (fd < 0) + { + save_errno = errno; + if (tTd(44, 10)) + dprintf("safefopen: safeopen failed: %s\n", + errstring(errno)); + errno = save_errno; + return NULL; + } + fp = fdopen(fd, fmode); + if (fp != NULL) + return fp; + + save_errno = errno; + if (tTd(44, 10)) + { + dprintf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%lx, err=%s\n", + fn, fmode, omode, sff, errstring(errno)); + } + (void) close(fd); + errno = save_errno; + return NULL; +} + /* +** FILECHANGED -- check to see if file changed after being opened +** +** Parameters: +** fn -- pathname of file to check. +** fd -- file descriptor to check. +** stb -- stat structure from before open. +** +** Returns: +** TRUE -- if a problem was detected. +** FALSE -- if this file is still the same. +*/ + +bool +filechanged(fn, fd, stb) + char *fn; + int fd; + struct stat *stb; +{ + struct stat sta; + + if (stb->st_mode == ST_MODE_NOFILE) + { +#if HASLSTAT && BOGUS_O_EXCL + /* only necessary if exclusive open follows symbolic links */ + if (lstat(fn, stb) < 0 || stb->st_nlink != 1) + return TRUE; +#else /* HASLSTAT && BOGUS_O_EXCL */ + return FALSE; +#endif /* HASLSTAT && BOGUS_O_EXCL */ + } + if (fstat(fd, &sta) < 0) + return TRUE; + + if (sta.st_nlink != stb->st_nlink || + sta.st_dev != stb->st_dev || + sta.st_ino != stb->st_ino || +#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ + sta.st_gen != stb->st_gen || +#endif /* HAS_ST_GEN && 0 */ + sta.st_uid != stb->st_uid || + sta.st_gid != stb->st_gid) + { + if (tTd(44, 8)) + { + dprintf("File changed after opening:\n"); + dprintf(" nlink = %ld/%ld\n", + (long) stb->st_nlink, (long) sta.st_nlink); + dprintf(" dev = %ld/%ld\n", + (long) stb->st_dev, (long) sta.st_dev); + if (sizeof sta.st_ino > sizeof (long)) + { + dprintf(" ino = %s/", + quad_to_string(stb->st_ino)); + dprintf("%s\n", + quad_to_string(sta.st_ino)); + } + else + dprintf(" ino = %lu/%lu\n", + (unsigned long) stb->st_ino, + (unsigned long) sta.st_ino); +#if HAS_ST_GEN + dprintf(" gen = %ld/%ld\n", + (long) stb->st_gen, (long) sta.st_gen); +#endif /* HAS_ST_GEN */ + dprintf(" uid = %ld/%ld\n", + (long) stb->st_uid, (long) sta.st_uid); + dprintf(" gid = %ld/%ld\n", + (long) stb->st_gid, (long) sta.st_gid); + } + return TRUE; + } + + return FALSE; +} + /* +** DFOPEN -- determined file open +** +** This routine has the semantics of open, except that it will +** keep trying a few times to make this happen. The idea is that +** on very loaded systems, we may run out of resources (inodes, +** whatever), so this tries to get around it. +*/ + +int +dfopen(filename, omode, cmode, sff) + char *filename; + int omode; + int cmode; + long sff; +{ + register int tries; + int fd = -1; + struct stat st; + + for (tries = 0; tries < 10; tries++) + { + (void) 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 /* ETXTBSY */ + continue; + } + break; + } + if (!bitset(SFF_NOLOCK, sff) && + fd >= 0 && + fstat(fd, &st) >= 0 && + S_ISREG(st.st_mode)) + { + int locktype; + + /* lock the file to avoid accidental conflicts */ + if ((omode & O_ACCMODE) != O_RDONLY) + locktype = LOCK_EX; + else + locktype = LOCK_SH; + if (!lockfile(fd, filename, NULL, locktype)) + { + int save_errno = errno; + + (void) close(fd); + fd = -1; + errno = save_errno; + } + else + errno = 0; + } + return fd; +} diff --git a/gnu/usr.sbin/sendmail/libsmutil/snprintf.c b/gnu/usr.sbin/sendmail/libsmutil/snprintf.c new file mode 100644 index 00000000000..fc5095da25e --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/snprintf.c @@ -0,0 +1,429 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: snprintf.c,v 8.27 1999/10/13 03:27:08 ca Exp $"; +#endif /* ! lint */ + +#include + + /* +** SNPRINTF, VSNPRINT -- counted versions of printf +** +** These versions have been grabbed off the net. They have been +** cleaned up to compile properly and support for .precision and +** %lx has been added. +*/ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (sm_dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + **************************************************************/ + +/*static char _id[] = "$OrigId: snprintf.c,v 1.2 1995/10/09 11:19:47 roberto Exp $";*/ +void sm_dopr(); +char *DoprEnd; +int SnprfOverflow; + +#if !HASSNPRINTF + +/* VARARGS3 */ +int +# ifdef __STDC__ +snprintf(char *str, size_t count, const char *fmt, ...) +# else /* __STDC__ */ +snprintf(str, count, fmt, va_alist) + char *str; + size_t count; + const char *fmt; + va_dcl +# endif /* __STDC__ */ +{ + int len; + VA_LOCAL_DECL + + VA_START(fmt); + len = vsnprintf(str, count, fmt, ap); + VA_END; + return len; +} + + +# ifndef luna2 +int +vsnprintf(str, count, fmt, args) + char *str; + size_t count; + const char *fmt; + va_list args; +{ + str[0] = 0; + DoprEnd = str + count - 1; + SnprfOverflow = 0; + sm_dopr( str, fmt, args ); + if (count > 0) + DoprEnd[0] = 0; + if (SnprfOverflow && tTd(57, 2)) + dprintf("\nvsnprintf overflow, len = %ld, str = %s", + (long) count, shortenstring(str, MAXSHORTSTR)); + return strlen(str); +} + +# endif /* ! luna2 */ +#endif /* !HASSNPRINTF */ + +/* + * sm_dopr(): poor man's version of doprintf + */ + +void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth)); +void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad)); +void dostr __P(( char * , int )); +char *output; +void dopr_outch __P(( int c )); +int SyslogErrno; + +void +sm_dopr( buffer, format, args ) + char *buffer; + const char *format; + va_list args; +{ + int ch; + long value; + int longflag = 0; + int pointflag = 0; + int maxwidth = 0; + char *strvalue; + int ljust; + int len; + int zpad; +#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) + extern char *sys_errlist[]; + extern int sys_nerr; +#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ + + + output = buffer; + while( (ch = *format++) != '\0' ){ + switch( ch ){ + case '%': + ljust = len = zpad = maxwidth = 0; + longflag = pointflag = 0; + nextch: + ch = *format++; + switch( ch ){ + case 0: + dostr( "**end of format**" , 0); + return; + case '-': ljust = 1; goto nextch; + case '0': /* set zero padding if len not set */ + if(len==0 && !pointflag) zpad = '0'; + /* FALLTHROUGH */ + case '1': case '2': case '3': + case '4': case '5': case '6': + case '7': case '8': case '9': + if (pointflag) + maxwidth = maxwidth*10 + ch - '0'; + else + len = len*10 + ch - '0'; + goto nextch; + case '*': + if (pointflag) + maxwidth = va_arg( args, int ); + else + len = va_arg( args, int ); + goto nextch; + case '.': pointflag = 1; goto nextch; + case 'l': longflag = 1; goto nextch; + case 'u': case 'U': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,0, ljust, len, zpad ); break; + case 'o': case 'O': + /*fmtnum(value,base,dosign,ljust,len,zpad) */ + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 8,0, ljust, len, zpad ); break; + case 'd': case 'D': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 10,1, ljust, len, zpad ); break; + case 'x': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value, 16,0, ljust, len, zpad ); break; + case 'X': + if( longflag ){ + value = va_arg( args, long ); + } else { + value = va_arg( args, int ); + } + fmtnum( value,-16,0, ljust, len, zpad ); break; + case 's': + strvalue = va_arg( args, char *); + if (maxwidth > 0 || !pointflag) { + if (pointflag && len > maxwidth) + len = maxwidth; /* Adjust padding */ + fmtstr( strvalue,ljust,len,zpad, maxwidth); + } + break; + case 'c': + ch = va_arg( args, int ); + dopr_outch( ch ); break; + case 'm': +#if HASSTRERROR + dostr(strerror(SyslogErrno), 0); +#else /* HASSTRERROR */ + if (SyslogErrno < 0 || SyslogErrno >= sys_nerr) + { + dostr("Error ", 0); + fmtnum(SyslogErrno, 10, 0, 0, 0, 0); + } + else + dostr((char *)sys_errlist[SyslogErrno], 0); +#endif /* HASSTRERROR */ + break; + + case '%': dopr_outch( ch ); continue; + default: + dostr( "???????" , 0); + } + break; + default: + dopr_outch( ch ); + break; + } + } + *output = 0; +} + +void +fmtstr( value, ljust, len, zpad, maxwidth ) + char *value; + int ljust, len, zpad, maxwidth; +{ + int padlen, strleng; /* amount to pad */ + + if( value == 0 ){ + value = ""; + } + for( strleng = 0; value[strleng]; ++ strleng ); /* strlen */ + if (strleng > maxwidth && maxwidth) + strleng = maxwidth; + padlen = len - strleng; + if( padlen < 0 ) padlen = 0; + if( ljust ) padlen = -padlen; + while( padlen > 0 ) { + dopr_outch( ' ' ); + --padlen; + } + dostr( value, maxwidth ); + while( padlen < 0 ) { + dopr_outch( ' ' ); + ++padlen; + } +} + +void +fmtnum( value, base, dosign, ljust, len, zpad ) + long value; + int base, dosign, ljust, len, zpad; +{ + int signvalue = 0; + unsigned long uvalue; + char convert[20]; + int place = 0; + int padlen = 0; /* amount to pad */ + int caps = 0; + + /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", + value, base, dosign, ljust, len, zpad )); */ + uvalue = value; + if( dosign ){ + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } + } + if( base < 0 ){ + caps = 1; + base = -base; + } + do{ + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + }while(uvalue); + convert[place] = 0; + padlen = len - place; + if( padlen < 0 ) padlen = 0; + if( ljust ) padlen = -padlen; + /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n", + convert,place,signvalue,padlen)); */ + if( zpad && padlen > 0 ){ + if( signvalue ){ + dopr_outch( signvalue ); + --padlen; + signvalue = 0; + } + while( padlen > 0 ){ + dopr_outch( zpad ); + --padlen; + } + } + while( padlen > 0 ) { + dopr_outch( ' ' ); + --padlen; + } + if( signvalue ) dopr_outch( signvalue ); + while( place > 0 ) dopr_outch( convert[--place] ); + while( padlen < 0 ){ + dopr_outch( ' ' ); + ++padlen; + } +} + +void +dostr( str , cut) + char *str; + int cut; +{ + if (cut) { + while(*str && cut-- > 0) dopr_outch(*str++); + } else { + while(*str) dopr_outch(*str++); + } +} + +void +dopr_outch( c ) + int c; +{ +#if 0 + if( iscntrl(c) && c != '\n' && c != '\t' ){ + c = '@' + (c & 0x1F); + if( DoprEnd == 0 || output < DoprEnd ) + *output++ = '^'; + } +#endif /* 0 */ + if( DoprEnd == 0 || output < DoprEnd ) + *output++ = c; + else + SnprfOverflow++; +} + + /* +** QUAD_TO_STRING -- Convert a quad type to a string. +** +** Convert a quad type to a string. This must be done +** separately as %lld/%qd are not supported by snprint() +** and adding support would slow down systems which only +** emulate the data type. +** +** Parameters: +** value -- number to convert to a string. +** +** Returns: +** pointer to a string. +*/ + +char * +quad_to_string(value) + QUAD_T value; +{ + char *formatstr; + static char buf[64]; + + /* + ** Use sprintf() instead of snprintf() since snprintf() + ** does not support %qu or %llu. The buffer is large enough + ** to hold the string so there is no danger of buffer + ** overflow. + */ + +#if NEED_PERCENTQ + formatstr = "%qu"; +#else /* NEED_PERCENTQ */ + formatstr = "%llu"; +#endif /* NEED_PERCENTQ */ + sprintf(buf, formatstr, value); + return buf; +} + /* +** SHORTENSTRING -- return short version of a string +** +** If the string is already short, just return it. If it is too +** long, return the head and tail of the string. +** +** Parameters: +** s -- the string to shorten. +** m -- the max length of the string (strlen()). +** +** Returns: +** Either s or a short version of s. +*/ + +char * +shortenstring(s, m) + register const char *s; + int m; +{ + int l; + static char buf[MAXSHORTSTR + 1]; + + l = strlen(s); + if (l < m) + return (char *) s; + if (m > MAXSHORTSTR) + m = MAXSHORTSTR; + else if (m < 10) + { + if (m < 5) + { + (void) strlcpy(buf, s, m + 1); + return buf; + } + (void) strlcpy(buf, s, m - 2); + (void) strlcat(buf, "...", sizeof buf); + return buf; + } + m = (m - 3) / 2; + (void) strlcpy(buf, s, m + 1); + (void) strlcat(buf, "...", sizeof buf); + (void) strlcat(buf, s + l - m, sizeof buf); + return buf; +} diff --git a/gnu/usr.sbin/sendmail/libsmutil/strl.c b/gnu/usr.sbin/sendmail/libsmutil/strl.c new file mode 100644 index 00000000000..d3cd20fe00a --- /dev/null +++ b/gnu/usr.sbin/sendmail/libsmutil/strl.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: strl.c,v 8.5 1999/12/29 22:13:46 ca Exp $"; +#endif /* ! lint */ + +#include + +#if !HASSTRL + /* +** strlcpy -- copy string obeying length and '\0' terminate it +** +** terminates with '\0' if len > 0 +** +** Parameters: +** dst -- "destination" string. +** src -- "from" string. +** len -- length of space available in "destination" string. +** +** Returns: +** total length of the string tried to create (=strlen(src)) +** if this is greater than len then an overflow would have +** occurred. +*/ + +size_t +strlcpy(dst, src, len) + register char *dst; + register const char *src; + size_t len; +{ + register size_t i; + + if (len-- <= 0) + return strlen(src); + for (i = 0; i < len && (dst[i] = src[i]) != 0; i++) + continue; + dst[i] = '\0'; + if (src[i] == '\0') + return i; + else + return i + strlen(src + i); +} + /* +** strlcat -- catenate strings obeying length and '\0' terminate it +** +** strlcat will append at most len - strlen(dst) - 1 chars. +** terminates with '\0' if len > 0 +** +** Parameters: +** dst -- "destination" string. +** src -- "from" string. +** len -- max. length of "destination" string. +** +** Returns: +** total length of the string tried to create +** (= initial length of dst + length of src) +** if this is greater than len then an overflow would have +** occurred. +*/ + +size_t +strlcat(dst, src, len) + register char *dst; + register const char *src; + size_t len; +{ + register size_t i, j, o; + + o = strlen(dst); + if (len < o + 1) + return o + strlen(src); + len -= o + 1; + for (i = 0, j = o; i < len && (dst[j] = src[i]) != 0; i++, j++) + continue; + dst[j] = '\0'; + if (src[i] == '\0') + return j; + else + return j + strlen(src + i); +} + +#endif /* !HASSTRL */ diff --git a/gnu/usr.sbin/sendmail/mail.local/Build b/gnu/usr.sbin/sendmail/mail.local/Build new file mode 100644 index 00000000000..fb86cd963e4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:32:28 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/mail.local/Makefile b/gnu/usr.sbin/sendmail/mail.local/Makefile new file mode 100644 index 00000000000..04a5fc91799 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/Makefile @@ -0,0 +1,19 @@ +# $Sendmail: Makefile,v 8.5 1999/10/05 16:39:32 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +force-install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/mail.local/Makefile.m4 b/gnu/usr.sbin/sendmail/mail.local/Makefile.m4 new file mode 100644 index 00000000000..f5344f8142d --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/Makefile.m4 @@ -0,0 +1,29 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +bldPRODUCT_START(`executable', `mail.local') +define(`bldNO_INSTALL') +define(`bldSOURCES', `mail.local.c ') +bldPUSH_SMLIB(`smutil') +PREPENDDEF(`confENVDEF', `confMAPDEF') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `mail.local') +define(`bldSOURCES', `mail.local.8') +bldPRODUCT_END + +divert(bldTARGETS_SECTION) +install: + @echo "NOTE: This version of mail.local is not suited for some operating" + @echo " systems such as HP-UX and Solaris. Please consult the" + @echo " README file in the mail.local directory. You can force" + @echo " the install using 'Build force-install'." + +force-install: install-mail.local ifdef(`confNO_MAN_BUILD',, `install-docs') + +install-mail.local: mail.local + ${INSTALL} -c -o ${UBINOWN} -g ${UBINGRP} -m ${UBINMODE} mail.local ${DESTDIR}${EBINDIR} +divert + +bldFINISH + + diff --git a/gnu/usr.sbin/sendmail/mail.local/README b/gnu/usr.sbin/sendmail/mail.local/README new file mode 100644 index 00000000000..21cdd04dd65 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/README @@ -0,0 +1,39 @@ +This directory contains the source files for mail.local. + +This is not intended to be used on *stock* 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). + +If you choose to run *this* mail.local on these systems then you may also +need to replace the existing MUAs, as well as IMAP and POP servers, with +ones that are compatible with the BSD interface. You have been warned! + +For systems with maillock() support, compile with -DMAILLOCK and link with +-lmail to use the maillock() routines. This can be accomplished in your +site.config.m4 file with: + + APPENDDEF(`conf_mail_local_ENVDEF', `-DMAILLOCK') + APPENDDEF(`conf_mail_local_LIBS', `-lmail') + +Defining CONTENTLENGTH (-DCONTENTLENGTH) will build a mail.local which +outputs a Content-Length: header. Solaris 2.3 and later will automatically +include Content-Length: support. This can be accomplished in your +site.config.m4 file with: + + APPENDDEF(`conf_mail_local_ENVDEF', `-DCONTENTLENGTH') + +Defining MAILGID to a 'gid' (-DMAILGID=6) will cause mailboxes to be +written group writable and with group 'gid'. This can be accomplished in +your site.config.m4 file with: + + APPENDDEF(`conf_mail_local_ENVDEF', `-DMAILGID=6') + +mail.local will not be installed setuid root. To use it as local +delivery agent without LMTP mode, use: + + MODIFY_MAILER_FLAGS(`LOCAL', `+S') + +in the .mc file. + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:42 $ diff --git a/gnu/usr.sbin/sendmail/mail.local/mail.local.0 b/gnu/usr.sbin/sendmail/mail.local/mail.local.0 new file mode 100644 index 00000000000..541fbd0dffa --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/mail.local.0 @@ -0,0 +1,132 @@ + + + +MAIL.LOCAL(8) MAIL.LOCAL(8) + + +NNAAMMEE + mmaaiill..llooccaall - store mail in a mailbox + +SSYYNNOOPPSSIISS + mmaaiill..llooccaall [--77] [--dd] [--ll] [--ff _f_r_o_m] _u_s_e_r _._._. + +DDEESSCCRRIIPPTTIIOONN + MMaaiill..llooccaall reads the standard input up to an end-of-file + and appends it to each _u_s_e_r_'_s mmaaiill file. The _u_s_e_r must be + a valid user name. + + The options are as follows: + + --77 Do not advertise 8BITMIME support in LMTP mode. + + --bb Return a permanent error instead of a temporary + error if a mailbox exceeds quota. + + --dd Specify this is a delivery (for backward compat- + ibility). + + --ff _f_r_o_m Specify the sender's name. + + --ll Turn on LMTP mode. + + --rr _f_r_o_m Specify the sender's name (for backward compati- + bility). + + 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 deliv- + ered mail message. A blank line is appended to each mes- + sage. A greater-than character (``>'') is prepended to + any line in the message which could be mistaken for a + ``From '' delimiter line (that is, a line beginning with + the five characters ``From '' following a blank line). + + The mail files are exclusively locked with flock(2) while + mail is appended, and a uusseerr..lloocckk file also is created + while the mailbox is locked for compatibility with older + MUAs. + + If the ``biff'' service is returned by getservbyname(3), + the biff server is notified of delivered mail. + + The mmaaiill..llooccaall utility exits 0 on success, and >0 if an + error occurs. + +EENNVVIIRROONNMMEENNTT + TZ Used to set the appropriate time zone on the times- + tamp. + + + + + + $Date: 2000/04/02 19:05:42 $ 1 + + + + + +MAIL.LOCAL(8) MAIL.LOCAL(8) + + +FFIILLEESS + /tmp/local.XXXXXX temporary files + /var/mail/user user's mailbox directory + /var/mail/user.lock lock file for a user's mailbox + +SSEEEE AALLSSOO + mail(1), xsend(1), flock(2), getservbyname(3), comsat(8), + sendmail(8) + +HHIISSTTOORRYY + A superset of mmaaiill..llooccaall (handling mailbox reading as well + as mail delivery) appeared in Version 7 AT&T UNIX as the + program mmaaiill. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:42 $ 2 + + diff --git a/gnu/usr.sbin/sendmail/mail.local/mail.local.8 b/gnu/usr.sbin/sendmail/mail.local/mail.local.8 new file mode 100644 index 00000000000..5e7b7f02a45 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/mail.local.8 @@ -0,0 +1,106 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: mail.local.8,v 8.14 1999/08/26 15:49:20 ca Exp $ +.\" +.TH MAIL.LOCAL 8 "$Date: 2000/04/02 19:05:42 $" +.SH NAME +.B mail.local +\- store mail in a mailbox +.SH SYNOPSIS +.B mail.local +.RB [ \-7 "] [" \-d "] [" \-l "] [" \-f +.IR from "] " "user ..." +.SH DESCRIPTION +.B Mail.local +reads the standard input up to an end-of-file and appends it to each +.I user's +.B mail +file. The +.I user +must be a valid user name. +.PP +The options are as follows: +.TP 1i +.B \-7 +Do not advertise 8BITMIME support in LMTP mode. +.TP +.B \-b +Return a permanent error instead of a temporary error +if a mailbox exceeds quota. +.TP +.B \-d +Specify this is a delivery (for backward compatibility). +.TP +.BI \-f " from" +Specify the sender's name. +.TP +.B \-l +Turn on LMTP mode. +.TP +.BI \-r " from" +Specify the sender's name (for backward compatibility). +.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 +(that is, +a line beginning with the five characters +``From '' following a blank line). +.PP +The mail files are exclusively locked with +flock(2) +while mail is appended, +and a +.B user.lock +file also is created while the mailbox is locked +for compatibility with older MUAs. +.PP +If the ``biff'' service is returned by +getservbyname(3), +the biff server is notified of delivered mail. +.PP +The +.B mail.local +utility exits 0 on success, and >0 if an error occurs. +.SH ENVIRONMENT +.IP TZ +Used to set the appropriate time zone on the timestamp. +.SH FILES +.PD 0.2v +.TP 2.2i +/tmp/local.XXXXXX +temporary files +.TP +/var/mail/user +user's mailbox directory +.TP +/var/mail/user.lock +lock file for a user's mailbox +.PD +.SH SEE ALSO +mail(1), +xsend(1), +flock(2), +getservbyname(3), +comsat(8), +sendmail(8) +.SH HISTORY +A superset of +.B mail.local +(handling mailbox reading as well as mail delivery) +appeared in +Version 7 AT&T UNIX +as the program +.BR mail . diff --git a/gnu/usr.sbin/sendmail/mail.local/mail.local.c b/gnu/usr.sbin/sendmail/mail.local/mail.local.c new file mode 100644 index 00000000000..10e9e94adff --- /dev/null +++ b/gnu/usr.sbin/sendmail/mail.local/mail.local.c @@ -0,0 +1,1667 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1990, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: mail.local.c,v 8.142 2000/02/26 01:32:19 gshapiro Exp $"; +#endif /* ! lint */ + +/* +** This is not intended to work 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 +** work on such architectures. +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include +#include + +#ifndef __P +# include "sendmail/cdefs.h" +#endif /* ! __P */ +#include "sendmail/useful.h" + +extern size_t strlcpy __P((char *, const char *, size_t)); +extern size_t strlcat __P((char *, const char *, size_t)); + +#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# ifndef HASSTRERROR +# define HASSTRERROR 1 +# endif /* ! HASSTRERROR */ +#endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || + defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ + +#include "sendmail/errstring.h" + + +#ifndef LOCKTO_RM +# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +#endif /* LOCKTO_RM */ +#ifndef LOCKTO_GLOB +# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ +#endif /* LOCKTO_GLOB */ + +#ifdef __STDC__ +# include +# define REALLOC(ptr, size) realloc(ptr, size) +#else /* __STDC__ */ +# include +/* define a realloc() which works for NULL pointers */ +# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) +#endif /* __STDC__ */ + +#if (defined(sun) && defined(__svr4__)) || defined(__SVR4) +# define USE_LOCKF 1 +# define USE_SETEUID 1 +# define _PATH_MAILDIR "/var/mail" +#endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */ + +#ifdef NCR_MP_RAS3 +# define USE_LOCKF 1 +# define HASSNPRINTF 1 +# define _PATH_MAILDIR "/var/mail" +#endif /* NCR_MP_RAS3 */ + +#if defined(_AIX) +# define USE_LOCKF 1 +# define USE_SETEUID 1 +# define USE_VSYSLOG 0 +#endif /* defined(_AIX) */ + +#if defined(__hpux) +# define USE_LOCKF 1 +# define USE_SETRESUID 1 +# define USE_VSYSLOG 0 +#endif /* defined(__hpux) */ + +#if defined(_CRAY) +# if !defined(MAXPATHLEN) +# define MAXPATHLEN PATHSIZE +# endif /* !defined(MAXPATHLEN) */ +# define USE_VSYSLOG 0 +# define _PATH_MAILDIR "/usr/spool/mail" +#endif /* defined(_CRAY) */ + +#if defined(ultrix) +# define USE_VSYSLOG 0 +#endif /* defined(ultrix) */ + +#if defined(__osf__) +# define USE_VSYSLOG 0 +#endif /* defined(__osf__) */ + +#if defined(NeXT) && !defined(__APPLE__) +# include +# define _PATH_MAILDIR "/usr/spool/mail" +# define S_IRUSR S_IREAD +# define S_IWUSR S_IWRITE +#endif /* defined(NeXT) && !defined(__APPLE__) */ + +#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# include +#endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ + +/* + * If you don't have flock, you could try using lockf instead. + */ + +#ifdef USE_LOCKF +# define flock(a, b) lockf(a, b, 0) +# ifdef LOCK_EX +# undef LOCK_EX +# endif /* LOCK_EX */ +# define LOCK_EX F_LOCK +#endif /* USE_LOCKF */ + +#ifndef USE_VSYSLOG +# define USE_VSYSLOG 1 +#endif /* ! USE_VSYSLOG */ + +#ifndef LOCK_EX +# include +#endif /* ! LOCK_EX */ + +#if defined(BSD4_4) || defined(__GLIBC__) +# include +# define _PATH_LOCTMP "/tmp/local.XXXXXX" +#endif /* defined(BSD4_4) || defined(__GLIBC__) */ + +#ifdef BSD4_4 +# define HAS_ST_GEN 1 +#else /* BSD4_4 */ +# ifndef _BSD_VA_LIST_ +# define _BSD_VA_LIST_ va_list +# endif /* ! _BSD_VA_LIST_ */ +#endif /* BSD4_4 */ + +#if defined(BSD4_4) || defined(linux) +# define HASSNPRINTF 1 +#else /* defined(BSD4_4) || defined(linux) */ +# ifndef ultrix +extern FILE *fdopen __P((int, const char *)); +# endif /* ! ultrix */ +#endif /* defined(BSD4_4) || defined(linux) */ + +#if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) +# define CONTENTLENGTH 1 /* Needs the Content-Length header */ +#endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ + +#if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) +# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +#endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ + +#ifdef HPUX11 +# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +#endif /* HPUX11 */ + +#if _AIX4 >= 40300 +# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ +#endif /* _AIX4 >= 40300 */ + +#if !HASSNPRINTF +extern int snprintf __P((char *, size_t, const char *, ...)); +# ifndef _CRAY +extern int vsnprintf __P((char *, size_t, const char *, ...)); +# endif /* ! _CRAY */ +#endif /* !HASSNPRINTF */ + +/* +** 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 /* USE_SETEUID */ + +/* +** And of course on hpux you have setresuid() +*/ +#ifdef USE_SETRESUID +# define setreuid(r, e) setresuid(-1, e, -1) +#endif /* USE_SETRESUID */ + +#ifndef _PATH_LOCTMP +# define _PATH_LOCTMP "/tmp/local.XXXXXX" +#endif /* ! _PATH_LOCTMP */ +# ifndef _PATH_MAILDIR +# define _PATH_MAILDIR "/var/spool/mail" +# endif /* ! _PATH_MAILDIR */ + +#ifndef S_ISREG +# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) +#endif /* ! S_ISREG */ + +#ifndef INADDRSZ +# define INADDRSZ 4 /* size of an IPv4 address in bytes */ +#endif /* ! INADDRSZ */ + +#ifndef MAILER_DAEMON +# define MAILER_DAEMON "MAILER-DAEMON" +#endif /* ! MAILER_DAEMON */ + +#ifdef MAILLOCK +# include +#endif /* MAILLOCK */ + +#ifdef CONTENTLENGTH +char ContentHdr[40] = "Content-Length: "; +off_t HeaderLength; +off_t BodyLength; +#endif /* CONTENTLENGTH */ + +bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */ +int ExitVal = EX_OK; /* sysexits.h error value. */ +bool LMTPMode = FALSE; +bool bouncequota = FALSE; /* permanent error when over quota */ + +void deliver __P((int, char *, bool)); +int e_to_sys __P((int)); +void notifybiff __P((char *)); +int store __P((char *, int)); +void usage __P((void)); +void vwarn __P((const char *, _BSD_VA_LIST_)); +int lockmbox __P((char *)); +void unlockmbox __P((void)); +void mailerr __P((const char *, 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; + extern void dolmtp __P((bool)); + + /* 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 /* LOG_MAIL */ + openlog("mail.local", 0); +#endif /* LOG_MAIL */ + + from = NULL; + while ((ch = getopt(argc, argv, "7bdf:r:l")) != EOF) + { + switch(ch) + { + case '7': /* Do not advertise 8BITMIME */ + EightBitMime = FALSE; + break; + + case 'b': /* bounce mail when over quota. */ + bouncequota = TRUE; + break; + + case 'd': /* Backward compatible. */ + break; + + case 'f': + case 'r': /* Backward compatible. */ + if (from != NULL) + { + mailerr(NULL, "multiple -f options"); + usage(); + } + from = optarg; + break; + + case 'l': + LMTPMode = TRUE; + break; + + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + + /* initialize biff structures */ + notifybiff(NULL); + + if (LMTPMode) + dolmtp(bouncequota); + + if (*argv == '\0') + 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 == NULL && ((from = getlogin()) == NULL || + (pw = getpwnam(from)) == NULL || + pw->pw_uid != uid)) + from = (pw = getpwuid(uid)) != NULL ? 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, 0); *argv; ++argv) + deliver(fd, *argv, bouncequota); + exit(ExitVal); + /* NOTREACHED */ + return ExitVal; +} + +char * +parseaddr(s, rcpt) + char *s; + bool rcpt; +{ + char *p; + int l; + + if (*s++ != '<') + return NULL; + + p = s; + + /* at-domain-list */ + while (*p == '@') + { + p++; + while (*p != ',' && *p != ':' && *p != '\0') + p++; + if (*p == '\0') + return NULL; + + /* Skip over , or : */ + p++; + } + + s = p; + + /* local-part */ + while (*p != '\0' && *p != '@' && *p != '>') + { + if (*p == '\\') + { + if (*++p == '\0') + return NULL; + } + else if (*p == '\"') + { + p++; + while (*p != '\0' && *p != '\"') + { + if (*p == '\\') + { + if (*++p == '\0') + return NULL; + } + p++; + } + if (*p == '\0' || *(p + 1) == '\0') + return NULL; + } + /* +detail ? */ + if (*p == '+' && rcpt) + *p = '\0'; + p++; + } + + /* @domain */ + if (*p == '@') + { + if (rcpt) + *p++ = '\0'; + while (*p != '\0' && *p != '>') + p++; + } + + if (*p != '>') + return NULL; + else + *p = '\0'; + p++; + + if (*p != '\0' && *p != ' ') + return NULL; + + if (*s == '\0') + s = MAILER_DAEMON; + + l = strlen(s) + 1; + p = malloc(l); + if (p == NULL) + { + printf("421 4.3.0 memory exhausted\r\n"); + exit(EX_TEMPFAIL); + } + + (void) strlcpy(p, s, l); + return p; +} + +char * +process_recipient(addr) + char *addr; +{ + if (getpwnam(addr) == NULL) + return "550 5.1.1 user unknown"; + return NULL; +} + +#define RCPT_GROW 30 + +void +dolmtp(bouncequota) + bool bouncequota; +{ + char *return_path = NULL; + char **rcpt_addr = NULL; + int rcpt_num = 0; + int rcpt_alloc = 0; + bool gotlhlo = FALSE; + char *err; + int msgfd; + char *p; + int i; + char myhostname[1024]; + char buf[4096]; + + (void) gethostname(myhostname, sizeof myhostname - 1); + + printf("220 %s LMTP ready\r\n", myhostname); + for (;;) + { + (void) fflush(stdout); + if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) + exit(EX_OK); + p = buf + strlen(buf) - 1; + if (p >= buf && *p == '\n') + *p-- = '\0'; + if (p >= buf && *p == '\r') + *p-- = '\0'; + + switch (buf[0]) + { + case 'd': + case 'D': + if (strcasecmp(buf, "data") == 0) + { + if (rcpt_num == 0) + { + printf("503 5.5.1 No recipients\r\n"); + continue; + } + msgfd = store(return_path, rcpt_num); + if (msgfd == -1) + continue; + + for (i = 0; i < rcpt_num; i++) + { + p = strchr(rcpt_addr[i], '+'); + if (p != NULL) + *p++ = '\0'; + deliver(msgfd, rcpt_addr[i], bouncequota); + } + (void) close(msgfd); + goto rset; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'l': + case 'L': + if (strncasecmp(buf, "lhlo ", 5) == 0) + { + /* check for duplicate per RFC 1651 4.2 */ + if (gotlhlo) + { + printf("503 %s Duplicate LHLO\r\n", + myhostname); + continue; + } + gotlhlo = TRUE; + printf("250-%s\r\n", myhostname); + if (EightBitMime) + printf("250-8BITMIME\r\n"); + printf("250-ENHANCEDSTATUSCODES\r\n"); + printf("250 PIPELINING\r\n"); + continue; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'm': + case 'M': + if (strncasecmp(buf, "mail ", 5) == 0) + { + if (return_path != NULL) + { + printf("503 5.5.1 Nested MAIL command\r\n"); + continue; + } + if (strncasecmp(buf+5, "from:", 5) != 0 || + ((return_path = parseaddr(buf + 10, + FALSE)) == NULL)) + { + printf("501 5.5.4 Syntax error in parameters\r\n"); + continue; + } + printf("250 2.5.0 ok\r\n"); + continue; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'n': + case 'N': + if (strcasecmp(buf, "noop") == 0) + { + printf("250 2.0.0 ok\r\n"); + continue; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'q': + case 'Q': + if (strcasecmp(buf, "quit") == 0) + { + printf("221 2.0.0 bye\r\n"); + exit(EX_OK); + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'r': + case 'R': + if (strncasecmp(buf, "rcpt ", 5) == 0) + { + if (return_path == NULL) + { + printf("503 5.5.1 Need MAIL command\r\n"); + continue; + } + if (rcpt_num >= rcpt_alloc) + { + rcpt_alloc += RCPT_GROW; + rcpt_addr = (char **) + REALLOC((char *)rcpt_addr, + rcpt_alloc * + sizeof(char **)); + if (rcpt_addr == NULL) + { + printf("421 4.3.0 memory exhausted\r\n"); + exit(EX_TEMPFAIL); + } + } + if (strncasecmp(buf + 5, "to:", 3) != 0 || + ((rcpt_addr[rcpt_num] = parseaddr(buf + 8, + TRUE)) == NULL)) + { + printf("501 5.5.4 Syntax error in parameters\r\n"); + continue; + } + if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL) + { + printf("%s\r\n", err); + continue; + } + rcpt_num++; + printf("250 2.1.5 ok\r\n"); + continue; + } + else if (strcasecmp(buf, "rset") == 0) + { + printf("250 2.0.0 ok\r\n"); + +rset: + while (rcpt_num) + free(rcpt_addr[--rcpt_num]); + if (return_path != NULL) + free(return_path); + return_path = NULL; + continue; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + case 'v': + case 'V': + if (strncasecmp(buf, "vrfy ", 5) == 0) + { + printf("252 2.3.3 try RCPT to attempt delivery\r\n"); + continue; + } + goto syntaxerr; + /* NOTREACHED */ + break; + + default: + syntaxerr: + printf("500 5.5.2 Syntax error\r\n"); + continue; + /* NOTREACHED */ + break; + } + } +} + +int +store(from, lmtprcpts) + char *from; + int lmtprcpts; +{ + FILE *fp = NULL; + time_t tval; + bool eline; + bool fullline = TRUE; + char line[2048]; + int fd; + char tmpbuf[sizeof _PATH_LOCTMP + 1]; + + (void) umask(0077); + (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf); + if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) + { + if (lmtprcpts) + { + printf("451 4.3.0 unable to open temporary file\r\n"); + return -1; + } + else + { + mailerr("451 4.3.0", "unable to open temporary file"); + exit(ExitVal); + } + } + (void) unlink(tmpbuf); + + if (LMTPMode) + { + printf("354 go ahead\r\n"); + (void) fflush(stdout); + } + + (void) time(&tval); + (void) fprintf(fp, "From %s %s", from, ctime(&tval)); + +#ifdef CONTENTLENGTH + HeaderLength = 0; + BodyLength = -1; +#endif /* CONTENTLENGTH */ + + line[0] = '\0'; + for (eline = TRUE; fgets(line, sizeof(line), stdin); ) + { + size_t line_len = 0; + int peek; + while (line[line_len] != '\n' && line_len < sizeof(line) - 2) + line_len++; + line_len++; + + /* Check for dot-stuffing */ + if (fullline && lmtprcpts && line[0] == '.') + { + if (line[1] == '\n' || + (line[1] == '\r' && line[2] == '\n')) + goto lmtpdot; + memcpy(line, line + 1, line_len); + line_len--; + } + + /* Check to see if we have the full line from the fgets() */ + fullline = FALSE; + if (line_len > 0) + { + if (line[line_len - 1] == '\n') + { + if (line_len >= 2 && + line[line_len - 2] == '\r') + { + (void) strlcpy(line + line_len - 2, + "\n", sizeof line - + line_len + 2); + line_len--; + } + fullline = TRUE; + } + else if (line[line_len - 1] == '\r') + { + /* Did we just miss the CRLF? */ + peek = fgetc(stdin); + if (peek == '\n') + { + line[line_len - 1] = '\n'; + fullline = TRUE; + } + else + (void) ungetc(peek, stdin); + } + } + else + fullline = TRUE; + +#ifdef CONTENTLENGTH + if (line[0] == '\n' && HeaderLength == 0) + { + eline = FALSE; + HeaderLength = ftell(fp); + if (HeaderLength <= 0) + { + /* + ** shouldn't happen, unless ftell() is + ** badly broken + */ + + HeaderLength = -1; + } + } +#else /* CONTENTLENGTH */ + if (line[0] == '\n') + eline = TRUE; +#endif /* CONTENTLENGTH */ + else + { + if (eline && line[0] == 'F' && + !memcmp(line, "From ", 5)) + (void)putc('>', fp); + eline = FALSE; +#ifdef CONTENTLENGTH + /* discard existing "Content-Length:" headers */ + if (HeaderLength == 0 && + (line[0] == 'C' || line[0] == 'c') && + strncasecmp(line, ContentHdr, 15) == 0) + continue; +#endif /* CONTENTLENGTH */ + + } + (void) fwrite(line, sizeof(char), line_len, fp); + if (ferror(fp)) + { + if (lmtprcpts) + { + while (lmtprcpts--) + printf("451 4.3.0 temporary file write error\r\n"); + (void) fclose(fp); + return -1; + } + else + { + mailerr("451 4.3.0", + "temporary file write error"); + (void) fclose(fp); + exit(ExitVal); + } + } + } + + if (lmtprcpts) + { + /* Got a premature EOF -- toss message and exit */ + exit(EX_OK); + } + + /* If message not newline terminated, need an extra. */ + if (strchr(line, '\n') == NULL) + (void) putc('\n', fp); + + lmtpdot: + +#ifdef CONTENTLENGTH + BodyLength = ftell(fp); + if (HeaderLength == 0 && BodyLength > 0) /* empty body */ + { + HeaderLength = BodyLength; + BodyLength = 0; + } + else + BodyLength = BodyLength - HeaderLength - 1 ; + + if (HeaderLength > 0 && BodyLength >= 0) + { + extern char *quad_to_string(); + + if (sizeof BodyLength > sizeof(long)) + snprintf(line, sizeof line, "%s\n", + quad_to_string(BodyLength)); + else + snprintf(line, sizeof line, "%ld\n", (long) BodyLength); + strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16); + } + else + BodyLength = -1; /* Something is wrong here */ +#endif /* CONTENTLENGTH */ + + /* Output a newline; note, empty messages are allowed. */ + (void) putc('\n', fp); + + if (fflush(fp) == EOF || ferror(fp) != 0) + { + if (lmtprcpts) + { + while (lmtprcpts--) + printf("451 4.3.0 temporary file write error\r\n"); + (void) fclose(fp); + return -1; + } + else + { + mailerr("451 4.3.0", "temporary file write error"); + (void) fclose(fp); + exit(ExitVal); + } + } + return fd; +} + +void +deliver(fd, name, bouncequota) + int fd; + char *name; + bool bouncequota; +{ + struct stat fsb, sb; + struct passwd *pw; + char path[MAXPATHLEN]; + int mbfd, nr = 0, nw, off; + char *p; + off_t curoff; +#ifdef CONTENTLENGTH + off_t headerbytes; + int readamount; +#endif /* CONTENTLENGTH */ + char biffmsg[100], buf[8*1024]; + extern char *quad_to_string(); + + + /* + ** Disallow delivery to unknown names -- special mailboxes can be + ** handled in the sendmail aliases file. + */ + if ((pw = getpwnam(name)) == NULL) + { + if (ExitVal != EX_TEMPFAIL) + ExitVal = EX_UNAVAILABLE; + if (LMTPMode) + { + if (ExitVal == EX_TEMPFAIL) + printf("451 4.3.0 cannot lookup name: %s\r\n", name); + else + printf("550 5.1.1 unknown name: %s\r\n", name); + } + else + { + char *errcode = NULL; + + if (ExitVal == EX_TEMPFAIL) + errcode = "451 4.3.0"; + else + errcode = "550 5.1.1"; + mailerr(errcode, "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: +#ifdef MAILLOCK + p = name; +#else /* MAILLOCK */ + p = path; +#endif /* MAILLOCK */ + if ((off = lockmbox(p)) != 0) + { + if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL) + { + ExitVal = EX_TEMPFAIL; + mailerr("451 4.3.0", + "lockmailbox %s failed; error code %d %s", + p, off, errno > 0 ? errstring(errno) : ""); + } + else + { + mailerr("551 5.3.0", + "lockmailbox %s failed; error code %d %s", + p, off, errno > 0 ? errstring(errno) : ""); + } + return; + } + + if (lstat(path, &sb) < 0) + { + int save_errno; + int mode = S_IRUSR|S_IWUSR; + gid_t gid = pw->pw_gid; + +#ifdef MAILGID + (void) umask(0007); + gid = MAILGID; + mode |= S_IRGRP|S_IWGRP; +#endif /* MAILGID */ + + mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY, mode); + + save_errno = errno; + + if (lstat(path, &sb) < 0) + { + ExitVal = EX_CANTCREAT; + mailerr("550 5.2.0", + "%s: lstat: file changed after open", path); + goto err1; + } + else + sb.st_uid = pw->pw_uid; + if (mbfd == -1) + { + if (save_errno == EEXIST) + goto tryagain; + } + else if (fchown(mbfd, pw->pw_uid, gid) < 0) + { + mailerr("451 4.3.0", "chown %u.%u: %s", + pw->pw_uid, gid, name); + goto err1; + } + } + else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) + { + mailerr("550 5.2.0", "%s: irregular file", path); + goto err0; + } + else if (sb.st_uid != pw->pw_uid) + { + ExitVal = EX_CANTCREAT; + mailerr("550 5.2.0", "%s: wrong ownership (%d)", + path, sb.st_uid); + goto err0; + } + else + mbfd = open(path, O_APPEND|O_WRONLY, 0); + + if (mbfd == -1) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + goto err0; + } + else if (fstat(mbfd, &fsb) < 0 || + fsb.st_nlink != 1 || + sb.st_nlink != 1 || + !S_ISREG(fsb.st_mode) || + sb.st_dev != fsb.st_dev || + sb.st_ino != fsb.st_ino || +#if HAS_ST_GEN && 0 /* AFS returns random values for st_gen */ + sb.st_gen != fsb.st_gen || +#endif /* HAS_ST_GEN && 0 */ + sb.st_uid != fsb.st_uid) + { + ExitVal = EX_TEMPFAIL; + mailerr("550 5.2.0", "%s: fstat: file changed after open", + path); + goto err1; + } + + + /* Wait until we can get a lock on the file. */ + if (flock(mbfd, LOCK_EX) < 0) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + goto err1; + } + + /* Get the starting offset of the new message for biff. */ + curoff = lseek(mbfd, (off_t)0, SEEK_END); + if (sizeof curoff > sizeof(long)) + (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n", + name, quad_to_string(curoff)); + else + (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n", + name, (long) curoff); + + /* Copy the message into the file. */ + if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) + { + mailerr("450 4.2.0", "temporary file: %s", + errstring(errno)); + goto err1; + } + if (setreuid(0, pw->pw_uid) < 0) + { + mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", + pw->pw_uid, errstring(errno), getuid(), geteuid()); + goto err1; + } +#ifdef DEBUG + fprintf(stderr, "new euid = %d\n", geteuid()); +#endif /* DEBUG */ +#ifdef CONTENTLENGTH + headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ; + for (;;) + { + if (headerbytes == 0) + { + snprintf(buf, sizeof buf, "%s", ContentHdr); + nr = strlen(buf); + headerbytes = -1; + readamount = 0; + } + else if (headerbytes > sizeof(buf) || headerbytes < 0) + readamount = sizeof(buf); + else + readamount = headerbytes; + if (readamount != 0) + nr = read(fd, buf, readamount); + if (nr <= 0) + break; + if (headerbytes > 0) + headerbytes -= nr ; + +#else /* CONTENTLENGTH */ + while ((nr = read(fd, buf, sizeof(buf))) > 0) + { +#endif /* CONTENTLENGTH */ + for (off = 0; off < nr; off += nw) + { + if ((nw = write(mbfd, buf + off, nr - off)) < 0) + { +#ifdef EDQUOT + if (errno == EDQUOT && bouncequota) + mailerr("552 5.2.2", "%s: %s", + path, errstring(errno)); + else +#endif /* EDQUOT */ + mailerr("450 4.2.0", "%s: %s", + path, errstring(errno)); + goto err3; + } + } + } + if (nr < 0) + { + mailerr("450 4.2.0", "temporary file: %s", + errstring(errno)); + goto err3; + } + + /* Flush to disk, don't wait for update. */ + if (fsync(mbfd) < 0) + { + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); +err3: + if (setreuid(0, 0) < 0) + { +#if 0 + /* already printed an error above for this recipient */ + (void) e_to_sys(errno); + mailerr("450 4.2.0", "setreuid(0, 0): %s", + errstring(errno)); +#endif /* 0 */ + } +#ifdef DEBUG + fprintf(stderr, "reset euid = %d\n", geteuid()); +#endif /* DEBUG */ + (void) ftruncate(mbfd, curoff); +err1: (void) close(mbfd); +err0: unlockmbox(); + return; + } + + /* Close and check -- NFS doesn't write until the close. */ + if (close(mbfd)) + { +#ifdef EDQUOT + if (errno == EDQUOT && bouncequota) + mailerr("552 5.2.2", "%s: %s", path, errstring(errno)); + else +#endif /* EDQUOT */ + mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + (void) truncate(path, curoff); + } + else + notifybiff(biffmsg); + + if (setreuid(0, 0) < 0) + { + mailerr("450 4.2.0", "setreuid(0, 0): %s", + errstring(errno)); + goto err0; + } +#ifdef DEBUG + fprintf(stderr, "reset euid = %d\n", geteuid()); +#endif /* DEBUG */ + unlockmbox(); + if (LMTPMode) + printf("250 2.1.5 %s OK\r\n", name); +} + +/* +** 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. +*/ + +bool Locked = FALSE; + +#ifdef MAILLOCK +int +lockmbox(name) + char *name; +{ + int r; + + if (Locked) + return 0; + if ((r = maillock(name, 15)) == L_SUCCESS) + { + Locked = TRUE; + return 0; + } + switch (r) + { + case L_TMPLOCK: /* Can't create tmp file */ + case L_TMPWRITE: /* Can't write pid into lockfile */ + case L_MAXTRYS: /* Failed after retrycnt attempts */ + errno = 0; + r = EX_TEMPFAIL; + break; + case L_ERROR: /* Check errno for reason */ + r = errno; + break; + default: /* other permanent errors */ + errno = 0; + r = EX_UNAVAILABLE; + break; + } + return r; +} + +void +unlockmbox() +{ + if (Locked) + mailunlock(); + Locked = FALSE; +} +#else /* MAILLOCK */ + +char LockName[MAXPATHLEN]; + +int +lockmbox(path) + char *path; +{ + int statfailed = 0; + time_t start; + + if (Locked) + return 0; + if (strlen(path) + 6 > sizeof LockName) + return EX_SOFTWARE; + (void) snprintf(LockName, sizeof LockName, "%s.lock", path); + (void) time(&start); + for (; ; sleep(5)) + { + int fd; + struct stat st; + time_t now; + + /* global timeout */ + (void) time(&now); + if (now > start + LOCKTO_GLOB) + { + errno = 0; + return EX_TEMPFAIL; + } + fd = open(LockName, O_WRONLY|O_EXCL|O_CREAT, 0); + if (fd >= 0) + { + /* defeat lock checking programs which test pid */ + (void) write(fd, "0", 2); + Locked = TRUE; + (void) close(fd); + return 0; + } + if (stat(LockName, &st) < 0) + { + if (statfailed++ > 5) + { + errno = 0; + return EX_TEMPFAIL; + } + continue; + } + statfailed = 0; + (void) time(&now); + if (now < st.st_ctime + LOCKTO_RM) + continue; + + /* try to remove stale lockfile */ + if (unlink(LockName) < 0) + return errno; + } +} + +void +unlockmbox() +{ + if (!Locked) + return; + (void) unlink(LockName); + Locked = FALSE; +} +#endif /* MAILLOCK */ + +void +notifybiff(msg) + char *msg; +{ + static bool initialized = FALSE; + static int f = -1; + struct hostent *hp; + struct servent *sp; + int len; + static struct sockaddr_in addr; + + if (!initialized) + { + initialized = TRUE; + + /* Be silent if biff service not available. */ + if ((sp = getservbyname("biff", "udp")) == NULL || + (hp = gethostbyname("localhost")) == NULL || + hp->h_length != INADDRSZ) + return; + + addr.sin_family = hp->h_addrtype; + memcpy(&addr.sin_addr, hp->h_addr, INADDRSZ); + addr.sin_port = sp->s_port; + } + + /* No message, just return */ + if (msg == NULL) + return; + + /* Couldn't initialize addr struct */ + if (addr.sin_family == AF_UNSPEC) + return; + + if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return; + len = strlen(msg) + 1; + (void) sendto(f, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); +} + +void +usage() +{ + ExitVal = EX_USAGE; + mailerr(NULL, "usage: mail.local [-l] [-f from] user ..."); + exit(ExitVal); +} + +void +#ifdef __STDC__ +mailerr(const char *hdr, const char *fmt, ...) +#else /* __STDC__ */ +mailerr(hdr, fmt, va_alist) + const char *hdr; + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else /* __STDC__ */ + va_start(ap); +#endif /* __STDC__ */ + if (LMTPMode) + { + if (hdr != NULL) + printf("%s ", hdr); + (void) vprintf(fmt, ap); + (void) printf("\r\n"); + } + else + { + (void) e_to_sys(errno); + vwarn(fmt, 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 (ExitVal != EX_USAGE) + (void) fprintf(stderr, "mail.local: "); + (void) vfprintf(stderr, fmt, ap); + (void) fprintf(stderr, "\n"); + +#if USE_VSYSLOG + /* Log the message to syslog. */ + vsyslog(LOG_ERR, fmt, ap); +#else /* USE_VSYSLOG */ + { + char fmtbuf[10240]; + + (void) vsnprintf(fmtbuf, sizeof fmtbuf, fmt, ap); + syslog(LOG_ERR, "%s", fmtbuf); + } +#endif /* USE_VSYSLOG */ +} + +/* + * e_to_sys -- + * Guess which errno's are temporary. Gag me. + */ +int +e_to_sys(num) + int num; +{ + /* Temporary failures override hard errors. */ + if (ExitVal == EX_TEMPFAIL) + return ExitVal; + + switch (num) /* Hopefully temporary errors. */ + { +#ifdef EDQUOT + case EDQUOT: /* Disc quota exceeded */ + if (bouncequota) + { + ExitVal = EX_UNAVAILABLE; + break; + } + /* FALLTHROUGH */ +#endif /* EDQUOT */ +#ifdef EAGAIN + case EAGAIN: /* Resource temporarily unavailable */ +#endif /* EAGAIN */ +#ifdef EBUSY + case EBUSY: /* Device busy */ +#endif /* EBUSY */ +#ifdef EPROCLIM + case EPROCLIM: /* Too many processes */ +#endif /* EPROCLIM */ +#ifdef EUSERS + case EUSERS: /* Too many users */ +#endif /* EUSERS */ +#ifdef ECONNABORTED + case ECONNABORTED: /* Software caused connection abort */ +#endif /* ECONNABORTED */ +#ifdef ECONNREFUSED + case ECONNREFUSED: /* Connection refused */ +#endif /* ECONNREFUSED */ +#ifdef ECONNRESET + case ECONNRESET: /* Connection reset by peer */ +#endif /* ECONNRESET */ +#ifdef EDEADLK + case EDEADLK: /* Resource deadlock avoided */ +#endif /* EDEADLK */ +#ifdef EFBIG + case EFBIG: /* File too large */ +#endif /* EFBIG */ +#ifdef EHOSTDOWN + case EHOSTDOWN: /* Host is down */ +#endif /* EHOSTDOWN */ +#ifdef EHOSTUNREACH + case EHOSTUNREACH: /* No route to host */ +#endif /* EHOSTUNREACH */ +#ifdef EMFILE + case EMFILE: /* Too many open files */ +#endif /* EMFILE */ +#ifdef ENETDOWN + case ENETDOWN: /* Network is down */ +#endif /* ENETDOWN */ +#ifdef ENETRESET + case ENETRESET: /* Network dropped connection on reset */ +#endif /* ENETRESET */ +#ifdef ENETUNREACH + case ENETUNREACH: /* Network is unreachable */ +#endif /* ENETUNREACH */ +#ifdef ENFILE + case ENFILE: /* Too many open files in system */ +#endif /* ENFILE */ +#ifdef ENOBUFS + case ENOBUFS: /* No buffer space available */ +#endif /* ENOBUFS */ +#ifdef ENOMEM + case ENOMEM: /* Cannot allocate memory */ +#endif /* ENOMEM */ +#ifdef ENOSPC + case ENOSPC: /* No space left on device */ +#endif /* ENOSPC */ +#ifdef EROFS + case EROFS: /* Read-only file system */ +#endif /* EROFS */ +#ifdef ESTALE + case ESTALE: /* Stale NFS file handle */ +#endif /* ESTALE */ +#ifdef ETIMEDOUT + case ETIMEDOUT: /* Connection timed out */ +#endif /* ETIMEDOUT */ +#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK + case EWOULDBLOCK: /* Operation would block. */ +#endif /* defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK */ + ExitVal = EX_TEMPFAIL; + break; + + default: + ExitVal = EX_UNAVAILABLE; + break; + } + return ExitVal; +} + +#if defined(ultrix) || defined(_CRAY) +/* + * 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 /* defined(LIBC_SCCS) && !defined(lint) */ + +# include +# include +# include +# include +# include +# include + +static int _gettemp(); + +mkstemp(path) + char *path; +{ + int fd; + + return (_gettemp(path, &fd) ? fd : -1); +} + +# if 0 +char * +mktemp(path) + char *path; +{ + return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); +} +# endif /* 0 */ + +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) < 0) + 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) < 0) + 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 (isascii(*trv) && isdigit(*trv)) + *trv = 'a'; + else + ++*trv; + break; + } + } + } + /* NOTREACHED */ +} +#endif /* defined(ultrix) || defined(_CRAY) */ diff --git a/gnu/usr.sbin/sendmail/mailstats/Build b/gnu/usr.sbin/sendmail/mailstats/Build new file mode 100644 index 00000000000..59beb2a4e17 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:33:27 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/mailstats/Makefile b/gnu/usr.sbin/sendmail/mailstats/Makefile new file mode 100644 index 00000000000..e1b3b3caadb --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.5 1999/09/23 22:36:36 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/mailstats/Makefile.m4 b/gnu/usr.sbin/sendmail/mailstats/Makefile.m4 new file mode 100644 index 00000000000..5a9259d1318 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/Makefile.m4 @@ -0,0 +1,20 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`executable', `mailstats') +define(`bldINSTALL_DIR', `S') +define(`bldSOURCES', `mailstats.c ') +bldPUSH_SMLIB(`smutil') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `mailstats') +define(`bldSOURCES', `mailstats.8') +bldPRODUCT_END + +bldFINISH + diff --git a/gnu/usr.sbin/sendmail/mailstats/mailstats.0 b/gnu/usr.sbin/sendmail/mailstats/mailstats.0 new file mode 100644 index 00000000000..e2dc8d3f111 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/mailstats.0 @@ -0,0 +1,66 @@ + + + +MAILSTATS(1) MAILSTATS(1) + + +NNAAMMEE + mmaaiillssttaattss - display mail statistics + +SSYYNNOOPPSSIISS + mmaaiillssttaattss [--oo] [--pp] [--CC _c_f_f_i_l_e] [--ff _s_t_f_i_l_e] + +DDEESSCCRRIIPPTTIIOONN + The mmaaiillssttaattss utility displays the current mail statis- + tics. + + First, the time at which statistics started being kept is + displayed, in the format specified by ctime(3). Then, the + statistics for each mailer are displayed on a single line, + each with the following whitespace separated fields: + + MM The mailer number. + mmssggssffrr Number of messages from the mailer. + bbyytteess__ffrroomm Kbytes from the mailer. + mmssggssttoo Number of messages to the mailer. + bbyytteess__ttoo Kbytes to the mailer. + mmssggssrreejj Number of messages rejected. + mmssggssddiiss Number of messages discarded. + MMaaiilleerr The name of the mailer. + + After this display, a line totaling the values for all of + the mailers is displayed (preceeded with a ``T''), sepa- + rated from the previous information by a line containing + only equals (``='') characters. Another line preceeded + with a ``C'' lists the number of connections. + + The options are as follows: + + --CC Read the specified file instead of the default + sseennddmmaaiill ``cf'' file. + + --ff Read the specified statistics file instead of the + statistics file specified in the sseennddmmaaiill ``cf'' + file. + + --pp Output information in program-readable mode and + clear statistics. + + --oo Don't display the name of the mailer in the output. + + The mmaaiillssttaattss utility exits 0 on success, and >0 if an + error occurs. + +FFIILLEESS + /etc/mail/sendmail.cf The default sseennddmmaaiill ``cf'' file. + /etc/mail/statistics The default sseennddmmaaiill statistics + file. + +SSEEEE AALLSSOO + mailq(1), sendmail(8) + + + + April 25, 1996 1 + + diff --git a/gnu/usr.sbin/sendmail/mailstats/mailstats.8 b/gnu/usr.sbin/sendmail/mailstats/mailstats.8 new file mode 100644 index 00000000000..052d2206b2e --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/mailstats.8 @@ -0,0 +1,107 @@ +.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: mailstats.8,v 8.16 2000/02/01 05:49:53 gshapiro Exp $ +.\" +.TH MAILSTATS 1 "April 25, 1996" +.SH NAME +.B mailstats +\- display mail statistics +.SH SYNOPSIS +.B mailstats +.RB [ \-o "] [" \-p ] +.RB [ \-C +.IR cffile ] +.RB [ \-f +.IR stfile ] +.SH DESCRIPTION +The +.B mailstats +utility displays the current mail statistics. +.PP +First, the time at which statistics started being kept is displayed, +in the format specified by +ctime(3). +Then, +the statistics for each mailer are displayed on a single line, +each with the following whitespace separated fields: +.sp +.RS +.PD 0.2v +.TP 1.2i +.B M +The mailer number. +.TP +.B msgsfr +Number of messages from the mailer. +.TP +.B bytes_from +Kbytes from the mailer. +.TP +.B msgsto +Number of messages to the mailer. +.TP +.B bytes_to +Kbytes to the mailer. +.TP +.B msgsrej +Number of messages rejected. +.TP +.B msgsdis +Number of messages discarded. +.TP +.B Mailer +The name of the mailer. +.PD +.RE +.PP +After this display, a line totaling the values for all of the mailers +is displayed (preceeded with a ``T''), +separated from the previous information by a line containing only equals +(``='') +characters. +Another line preceeded with a ``C'' lists the number of connections. +.PP +The options are as follows: +.TP +.B \-C +Read the specified file instead of the default +.B sendmail +``cf'' file. +.TP +.B \-f +Read the specified statistics file instead of the statistics file +specified in the +.B sendmail +``cf'' file. +.TP +.B \-p +Output information in program-readable mode and clear statistics. +.TP +.B \-o +Don't display the name of the mailer in the output. +.PP +The +.B mailstats +utility exits 0 on success, and >0 if an error occurs. +.SH FILES +.PD 0.2v +.TP 2.5i +/etc/mail/sendmail.cf +The default +.B sendmail +``cf'' file. +.TP +/etc/mail/statistics +The default +.B sendmail +statistics file. +.PD +.SH SEE ALSO +mailq(1), +sendmail(8) diff --git a/gnu/usr.sbin/sendmail/mailstats/mailstats.c b/gnu/usr.sbin/sendmail/mailstats/mailstats.c new file mode 100644 index 00000000000..74746da99e5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/mailstats/mailstats.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: mailstats.c,v 8.53 1999/10/13 05:43:54 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include + +#include +#include +#include + +#define MNAMELEN 20 /* max length of mailer name */ + +int +main(argc, argv) + int argc; + char **argv; +{ + register int i; + int mno; + int save_errno; + int ch, fd; + char *sfile; + char *cfile; + FILE *cfp; + bool mnames; + bool progmode; + long frmsgs = 0, frbytes = 0, tomsgs = 0, tobytes = 0, rejmsgs = 0; + long dismsgs = 0; + time_t now; + char mtable[MAXMAILERS][MNAMELEN + 1]; + char sfilebuf[MAXLINE]; + char buf[MAXLINE]; + struct statistics stats; + extern char *ctime(); + extern char *optarg; + extern int optind; + + cfile = _PATH_SENDMAILCF; + sfile = NULL; + mnames = TRUE; + progmode = FALSE; + while ((ch = getopt(argc, argv, "C:f:op")) != EOF) + { + switch (ch) + { + case 'C': + cfile = optarg; + break; + + case 'f': + sfile = optarg; + break; + + case 'o': + mnames = FALSE; + break; + + case 'p': + progmode = TRUE; + break; + + case '?': + default: + usage: + (void) fputs("usage: mailstats [-C cffile] [-f stfile] -o -p\n", + stderr); + exit(EX_USAGE); + } + } + argc -= optind; + argv += optind; + + if (argc != 0) + goto usage; + + if ((cfp = fopen(cfile, "r")) == NULL) + { + save_errno = errno; + fprintf(stderr, "mailstats: "); + errno = save_errno; + perror(cfile); + exit(EX_NOINPUT); + } + + mno = 0; + (void) strlcpy(mtable[mno++], "prog", MNAMELEN + 1); + (void) strlcpy(mtable[mno++], "*file*", MNAMELEN + 1); + (void) strlcpy(mtable[mno++], "*include*", MNAMELEN + 1); + + 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 && + !(isascii(b[11]) && isalnum(b[11]))) + { + /* new form -- find value */ + b = strchr(b, '='); + if (b == NULL) + continue; + while (isascii(*++b) && isspace(*b)) + continue; + } + else if (*b++ != 'S') + { + /* something else boring */ + continue; + } + + /* this is the S or StatusFile option -- save it */ + if (strlcpy(sfilebuf, b, sizeof sfilebuf) >= + sizeof sfilebuf) + { + fprintf(stderr, + "StatusFile filename too long: %.30s...\n", + b); + exit(EX_CONFIG); + } + b = strchr(sfilebuf, '#'); + if (b == NULL) + b = strchr(sfilebuf, '\n'); + if (b == NULL) + b = &sfilebuf[strlen(sfilebuf)]; + while (isascii(*--b) && 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 != ',' && !(isascii(*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 || + (i = read(fd, &stats, sizeof stats)) < 0) + { + save_errno = errno; + (void) fputs("mailstats: ", stderr); + errno = save_errno; + perror(sfile); + exit(EX_NOINPUT); + } + if (i == 0) + { + (void) sleep(1); + if ((i = read(fd, &stats, sizeof stats)) < 0) + { + save_errno = errno; + (void) fputs("mailstats: ", stderr); + errno = save_errno; + perror(sfile); + exit(EX_NOINPUT); + } + else if (i == 0) + { + memset((ARBPTR_T) &stats, '\0', sizeof stats); + (void) time(&stats.stat_itime); + } + } + if (i != 0) + { + if (stats.stat_magic != STAT_MAGIC) + { + fprintf(stderr, + "mailstats: incorrect magic number in %s\n", + sfile); + exit(EX_OSERR); + } + else if (stats.stat_version != STAT_VERSION) + { + fprintf(stderr, + "mailstats version (%d) incompatible with %s version (%d)\n", + STAT_VERSION, sfile, stats.stat_version); + exit(EX_OSERR); + } + else if (i != sizeof stats || stats.stat_size != sizeof(stats)) + { + (void) fputs("mailstats: file size changed.\n", stderr); + exit(EX_OSERR); + } + } + + if (progmode) + { + (void) time(&now); + printf("%ld %ld\n", (long) stats.stat_itime, (long) now); + } + else + { + printf("Statistics from %s", ctime(&stats.stat_itime)); + printf(" M msgsfr bytes_from msgsto bytes_to msgsrej msgsdis%s\n", + mnames ? " Mailer" : ""); + } + for (i = 0; i < MAXMAILERS; i++) + { + if (stats.stat_nf[i] || stats.stat_nt[i] || + stats.stat_nr[i] || stats.stat_nd[i]) + { + char *format; + + if (progmode) + format = "%2d %8ld %10ld %8ld %10ld %6ld %6ld"; + else + format = "%2d %8ld %10ldK %8ld %10ldK %6ld %6ld"; + printf(format, i, + stats.stat_nf[i], stats.stat_bf[i], + stats.stat_nt[i], stats.stat_bt[i], + stats.stat_nr[i], stats.stat_nd[i]); + if (mnames) + printf(" %s", mtable[i]); + printf("\n"); + frmsgs += stats.stat_nf[i]; + frbytes += stats.stat_bf[i]; + tomsgs += stats.stat_nt[i]; + tobytes += stats.stat_bt[i]; + rejmsgs += stats.stat_nr[i]; + dismsgs += stats.stat_nd[i]; + } + } + if (progmode) + { + printf(" T %8ld %10ld %8ld %10ld %6ld %6ld\n", + frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); + printf(" C %8ld %8ld %6ld\n", + stats.stat_cf, stats.stat_ct, stats.stat_cr); + (void) close(fd); + fd = open(sfile, O_RDWR | O_TRUNC); + if (fd >= 0) + (void) close(fd); + } + else + { + printf("=============================================================\n"); + printf(" T %8ld %10ldK %8ld %10ldK %6ld %6ld\n", + frmsgs, frbytes, tomsgs, tobytes, rejmsgs, dismsgs); + printf(" C %8ld %10s %8ld %10s %6ld\n", + stats.stat_cf, "", stats.stat_ct, "", stats.stat_cr); + } + exit(EX_OK); + /* NOTREACHED */ + return EX_OK; +} diff --git a/gnu/usr.sbin/sendmail/makemap/Build b/gnu/usr.sbin/sendmail/makemap/Build new file mode 100644 index 00000000000..21fdb4dda0b --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:33:50 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/makemap/Makefile b/gnu/usr.sbin/sendmail/makemap/Makefile new file mode 100644 index 00000000000..d263b14d13b --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.7 1999/09/23 22:36:37 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/makemap/Makefile.m4 b/gnu/usr.sbin/sendmail/makemap/Makefile.m4 new file mode 100644 index 00000000000..40772390636 --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/Makefile.m4 @@ -0,0 +1,20 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`executable', `makemap') +define(`bldSOURCES', `makemap.c ') +define(`bldINSTALL_DIR', `S') +bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`smdb') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `makemap') +define(`bldSOURCES', `makemap.8') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/makemap/makemap.0 b/gnu/usr.sbin/sendmail/makemap/makemap.0 new file mode 100644 index 00000000000..bc7a34bd488 --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/makemap.0 @@ -0,0 +1,132 @@ + + + +MAKEMAP(8) MAKEMAP(8) + + +NNAAMMEE + mmaakkeemmaapp - create database maps for sendmail + +SSYYNNOOPPSSIISS + mmaakkeemmaapp [--CC _f_i_l_e] [--NN] [--cc _c_a_c_h_e_s_i_z_e] [--dd] [--ee] [--ff] [--ll] + [--oo] [--rr] [--ss] [--uu] [--vv] _m_a_p_t_y_p_e _m_a_p_n_a_m + +DDEESSCCRRIIPPTTIIOONN + MMaakkeemmaapp creates the database maps used by the keyed map + lookups in sendmail(8). It reads input from the standard + input and outputs them to the indicated _m_a_p_n_a_m_e_. + + Depending on how it is compiled, mmaakkeemmaapp handles up to + three different database formats, selected using the _m_a_p_- + _t_y_p_e parameter. They may be + + dbm DBM format maps. This requires the ndbm(3) + library. + + btree B-Tree format maps. This requires the new Berkeley + DB library. + + hash Hash format maps. This also requires the Berkeley + DB library. + + In all cases, mmaakkeemmaapp 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 ``%_n'' strings to indicate parameter + substitution. Literal percents should be doubled + (``%%''). Blank lines and lines beginning with ``#'' are + ignored. + + If the _T_r_u_s_t_e_d_U_s_e_r option is set in the sendmail configu- + ration file and mmaakkeemmaapp is invoked as root, the generated + files will be owned by the specified _T_r_u_s_t_e_d_U_s_e_r_. + + FFllaaggss + --CC Use the specified sendmail configuration file for + looking up the TrustedUser option. + + --NN Include the null byte that terminates strings in + the map. This must match the -N flag in the send- + mail.cf ``K'' line. + + --cc Use the specified hash and B-Tree cache size. + + --dd 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. + + --ee Allow empty value (right hand side). + + + + + November 16, 1992 1 + + + + + +MAKEMAP(8) MAKEMAP(8) + + + --ff 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 KK line in sendmail.cf. The value is + never case folded. + + --ll List supported map types. + + --oo Append to an old file. This allows you to augment + an existing file. + + --rr Allow replacement of existing keys. Normally + mmaakkeemmaapp complains if you repeat a key, and does not + do the insert. + + --ss Ignore safety checks on maps being created. This + includes checking for hard or symbolic links in + world writable directories. + + --uu dump (unmap) the content of the database to stan- + dard output. + + --vv Verbosely print what it is doing. + +SSEEEE AALLSSOO + sendmail(8) + +HHIISSTTOORRYY + The mmaakkeemmaapp command appeared in 4.4BSD. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + November 16, 1992 2 + + diff --git a/gnu/usr.sbin/sendmail/makemap/makemap.8 b/gnu/usr.sbin/sendmail/makemap/makemap.8 new file mode 100644 index 00000000000..3749f95c00b --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/makemap.8 @@ -0,0 +1,143 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: makemap.8,v 8.21 1999/07/30 06:15:31 gshapiro Exp $ +.\" +.TH MAKEMAP 8 "November 16, 1992" +.SH NAME +.B makemap +\- create database maps for sendmail +.SH SYNOPSIS +.B makemap +.RB [ \-C +.IR file ] +.RB [ \-N ] +.RB [ \-c +.IR cachesize ] +.RB [ \-d "] [" \-e "] [" \-f "] [" \-l "] [" \-o "] [" \-r "] [" \-s "] [" \-u "] [" \-v ] +.I +maptype mapnam +.SH DESCRIPTION +.B Makemap +creates the database maps used by the keyed map lookups in +sendmail(8). +It reads input from the standard input +and outputs them to the indicated +.I mapname. +.PP +Depending on how it is compiled, +.B makemap +handles up to three different database formats, +selected using the +.I maptype +parameter. +They may be +.TP +dbm +DBM format maps. +This requires the +ndbm(3) +library. +.TP +btree +B-Tree format maps. +This requires the new Berkeley DB +library. +.TP +hash +Hash format maps. +This also requires the Berkeley DB +library. +.PP +In all cases, +.B makemap +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 indicate parameter substitution. +Literal percents should be doubled +(``%%''). +Blank lines and lines beginning with ``#'' are ignored. +.PP +If the +.I TrustedUser +option is set in the sendmail configuration file and +.B makemap +is invoked as root, the generated files will be owned by +the specified +.IR TrustedUser. +.SS Flags +.TP +.B \-C +Use the specified sendmail configuration file for +looking up the TrustedUser option. +.TP +.B \-N +Include the null byte that terminates strings +in the map. +This must match the \-N flag in the sendmail.cf +``K'' line. +.TP +.B \-c +Use the specified hash and B-Tree cache size. +.TP +.B \-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. +.TP +.B \-e +Allow empty value (right hand side). +.TP +.B \-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 +.B K +line in sendmail.cf. +The value is never case folded. +.TP +.B \-l +List supported map types. +.TP +.B \-o +Append to an old file. +This allows you to augment an existing file. +.TP +.B \-r +Allow replacement of existing keys. +Normally +.B makemap +complains if you repeat a key, +and does not do the insert. +.TP +.B \-s +Ignore safety checks on maps being created. +This includes checking for hard or symbolic +links in world writable directories. +.TP +.B \-u +dump (unmap) the content of the database to standard output. +.TP +.B \-v +Verbosely print what it is doing. +.SH SEE ALSO +sendmail(8) +.SH HISTORY +The +.B makemap +command appeared in +4.4BSD. diff --git a/gnu/usr.sbin/sendmail/makemap/makemap.c b/gnu/usr.sbin/sendmail/makemap/makemap.c new file mode 100644 index 00000000000..dbcfdf4ba64 --- /dev/null +++ b/gnu/usr.sbin/sendmail/makemap/makemap.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1992 Eric P. Allman. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1992 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: makemap.c,v 8.132 1999/12/28 17:10:34 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#ifndef ISC_UNIX +# include +#endif /* ! ISC_UNIX */ +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include +#include +#include +#include + +uid_t RealUid; +gid_t RealGid; +char *RealUserName; +uid_t RunAsUid; +uid_t RunAsGid; +char *RunAsUserName; +int Verbose = 2; +bool DontInitGroups = FALSE; +uid_t TrustedUid = 0; +BITMAP256 DontBlameSendmail; + +#define BUFSIZE 1024 +#if _FFR_DELIM +# define ISSEP(c) ((sep == '\0' && isascii(c) && isspace(c)) || (c) == sep) +#else /* _FFR_DELIM */ +# define ISSEP(c) (isascii(c) && isspace(c)) +#endif /* _FFR_DELIM */ + +static void +usage(progname) + char *progname; +{ + fprintf(stderr, + "Usage: %s [-C cffile] [-N] [-c cachesize] [-d] [-e] [-f] [-l] [-o] [-r] [-s] %s[-u] [-v] type mapname\n", +#if _FFR_DELIM + "[-t delimiter] ", +#else /* _FFR_DELIM */ + "", +#endif /* _FFR_DELIM */ + progname); + exit(EX_USAGE); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + char *progname; + char *cfile; + bool inclnull = FALSE; + bool notrunc = FALSE; + bool allowreplace = FALSE; + bool allowempty = FALSE; + bool verbose = FALSE; + bool foldcase = TRUE; + bool unmake = FALSE; +#if _FFR_DELIM + char sep = '\0'; +#endif /* _FFR_DELIM */ + int exitstat; + int opt; + char *typename = NULL; + char *mapname = NULL; + int lineno; + int st; + int mode; + int smode; + int putflags = 0; + int sff = SFF_ROOTOK|SFF_REGONLY; + struct passwd *pw; + SMDB_DATABASE *database; + SMDB_CURSOR *cursor; + SMDB_DBENT db_key, db_val; + SMDB_DBPARAMS params; + SMDB_USER_INFO user_info; + char ibuf[BUFSIZE]; +#if HASFCHOWN + FILE *cfp; + char buf[MAXLINE]; +#endif /* HASFCHOWN */ + static char rnamebuf[MAXNAME]; /* holds RealUserName */ + extern char *optarg; + extern int optind; + + memset(¶ms, '\0', sizeof params); + params.smdbp_cache_size = 1024 * 1024; + + progname = strrchr(argv[0], '/'); + if (progname != NULL) + progname++; + else + progname = argv[0]; + cfile = _PATH_SENDMAILCF; + + clrbitmap(DontBlameSendmail); + RunAsUid = RealUid = getuid(); + RunAsGid = RealGid = getgid(); + pw = getpwuid(RealUid); + if (pw != NULL) + (void) strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); + else + snprintf(rnamebuf, sizeof rnamebuf, + "Unknown UID %d", (int) RealUid); + RunAsUserName = RealUserName = rnamebuf; + user_info.smdbu_id = RunAsUid; + user_info.smdbu_group_id = RunAsGid; + (void) strlcpy(user_info.smdbu_name, RunAsUserName, + SMDB_MAX_USER_NAME_LEN); + + +#define OPTIONS "C:Nc:t:deflorsuv" + while ((opt = getopt(argc, argv, OPTIONS)) != EOF) + { + switch (opt) + { + case 'C': + cfile = optarg; + break; + + case 'N': + inclnull = TRUE; + break; + + case 'c': + params.smdbp_cache_size = atol(optarg); + break; + + case 'd': + params.smdbp_allow_dup = TRUE; + break; + + case 'e': + allowempty = TRUE; + break; + + case 'f': + foldcase = FALSE; + break; + + case 'l': + smdb_print_available_types(); + exit(EX_OK); + break; + + case 'o': + notrunc = TRUE; + break; + + case 'r': + allowreplace = TRUE; + break; + + case 's': + setbitn(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail); + setbitn(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail); + setbitn(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail); + setbitn(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail); + break; + +#if _FFR_DELIM + case 't': + if (optarg == NULL || *optarg == '\0') + { + fprintf(stderr, "Invalid separator\n"); + break; + } + sep = *optarg; + break; +#endif /* _FFR_DELIM */ + + case 'u': + unmake = TRUE; + break; + + case 'v': + verbose = TRUE; + break; + + default: + usage(progname); + /* NOTREACHED */ + } + } + + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + + argc -= optind; + argv += optind; + if (argc != 2) + { + usage(progname); + /* NOTREACHED */ + } + else + { + typename = argv[0]; + mapname = argv[1]; + } + +#if HASFCHOWN + /* Find TrustedUser value in sendmail.cf */ + if ((cfp = fopen(cfile, "r")) == NULL) + { + fprintf(stderr, "makemap: %s: %s", cfile, errstring(errno)); + exit(EX_NOINPUT); + } + while (fgets(buf, sizeof(buf), cfp) != NULL) + { + register char *b; + + if ((b = strchr(buf, '\n')) != NULL) + *b = '\0'; + + b = buf; + switch (*b++) + { + case 'O': /* option */ + if (strncasecmp(b, " TrustedUser", 12) == 0 && + !(isascii(b[12]) && isalnum(b[12]))) + { + b = strchr(b, '='); + if (b == NULL) + continue; + while (isascii(*++b) && isspace(*b)) + continue; + if (isascii(*b) && isdigit(*b)) + TrustedUid = atoi(b); + else + { + TrustedUid = 0; + pw = getpwnam(b); + if (pw == NULL) + fprintf(stderr, + "TrustedUser: unknown user %s\n", b); + else + TrustedUid = pw->pw_uid; + } + +# ifdef UID_MAX + if (TrustedUid > UID_MAX) + { + fprintf(stderr, + "TrustedUser: uid value (%ld) > UID_MAX (%ld)", + (long) TrustedUid, + (long) UID_MAX); + TrustedUid = 0; + } +# endif /* UID_MAX */ + break; + } + + + default: + continue; + } + } + (void) fclose(cfp); +#endif /* HASFCHOWN */ + + if (!params.smdbp_allow_dup && !allowreplace) + putflags = SMDBF_NO_OVERWRITE; + + if (unmake) + { + mode = O_RDONLY; + smode = S_IRUSR; + } + else + { + mode = O_RDWR; + if (!notrunc) + { + mode |= O_CREAT|O_TRUNC; + sff |= SFF_CREAT; + } + smode = S_IWUSR; + } + + params.smdbp_num_elements = 4096; + + errno = smdb_open_database(&database, mapname, mode, smode, sff, + typename, &user_info, ¶ms); + if (errno != SMDBE_OK) + { + char *hint; + + if (errno == SMDBE_UNSUPPORTED_DB_TYPE && + (hint = smdb_db_definition(typename)) != NULL) + fprintf(stderr, + "%s: Need to recompile with -D%s for %s support\n", + progname, hint, typename); + else + fprintf(stderr, + "%s: error opening type %s map %s: %s\n", + progname, typename, mapname, errstring(errno)); + exit(EX_CANTCREAT); + } + + (void) database->smdb_sync(database, 0); + + if (geteuid() == 0 && TrustedUid != 0) + { + errno = database->smdb_set_owner(database, TrustedUid, -1); + if (errno != SMDBE_OK) + { + fprintf(stderr, + "WARNING: ownership change on %s failed %s", + mapname, errstring(errno)); + } + } + + /* + ** Copy the data + */ + + exitstat = EX_OK; + if (unmake) + { + bool stop; + errno = database->smdb_cursor(database, &cursor, 0); + if (errno != SMDBE_OK) + { + + fprintf(stderr, + "%s: cannot make cursor for type %s map %s\n", + progname, typename, mapname); + exit(EX_SOFTWARE); + } + + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + + for (stop = FALSE, lineno = 0; !stop; lineno++) + { + errno = cursor->smdbc_get(cursor, &db_key, &db_val, + SMDB_CURSOR_GET_NEXT); + if (errno != SMDBE_OK) + { + stop = TRUE; + } + if (!stop) + printf("%.*s\t%.*s\n", + (int) db_key.data.size, + (char *) db_key.data.data, + (int) db_val.data.size, + (char *)db_val.data.data); + + } + (void) cursor->smdbc_close(cursor); + } + else + { + lineno = 0; + 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 (%ld bytes max)\n", + progname, mapname, lineno, (long) sizeof ibuf); + exitstat = EX_DATAERR; + continue; + } + + if (ibuf[0] == '\0' || ibuf[0] == '#') + continue; + if ( +#if _FFR_DELIM + sep == '\0' && +#endif /* _FFR_DELIM */ + isascii(ibuf[0]) && isspace(ibuf[0])) + { + fprintf(stderr, + "%s: %s: line %d: syntax error (leading space)\n", + progname, mapname, lineno); + exitstat = EX_DATAERR; + continue; + } + + memset(&db_key, '\0', sizeof db_key); + memset(&db_val, '\0', sizeof db_val); + db_key.data.data = ibuf; + + for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++) + { + if (foldcase && isascii(*p) && isupper(*p)) + *p = tolower(*p); + } + db_key.data.size = p - ibuf; + if (inclnull) + db_key.data.size++; + + if (*p != '\0') + *p++ = '\0'; + while (ISSEP(*p)) + p++; + if (!allowempty && *p == '\0') + { + fprintf(stderr, + "%s: %s: line %d: no RHS for LHS %s\n", + progname, mapname, lineno, + (char *) db_key.data.data); + exitstat = EX_DATAERR; + continue; + } + + db_val.data.data = p; + db_val.data.size = strlen(p); + if (inclnull) + db_val.data.size++; + + /* + ** Do the database insert. + */ + + if (verbose) + { + printf("key=`%s', val=`%s'\n", + (char *) db_key.data.data, + (char *) db_val.data.data); + } + + errno = database->smdb_put(database, &db_key, &db_val, + putflags); + switch (errno) + { + case SMDBE_KEY_EXIST: + st = 1; + break; + + case 0: + st = 0; + break; + + default: + st = -1; + break; + } + + if (st < 0) + { + fprintf(stderr, + "%s: %s: line %d: key %s: put error: %s\n", + progname, mapname, lineno, + (char *) db_key.data.data, + errstring(errno)); + exitstat = EX_IOERR; + } + else if (st > 0) + { + fprintf(stderr, + "%s: %s: line %d: key %s: duplicate key\n", + progname, mapname, + lineno, (char *) db_key.data.data); + exitstat = EX_DATAERR; + } + } + } + + /* + ** Now close the database. + */ + + errno = database->smdb_close(database); + if (errno != SMDBE_OK) + { + fprintf(stderr, "%s: close(%s): %s\n", + progname, mapname, errstring(errno)); + exitstat = EX_IOERR; + } + smdb_free_database(database); + + exit(exitstat); + /* NOTREACHED */ + return exitstat; +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +message(const char *msg, ...) +#else /* __STDC__ */ +message(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +syserr(const char *msg, ...) +#else /* __STDC__ */ +syserr(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} diff --git a/gnu/usr.sbin/sendmail/praliases/Build b/gnu/usr.sbin/sendmail/praliases/Build new file mode 100644 index 00000000000..50e2b2350ed --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:34:32 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/praliases/Makefile b/gnu/usr.sbin/sendmail/praliases/Makefile new file mode 100644 index 00000000000..eaad99857c3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.5 1999/09/23 22:36:39 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/praliases/Makefile.m4 b/gnu/usr.sbin/sendmail/praliases/Makefile.m4 new file mode 100644 index 00000000000..670c2ccf974 --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/Makefile.m4 @@ -0,0 +1,21 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`executable', `praliases') +define(`bldINSTALL_DIR', `S') +define(`bldSOURCES', `praliases.c ') +bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`smdb') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `praliases') +define(`bldSOURCES', `praliases.8') +bldPRODUCT_END + +bldFINISH + diff --git a/gnu/usr.sbin/sendmail/praliases/praliases.0 b/gnu/usr.sbin/sendmail/praliases/praliases.0 new file mode 100644 index 00000000000..9c15dc980be --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/praliases.0 @@ -0,0 +1,66 @@ + + + +PRALIASES(1) PRALIASES(1) + + +NNAAMMEE + pprraalliiaasseess - display system mail aliases + +SSYYNNOOPPSSIISS + pprraalliiaasseess [--CC _f_i_l_e] [--ff _f_i_l_e] + +DDEESSCCRRIIPPTTIIOONN + The pprraalliiaasseess utility displays the current system aliases, + one per line, in no particular order. The special inter- + nal @:@ alias will be displayed if present. + + The options are as follows: + + --CC Read the specified sendmail configuration file + instead of the default sseennddmmaaiill configuration file. + + --ff Read the specified file instead of the configured + sseennddmmaaiill system aliases file(s). + + The pprraalliiaasseess utility exits 0 on success, and >0 if an + error occurs. + +FFIILLEESS + /etc/mail/sendmail.cf The default sseennddmmaaiill configura- + tion file. + +SSEEEE AALLSSOO + mailq(1), sendmail(8) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + April 25, 1996 1 + + diff --git a/gnu/usr.sbin/sendmail/praliases/praliases.8 b/gnu/usr.sbin/sendmail/praliases/praliases.8 new file mode 100644 index 00000000000..561a362e040 --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/praliases.8 @@ -0,0 +1,51 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: praliases.8,v 8.12 1999/09/01 22:15:16 gshapiro Exp $ +.\" +.TH PRALIASES 1 "April 25, 1996" +.SH NAME +.B praliases +\- display system mail aliases +.SH SYNOPSIS +.B praliases +.RB [ \-C +.IR file ] +.RB [ \-f +.IR file ] +.SH DESCRIPTION +The +.B praliases +utility displays the current system aliases, +one per line, in no particular order. +The special internal @:@ alias will be displayed if present. +.PP +The options are as follows: +.TP +.B \-C +Read the specified sendmail configuration file instead of the default +.B sendmail +configuration file. +.TP +.B \-f +Read the specified file instead of the configured +.B sendmail +system aliases file(s). +.PP +The +.B praliases +utility exits 0 on success, and >0 if an error occurs. +.SH FILES +.TP 2.5i +/etc/mail/sendmail.cf +The default +.B sendmail +configuration file. +.SH SEE ALSO +mailq(1), +sendmail(8) diff --git a/gnu/usr.sbin/sendmail/praliases/praliases.c b/gnu/usr.sbin/sendmail/praliases/praliases.c new file mode 100644 index 00000000000..9137ec512d0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/praliases/praliases.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: praliases.c,v 8.57 1999/10/13 03:35:16 ca Exp $"; +#endif /* ! lint */ + +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include + +#ifndef NOT_SENDMAIL +# define NOT_SENDMAIL +#endif /* ! NOT_SENDMAIL */ +#include +#include +#include + +static void praliases __P((char *, int, char **)); + +uid_t RealUid; +gid_t RealGid; +char *RealUserName; +uid_t RunAsUid; +uid_t RunAsGid; +char *RunAsUserName; +int Verbose = 2; +bool DontInitGroups = FALSE; +uid_t TrustedUid = 0; +BITMAP256 DontBlameSendmail; + +extern void syserr __P((const char *, ...)); + +int +main(argc, argv) + int argc; + char **argv; +{ + char *cfile; + char *filename = NULL; + FILE *cfp; + int ch; + char afilebuf[MAXLINE]; + char buf[MAXLINE]; + struct passwd *pw; + static char rnamebuf[MAXNAME]; + extern char *optarg; + extern int optind; + + clrbitmap(DontBlameSendmail); + RunAsUid = RealUid = getuid(); + RunAsGid = RealGid = getgid(); + pw = getpwuid(RealUid); + if (pw != NULL) + { + if (strlen(pw->pw_name) > MAXNAME - 1) + pw->pw_name[MAXNAME] = 0; + snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); + } + else + snprintf(rnamebuf, sizeof rnamebuf, + "Unknown UID %d", (int) RealUid); + RunAsUserName = RealUserName = rnamebuf; + + cfile = _PATH_SENDMAILCF; + while ((ch = getopt(argc, argv, "C:f:")) != EOF) + { + switch ((char)ch) { + case 'C': + cfile = optarg; + break; + case 'f': + filename = optarg; + break; + case '?': + default: + (void)fprintf(stderr, + "usage: praliases [-C cffile] [-f aliasfile]\n"); + exit(EX_USAGE); + } + } + argc -= optind; + argv += optind; + + if (filename != NULL) + { + praliases(filename, argc, argv); + exit(EX_OK); + } + + if ((cfp = fopen(cfile, "r")) == NULL) + { + fprintf(stderr, "praliases: %s: %s\n", + cfile, errstring(errno)); + exit(EX_NOINPUT); + } + + while (fgets(buf, sizeof(buf), cfp) != NULL) + { + register char *b, *p; + + b = strchr(buf, '\n'); + if (b != NULL) + *b = '\0'; + + b = buf; + switch (*b++) + { + case 'O': /* option -- see if alias file */ + if (strncasecmp(b, " AliasFile", 10) == 0 && + !(isascii(b[10]) && isalnum(b[10]))) + { + /* new form -- find value */ + b = strchr(b, '='); + if (b == NULL) + continue; + while (isascii(*++b) && isspace(*b)) + continue; + } + else if (*b++ != 'A') + { + /* something else boring */ + continue; + } + + /* this is the A or AliasFile option -- save it */ + if (strlcpy(afilebuf, b, sizeof afilebuf) >= + sizeof afilebuf) + { + fprintf(stderr, + "praliases: AliasFile filename too long: %.30s\n", + b); + (void) fclose(cfp); + exit(EX_CONFIG); + } + b = afilebuf; + + for (p = b; p != NULL; ) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + b = p; + + p = strpbrk(p, " ,/"); + + /* find end of spec */ + if (p != NULL) + { + bool quoted = FALSE; + + for (; *p != '\0'; p++) + { + /* + ** Don't break into a quoted + ** string. + */ + + if (*p == '"') + quoted = !quoted; + else if (*p == ',' && !quoted) + break; + } + + /* No more alias specs follow */ + if (*p == '\0') + { + /* chop trailing whitespace */ + while (isascii(*p) && + isspace(*p) && + p > b) + p--; + *p = '\0'; + p = NULL; + } + } + + if (p != NULL) + { + char *e = p - 1; + + /* chop trailing whitespace */ + while (isascii(*e) && + isspace(*e) && + e > b) + e--; + *++e = '\0'; + *p++ = '\0'; + } + praliases(b, argc, argv); + } + + default: + continue; + } + } + (void) fclose(cfp); + exit(EX_OK); + /* NOTREACHED */ + return EX_OK; +} + +static void +praliases(filename, argc, argv) + char *filename; + int argc; + char **argv; +{ + int result; + char *colon; + char *db_name; + char *db_type; + SMDB_DATABASE *database = NULL; + SMDB_CURSOR *cursor = NULL; + SMDB_DBENT db_key, db_value; + SMDB_DBPARAMS params; + SMDB_USER_INFO user_info; + + colon = strchr(filename, ':'); + if (colon == NULL) + { + db_name = filename; + db_type = SMDB_TYPE_DEFAULT; + } + else + { + *colon = '\0'; + db_name = colon + 1; + db_type = filename; + } + + /* clean off arguments */ + for (;;) + { + while (isascii(*db_name) && isspace(*db_name)) + db_name++; + if (*db_name != '-') + break; + while (*db_name != '\0' && + !(isascii(*db_name) && isspace(*db_name))) + db_name++; + } + + if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) + { + if (colon != NULL) + *colon = ':'; + fprintf(stderr, "praliases: illegal alias specification: %s\n", + filename); + goto fatal; + } + + memset(¶ms, '\0', sizeof params); + params.smdbp_cache_size = 1024 * 1024; + + user_info.smdbu_id = RunAsUid; + user_info.smdbu_group_id = RunAsGid; + strlcpy(user_info.smdbu_name, RunAsUserName, SMDB_MAX_USER_NAME_LEN); + + result = smdb_open_database(&database, db_name, O_RDONLY, 0, + SFF_ROOTOK, db_type, &user_info, ¶ms); + if (result != SMDBE_OK) + { + fprintf(stderr, "praliases: %s: open: %s\n", + db_name, errstring(result)); + goto fatal; + } + + memset(&db_key, '\0', sizeof db_key); + memset(&db_value, '\0', sizeof db_value); + + result = database->smdb_cursor(database, &cursor, 0); + if (result != SMDBE_OK) + { + fprintf(stderr, "praliases: %s: set cursor: %s\n", + db_name, errstring(result)); + goto fatal; + } + + while ((result = cursor->smdbc_get(cursor, &db_key, &db_value, + SMDB_CURSOR_GET_NEXT)) == SMDBE_OK) + { +#if 0 + /* skip magic @:@ entry */ + if (db_key.data.size == 2 && + db_key.data.data[0] == '@' && + db_key.data.data[1] == '\0' && + db_value.data.size == 2 && + db_value.data.data[0] == '@' && + db_value.data.data[1] == '\0') + continue; +#endif /* 0 */ + + printf("%.*s:%.*s\n", + (int) db_key.data.size, + (char *) db_key.data.data, + (int) db_value.data.size, + (char *) db_value.data.data); + } + + if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) + { + fprintf(stderr, "praliases: %s: get value at cursor: %s\n", + db_name, errstring(result)); + goto fatal; + } + + fatal: + if (cursor != NULL) + (void) cursor->smdbc_close(cursor); + if (database != NULL) + (void) database->smdb_close(database); + if (colon != NULL) + *colon = ':'; + return; +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +message(const char *msg, ...) +#else /* __STDC__ */ +message(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +syserr(const char *msg, ...) +#else /* __STDC__ */ +syserr(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} diff --git a/gnu/usr.sbin/sendmail/rmail/Build b/gnu/usr.sbin/sendmail/rmail/Build new file mode 100644 index 00000000000..48c023ae0c9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:34:45 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/rmail/Makefile b/gnu/usr.sbin/sendmail/rmail/Makefile new file mode 100644 index 00000000000..d376b4fdaec --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/Makefile @@ -0,0 +1,19 @@ +# $Sendmail: Makefile,v 8.5 1999/10/05 16:39:19 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +force-install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/rmail/Makefile.m4 b/gnu/usr.sbin/sendmail/rmail/Makefile.m4 new file mode 100644 index 00000000000..0c42c6b74ac --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/Makefile.m4 @@ -0,0 +1,32 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +PREPENDDEF(`confENVDEF', `confMAPDEF') + +bldPRODUCT_START(`executable', `rmail') +define(`bldNO_INSTALL') +define(`bldSOURCES', `rmail.c ') +bldPUSH_SMLIB(`smutil') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `rmail') +define(`bldSOURCES', `rmail.8') +bldPRODUCT_END + +RMAIL=ifdef(`confFORCE_RMAIL', `force-install', `defeat-install') + +divert(bldTARGETS_SECTION) +install: ${RMAIL} + +defeat-install: + @echo "NOTE: This version of rmail is not suited for some operating" + @echo " systems. You can force the install using" + @echo " 'Build force-install'." + +force-install: install-rmail ifdef(`confNO_MAN_BUILD',, `install-docs') + +install-rmail: rmail + ${INSTALL} -c -o ${UBINOWN} -g ${UBINGRP} -m ${UBINMODE} rmail ${DESTDIR}${UBINDIR} +divert + +bldFINISH + diff --git a/gnu/usr.sbin/sendmail/rmail/rmail.0 b/gnu/usr.sbin/sendmail/rmail/rmail.0 new file mode 100644 index 00000000000..757e1aa696d --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/rmail.0 @@ -0,0 +1,66 @@ + + + +RMAIL(8) RMAIL(8) + + +NNAAMMEE + rrmmaaiill - handle remote mail received via uucp + +SSYYNNOOPPSSIISS + rrmmaaiill _u_s_e_r _._._. + +DDEESSCCRRIIPPTTIIOONN + RRmmaaiill interprets incoming mail received via uucp(1), col- + lapsing ``From'' lines in the form generated by + mail.local(8) into a single line of the form ``return- + path!sender'', and passing the processed mail on to send- + mail(8). + + RRmmaaiill is explicitly designed for use with uucp and send- + mail. + +SSEEEE AALLSSOO + uucp(1), mail.local(8), sendmail(8) + +HHIISSTTOORRYY + The rrmmaaiill program appeared in 4.2BSD. + +BBUUGGSS + RRmmaaiill should not reside in /bin. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:57 $ 1 + + diff --git a/gnu/usr.sbin/sendmail/rmail/rmail.8 b/gnu/usr.sbin/sendmail/rmail/rmail.8 new file mode 100644 index 00000000000..85e5577e41b --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/rmail.8 @@ -0,0 +1,49 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1990 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: rmail.8,v 8.1 1999/06/22 20:41:33 tony Exp $ +.\" +.TH RMAIL 8 "$Date: 2000/04/02 19:05:57 $" +.SH NAME +.B rmail +\- handle remote mail received via uucp +.SH SYNOPSIS +.B rmail +.I +user ... +.SH DESCRIPTION +.B Rmail +interprets incoming mail received via +uucp(1), +collapsing ``From'' lines in the form generated +by +mail.local(8) +into a single line of the form ``return-path!sender'', +and passing the processed mail on to +sendmail(8). +.PP +.B Rmail +is explicitly designed for use with +uucp +and +sendmail. +.SH SEE ALSO +uucp(1), +mail.local(8), +sendmail(8) +.SH HISTORY +The +.B rmail +program appeared in +4.2BSD. +.SH BUGS +.B Rmail +should not reside in +/bin. diff --git a/gnu/usr.sbin/sendmail/rmail/rmail.c b/gnu/usr.sbin/sendmail/rmail/rmail.c new file mode 100644 index 00000000000..7cdcc123c9b --- /dev/null +++ b/gnu/usr.sbin/sendmail/rmail/rmail.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: rmail.c,v 8.38 2000/02/26 01:32:22 gshapiro Exp $"; +#endif /* ! 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: + * + * := [-a-z0-9]+ + * := ctime format + * := [-a-z0-9!]+ + * := "^\n$" + * := "From" + * [ "remote from" ] + * := ">" + * msg := * + * + * The output of rmail(8) compresses the lines into a single + * from path. + * + * The err(3) routine is included here deliberately to make this code + * a bit more portable. + */ + +#include +#include +#include +#include + +#include +#include +#ifdef BSD4_4 +# define FORK vfork +# include +#else /* BSD4_4 */ +# define FORK fork +# ifndef _PATH_SENDMAIL +# define _PATH_SENDMAIL "/usr/lib/sendmail" +# endif /* ! _PATH_SENDMAIL */ +#endif /* BSD4_4 */ +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include + +#ifndef MAX +# define MAX(a, b) ((a) < (b) ? (b) : (a)) +#endif /* ! MAX */ + +#ifndef __P +# ifdef __STDC__ +# define __P(protos) protos +# else /* __STDC__ */ +# define __P(protos) () +# define const +# endif /* __STDC__ */ +#endif /* ! __P */ + +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif /* ! STDIN_FILENO */ + +#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) +# define HASSNPRINTF 1 +#endif /* defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ + +#if defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) +# define memmove(d, s, l) (bcopy((s), (d), (l))) +#endif /* defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) */ + +#if !HASSNPRINTF +extern int snprintf __P((char *, size_t, const char *, ...)); +#endif /* !HASSNPRINTF */ + +#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# ifndef HASSTRERROR +# define HASSTRERROR 1 +# endif /* ! HASSTRERROR */ +#endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || + defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ + +#if defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__) +# undef WIFEXITED +# undef WEXITSTATUS +# define WIFEXITED(st) (((st) & 0377) == 0) +# define WEXITSTATUS(st) (((st) >> 8) & 0377) +#endif /* defined(SUNOS403) || defined(NeXT) || (defined(MACH) && defined(i386) && !defined(__GNU__)) || defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) || defined(ALTOS_SYSTEM_V) || defined(RISCOS) || defined(_AUX_SOURCE) || defined(UMAXV) || defined(titan) || defined(UNIXWARE) || defined(sony_news) || defined(luna) || defined(nec_ews_svr4) || defined(_nec_ews_svr4) || defined(__MAXION__) */ + + +#include "sendmail/errstring.h" + +static void err __P((int, const char *, ...)); +static void usage __P((void)); +static char *xalloc __P((int)); + +#define newstr(s) strcpy(xalloc(strlen(s) + 1), s) + +static 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_TEMPFAIL, "out of memory"); + return (p); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, debug, i, pdes[2], pid, status; + size_t fplen = 0, fptlen = 0, len; + off_t offset; + FILE *fp; + char *addrp = NULL, *domain, *p, *t; + char *from_path, *from_sys, *from_user; + char *args[100], buf[2048], lbuf[2048]; + struct stat sb; + extern char *optarg; + extern int optind; + + 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 != '\0'; ++t) + { + if (isascii(*t) && isspace(*t)) + break; + } + *t = '\0'; + if (debug) + 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) + 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 != '\0'; ++t) + { + if (isascii(*t) && isspace(*t)) + break; + } + *t = '\0'; + + /* If the first system, copy to the from_sys string. */ + if (from_sys == NULL) + { + from_sys = newstr(p); + if (debug) + 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 != '\0'; ++p) + { + if (isascii(*p) && isspace(*p)) + break; + } + *p = '\0'; + if (*addrp == '\0') + addrp = "<>"; + if (from_user != NULL) + free(from_user); + from_user = newstr(addrp); + + if (debug) + { + if (from_path != NULL) + fprintf(stderr, "from_path: %s\n", from_path); + 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) + snprintf(buf, sizeof(buf), "-p%s", domain); + else if (strchr(from_sys, '.') == NULL) + snprintf(buf, sizeof(buf), "-p%s:%s.%s", + domain, from_sys, domain); + else + snprintf(buf, sizeof(buf), "-p%s:%s", domain, from_sys); + args[i++] = newstr(buf); + + /* Set name of ``from'' person. */ + snprintf(buf, sizeof(buf), "-f%s%s", + from_path ? from_path : "", from_user); + args[i++] = newstr(buf); + + /* + ** 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 + { + len = strlen(*argv) + 3; + if ((args[i] = malloc(len)) == NULL) + err(EX_TEMPFAIL, "Cannot malloc"); + snprintf(args[i++], len, "<%s>", *argv); + } + argv++; + } + args[i] = 0; + + if (debug) + { + fprintf(stderr, "Sendmail arguments:\n"); + for (i = 0; args[i]; i++) + 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"); + (void) execv(_PATH_SENDMAIL, args); + err(EX_OSERR, "%s", _PATH_SENDMAIL); + } + + if (pipe(pdes) < 0) + err(EX_OSERR, NULL); + + switch (pid = FORK()) + { + case -1: /* Err. */ + err(EX_OSERR, NULL); + /* NOTREACHED */ + + case 0: /* Child. */ + if (pdes[0] != STDIN_FILENO) + { + (void) dup2(pdes[0], STDIN_FILENO); + (void) close(pdes[0]); + } + (void) close(pdes[1]); + (void) 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", errstring(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); + /* NOTREACHED */ + return EX_OK; +} + +static void +usage() +{ + (void) fprintf(stderr, "usage: rmail [-T] [-D domain] user ...\n"); + exit(EX_USAGE); +} + +#ifdef __STDC__ +# include +#else /* __STDC__ */ +# include +#endif /* __STDC__ */ + +static void +#ifdef __STDC__ +err(int eval, const char *fmt, ...) +#else /* __STDC__ */ +err(eval, fmt, va_alist) + int eval; + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else /* __STDC__ */ + va_start(ap); +#endif /* __STDC__ */ + (void) fprintf(stderr, "rmail: "); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + (void) fprintf(stderr, "\n"); + exit(eval); +} diff --git a/gnu/usr.sbin/sendmail/sendmail/Build b/gnu/usr.sbin/sendmail/sendmail/Build new file mode 100644 index 00000000000..eca221fae08 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:34:01 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/sendmail/Makefile b/gnu/usr.sbin/sendmail/sendmail/Makefile new file mode 100644 index 00000000000..546ce4c5544 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.11 1999/09/23 22:36:42 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/sendmail/Makefile.m4 b/gnu/usr.sbin/sendmail/sendmail/Makefile.m4 new file mode 100644 index 00000000000..c59701b42be --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/Makefile.m4 @@ -0,0 +1,53 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +bldPRODUCT_START(`executable', `sendmail') +define(`bldBIN_TYPE', `S') +define(`bldINSTALL_DIR', `') +define(`bldSOURCES', `main.c alias.c arpadate.c bf_'ifdef(`confSTDIO_TYPE', `confSTDIO_TYPE', `portable')`.c clock.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c readcf.c recipient.c savemail.c sfsasl.c shmticklib.c srvrsmtp.c stab.c stats.c sysexits.c timers.c trace.c udb.c usersmtp.c util.c version.c ') +PREPENDDEF(`confENVDEF', `confMAPDEF') +bldPUSH_SMLIB(`smutil') + +define(`bldTARGET_LINKS', ifdef(`confLINKS', `confLINKS', +`${DESTDIR}${UBINDIR}/newaliases ${DESTDIR}${UBINDIR}/mailq ${DESTDIR}${UBINDIR}/hoststat ${DESTDIR}${UBINDIR}/purgestat') +)dnl + +# location of sendmail statistics file (usually /etc/mail/ or /var/log) +STDIR= ifdef(`confSTDIR', `confSTDIR', `/etc/mail') + +# full path to installed statistics file (usually ${STDIR}/statistics) +STFILE= ${STDIR}/ifdef(`confSTFILE', `confSTFILE', `statistics') + +# location of sendmail helpfile file (usually /etc/mail) +HFDIR= ifdef(`confHFDIR', `confHFDIR', `/etc/mail') + +# full path to installed help file (usually ${HFDIR}/helpfile) +HFFILE= ${HFDIR}/ifdef(`confHFFILE', `confHFFILE', `helpfile') + +ifdef(`confSMSRCADD', `APPENDDEF(`confSRCADD', `confSMSRCADD')') +ifdef(`confSMOBJADD', `APPENDDEF(`confOBJADD', `confSMOBJADD')') + +bldPUSH_TARGET(`statistics') +divert(bldTARGETS_SECTION) +statistics: + ${CP} /dev/null statistics + +divert(0) + +ifdef(`confNO_HELPFILE_INSTALL',, `bldPUSH_INSTALL_TARGET(`install-hf')') +ifdef(`confNO_STATISTICS_INSTALL',, `bldPUSH_INSTALL_TARGET(`install-st')') +divert(bldTARGETS_SECTION) +install-hf: + if [ ! -d ${DESTDIR}${HFDIR} ]; then mkdir -p ${DESTDIR}${HFDIR}; fi + ${INSTALL} -c -o ${UBINOWN} -g ${UBINGRP} -m 444 helpfile ${DESTDIR}${HFFILE} + +install-st: statistics + if [ ! -d ${DESTDIR}${STDIR} ]; then mkdir -p ${DESTDIR}${STDIR}; fi + ${INSTALL} -c -o ${SBINOWN} -g ${UBINGRP} -m 644 statistics ${DESTDIR}${STFILE} +divert(0) +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `sendmail') +define(`bldSOURCES', `sendmail.8 aliases.5 mailq.1 newaliases.1') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/sendmail/README b/gnu/usr.sbin/sendmail/sendmail/README new file mode 100644 index 00000000000..a2ea8865b79 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/README @@ -0,0 +1,1541 @@ +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# All rights reserved. +# Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. +# Copyright (c) 1988 +# The Regents of the University of California. All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: README,v 8.257 2000/02/25 04:36:37 gshapiro Exp $ +# + +This directory contains the source files for sendmail(TM). + +********************* +!! DO NOT USE MAKE !! in this directory to compile sendmail -- +********************* instead, use the "Build" script located in +the sendmail directory. It will build an appropriate Makefile, and +create an appropriate obj.* subdirectory so that multiplatform +support works easily. + + ********************************************************** + ** Read below for more details on building sendmail. ** + ********************************************************** + +************************************************************************** +** IMPORTANT: Read the appropriate paragraphs in the section on ** +** ``Operating System and Compile Quirks''. ** +************************************************************************** + +For detailed instructions, please read the document ../doc/op/op.me: + + eqn ../doc/op/op.me | pic | ditroff -me + +Sendmail is a trademark of Sendmail, Inc. + + ++-------------------+ +| BUILDING SENDMAIL | ++-------------------+ + +By far, the easiest way to compile sendmail is to use the "Build" +script: + + sh Build + +This uses the "uname" command to figure out what architecture you are +on and creates 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. IRIX 6.x users should +read the note below in the OPERATING SYSTEM AND COMPILE QUIRKS section. + +If you need to look at other include or library directories, use the +-I or -L flags on the command line, e.g., + + sh Build -I/usr/sww/include -L/usr/sww/lib + +It's also possible to create local site configuration in the file +site.config.m4 (or another file settable with the -f flag). This +file contains M4 definitions for various compilation values; the +most useful are: + +confMAPDEF -D flags to specify database types to be included + (see below) +confENVDEF -D flags to specify other environment information +confINCDIRS -I flags for finding include files during compilation +confLIBDIRS -L flags for finding libraries during linking +confLIBS -l flags for selecting libraries during linking +confLDOPTS other ld(1) linker options + +Others can be found by examining Makefile.m4. Please read +../devtools/README for more information about the site.config.m4 +file. + +You can recompile from scratch using the -c flag with the Build +command. This removes the existing compilation directory for the +current platform and builds a new one. + +Porting to a new Unix-based system should be a matter of creating +an appropriate configuration file in the devtools/OS/ directory. + + + ++----------------------+ +| 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 backward compatible. + +The options are: + +NEWDB The new Berkeley DB package. Some systems (e.g., BSD/OS and + Digital UNIX 4.0) have some version of this package + pre-installed. If your system does not have Berkeley DB + pre-installed, or the version installed is not version 2.0 + or greater (e.g., is Berkeley DB 1.85 or 1.86), get the + current version from http://www.sleepycat.com/. DO NOT + use a version from any of the University of California, + Berkeley "Net" or other distributions. If you are still + running BSD/386 1.x, you will need to upgrade the included + Berkeley DB library to a current version. NEWDB is included + automatically if the Build script can find a library named + libdb.a or libdb.so. +NDBM The older NDBM implementation -- the very old V7 DBM + implementation is no longer supported. +NIS Network Information Services. To use this you must have + NIS support on your system. +NISPLUS NIS+ (the revised NIS released with Solaris 2). You must + have NIS+ support on your system to use this flag. +HESIOD Support for Hesiod (from the DEC/Athena distribution). You + must already have Hesiod support on your system for this to + work. You may be able to get this to work with the MIT/Athena + version of Hesiod, but that's likely to be a lot of work. +LDAPMAP Lightweight Directory Lookup Protocol support. You will + have to install the UMich or OpenLDAP + (http://www.openldap.org/) ldap and lber libraries to use + this flag. +MAP_REGEX Regular Expression support. You will need to use an + operating system which comes with the POSIX regex() + routines or install a regexp library such as libregex from + the Free Software Foundation. +PH_MAP PH map support. You will need the qi PH package. +MAP_NSD nsd map support (IRIX 6.5 and later). + +>>> NOTE WELL for NEWDB support: If you want to get ndbm support, for +>>> Berkeley DB versions under 2.0, it is CRITICAL that you remove +>>> ndbm.o from libdb.a before you install it and DO NOT install ndbm.h; +>>> for Berkeley DB versions 2.0 through 2.3.14, remove dbm.o from libdb.a +>>> before you install it. If you don't delete these, there is absolutely +>>> no point to including -DNDBM, since it will just get you another +>>> (inferior) API to the same format database. These files 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. Berkeley DB versions later than 2.3.14 do not need +>>> to be modified. Please also consult the README in the top level +>>> directory of the sendmail distribution for other important information. +>>> +>>> Further note: DO NOT remove your existing /usr/include/ndbm.h -- +>>> you need that one. But do not install an updated ndbm.h in +>>> /usr/include, /usr/local/include, or anywhere else. + +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. + +If NEWDB, NDBM, and NIS are all 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. This is needed because the NIS +maps on an NIS server are built directly from the NDBM files. + +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. + +All of these flags 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. + +Hesiod and LDAP require libraries that may not be installed with your +system. These are outside of my ability to provide support. See the +"Quirks" section for more information. + +The regex map can be used to see if an address matches a certain regular +expression. For example, all-numerics local parts are common spam +addresses, so "^[0-9]+$" would match this. By using such a map in a +check_* rule-set, you can block a certain range of addresses that would +otherwise be considered valid. + ++---------------+ +| COMPILE FLAGS | ++---------------+ + +Wherever 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 devtools/OS 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. +HASFCHOWN Define this to one if you have the fchown(2) system call. + This is required for the TrustedUser option. +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 a seteuid(2) 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. +HAS_ST_GEN Define this to 1 if your system has the st_gen field in + the stat structure (see stat(2)). +HASSRANDOMDEV Define this if your system has the srandomdev(3) function + call. +HASSTRERROR Define this if you have the libc strerror(3) function (which + should be declared in ), and it should be used + instead of sys_errlist. +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 *". +SOCKADDR_LEN_T The type used for the third parameter to accept(2), + getsockname(2), and getpeername(2), representing the + length of a struct sockaddr. Defaults to int. +SOCKOPT_LEN_T The type used for the fifth parameter to getsockopt(2) + and setsockopt(2), representing the length of the option + buffer. Defaults to int. +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_IRIX6 (11) is an IRIX 6.x specific version that adapts + to 32 or 64 bit kernels; it is otherwise very similar + to LA_INT. + LA_KSTAT (12) uses the (Solaris-specific) kstat(3k) + implementation. + LA_DEVSHORT (13) reads a short from a system file (default: + /dev/table/avenrun) and scales it in the same manner + as LA_SHORT. + LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several + other parameters that they try to divine: the name of your + kernel, the name of the variable in the kernel to examine, + the number of bits of precision in a fixed point load average, + and so forth. LA_DEVSHORT uses _PATH_AVENRUN to find the + device to be read to find the load average. + In desperation, use LA_ZERO. The actual code is in + conf.c -- it can be tweaked if you are brave. +FSHIFT For LA_INT, LA_SHORT, and LA_READKSYM, this is the number + 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 ), + SFS_VFS (3), SFS_MOUNT (4), SFS_STATFS (5) if you have + the two-argument statfs(2) system call with includes in + , , or 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 you 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_SYSMIPS (5) -- Use sysmips() supported by NEWS-OS 6. + SPT_SCO (6) -- Write kernel u. area. + SPT_CHANGEARGV (7) -- Write pointers to our own strings into + the existing argv vector. +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. +SAFENFSPATHCONF Set this to 1 if and only if you have verified that a + pathconf(2) call with _PC_CHOWN_RESTRICTED argument on an + NFS filesystem where the underlying system allows users to + give away files to other users returns <= 0. Be sure you + try both on NFS V2 and V3. Some systems assume that their + local policy apply to NFS servers -- this is a bad + assumption! The test/t_pathconf.c program will try this + for you -- you have to run it in a directory that is + mounted from a server that allows file giveaway. +SIOCGIFCONF_IS_BROKEN + Set this if your system has an SIOCGIFCONF ioctl defined, + but it doesn't behave the same way as "most" systems (BSD, + Solaris, SunOS, HP-UX, etc.) +SIOCGIFNUM_IS_BROKEN + Set this if your system has an SIOCGIFNUM ioctl defined, + but it doesn't behave the same way as "most" systems + (Solaris, HP-UX). +NEED_PERCENTQ Set this if your system doesn't support the printf + format strings %lld or %llu. If this is set, %qd and + %qu are used instead. +FAST_PID_RECYCLE + Set this if your system can reuse the same PID in the same + second. + + ++-----------------------+ +| 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. + If 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), you must upgrade to the + current version of Berkeley DB. +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. +LDAPMAP Define this to get LDAP support for maps. +PH_MAP Define this to get PH support for maps. +MAP_NSD Define this to get nsd support for maps. +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 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 AIX3 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. +NETINET6 Set this to get IPv6 support. Other configuration may + be needed in conf.h for your particular operating system. +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. +NETNS Define this to get NS networking support. +NETX25 Define this to get X.25 networking support. +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. +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. +TCPWRAPPERS Turns on support for the TCP wrappers library (-lwrap). + See below for further information. +SECUREWARE Enable calls to the SecureWare luid enabling/changing routines. + SecureWare is a C2 security package added to several UNIX's + (notably ConvexOS) to get a C2 Secure system. This + option causes mail delivery to be done with the luid of the + recipient. +SHARE_V1 Support for the fair share scheduler, version 1. Setting to + 1 causes final delivery to be done using the recipients + resource limitations. So far as I know, this is only + supported on ConvexOS. +SASL Enables SMTP AUTH (RFC 2554). This requires the Cyrus SASL + library (ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/). Please + install at least version 1.5.13. See below for further + information: SASL COMPILATION AND CONFIGURATION. If your + SASL library is older than 1.5.10, you have to set this + to its version number using a simple conversion: a.b.c + -> c + b*100 + a*10000, e.g. for 1.5.9 define SASL=10509. + Note: Using an older version than 1.5.5 of Cyrus SASL is + not supported. Starting with version 1.5.10, setting SASL=1 + is sufficient. Any value other than 1 (or 0) will be + compared with the actual version found and if there is a + mismatch, compilation will fail. + + ++---------------------+ +| 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. This has apparently +been fixed in later versions of BIND, starting around 4.9.3. In other +words, if you use 4.9.0 through 4.9.2, you need -l44bsd; for earlier or +later versions, you do not. + +!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! + + ++------------------------------------+ +| SASL COMPILATION AND CONFIGURATION | ++------------------------------------+ + +Please read the docs accompanying the library (INSTALL and README). +If you use Berkeley DB for Cyrus SASL then you must compile sendmail +with the same version of Berkeley DB. + +You have to select and install authentication mechanisms and tell +sendmail where to find the sasl library and the include files (see +devtools/README for the parameters to set). Setup the required +users and passwords as explained in the SASL documentation. See +also cf/README for authentication related options (esp. DefaultAuthInfo +if you want authentication between MTAs). + +To perform an initial test, connect to your sendmail daemon +(telnet localhost 25) and issue a EHLO localhost and see whether +250-AUTH .... +is in the response. If it isn't, run the daemon with +-O LogLevel=14 +and try again. Then take a look at the logfile and see whether +there are any security related problems listed (unsafe files). + +Further information can be found at: +http://www.sendmail.org/~ca/email/auth.html + + ++-------------------------------------+ +| OPERATING SYSTEM AND COMPILE QUIRKS | ++-------------------------------------+ + +GCC problems + ***************************************************************** + ** 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. + + A bug in gcc 2.5.5 caused problems compiling sendmail 8.6.5 with + optimization on a Sparc. If you are using gcc 2.5.5, youi should + upgrade to the latest version of gcc. + + 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. + + Solaris 2.X users should use version 2.7.2.3 over 2.7.2. + + We have been told there are problems with gcc 2.8.0. If you are + using this version, you should upgrade to 2.8.1 or later. + +GDBM GDBM does not work with sendmail 8.8 because the additional + security checks and file locking cause problems. Unfortunately, + gdbm does not provide a compile flag in its version of ndbm.h so + the code can adapt. Until the GDBM authors can fix these problems, + GDBM will not be supported. Please use Berkeley DB instead. + +Configuration file location + Up to 8.6, sendmail tried to find the sendmail.cf file in the same + place as the vendors had put it, even when this was obviously + stupid. As of 8.7, sendmail ALWAYS looks for /etc/sendmail.cf. + Beginning with 8.10, sendmail uses /etc/mail/sendmail.cf. + You can get sendmail to use the stupid vendor .cf location by + adding -DUSE_VENDOR_CF_PATH during compilation, but this may break + support programs and scripts that need to find sendmail.cf. You + are STRONGLY urged to use symbolic links if you want to use the + vendor location rather than changing the location in the sendmail + binary. + +ControlSocket permissions + Paraphrased from BIND 8.2.1's README: + + Solaris and other pre-4.4BSD kernels do not respect ownership or + protections on UNIX-domain sockets. The short term fix for this is to + override the default path and put such control sockets into root- + owned directories which do not permit non-root to r/w/x through them. + The long term fix is for all kernels to upgrade to 4.4BSD semantics. + +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 + 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 + devtools/OS/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, 4.1.3_U1 + Sendmail causes crashes on SunOS 4.1.3 and 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. + + For 4.1.3, this is fixed in patch 100584-08, available on the + Sunsolve 2.7.1 or later CDs. For 4.1.3_U1, this was fixed in patch + 101790-01 (SunOS 4.1.3_U1: TCP socket and reset problems), later + obsoleted by patch 102010-05. + + Sun patch 100584-08 is not currently publicly available on their + ftp site but a user has reported it can be found at other sites + using a web search engine. + +Solaris 2.x (SunOS 5.x) + To compile for Solaris, the Makefile built by Build must + include a SOLARIS definition which reflects the Solaris version + (i.e. -DSOLARIS=20400 for 2.4 or -DSOLARIS=20501 for 2.5.1). + If you are using gcc, make sure -I/usr/include is not used (or + it might complain about TopFrame). If you are using Sun's cc, + make sure /opt/SUNWspro/bin/cc is used instead of /usr/ucb/cc + (or it might complain about tm_zone). + + 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. + +Solaris 2.6 (SunOS 5.6) + If you built sendmail 8.8.1 through 8.8.4 inclusive on a Solaris 2.5 + system, that binary will not run on Solaris 2.6, due to problems with + incompatible snprintf(3s) calls. This problem is fixed in sendmail + 8.8.5. + +Solaris 2.5.1 (SunOS 5.5.1) and 2.6 (SunOS 5.6) + Apparently Solaris 2.5.1 patch 103663-01 installs a new + /usr/include/resolv.h file that defines the __P macro without + checking to see if it is already defined. This new resolv.h is also + included in the Solaris 2.6 distribution. This causes compile + warnings such as: + + In file included from daemon.c:51: + /usr/include/resolv.h:208: warning: `__P' redefined + cdefs.h:58: warning: this is the location of the previous definition + + These warnings can be safely ignored or you can create a resolv.h + file in the obj.SunOS.5.5.1.* or obj.SunOS.5.6.* directory that reads: + + #undef __P + #include "/usr/include/resolv.h" + + Sun is aware of the problem (Sun bug ID 4081053) and it will be fixed + in Solaris 2.7. + +Solaris 7 (SunOS 5.7) + Solaris 7 includes LDAP libraries but the implementation was + lacking a few things. The following settings can be placed in + devtools/Site/site.SunOS.5.7.m4 if you plan on using those + libraries. + + APPENDDEF(`confMAPDEF', `-DLDAPMAP') + APPENDDEF(`confENVDEF', `-DLDAP_VERSION_MAX=3') + APPENDDEF(`confLIBS', `-lldap') + + Also, Sun's patch 107555 is needed to prevent a crash in the call + to ldap_set_option for LDAP_OPT_REFERRALS in ldapmap_setopts if + LDAP support is compiled in sendmail. + +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. + + The Ultrix 4.5 Y2K patch (ULTV45-022-1) has changed the resolver + included in libc.a. Unfortunately, the __RES symbol hasn't changed + and therefore, sendmail can no longer automatically detect the + newer version. If you get a compiler error: + + /lib/libc.a(gethostent.o): local_hostname_length: multiply defined + + Then rebuild with this in devtools/Site/site.ULTRIX.m4: + + APPENDDEF(`conf_sendmail_ENVDEF', `-DNEEDLOCAL_HOSTNAME_LENGTH=0') + +Digital UNIX (formerly DEC 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. + + On DEC OSF/1 3.2 or earlier, the MatchGECOS option doesn't work + properly due to a bug in the getpw* routines. If you want to use + this, use -DDEC_OSF_BROKEN_GETPWENT=1. The problem is fixed in 3.2C. + + Digital's mail delivery agent, /bin/mail (aka /bin/binmail), will + only preserve the envelope sender in the "From " header if + DefaultUserID is set to daemon. Setting this to mailnull will + cause all mail to have the header "From mailnull ...". To use + a different DefaultUserID, you will need to use a different mail + delivery agent (such as mail.local found in the sendmail + distribution). + + On Digital UNIX 4.0 and later, Berkeley DB 1.85 is included with the + operating system and already has the ndbm.o module removed. However, + Digital has modified the original Berkeley DB db.h include file. + This results in the following warning while compiling map.c and udb.c: + + cc: Warning: /usr/include/db.h, line 74: The redefinition of the macro + "__signed" conflicts with a current definition because the replacement + lists differ. The redefinition is now in effect. + #define __signed signed + ------------------------^ + + This warning can be ignored. + + Digital UNIX's linker checks /usr/ccs/lib/ before /usr/lib/. + If you have installed a new version of BIND in /usr/include + and /usr/lib, you will experience difficulties as Digital ships + libresolv.a in /usr/ccs/lib/ as well. Be sure to replace both + copies of libresolv.a. + +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. + + If you compile with -lmalloc (the fast memory allocator), you may + get warning messages such as the following: + + ld32: WARNING 85: definition of _calloc in /usr/lib32/libmalloc.so + preempts that definition in /usr/lib32/mips3/libc.so. + ld32: WARNING 85: definition of _malloc in /usr/lib32/libmalloc.so + preempts that definition in /usr/lib32/mips3/libc.so. + ld32: WARNING 85: definition of _realloc in /usr/lib32/libmalloc.so + preempts that definition in /usr/lib32/mips3/libc.so. + ld32: WARNING 85: definition of _free in /usr/lib32/libmalloc.so + preempts that definition in /usr/lib32/mips3/libc.so. + ld32: WARNING 85: definition of _cfree in /usr/lib32/libmalloc.so + preempts that definition in /usr/lib32/mips3/libc.so. + + These are unavoidable and innocuous -- just ignore them. + + According to Dave Sill , there is a version of the + Berkeley DB library patched to run on Irix 6.2 available from + http://reality.sgi.com/ariel/freeware/#db . + +IRIX 6.x + If you are using XFS filesystem, avoid using the -32 ABI switch to + the cc compiler if possible. + +IRIX 6.4 + The IRIX 6.5.4 version of /bin/m4 does not work properly with + sendmail. Either install fw_m4.sw.m4 off the Freeware_May99 CD and + use /usr/freeware/bin/m4 or install and use GNU m4. + +NeXT or NEXTSTEP + NEXTSTEP 3.3 and earlier ship with the old DBM library. Also, + Berkeley DB does not currently run on NEXTSTEP. + + If you are compiling on NEXTSTEP, you will have to create an + empty file "unistd.h" and create a file "dirent.h" containing: + + #include + #define dirent direct + + (devtools/OS/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 devtools/OS/FreeBSD). NetBSD-current may have + it too but it has not been verified. + + The latest version of Berkeley DB uses a different naming + scheme than the version that is supplied with your release. This + means you will be able to use the current version of Berkeley DB + with sendmail as long you use the new db.h when compiling + sendmail and link it against the new libdb.a or libdb.so. You + should probably keep the original db.h in /usr/include and the + new db.h in /usr/local/include. + +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 sendmail 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" + 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. + [NOTE: see comment above about GDBM] + + 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. + + [NOTE: Berkeley DB version 2.X runs on A/UX and can be used for + database maps.] + +SCO Unix + From: Thomas Essebier + 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 - + + According to SCO, the m4 which ships with UnixWare 2.1.2 is broken. + We recommend installing GNU m4 before attempting to build sendmail. + +DG/UX + Doug Anderson 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" (for DomainOS 10.3 and earlier) and create a file + "dirent.h" containing: + + #include + #define dirent direct + + (devtools/OS/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 + 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). + + NOTE ON LINUX & BIND: By default, the Makefile generated for Linux + includes header files in /usr/local/include and libraries in + /usr/local/lib. If you've installed BIND on your system, the header + files typically end up in the search path and you need to add + "-lresolv" to the LIBS line in your Makefile. Really old versions + may need to include "-l44bsd" as well (particularly if the link phase + complains about missing strcasecmp, strncasecmp or strpbrk). + Complaints about an undefined reference to `__dn_skipname' in + domain.o are a sure sign that you need to add -lresolv to LIBS. + Newer versions of Linux are basically threaded BIND, so you may or + may not see complaints if you accidentally mix BIND + headers/libraries with virginal libc. If you have BIND headers in + /usr/local/include (resolv.h, etc) you *should* be adding -lresolv + to LIBS. Data structures may change and you'd be asking for a + core dump. + + A number of problems have been reported regarding the Linux 2.2.0 + kernel. So far, these problems have been tracked down to syslog() + and DNS resolution. We believe the problem is with the poll() + implementation in the Linux 2.2.0 kernel and poll()-aware versions + of glib (at least up to 2.0.111). + +AIX 4.2 + The AIX m4 implements a different mechanism for ifdef which is + inconsistent with other versions of m4. Therefore, it will not + work properly with the sendmail Build architecture or m4 + configuration method. To work around this problem, please use + GNU m4 from ftp://ftp.gnu.org/pub/gnu/. + +AIX 3.x + 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/. + +AIX 3.1.x + The supplied load average code only works correctly for AIX 3.2.x. + For 3.1, use -DLA_TYPE=LA_SUBR and get the latest ``monitor'' + package by Jussi Maki from ftp.funet.fi in the + directory pub/unix/AIX/rs6000/monitor-1.12.tar.Z; use the loadavgd + daemon, and the getloadavg subroutine supplied with that package. + If you don't care about load average throttling, just turn off + load average checking using -DLA_TYPE=LA_ZERO. + +AIX 2.2.1 + Date: Mon Dec 4 14:14:56 CST 1995 + From: Mark Whetzel + Subject: Porting sendmail 8.7.2 to AIX V2 on the RT. + + This version of sendmail does not support MB, MG, and MR resource + records, which are supported by AIX sendmail. + + AIX V2 on the RT does not have 'paths.h'. Create a null + file in the 'obj' directory to remove this compile error. + + A patch file is needed to get the BSD 'db' library to compile + for AIX/RT. I have sent the necessary updates to the author, + but they may not be immediately available. + [NOTE: Berkeley DB version 2.X runs on AIX/RT.] + + The original AIX/RT resolver libraries are very old, and you + should get the latest BIND to replace it. The 4.8.3 version + has been tested, but 4.9.x is out and should work. + + To make the load average code work correctly requires an + external routine, as the kernel does not maintain system + load averages, similar to AIX V3.1.x. A reverse port of the + older 1.05 'monitor' load average daemon code written by + Jussi Maki that will work on AIX V2 for the RT is available + by E-mail to Mark Whetzel . + That code depends on an external daemon to collect system + load information, and the external routine 'getloadavg', + that will return that information. The 'LA_SUBR' define + will handle this for AIX V2 on the RT. + + Note: You will have to change devtools/OS/AIX.2 to correctly + point to the locatons of the updated BIND source tree and + the location of the 'newdb' tree and library location. + You will also have to change devtools/OS/AIX.2 to know + about the location of the 'getloadavg' routine if you use + the LA_SUBR define. + + + Manual pages will format correctly if given the mandoc macros + and used with nroff. I have not tried groff. + +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 devtools OS that is intended for all SVR4-based + systems (built from devtools/OS/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 generated Makefile or create a devtools/Site/site.config.m4 + file. + + It's been tested on Dell Issue 2.2. + +DELL SVR4 + Date: Mon, 06 Dec 1993 10:42:29 EST + From: "Kimmo Suominen" + 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 . + 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 + According to Alexander Kolbasov , + 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. + + According to Larry Rosenman : + + UnixWare 2.1.[23]'s m4 chokes (not obviously) when + processing the 8.9.0 cf files. + + I had a LOCAL_RULE_0 that wound up AFTER the + SBasic_check_rcpt rules using the SCO supplied M4. + GNU M4 works fine. + +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 . + +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. + +BIND 8.X + BIND 8.X returns HOST_NOT_FOUND instead of TRY_AGAIN on temporary + DNS failures when trying to find the hostname associated with an IP + address (gethostbyaddr()). This can cause problems as + $&{client_name} based lookups in class R ($=R) and the access + database won't succeed. + + This will be fixed in BIND 8.2.1. For earlier versions, this can + be fixed by making "dns" the last name service queried for host + resolution in /etc/irs.conf: + + hosts local continue + hosts dns + +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. :) + +PH + PH support is provided by Mark Roth . The map is + described at http://www-wsg.cso.uiuc.edu/sendmail/patches/ . + Please contact Mark Roth for support and questions regarding the + map. + +TCP Wrappers + If you are using -DTCPWRAPPERS to get TCP Wrappers support you will + also need to install libwrap.a and modify your site.config.m4 file + or the generated Makefile to include -lwrap in the LIBS line + (make sure that INCDIRS and LIBDIRS point to where the tcpd.h and + libwrap.a can be found). + + TCP Wrappers is available at ftp://ftp.porcupine.org/pub/security/. + + If you have alternate MX sites for your site, be sure that all of + your MX sites reject the same set of hosts. If not, a bad guy whom + you reject will connect to your site, fail, and move on to the next + MX site, which will accept the mail for you and forward it on to you. + +Regular Expressions (MAP_REGEX) + If sendmail linking fails with: + + undefined reference to 'regcomp' + + or sendmail gives an error about a regular expression with: + + pattern-compile-error: : Operation not applicable + + Your libc does not include a running version of POSIX-regex. Use + librx or regex.o from the GNU Free Software Foundation, + ftp://ftp.gnu.org/pub/gnu/rx-?.?.tar.gz or + ftp://ftp.gnu.org/pub/gnu/regex-?.?.tar.gz. + You can also use the regex-lib by Henry Spencer, + ftp://ftp.funet.fi/pub/languages/C/spencer/regex.shar.gz + Make sure, your compiler reads regex.h from the distribution, + not from /usr/include, otherwise sendmail will dump a core. + + ++--------------+ +| MANUAL PAGES | ++--------------+ + +The manual pages have been written against the -man macros, and +should format correctly with any reasonable *roff. + ++-----------------+ +| 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.m4 A template for constructing a makefile based on the + information in the devtools directory. +README 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. +bf.h Buffered file I/O function declarations. +bf_portable.c Stub routines for systems lacking the Torek stdio library. +bf_portable.h Data structure and function declarations for bf_portable.c. +bf_torek.c Routines to implement memory-buffered file system using + hooks provided by Torek stdio library. +bf_torek.h Data structure and function declarations for bf_torek.c. +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. +mime.c MIME conversion routines. +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. +safefile.c Routines to do careful checking of file modes and permissions + when opening or creating files. +savemail.c Routines which save the letter on processing errors. +sendmail.h Main header file for sendmail. +shmticklib.c Routines for shared memory counters. +snprintf.c Routines to manipulate strings but prevent buffer overflows. +srvrsmtp.c Routines to implement server SMTP. +stab.c Routines to manage the symbol table. +stats.c Routines to collect and post the statistics. +statusd_shm.h Data structure and function declarations for shmticklib.c. +sysexits.c List of error messages associated with error codes + in sysexits.h. +timers.c Routines to provide microtimers. +timers.h Data structure and function declarations for timers.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. + +(Version $Revision: 1.1.1.1 $, last update $Date: 2000/04/02 19:05:43 $ ) diff --git a/gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS b/gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS new file mode 100644 index 00000000000..21598e84c61 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS @@ -0,0 +1,85 @@ +# $Sendmail: TRACEFLAGS,v 8.29 1999/11/04 23:31:02 gshapiro Exp $ +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 +0, 101 main.c main print version and exit +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, smtpdata +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, setupmaps (bogus map) +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 safefile.c safefile, safedirpath, filechanged +45 envelope.c setsender +46 envelope.c openxscript +47 main.c drop_privileges +48 parseaddr.c rscheck +48 conf.c validate_connection +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 +56 mci.c persistent host status +57 util.c snprintf +58 bf.c bf* routines +60 map.c +61 conf.c sm_gethostbyname +62 multiple file descriptor checking +63 queue.c runqueue process watching +64 multiple Milter +80 content length +81 sun remote mode +91 mci.c syslogging of MCI cache information +94 srvrsmtp.c cause commands to fail (for protocol testing) +95 srvrsmtp.c AUTH +95 usersmtp.c AUTH +98 * timers +99 main.c avoid backgrounding (no printed output) diff --git a/gnu/usr.sbin/sendmail/sendmail/alias.c b/gnu/usr.sbin/sendmail/sendmail/alias.c new file mode 100644 index 00000000000..0f10e9d3ad1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/alias.c @@ -0,0 +1,973 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: alias.c,v 8.140 2000/02/01 05:49:54 gshapiro Exp $"; +#endif /* ! lint */ + +static MAP *AliasFileMap = NULL; /* the actual aliases.files map */ +static int NAliasFileMaps; /* the number of entries in AliasFileMap */ + +static char *aliaslookup __P((char *, int *)); + + /* +** 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; + char *owner; + auto int status = EX_OK; + char obuf[MAXNAME + 7]; + + if (tTd(27, 1)) + dprintf("alias(%s)\n", a->q_user); + + /* don't realias already aliased names */ + if (!QS_IS_OK(a->q_state)) + 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. + */ + + +#if _FFR_REDIRECTEMPTY + /* + ** envelope <> can't be sent to mailing lists, only owner- + ** send spam of this type to owner- of the list + ** ---- to stop spam from going to mailing lists! + */ + if (e->e_sender != NULL && *e->e_sender == '\0') + { + /* Look for owner of alias */ + (void) strlcpy(obuf, "owner-", sizeof obuf); + (void) strlcat(obuf, a->q_user, sizeof obuf); + if (aliaslookup(obuf, &status) != NULL) + { + if (LogLevel > 8) + syslog(LOG_WARNING, + "possible spam from <> to list: %s, redirected to %s\n", + a->q_user, obuf); + a->q_user = newstr(obuf); + } + } +#endif /* _FFR_REDIRECTEMPTY */ + + p = aliaslookup(a->q_user, &status); + if (status == EX_TEMPFAIL || status == EX_UNAVAILABLE) + { + a->q_state = QS_QUEUEUP; + if (e->e_message == NULL) + e->e_message = newstr("alias database unavailable"); + return; + } + if (p == NULL) + return; + + /* + ** Match on Alias. + ** Deliver to the target list. + */ + + if (tTd(27, 1)) + dprintf("%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_state = QS_VERIFIED; + return; + } + message("aliased to %s", shortenstring(p, MAXSHORTSTR)); + if (LogLevel > 10) + sm_syslog(LOG_INFO, e->e_id, + "alias %.100s => %s", + a->q_paddr, shortenstring(p, MAXSHORTSTR)); + a->q_flags &= ~QSELFREF; + if (tTd(27, 5)) + { + dprintf("alias: QS_EXPANDED "); + printaddr(a, FALSE); + } + a->q_state = QS_EXPANDED; + + /* + ** Always deliver aliased items as the default user. + ** Setting q_gid to 0 forces deliver() to use DefUser + ** instead of the alias name for the call to initgroups(). + */ + + a->q_uid = DefUid; + a->q_gid = 0; + a->q_fullname = NULL; + a->q_flags |= QGOODUID|QALIAS; + + (void) sendtolist(p, a, sendq, aliaslevel + 1, e); + if (bitset(QSELFREF, a->q_flags) && QS_IS_EXPANDED(a->q_state)) + a->q_state = QS_OK; + + /* + ** Look for owner of alias + */ + + (void) strlcpy(obuf, "owner-", sizeof obuf); + if (strncmp(a->q_user, "owner-", 6) == 0 || + strlen(a->q_user) > (SIZE_T) sizeof obuf - 7) + (void) strlcat(obuf, "owner", sizeof obuf); + else + (void) strlcat(obuf, a->q_user, sizeof obuf); + owner = aliaslookup(obuf, &status); + 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. +** +** Returns: +** the value of name. +** NULL if unknown. +** +** Side Effects: +** none. +** +** Warnings: +** The return value will be trashed across calls. +*/ + +static char * +aliaslookup(name, pstat) + char *name; + int *pstat; +{ + static MAP *map = NULL; + + if (map == NULL) + { + STAB *s = stab("aliases", ST_MAP, ST_FIND); + + if (s == NULL) + return NULL; + map = &s->s_map; + } + DYNOPENMAP(map); + + /* special case POstMastER -- always use lower case */ + if (strcasecmp(name, "postmaster") == 0) + name = "postmaster"; + + 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)) + dprintf("setalias(%s)\n", spec); + + for (p = spec; p != NULL; ) + { + char buf[50]; + + while (isascii(*p) && 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) + { + (void) strlcpy(buf, "aliases.files sequence", + sizeof buf); + AliasFileMap = makemapentry(buf); + if (AliasFileMap == NULL) + { + syserr("setalias: cannot create aliases.files map"); + return; + } + } + (void) snprintf(buf, sizeof buf, "Alias%d", NAliasFileMaps); + s = stab(buf, ST_MAP, ST_ENTER); + map = &s->s_map; + memset(map, '\0', 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_INCLNULL; + } + + /* find end of spec */ + if (p != NULL) + { + bool quoted = FALSE; + + for (; *p != '\0'; p++) + { + /* + ** Don't break into a quoted string. + ** Needed for ldap maps which use + ** commas in their specifications. + */ + + if (*p == '"') + quoted = !quoted; + else if (*p == ',' && !quoted) + break; + } + + /* No more alias specifications follow */ + if (*p == '\0') + p = NULL; + } + if (p != NULL) + *p++ = '\0'; + + if (tTd(27, 20)) + dprintf(" map %s:%s %s\n", class, s->s_name, spec); + + /* look up class */ + s = stab(class, ST_MAPCLASS, ST_FIND); + if (s == NULL) + { + syserr("setalias: unknown alias class %s", 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; + bool isopen; +{ + bool attimeout = FALSE; + time_t mtime; + struct stat stb; + char buf[MAXNAME + 1]; + + if (tTd(27, 3)) + dprintf("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)) + dprintf("aliaswait: sleeping for %u seconds\n", + sleeptime); + + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + (void) 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)) + dprintf("aliaswait: not rebuildable\n"); + map->map_mflags &= ~MF_ALIASWAIT; + return isopen; + } + if (stat(map->map_file, &stb) < 0) + { + if (tTd(27, 3)) + dprintf("aliaswait: no source file\n"); + map->map_mflags &= ~MF_ALIASWAIT; + return isopen; + } + mtime = stb.st_mtime; + snprintf(buf, sizeof buf, "%s%s", + map->map_file, ext == NULL ? "" : ext); + if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout) + { +#if !_FFR_REMOVE_AUTOREBUILD + /* database is out of date */ + if (AutoRebuild && stb.st_ino != 0 && + (stb.st_uid == geteuid() || + (geteuid() == 0 && stb.st_uid == TrustedUid))) + { + 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); + } + (void) rebuildaliases(map, TRUE); + isopen = map->map_class->map_open(map, O_RDONLY); + SuprErrs = oldSuprErrs; + } + else + { + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, + "alias database %s out of date", + buf); + message("Warning: alias database %s out of date", buf); + } +#else /* !_FFR_REMOVE_AUTOREBUILD */ + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, + "alias database %s out of date", + buf); + message("Warning: alias database %s out of date", buf); +#endif /* !_FFR_REMOVE_AUTOREBUILD */ + } + 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: +** TRUE if successful; FALSE otherwise. +** +** Side Effects: +** Reads the text version of the database, builds the +** DBM or DB version. +*/ + +bool +rebuildaliases(map, automatic) + register MAP *map; + bool automatic; +{ + FILE *af; + bool nolock = FALSE; + bool success = FALSE; + long sff = SFF_OPENASROOT|SFF_REGONLY|SFF_NOLOCK; + sigfunc_t oldsigint, oldsigquit; +#ifdef SIGTSTP + sigfunc_t oldsigtstp; +#endif /* SIGTSTP */ + + if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) + return FALSE; + + if (!bitnset(DBS_LINKEDALIASFILEINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + if (!bitnset(DBS_GROUPWRITABLEALIASFILE, DontBlameSendmail)) + sff |= SFF_NOGWFILES; + if (!bitnset(DBS_WORLDWRITABLEALIASFILE, DontBlameSendmail)) + sff |= SFF_NOWWFILES; + + /* try to lock the source file */ + if ((af = safefopen(map->map_file, O_RDWR, 0, sff)) == NULL) + { + struct stat stb; + + if ((errno != EACCES && errno != EROFS) || automatic || + (af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL) + { + int saveerr = errno; + + if (tTd(27, 1)) + dprintf("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 FALSE; + } + 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 locked (maybe 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) fclose(af); + errno = 0; + return FALSE; + } + + oldsigint = setsignal(SIGINT, SIG_IGN); + oldsigquit = setsignal(SIGQUIT, SIG_IGN); +#ifdef SIGTSTP + oldsigtstp = setsignal(SIGTSTP, SIG_IGN); +#endif /* SIGTSTP */ + + if (map->map_class->map_open(map, O_RDWR)) + { + if (LogLevel > 7) + { + sm_syslog(LOG_NOTICE, NOQID, + "alias database %s %srebuilt by %s", + map->map_file, automatic ? "auto" : "", + username()); + } + map->map_mflags |= MF_OPEN|MF_WRITABLE; + map->map_pid = getpid(); + readaliases(map, af, !automatic, TRUE); + success = TRUE; + } + else + { + if (tTd(27, 1)) + dprintf("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 */ + (void) fclose(af); + + /* 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 /* SIGTSTP */ + return success; +} + /* +** 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 -- announce 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; + int c; + + LineNumber++; + p = strchr(line, '\n'); + while (p != NULL && p > line && p[-1] == '\\') + { + p--; + if (fgets(p, SPACELEFT(line, p), af) == NULL) + break; + LineNumber++; + p = strchr(p, '\n'); + } + if (p != NULL) + *p = '\0'; + else if (!feof(af)) + { + syserr("554 5.3.0 alias line too long"); + + /* flush to end of line */ + while ((c = getc(af)) != EOF && c != '\n') + continue; + + /* skip any continuation lines */ + skipping = TRUE; + continue; + } + switch (line[0]) + { + case '#': + case '\0': + skipping = FALSE; + continue; + + case ' ': + case '\t': + if (!skipping) + syserr("554 5.3.5 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 5.3.5 missing colon"); + continue; + } + if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL) + { + syserr("554 5.3.5 %.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 *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 5.3.5 %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 && !feof(af)) + { + usrerr("554 5.3.5 alias too long"); + while ((c = fgetc(af)) != EOF && c != '\n') + continue; + skipping = TRUE; + break; + } + } + + if (skipping) + continue; + + if (!bitnset(M_ALIASABLE, al.q_mailer->m_flags)) + { + syserr("554 5.3.5 %s... cannot alias non-local names", + al.q_paddr); + continue; + } + + /* + ** Insert alias into symbol table or database file. + ** + ** Special case pOStmaStER -- always make it lower case. + */ + + if (strcasecmp(al.q_user, "postmaster") == 0) + 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); + if (LogLevel > 7 && logstats) + sm_syslog(LOG_INFO, NOQID, + "%s: %d aliases, longest %d bytes, %d bytes total", + map->map_file, naliases, longest, bytes); +} + /* +** 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; + bool got_transient; + + if (tTd(27, 1)) + dprintf("forward(%s)\n", user->q_paddr); + + if (!bitnset(M_HASPWENT, user->q_mailer->m_flags) || + !QS_IS_OK(user->q_state)) + return; + if (user->q_home == NULL) + { + syserr("554 5.3.0 forward: no home"); + user->q_home = "/no/such/directory"; + } + + /* 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"); + + got_transient = FALSE; + for (pp = ForwardPath; pp != NULL; pp = ep) + { + int err; + char buf[MAXPATHLEN + 1]; + struct stat st; + + ep = strchr(pp, ':'); + if (ep != NULL) + *ep = '\0'; + expand(pp, buf, sizeof buf, e); + if (ep != NULL) + *ep++ = ':'; + if (buf[0] == '\0') + continue; + if (tTd(27, 3)) + dprintf("forward: trying %s\n", buf); + + err = include(buf, TRUE, user, sendq, aliaslevel, e); + if (err == 0) + break; + else if (transienterror(err)) + { + /* we may have to suspend this message */ + got_transient = TRUE; + if (tTd(27, 2)) + dprintf("forward: transient error on %s\n", + buf); + if (LogLevel > 2) + { + char *curhost = CurHostName; + + CurHostName = NULL; + sm_syslog(LOG_ERR, e->e_id, + "forward %s: transient error: %s", + buf, errstring(err)); + CurHostName = curhost; + } + + } + else + { + switch (err) + { + case ENOENT: + break; + + case E_SM_WWDIR: + case E_SM_GWDIR: + /* check if it even exists */ + if (stat(buf, &st) < 0 && errno == ENOENT) + { + if (bitnset(DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH, + DontBlameSendmail)) + break; + } + /* FALLTHROUGH */ + +#if _FFR_FORWARD_SYSERR + case E_SM_NOSLINK: + case E_SM_NOHLINK: + case E_SM_REGONLY: + case E_SM_ISEXEC: + case E_SM_WWFILE: + case E_SM_GWFILE: + syserr("forward: %s: %s", buf, errstring(err)); + break; +#endif /* _FFR_FORWARD_SYSERR */ + + default: + if (LogLevel > (RunAsUid == 0 ? 2 : 10)) + sm_syslog(LOG_WARNING, e->e_id, + "forward %s: %s", buf, + errstring(err)); + if (Verbose) + message("forward: %s: %s", + buf, + errstring(err)); + break; + } + } + } + if (pp == NULL && got_transient) + { + /* + ** There was no successful .forward open and at least one + ** transient open. We have to defer this address for + ** further delivery. + */ + + message("transient .forward open error: message queued"); + user->q_state = QS_QUEUEUP; + return; + } +} diff --git a/gnu/usr.sbin/sendmail/sendmail/aliases b/gnu/usr.sbin/sendmail/sendmail/aliases new file mode 100644 index 00000000000..eb7f1cb0650 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/aliases @@ -0,0 +1,54 @@ +# +# $Sendmail: aliases,v 8.1 1999/02/06 18:44:07 gshapiro Exp $ +# @(#)aliases 8.2 (Berkeley) 3/5/94 +# +# Aliases in this file will NOT be expanded in the header from +# Mail, but WILL be visible over networks or from /bin/mail. +# +# >>>>>>>>>> The program "newaliases" must be run after +# >> NOTE >> this file is updated for any changes to +# >>>>>>>>>> show through to sendmail. +# + +# Basic system aliases -- these MUST be present. +MAILER-DAEMON: postmaster +postmaster: root + +# General redirections for pseudo accounts. +bin: root +daemon: root +games: root +ingres: root +nobody: root +system: root +toor: root +uucp: root + +# Well-known aliases. +manager: root +dumper: root +operator: root + +# trap decode to catch security attacks +decode: root + +# OFFICIAL CSRG/BUG ADDRESSES + +# Ftp maintainer. +ftp: ftp-bugs +ftp-bugs: bigbug@cs.berkeley.edu + +# Distribution office. +bsd-dist: bsd-dist@cs.berkeley.edu + +# Fortune maintainer. +fortune: fortune@cs.berkeley.edu + +# Termcap maintainer. +termcap: termcap@cs.berkeley.edu + +# General bug address. +ucb-fixes: bigbug@cs.berkeley.edu +ucb-fixes-request: bigbug@cs.berkeley.edu +bugs: bugs@cs.berkeley.edu +# END OFFICIAL BUG ADDRESSES diff --git a/gnu/usr.sbin/sendmail/sendmail/aliases.0 b/gnu/usr.sbin/sendmail/sendmail/aliases.0 new file mode 100644 index 00000000000..bf2fc717be2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/aliases.0 @@ -0,0 +1,132 @@ + + + +ALIASES(5) ALIASES(5) + + +NNAAMMEE + aalliiaasseess - aliases file for sendmail + +SSYYNNOOPPSSIISS + aalliiaasseess + +DDEESSCCRRIIPPTTIIOONN + This file describes user ID aliases used by sendmail. The + file resides in /etc/mail and is formatted as a series of + lines of the form + + name: addr_1, addr_2, addr_3, . . . + + The _n_a_m_e is the name to alias, and the _a_d_d_r___n are the + aliases for that name. _a_d_d_r___n can be another alias, a + local username, a local filename, a command, an include + file, or an external address. + + LLooccaall UUsseerrnnaammee + username + + The username must be available via getpwnam(3). + + LLooccaall FFiilleennaammee + /path/name + + Messages are appended to the file specified by the + full pathname (starting with a slash (/)) + + CCoommmmaanndd + |command + + A command starts with a pipe symbol (|), it + receives messages via standard input. + + IInncclluuddee FFiillee + :include: /path/name + + The aliases in pathname are added to the aliases + for _n_a_m_e_. + + EE--MMaaiill AAddddrreessss + user@domain + + An e-mail address in RFC 822 format. + + Lines beginning with white space are continuation lines. + Another way to continue lines is by placing a backslash + directly before a newline. Lines beginning with # are + comments. + + Aliasing occurs only on local names. Loops can not occur, + since no message will be sent to any person more than + once. + + + + $Date: 2000/04/02 19:05:43 $ 1 + + + + + +ALIASES(5) ALIASES(5) + + + After aliasing has been done, local and valid recipients + who have a ``.forward'' file in their home directory have + messages forwarded to the list of users defined in that + file. + + This is only the raw data file; the actual aliasing infor- + mation is placed into a binary format in the file + /etc/mail/aliases.db using the program newaliases(1). A + newaliases command should be executed each time the + aliases file is changed for the change to take effect. + +SSEEEE AALLSSOO + newaliases(1), dbopen(3), dbm(3), sendmail(8) + + _S_E_N_D_M_A_I_L _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n _G_u_i_d_e_. + + _S_E_N_D_M_A_I_L _A_n _I_n_t_e_r_n_e_t_w_o_r_k _M_a_i_l _R_o_u_t_e_r_. + +BBUUGGSS + If you have compiled sendmail with DBM support instead of + NEWDB, you may have encountered problems in dbm(3) + restricting a single alias to about 1000 bytes of informa- + tion. You can get longer aliases by ``chaining''; that + is, make the last name in the alias be a dummy name which + is a continuation alias. + +HHIISSTTOORRYY + The aalliiaasseess file format appeared in 4.0BSD. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:43 $ 2 + + diff --git a/gnu/usr.sbin/sendmail/sendmail/aliases.5 b/gnu/usr.sbin/sendmail/sendmail/aliases.5 new file mode 100644 index 00000000000..5620a8e4eda --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/aliases.5 @@ -0,0 +1,119 @@ +.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: aliases.5,v 8.15 2000/02/26 01:12:21 ca Exp $ +.\" +.TH ALIASES 5 "$Date: 2000/04/02 19:05:43 $" +.SH NAME +.B aliases +\- aliases file for sendmail +.SH SYNOPSIS +.B aliases +.SH DESCRIPTION +This file describes user +ID +aliases used by +sendmail. +The file resides in +/etc/mail +and +is formatted as a series of lines of the form +.IP +name: addr_1, addr_2, addr_3, . . . +.PP +The +.I name +is the name to alias, and the +.I addr_n +are the aliases for that name. +.I addr_n +can be another alias, a local username, a local filename, +a command, +an include file, +or an external address. +.TP +.B Local Username +username +.IP +The username must be available via getpwnam(3). +.TP +.B Local Filename +/path/name +.IP +Messages are appended to the file specified by the full pathname +(starting with a slash (/)) +.TP +.B Command +|command +.IP +A command starts with a pipe symbol (|), +it receives messages via standard input. +.TP +.B Include File +:include: /path/name +.IP +The aliases in pathname are added to the aliases for +.I name. +.TP +.B E-Mail Address +user@domain +.IP +An e-mail address in RFC 822 format. +.PP +Lines beginning with white space are continuation lines. +Another way to continue lines is by placing a backslash +directly before a newline. +Lines beginning with +# +are comments. +.PP +Aliasing occurs only on local names. +Loops can not occur, since no message will be sent to any person more than once. +.PP +After aliasing has been done, local and valid recipients who have a +``.forward'' +file in their home directory have messages forwarded to the +list of users defined in that file. +.PP +This is only the raw data file; the actual aliasing information is +placed into a binary format in the file +/etc/mail/aliases.db +using the program +newaliases(1). +A +newaliases +command should be executed each time the aliases file is changed for the +change to take effect. +.SH SEE ALSO +newaliases(1), +dbopen(3), +dbm(3), +sendmail(8) +.PP +.I +SENDMAIL Installation and Operation Guide. +.PP +.I +SENDMAIL An Internetwork Mail Router. +.SH BUGS +If you have compiled +sendmail +with DBM support instead of NEWDB, +you may have encountered problems in +dbm(3) +restricting a single alias to about 1000 bytes of information. +You can get longer aliases by ``chaining''; that is, make the last name in +the alias be a dummy name which is a continuation alias. +.SH HISTORY +The +.B aliases +file format appeared in +4.0BSD. diff --git a/gnu/usr.sbin/sendmail/sendmail/arpadate.c b/gnu/usr.sbin/sendmail/sendmail/arpadate.c new file mode 100644 index 00000000000..2b2de68fd3f --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/arpadate.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: arpadate.c,v 8.23 1999/09/23 19:59:18 ca Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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 wherever (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 /* ! TZNAME_MAX */ + +/* 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. + */ + + t = curtime(); + 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 /* TZ_TYPE == TZ_TM_NAME */ +#if TZ_TYPE == TZ_TM_ZONE + tz = lt->tm_zone; +#endif /* TZ_TYPE == TZ_TM_ZONE */ +#if TZ_TYPE == TZ_TZNAME + { + extern char *tzname[]; + + if (lt->tm_isdst > 0) + tz = tzname[1]; + else if (lt->tm_isdst == 0) + tz = tzname[0]; + else + tz = NULL; + } +#endif /* TZ_TYPE == TZ_TZNAME */ +#if TZ_TYPE == TZ_TIMEZONE + { + extern char *timezone(); + + tz = timezone(off, lt->tm_isdst); + } +#endif /* TZ_TYPE == TZ_TIMEZONE */ + 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 < &b[sizeof b - 3]) + *q++ = *tz++; + *q++ = ')'; + } + } + *q = '\0'; + + return b; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/bf.h b/gnu/usr.sbin/sendmail/sendmail/bf.h new file mode 100644 index 00000000000..3e347ccc866 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/bf.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: bf.h,v 8.5 1999/11/04 19:31:25 ca Exp $ + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef BF_H +#define BF_H 1 + +extern FILE *bfopen __P((char *, int, size_t, long)); +extern FILE *bfdup __P((FILE *)); +extern int bfcommit __P((FILE *)); +extern int bfrewind __P((FILE *)); +extern int bftruncate __P((FILE *)); +extern int bfclose __P((FILE *)); +extern bool bftest __P((FILE *)); + +#endif /* BF_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/bf_portable.c b/gnu/usr.sbin/sendmail/sendmail/bf_portable.c new file mode 100644 index 00000000000..9b6693a6a43 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/bf_portable.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: bf_portable.c,v 8.25 2000/02/26 01:32:25 gshapiro Exp $"; +#endif /* ! lint */ + + +#include +#include +#include +#include +#include +#include +#include +# include +#ifndef BF_STANDALONE +# include "sendmail.h" +#endif /* ! BF_STANDALONE */ +#include "bf_portable.h" +#include "bf.h" + + /* +** BFOPEN -- create a new buffered file +** +** Parameters: +** filename -- the file's name +** fmode -- what mode the file should be created as +** bsize -- amount of buffer space to allocate (may be 0) +** flags -- if running under sendmail, passed directly to safeopen +** +** Returns: +** a FILE * which may then be used with stdio functions, or NULL +** on failure. FILE * is opened for writing (mode "w+"). +** +** Side Effects: +** none. +** +** Sets errno: +** ENOMEM -- out of memory +** ENOENT -- illegal empty filename specified +** any value of errno specified by open() +** any value of errno specified by fdopen() +** any value of errno specified by funopen() +*/ + +#ifdef BF_STANDALONE +# define OPEN(fn, omode, cmode, sff) open(fn, omode, cmode) +#else /* BF_STANDALONE */ +# define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff) +#endif /* BF_STANDALONE */ + +/* List of currently-open buffered files */ +struct bf *bflist = NULL; + +FILE * +bfopen(filename, fmode, bsize, flags) + char *filename; + int fmode; + size_t bsize; + long flags; +{ + struct bf *bfp; + FILE *retval; + int fd, l; + + fd = OPEN(filename, O_RDWR | O_CREAT | O_TRUNC, fmode, flags); + if (fd == -1) + { + /* errno is set implicitly by open */ + return NULL; + } + + retval = fdopen(fd, "w+"); + + /* If failure, return immediately */ + if (retval == NULL) + { + /* errno is set implicitly by fdopen */ + return NULL; + } + + /* Allocate memory */ + bfp = (struct bf *)malloc(sizeof(struct bf)); + if (bfp == NULL) + { + (void) fclose(retval); + + /* don't care about errors */ + (void) unlink(filename); + errno = ENOMEM; + return NULL; + } + if (tTd(58, 8)) + dprintf("bfopen(%s): malloced %ld\n", + filename, (long) sizeof(struct bf)); + + l = strlen(filename) + 1; + bfp->bf_filename = (char *)malloc(l); + if (bfp->bf_filename == NULL) + { + free(bfp); + (void) fclose(retval); + + /* don't care about errors */ + (void) unlink(filename); + errno = ENOMEM; + return NULL; + } + (void) strlcpy(bfp->bf_filename, filename, l); + + /* Fill in the other fields, then add it to the list */ + bfp->bf_key = retval; + bfp->bf_committed = 0; + bfp->bf_refcount = 1; + + bfinsert(bfp); + + /* Whew. Nothing bad happened. We're okay. */ + return retval; +} + /* +** BFDUP -- increase refcount on buffered file +** +** Parameters: +** fp -- FILE * to "duplicate" +** +** Returns: +** fp with increased refcount +*/ + +FILE * +bfdup(fp) + FILE *fp; +{ + struct bf *bfp; + + /* Get associated bf structure */ + bfp = bflookup(fp); + + if (bfp == NULL) + return NULL; + + /* Increase the refcount */ + bfp->bf_refcount++; + + return fp; +} + + /* +** BFCOMMIT -- "commits" the buffered file +** +** Parameters: +** fp -- FILE * to commit to disk +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** Forces the given FILE * to be written to disk if it is not +** already, and ensures that it will be kept after closing. If +** fp is not a buffered file, this is a no-op. +** +** Sets errno: +** any value of errno specified by open() +** any value of errno specified by write() +** any value of errno specified by lseek() +*/ + +int +bfcommit(fp) + FILE *fp; +{ + struct bf *bfp; + + /* Get associated bf structure */ + bfp = bflookup(fp); + + /* If called on a normal FILE *, noop */ + if (bfp != NULL) + bfp->bf_committed = TRUE; + + return 0; +} + + /* +** BFREWIND -- rewinds the FILE * +** +** Parameters: +** fp -- FILE * to rewind +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the FILE * and puts it into read mode. Normally one +** would bfopen() a file, write to it, then bfrewind() and +** fread(). If fp is not a buffered file, this is equivalent to +** rewind(). +** +** Sets errno: +** any value of errno specified by fseek() +*/ + +int +bfrewind(fp) + FILE *fp; +{ + int err; + + /* check to see if there is an error on the stream */ + err = ferror(fp); + + (void) fflush(fp); + + /* + ** Clear error if tried to fflush() + ** a read-only file pointer and + ** there wasn't a previous error. + */ + + if (err == 0) + clearerr(fp); + + /* errno is set implicitly by fseek() before return */ + return fseek(fp, 0, SEEK_SET); +} + + /* +** BFTRUNCATE -- rewinds and truncates the FILE * +** +** Parameters: +** fp -- FILE * to truncate +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the FILE *, truncates it to zero length, and puts it +** into write mode. If fp is not a buffered file, this is +** equivalent to a rewind() and then an ftruncate(fileno(fp), 0). +** +** Sets errno: +** any value of errno specified by fseek() +** any value of errno specified by ftruncate() +*/ + +int +bftruncate(fp) + FILE *fp; +{ + int ret; + + if (bfrewind(fp) == -1) + { + /* errno is set implicitly by bfrewind() */ + return -1; + } + +#if NOFTRUNCATE + /* XXX */ + errno = EINVAL; + ret = -1; +#else /* NOFTRUNCATE */ + /* errno is set implicitly by ftruncate() before return */ + ret = ftruncate(fileno(fp), 0); +#endif /* NOFTRUNCATE */ + return ret; +} + + /* +** BFCLOSE -- close a buffered file +** +** Parameters: +** fp -- FILE * to close +** +** Returns: +** 0 on success, EOF on failure +** +** Side Effects: +** Closes fp. If fp is a buffered file, unlink it if it has not +** already been committed. If fp is not a buffered file, this is +** equivalent to fclose(). +** +** Sets errno: +** any value of errno specified by fclose() +*/ + +int +bfclose(fp) + FILE *fp; +{ + int retval; + struct bf *bfp = NULL; + + /* Get associated bf structure */ + bfp = bflookup(fp); + + /* Decrement and check refcount */ + if (bfp != NULL && --bfp->bf_refcount > 0) + return 0; + + /* If bf, get bf structure and remove from list */ + if (bfp != NULL) + bfp = bfdelete(fp); + + if (fclose(fp) == EOF) + { + if (tTd(58, 8)) + dprintf("bfclose: fclose failed\n"); + /* errno is set implicitly by fclose() */ + return -1; + } + + if (bfp == NULL) + return 0; + + /* Success unless we determine otherwise in next block */ + retval = 0; + + if (bfp != NULL) + { + /* Might have to unlink; certainly will have to deallocate */ + if (!bfp->bf_committed) + retval = unlink(bfp->bf_filename); + + free(bfp->bf_filename); + free(bfp); + if (tTd(58, 8)) + dprintf("bfclose: freed %ld\n", + (long) sizeof(struct bf)); + } + else + { + if (tTd(58, 8)) + dprintf("bfclose: bfp was NULL\n"); + } + + return retval; +} + + /* +** BFTEST -- test if a FILE * is a buffered file +** +** Parameters: +** fp -- FILE * to test +** +** Returns: +** TRUE if fp is a buffered file, FALSE otherwise. +** +** Side Effects: +** none. +** +** Sets errno: +** never. +*/ + +bool +bftest(fp) + FILE *fp; +{ + return (bflookup(fp) != NULL); +} + + /* +** BFINSERT -- insert item in linking list +** +** Parameters: +** datum -- item to insert +** +** Returns: +** none. +** +** Side Effects: +** none. +** +** Sets errno: +** never. +*/ + +void +bfinsert(datum) + struct bf *datum; +{ + datum->bf_cdr = bflist; + bflist = datum; +} + + /* +** BFLOOKUP -- lookup FILE * in list +** +** Parameters: +** fp -- FILE * to lookup +** +** Returns: +** bf struct for the FILE *, NULL if not found +** +** Side Effects: +** none. +** +** Sets errno: +** never. +*/ + +struct bf * +bflookup(key) + FILE *key; +{ + struct bf *t; + + for (t = bflist; t != NULL; t = t->bf_cdr) + { + if (t->bf_key == key) + { + return t; + } + } + + /* If we got this far, we didn't find it */ + return NULL; +} + + /* +** BFDELETE -- delete a FILE * in list +** +** Parameters: +** fp -- FILE * to delete +** +** Returns: +** bf struct for deleted FILE *, NULL if not found, +** +** Side Effects: +** none. +** +** Sets errno: +** never. +*/ + +struct bf * +bfdelete(key) + FILE *key; +{ + struct bf *t, *u; + + if (bflist == NULL) + return NULL; + + /* if first element, special case */ + if (bflist->bf_key == key) + { + u = bflist; + bflist = bflist->bf_cdr; + return u; + } + + for (t = bflist; t->bf_cdr != NULL; t = t->bf_cdr) + { + if (t->bf_cdr->bf_key == key) + { + u = t->bf_cdr; + t->bf_cdr = u->bf_cdr; + return u; + } + } + + /* If we got this far, we didn't find it */ + return NULL; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/bf_portable.h b/gnu/usr.sbin/sendmail/sendmail/bf_portable.h new file mode 100644 index 00000000000..d1b7b1cace1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/bf_portable.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: bf_portable.h,v 8.6 1999/11/04 19:31:25 ca Exp $ + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef BF_PORTABLE_H +#define BF_PORTABLE_H 1 +/* +** This implementation will behave differently from the Torek-based code in +** the following major ways: +** - The buffer size argument to bfopen() will be sent in, sent back, +** queried, lost, found, subjected to public inquiry, lost again, and +** finally buried in soft peat and recycled as firelighters. +** - Errors in creating the file (but not necessarily writing to it) will +** always be detected and reported synchronously with the bfopen() +*/ + +/* Linked structure for storing information about each buffered file */ +struct bf +{ + FILE *bf_key; /* Unused except as a key for lookup */ + bool bf_committed; /* buffered file is on disk */ + char *bf_filename; /* Name of disk file */ + int bf_refcount; /* Reference count */ + struct bf *bf_cdr; +}; + +/* +** Access routines for looking up bf structures +** +** maybe replace with a faster data structure later +*/ + +extern void bfinsert __P((struct bf *)); +extern struct bf *bflookup __P((FILE *)); +extern struct bf *bfdelete __P((FILE *)); +#endif /* BF_PORTABLE_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/bf_torek.c b/gnu/usr.sbin/sendmail/sendmail/bf_torek.c new file mode 100644 index 00000000000..b558ca528e9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/bf_torek.c @@ -0,0 +1,780 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: bf_torek.c,v 8.19 1999/10/11 23:37:26 ca Exp $"; +#endif /* ! lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BF_STANDALONE +# include "sendmail.h" +#endif /* ! BF_STANDALONE */ +#include "bf_torek.h" +#include "bf.h" + + /* +** BFOPEN -- create a new buffered file +** +** Parameters: +** filename -- the file's name +** fmode -- what mode the file should be created as +** bsize -- amount of buffer space to allocate (may be 0) +** flags -- if running under sendmail, passed directly to safeopen +** +** Returns: +** a FILE * which may then be used with stdio functions, or NULL +** on failure. FILE * is opened for writing (mode "w+"). +** +** Side Effects: +** none. +** +** Sets errno: +** ENOMEM -- out of memory +** ENOENT -- illegal empty filename specified +** any value of errno specified by open() +** any value of errno specified by fdopen() +** any value of errno specified by funopen() +*/ + +#ifdef BF_STANDALONE +# define OPEN(fn, omode, cmode, sff) open(fn, omode, cmode) +#else /* BF_STANDALONE */ +# define OPEN(fn, omode, cmode, sff) safeopen(fn, omode, cmode, sff) +#endif /* BF_STANDALONE */ + +FILE * +bfopen(filename, fmode, bsize, flags) + char *filename; + int fmode; + size_t bsize; + long flags; +{ + struct bf *bfp; + FILE *retval; + int save_errno, l; + struct stat st; + + /* Sanity checks */ + /* Empty filename string */ + if (*filename == '\0') + { + errno = ENOENT; + return NULL; + } + + if (stat(filename, &st) == 0) + { + /* file already exists on disk */ + errno = EEXIST; + return NULL; + } + + /* Allocate memory */ + bfp = (struct bf *)malloc(sizeof(struct bf)); + if (bfp == NULL) + { + errno = ENOMEM; + return NULL; + } + + /* A zero bsize is valid, just don't allocate memory */ + if (bsize > 0) + { + bfp->bf_buf = (char *)malloc(bsize); + if (bfp->bf_buf == NULL) + { + free(bfp); + errno = ENOMEM; + return NULL; + } + } + else + bfp->bf_buf = NULL; + + /* Nearly home free, just set all the parameters now */ + bfp->bf_committed = FALSE; + bfp->bf_ondisk = FALSE; + bfp->bf_refcount = 1; + bfp->bf_flags = flags; + bfp->bf_bufsize = bsize; + bfp->bf_buffilled = 0; + l = strlen(filename) + 1; + bfp->bf_filename = (char *)malloc(l); + if (bfp->bf_filename == NULL) + { + free(bfp); + if (bfp->bf_buf != NULL) + free(bfp->bf_buf); + errno = ENOMEM; + return NULL; + } + (void) strlcpy(bfp->bf_filename, filename, l); + bfp->bf_filemode = fmode; + bfp->bf_offset = 0; + bfp->bf_size = 0; + + if (tTd(58, 8)) + dprintf("bfopen(%s, %d)\n", filename, bsize); + + /* The big test: will funopen accept it? */ + retval = funopen((void *)bfp, _bfread, _bfwrite, _bfseek, _bfclose); + if (retval == NULL) + { + /* Just in case free() sets errno */ + save_errno = errno; + free(bfp); + free(bfp->bf_filename); + if (bfp->bf_buf != NULL) + free(bfp->bf_buf); + errno = save_errno; + return NULL; + } + else + { + /* Success */ + return retval; + } +} + /* +** BFDUP -- increase refcount on buffered file +** +** Parameters: +** fp -- FILE * to "duplicate" +** +** Returns: +** If file is memory buffered, fp with increased refcount +** If file is on disk, NULL (need to use link()) +*/ + +FILE * +bfdup(fp) + FILE *fp; +{ + struct bf *bfp; + + /* If called on a normal FILE *, noop */ + if (!bftest(fp)) + return NULL; + + /* Get associated bf structure */ + bfp = (struct bf *)fp->_cookie; + + /* Increase ref count */ + bfp->bf_refcount++; + + return fp; +} + + /* +** BFCOMMIT -- "commits" the buffered file +** +** Parameters: +** fp -- FILE * to commit to disk +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** Forces the given FILE * to be written to disk if it is not +** already, and ensures that it will be kept after closing. If +** fp is not a buffered file, this is a no-op. +** +** Sets errno: +** any value of errno specified by open() +** any value of errno specified by write() +** any value of errno specified by lseek() +*/ + +int +bfcommit(fp) + FILE *fp; +{ + struct bf *bfp; + int retval; + int byteswritten; + + /* If called on a normal FILE *, noop */ + if (!bftest(fp)) + return 0; + + /* Get associated bf structure */ + bfp = (struct bf *)fp->_cookie; + + /* If already committed, noop */ + if (bfp->bf_committed) + return 0; + + /* Do we need to open a file? */ + if (!bfp->bf_ondisk) + { + struct stat st; + + if (tTd(58, 8)) + dprintf("bfcommit(%s): to disk\n", bfp->bf_filename); + + if (stat(bfp->bf_filename, &st) == 0) + { + errno = EEXIST; + return -1; + } + + retval = OPEN(bfp->bf_filename, O_RDWR | O_CREAT | O_TRUNC, + bfp->bf_filemode, bfp->bf_flags); + + /* Couldn't create file: failure */ + if (retval < 0) + { + /* errno is set implicitly by open() */ + return -1; + } + + bfp->bf_disk_fd = retval; + bfp->bf_ondisk = TRUE; + } + + /* Write out the contents of our buffer, if we have any */ + if (bfp->bf_buffilled > 0) + { + byteswritten = 0; + + if (lseek(bfp->bf_disk_fd, 0, SEEK_SET) < 0) + { + /* errno is set implicitly by lseek() */ + return -1; + } + + while (byteswritten < bfp->bf_buffilled) + { + retval = write(bfp->bf_disk_fd, + bfp->bf_buf + byteswritten, + bfp->bf_buffilled - byteswritten); + if (retval < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + else + byteswritten += retval; + } + } + bfp->bf_committed = TRUE; + + /* Invalidate buf; all goes to file now */ + bfp->bf_buffilled = 0; + if (bfp->bf_bufsize > 0) + { + /* Don't need buffer anymore; free it */ + bfp->bf_bufsize = 0; + free(bfp->bf_buf); + } + return 0; +} + + /* +** BFREWIND -- rewinds the FILE * +** +** Parameters: +** fp -- FILE * to rewind +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the FILE * and puts it into read mode. Normally one +** would bfopen() a file, write to it, then bfrewind() and +** fread(). If fp is not a buffered file, this is equivalent to +** rewind(). +** +** Sets errno: +** any value of errno specified by fseek() +*/ + +int +bfrewind(fp) + FILE *fp; +{ + int err; + + /* check to see if there is an error on the stream */ + err = ferror(fp); + + (void) fflush(fp); + + /* + ** Clear error if tried to fflush() + ** a read-only file pointer and + ** there wasn't a previous error. + */ + + if (err == 0) + clearerr(fp); + + /* errno is set implicitly by fseek() before return */ + return fseek(fp, 0, SEEK_SET); +} + + /* +** BFTRUNCATE -- rewinds and truncates the FILE * +** +** Parameters: +** fp -- FILE * to truncate +** +** Returns: +** 0 on success, -1 on error +** +** Side Effects: +** rewinds the FILE *, truncates it to zero length, and puts it +** into write mode. If fp is not a buffered file, this is +** equivalent to a rewind() and then an ftruncate(fileno(fp), 0). +** +** Sets errno: +** any value of errno specified by fseek() +** any value of errno specified by ftruncate() +*/ + +int +bftruncate(fp) + FILE *fp; +{ + struct bf *bfp; + + if (bfrewind(fp) < 0) + return -1; + + if (bftest(fp)) + { + /* Get bf structure */ + bfp = (struct bf *)fp->_cookie; + bfp->bf_buffilled = 0; + bfp->bf_size = 0; + + /* Need to zero the buffer */ + if (bfp->bf_bufsize > 0) + memset(bfp->bf_buf, '\0', bfp->bf_bufsize); + if (bfp->bf_ondisk) + return ftruncate(bfp->bf_disk_fd, 0); + else + return 0; + } + else + return ftruncate(fileno(fp), 0); +} + + /* +** BFCLOSE -- close a buffered file +** +** Parameters: +** fp -- FILE * to close +** +** Returns: +** 0 on success, EOF on failure +** +** Side Effects: +** Closes fp. If fp is a buffered file, unlink it if it has not +** already been committed. If fp is not a buffered file, this is +** equivalent to fclose(). +** +** Sets errno: +** any value of errno specified by fclose() +*/ + +int +bfclose(fp) + FILE *fp; +{ + struct bf *bfp; + + /* If called on a normal FILE *, call fclose() on it */ + if (!bftest(fp)) + return fclose(fp); + + /* Cast cookie back to correct type */ + bfp = (struct bf *)fp->_cookie; + + /* Check reference count to see if we actually want to close */ + if (bfp != NULL && --bfp->bf_refcount > 0) + return 0; + + /* + ** In this implementation, just call fclose--the _bfclose + ** routine will be called by that + */ + + return fclose(fp); +} + + /* +** BFTEST -- test if a FILE * is a buffered file +** +** Parameters: +** fp -- FILE * to test +** +** Returns: +** TRUE if fp is a buffered file, FALSE otherwise. +** +** Side Effects: +** none. +** +** Sets errno: +** never. +*/ + +bool +bftest(fp) + FILE *fp; +{ + /* + ** Check to see if our special I/O routines are installed + ** in this file structure + */ + + return ((fp->_close == _bfclose) && + (fp->_read == _bfread) && + (fp->_seek == _bfseek) && + (fp->_write == _bfwrite)); +} + + /* +** _BFCLOSE -- close a buffered file +** +** Parameters: +** cookie -- cookie of file to close +** +** Returns: +** 0 to indicate success +** +** Side Effects: +** deletes backing file, frees memory. +** +** Sets errno: +** never. +*/ + +int +_bfclose(cookie) + void *cookie; +{ + struct bf *bfp; + + /* Cast cookie back to correct type */ + bfp = (struct bf *)cookie; + + /* Need to clean up the file */ + if (bfp->bf_ondisk && !bfp->bf_committed) + unlink(bfp->bf_filename); + + /* Need to free the buffer */ + if (bfp->bf_bufsize > 0) + free(bfp->bf_buf); + + /* Finally, free the structure */ + free(bfp); + + return 0; +} + + /* +** _BFREAD -- read a buffered file +** +** Parameters: +** cookie -- cookie of file to read +** buf -- buffer to fill +** nbytes -- how many bytes to read +** +** Returns: +** number of bytes read or -1 indicate failure +** +** Side Effects: +** none. +** +*/ + +int +_bfread(cookie, buf, nbytes) + void *cookie; + char *buf; + int nbytes; +{ + struct bf *bfp; + int count = 0; /* Number of bytes put in buf so far */ + int retval; + + /* Cast cookie back to correct type */ + bfp = (struct bf *)cookie; + + if (bfp->bf_offset < bfp->bf_buffilled) + { + /* Need to grab some from buffer */ + count = nbytes; + if ((bfp->bf_offset + count) > bfp->bf_buffilled) + count = bfp->bf_buffilled - bfp->bf_offset; + + memcpy(buf, bfp->bf_buf + bfp->bf_offset, count); + } + + if ((bfp->bf_offset + nbytes) > bfp->bf_buffilled) + { + /* Need to grab some from file */ + + if (!bfp->bf_ondisk) + { + /* Oops, the file doesn't exist. EOF. */ + goto finished; + } + + /* Catch a read() on an earlier failed write to disk */ + if (bfp->bf_disk_fd < 0) + { + errno = EIO; + return -1; + } + + if (lseek(bfp->bf_disk_fd, + bfp->bf_offset + count, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from read()! Change them + ** into something it can understand. + */ + + errno = EIO; + } + return -1; + } + + while (count < nbytes) + { + retval = read(bfp->bf_disk_fd, + buf + count, + nbytes - count); + if (retval < 0) + { + /* errno is set implicitly by read() */ + return -1; + } + else if (retval == 0) + goto finished; + else + count += retval; + } + } + +finished: + bfp->bf_offset += count; + return count; +} + + /* +** _BFSEEK -- seek to a position in a buffered file +** +** Parameters: +** cookie -- cookie of file to seek +** offset -- position to seek to +** whence -- how to seek +** +** Returns: +** new file offset or -1 indicate failure +** +** Side Effects: +** none. +** +*/ + +fpos_t +_bfseek(cookie, offset, whence) + void *cookie; + fpos_t offset; + int whence; + +{ + struct bf *bfp; + + /* Cast cookie back to correct type */ + bfp = (struct bf *)cookie; + + switch (whence) + { + case SEEK_SET: + bfp->bf_offset = offset; + break; + + case SEEK_CUR: + bfp->bf_offset += offset; + break; + + case SEEK_END: + bfp->bf_offset = bfp->bf_size + offset; + break; + + default: + errno = EINVAL; + return -1; + } + return bfp->bf_offset; +} + + /* +** _BFWRITE -- write to a buffered file +** +** Parameters: +** cookie -- cookie of file to write +** buf -- data buffer +** nbytes -- how many bytes to write +** +** Returns: +** number of bytes written or -1 indicate failure +** +** Side Effects: +** may create backing file if over memory limit for file. +** +*/ + +int +_bfwrite(cookie, buf, nbytes) + void *cookie; + const char *buf; + int nbytes; +{ + struct bf *bfp; + int count = 0; /* Number of bytes written so far */ + int retval; + + /* Cast cookie back to correct type */ + bfp = (struct bf *)cookie; + + /* If committed, go straight to disk */ + if (bfp->bf_committed) + { + if (lseek(bfp->bf_disk_fd, bfp->bf_offset, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from write()! Change them + ** into something it can understand. + */ + + errno = EIO; + } + return -1; + } + + count = write(bfp->bf_disk_fd, buf, nbytes); + if (count < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + goto finished; + } + + if (bfp->bf_offset < bfp->bf_bufsize) + { + /* Need to put some in buffer */ + count = nbytes; + if ((bfp->bf_offset + count) > bfp->bf_bufsize) + count = bfp->bf_bufsize - bfp->bf_offset; + + memcpy(bfp->bf_buf + bfp->bf_offset, buf, count); + if ((bfp->bf_offset + count) > bfp->bf_buffilled) + bfp->bf_buffilled = bfp->bf_offset + count; + } + + if ((bfp->bf_offset + nbytes) > bfp->bf_bufsize) + { + /* Need to put some in file */ + if (!bfp->bf_ondisk) + { + /* Oops, the file doesn't exist. */ + if (tTd(58, 8)) + dprintf("_bfwrite(%s): to disk\n", + bfp->bf_filename); + + retval = OPEN(bfp->bf_filename, + O_RDWR | O_CREAT | O_TRUNC, + bfp->bf_filemode, bfp->bf_flags); + + /* Couldn't create file: failure */ + if (retval < 0) + { + /* + ** stdio may not be expecting these + ** errnos from write()! Change to + ** something which it can understand. + ** Note that ENOSPC and EDQUOT are saved + ** because they are actually valid for + ** write(). + */ + + if (!((errno == ENOSPC) || (errno == EDQUOT))) + errno = EIO; + + return -1; + } + bfp->bf_disk_fd = retval; + bfp->bf_ondisk = TRUE; + } + + /* Catch a write() on an earlier failed write to disk */ + if (bfp->bf_ondisk && bfp->bf_disk_fd < 0) + { + errno = EIO; + return -1; + } + + if (lseek(bfp->bf_disk_fd, + bfp->bf_offset + count, SEEK_SET) < 0) + { + if ((errno == EINVAL) || (errno == ESPIPE)) + { + /* + ** stdio won't be expecting these + ** errnos from write()! Change them into + ** something which it can understand. + */ + + errno = EIO; + } + return -1; + } + + while (count < nbytes) + { + retval = write(bfp->bf_disk_fd, buf + count, + nbytes - count); + if (retval < 0) + { + /* errno is set implicitly by write() */ + return -1; + } + else + count += retval; + } + } + +finished: + bfp->bf_offset += count; + if (bfp->bf_offset > bfp->bf_size) + bfp->bf_size = bfp->bf_offset; + return count; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/bf_torek.h b/gnu/usr.sbin/sendmail/sendmail/bf_torek.h new file mode 100644 index 00000000000..cfd65bcaf7e --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/bf_torek.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: bf_torek.h,v 8.6 1999/11/04 19:31:25 ca Exp $ + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef BF_TOREK_H +#define BF_TOREK_H 1 +/* +** Data structure for storing information about each buffered file +*/ + +struct bf +{ + bool bf_committed; /* Has this buffered file been committed? */ + bool bf_ondisk; /* On disk: committed or buffer overflow */ + int bf_flags; + int bf_disk_fd; /* If on disk, associated file descriptor */ + char *bf_buf; /* Memory buffer */ + int bf_bufsize; /* Length of above buffer */ + int bf_buffilled; /* Bytes of buffer actually filled */ + char *bf_filename; /* Name of buffered file, if ever committed */ + mode_t bf_filemode; /* Mode of buffered file, if ever committed */ + fpos_t bf_offset; /* Currect file offset */ + int bf_size; /* Total current size of file */ + int bf_refcount; /* Reference count */ +}; + +/* Our lower-level I/O routines */ +extern int _bfclose __P((void *)); +extern int _bfread __P((void *, char *, int)); +extern fpos_t _bfseek __P((void *, fpos_t, int)); +extern int _bfwrite __P((void *, const char *, int)); +#endif /* BF_TOREK_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/clock.c b/gnu/usr.sbin/sendmail/sendmail/clock.c new file mode 100644 index 00000000000..6365d3e65ab --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/clock.c @@ -0,0 +1,310 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: clock.c,v 8.52 1999/10/13 22:16:42 ca Exp $"; +#endif /* ! lint */ + +#include + +#ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +#endif /* ! sigmask */ + +static void endsleep __P((void)); + +/* +** 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. +*/ + +EVENT *FreeEventList; /* list of free events */ + +EVENT * +setevent(intvl, func, arg) + time_t intvl; + void (*func)(); + int arg; +{ + register EVENT **evp; + register EVENT *ev; + auto time_t now; + int wasblocked; + + if (intvl <= 0) + { + syserr("554 5.3.0 setevent: intvl=%ld\n", intvl); + return NULL; + } + + wasblocked = blocksignal(SIGALRM); + now = curtime(); + + /* 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 = FreeEventList; + if (ev == NULL) + ev = (EVENT *) xalloc(sizeof *ev); + else + FreeEventList = ev->ev_link; + 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)) + dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", + (long) intvl, (long)(now + intvl), (u_long) func, + arg, (u_long) ev); + + (void) setsignal(SIGALRM, tick); + intvl = EventQueue->ev_time - now; + (void) alarm((unsigned) intvl < 1 ? 1 : intvl); + if (wasblocked == 0) + (void) releasesignal(SIGALRM); + 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; + int wasblocked; + + if (tTd(5, 5)) + dprintf("clrevent: ev=%lx\n", (u_long) ev); + if (ev == NULL) + return; + + /* find the parent event */ + wasblocked = blocksignal(SIGALRM); + for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) + { + if (*evp == ev) + break; + } + + /* now remove it */ + if (*evp != NULL) + { + *evp = ev->ev_link; + ev->ev_link = FreeEventList; + FreeEventList = ev; + } + + /* restore clocks and pick up anything spare */ + if (wasblocked == 0) + (void) releasesignal(SIGALRM); + if (EventQueue != NULL) + (void) kill(getpid(), SIGALRM); + else + { + /* nothing left in event queue, no need for an alarm */ + (void) alarm(0); + } +} + /* +** CLEAR_EVENTS -- remove all events from the event queue. +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +clear_events() +{ + register EVENT *ev; + int wasblocked; + + if (tTd(5, 5)) + dprintf("clear_events: EventQueue=%lx\n", (u_long) EventQueue); + + if (EventQueue == NULL) + return; + + /* nothing will be left in event queue, no need for an alarm */ + (void) alarm(0); + wasblocked = blocksignal(SIGALRM); + + /* find the end of the EventQueue */ + for (ev = EventQueue; ev->ev_link != NULL; ev = ev->ev_link) + continue; + + ev->ev_link = FreeEventList; + FreeEventList = EventQueue; + EventQueue = NULL; + + /* restore clocks and pick up anything spare */ + if (wasblocked == 0) + (void) releasesignal(SIGALRM); +} + /* +** TICK -- take a clock tick +** +** Called by the alarm clock. This routine runs events as needed. +** Always called as a signal handler, so we assume that SIGALRM +** has been blocked. +** +** Parameters: +** One that is ignored; for compatibility with signal handlers. +** +** Returns: +** none. +** +** Side Effects: +** calls the next function in EventQueue. +*/ + +/* ARGSUSED */ +SIGFUNC_DECL +tick(sig) + int sig; +{ + register time_t now; + register EVENT *ev; + int mypid = getpid(); + int save_errno = errno; + + (void) alarm(0); + now = curtime(); + + if (tTd(5, 4)) + dprintf("tick: now=%ld\n", (long) now); + + /* reset signal in case System V semantics */ + (void) setsignal(SIGALRM, tick); + 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)) + dprintf("tick: ev=%lx, func=%lx, arg=%d, pid=%d\n", + (u_long) ev, (u_long) 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; + ev->ev_link = FreeEventList; + FreeEventList = ev; + if (pid != getpid()) + continue; + if (EventQueue != NULL) + { + if (EventQueue->ev_time > now) + (void) alarm((unsigned) (EventQueue->ev_time - now)); + else + (void) alarm(3); + } + + /* call ev_func */ + errno = save_errno; + (*f)(arg); + (void) alarm(0); + now = curtime(); + } + if (EventQueue != NULL) + (void) alarm((unsigned) (EventQueue->ev_time - now)); + errno = save_errno; + return SIGFUNC_RETURN; +} + /* +** 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; + +#ifndef SLEEP_T +# define SLEEP_T unsigned int +#endif /* ! SLEEP_T */ + +SLEEP_T +sleep(intvl) + unsigned int intvl; +{ + int was_held; + + if (intvl == 0) + return (SLEEP_T) 0; + SleepDone = FALSE; + (void) setevent((time_t) intvl, endsleep, 0); + was_held = releasesignal(SIGALRM); + while (!SleepDone) + (void) pause(); + if (was_held > 0) + (void) blocksignal(SIGALRM); + return (SLEEP_T) 0; +} + +static void +endsleep() +{ + SleepDone = TRUE; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/collect.c b/gnu/usr.sbin/sendmail/sendmail/collect.c new file mode 100644 index 00000000000..04e34554859 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/collect.c @@ -0,0 +1,932 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: collect.c,v 8.135 2000/02/27 01:27:43 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +static void collecttimeout __P((time_t)); +static void dferror __P((FILE *volatile, char *, ENVELOPE *)); +static void eatfrom __P((char *volatile, ENVELOPE *)); + + /* +** 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. +** 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 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 */ +#define MS_DISCARD 3 /* discarding rest of message */ + +#if _FFR_MILTER +# define MILTER_EOH() \ +{ \ + if (bitset(CHHDR_MILTER, chompflags) && \ + rstat == EX_OK && \ + !bitset(EF_DISCARD, e->e_flags)) \ + { \ + char state; \ + char *response; \ + \ + response = milter_eoh(e, &state); \ + chompflags &= ~CHHDR_MILTER; \ + switch (state) \ + { \ + case SMFIR_REPLYCODE: \ + usrerr(response); \ + break; \ + \ + case SMFIR_REJECT: \ + usrerr("554 5.7.1 Message rejected"); \ + break; \ + \ + case SMFIR_DISCARD: \ + e->e_flags |= EF_DISCARD; \ + break; \ + \ + case SMFIR_TEMPFAIL: \ + usrerr("451 4.7.1 Try again later"); \ + break; \ + } \ + } \ +} +# endif /* _FFR_MILTER */ + + +void +collect(fp, smtpmode, hdrp, e) + FILE *fp; + bool smtpmode; + HDR **hdrp; + register ENVELOPE *e; +{ + register FILE *volatile df; + volatile bool ignrdot = smtpmode ? FALSE : IgnrDot; + volatile time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; + register char *volatile bp; + volatile int c = EOF; + volatile bool inputerr = FALSE; + bool headeronly; + char *volatile buf; + volatile int buflen; + volatile int istate; + volatile int mstate; + volatile int hdrslen = 0; + volatile int numhdrs = 0; + volatile int dfd; + volatile int afd; + volatile int chompflags = CHHDR_CHECK|CHHDR_USER; + volatile int rstat = EX_OK; + u_char *volatile pbp; + u_char peekbuf[8]; + char hsize[16]; + char hnum[16]; + char dfname[MAXPATHLEN]; + char bufbuf[MAXLINE]; + + headeronly = hdrp != NULL; + + /* + ** Create the temp file name and create the file. + */ + + if (!headeronly) + { + struct stat stbuf; + + (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); +#if _FFR_QUEUE_FILE_MODE + { + MODE_T oldumask; + + if (bitset(S_IWGRP, QueueFileMode)) + oldumask = umask(002); + df = bfopen(dfname, QueueFileMode, DataFileBufferSize, + SFF_OPENASROOT); + if (bitset(S_IWGRP, QueueFileMode)) + (void) umask(oldumask); + } +#else /* _FFR_QUEUE_FILE_MODE */ + df = bfopen(dfname, FileMode, DataFileBufferSize, + SFF_OPENASROOT); +#endif /* _FFR_QUEUE_FILE_MODE */ + if (df == NULL) + { + syserr("Cannot create %s", dfname); + e->e_flags |= EF_NO_BODY_RETN; + finis(TRUE, ExitStat); + /* NOTREACHED */ + } + dfd = fileno(df); + if (dfd < 0 || fstat(dfd, &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 _FFR_MILTER + chompflags |= CHHDR_MILTER; +# endif /* _FFR_MILTER */ + } + + if (tTd(30, 2)) + dprintf("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) + { + if (LogLevel > 2) + sm_syslog(LOG_NOTICE, e->e_id, + "timeout waiting for input from %s during message collect", + CurHostName ? CurHostName : ""); + errno = 0; + usrerr("451 4.4.1 timeout waiting for input during message collect"); + goto readerr; + } + CollectTimeout = setevent(dbto, collecttimeout, dbto); + } + + for (;;) + { + if (tTd(30, 35)) + dprintf("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) + (void) fprintf(TrafficLogFile, "%05d <<< ", + (int) getpid()); + if (c == EOF) + (void) fprintf(TrafficLogFile, "[EOF]\n"); + else + (void) putc(c, TrafficLogFile); + } + if (c == EOF) + goto readerr; + if (SevenBitInput) + c &= 0x7f; + else + HasEightBits |= bitset(0x80, c); + } + if (tTd(30, 94)) + dprintf("istate=%d, c=%c (0x%x)\n", + istate, (char) 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' && !ignrdot) + goto readerr; + else + { + /* push back the ".\rx" */ + *pbp++ = c; + *pbp++ = '\r'; + c = '.'; + } + break; + + case IS_CR: + if (c == '\n') + istate = IS_BOL; + else + { + (void) 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 (!headeronly) + e->e_msgsize++; + switch (mstate) + { + case MS_BODY: + /* just put the character out */ + if (MaxMessageSize <= 0 || + e->e_msgsize <= MaxMessageSize) + (void) putc(c, df); + + /* FALLTHROUGH */ + + case MS_DISCARD: + 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); + memmove(buf, obuf, bp - obuf); + bp = &buf[bp - obuf]; + if (obuf != bufbuf) + free(obuf); + } + if (c >= 0200 && c <= 0237) + { +#if 0 /* causes complaints -- figure out something for 8.11 */ + usrerr("Illegal character 0x%x in header", c); +#else /* 0 */ + /* EMPTY */ +#endif /* 0 */ + } + else if (c != '\0') + { + *bp++ = c; + if (MaxHeadersLength > 0 && + ++hdrslen > MaxHeadersLength) + { + sm_syslog(LOG_NOTICE, e->e_id, + "headers too large (%d max) from %s during message collect", + MaxHeadersLength, + CurHostName != NULL ? CurHostName : "localhost"); + errno = 0; + e->e_flags |= EF_CLRQUEUE; + e->e_status = "5.6.0"; + usrerrenh(e->e_status, + "552 Headers too large (%d max)", + MaxHeadersLength); + mstate = MS_DISCARD; + } + } + if (istate == IS_BOL) + break; + } + *bp = '\0'; + +nextstate: + if (tTd(30, 35)) + dprintf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", + istate, mstate, buf); + switch (mstate) + { + case MS_UFROM: + mstate = MS_HEADER; +#ifndef NOTUNIX + if (strncmp(buf, "From ", 5) == 0) + { + bp = buf; + eatfrom(buf, e); + continue; + } +#endif /* ! NOTUNIX */ + /* FALLTHROUGH */ + + 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) + (void) 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, (int *)&chompflags, + hdrp, e))) + { + mstate = MS_BODY; + goto nextstate; + } + numhdrs++; + break; + + case MS_BODY: + if (tTd(30, 1)) + dprintf("EOH\n"); + + if (headeronly) + goto readerr; + + /* call the end-of-header check ruleset */ + snprintf(hnum, sizeof hnum, "%d", numhdrs); + snprintf(hsize, sizeof hsize, "%d", hdrslen); + if (tTd(30, 10)) + dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n", + hnum, hsize); + rstat = rscheck("check_eoh", hnum, hsize, e, FALSE, + TRUE); + +#if _FFR_MILTER + /* + ** see if a header check already rejected + ** this message or if the check_eoh call + ** resulted in an error. Also, don't call + ** filters if we are discarding the message. + */ + + MILTER_EOH(); +# endif /* _FFR_MILTER */ + + 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') + (void) putc(*bp++, df); + } + break; + } + bp = buf; + } + +readerr: + if ((feof(fp) && smtpmode) || ferror(fp)) + { + const char *errmsg = errstring(errno); + + if (tTd(30, 1)) + dprintf("collect: premature EOM: %s\n", errmsg); + if (LogLevel >= 2) + sm_syslog(LOG_WARNING, e->e_id, + "collect: premature EOM: %s", errmsg); + inputerr = TRUE; + } + +#if _FFR_MILTER + /* + ** If the message was completely empty (no headers, no body), + ** milter hasn't been sent the EOH so do it now. + */ + + MILTER_EOH(); +# endif /* _FFR_MILTER */ + + /* reset global timer */ + clrevent(CollectTimeout); + + if (headeronly) + return; + + if (df == NULL) + { + /* skip next few clauses */ + /* EMPTY */ + } + else if (fflush(df) != 0 || ferror(df)) + { + dferror(df, "fflush||ferror", e); + flush_errors(TRUE); + finis(TRUE, ExitStat); + /* NOTREACHED */ + } + else if (!SuperSafe) + { + /* skip next few clauses */ + /* EMPTY */ + } + else if ((afd = fileno(df)) >= 0 && fsync(afd) < 0) + { + dferror(df, "fsync", e); + flush_errors(TRUE); + finis(TRUE, ExitStat); + /* NOTREACHED */ + } + else if (bfcommit(df) < 0) + { + int save_errno = errno; + + if (save_errno == EEXIST) + { + char *dfile; + struct stat st; + + dfile = queuename(e, 'd'); + if (stat(dfile, &st) < 0) + st.st_size = -1; + errno = EEXIST; + syserr("collect: bfcommit(%s): already on disk, size = %ld", + dfile, st.st_size); + dfd = fileno(df); + if (dfd >= 0) + dumpfd(dfd, TRUE, TRUE); + } + errno = save_errno; + dferror(df, "bfcommit", e); + flush_errors(TRUE); + finis(save_errno != EEXIST, ExitStat); + } + else if (bfclose(df) < 0) + { + dferror(df, "bfclose", e); + flush_errors(TRUE); + finis(TRUE, ExitStat); + /* NOTREACHED */ + } + else + { + /* everything is happily flushed to disk */ + df = NULL; + } + + /* 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"; + if (LogLevel > 0 && feof(fp)) + sm_syslog(LOG_NOTICE, e->e_id, + "collect: %s on connection from %.100s, sender=%s: %s", + problem, host, + shortenstring(e->e_from.q_paddr, MAXSHORTSTR), + errstring(errno)); + if (feof(fp)) + usrerr("451 4.4.1 collect: %s on connection from %s, from=%s", + problem, host, + shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); + else + syserr("451 4.4.1 collect: %s on connection from %s, from=%s", + problem, host, + shortenstring(e->e_from.q_paddr, MAXSHORTSTR)); + + /* 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(TRUE, ExitStat); + /* NOTREACHED */ + } + + /* + ** Find out some information from the headers. + ** Examples are who is the from person & the date. + */ + + eatheader(e, TRUE); + + if (GrabTo && e->e_sendqueue == NULL) + usrerr("No recipient addresses found in header"); + + /* collect statistics */ + if (OpMode != MD_VERIFY) + markstats(e, (ADDRESS *) NULL, FALSE); + + /* + ** If we have a Return-Receipt-To:, turn it into a DSN. + */ + + if (RrtImpliesDsn && hvalue("return-receipt-to", e->e_header) != NULL) + { + ADDRESS *q; + + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + if (!bitset(QHASNOTIFY, q->q_flags)) + q->q_flags |= QHASNOTIFY|QPINGONSUCCESS; + } + + /* + ** 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; + + /* 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)) + dprintf("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_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; + e->e_status = "5.2.3"; + usrerrenh(e->e_status, + "552 Message exceeds maximum fixed size (%ld)", + MaxMessageSize); + if (LogLevel > 6) + sm_syslog(LOG_NOTICE, e->e_id, + "message size (%ld) exceeds maximum (%ld)", + e->e_msgsize, MaxMessageSize); + } + + /* check for illegal 8-bit data */ + if (HasEightBits) + { + e->e_flags |= EF_HAS8BIT; + if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) && + !bitset(EF_IS_MIME, e->e_flags)) + { + e->e_status = "5.6.1"; + usrerrenh(e->e_status, "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 (SuperSafe) + { + if ((e->e_dfp = fopen(dfname, "r")) == NULL) + { + /* we haven't acked receipt yet, so just chuck this */ + syserr("Cannot reopen %s", dfname); + finis(TRUE, ExitStat); + /* NOTREACHED */ + } + } + else + e->e_dfp = df; + if (e->e_dfp == NULL) + syserr("!collect: no e_dfp"); +} + + +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; +} +/* +** DFERROR -- signal error on writing the data file. +** +** Parameters: +** df -- the file pointer for the data file. +** msg -- detailed message. +** e -- the current envelope. +** +** Returns: +** none. +** +** Side Effects: +** Gives an error message. +** Arranges for following output to go elsewhere. +*/ + +static void +dferror(df, msg, e) + FILE *volatile df; + char *msg; + register ENVELOPE *e; +{ + char *dfname; + + dfname = queuename(e, 'd'); + setstat(EX_IOERR); + if (errno == ENOSPC) + { +#if STAT64 > 0 + struct stat64 st; +#else /* STAT64 > 0 */ + struct stat st; +#endif /* STAT64 > 0 */ + long avail; + long bsize; + + e->e_flags |= EF_NO_BODY_RETN; + + if ( +#if STAT64 > 0 + fstat64(fileno(df), &st) +#else /* STAT64 > 0 */ + fstat(fileno(df), &st) +#endif /* STAT64 > 0 */ + < 0) + st.st_size = 0; + (void) freopen(dfname, "w", df); + if (st.st_size <= 0) + fprintf(df, "\n*** Mail could not be accepted"); + /*CONSTCOND*/ + else if (sizeof st.st_size > sizeof (long)) + fprintf(df, "\n*** Mail of at least %s bytes could not be accepted\n", + quad_to_string(st.st_size)); + else + fprintf(df, "\n*** Mail of at least %lu bytes could not be accepted\n", + (unsigned long) st.st_size); + fprintf(df, "*** at %s due to lack of disk space for temp file.\n", + MyHostName); + avail = freediskspace(qid_printqueue(e->e_queuedir), &bsize); + if (avail > 0) + { + if (bsize > 1024) + avail *= bsize / 1024; + else if (bsize < 1024) + avail /= 1024 / bsize; + fprintf(df, "*** Currently, %ld kilobytes are available for mail temp files.\n", + avail); + } + e->e_status = "4.3.1"; + usrerrenh(e->e_status, "452 Out of disk space for temp file"); + } + else + syserr("collect: Cannot write %s (%s, uid=%d)", + dfname, msg, geteuid()); + if (freopen("/dev/null", "w", df) == NULL) + sm_syslog(LOG_ERR, e->e_id, + "dferror: freopen(\"/dev/null\") failed: %s", + errstring(errno)); +} + /* +** 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 + +static char *DowList[] = +{ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL +}; + +static char *MonthList[] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + NULL +}; + +static void +eatfrom(fm, e) + char *volatile fm; + register ENVELOPE *e; +{ + register char *p; + register char **dt; + + if (tTd(30, 2)) + dprintf("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; + + /* we have found a date */ + q = xalloc(25); + (void) strlcpy(q, p, 25); + q = arpadate(q); + define('a', newstr(q), e); + } +} +#endif /* ! NOTUNIX */ diff --git a/gnu/usr.sbin/sendmail/sendmail/conf.c b/gnu/usr.sbin/sendmail/sendmail/conf.c new file mode 100644 index 00000000000..01229fa4382 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/conf.c @@ -0,0 +1,5622 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: conf.c,v 8.643 2000/02/26 06:37:31 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include +#include +#include +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ +#if HASULIMIT && defined(HPUX11) +# include +#endif /* HASULIMIT && defined(HPUX11) */ + +static void setupmaps __P((void)); +static void setupmailers __P((void)); +static int get_num_procs_online __P((void)); + + +/* +** 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, NULL }, + { "resent-from", H_FROM|H_RESENT, NULL }, + { "resent-reply-to", H_FROM|H_RESENT, NULL }, + { "sender", H_FROM, NULL }, + { "from", H_FROM, NULL }, + { "reply-to", H_FROM, NULL }, + { "errors-to", H_FROM|H_ERRORSTO, NULL }, + { "full-name", H_ACHECK, NULL }, + { "return-receipt-to", H_RECEIPTTO, NULL }, + + /* destination fields */ + { "to", H_RCPT, NULL }, + { "resent-to", H_RCPT|H_RESENT, NULL }, + { "cc", H_RCPT, NULL }, + { "resent-cc", H_RCPT|H_RESENT, NULL }, + { "bcc", H_RCPT|H_BCC, NULL }, + { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL }, + { "apparently-to", H_RCPT, NULL }, + + /* message identification and control */ + { "message-id", 0, NULL }, + { "resent-message-id", H_RESENT, NULL }, + { "message", H_EOH, NULL }, + { "text", H_EOH, NULL }, + + /* date fields */ + { "date", 0, NULL }, + { "resent-date", H_RESENT, NULL }, + + /* trace fields */ + { "received", H_TRACE|H_FORCE, NULL }, + { "x400-received", H_TRACE|H_FORCE, NULL }, + { "via", H_TRACE|H_FORCE, NULL }, + { "mail-from", H_TRACE|H_FORCE, NULL }, + + /* miscellaneous fields */ + { "comments", H_FORCE|H_ENCODABLE, NULL }, + { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL }, + { "content-transfer-encoding", H_CTE, NULL }, + { "content-type", H_CTYPE, NULL }, + { "content-length", H_ACHECK, NULL }, + { "subject", H_ENCODABLE, NULL }, + { "x-authentication-warning", H_FORCE, NULL }, + + { NULL, 0, NULL } +}; + + + +/* +** 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 }, + { "noetrn", PRIV_NOETRN }, + { "noverb", PRIV_NOVERB }, + { "authwarnings", PRIV_AUTHWARNINGS }, + { "noreceipts", PRIV_NORECEIPTS }, + { "nobodyreturn", PRIV_NOBODYRETN }, + { "goaway", PRIV_GOAWAY }, + { NULL, 0 } +}; + +/* +** DontBlameSendmail values +*/ +struct dbsval DontBlameSendmailValues[] = +{ + { "safe", DBS_SAFE }, + { "assumesafechown", DBS_ASSUMESAFECHOWN }, + { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE }, + { "groupwritableforwardfilesafe", + DBS_GROUPWRITABLEFORWARDFILESAFE }, + { "groupwritableincludefilesafe", + DBS_GROUPWRITABLEINCLUDEFILESAFE }, + { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE }, + { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE }, + { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH }, + { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH }, + { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH }, + { "linkedaliasfileinwritabledir", + DBS_LINKEDALIASFILEINWRITABLEDIR }, + { "linkedclassfileinwritabledir", + DBS_LINKEDCLASSFILEINWRITABLEDIR }, + { "linkedforwardfileinwritabledir", + DBS_LINKEDFORWARDFILEINWRITABLEDIR }, + { "linkedincludefileinwritabledir", + DBS_LINKEDINCLUDEFILEINWRITABLEDIR }, + { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR }, + { "linkedserviceswitchfileinwritabledir", + DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR }, + { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK }, + { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK }, + { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK }, + { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK }, + { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK }, + { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK }, + { "forwardfileingroupwritabledirpath", + DBS_FORWARDFILEINGROUPWRITABLEDIRPATH }, + { "includefileingroupwritabledirpath", + DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH }, + { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH }, + { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH }, + { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH }, + { "forwardfileinunsafedirpathsafe", + DBS_FORWARDFILEINUNSAFEDIRPATHSAFE }, + { "includefileinunsafedirpathsafe", + DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE }, + { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH }, + { "runwritableprogram", DBS_RUNWRITABLEPROGRAM }, + { "nonrootsafeaddr", DBS_NONROOTSAFEADDR }, + { "truststickybit", DBS_TRUSTSTICKYBIT }, + { "dontwarnforwardfileinunsafedirpath", + DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, +#if _FFR_UNSAFE_SASL + { "groupreadablesaslfile", DBS_GROUPREADABLESASLFILE }, +#endif /* _FFR_UNSAFE_SASL */ + { 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 /* ! MAXRULERECURSION */ + +void +setdefaults(e) + register ENVELOPE *e; +{ + int i; + int numprocs; + struct passwd *pw; + + numprocs = get_num_procs_online(); + SpaceSub = ' '; /* option B */ + QueueLA = 8 * numprocs; /* option x */ + RefuseLA = 12 * numprocs; /* 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 */ +#if _FFR_QUEUE_FILE_MODE + QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600; + /* option QueueFileMode */ +#endif /* _FFR_QUEUE_FILE_MODE */ + + if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) || + ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) || + ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0)) + { + DefUid = pw->pw_uid; /* option u */ + DefGid = pw->pw_gid; /* option g */ + DefUser = newstr(pw->pw_name); + } + else + { + DefUid = 1; /* option u */ + DefGid = 1; /* option g */ + setdefuser(); + } + TrustedUid = 0; + if (tTd(37, 4)) + dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n", + DefUser != NULL ? DefUser : "<1:1>", + (int) DefUid, (int) DefGid); + CheckpointInterval = 10; /* option C */ + MaxHopCount = 25; /* option h */ + set_delivery_mode(SM_FORK, e); /* option d */ + e->e_errormode = EM_PRINT; /* option e */ + e->e_queuedir = NOQDIR; + e->e_ctime = curtime(); + SevenBitInput = FALSE; /* option 7 */ + MaxMciCache = 1; /* option k */ + MciCacheTimeout = 5 MINUTES; /* option K */ + LogLevel = 9; /* option L */ + inittimeouts(NULL, FALSE); /* option r */ + PrivacyFlags = PRIV_PUBLIC; /* option p */ + MeToo = TRUE; /* option m */ + SendMIMEErrors = TRUE; /* option f */ + SuperSafe = TRUE; /* option s */ + clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */ +#if MIME8TO7 + MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ +#else /* MIME8TO7 */ + MimeMode = MM_PASS8BIT; +#endif /* MIME8TO7 */ + 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/mail/service.switch"; + ServiceCacheMaxAge = (time_t) 10; + HostsFile = _PATH_HOSTS; + PidFile = newstr(_PATH_SENDMAILPID); + MustQuoteChars = "@,;:\\()[].'"; + MciInfoTimeout = 30 MINUTES; + MaxRuleRecursion = MAXRULERECURSION; + MaxAliasRecursion = 10; + MaxMacroRecursion = 10; + ColonOkInAddr = TRUE; + DontLockReadFiles = TRUE; + DoubleBounceAddr = "postmaster"; + MaxHeadersLength = MAXHDRSLEN; + MaxForwardEntries = 0; +#if SASL + AuthMechanisms = newstr(AUTH_MECHANISMS); +#endif /* SASL */ +#ifdef HESIOD_INIT + HesiodContext = NULL; +#endif /* HESIOD_INIT */ +#if NETINET6 + /* Detect if IPv6 is available at run time */ + i = socket(AF_INET6, SOCK_STREAM, 0); + if (i >= 0) + { + InetMode = AF_INET6; + (void) close(i); + } + else + InetMode = AF_INET; +#else /* NETINET6 */ + InetMode = AF_INET; +#endif /* NETINET6 */ + ControlSocketName = NULL; + memset(&ConnectOnlyTo, '\0', sizeof ConnectOnlyTo); + DataFileBufferSize = 4096; + XscriptFileBufferSize = 4096; + for (i = 0; i < MAXRWSETS; i++) + RuleSetNames[i] = NULL; +#if _FFR_MILTER + InputFilters[0] = NULL; +#endif /* _FFR_MILTER */ + setupmaps(); + setupmailers(); + setupheaders(); +} + + +/* +** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) +*/ + +void +setdefuser() +{ + struct passwd *defpwent; + static char defuserbuf[40]; + + DefUser = defuserbuf; + defpwent = sm_getpwuid(DefUid); + snprintf(defuserbuf, sizeof defuserbuf, "%s", + defpwent == NULL ? "nobody" : defpwent->pw_name); + if (tTd(37, 4)) + dprintf("setdefuser: DefUid=%d, DefUser=%s\n", + (int) DefUid, DefUser); +} + /* +** SETUPMAILERS -- initialize default mailers +*/ + +static void +setupmailers() +{ + char buf[100]; + + (void) strlcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", + sizeof buf); + makemailer(buf); + + (void) strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u", + sizeof buf); + makemailer(buf); + + (void) strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u", + sizeof buf); + makemailer(buf); + initerrmailers(); +} + /* +** 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; \ + } + +static 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 /* NEWDB */ + +#ifdef NDBM + MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, + map_parseargs, ndbm_map_open, ndbm_map_close, + ndbm_map_lookup, ndbm_map_store); +#endif /* NDBM */ + +#ifdef NIS + MAPDEF("nis", NULL, MCF_ALIASOK, + map_parseargs, nis_map_open, null_map_close, + nis_map_lookup, null_map_store); +#endif /* NIS */ + +#ifdef NISPLUS + MAPDEF("nisplus", NULL, MCF_ALIASOK, + map_parseargs, nisplus_map_open, null_map_close, + nisplus_map_lookup, null_map_store); +#endif /* NISPLUS */ + +#ifdef LDAPMAP + MAPDEF("ldap", NULL, MCF_ALIASOK, + ldapmap_parseargs, ldapmap_open, ldapmap_close, + ldapmap_lookup, null_map_store); + + /* Deprecated */ + MAPDEF("ldapx", NULL, MCF_ALIASOK, + ldapx_map_parseargs, ldapmap_open, ldapmap_close, + ldapmap_lookup, null_map_store); +#endif /* LDAPMAP */ + +#ifdef PH_MAP + MAPDEF("ph", NULL, 0, + ph_map_parseargs, ph_map_open, ph_map_close, + ph_map_lookup, null_map_store); +#endif /* PH_MAP */ + +#if MAP_NSD + /* IRIX 6.5 nsd support */ + MAPDEF("nsd", NULL, MCF_ALIASOK, + map_parseargs, null_map_open, null_map_close, + nsd_map_lookup, null_map_store); +#endif /* MAP_NSD */ + +#ifdef HESIOD + MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, + map_parseargs, hes_map_open, null_map_close, + hes_map_lookup, null_map_store); +#endif /* HESIOD */ + +#if NETINFO + MAPDEF("netinfo", NULL, MCF_ALIASOK, + map_parseargs, ni_map_open, null_map_close, + ni_map_lookup, null_map_store); +#endif /* NETINFO */ + +#if 0 + MAPDEF("dns", NULL, 0, + dns_map_init, null_map_open, null_map_close, + dns_map_lookup, null_map_store); +#endif /* 0 */ + +#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 /* NAMED_BIND */ + + 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); + +#ifdef MAP_REGEX + MAPDEF("regex", NULL, 0, + regex_map_init, null_map_open, null_map_close, + regex_map_lookup, null_map_store); +#endif /* MAP_REGEX */ + +#if USERDB + /* user database */ + MAPDEF("userdb", ".db", 0, + map_parseargs, null_map_open, null_map_close, + udb_map_lookup, null_map_store); +#endif /* USERDB */ + + /* 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); + + /* syslog map -- logs information to syslog */ + MAPDEF("syslog", NULL, 0, + syslog_map_parseargs, null_map_open, null_map_close, + syslog_map_lookup, null_map_store); + + /* macro storage map -- rulesets can set macros */ + MAPDEF("macro", NULL, 0, + dequote_init, null_map_open, null_map_close, + macro_map_lookup, null_map_store); + + /* arithmetic map -- add/subtract/compare */ + MAPDEF("arith", NULL, 0, + dequote_init, null_map_open, null_map_close, + arith_map_lookup, null_map_store); + + if (tTd(38, 2)) + { + /* bogus map -- always return tempfail */ + MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE, + map_parseargs, null_map_open, null_map_close, + bogus_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) + { + (void) strlcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts", + sizeof buf); + (void) makemapentry(buf); + } +# if NAMED_BIND + else if (strcmp(maptype[i], "dns") == 0 && + stab("hosts.dns", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "hosts.dns dns A", sizeof buf); + (void) makemapentry(buf); + } +# endif /* NAMED_BIND */ +# ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "hosts.nisplus nisplus -k name -v address hosts.org_dir", + sizeof buf); + (void) makemapentry(buf); + } +# endif /* NISPLUS */ +# ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("hosts.nis", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "hosts.nis nis -k 0 -v 1 hosts.byname", + sizeof buf); + (void) makemapentry(buf); + } +# endif /* NIS */ +# if NETINFO + else if (strcmp(maptype[i], "netinfo") == 0) && + stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "hosts.netinfo netinfo -v name /machines", + sizeof buf); + (void) makemapentry(buf); + } +# endif /* NETINFO */ + } +#endif /* 0 */ + + /* + ** Make sure we have a host map. + */ + + if (stab("host", ST_MAP, ST_FIND) == NULL) + { + /* user didn't initialize: set up host map */ + (void) strlcpy(buf, "host host", sizeof buf); +#if NAMED_BIND + if (ConfigLevel >= 2) + (void) strlcat(buf, " -a. -D", sizeof buf); +#endif /* NAMED_BIND */ + (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) + { + (void) strlcpy(buf, "aliases.files null", sizeof buf); + (void) makemapentry(buf); + } +#ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir", + sizeof buf); + (void) makemapentry(buf); + } +#endif /* NISPLUS */ +#ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("aliases.nis", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "aliases.nis nis mail.aliases", + sizeof buf); + (void) makemapentry(buf); + } +#endif /* NIS */ +#if NETINFO + else if (strcmp(maptype[i], "netinfo") == 0 && + stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "aliases.netinfo netinfo -z, /aliases", + sizeof buf); + (void) makemapentry(buf); + } +#endif /* NETINFO */ +#ifdef HESIOD + else if (strcmp(maptype[i], "hesiod") == 0 && + stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "aliases.hesiod hesiod aliases", + sizeof buf); + (void) makemapentry(buf); + } +#endif /* HESIOD */ + } + if (stab("aliases", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "aliases switch aliases", sizeof buf); + (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) + { + (void) strlcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd", + sizeof buf); + (void) makemapentry(buf); + } +# ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("users.nisplus", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "users.nisplus nisplus -m -kname -vhome passwd.org_dir", + sizeof buf); + (void) makemapentry(buf); + } +# endif /* NISPLUS */ +# ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("users.nis", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "users.nis nis -m passwd.byname", + sizeof buf); + (void) makemapentry(buf); + } +# endif /* NIS */ +# ifdef HESIOD + else if (strcmp(maptype[i], "hesiod") == 0) && + stab("users.hesiod", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "users.hesiod hesiod", sizeof buf); + (void) makemapentry(buf); + } +# endif /* HESIOD */ + } + if (stab("users", ST_MAP, ST_FIND) == NULL) + { + (void) strlcpy(buf, "users switch -m passwd", sizeof buf); + (void) makemapentry(buf); + } +#endif /* 0 */ +} + /* +** 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. +** +** Side effects: +** Preserves errno so nothing in the routine clobbers it. +*/ + +#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) +# define _USE_SUN_NSSWITCH_ +#endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */ + +#ifdef _USE_SUN_NSSWITCH_ +# include +#endif /* _USE_SUN_NSSWITCH_ */ + +#if defined(ultrix) || (defined(__osf__) && defined(__alpha)) +# define _USE_DEC_SVC_CONF_ +#endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */ + +#ifdef _USE_DEC_SVC_CONF_ +# include +#endif /* _USE_DEC_SVC_CONF_ */ + +int +switch_map_find(service, maptype, mapreturn) + char *service; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; +{ + int svcno; + int save_errno = errno; + +#ifdef _USE_SUN_NSSWITCH_ + struct __nsw_switchconfig *nsw_conf; + enum __nsw_parse_err pserr; + struct __nsw_lookup *lk; + 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; + } + errno = save_errno; + return svcno; +#endif /* _USE_SUN_NSSWITCH_ */ + +#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 + { + errno = save_errno; + 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 /* SVC_HESIOD */ + + case SVC_LAST: + errno = save_errno; + return svcno; + } + } + errno = save_errno; + return svcno; +#endif /* _USE_DEC_SVC_CONF_ */ + +#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) + /* + ** Fall-back mechanism. + */ + + STAB *st; + time_t now = curtime(); + + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + + if ((now - ServiceCacheTime) > (time_t) ServiceCacheMaxAge) + { + /* (re)read service switch */ + register FILE *fp; + long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK; + + if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, + DontBlameSendmail)) + sff |= SFF_NOWLINK; + + if (ConfigFileRead) + ServiceCacheTime = now; + fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff); + if (fp != NULL) + { + char buf[MAXLINE]; + + 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 (buf[0] == '\0') + continue; + if (p == NULL) + { + sm_syslog(LOG_ERR, NOQID, + "Bad line on %.100s: %.100s", + ServiceSwitchFile, + buf); + continue; + } + while (isspace(*p)) + p++; + if (*p == '\0') + continue; + + /* + ** Find/allocate space for this service entry. + ** Space for all of the service strings + ** are allocated at once. This means + ** that we only have to free the first + ** one to free all of them. + */ + + st = stab(buf, ST_SERVICE, ST_ENTER); + if (st->s_service[0] != NULL) + free((void *) st->s_service[0]); + p = newstr(p); + for (svcno = 0; svcno < MAXMAPSTACK; ) + { + if (*p == '\0') + break; + st->s_service[svcno++] = p; + p = strpbrk(p, " \t"); + if (p == NULL) + break; + *p++ = '\0'; + while (isspace(*p)) + p++; + } + if (svcno < MAXMAPSTACK) + st->s_service[svcno] = NULL; + } + (void) fclose(fp); + } + } + + /* look up entry in cache */ + st = stab(service, ST_SERVICE, ST_FIND); + if (st != NULL && st->s_service[0] != NULL) + { + /* extract data */ + svcno = 0; + while (svcno < MAXMAPSTACK) + { + maptype[svcno] = st->s_service[svcno]; + if (maptype[svcno++] == NULL) + break; + } + errno = save_errno; + return --svcno; + } +#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ + +#if !defined(_USE_SUN_NSSWITCH_) + /* if the service file doesn't work, use an absolute fallback */ +# ifdef _USE_DEC_SVC_CONF_ + punt: +# endif /* _USE_DEC_SVC_CONF_ */ + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + svcno = 0; + if (strcmp(service, "aliases") == 0) + { + maptype[svcno++] = "files"; +# if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) + maptype[svcno++] = "netinfo"; +# endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */ +# ifdef AUTO_NIS_ALIASES +# ifdef NISPLUS + maptype[svcno++] = "nisplus"; +# endif /* NISPLUS */ +# ifdef NIS + maptype[svcno++] = "nis"; +# endif /* NIS */ +# endif /* AUTO_NIS_ALIASES */ + errno = save_errno; + return svcno; + } + if (strcmp(service, "hosts") == 0) + { +# if NAMED_BIND + maptype[svcno++] = "dns"; +# else /* NAMED_BIND */ +# if defined(sun) && !defined(BSD) + /* SunOS */ + maptype[svcno++] = "nis"; +# endif /* defined(sun) && !defined(BSD) */ +# endif /* NAMED_BIND */ +# if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) + maptype[svcno++] = "netinfo"; +# endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */ + maptype[svcno++] = "files"; + errno = save_errno; + return svcno; + } + errno = save_errno; + return -1; +#endif /* !defined(_USE_SUN_NSSWITCH_) */ +} + /* +** 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 5.3.0 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(S_IWOTH, 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; +{ + if (tTd(49, 1)) + dprintf("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 suppress 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; +{ + /* + ** First, try for modern signal calls + ** and restartable syscalls + */ + +#ifdef SA_RESTART + struct sigaction n, o; + + memset(&n, '\0', sizeof n); +# if USE_SA_SIGACTION + n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler; + n.sa_flags = SA_RESTART|SA_SIGINFO; +# else /* USE_SA_SIGACTION */ + n.sa_handler = handler; + n.sa_flags = SA_RESTART; +# endif /* USE_SA_SIGACTION */ + if (sigaction(sig, &n, &o) < 0) + return SIG_ERR; + return o.sa_handler; +#else /* SA_RESTART */ + + /* + ** Else check for SYS5SIGNALS or + ** BSD4_3 signals + */ + +# if defined(SYS5SIGNALS) || defined(BSD4_3) +# ifdef BSD4_3 + return signal(sig, handler); +# else /* BSD4_3 */ + return sigset(sig, handler); +# endif /* BSD4_3 */ +# else /* defined(SYS5SIGNALS) || defined(BSD4_3) */ + + /* + ** Finally, if nothing else is available, + ** go for a default + */ + + struct sigaction n, o; + + memset(&n, '\0', sizeof n); + n.sa_handler = handler; + if (sigaction(sig, &n, &o) < 0) + return SIG_ERR; + return o.sa_handler; +# endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */ +#endif /* SA_RESTART */ +} + /* +** BLOCKSIGNAL -- hold a signal to prevent delivery +** +** Parameters: +** sig -- the signal to block. +** +** Returns: +** 1 signal was previously blocked +** 0 signal was not previously blocked +** -1 on failure. +*/ + +int +blocksignal(sig) + int sig; +{ +#ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ + return (sigblock(sigmask(sig)) & sigmask(sig)) != 0; +#else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + sigfunc_t handler; + + handler = sigset(sig, SIG_HOLD); + if (handler == SIG_ERR) + return -1; + else + return handler == SIG_HOLD; +# else /* ALTOS_SYSTEM_V */ + sigset_t sset, oset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); + if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0) + return -1; + else + return sigismember(&oset, sig); +# endif /* ALTOS_SYSTEM_V */ +#endif /* BSD4_3 */ +} + /* +** RELEASESIGNAL -- release a held signal +** +** Parameters: +** sig -- the signal to release. +** +** Returns: +** 1 signal was previously blocked +** 0 signal was not previously blocked +** -1 on failure. +*/ + +int +releasesignal(sig) + int sig; +{ +#ifdef BSD4_3 + return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0; +#else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + sigfunc_t handler; + + handler = sigset(sig, SIG_HOLD); + if (sigrelse(sig) < 0) + return -1; + else + return handler == SIG_HOLD; +# else /* ALTOS_SYSTEM_V */ + sigset_t sset, oset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, sig); + if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0) + return -1; + else + return sigismember(&oset, sig); +# endif /* ALTOS_SYSTEM_V */ +#endif /* BSD4_3 */ +} + /* +** 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 +#endif /* _AUX_SOURCE */ + +#if SHARE_V1 +# include +#endif /* SHARE_V1 */ + +void +init_md(argc, argv) + int argc; + char **argv; +{ +#ifdef _AUX_SOURCE + setcompat(getcompat() | COMPAT_BSDPROT); +#endif /* _AUX_SOURCE */ + +#ifdef SUN_EXTENSIONS + init_md_sun(); +#endif /* SUN_EXTENSIONS */ + +#if _CONVEX_SOURCE + /* keep gethostby*() from stripping the local domain name */ + set_domain_trim_off(); +#endif /* _CONVEX_SOURCE */ +#ifdef __QNX__ + /* + ** Due to QNX's network distributed nature, you can target a tcpip + ** stack on a different node in the qnx network; this patch lets + ** this feature work. The __sock_locate() must be done before the + ** environment is clear. + */ + __sock_locate(); +#endif /* __QNX__ */ +#if SECUREWARE || defined(_SCO_unix_) + set_auth_parameters(argc, argv); + +# ifdef _SCO_unix_ + /* + ** This is required for highest security levels (the kernel + ** won't let it call set*uid() or run setuid binaries without + ** it). It may be necessary on other SECUREWARE systems. + */ + + if (getluid() == -1) + setluid(0); +# endif /* _SCO_unix_ */ +#endif /* SECUREWARE || defined(_SCO_unix_) */ + +#ifdef VENDOR_DEFAULT + VendorCode = VENDOR_DEFAULT; +#else /* VENDOR_DEFAULT */ + VendorCode = VENDOR_BERKELEY; +#endif /* VENDOR_DEFAULT */ +} + /* +** 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 */ +#define LA_IRIX6 11 /* special IRIX 6.2 implementation */ +#define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */ +#define LA_DEVSHORT 13 /* read short from a device */ +#define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */ + +/* do guesses based on general OS type */ +#ifndef LA_TYPE +# define LA_TYPE LA_ZERO +#endif /* ! LA_TYPE */ + +#ifndef FSHIFT +# if defined(unixpc) +# define FSHIFT 5 +# endif /* defined(unixpc) */ + +# if defined(__alpha) || defined(IRIX) +# define FSHIFT 10 +# endif /* defined(__alpha) || defined(IRIX) */ + +#endif /* ! FSHIFT */ + +#ifndef FSHIFT +# define FSHIFT 8 +#endif /* ! FSHIFT */ + +#ifndef FSCALE +# define FSCALE (1 << FSHIFT) +#endif /* ! FSCALE */ + +#ifndef LA_AVENRUN +# ifdef SYSTEM5 +# define LA_AVENRUN "avenrun" +# else /* SYSTEM5 */ +# define LA_AVENRUN "_avenrun" +# endif /* SYSTEM5 */ +#endif /* ! LA_AVENRUN */ + +/* _PATH_KMEM should be defined in */ +#ifndef _PATH_KMEM +# define _PATH_KMEM "/dev/kmem" +#endif /* ! _PATH_KMEM */ + +#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) + +# include + +/* _PATH_UNIX should be defined in */ +# ifndef _PATH_UNIX +# if defined(SYSTEM5) +# define _PATH_UNIX "/unix" +# else /* defined(SYSTEM5) */ +# define _PATH_UNIX "/vmunix" +# endif /* defined(SYSTEM5) */ +# endif /* ! _PATH_UNIX */ + +# ifdef _AUX_SOURCE +struct nlist Nl[2]; +# else /* _AUX_SOURCE */ +struct nlist Nl[] = +{ + { LA_AVENRUN }, + { 0 }, +}; +# endif /* _AUX_SOURCE */ +# define X_AVENRUN 0 + +static int +getla() +{ + static int kmem = -1; +# if LA_TYPE == LA_INT + long avenrun[3]; +# else /* LA_TYPE == LA_INT */ +# if LA_TYPE == LA_SHORT + short avenrun[3]; +# else /* LA_TYPE == LA_SHORT */ + double avenrun[3]; +# endif /* LA_TYPE == LA_SHORT */ +# endif /* LA_TYPE == LA_INT */ + extern int errno; + extern off_t lseek(); + + if (kmem < 0) + { +# ifdef _AUX_SOURCE + (void) strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN, + sizeof Nl[X_AVENRUN].n_name); + Nl[1].n_name[0] = '\0'; +# endif /* _AUX_SOURCE */ + +# if defined(_AIX3) || defined(_AIX4) + if (knlist(Nl, 1, sizeof Nl[0]) < 0) +# else /* defined(_AIX3) || defined(_AIX4) */ + if (nlist(_PATH_UNIX, Nl) < 0) +# endif /* defined(_AIX3) || defined(_AIX4) */ + { + if (tTd(3, 1)) + dprintf("getla: nlist(%s): %s\n", _PATH_UNIX, + errstring(errno)); + return -1; + } + if (Nl[X_AVENRUN].n_value == 0) + { + if (tTd(3, 1)) + dprintf("getla: nlist(%s, %s) ==> 0\n", + _PATH_UNIX, LA_AVENRUN); + return -1; + } +# ifdef NAMELISTMASK + Nl[X_AVENRUN].n_value &= NAMELISTMASK; +# endif /* NAMELISTMASK */ + + kmem = open(_PATH_KMEM, 0, 0); + if (kmem < 0) + { + if (tTd(3, 1)) + dprintf("getla: open(/dev/kmem): %s\n", + errstring(errno)); + return -1; + } + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); + } + if (tTd(3, 20)) + dprintf("getla: symbol address = %#lx\n", + (u_long) 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)) + dprintf("getla: lseek or read: %s\n", + errstring(errno)); + return -1; + } +# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) + if (tTd(3, 5)) + { +# if LA_TYPE == LA_SHORT + dprintf("getla: avenrun = %d", avenrun[0]); + if (tTd(3, 15)) + dprintf(", %d, %d", avenrun[1], avenrun[2]); +# else /* LA_TYPE == LA_SHORT */ + dprintf("getla: avenrun = %ld", avenrun[0]); + if (tTd(3, 15)) + dprintf(", %ld, %ld", avenrun[1], avenrun[2]); +# endif /* LA_TYPE == LA_SHORT */ + dprintf("\n"); + } + if (tTd(3, 1)) + dprintf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); +# else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ + if (tTd(3, 5)) + { + dprintf("getla: avenrun = %g", avenrun[0]); + if (tTd(3, 15)) + dprintf(", %g, %g", avenrun[1], avenrun[2]); + dprintf("\n"); + } + if (tTd(3, 1)) + dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); + return ((int) (avenrun[0] + 0.5)); +# endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ +} + +#endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) */ + +#if LA_TYPE == LA_READKSYM + +# include + +static int +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)) + dprintf("getla: open(/dev/kmem): %s\n", + errstring(errno)); + return -1; + } + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); + } + 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)) + dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n", + errstring(errno)); + return -1; + } + if (tTd(3, 5)) + { + dprintf("getla: avenrun = %d", avenrun[0]); + if (tTd(3, 15)) + dprintf(", %d, %d", avenrun[1], avenrun[2]); + dprintf("\n"); + } + if (tTd(3, 1)) + dprintf("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 + +static 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)) + dprintf("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 +# include + +static 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)) + dprintf("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 + +static int +getla() +{ + double avenrun[3]; + + if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) + { + if (tTd(3, 1)) + dprintf("getla: getloadavg failed: %s", + errstring(errno)); + return -1; + } + if (tTd(3, 1)) + dprintf("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 +# else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ +# include +# endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ + +static int +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) + { + if (tTd(3, 1)) + dprintf("getla: processor_set_default failed: %s", + errstring(errno)); + 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) + { + if (tTd(3, 1)) + dprintf("getla: processor_set_info failed: %s", + errstring(errno)); + return -1; + } + if (tTd(3, 1)) + dprintf("getla: %d\n", + (int) ((info.load_average + (LOAD_SCALE / 2)) / + LOAD_SCALE)); + 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 /* ! _PATH_LOADAVG */ + +static int +getla() +{ + double avenrun; + register int result; + FILE *fp; + + fp = fopen(_PATH_LOADAVG, "r"); + if (fp == NULL) + { + if (tTd(3, 1)) + dprintf("getla: fopen(%s): %s\n", + _PATH_LOADAVG, errstring(errno)); + return -1; + } + result = fscanf(fp, "%lf", &avenrun); + (void) fclose(fp); + if (result != 1) + { + if (tTd(3, 1)) + dprintf("getla: fscanf() = %d: %s\n", + result, errstring(errno)); + return -1; + } + + if (tTd(3, 1)) + dprintf("getla(): %.2f\n", avenrun); + + return ((int) (avenrun + 0.5)); +} + +#endif /* LA_TYPE == LA_PROCSTR */ + +#if LA_TYPE == LA_IRIX6 + +# include + +int getla(void) +{ + static int kmem = -1; + int avenrun[3]; + + if (kmem < 0) + { + kmem = open(_PATH_KMEM, 0, 0); + if (kmem < 0) + { + if (tTd(3, 1)) + dprintf("getla: open(%s): %s\n", _PATH_KMEM, + errstring(errno)); + return -1; + } + (void) fcntl(kmem, F_SETFD, FD_CLOEXEC); + } + + if (lseek(kmem, (sysmp(MP_KERNADDR, MPKA_AVENRUN) & 0x7fffffff), SEEK_SET) == -1 || + read(kmem, (char *)avenrun, sizeof(avenrun)) < sizeof(avenrun)) + { + if (tTd(3, 1)) + dprintf("getla: lseek or read: %s\n", + errstring(errno)); + return -1; + } + if (tTd(3, 5)) + { + dprintf("getla: avenrun = %ld", (long int) avenrun[0]); + if (tTd(3, 15)) + dprintf(", %ld, %ld", + (long int) avenrun[1], (long int) avenrun[2]); + dprintf("\n"); + } + + if (tTd(3, 1)) + dprintf("getla: %d\n", + (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); + +} +#endif /* LA_TYPE == LA_IRIX6 */ + +#if LA_TYPE == LA_KSTAT + +# include + +static int +getla() +{ + static kstat_ctl_t *kc = NULL; + static kstat_t *ksp = NULL; + kstat_named_t *ksn; + int la; + + if (kc == NULL) /* if not initialized before */ + kc = kstat_open(); + if (kc == NULL) + { + if (tTd(3, 1)) + dprintf("getla: kstat_open(): %s\n", + errstring(errno)); + return -1; + } + if (ksp == NULL) + ksp = kstat_lookup(kc, "unix", 0, "system_misc"); + if (ksp == NULL) + { + if (tTd(3, 1)) + dprintf("getla: kstat_lookup(): %s\n", + errstring(errno)); + return -1; + } + if (kstat_read(kc, ksp, NULL) < 0) + { + if (tTd(3, 1)) + dprintf("getla: kstat_read(): %s\n", + errstring(errno)); + return -1; + } + ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min"); + la = ((double)ksn->value.ul + FSCALE/2) / FSCALE; + /* kstat_close(kc); /o do not close for fast access */ + return la; +} + +#endif /* LA_TYPE == LA_KSTAT */ + +#if LA_TYPE == LA_DEVSHORT + +/* +** Read /dev/table/avenrun for the load average. This should contain +** three shorts for the 1, 5, and 15 minute loads. We only read the +** first, since that's all we care about. +** +** Intended for SCO OpenServer 5. +*/ + +# ifndef _PATH_AVENRUN +# define _PATH_AVENRUN "/dev/table/avenrun" +# endif /* ! _PATH_AVENRUN */ + +static int +getla() +{ + static int afd = -1; + short avenrun; + int loadav; + int r; + + errno = EBADF; + + if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1) + { + if (errno != EBADF) + return -1; + afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC); + if (afd < 0) + { + sm_syslog(LOG_ERR, NOQID, + "can't open %s: %m", + _PATH_AVENRUN); + return -1; + } + } + + r = read(afd, &avenrun, sizeof avenrun); + + if (tTd(3, 5)) + dprintf("getla: avenrun = %d\n", avenrun); + loadav = (int) (avenrun + FSCALE/2) >> FSHIFT; + if (tTd(3, 1)) + dprintf("getla: %d\n", loadav); + return loadav; +} + +#endif /* LA_TYPE == LA_DEVSHORT */ + +#if LA_TYPE == LA_ALPHAOSF +struct rtentry; +struct mbuf; +# include + +int getla() +{ + int ave = 0; + struct tbl_loadavg tab; + + if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1) + { + if (tTd(3, 1)) + dprintf("getla: table %s\n", errstring(errno)); + return -1; + } + + if (tTd(3, 1)) + dprintf("getla: scale = %d\n", tab.tl_lscale); + + if (tab.tl_lscale) + ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) / + tab.tl_lscale); + else + ave = (int) (tab.tl_avenrun.d[2] + 0.5); + + if (tTd(3, 1)) + dprintf("getla: %d\n", ave); + + return ave; +} + +#endif /* LA_TYPE == LA_ALPHAOSF */ + +#if LA_TYPE == LA_ZERO + +static int +getla() +{ + if (tTd(3, 1)) + dprintf("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[] = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; +#endif /* ! lint */ + +#ifdef apollo +# undef volatile +# include + +/* 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 */ + /* +** SM_GETLA -- get the current load average and set macro +** +** Parameters: +** e -- the envelope for the load average macro. +** +** Returns: +** The current load average as an integer. +** +** Side Effects: +** Sets the load average macro ({load_avg}) if +** envelope e is not NULL. +*/ + +int +sm_getla(e) + ENVELOPE *e; +{ + register int la; + + la = getla(); + if (e != NULL) + { + char labuf[8]; + + snprintf(labuf, sizeof labuf, "%d", CurrentLA); + define(macid("{load_avg}", NULL), newstr(labuf), e); + } + return la; +} + + /* +** 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. +** ct -- 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. +*/ + +/* ARGSUSED1 */ +bool +shouldqueue(pri, ct) + long pri; + time_t ct; +{ + bool rval; + + if (tTd(3, 30)) + dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ", + CurrentLA, pri); + if (CurrentLA < QueueLA) + { + if (tTd(3, 30)) + dprintf("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)) + dprintf("TRUE (CurrentLA >= RefuseLA)\n"); + return TRUE; + } +#endif /* 0 */ + rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); + if (tTd(3, 30)) + dprintf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); + return rval; +} + /* +** REFUSECONNECTIONS -- decide if connections should be refused +** +** Parameters: +** name -- daemon name (for error messages only) +** e -- the current envelope. +** d -- number of daemon +** +** 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(name, e, d) + char *name; + ENVELOPE *e; + int d; +{ + time_t now; + static time_t lastconn[MAXDAEMONS]; + static int conncnt[MAXDAEMONS]; + +#ifdef XLA + if (!xla_smtp_ok()) + return TRUE; +#endif /* XLA */ + + now = curtime(); + if (now != lastconn[d]) + { + lastconn[d] = now; + conncnt[d] = 0; + } + else if (conncnt[d]++ > ConnRateThrottle && ConnRateThrottle > 0) + { + /* sleep to flatten out connection load */ + sm_setproctitle(TRUE, e, "deferring connections on daemon %s: %d per second", + name, ConnRateThrottle); + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "deferring connections on daemon %s: %d per second", + name, ConnRateThrottle); + (void) sleep(1); + } + + CurrentLA = getla(); + if (RefuseLA > 0 && CurrentLA >= RefuseLA) + { + sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: load average: %d", + name, CurrentLA); + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "rejecting connections on daemon %s: load average: %d", + name, CurrentLA); + return TRUE; + } + + if (MaxChildren > 0 && CurChildren >= MaxChildren) + { + proc_list_probe(); + if (CurChildren >= MaxChildren) + { + sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: %d children, max %d", + name, CurChildren, MaxChildren); + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "rejecting connections on daemon %s: %d children, max %d", + name, CurChildren, MaxChildren); + return TRUE; + } + } + + return FALSE; +} + /* +** 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 */ +#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ + +#ifndef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +#endif /* ! SPT_TYPE */ + +#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN + +# if SPT_TYPE == SPT_PSTAT +# include +# endif /* SPT_TYPE == SPT_PSTAT */ +# if SPT_TYPE == SPT_PSSTRINGS +# include +# include +# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ +# undef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +# else /* ! PS_STRINGS */ +# ifndef NKPDE /* FreeBSD 2.0 */ +# define NKPDE 63 +typedef unsigned int *pt_entry_t; +# endif /* ! NKPDE */ +# endif /* ! PS_STRINGS */ +# endif /* SPT_TYPE == SPT_PSSTRINGS */ + +# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV +# define SETPROC_STATIC static +# else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ +# define SETPROC_STATIC +# endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */ + +# if SPT_TYPE == SPT_SYSMIPS +# include +# include +# endif /* SPT_TYPE == SPT_SYSMIPS */ + +# if SPT_TYPE == SPT_SCO +# include +# include +# include +# include +# if PSARGSZ > MAXLINE +# define SPT_BUFSIZE PSARGSZ +# endif /* PSARGSZ > MAXLINE */ +# endif /* SPT_TYPE == SPT_SCO */ + +# ifndef SPT_PADCHAR +# define SPT_PADCHAR ' ' +# endif /* ! SPT_PADCHAR */ + +#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ + +#ifndef SPT_BUFSIZE +# define SPT_BUFSIZE MAXLINE +#endif /* ! SPT_BUFSIZE */ + +/* +** Pointers for setproctitle. +** This allows "ps" listings to give more useful information. +*/ + +static char **Argv = NULL; /* pointer to argument vector */ +static char *LastArgv = NULL; /* end of argv */ +#if SPT_TYPE != SPT_BUILTIN +static void setproctitle __P((const char *, ...)); +#endif /* SPT_TYPE != SPT_BUILTIN */ + +void +initsetproctitle(argc, argv, envp) + int argc; + char **argv; + char **envp; +{ + register int i, envpsize = 0; + extern char **environ; + + /* + ** Move the environment so setproctitle can use the space at + ** the top of memory. + */ + + for (i = 0; envp[i] != NULL; i++) + envpsize += strlen(envp[i]) + 1; + 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; + + /* + ** Determine how much space we can use for setproctitle. + ** Use all contiguous argv and envp pointers starting at argv[0] + */ + for (i = 0; i < argc; i++) + { + if (i == 0 || LastArgv + 1 == argv[i]) + LastArgv = argv[i] + strlen(argv[i]); + } + for (i = 0; LastArgv != NULL && envp[i] != NULL; i++) + { + if (LastArgv + 1 == envp[i]) + LastArgv = envp[i] + strlen(envp[i]); + } +} + +#if SPT_TYPE != SPT_BUILTIN + +/*VARARGS1*/ +static void +# ifdef __STDC__ +setproctitle(const char *fmt, ...) +# else /* __STDC__ */ +setproctitle(fmt, va_alist) + const char *fmt; + va_dcl +# endif /* __STDC__ */ +{ +# if SPT_TYPE != SPT_NONE + register int i; + register char *p; + SETPROC_STATIC char buf[SPT_BUFSIZE]; + VA_LOCAL_DECL +# if SPT_TYPE == SPT_PSTAT + union pstun pst; +# endif /* SPT_TYPE == SPT_PSTAT */ +# if SPT_TYPE == SPT_SCO + off_t seek_off; + static int kmem = -1; + static int kmempid = -1; + struct user u; +# endif /* SPT_TYPE == SPT_SCO */ + + p = buf; + + /* print sendmail: heading for grep */ + (void) strlcpy(p, "sendmail: ", SPACELEFT(buf, p)); + p += strlen(p); + + /* print the argument string */ + VA_START(fmt); + (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap); + VA_END; + + i = strlen(buf); + +# if SPT_TYPE == SPT_PSTAT + pst.pst_command = buf; + pstat(PSTAT_SETCMD, pst, i, 0, 0); +# endif /* SPT_TYPE == SPT_PSTAT */ +# if SPT_TYPE == SPT_PSSTRINGS + PS_STRINGS->ps_nargvstr = 1; + PS_STRINGS->ps_argvstr = buf; +# endif /* SPT_TYPE == SPT_PSSTRINGS */ +# if SPT_TYPE == SPT_SYSMIPS + sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); +# endif /* SPT_TYPE == SPT_SYSMIPS */ +# 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, FD_CLOEXEC); + kmempid = getpid(); + } + buf[PSARGSZ - 1] = '\0'; + seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; + if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off) + (void) write(kmem, buf, PSARGSZ); +# endif /* SPT_TYPE == SPT_SCO */ +# if SPT_TYPE == SPT_REUSEARGV + if (LastArgv == NULL) + return; + + if (i > LastArgv - Argv[0] - 2) + { + i = LastArgv - Argv[0] - 2; + buf[i] = '\0'; + } + (void) strlcpy(Argv[0], buf, i + 1); + p = &Argv[0][i]; + while (p < LastArgv) + *p++ = SPT_PADCHAR; + Argv[1] = NULL; +# endif /* SPT_TYPE == SPT_REUSEARGV */ +# if SPT_TYPE == SPT_CHANGEARGV + Argv[0] = buf; + Argv[1] = 0; +# endif /* SPT_TYPE == SPT_CHANGEARGV */ +# endif /* SPT_TYPE != SPT_NONE */ +} + +#endif /* SPT_TYPE != SPT_BUILTIN */ + /* +** SM_SETPROCTITLE -- set process task and set process title for ps +** +** Possibly set process status and call setproctitle() to +** change the ps display. +** +** Parameters: +** status -- whether or not to store as process status +** e -- the current envelope. +** fmt -- a printf style format string. +** a, b, c -- possible parameters to fmt. +** +** Returns: +** none. +*/ + +/*VARARGS2*/ +void +#ifdef __STDC__ +sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...) +#else /* __STDC__ */ +sm_setproctitle(status, e, fmt, va_alist) + bool status; + ENVELOPE *e; + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + char buf[SPT_BUFSIZE]; + VA_LOCAL_DECL + + /* print the argument string */ + VA_START(fmt); + (void) vsnprintf(buf, sizeof buf, fmt, ap); + VA_END; + + if (status) + proc_list_set(getpid(), buf); + + if (ProcTitlePrefix != NULL) + { + char prefix[SPT_BUFSIZE]; + + expand(ProcTitlePrefix, prefix, sizeof prefix, e); + setproctitle("%s: %s", prefix, buf); + } + else + setproctitle("%s", buf); +} + /* +** 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) + pid_t pid; +{ +#ifdef WAITUNION + union wait st; +#else /* WAITUNION */ + auto int st; +#endif /* WAITUNION */ + pid_t i; +#if defined(ISC_UNIX) || defined(_SCO_unix_) + int savesig; +#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ + + do + { + errno = 0; +#if defined(ISC_UNIX) || defined(_SCO_unix_) + savesig = releasesignal(SIGCHLD); +#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ + i = wait(&st); +#if defined(ISC_UNIX) || defined(_SCO_unix_) + if (savesig > 0) + blocksignal(SIGCHLD); +#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ + if (i > 0) + (void) proc_list_drop(i); + } while ((i >= 0 || errno == EINTR) && i != pid); + if (i < 0) + return -1; +#ifdef WAITUNION + return st.w_status; +#else /* WAITUNION */ + return st; +#endif /* WAITUNION */ +} + /* +** 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. +** Control socket exits may restart/shutdown daemon. +*/ + +/* ARGSUSED0 */ +SIGFUNC_DECL +reapchild(sig) + int sig; +{ + int save_errno = errno; + int st; + pid_t pid; +#if HASWAITPID + auto int status; + int count; + + count = 0; + while ((pid = waitpid(-1, &status, WNOHANG)) > 0) + { + st = status; + if (count++ > 1000) + { + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "reapchild: waitpid loop: pid=%d, status=%x", + pid, status); + break; + } +#else /* HASWAITPID */ +# ifdef WNOHANG + union wait status; + + while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) + { + st = status.w_status; +# else /* WNOHANG */ + auto int status; + + /* + ** Catch one zombie -- we will be re-invoked (we hope) if there + ** are more. Unreliable signals probably break this, but this + ** is the "old system" situation -- waitpid or wait3 are to be + ** strongly preferred. + */ + + if ((pid = wait(&status)) > 0) + { + st = status; +# endif /* WNOHANG */ +#endif /* HASWAITPID */ + /* Drop PID and check if it was a control socket child */ + if (proc_list_drop(pid) == PROC_CONTROL && + WIFEXITED(st)) + { + /* if so, see if we need to restart or shutdown */ + if (WEXITSTATUS(st) == EX_RESTART) + { + /* emulate a SIGHUP restart */ + sighup(0); + /* NOTREACHED */ + } + else if (WEXITSTATUS(st) == EX_SHUTDOWN) + { + /* emulate a SIGTERM shutdown */ + intsig(0); + /* NOTREACHED */ + } + } + } +#ifdef SYS5SIGNALS + (void) setsignal(SIGCHLD, reapchild); +#endif /* SYS5SIGNALS */ + errno = save_errno; + return SIGFUNC_RETURN; +} + /* +** 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. +*/ + +#if 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 bool first = TRUE; + extern char **environ; + + /* + * find out how much of str to match when searching + * for a string to replace. + */ + if ((tmp = strchr(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 = FALSE; + (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 /* NEEDPUTENV == 2 */ + +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; + memmove(nbuf, env, l); + nbuf[l] = '\0'; + return setenv(nbuf, ++p, 1); +} + +# endif /* NEEDPUTENV == 2 */ +#endif /* NEEDPUTENV */ + /* +** 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. +*/ + +#if !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 /* !HASUNSETENV */ + /* +** 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 +#endif /* SOLARIS */ + +int +getdtsize() +{ +#ifdef RLIMIT_NOFILE + struct rlimit rl; + + if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) + return rl.rlim_cur; +#endif /* RLIMIT_NOFILE */ + +#if HASGETDTABLESIZE + return getdtablesize(); +#else /* HASGETDTABLESIZE */ +# ifdef _SC_OPEN_MAX + return sysconf(_SC_OPEN_MAX); +# else /* _SC_OPEN_MAX */ + return NOFILE; +# endif /* _SC_OPEN_MAX */ +#endif /* HASGETDTABLESIZE */ +} + /* +** UNAME -- get the UUCP name of this system. +*/ + +#if !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; + } + +# if 0 + /* + ** 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 /* 0 */ + + return -1; +} +#endif /* !HASUNAME */ + /* +** INITGROUPS -- initialize groups +** +** Stub implementation for System V style systems +*/ + +#if !HASINITGROUPS + +initgroups(name, basegid) + char *name; + int basegid; +{ + return 0; +} + +#endif /* !HASINITGROUPS */ + /* +** SETGROUPS -- set group list +** +** Stub implementation for systems that don't have group lists +*/ + +#ifndef NGROUPS_MAX + +int +setgroups(ngroups, grouplist) + int ngroups; + GIDSET_T grouplist[]; +{ + return 0; +} + +#endif /* ! NGROUPS_MAX */ + /* +** SETSID -- set session id (for non-POSIX systems) +*/ + +#if !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 /* SYS5SETPGRP */ + return setpgid(0, getpid()); +# endif /* SYS5SETPGRP */ +} + +#endif /* !HASSETSID */ + /* +** FSYNC -- dummy fsync +*/ + +#if NEEDFSYNC + +fsync(fd) + int fd; +{ +# ifdef O_SYNC + return fcntl(fd, F_SETFL, O_SYNC); +# else /* O_SYNC */ + /* nothing we can do */ + return 0; +# endif /* O_SYNC */ +} + +#endif /* NEEDFSYNC */ + /* +** 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 /* DGUX_5_4_2 */ + /* +** GETOPT -- for old systems or systems with bogus implementations +*/ + +#if 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 /* defined(LIBC_SCCS) && !defined(lint) */ + +/* + * get option letter from argument vector + */ +# ifdef _CONVEX_SOURCE +extern int optind, opterr, optopt; +extern char *optarg; +# else /* _CONVEX_SOURCE */ +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 /* _CONVEX_SOURCE */ + +# define BADCH (int)'?' +# define EMSG "" +# define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \ + fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);} + +int +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 = NULL; /* option letter list index */ + + if (atend) { + atend = 0; + place = EMSG; + } + if(!*place) { /* update scanning pointer */ + if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) { + atend++; + return -1; + } + if (*place == '-') { /* found "--" */ + ++optind; + atend++; + return -1; + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) { + if (!*place) ++optind; + tell(": illegal option -- "); + } + if (oli && *++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 /* NEEDGETOPT */ + /* +** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version +*/ + +#if 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 /* NEEDVPRINTF */ + /* +** 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 /* ! _PATH_SHELLS */ + +# if defined(_AIX3) || defined(_AIX4) +# include +# if _AIX4 >= 40200 +# include +# endif /* _AIX4 >= 40200 */ +# include +# endif /* defined(_AIX3) || defined(_AIX4) */ + +static 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 /* V4FS */ + "/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 /* V4FS */ +# endif /* __hpux */ +# if defined(_AIX3) || defined(_AIX4) + "/bin/ksh", /* Korn shell */ + "/usr/bin/ksh", + "/bin/tsh", /* trusted shell */ + "/usr/bin/tsh", + "/bin/bsh", /* Bourne shell */ + "/usr/bin/bsh", +# endif /* defined(_AIX3) || defined(_AIX4) */ +# if defined(__svr4__) || defined(__svr5__) + "/bin/ksh", /* Korn shell */ + "/usr/bin/ksh", +# endif /* defined(__svr4__) || defined(__svr5__) */ +# ifdef sgi + "/sbin/sh", /* SGI's shells really live in /sbin */ + "/sbin/csh", + "/bin/ksh", /* Korn shell */ + "/sbin/ksh", + "/usr/bin/ksh", + "/bin/tcsh", /* Extended csh */ + "/usr/bin/tcsh", +# endif /* sgi */ + NULL +}; + +#endif /* !HASGETUSERSHELL */ + +#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 /* HASGETUSERSHELL */ +# if USEGETCONFATTR + auto char *v; +# endif /* USEGETCONFATTR */ + register FILE *shellf; + char buf[MAXLINE]; + + if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || + ConfigLevel <= 1) + 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 /* USEGETCONFATTR */ + + shellf = fopen(_PATH_SHELLS, "r"); + if (shellf == NULL) + { + /* no /etc/shells; see if it is one of the std shells */ + char **d; + + if (errno != ENOENT && LogLevel > 3) + sm_syslog(LOG_ERR, NOQID, + "usershellok: cannot open %s: %s", + _PATH_SHELLS, errstring(errno)); + + 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 != '#' && !(isascii(*p) && isspace(*p))) + p++; + *p = '\0'; + if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0) + { + (void) fclose(shellf); + return TRUE; + } + } + (void) fclose(shellf); + return FALSE; +#endif /* HASGETUSERSHELL */ +} + /* +** 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 implementation */ +#define SFS_MOUNT 4 /* use implementation */ +#define SFS_STATFS 5 /* use implementation */ +#define SFS_STATVFS 6 /* use implementation */ + +#ifndef SFS_TYPE +# define SFS_TYPE SFS_NONE +#endif /* ! SFS_TYPE */ + +#if SFS_TYPE == SFS_USTAT +# include +#endif /* SFS_TYPE == SFS_USTAT */ +#if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS +# include +#endif /* SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS */ +#if SFS_TYPE == SFS_VFS +# include +#endif /* SFS_TYPE == SFS_VFS */ +#if SFS_TYPE == SFS_MOUNT +# include +#endif /* SFS_TYPE == SFS_MOUNT */ +#if SFS_TYPE == SFS_STATVFS +# include +#endif /* SFS_TYPE == SFS_STATVFS */ + +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 /* SFS_TYPE == SFS_USTAT */ +# if defined(ultrix) + struct fs_data fs; +# define SFS_BAVAIL fd_bfreen +# define FSBLOCKSIZE 1024L +# else /* defined(ultrix) */ +# if SFS_TYPE == SFS_STATVFS + struct statvfs fs; +# define FSBLOCKSIZE fs.f_frsize +# else /* SFS_TYPE == SFS_STATVFS */ + struct statfs fs; +# define FSBLOCKSIZE fs.f_bsize +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_USTAT */ +# ifndef SFS_BAVAIL +# define SFS_BAVAIL f_bavail +# endif /* ! SFS_BAVAIL */ + +# if SFS_TYPE == SFS_USTAT + if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) +# else /* SFS_TYPE == SFS_USTAT */ +# if SFS_TYPE == SFS_4ARGS + if (statfs(dir, &fs, sizeof fs, 0) == 0) +# else /* SFS_TYPE == SFS_4ARGS */ +# if SFS_TYPE == SFS_STATVFS + if (statvfs(dir, &fs) == 0) +# else /* SFS_TYPE == SFS_STATVFS */ +# if defined(ultrix) + if (statfs(dir, &fs) > 0) +# else /* defined(ultrix) */ + if (statfs(dir, &fs) == 0) +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* SFS_TYPE == SFS_4ARGS */ +# endif /* SFS_TYPE == SFS_USTAT */ + { + if (bsize != NULL) + *bsize = FSBLOCKSIZE; + if (fs.SFS_BAVAIL <= 0) + return 0; + else if (fs.SFS_BAVAIL > LONG_MAX) + return (long) LONG_MAX; + else + return (long) fs.SFS_BAVAIL; + } +#endif /* SFS_TYPE != SFS_NONE */ + 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. +** log -- log message? +** +** Returns: +** TRUE if there is enough space. +** FALSE otherwise. +*/ + +bool +enoughdiskspace(msize, log) + long msize; + bool log; +{ + long bfree, bsize; + + if (MinBlocksFree <= 0 && msize <= 0) + { + if (tTd(4, 80)) + dprintf("enoughdiskspace: no threshold\n"); + return TRUE; + } + + if ((bfree = freediskspace(QueueDir, &bsize)) >= 0) + { + if (tTd(4, 80)) + dprintf("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) + { + if (log && LogLevel > 0) + sm_syslog(LOG_ALERT, CurEnv->e_id, + "low on space (have %ld, %s needs %ld in %s)", + bfree, + CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, + msize, QueueDir); + return FALSE; + } + } + else if (tTd(4, 80)) + dprintf("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 /* ETIMEDOUT */ +#ifdef ESTALE + case ESTALE: /* Stale NFS file handle */ +#endif /* ESTALE */ +#ifdef ENETDOWN + case ENETDOWN: /* Network is down */ +#endif /* ENETDOWN */ +#ifdef ENETUNREACH + case ENETUNREACH: /* Network is unreachable */ +#endif /* ENETUNREACH */ +#ifdef ENETRESET + case ENETRESET: /* Network dropped connection on reset */ +#endif /* ENETRESET */ +#ifdef ECONNABORTED + case ECONNABORTED: /* Software caused connection abort */ +#endif /* ECONNABORTED */ +#ifdef ECONNRESET + case ECONNRESET: /* Connection reset by peer */ +#endif /* ECONNRESET */ +#ifdef ENOBUFS + case ENOBUFS: /* No buffer space available */ +#endif /* ENOBUFS */ +#ifdef ESHUTDOWN + case ESHUTDOWN: /* Can't send after socket shutdown */ +#endif /* ESHUTDOWN */ +#ifdef ECONNREFUSED + case ECONNREFUSED: /* Connection refused */ +#endif /* ECONNREFUSED */ +#ifdef EHOSTDOWN + case EHOSTDOWN: /* Host is down */ +#endif /* EHOSTDOWN */ +#ifdef EHOSTUNREACH + case EHOSTUNREACH: /* No route to host */ +#endif /* EHOSTUNREACH */ +#ifdef EDQUOT + case EDQUOT: /* Disc quota exceeded */ +#endif /* EDQUOT */ +#ifdef EPROCLIM + case EPROCLIM: /* Too many processes */ +#endif /* EPROCLIM */ +#ifdef EUSERS + case EUSERS: /* Too many users */ +#endif /* EUSERS */ +#ifdef EDEADLK + case EDEADLK: /* Resource deadlock avoided */ +#endif /* EDEADLK */ +#ifdef EISCONN + case EISCONN: /* Socket already connected */ +#endif /* EISCONN */ +#ifdef EINPROGRESS + case EINPROGRESS: /* Operation now in progress */ +#endif /* EINPROGRESS */ +#ifdef EALREADY + case EALREADY: /* Operation already in progress */ +#endif /* EALREADY */ +#ifdef EADDRINUSE + case EADDRINUSE: /* Address already in use */ +#endif /* EADDRINUSE */ +#ifdef EADDRNOTAVAIL + case EADDRNOTAVAIL: /* Can't assign requested address */ +#endif /* EADDRNOTAVAIL */ +#ifdef ETXTBSY + case ETXTBSY: /* (Apollo) file locked */ +#endif /* ETXTBSY */ +#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) + case ENOSR: /* Out of streams resources */ +#endif /* defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) */ +#ifdef ENOLCK + case ENOLCK: /* No locks available */ +#endif /* ENOLCK */ + case E_SM_OPENTIMEOUT: /* 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; +{ + int i; + int save_errno; +#if !HASFLOCK + int action; + struct flock lfd; + + if (ext == NULL) + ext = ""; + + memset(&lfd, '\0', 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)) + dprintf("lockfile(%s%s, action=%d, type=%d): ", + filename, ext, action, lfd.l_type); + + while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) + continue; + if (i >= 0) + { + if (tTd(55, 60)) + dprintf("SUCCESS\n"); + return TRUE; + } + save_errno = errno; + + if (tTd(55, 60)) + dprintf("(%s) ", errstring(save_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 (save_errno == EINVAL) + { + if (tTd(55, 60)) + dprintf("SUCCESS\n"); + return TRUE; + } + + if (!bitset(LOCK_NB, type) || + (save_errno != EACCES && save_errno != EAGAIN)) + { + int omode = -1; +# ifdef F_GETFL + (void) fcntl(fd, F_GETFL, &omode); + errno = save_errno; +# endif /* F_GETFL */ + syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", + filename, ext, fd, type, omode, geteuid()); + dumpfd(fd, TRUE, TRUE); + } +#else /* !HASFLOCK */ + if (ext == NULL) + ext = ""; + + if (tTd(55, 60)) + dprintf("lockfile(%s%s, type=%o): ", filename, ext, type); + + while ((i = flock(fd, type)) < 0 && errno == EINTR) + continue; + if (i >= 0) + { + if (tTd(55, 60)) + dprintf("SUCCESS\n"); + return TRUE; + } + save_errno = errno; + + if (tTd(55, 60)) + dprintf("(%s) ", errstring(save_errno)); + + if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) + { + int omode = -1; +# ifdef F_GETFL + (void) fcntl(fd, F_GETFL, &omode); + errno = save_errno; +# endif /* F_GETFL */ + syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", + filename, ext, fd, type, omode, geteuid()); + dumpfd(fd, TRUE, TRUE); + } +#endif /* !HASFLOCK */ + if (tTd(55, 60)) + dprintf("FAIL\n"); + errno = save_errno; + return FALSE; +} + /* +** CHOWNSAFE -- tell if chown is "safe" (executable only by root) +** +** Unfortunately, given that we can't predict other systems on which +** a remote mounted (NFS) filesystem will be mounted, the answer is +** almost always that this is unsafe. +** +** Note also that many operating systems have non-compliant +** implementations of the _POSIX_CHOWN_RESTRICTED variable and the +** fpathconf() routine. According to IEEE 1003.1-1990, if +** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then +** no non-root process can give away the file. However, vendors +** don't take NFS into account, so a comfortable value of +** _POSIX_CHOWN_RESTRICTED tells us nothing. +** +** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf() +** even on files where chown is not restricted. Many systems get +** this wrong on NFS-based filesystems (that is, they say that chown +** is restricted [safe] on NFS filesystems where it may not be, since +** other systems can access the same filesystem and do file giveaway; +** only the NFS server knows for sure!) Hence, it is important to +** get the value of SAFENFSPATHCONF correct -- it should be defined +** _only_ after testing (see test/t_pathconf.c) a system on an unsafe +** NFS-based filesystem to ensure that you can get meaningful results. +** If in doubt, assume unsafe! +** +** You may also need to tweak IS_SAFE_CHOWN -- it should be a +** condition indicating whether the return from pathconf indicates +** that chown is safe (typically either > 0 or >= 0 -- there isn't +** even any agreement about whether a zero return means that a file +** is or is not safe). It defaults to "> 0". +** +** If the parent directory is safe (writable only by owner back +** to the root) then we can relax slightly and trust fpathconf +** in more circumstances. This is really a crock -- if this is an +** NFS mounted filesystem then we really know nothing about the +** underlying implementation. However, most systems pessimize and +** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which +** we interpret as unsafe, as we should. Thus, this heuristic gets +** us into a possible problem only on systems that have a broken +** pathconf implementation and which are also poorly configured +** (have :include: files in group- or world-writable directories). +** +** Parameters: +** fd -- the file descriptor to check. +** safedir -- set if the parent directory is safe. +** +** Returns: +** TRUE -- if the chown(2) operation is "safe" -- that is, +** only root can chown the file to an arbitrary user. +** FALSE -- if an arbitrary user can give away a file. +*/ + +#ifndef IS_SAFE_CHOWN +# define IS_SAFE_CHOWN > 0 +#endif /* ! IS_SAFE_CHOWN */ + +bool +chownsafe(fd, safedir) + int fd; + bool safedir; +{ +#if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ + (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H)) + int rval; + + /* give the system administrator a chance to override */ + if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail)) + return TRUE; + + /* + ** 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 SAFENFSPATHCONF + return errno == 0 && rval IS_SAFE_CHOWN; +# else /* SAFENFSPATHCONF */ + return safedir && errno == 0 && rval IS_SAFE_CHOWN; +# endif /* SAFENFSPATHCONF */ +#else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ + return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); +#endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ +} + /* +** RESETLIMITS -- reset system controlled resource limits +** +** This is to avoid denial-of-service attacks +** +** Parameters: +** none +** +** Returns: +** none +*/ + +#if HASSETRLIMIT +# ifdef RLIMIT_NEEDS_SYS_TIME_H +# include +# endif /* RLIMIT_NEEDS_SYS_TIME_H */ +# include +#endif /* HASSETRLIMIT */ +#ifndef FD_SETSIZE +# define FD_SETSIZE 256 +#endif /* ! FD_SETSIZE */ + +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); +# ifdef RLIMIT_NOFILE + lim.rlim_cur = lim.rlim_max = FD_SETSIZE; + (void) setrlimit(RLIMIT_NOFILE, &lim); +# endif /* RLIMIT_NOFILE */ +#else /* HASSETRLIMIT */ +# if HASULIMIT + (void) ulimit(2, 0x3fffff); + (void) ulimit(4, FD_SETSIZE); +# endif /* HASULIMIT */ +#endif /* HASSETRLIMIT */ + errno = 0; +} + /* +** 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 + { + char *cflocation; + + cflocation = ni_propval("/locations", NULL, "sendmail", + "sendmail.cf", '\0'); + if (cflocation != NULL) + return cflocation; + } +#endif /* NETINFO */ + + 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 /* SUN_EXTENSIONS */ + +#if defined(VENDOR_NAME) && defined(VENDOR_CODE) + if (strcasecmp(vendor, VENDOR_NAME) == 0) + { + VendorCode = VENDOR_CODE; + return TRUE; + } +#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ + + return FALSE; +} + /* +** GETVENDOR -- return vendor name based on vendor code +** +** Parameters: +** vendorcode -- numeric representation of vendor. +** +** Returns: +** string containing vendor name. +*/ + +char * +getvendor(vendorcode) + int vendorcode; +{ +#if defined(VENDOR_NAME) && defined(VENDOR_CODE) + /* + ** Can't have the same switch case twice so need to + ** handle VENDOR_CODE outside of switch. It might + ** match one of the existing VENDOR_* codes. + */ + + if (vendorcode == VENDOR_CODE) + return VENDOR_NAME; +#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ + + switch (vendorcode) + { + case VENDOR_BERKELEY: + return "Berkeley"; + + case VENDOR_SUN: + return "Sun"; + + case VENDOR_HP: + return "HP"; + + case VENDOR_IBM: + return "IBM"; + + case VENDOR_SENDMAIL: + return "Sendmail"; + + default: + return "Unknown"; + } +} + /* +** 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. +*/ + +#if SHARE_V1 +int DefShareUid; /* default share uid to run as -- unused??? */ +#endif /* SHARE_V1 */ + +void +vendor_pre_defaults(e) + ENVELOPE *e; +{ +#if SHARE_V1 + /* OTHERUID is defined in shares.h, do not be alarmed */ + DefShareUid = OTHERUID; +#endif /* SHARE_V1 */ +#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) + sun_pre_defaults(e); +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ +#ifdef apollo + /* + ** stupid domain/os can't even open + ** /etc/mail/sendmail.cf without this + */ + + setuserenv("ISP", NULL); + setuserenv("SYSTYPE", NULL); +#endif /* apollo */ +} + + +void +vendor_post_defaults(e) + ENVELOPE *e; +{ +#ifdef __QNX__ + char *p; + + /* Makes sure the SOCK environment variable remains */ + if (p = getextenv("SOCK")) + setuserenv("SOCK", p); +#endif /* __QNX__ */ +#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) + sun_post_defaults(e); +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ +} + /* +** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode +*/ + +void +vendor_daemon_setup(e) + ENVELOPE *e; +{ +#if HASSETLOGIN + (void) setlogin(RunAsUserName); +#endif /* HASSETLOGIN */ +#if SECUREWARE + if (getluid() != -1) + { + usrerr("Daemon cannot have LUID"); + finis(FALSE, EX_USAGE); + } +#endif /* SECUREWARE */ +} + /* +** VENDOR_SET_UID -- do setup for setting a user id +** +** This is called when we are still root. +** +** Parameters: +** uid -- the uid we are about to become. +** +** Returns: +** none. +*/ + +void +vendor_set_uid(uid) + UID_T uid; +{ + /* + ** We need to setup the share groups (lnodes) + ** and add auditing information (luid's) + ** before we loose our ``root''ness. + */ +#if SHARE_V1 + if (setupshares(uid, syserr) != 0) + syserr("Unable to set up shares"); +#endif /* SHARE_V1 */ +#if SECUREWARE + (void) setup_secure(uid); +#endif /* SECUREWARE */ +} + /* +** VALIDATE_CONNECTION -- check connection for rationality +** +** If the connection is rejected, this routine should log an +** appropriate message -- but should never issue any SMTP protocol. +** +** Parameters: +** sap -- a pointer to a SOCKADDR naming the peer. +** hostname -- the name corresponding to sap. +** e -- the current envelope. +** +** Returns: +** error message from rejection. +** NULL if not rejected. +*/ + +#if TCPWRAPPERS +# include + +/* tcpwrappers does no logging, but you still have to declare these -- ugh */ +int allow_severity = LOG_INFO; +int deny_severity = LOG_NOTICE; +#endif /* TCPWRAPPERS */ + +#if DAEMON +char * +validate_connection(sap, hostname, e) + SOCKADDR *sap; + char *hostname; + ENVELOPE *e; +{ +# if TCPWRAPPERS + char *host; +# endif /* TCPWRAPPERS */ + + if (tTd(48, 3)) + dprintf("validate_connection(%s, %s)\n", + hostname, anynet_ntoa(sap)); + + if (rscheck("check_relay", hostname, anynet_ntoa(sap), e, TRUE, TRUE) + != EX_OK) + { + static char reject[BUFSIZ*2]; + extern char MsgBuf[]; + + if (tTd(48, 4)) + dprintf(" ... validate_connection: BAD (rscheck)\n"); + + if (strlen(MsgBuf) > 5) + { + if (ISSMTPCODE(MsgBuf)) + { + int off; + + if ((off = isenhsc(MsgBuf + 4, ' ')) > 0) + off += 5; + else + off = 4; + (void) strlcpy(reject, &MsgBuf[off], + sizeof reject); + } + else + (void) strlcpy(reject, MsgBuf, sizeof reject); + } + else + (void) strlcpy(reject, "Access denied", sizeof reject); + + return reject; + } + +# if TCPWRAPPERS + if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']') + host = "unknown"; + else + host = hostname; + if (!hosts_ctl("sendmail", host, anynet_ntoa(sap), STRING_UNKNOWN)) + { + if (tTd(48, 4)) + dprintf(" ... validate_connection: BAD (tcpwrappers)\n"); + if (LogLevel >= 4) + sm_syslog(LOG_NOTICE, e->e_id, + "tcpwrappers (%s, %s) rejection", + host, anynet_ntoa(sap)); + return "Access denied"; + } +# endif /* TCPWRAPPERS */ + if (tTd(48, 4)) + dprintf(" ... validate_connection: OK\n"); + return NULL; +} + +#endif /* DAEMON */ + /* +** 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. +*/ + +#if NEEDSTRTOL + +# if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; +# endif /* defined(LIBC_SCCS) && !defined(lint) */ + +/* + * 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 /* NEEDSTRTOL */ + /* +** 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. +*/ + +#if 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 /* NEEDSTRSTR */ + /* +** 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. +** +** Support IPv6 as well as IPv4. +*/ + +#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 + +# ifndef AI_V4MAPPED +# define AI_V4MAPPED 0 /* dummy */ +# endif /* ! AI_V4MAPPED */ +# ifndef AI_ALL +# define AI_ALL 0 /* dummy */ +# endif /* ! AI_ALL */ + +static struct hostent * +getipnodebyname(name, family, flags, err) + char *name; + int family; + int flags; + int *err; +{ + bool resv6 = TRUE; + struct hostent *h; + + if (family == AF_INET6) + { + /* From RFC2133, section 6.1 */ + resv6 = bitset(RES_USE_INET6, _res.options); + _res.options |= RES_USE_INET6; + } + h_errno = 0; + h = gethostbyname(name); + *err = h_errno; + if (family == AF_INET6 && !resv6) + _res.options &= ~RES_USE_INET6; + return h; +} + +static struct hostent * +getipnodebyaddr(addr, len, family, err) + char *addr; + int len; + int family; + int *err; +{ + struct hostent *h; + + h_errno = 0; + h = gethostbyaddr(addr, len, family); + *err = h_errno; + return h; +} +#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ + +struct hostent * +sm_gethostbyname(name, family) + char *name; + int family; +{ + struct hostent *h = NULL; +#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) +# if SOLARIS == 20300 || SOLARIS == 203 + static struct hostent hp; + static char buf[1000]; + extern struct hostent *_switch_gethostbyname_r(); + + if (tTd(61, 10)) + dprintf("_switch_gethostbyname_r(%s)... ", name); + h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); +# else /* SOLARIS == 20300 || SOLARIS == 203 */ + extern struct hostent *__switch_gethostbyname(); + + if (tTd(61, 10)) + dprintf("__switch_gethostbyname(%s)... ", name); + h = __switch_gethostbyname(name); +# endif /* SOLARIS == 20300 || SOLARIS == 203 */ +#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ + int nmaps; +# if NETINET6 + int err; +# endif /* NETINET6 */ + int save_errno; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; + char hbuf[MAXNAME]; + + if (tTd(61, 10)) + dprintf("sm_gethostbyname(%s, %d)... ", name, family); + +# if NETINET6 + h = getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); + h_errno = err; +# else /* NETINET6 */ + h = gethostbyname(name); +# endif /* NETINET6 */ + + save_errno = errno; + if (h == NULL) + { + if (tTd(61, 10)) + dprintf("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) > (SIZE_T) sizeof hbuf - 1) + { + errno = save_errno; + return NULL; + } + (void) strlcpy(hbuf, name, sizeof hbuf); + shorten_hostname(hbuf); + + /* if it hasn't been shortened, there's no point */ + if (strcmp(hbuf, name) != 0) + { + if (tTd(61, 10)) + dprintf("sm_gethostbyname(%s, %d)... ", + hbuf, family); + +# if NETINET6 + h = getipnodebyname(hbuf, family, + AI_V4MAPPED|AI_ALL, + &err); + h_errno = err; + save_errno = errno; +# else /* NETINET6 */ + h = gethostbyname(hbuf); + save_errno = errno; +# endif /* NETINET6 */ + } + } + } +#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ + if (tTd(61, 10)) + { + if (h == NULL) + dprintf("failure\n"); + else + { + dprintf("%s\n", h->h_name); + if (tTd(61, 11)) + { +#if NETINET6 + struct in6_addr ia6; + char buf6[INET6_ADDRSTRLEN]; +#else /* NETINET6 */ + struct in_addr ia; +#endif /* NETINET6 */ + int i; + + if (h->h_aliases != NULL) + for (i = 0; h->h_aliases[i] != NULL; + i++) + dprintf("\talias: %s\n", + h->h_aliases[i]); + for (i = 0; h->h_addr_list[i] != NULL; i++) + { + char *addr; + +#if NETINET6 + memmove(&ia6, h->h_addr_list[i], + IN6ADDRSZ); + addr = anynet_ntop(&ia6, + buf6, sizeof buf6); +#else /* NETINET6 */ + memmove(&ia, h->h_addr_list[i], + INADDRSZ); + addr = (char *) inet_ntoa(ia); +#endif /* NETINET6 */ + if (addr != NULL) + dprintf("\taddr: %s\n", addr); + } + } + } + } + errno = save_errno; + return h; +} + +struct hostent * +sm_gethostbyaddr(addr, len, type) + char *addr; + int len; + int type; +{ + struct hostent *hp; +#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) +# if SOLARIS == 20300 || SOLARIS == 203 + static struct hostent he; + static char buf[1000]; + extern struct hostent *_switch_gethostbyaddr_r(); + + hp = _switch_gethostbyaddr_r(addr, len, type, &he, buf, sizeof(buf), &h_errno); +# else /* SOLARIS == 20300 || SOLARIS == 203 */ + extern struct hostent *__switch_gethostbyaddr(); + + hp = __switch_gethostbyaddr(addr, len, type); +# endif /* SOLARIS == 20300 || SOLARIS == 203 */ +#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ +# if NETINET6 + int err; +# endif /* NETINET6 */ + +# if NETINET6 + hp = getipnodebyaddr(addr, len, type, &err); + h_errno = err; +# else /* NETINET6 */ + hp = gethostbyaddr(addr, len, type); +# endif /* NETINET6 */ + return hp; +#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ +} + /* +** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid +*/ + + +struct passwd * +sm_getpwnam(user) + char *user; +{ +# ifdef _AIX4 + extern struct passwd *_getpwnam_shadow(const char *, const int); + + return _getpwnam_shadow(user, 0); +# else /* _AIX4 */ + return getpwnam(user); +# endif /* _AIX4 */ +} + +struct passwd * +sm_getpwuid(uid) + UID_T uid; +{ +# if defined(_AIX4) && 0 + extern struct passwd *_getpwuid_shadow(const int, const int); + + return _getpwuid_shadow(uid,0); +# else /* defined(_AIX4) && 0 */ + return getpwuid(uid); +# endif /* defined(_AIX4) && 0 */ +} + /* +** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup +** +** Set up the trusted computing environment for C2 level security +** under SecureWare. +** +** Parameters: +** uid -- uid of the user to initialize in the TCB +** +** Returns: +** none +** +** Side Effects: +** Initialized the user in the trusted computing base +*/ + +#if SECUREWARE + +# include +# include + +void +secureware_setup_secure(uid) + UID_T uid; +{ + int rc; + + if (getluid() != -1) + return; + + if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN) + { + switch (rc) + { + case SSI_NO_PRPW_ENTRY: + syserr("No protected passwd entry, uid = %d", uid); + break; + + case SSI_LOCKED: + syserr("Account has been disabled, uid = %d", uid); + break; + + case SSI_RETIRED: + syserr("Account has been retired, uid = %d", uid); + break; + + case SSI_BAD_SET_LUID: + syserr("Could not set LUID, uid = %d", uid); + break; + + case SSI_BAD_SET_PRIVS: + syserr("Could not set kernel privs, uid = %d", uid); + + default: + syserr("Unknown return code (%d) from set_secure_info(%d)", + rc, uid); + break; + } + finis(FALSE, EX_NOPERM); + } +} +#endif /* SECUREWARE */ + /* +** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address +** +** Add hostnames to class 'w' based on the IP address read from +** the network interface. +** +** Parameters: +** sa -- a pointer to a SOCKADDR containing the address +** +** Returns: +** 0 if successful, -1 if host lookup fails. +*/ + +static int +add_hostnames(sa) + SOCKADDR *sa; +{ + struct hostent *hp; + char **ha; + char hnb[MAXHOSTNAMELEN]; + + /* lookup name with IP address */ + switch (sa->sa.sa_family) + { +#if NETINET + case AF_INET: + hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, + sizeof(sa->sin.sin_addr), sa->sa.sa_family); + break; +#endif /* NETINET */ + +#if NETINET6 + case AF_INET6: + hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, + sizeof(sa->sin6.sin6_addr), sa->sa.sa_family); + break; +#endif /* NETINET6 */ + + default: + /* Give warning about unsupported family */ + if (LogLevel > 3) + sm_syslog(LOG_WARNING, NOQID, + "Unsupported address family %d: %.100s", + sa->sa.sa_family, anynet_ntoa(sa)); + return -1; + } + + if (hp == NULL) + { + int save_errno = errno; + + if (LogLevel > 3 && +#if NETINET6 + !(sa->sa.sa_family == AF_INET6 && + IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) && +#endif /* NETINET6 */ + TRUE) + sm_syslog(LOG_WARNING, NOQID, + "gethostbyaddr(%.100s) failed: %d\n", + anynet_ntoa(sa), +#if NAMED_BIND + h_errno +#else /* NAMED_BIND */ + -1 +#endif /* NAMED_BIND */ + ); + errno = save_errno; + return -1; + } + + /* save its cname */ + if (!wordinclass((char *) hp->h_name, 'w')) + { + setclass('w', (char *) hp->h_name); + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", hp->h_name); + + if (snprintf(hnb, sizeof hnb, "[%s]", hp->h_name) < sizeof hnb + && !wordinclass((char *) hnb, 'w')) + setclass('w', hnb); + } + else + { + if (tTd(0, 43)) + dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name); + } + + /* save all it aliases name */ + for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) + { + if (!wordinclass(*ha, 'w')) + { + setclass('w', *ha); + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", *ha); + if (snprintf(hnb, sizeof hnb, + "[%s]", *ha) < sizeof hnb && + !wordinclass((char *) hnb, 'w')) + setclass('w', hnb); + } + else + { + if (tTd(0, 43)) + dprintf("\ta.k.a.: %s (already in $=w)\n", + *ha); + } + } + return 0; +} + /* +** LOAD_IF_NAMES -- load interface-specific names into $=w +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** Loads $=w with the names of all the interfaces. +*/ + +#if !NETINET +# define SIOCGIFCONF_IS_BROKEN 1 /* XXX */ +#endif /* !NETINET */ + +#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN +struct rtentry; +struct mbuf; +# ifndef SUNOS403 +# include +# endif /* ! SUNOS403 */ +# if (_AIX4 >= 40300) && !defined(_NET_IF_H) +# undef __P +# endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */ +# include +#endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ + +void +load_if_names() +{ +#if NETINET6 && defined(SIOCGLIFCONF) + int s; + int i; + struct lifconf lifc; + struct lifnum lifn; + int numifs; + + s = socket(InetMode, SOCK_DGRAM, 0); + if (s == -1) + return; + + /* get the list of known IP address from the kernel */ +# ifdef SIOCGLIFNUM + lifn.lifn_family = AF_UNSPEC; + lifn.lifn_flags = 0; + if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) + { + /* can't get number of interfaces -- fall back */ + if (tTd(0, 4)) + dprintf("SIOCGLIFNUM failed: %s\n", errstring(errno)); + numifs = -1; + } + else + { + numifs = lifn.lifn_count; + if (tTd(0, 42)) + dprintf("system has %d interfaces\n", numifs); + } + if (numifs < 0) +# endif /* SIOCGLIFNUM */ + numifs = MAXINTERFACES; + + if (numifs <= 0) + { + close(s); + return; + } + lifc.lifc_len = numifs * sizeof (struct lifreq); + lifc.lifc_buf = xalloc(lifc.lifc_len); + lifc.lifc_family = AF_UNSPEC; + lifc.lifc_flags = 0; + if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) + { + if (tTd(0, 4)) + dprintf("SIOCGLIFCONF failed: %s\n", errstring(errno)); + close(s); + return; + } + + /* scan the list of IP address */ + if (tTd(0, 40)) + dprintf("scanning for interface specific names, lifc_len=%d\n", + lifc.lifc_len); + + for (i = 0; i < lifc.lifc_len; ) + { + struct lifreq *ifr = (struct lifreq *)&lifc.lifc_buf[i]; + SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr; + char *addr; + struct in6_addr ia6; + struct in_addr ia; +# ifdef SIOCGLIFFLAGS + struct lifreq ifrf; +# endif /* SIOCGLIFFLAGS */ + char ip_addr[256]; + char buf6[INET6_ADDRSTRLEN]; + int af = ifr->lifr_addr.ss_family; + + /* + ** We must close and recreate the socket each time + ** since we don't know what type of socket it is now + ** (each status function may change it). + */ + + (void) close(s); + + s = socket(af, SOCK_DGRAM, 0); + if (s == -1) + return; + + /* + ** If we don't have a complete ifr structure, + ** don't try to use it. + */ + + if ((lifc.lifc_len - i) < sizeof *ifr) + break; + +# ifdef BSD4_4_SOCKADDR + if (sa->sa.sa_len > sizeof ifr->lifr_addr) + i += sizeof ifr->lifr_name + sa->sa.sa_len; + else +# endif /* BSD4_4_SOCKADDR */ + i += sizeof *ifr; + + if (tTd(0, 20)) + dprintf("%s\n", anynet_ntoa(sa)); + + if (af != AF_INET && af != AF_INET6) + continue; + +# ifdef SIOCGLIFFLAGS + memset(&ifrf, '\0', sizeof(struct lifreq)); + (void) strlcpy(ifrf.lifr_name, ifr->lifr_name, + sizeof(ifrf.lifr_name)); + if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0) + { + if (tTd(0, 4)) + dprintf("SIOCGLIFFLAGS failed: %s\n", + errstring(errno)); + continue; + } + else if (tTd(0, 41)) + dprintf("\tflags: %lx\n", + (unsigned long)ifrf.lifr_flags); + + if (!bitset(IFF_UP, ifrf.lifr_flags)) + continue; +# endif /* SIOCGLIFFLAGS */ + + ip_addr[0] = '\0'; + + /* extract IP address from the list*/ + switch (af) + { + case AF_INET6: + ia6 = sa->sin6.sin6_addr; + if (ia6.s6_addr == in6addr_any.s6_addr) + { + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + message("WARNING: interface %s is UP with %s address", + ifr->lifr_name, + addr == NULL ? "(NULL)" : addr); + continue; + } + + /* save IP address in text from */ + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + if (addr != NULL) + (void) snprintf(ip_addr, sizeof ip_addr, + "[%.*s]", + sizeof ip_addr - 3, addr); + break; + + case AF_INET: + ia = sa->sin.sin_addr; + if (ia.s_addr == INADDR_ANY || + ia.s_addr == INADDR_NONE) + { + message("WARNING: interface %s is UP with %s address", + ifr->lifr_name, inet_ntoa(ia)); + continue; + } + + /* save IP address in text from */ + (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", + sizeof ip_addr - 3, inet_ntoa(ia)); + break; + } + + if (*ip_addr == '\0') + continue; + + if (!wordinclass(ip_addr, 'w')) + { + setclass('w', ip_addr); + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", ip_addr); + } + +# ifdef SIOCGLIFFLAGS + /* skip "loopback" interface "lo" */ + if (bitset(IFF_LOOPBACK, ifrf.lifr_flags)) + continue; +# endif /* SIOCGLIFFLAGS */ + (void) add_hostnames(sa); + } + free(lifc.lifc_buf); + close(s); +#else /* NETINET6 && defined(SIOCGLIFCONF) */ +# if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN + int s; + int i; + struct ifconf ifc; + int numifs; + + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == -1) + return; + + /* get the list of known IP address from the kernel */ +# if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN + if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) + { + /* can't get number of interfaces -- fall back */ + if (tTd(0, 4)) + dprintf("SIOCGIFNUM failed: %s\n", errstring(errno)); + numifs = -1; + } + else if (tTd(0, 42)) + dprintf("system has %d interfaces\n", numifs); + if (numifs < 0) +# endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */ + numifs = MAXINTERFACES; + + if (numifs <= 0) + { + (void) close(s); + return; + } + ifc.ifc_len = numifs * sizeof (struct ifreq); + ifc.ifc_buf = xalloc(ifc.ifc_len); + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) + { + if (tTd(0, 4)) + dprintf("SIOCGIFCONF failed: %s\n", errstring(errno)); + (void) close(s); + return; + } + + /* scan the list of IP address */ + if (tTd(0, 40)) + dprintf("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]; + SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; + struct in_addr ia; +# ifdef SIOCGIFFLAGS + struct ifreq ifrf; +# endif /* SIOCGIFFLAGS */ + char ip_addr[256]; + + /* + ** If we don't have a complete ifr structure, + ** don't try to use it. + */ + + if ((ifc.ifc_len - i) < sizeof *ifr) + break; + +# ifdef BSD4_4_SOCKADDR + if (sa->sa.sa_len > sizeof ifr->ifr_addr) + i += sizeof ifr->ifr_name + sa->sa.sa_len; + else +# endif /* BSD4_4_SOCKADDR */ + i += sizeof *ifr; + + if (tTd(0, 20)) + dprintf("%s\n", anynet_ntoa(sa)); + + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + +# ifdef SIOCGIFFLAGS + memset(&ifrf, '\0', sizeof(struct ifreq)); + (void) strlcpy(ifrf.ifr_name, ifr->ifr_name, + sizeof(ifrf.ifr_name)); + (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); + if (tTd(0, 41)) + dprintf("\tflags: %lx\n", + (unsigned long) ifrf.ifr_flags); +# define IFRFREF ifrf +# else /* SIOCGIFFLAGS */ +# define IFRFREF (*ifr) +# endif /* SIOCGIFFLAGS */ + if (!bitset(IFF_UP, IFRFREF.ifr_flags)) + continue; + + /* extract IP address from the list*/ + ia = sa->sin.sin_addr; + if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE) + { + message("WARNING: interface %s is UP with %s address", + ifr->ifr_name, inet_ntoa(ia)); + continue; + } + + /* save IP address in text from */ + (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", + (int) sizeof ip_addr - 3, inet_ntoa(ia)); + + if (!wordinclass(ip_addr, 'w')) + { + setclass('w', ip_addr); + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", ip_addr); + } + + /* skip "loopback" interface "lo" */ + if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags)) + continue; + + (void) add_hostnames(sa); + } + free(ifc.ifc_buf); + (void) close(s); +# undef IFRFREF +# endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ +#endif /* NETINET6 && defined(SIOCGLIFCONF) */ +} + /* +** ISLOOPBACK -- is socket address in the loopback net? +** +** Parameters: +** sa -- socket address. +** +** Returns: +** TRUE -- is socket address in the loopback net? +** FALSE -- otherwise +** +*/ + +bool +isloopback(sa) + SOCKADDR sa; +{ +#if NETINET6 + if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) + return TRUE; +#else /* NETINET6 */ + /* XXX how to correctly extract IN_LOOPBACKNET part? */ + if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET) + >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) + return TRUE; +#endif /* NETINET6 */ + return FALSE; +} + /* +** GET_NUM_PROCS_ONLINE -- return the number of processors currently online +** +** Parameters: +** none. +** +** Returns: +** The number of processors online. +*/ + +static int +get_num_procs_online() +{ + int nproc = 0; + +#ifdef USESYSCTL +# if defined(CTL_HW) && defined(HW_NCPU) + size_t sz; + int mib[2]; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + sz = (size_t) sizeof nproc; + (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); +# endif /* defined(CTL_HW) && defined(HW_NCPUS) */ +#else /* USESYSCTL */ +# ifdef _SC_NPROCESSORS_ONLN + nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); +# else /* _SC_NPROCESSORS_ONLN */ +# ifdef MPC_GETNUMSPUS + nproc = mpctl(MPC_GETNUMSPUS, 0, 0); +# endif /* MPC_GETNUMSPUS */ +# endif /* _SC_NPROCESSORS_ONLN */ +#endif /* USESYSCTL */ + + if (nproc <= 0) + nproc = 1; + return nproc; +} + /* +** SEED_RANDOM -- seed the random number generator +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +seed_random() +{ +#if HASSRANDOMDEV + srandomdev(); +#else /* HASSRANDOMDEV */ + long seed; + struct timeval t; + + seed = (long) getpid(); + if (gettimeofday(&t, NULL) >= 0) + seed += t.tv_sec + t.tv_usec; + +# if HASRANDOM + (void) srandom(seed); +# else /* HASRANDOM */ + (void) srand((unsigned int) seed); +# endif /* HASRANDOM */ +#endif /* HASSRANDOMDEV */ +} + /* +** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE +** +** Parameters: +** level -- syslog level +** id -- envelope ID or NULL (NOQUEUE) +** fmt -- format string +** arg... -- arguments as implied by fmt. +** +** Returns: +** none +*/ + +/* VARARGS3 */ +void +#ifdef __STDC__ +sm_syslog(int level, const char *id, const char *fmt, ...) +#else /* __STDC__ */ +sm_syslog(level, id, fmt, va_alist) + int level; + const char *id; + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + static char *buf = NULL; + static size_t bufsize; + char *begin, *end; + int seq = 1; + int idlen; + char buf0[MAXLINE]; + extern int SnprfOverflow; + extern int SyslogErrno; + extern char *DoprEnd; + VA_LOCAL_DECL + + SyslogErrno = errno; + if (id == NULL) + id = "NOQUEUE"; + else if (strcmp(id, NOQID) == 0) + id = ""; + idlen = strlen(id); + + if (buf == NULL) + { + buf = buf0; + bufsize = sizeof buf0; + } + + for (;;) + { + /* do a virtual vsnprintf into buf */ + VA_START(fmt); + buf[0] = 0; + DoprEnd = buf + bufsize - 1; + SnprfOverflow = 0; + sm_dopr(buf, fmt, ap); + *DoprEnd = '\0'; + VA_END; + /* end of virtual vsnprintf */ + + if (SnprfOverflow == 0) + break; + + /* String too small, redo with correct size */ + bufsize += SnprfOverflow + 1; + if (buf != buf0) + free(buf); + buf = xalloc(bufsize * sizeof (char)); + } + if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE) + { +#if LOG + if (*id == '\0') + syslog(level, "%s", buf); + else + syslog(level, "%s: %s", id, buf); +#else /* LOG */ + /*XXX should do something more sensible */ + if (*id == '\0') + fprintf(stderr, "%s\n", buf); + else + fprintf(stderr, "%s: %s\n", id, buf); +#endif /* LOG */ + if (buf == buf0) + buf = NULL; + return; + } + + begin = buf; + while (*begin != '\0' && + (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE) + { + char save; + + if (seq == 999) + { + /* Too many messages */ + break; + } + end = begin + SYSLOG_BUFSIZE - idlen - 12; + while (end > begin) + { + /* Break on comma or space */ + if (*end == ',' || *end == ' ') + { + end++; /* Include separator */ + break; + } + end--; + } + /* No separator, break midstring... */ + if (end == begin) + end = begin + SYSLOG_BUFSIZE - idlen - 12; + save = *end; + *end = 0; +#if LOG + syslog(level, "%s[%d]: %s ...", id, seq++, begin); +#else /* LOG */ + fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin); +#endif /* LOG */ + *end = save; + begin = end; + } + if (seq == 999) +#if LOG + syslog(level, "%s[%d]: log terminated, too many parts", + id, seq); +#else /* LOG */ + fprintf(stderr, "%s[%d]: log terminated, too many parts\n", + id, seq); +#endif /* LOG */ + else if (*begin != '\0') +#if LOG + syslog(level, "%s[%d]: %s", id, seq, begin); +#else /* LOG */ + fprintf(stderr, "%s[%d]: %s\n", id, seq, begin); +#endif /* LOG */ + if (buf == buf0) + buf = NULL; +} + /* +** HARD_SYSLOG -- call syslog repeatedly until it works +** +** Needed on HP-UX, which apparently doesn't guarantee that +** syslog succeeds during interrupt handlers. +*/ + +#if defined(__hpux) && !defined(HPUX11) + +# define MAXSYSLOGTRIES 100 +# undef syslog +# ifdef V4FS +# define XCNST const +# define CAST (const char *) +# else /* V4FS */ +# define XCNST +# define CAST +# endif /* V4FS */ + +void +# ifdef __STDC__ +hard_syslog(int pri, XCNST char *msg, ...) +# else /* __STDC__ */ +hard_syslog(pri, msg, va_alist) + int pri; + XCNST char *msg; + va_dcl +# endif /* __STDC__ */ +{ + int i; + char buf[SYSLOG_BUFSIZE]; + VA_LOCAL_DECL; + + VA_START(msg); + vsnprintf(buf, sizeof buf, msg, ap); + VA_END; + + for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; ) + continue; +} + +# undef CAST +#endif /* defined(__hpux) && !defined(HPUX11) */ +#if NEEDLOCAL_HOSTNAME_LENGTH + /* +** LOCAL_HOSTNAME_LENGTH +** +** This is required to get sendmail to compile against BIND 4.9.x +** on Ultrix. +** +** Unfortunately, a Compaq Y2K patch kit provides it without +** bumping __RES in /usr/include/resolv.h so we can't automatically +** figure out whether it is needed. +*/ + +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 /* NEEDLOCAL_HOSTNAME_LENGTH */ + + /* +** Compile-Time options +*/ + +char *CompileOptions[] = +{ +#ifdef HESIOD + "HESIOD", +#endif /* HESIOD */ +#if HES_GETMAILHOST + "HES_GETMAILHOST", +#endif /* HES_GETMAILHOST */ +#ifdef LDAPMAP + "LDAPMAP", +#endif /* LDAPMAP */ +#ifdef MAP_NSD + "MAP_NSD", +#endif /* MAP_NSD */ +#ifdef MAP_REGEX + "MAP_REGEX", +#endif /* MAP_REGEX */ +#if LOG + "LOG", +#endif /* LOG */ +#if MATCHGECOS + "MATCHGECOS", +#endif /* MATCHGECOS */ +#if MIME7TO8 + "MIME7TO8", +#endif /* MIME7TO8 */ +#if MIME8TO7 + "MIME8TO7", +#endif /* MIME8TO7 */ +#if NAMED_BIND + "NAMED_BIND", +#endif /* NAMED_BIND */ +#ifdef NDBM + "NDBM", +#endif /* NDBM */ +#if NETINET + "NETINET", +#endif /* NETINET */ +#if NETINET6 + "NETINET6", +#endif /* NETINET6 */ +#if NETINFO + "NETINFO", +#endif /* NETINFO */ +#if NETISO + "NETISO", +#endif /* NETISO */ +#if NETNS + "NETNS", +#endif /* NETNS */ +#if NETUNIX + "NETUNIX", +#endif /* NETUNIX */ +#if NETX25 + "NETX25", +#endif /* NETX25 */ +#ifdef NEWDB + "NEWDB", +#endif /* NEWDB */ +#ifdef NIS + "NIS", +#endif /* NIS */ +#ifdef NISPLUS + "NISPLUS", +#endif /* NISPLUS */ +#ifdef PH_MAP + "PH_MAP", +#endif /* PH_MAP */ +#if QUEUE + "QUEUE", +#endif /* QUEUE */ +#if SASL + "SASL", +#endif /* SASL */ +#if SCANF + "SCANF", +#endif /* SCANF */ +#if SMTP + "SMTP", +#endif /* SMTP */ +#if SMTPDEBUG + "SMTPDEBUG", +#endif /* SMTPDEBUG */ +#ifdef SUID_ROOT_FILES_OK + "SUID_ROOT_FILES_OK", +#endif /* SUID_ROOT_FILES_OK */ +#if TCPWRAPPERS + "TCPWRAPPERS", +#endif /* TCPWRAPPERS */ +#if USERDB + "USERDB", +#endif /* USERDB */ +#if XDEBUG + "XDEBUG", +#endif /* XDEBUG */ +#ifdef XLA + "XLA", +#endif /* XLA */ + NULL +}; + + +/* +** OS compile options. +*/ + +char *OsCompileOptions[] = +{ +#if BOGUS_O_EXCL + "BOGUS_O_EXCL", +#endif /* BOGUS_O_EXCL */ +#if FAST_PID_RECYCLE + "FAST_PID_RECYCLE", +#endif /* FAST_PID_RECYCLE */ +#if HASFCHOWN + "HASFCHOWN", +#endif /* HASFCHOWN */ +#if HASFCHMOD + "HASFCHMOD", +#endif /* HASFCHMOD */ +#if HASFLOCK + "HASFLOCK", +#endif /* HASFLOCK */ +#if HASGETDTABLESIZE + "HASGETDTABLESIZE", +#endif /* HASGETDTABLESIZE */ +#if HASGETUSERSHELL + "HASGETUSERSHELL", +#endif /* HASGETUSERSHELL */ +#if HASINITGROUPS + "HASINITGROUPS", +#endif /* HASINITGROUPS */ +#if HASLSTAT + "HASLSTAT", +#endif /* HASLSTAT */ +#if HASRANDOM + "HASRANDOM", +#endif /* HASRANDOM */ +#if HASSETLOGIN + "HASSETLOGIN", +#endif /* HASSETLOGIN */ +#if HASSETREUID + "HASSETREUID", +#endif /* HASSETREUID */ +#if HASSETRLIMIT + "HASSETRLIMIT", +#endif /* HASSETRLIMIT */ +#if HASSETSID + "HASSETSID", +#endif /* HASSETSID */ +#if HASSETUSERCONTEXT + "HASSETUSERCONTEXT", +#endif /* HASSETUSERCONTEXT */ +#if HASSETVBUF + "HASSETVBUF", +#endif /* HASSETVBUF */ +#if HASSNPRINTF + "HASSNPRINTF", +#endif /* HASSNPRINTF */ +#if HAS_ST_GEN + "HAS_ST_GEN", +#endif /* HAS_ST_GEN */ +#if HASSRANDOMDEV + "HASSRANDOMDEV", +#endif /* HASSRANDOMDEV */ +#if HASSTRERROR + "HASSTRERROR", +#endif /* HASSTRERROR */ +#if HASULIMIT + "HASULIMIT", +#endif /* HASULIMIT */ +#if HASUNAME + "HASUNAME", +#endif /* HASUNAME */ +#if HASUNSETENV + "HASUNSETENV", +#endif /* HASUNSETENV */ +#if HASWAITPID + "HASWAITPID", +#endif /* HASWAITPID */ +#if IDENTPROTO + "IDENTPROTO", +#endif /* IDENTPROTO */ +#if IP_SRCROUTE + "IP_SRCROUTE", +#endif /* IP_SRCROUTE */ +#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL + "LOCK_ON_OPEN", +#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ +#if NEEDFSYNC + "NEEDFSYNC", +#endif /* NEEDFSYNC */ +#if NOFTRUNCATE + "NOFTRUNCATE", +#endif /* NOFTRUNCATE */ +#if RLIMIT_NEEDS_SYS_TIME_H + "RLIMIT_NEEDS_SYS_TIME_H", +#endif /* RLIMIT_NEEDS_SYS_TIME_H */ +#if SAFENFSPATHCONF + "SAFENFSPATHCONF", +#endif /* SAFENFSPATHCONF */ +#if SECUREWARE + "SECUREWARE", +#endif /* SECUREWARE */ +#if SHARE_V1 + "SHARE_V1", +#endif /* SHARE_V1 */ +#if SIOCGIFCONF_IS_BROKEN + "SIOCGIFCONF_IS_BROKEN", +#endif /* SIOCGIFCONF_IS_BROKEN */ +#if SIOCGIFNUM_IS_BROKEN + "SIOCGIFNUM_IS_BROKEN", +#endif /* SIOCGIFNUM_IS_BROKEN */ +#if SYS5SETPGRP + "SYS5SETPGRP", +#endif /* SYS5SETPGRP */ +#if SYSTEM5 + "SYSTEM5", +#endif /* SYSTEM5 */ +#if USE_SA_SIGACTION + "USE_SA_SIGACTION", +#endif /* USE_SA_SIGACTION */ +#if USE_SIGLONGJMP + "USE_SIGLONGJMP", +#endif /* USE_SIGLONGJMP */ +#if USESETEUID + "USESETEUID", +#endif /* USESETEUID */ + NULL +}; diff --git a/gnu/usr.sbin/sendmail/sendmail/conf.h b/gnu/usr.sbin/sendmail/sendmail/conf.h new file mode 100644 index 00000000000..e4df32b4533 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/conf.h @@ -0,0 +1,2736 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * + * $Sendmail: conf.h,v 8.492 2000/02/26 06:04:21 gshapiro Exp $ + */ + +/* +** CONF.H -- All user-configurable parameters for sendmail +** +** Send updates to sendmail@Sendmail.ORG so they will be +** included in the next release. +*/ + +#ifndef CONF_H +#define CONF_H 1 + +#ifdef __GNUC__ +struct rusage; /* forward declaration to get gcc to shut up in wait.h */ +#endif /* __GNUC__ */ + +#include +#include +#include +#ifndef __QNX__ +/* in QNX this grabs bogus LOCK_* manifests */ +# include +#endif /* ! __QNX__ */ +#include +#include +#include +#include +#include +#include +#include + +/* make sure TOBUFSIZ isn't larger than system limit for size of exec() args */ +#ifdef ARG_MAX +# if ARG_MAX > 4096 +# define SM_ARG_MAX 4096 +# else /* ARG_MAX > 4096 */ +# define SM_ARG_MAX ARG_MAX +# endif /* ARG_MAX > 4096 */ +#else /* ARG_MAX */ +# define SM_ARG_MAX 4096 +#endif /* ARG_MAX */ + +/********************************************************************** +** 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 256 /* max # of parms to mailers */ +#define MAXATOM 1000 /* max atoms per address */ +#define MAXRWSETS 200 /* max # of sets of rewriting rules */ +#define MAXPRIORITIES 25 /* max values for Precedence: field */ +#define MAXMXHOSTS 100 /* max # of MX records for one host */ +#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 */ +#if _FFR_MILTER +# define MAXFILTERS 25 /* max # of milter filters */ +# define MAXFILTERMACROS 50 /* max # of macros per milter cmd */ +#endif /* _FFR_MILTER */ +#define MAXSMTPARGS 20 /* max # of ESMTP args for MAIL/RCPT */ +#define MAXTOCLASS 8 /* max # of message timeout classes */ +#define MAXRESTOTYPES 3 /* max # of resolver timeout types */ +#define MAXMIMEARGS 20 /* max args in Content-Type: */ +#define MAXMIMENESTING 20 /* max MIME multipart nesting */ +#define QUEUESEGSIZE 1000 /* increment for queue size */ +#define MAXQFNAME 20 /* max qf file name length */ +#define MACBUFSIZE 4096 /* max expanded macro buffer size */ +#define TOBUFSIZE SM_ARG_MAX /* max buffer to hold address list */ +#define MAXSHORTSTR 203 /* max short string length */ +#define MAXMACNAMELEN 25 /* max macro name length */ +#define MAXMACROID 0377 /* max macro id number */ +#ifndef MAXHDRSLEN +# define MAXHDRSLEN (32 * 1024) /* max size of message headers */ +#endif /* ! MAXHDRSLEN */ +#define MAXDAEMONS 10 /* max number of ports to listen to */ +#ifndef MAXINTERFACES +# define MAXINTERFACES 512 /* number of interfaces to probe */ +#endif /* MAXINTERFACES */ +#ifndef MAXSYMLINKS +# define MAXSYMLINKS 32 /* max number of symlinks in a path */ +#endif /* ! MAXSYMLINKS */ +#define MAXLINKPATHLEN (MAXPATHLEN * MAXSYMLINKS) /* max link-expanded file */ +#define DATA_PROGRESS_TIMEOUT 300 /* how ofter to check DATA progress */ +#define ENHSCLEN 10 /* max len of enhanced status code */ + +#if SASL +# ifndef AUTH_MECHANISMS +# define AUTH_MECHANISMS "GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# endif /* ! AUTH_MECHANISMS */ +#else /* SASL */ +#endif /* SASL */ + +#ifdef LDAPMAP +# define LDAPMAP_MAX_ATTR 64 +# define LDAPMAP_MAX_FILTER 1024 +# define LDAPMAP_MAX_PASSWD 256 +#endif /* LDAPMAP */ + +/********************************************************************** +** 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 /* ! NETINET */ + +#ifndef NETINET6 +# define NETINET6 0 /* do not include IPv6 support */ +#endif /* ! NETINET6 */ + +#ifndef NETISO +# define NETISO 0 /* do not include ISO socket support */ +#endif /* ! NETISO */ + +#ifndef NAMED_BIND +# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */ +#endif /* ! NAMED_BIND */ + +#ifndef XDEBUG +# define XDEBUG 1 /* enable extended debugging */ +#endif /* ! XDEBUG */ + +#ifndef MATCHGECOS +# define MATCHGECOS 1 /* match user names from gecos field */ +#endif /* ! MATCHGECOS */ + +#ifndef DSN +# define DSN 1 /* include delivery status notification code */ +#endif /* ! DSN */ + +#if !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) +# define USERDB 1 /* look in user database */ +#endif /* !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) */ + +#ifndef MIME8TO7 +# define MIME8TO7 1 /* 8->7 bit MIME conversions */ +#endif /* ! MIME8TO7 */ + +#ifndef MIME7TO8 +# define MIME7TO8 1 /* 7->8 bit MIME conversions */ +#endif /* ! MIME7TO8 */ + +/********************************************************************** +** "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 1 /* 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 /* __STDC__ */ + +/* +** Assume you have standard calls; can be #undefed below if necessary. +*/ + +#ifndef HASLSTAT +# define HASLSTAT 1 /* has lstat(2) call */ +#endif /* ! HASLSTAT */ + /********************************************************************** +** 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. +** 11.x support from Richard Allen . +*/ + +#ifdef __hpux + /* common definitions for HP-UX 9.x and 10.x */ +# undef m_flags /* conflict between Berkeley DB 1.85 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 usable seteuid(2) call */ +# define BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ +# 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 statfs() implementation */ +# define GIDSET_T gid_t +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ +# endif /* ! HASGETUSERSHELL */ +# ifdef HPUX11 +# define HASSNPRINTF 1 /* has snprintf(3) */ +# else /* HPUX11 */ +# ifndef NOT_SENDMAIL +# define syslog hard_syslog +# endif /* ! NOT_SENDMAIL */ +# endif /* HPUX11 */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ + +# ifdef V4FS + /* HP-UX 10.x */ +# define _PATH_UNIX "/stand/vmunix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef IDENTPROTO +# define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */ +# endif /* ! IDENTPROTO */ +# include /* for mpctl() in get_num_procs_online() */ +# else /* V4FS */ + /* HP-UX 9.x */ +# define _PATH_UNIX "/hp-ux" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifdef __STDC__ +extern void hard_syslog(int, char *, ...); +# else /* __STDC__ */ +extern void hard_syslog(); +# endif /* __STDC__ */ +# define FDSET_CAST (int *) /* cast for fd_set parameters to select */ +# endif /* V4FS */ + +#endif /* __hpux */ + + +/* +** IBM AIX 4.x +*/ + +#ifdef _AIX4 +# define _AIX3 1 /* pull in AIX3 stuff */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define USESETEUID 1 /* seteuid(2) works */ +# define TZ_TYPE TZ_NAME /* use tzname[] vector */ +# define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ +# if _AIX4 >= 40200 +# define HASSETREUID 1 /* setreuid(2) works as of AIX 4.2 */ +# define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ +# endif /* _AIX4 >= 40200 */ +# if _AIX4 >= 40300 +# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ +# endif /* _AIX4 >= 40300 */ +# if defined(_ILS_MACROS) /* IBM versions aren't side-effect clean */ +# undef isascii +# define isascii(c) !(c & ~0177) +# undef isdigit +# define isdigit(__a) (_IS(__a,_ISDIGIT)) +# undef isspace +# define isspace(__a) (_IS(__a,_ISSPACE)) +# endif /* defined(_ILS_MACROS) */ +#endif /* _AIX4 */ + + +/* +** IBM AIX 3.x -- actually tested for 3.2.3 +*/ + +#ifdef _AIX3 +# include +# include /* to get byte order */ +# include +# define HASFCHOWN 1 /* has fchown(2) */ +# 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 GIDSET_T gid_t +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define LA_TYPE LA_INT +# define FSHIFT 16 +# define LA_AVENRUN "avenrun" +#endif /* _AIX3 */ + + +/* +** IBM AIX 2.2.1 -- actually tested for osupdate level 2706+1773 +** +** From Mark Whetzel . +*/ + +#ifdef AIX /* AIX/RT compiler pre-defines this */ +# include +# include /* AIX/RT resource.h does NOT include this */ +# 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 0 /* does not have fchmod(2) syscall */ +# define HASSETREUID 1 /* use setreuid(2) -lbsd system call */ +# define HASSETVBUF 1 /* use setvbuf(2) system call */ +# define HASSETRLIMIT 0 /* does not have setrlimit call */ +# define HASFLOCK 0 /* does not have flock call - use fcntl */ +# define HASULIMIT 1 /* use ulimit instead of setrlimit call */ +# define NEEDGETOPT 1 /* Do we need theirs or ours */ +# define SYS5SETPGRP 1 /* don't have setpgid on AIX/RT */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define BSD4_3 1 /* NOT bsd 4.4 or posix signals */ +# define GIDSET_T int +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define LA_TYPE LA_SUBR /* use our ported loadavgd daemon */ +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# define ARBPTR_T int * +# define void int +typedef int pid_t; +/* RTisms for BSD compatibility, specified in the Makefile + define BSD 1 + define BSD_INCLUDES 1 + define BSD_REMAP_SIGNAL_TO_SIGVEC + RTisms needed above */ +/* make this sendmail in a completely different place */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/local/newmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* AIX */ + + +/* +** 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. +** +** This version tries to be adaptive using _MIPS_SIM: +** _MIPS_SIM == _ABIO32 (= 1) Abi: -32 on IRIX 6.2 +** _MIPS_SIM == _ABIN32 (= 2) Abi: -n32 on IRIX 6.2 +** _MIPS_SIM == _ABI64 (= 3) Abi: -64 on IRIX 6.2 +** +** _MIPS_SIM is 1 also on IRIX 5.3 +** +** IRIX64 changes from Mark R. Levinson . +** IRIX5 changes from Kari E. Hurtta . +** Adaptive changes from Kari E. Hurtta . +*/ + +#if defined(__sgi) +# ifndef IRIX +# define IRIX +# endif /* ! IRIX */ +# if _MIPS_SIM > 0 && !defined(IRIX5) +# define IRIX5 /* IRIX5 or IRIX6 */ +# endif /* _MIPS_SIM > 0 && !defined(IRIX5) */ +# if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) +# define IRIX6 /* IRIX6 */ +# endif /* _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64) */ +#endif /* defined(__sgi) */ + +#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 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 SYSLOG_BUFSIZE 512 +# ifdef IRIX6 +# define STAT64 1 +# define QUAD_T unsigned long long +# define LA_TYPE LA_IRIX6 /* figure out at run time */ +# define SAFENFSPATHCONF 0 /* pathconf(2) lies on NFS filesystems */ +# else /* IRIX6 */ +# define LA_TYPE LA_INT + +# ifdef IRIX64 +# define STAT64 1 +# define QUAD_T unsigned long long +# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */ +# else /* IRIX64 */ +# define STAT64 0 +# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ +# endif /* IRIX64 */ +# endif /* IRIX6 */ +# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# include +# include +# define ARGV_T char *const * +# define HASFCHOWN 1 /* has fchown(2) */ +# define HASSETRLIMIT 1 /* has setrlimit(2) syscall */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# else /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +# define ARGV_T const char ** +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +#endif /* IRIX */ + + +/* +** 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) + +# include +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ +# ifndef HASFCHOWN +# define HASFCHOWN 1 /* fchown(2) */ +# endif /* ! HASFCHOWN */ + +# ifdef SOLARIS_2_3 +# define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */ +# endif /* SOLARIS_2_3 */ + +# if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# define SOLARIS 1 /* unknown Solaris version */ +# endif /* defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4)) */ + +# ifdef SOLARIS + /* Solaris 2.x (a.k.a. SunOS 5.x) */ +# ifndef __svr4__ +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ +# define GIDSET_T gid_t +# define USE_SA_SIGACTION 1 /* use sa_sigaction field */ +# ifndef _PATH_UNIX +# define _PATH_UNIX "/dev/ksyms" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef _PATH_HOSTS +# define _PATH_HOSTS "/etc/inet/hosts" +# endif /* ! _PATH_HOSTS */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ +# endif /* ! SYSLOG_BUFSIZE */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME +# endif /* ! TZ_TYPE */ +# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) +# define USESETEUID 1 /* seteuid works as of 2.3 */ +# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ +# if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) +# define HASSETREUID 1 /* setreuid works as of 2.5 */ +# if SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) +# ifndef LA_TYPE +# define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */ +# endif /* ! LA_TYPE */ +# endif /* SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) */ +# else /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ +# ifndef HASRANDOM +# define HASRANDOM 0 /* doesn't have random(3) */ +# endif /* ! HASRANDOM */ +# endif /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ +# if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) +# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ +# if SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) +# ifndef LA_TYPE +# include +# define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ +# endif /* ! LA_TYPE */ +# define HASGETUSERSHELL 1 /* getusershell(3c) bug fixed in 2.7 */ +# endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ +# if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) +# undef NETINET6 +# define NETINET6 1 /* IPv6 added in 2.8 */ +# define HASSTRL 1 /* str*(3) added in 2.8 */ +# endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ +# endif /* ! HASGETUSERSHELL */ + +# else /* SOLARIS */ + /* SunOS 4.0.3 or 4.1.x */ +# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# include +# include +# ifdef __GNUC__ +# define strtoul strtol /* gcc library bogosity */ +# endif /* __GNUC__ */ +# define memmove(d, s, l) (bcopy((s), (d), (l))) + +# ifdef SUNOS403 + /* special tweaking for SunOS 4.0.3 */ +# include +# 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 +# define MODE_T int +typedef int pid_t; +extern char *getenv(); + +# else /* SUNOS403 */ + /* 4.1.x specifics */ +# define HASSETSID 1 /* has Posix setsid(2) call */ +# define HASSETVBUF 1 /* we have setvbuf(3) in libc */ + +# endif /* SUNOS403 */ +# endif /* SOLARIS */ + +# ifndef LA_TYPE +# define LA_TYPE LA_INT +# endif /* ! LA_TYPE */ + +#endif /* defined(sun) && !defined(BSD) */ + +/* +** 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 . +*/ + +#ifdef DGUX_5_4_2 +# define DGUX 1 +#endif /* DGUX_5_4_2 */ + +#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 */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) */ +# define HASSNPRINTF 1 /* has snprintf(3) */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# 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 +# include + +/* compiler doesn't understand const? */ +# define const + +# ifdef DGUX_5_4_2 +# define inet_addr dgux_inet_addr +extern long dgux_inet_addr(); +# endif /* DGUX_5_4_2 */ +#endif /* DGUX */ + + +/* +** 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 */ +# define HASFCHOWN 1 /* has fchown(2) syscall */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# 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 /* ! BROKEN_RES_SEARCH */ +# if !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 +# define NEEDLOCAL_HOSTNAME_LENGTH 1 /* see sendmail/README */ +# endif /* !defined(NEEDLOCAL_HOSTNAME_LENGTH) && NAMED_BIND && __RES >= 19931104 && __RES < 19950621 */ +# ifdef vax +# define LA_TYPE LA_FLOAT +# else /* vax */ +# define LA_TYPE LA_INT +# define LA_AVENRUN "avenrun" +# endif /* vax */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# define SYSLOG_BUFSIZE 256 +#endif /* ultrix */ + + +/* +** OSF/1 for KSR. +** +** Contributed by Todd C. Miller +*/ + +#ifdef __ksr__ +# define __osf__ 1 /* get OSF/1 defines below */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif /* ! TZ_TYPE */ +#endif /* __ksr__ */ + + +/* +** OSF/1 for Intel Paragon. +** +** Contributed by Jeff A. Earickson +** of Intel Scalable Systems Divison. +*/ + +#ifdef __PARAGON__ +# define __osf__ 1 /* get OSF/1 defines below */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif /* ! TZ_TYPE */ +# define GIDSET_T gid_t +# define MAXNAMLEN NAME_MAX +#endif /* __PARAGON__ */ + + +/* +** Tru64 UNIX, formerly known as Digital UNIX, formerly known as DEC OSF/1 +** +** Tested for 3.2 and 4.0. +*/ + +#ifdef __osf__ +# define HASUNAME 1 /* has uname(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* has fchown(2) syscall */ +# define HASSETLOGIN 1 /* has setlogin(2) */ +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define GIDSET_T gid_t +# if _FFR_MILTER +# define SM_INT32 int /* 32bit integer */ +# endif /* _FFR_MILTER */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define LA_TYPE LA_ALPHAOSF +# define SFS_TYPE SFS_STATVFS /* use statfs() impl */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __osf__ */ + + +/* +** 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 /* ! HASFLOCK */ +# 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 GID_T int /* ditto for gid_t */ +# define MODE_T int /* and mode_t */ +# define setpgid setpgrp +# ifndef NOT_SENDMAIL +# define sleep sleepX +# endif /* ! NOT_SENDMAIL */ +# ifndef LA_TYPE +# define LA_TYPE LA_MACH +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# ifndef _POSIX_SOURCE +typedef int pid_t; +# undef WEXITSTATUS +# undef WIFEXITED +# undef WIFSTOPPED +# undef WTERMSIG +# endif /* ! _POSIX_SOURCE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ + +# ifdef TCPWRAPPERS +# ifndef HASUNSETENV +# define HASUNSETENV 1 +# endif /* ! HASUNSETENV */ +# undef NEEDPUTENV +# endif /* TCPWRAPPERS */ + +#endif /* NeXT */ + +/* +** Apple Rhapsody +** Contributed by Wilfredo Sanchez +** +** Also used for Apple Darwin support. +*/ + +#if defined(__APPLE__) && !defined(NeXT) +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFLOCK 1 /* has flock(2) syscall */ +# define HASUNAME 1 /* has uname(2) syscall */ +# define HASUNSETENV 1 +# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define HASINITGROUPS 1 +# define HASSETVBUF 1 +# define HASSETREUID 1 +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASLSTAT 1 +# define HASSETRLIMIT 1 +# define HASWAITPID 1 +# define HASSTRERROR 1 /* has strerror(3) */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HASGETDTABLESIZE 1 +# define HASGETUSERSHELL 1 +# define NEEDGETOPT 1 /* need a replacement for getopt(3) */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define GIDSET_T gid_t +# define LA_TYPE LA_SUBR /* use getloadavg(3) */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# define SPT_TYPE SPT_PSSTRINGS +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +#endif /* __APPLE__ && ! NeXT */ + + +/* +** 4.4 BSD +** +** See also BSD defines. +*/ + +#if defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) +# include +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# include +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ +# define NETLINK 1 /* supports AF_LINK */ +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */ +#endif /* defined(BSD4_4) && !defined(__bsdi__) && !defined(__GNU__) */ + + +/* +** BSD/OS (was BSD/386) (all versions) +** From Tony Sanders, BSDI +*/ + +#ifdef __bsdi__ +# include +# define HASUNSETENV 1 /* has the unsetenv(3) call */ +# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSETLOGIN 1 /* has setlogin(2) */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# include +# 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 statfs() impl */ +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# endif /* ! LA_TYPE */ +# define GIDSET_T gid_t +# define QUAD_T quad_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 /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ + /* version 1.0 or earlier */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 */ +# if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 /* on 3.x */ +# define HASSETUSERCONTEXT 1 /* has setusercontext */ +# endif /* defined(_BSDI_VERSION) && _BSDI_VERSION >= 199701 */ +#endif /* __bsdi__ */ + + +/* +** QNX 4.2x +** Contributed by Glen McCready . +** +** Should work with all versions of QNX. +*/ + +#if defined(__QNX__) +# include +# include +# undef NGROUPS_MAX +# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HASFLOCK 0 +# undef HASINITGROUPS /* has initgroups(3) call */ +# define NEEDGETOPT 1 /* use sendmail's getopt */ +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define TZ_TYPE TZ_TMNAME /* use tmname variable */ +# define GIDSET_T gid_t +# define LA_TYPE LA_ZERO +# define SFS_TYPE SFS_NONE +# define SPT_TYPE SPT_REUSEARGV +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define HASGETUSERSHELL 0 +# define E_PSEUDOBASE 512 +# define _FILE_H_INCLUDED +#endif /* defined(__QNX__) */ + + +/* +** FreeBSD / NetBSD / OpenBSD (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__) || defined(__OpenBSD__) +# include +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has usable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASFCHOWN 1 /* fchown(2) */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASUNAME 1 /* has uname(2) syscall */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define NEED_PRINTF_PERCENTQ 1 /* doesn't have %lld */ +# include +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ +# define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ +# define GIDSET_T gid_t +# define QUAD_T unsigned long long +# ifndef LA_TYPE +# define LA_TYPE LA_SUBR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_MOUNT /* use statfs() impl */ +# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ +# endif /* defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) */ +# if defined(__FreeBSD__) +# define HASSETLOGIN 1 /* has setlogin(2) */ +# if __FreeBSD_version >= 227001 +# define HASSRANDOMDEV 1 /* has srandomdev(3) */ +# endif /* __FreeBSD_version >= 227001 */ +# undef SPT_TYPE +# if __FreeBSD__ >= 2 +# include +# if __FreeBSD_version >= 199512 /* 2.2-current when it appeared */ +# include +# define SPT_TYPE SPT_BUILTIN +# endif /* __FreeBSD_version >= 199512 */ +# if __FreeBSD_version >= 222000 /* 2.2.2-release and later */ +# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ +# endif /* __FreeBSD_version >= 222000 */ +# if __FreeBSD_version >= 330000 /* 3.3.0-release and later */ +# ifndef HASSTRL +# define HASSTRL 1 /* has strlc{py,at}(3) functions */ +# endif /* HASSTRL */ +# endif /* __FreeBSD_version >= 330000 */ +# define USESYSCTL 1 /* use sysctl(3) for getting ncpus */ +# include +# endif /* __FreeBSD__ >= 2 */ +# ifndef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# endif /* ! SPT_TYPE */ +# endif /* defined(__FreeBSD__) */ +# if defined(__OpenBSD__) +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ +# define HASSETLOGIN 1 /* has setlogin(2) */ + +/* strlcat(3) is broken in OpenBSD 2.5 and earlier */ +# define HASSTRL 0 /* has strlc{py,at}(3) functions */ +# endif /* defined(__OpenBSD__) */ +#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ + + +/* +** Mach386 +** +** For mt Xinu's Mach386 system. +*/ + +#if defined(MACH) && defined(i386) && !defined(__GNU__) +# 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 /* ! HASFLOCK */ +# 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 /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# undef HASSETVBUF /* don't actually have setvbuf(3) */ +# undef WEXITSTATUS +# undef WIFEXITED +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* defined(MACH) && defined(i386) && !defined(__GNU__) */ + + + +/* +** GNU OS (hurd) +** Largely BSD & posix compatible. +** Port contributed by Miles Bader . +** Updated by Mark Kettenis . +*/ + +#if defined(__GNU__) && !defined(NeXT) +# include +# define HASFCHMOD 1 /* has fchmod(2) call */ +# define HASFCHOWN 1 /* has fchown(2) call */ +# define HASUNAME 1 /* has uname(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) call */ +# define HAS_ST_GEN 1 /* has st_gen field in stat struct */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define GIDSET_T gid_t +# define SOCKADDR_LEN_T socklen_t +# define SOCKOPT_LEN_T socklen_t +# if (__GLIBC__ == 2 && __GLIBC_MINOR__ > 1) || __GLIBC__ > 2 +# define LA_TYPE LA_SUBR +# else +# define LA_TYPE LA_MACH + /* GNU uses mach[34], which renames some rpcs from mach2.x. */ +# define host_self mach_host_self +# endif +# define SFS_TYPE SFS_STATFS +# define SPT_TYPE SPT_CHANGEARGV +# define ERRLIST_PREDEFINED 1 /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR 1 /* has sa_len */ +# define SIOCGIFCONF_IS_BROKEN 1 /* SIOCGFCONF doesn't work */ +# define HAS_IN_H 1 /* GNU has netinet/in.h. */ +/* GNU has no MAXPATHLEN; ideally the code should be changed to not use it. */ +# define MAXPATHLEN 2048 +#endif /* defined(__GNU__) && !defined(NeXT) */ + +/* +** 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 /* ! LA_TYPE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# undef WEXITSTATUS +# undef WIFEXITED +typedef short pid_t; +#endif /* defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd) */ + + +/* +** SCO Unix +** +** This includes three parts: +** +** The first is for SCO OpenServer 5. +** (Contributed by Keith Reynolds ). +** +** SCO OpenServer 5 has a compiler version number macro, +** which we can use to figure out what version we're on. +** This may have to change in future releases. +** +** The second is for SCO UNIX 3.2v4.2/Open Desktop 3.0. +** (Contributed by Philippe Brand ). +** +** The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier. +*/ + +/* SCO OpenServer 5 */ +#if _SCO_DS >= 1 +# include +# define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM returns bogus value */ +# define HASSNPRINTF 1 /* has snprintf(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) call */ +# define HASFCHOWN 1 /* has fchown(2) call */ +# define HASSETRLIMIT 1 /* has setrlimit(2) call */ +# define USESETEUID 1 /* has seteuid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ +# define RLIMIT_NEEDS_SYS_TIME_H 1 +# ifndef LA_TYPE +# define LA_TYPE LA_DEVSHORT +# endif /* ! LA_TYPE */ +# define _PATH_AVENRUN "/dev/table/avenrun" +# ifndef _SCO_unix_4_2 +# define _SCO_unix_4_2 +# else /* ! _SCO_unix_4_2 */ +# define SOCKADDR_LEN_T size_t /* e.g., arg#3 to accept, getsockname */ +# define SOCKOPT_LEN_T size_t /* arg#5 to getsockopt */ +# endif /* ! _SCO_unix_4_2 */ +#endif /* _SCO_DS >= 1 */ + +/* SCO UNIX 3.2v4.2/Open Desktop 3.0 */ +#ifdef _SCO_unix_4_2 +# define _SCO_unix_ +# define HASSETREUID 1 /* has setreuid(2) call */ +#endif /* _SCO_unix_4_2 */ + +/* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */ +#ifdef _SCO_unix_ +# include /* needed for IP_SRCROUTE */ +# define SYSTEM5 1 /* include all the System V defines */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define NOFTRUNCATE 0 /* has (simulated) ftruncate call */ +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +# define MAXPATHLEN PATHSIZE +# define SFS_TYPE SFS_4ARGS /* use 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 UID_T uid_t +# define GID_T gid_t +# define GIDSET_T gid_t +# define _PATH_UNIX "/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ + +/* stuff fixed in later releases */ +# ifndef _SCO_unix_4_2 +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# endif /* ! _SCO_unix_4_2 */ + +# ifndef _SCO_DS +# define ftruncate chsize /* use chsize(2) to emulate ftruncate */ +# define NEEDFSYNC 1 /* needs the fsync(2) call stub */ +# define NETUNIX 0 /* no unix domain socket support */ +# define LA_TYPE LA_SHORT +# endif /* ! _SCO_DS */ + +#endif /* _SCO_unix_ */ + + +/* +** ISC (SunSoft) Unix. +** +** Contributed by J.J. Bailey +*/ + +#ifdef ISC_UNIX +# include +# include /* needed for IP_SRCROUTE */ +# include +# 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 MAXPATHLEN 1024 +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _PATH_UNIX "/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* ISC_UNIX */ + + +/* +** Altos System V (5.3.1) +** Contributed by Tim Rice . +*/ + +#ifdef ALTOS_SYSTEM_V +# include +# include +# 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 NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define NOFTRUNCATE 1 /* do not have ftruncate(2) */ +# define MAXPATHLEN PATH_MAX +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_STATFS /* use statfs() impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# 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; +typedef unsigned long mode_t; + +/* some stuff that should have been in the include files */ +extern char *malloc(); +extern struct passwd *getpwent(); +extern struct passwd *getpwnam(); +extern struct passwd *getpwuid(); +extern char *getenv(); +extern struct group *getgrgid(); +extern struct group *getgrnam(); + +#endif /* ALTOS_SYSTEM_V */ + + +/* +** ConvexOS 11.0 and later +** +** "Todd C. Miller" claims this +** works on 9.1 as well. +** +** ConvexOS 11.5 and later, should work on 11.0 as defined. +** For pre-ConvexOOS 11.0, define NEEDGETOPT, undef IDENTPROTO +** +** Eric Schnoebelen (eric@cirr.com) For CONVEX Computer Corp. +** (now the CONVEX Technologies Center of Hewlett Packard) +*/ + +#ifdef _CONVEX_SOURCE +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) */ +# define HASINITGROUPS 1 /* has initgroups(3) */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASSETSID 1 /* has POSIX setsid(2) call */ +# define HASUNSETENV 1 /* has unsetenv(3) */ +# define HASFLOCK 1 /* has flock(2) */ +# define HASSETRLIMIT 1 /* has setrlimit(2) */ +# define HASSETREUID 1 /* has setreuid(2) */ +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_error=0 */ +# define NEEDPUTENV 1 /* needs putenv (written in terms of setenv) */ +# define NEEDGETOPT 0 /* 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 statfs() implementation */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_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 /* ! S_IREAD */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TIMEZONE +# endif /* ! TZ_TYPE */ +# ifndef IDENTPROTO +# define IDENTPROTO 1 +# endif /* ! IDENTPROTO */ +# ifndef SHARE_V1 +# define SHARE_V1 1 /* version 1 of the fair share scheduler */ +# endif /* ! SHARE_V1 */ +# if !defined(__GNUC__ ) +# define UID_T int /* GNUC gets it right, ConvexC botches */ +# define GID_T int /* GNUC gets it right, ConvexC botches */ +# endif /* !defined(__GNUC__ ) */ +# if SECUREWARE +# define FORK fork /* SecureWare wants the real fork! */ +# else /* SECUREWARE */ +# define FORK vfork /* the rest of the OS versions don't care */ +# endif /* SECUREWARE */ +#endif /* _CONVEX_SOURCE */ + + +/* +** 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 /* ! HASFLOCK */ +# 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 statfs() implementation */ +# define LA_TYPE LA_INT +# define LA_AVENRUN "avenrun" +# define _PATH_UNIX "/unix" +# undef WIFEXITED + +# define setpgid setpgrp + +typedef int pid_t; +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int +typedef int (*sigfunc_t)(); +extern char *getenv(); +extern void *malloc(); + +/* added for RISC/os 4.01...which is dumber than 4.50 */ +# ifdef RISCOS_4_0 +# ifndef ARBPTR_T +# define ARBPTR_T char * +# endif /* ! ARBPTR_T */ +# undef HASFLOCK +# define HASFLOCK 0 +# endif /* RISCOS_4_0 */ + +# include + +#endif /* RISCOS */ + + +/* +** Linux 0.99pl10 and above... +** +** Thanks to, in reverse order of contact: +** +** John Kennedy +** Andrew Pam +** Florian La Roche +** Karl London +** +** Last compiled against: [07/21/98 @ 11:47:34 AM (Tuesday)] +** sendmail 8.9.1 bind-8.1.2 db-2.4.14 +** gcc-2.8.1 glibc-2.0.94 linux-2.1.109 +** +** NOTE: Override HASFLOCK as you will but, as of 1.99.6, mixed-style +** file locking is no longer allowed. In particular, make sure +** your DBM library and sendmail are both using either flock(2) +** *or* fcntl(2) file locking, but not both. +*/ + +#ifdef __linux__ +# define BSD 1 /* include BSD defines */ +# define USESETEUID 0 /* Have it due to POSIX, but doesn't work */ +# 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 /* ! HASSNPRINTF */ +# define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define GIDSET_T gid_t /* from */ +# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ +# ifndef IP_SRCROUTE +# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ +# endif /* ! IP_SRCROUTE */ +# ifndef HAS_IN_H +# define HAS_IN_H 1 /* use netinet/in.h */ +# endif /* ! HAS_IN_H */ +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +# ifndef HASFLOCK +# include +# if LINUX_VERSION_CODE < 66399 +# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ +# else /* LINUX_VERSION_CODE < 66399 */ +# define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */ +# endif /* LINUX_VERSION_CODE < 66399 */ +# endif /* ! HASFLOCK */ +# ifndef LA_TYPE +# define LA_TYPE LA_PROCSTR +# endif /* ! LA_TYPE */ +# define SFS_TYPE SFS_VFS /* use statfs() impl */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_NONE /* no standard for Linux */ +# endif /* ! TZ_TYPE */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# include +# undef atol /* wounded in */ +# if NETINET6 + /* + ** Indirectly included from glibc's . IPv6 support is native + ** in 2.1 and later, but the APIs appear before the functions. + */ +# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define GLIBC_VERSION ((__GLIBC__ << 8) + __GLIBC_MINOR__) +# if (GLIBC_VERSION >= 0x201) +# undef IPPROTO_ICMPV6 /* linux #defines, glibc enums */ +# else /* (GLIBC_VERSION >= 0x201) */ +# include /* IPv6 support */ +# endif /* (GLIBC_VERSION >= 0x201) */ +# if (GLIBC_VERSION == 0x201 && !defined(NEEDSGETIPNODE)) + /* Have APIs in , but no support in glibc */ +# define NEEDSGETIPNODE 1 +# endif /* (GLIBC_VERSION == 0x201 && ! NEEDSGETIPNODE) */ +# undef GLIBC_VERSION +# endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ +# endif /* NETINET6 */ +# ifndef HASFCHOWN +# define HASFCHOWN 1 /* fchown(2) */ +# endif /* ! HASFCHOWN */ +#endif /* __linux__ */ + + +/* +** DELL SVR4 Issue 2.2, and others +** From Kimmo Suominen +** +** It's on #ifdef DELL_SVR4 because Solaris also gets __svr4__ +** defined, and the definitions conflict. +** +** Peter Wemm 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 /* DELL_SVR4 */ + + +/* +** Apple A/UX 3.0 +*/ + +#ifdef _AUX_SOURCE +# include +# 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 BOGUS_O_EXCL 1 /* exclusive open follows symlinks */ +# 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 /* has setvbuf(3) in libc */ +# define HASSTRERROR 1 /* has strerror(3) */ +# define SIGFUNC_DEFINED /* sigfunc_t already defined */ +# define SIGFUNC_RETURN /* POSIX-mode */ +# define SIGFUNC_DECL void /* POSIX-mode */ +# define ERRLIST_PREDEFINED 1 +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef LA_TYPE +# define LA_TYPE LA_INT +# define FSHIFT 16 +# endif /* ! LA_TYPE */ +# define LA_AVENRUN "avenrun" +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define TZ_TYPE TZ_TZNAME +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" /* should be in */ +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# undef WIFEXITED +# undef WEXITSTATUS +#endif /* _AUX_SOURCE */ + + +/* +** 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 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 /* UMAXV */ + + +/* +** Stardent Titan 3000 running TitanOS 4.2. +** +** Must be compiled in "cc -43" mode. +** +** From Kate Hedstrom . +** +** Note the tweaking below after the BSD defines are set. +*/ + +#ifdef titan +# define setpgid setpgrp +typedef int pid_t; +# undef WIFEXITED +# undef WEXITSTATUS +#endif /* titan */ + + +/* +** Sequent DYNIX 3.2.0 +** +** From Jim Davis . +*/ + +#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 */ +# endif /* _POSIX_VERSION */ +# 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 /* ! IDENTPROTO */ + +# ifndef _PATH_UNIX +# define _PATH_UNIX "/dynix" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +#endif /* sequent */ + + +/* +** Sequent DYNIX/ptx v2.0 (and higher) +** +** For DYNIX/ptx v1.x, undefine HASSETREUID. +** +** From Tim Wright . +** Update from Jack Woolley , 26 Dec 1995, +** for DYNIX/ptx 4.0.2. +*/ + +#ifdef _SEQUENT_ +# include +# 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 statfs() impl */ +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* _SEQUENT_ */ + + +/* +** Cray Unicos +** +** Ported by David L. Kensiski, Sterling Sofware +*/ + +#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 /* UNICOS */ + + +/* +** Apollo DomainOS +** +** From Todd Martin & Don Lewis +** +** 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 */ +# 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 +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# 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 /* ! IDENTPROTO */ +# define RLIMIT_NEEDS_SYS_TIME_H 1 +# if defined(NGROUPS_MAX) && !NGROUPS_MAX +# undef NGROUPS_MAX +# endif /* defined(NGROUPS_MAX) && !NGROUPS_MAX */ +#endif /* apollo */ + +/* +** System V Rel 5.x (a.k.a Unixware7 w/o BSD-Compatibility Libs ie. native) +** +** Contributed by Paul Gampe +*/ + +#ifdef __svr5__ +# include +# define __svr4__ +# define SYS5SIGNALS 1 +# define HASSETSID 1 +# define HASSETREUID 1 +# define HASWAITPID 1 +# define HASGETDTABLESIZE 1 +# define GIDSET_T gid_t +# define SOCKADDR_LEN_T size_t +# define SOCKOPT_LEN_T size_t +# ifndef _PATH_UNIX +# define _PATH_UNIX "/stand/unix" +# endif /* ! _PATH_UNIX */ +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* unsure */ +# endif /* SYSLOG_BUFSIZE */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __svr5__ */ + +/* ###################################################################### */ + +/* +** UnixWare 2.x +*/ + +#ifdef UNIXWARE2 +# define UNIXWARE 1 +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ +#endif /* UNIXWARE2 */ + + +/* +** UnixWare 1.1.2. +** +** Updated by Petr Lampa . +** From Evan Champion . +*/ + +#ifdef UNIXWARE +# include +# 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 +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# define SYSLOG_BUFSIZE 128 +#endif /* UNIXWARE */ + + +/* +** Intergraph CLIX 3.1 +** +** From Paul Southworth +*/ + +#ifdef CLIX +# define SYSTEM5 1 /* looks like System V */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# endif /* ! HASGETUSERSHELL */ +# 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 /* CLIX */ + + +/* +** NCR MP-RAS 2.x (SysVr4) with Wollongong TCP/IP +** +** From Kevin Darcy . +*/ + +#ifdef NCR_MP_RAS2 +# include +# define __svr4__ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ +# define SYSLOG_BUFSIZE 1024 +# define SPT_TYPE SPT_NONE +#endif /* NCR_MP_RAS2 */ + + +/* +** NCR MP-RAS 3.x (SysVr4) with STREAMware TCP/IP +** +** From Tom Moore +*/ + +#ifdef NCR_MP_RAS3 +# define __svr4__ +# define HASFCHOWN 1 /* has fchown(2) call */ +# define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM has non-std interface */ +# define SYSLOG_BUFSIZE 1024 +# define SPT_TYPE SPT_NONE +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE +# define _XOPEN_SOURCE_EXTENDED 1 +# include +# undef _XOPEN_SOURCE +# undef _XOPEN_SOURCE_EXTENDED +# endif /* ! _XOPEN_SOURCE */ +#endif /* NCR_MP_RAS3 */ + + +/* +** Tandem NonStop-UX SVR4 +** +** From Rick McCarty . +*/ + +#ifdef NonStop_UX_BXX +# define __svr4__ +#endif /* NonStop_UX_BXX */ + + +/* +** Hitachi 3050R/3050RX and 3500 Workstations running HI-UX/WE2. +** +** Tested for 1.04, 1.03 +** From Akihiro Hashimoto ("Hash") . +** +** Tested for 4.02, 6.10 and 7.10 +** From Motonori NAKAMURA . +*/ + +#if !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) +# define SYSTEM5 1 /* include all the System V defines */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define setreuid(r, e) setresuid(r, e, -1) +# define LA_TYPE LA_FLOAT +# define SPT_TYPE SPT_PSTAT +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# ifndef HASSETVBUF +# define HASSETVBUF /* HI-UX has no setlinebuf */ +# endif /* ! HASSETVBUF */ +# ifndef GIDSET_T +# define GIDSET_T gid_t +# endif /* ! GIDSET_T */ +# ifndef _PATH_UNIX +# define _PATH_UNIX "/HI-UX" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ +# endif /* ! HASGETUSERSHELL */ +# define FDSET_CAST (int *) /* cast for fd_set parameters to select */ + +/* +** avoid m_flags conflict between Berkeley DB 1.85 db.h & sys/sysmacros.h +** on HIUX 3050 +*/ +# undef m_flags + +# ifdef __STDC__ +extern int syslog(int, char *, ...); +# else /* __STDC__ */ +extern int syslog(); +# endif /* __STDC__ */ + +#endif /* !defined(__hpux) && (defined(_H3050R) || defined(_HIUX_SOURCE)) */ + + +/* +** Amdahl UTS System V 2.1.5 (SVr3-based) +** +** From: Janet Jackson . +*/ + +#ifdef _UTS +# include +# 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 */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) function */ +# endif /* ! HASGETUSERSHELL */ +# 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" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +#endif /* _UTS */ + +/* +** Cray Computer Corporation's CSOS +** +** From Scott Bolte . +*/ + +#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 /* _CRAYCOM */ + + +/* +** Sony NEWS-OS 4.2.1R and 6.0.3 +** +** From Motonori NAKAMURA . +*/ + +#ifdef sony_news +# ifndef __svr4 + /* NEWS-OS 4.2.1R */ +# ifndef BSD +# define BSD /* has BSD routines */ +# endif /* ! BSD */ +# 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 statfs() implementation */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +# define MODE_T int /* system include files have no mode_t */ +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int + +# else /* ! __svr4 */ + /* NEWS-OS 6.0.3 with /bin/cc */ +# ifndef __svr4__ +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ +# 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 /* ! SPT_TYPE */ +# define GIDSET_T gid_t +# undef WIFEXITED +# undef WEXITSTATUS +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 256 +# endif /* ! SYSLOG_BUFSIZE */ +# define _PATH_UNIX "/stand/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ + +# endif /* ! __svr4 */ +#endif /* sony_news */ + + +/* +** Omron LUNA/UNIOS-B 3.0, LUNA2/Mach and LUNA88K Mach +** +** From Motonori NAKAMURA . +*/ + +#ifdef luna +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +# 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 +# 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 /* uniosb */ +# ifdef luna2 +# define LA_TYPE LA_SUBR +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# endif /* luna2 */ +# ifdef luna88k +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define LA_TYPE LA_INT +# endif /* luna88k */ +# define SFS_TYPE SFS_VFS /* use statfs() implementation */ +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED +# define SIGFUNC_RETURN (0) +# define SIGFUNC_DECL int +extern char *getenv(); +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +#endif /* luna */ + + +/* +** NEC EWS-UX/V 4.2 (with /usr/ucb/cc) +** +** From Motonori NAKAMURA . +*/ + +#if defined(nec_ews_svr4) || defined(_nec_ews_svr4) +# ifndef __svr4__ +# define __svr4__ /* use all System V Release 4 defines below */ +# endif /* ! __svr4__ */ +# 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 _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ +# endif /* ! SYSLOG_BUFSIZE */ +#endif /* defined(nec_ews_svr4) || defined(_nec_ews_svr4) */ + + +/* +** Fujitsu/ICL UXP/DS (For the DS/90 Series) +** +** From Diego R. Lopez . +** Additional changes from Fumio Moriya and Toshiaki Nomura of the +** Fujitsu Fresoftware group . +*/ + +#ifdef __uxp__ +# include +# include +# include +# define __svr4__ +# define HASGETUSERSHELL 0 +# define HASFLOCK 0 +# if UXPDS == 10 +# define HASSNPRINTF 0 /* no snprintf(3) or vsnprintf(3) */ +# else /* UXPDS == 10 */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# endif /* UXPDS == 10 */ +# define _PATH_UNIX "/stand/unix" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +#endif /* __uxp__ */ + +/* +** Pyramid DC/OSx +** +** From Earle Ake . +*/ + +#ifdef DCOSx +# define GIDSET_T gid_t +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif /* ! IDENTPROTO */ +#endif /* DCOSx */ + +/* +** Concurrent Computer Corporation Maxion +** +** From Donald R. Laster Jr. . +*/ + +#ifdef __MAXION__ + +# include +# define __svr4__ 1 /* SVR4.2MP */ +# define HASSETREUID 1 /* have setreuid(2) */ +# define HASLSTAT 1 /* have lstat(2) */ +# define HASSETRLIMIT 1 /* have setrlimit(2) */ +# define HASGETDTABLESIZE 1 /* have getdtablesize(2) */ +# define HASSNPRINTF 1 /* have snprintf(3) */ +# define HASGETUSERSHELL 1 /* have getusershell(3) */ +# define NOFTRUNCATE 1 /* do not have ftruncate(2) */ +# define SLEEP_T unsigned +# define SFS_TYPE SFS_STATVFS +# define SFS_BAVAIL f_bavail +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 256 /* Use 256 bytes */ +# endif /* ! SYSLOG_BUFSIZE */ + +# undef WUNTRACED +# undef WIFEXITED +# undef WIFSIGNALED +# undef WIFSTOPPED +# undef WEXITSTATUS +# undef WTERMSIG +# undef WSTOPSIG + +#endif /* __MAXION__ */ + +/* +** Harris Nighthawk PowerUX (nh6000 box) +** +** Contributed by Bob Miorelli, Pratt & Whitney +*/ + +#ifdef _PowerUX +# ifndef __svr4__ +# define __svr4__ +# endif /* ! __svr4__ */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# define SYSLOG_BUFSIZE 1024 +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define LA_TYPE LA_ZERO +typedef struct msgb mblk_t; +# undef offsetof /* avoid stddefs.h and sys/sysmacros.h conflict */ +#endif /* _PowerUX */ + +/* +** Siemens Nixdorf Informationssysteme AG SINIX +** +** Contributed by Gerald Rinske +** of Siemens Business Services VAS. +*/ +#ifdef sinix +# define SYSLOG_BUFSIZE 1024 +#endif /* sinix */ + +/* +** CRAY T3E +** +** Contributed by Manu Mahonen +** of Center for Scientific Computing. +*/ +#ifdef _CRAY +# define GET_IPOPT_DST(dst) *(struct in_addr *)&(dst) +#endif /* _CRAY */ + +/* +** Motorola 922, MC88110, UNIX SYSTEM V/88 Release 4.0 Version 4.3 +** +** Contributed by Sergey Rusanov +*/ + +#ifdef MOTO +# define HASFCHMOD 1 +# define HASSETRLIMIT 0 +# define HASSETSID 1 +# define HASSETREUID 1 +# define HASULIMIT 1 +# define HASWAITPID 1 +# define HASGETDTABLESIZE 1 +# define HASGETUSERSHELL 1 +# define IP_SRCROUTE 0 +# define IDENTPROTO 0 +# define RES_DNSRCH_VARIABLE _res_dnsrch +# define _PATH_UNIX "/unix" +# define _PATH_VENDOR_CF "/etc/sendmail.cf" +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +#endif /* MOTO */ + +/********************************************************************** +** 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 /* ! IP_SRCROUTE */ +# ifndef HASSETRLIMIT +# define HASSETRLIMIT 1 /* has setrlimit(2) call */ +# endif /* ! HASSETRLIMIT */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif /* ! HASFLOCK */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */ +# endif /* ! TZ_TYPE */ +#endif /* BSD */ + +/* general System V Release 4 defines */ +#ifdef __svr4__ +# define SYSTEM5 1 +# define USESETEUID 1 /* has usable 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 /* ! HASSETRLIMIT */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# endif /* ! HASGETUSERSHELL */ +# ifndef HASFCHMOD +# define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */ +# endif /* ! HASFCHMOD */ + +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" +# endif /* ! _PATH_UNIX */ +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" +# endif /* ! _PATH_VENDOR_CF */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" +# endif /* ! _PATH_SENDMAILPID */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 128 +# endif /* ! SYSLOG_BUFSIZE */ +# ifndef SFS_TYPE +# define SFS_TYPE SFS_STATVFS +# endif /* ! SFS_TYPE */ + +# define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ +#endif /* __svr4__ */ + +/* general System V defines */ +#ifdef SYSTEM5 +# include +# 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 /* ! HASULIMIT */ +# ifndef LA_TYPE +# ifdef MIOC_READKSYM +# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ +# else /* MIOC_READKSYM */ +# define LA_TYPE LA_INT /* assume integer load average */ +# endif /* MIOC_READKSYM */ +# endif /* ! LA_TYPE */ +# ifndef SFS_TYPE +# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ +# endif /* ! SFS_TYPE */ +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif /* ! TZ_TYPE */ +#endif /* SYSTEM5 */ + +/* 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 usable seteuid(2) call */ +# endif /* _POSIX_VERSION >= 199500 && !defined(USESETEUID) */ +#endif /* _POSIX_VERSION */ + /* +** 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 /* titan */ + +#ifdef _CRAYCOM +# undef HASSETSID /* despite POSIX claim, doesn't have setsid */ +#endif /* _CRAYCOM */ + +#ifdef MOTO +# undef USESETEUID +#endif /* MOTO */ + +/* +** 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 _FILTER_PROHIB. If +** not explicitly set to zero above, default it on. +*/ + +#ifndef IDENTPROTO +# define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */ +#endif /* ! IDENTPROTO */ + +#ifndef IP_SRCROUTE +# define IP_SRCROUTE 1 /* Detect IP source routing */ +#endif /* ! IP_SRCROUTE */ + +#ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 1 /* libc has getusershell(3) call */ +#endif /* ! HASGETUSERSHELL */ + +#ifndef NETUNIX +# define NETUNIX 1 /* include unix domain support */ +#endif /* ! NETUNIX */ + +#ifndef HASRANDOM +# define HASRANDOM 1 /* has random(3) support */ +#endif /* ! HASRANDOM */ + +#ifndef HASFLOCK +# define HASFLOCK 0 /* assume no flock(2) support */ +#endif /* ! HASFLOCK */ + +#ifndef HASSETREUID +# define HASSETREUID 0 /* assume no setreuid(2) call */ +#endif /* ! HASSETREUID */ + +#ifndef HASFCHMOD +# define HASFCHMOD 0 /* assume no fchmod(2) syscall */ +#endif /* ! HASFCHMOD */ + +#ifndef USESETEUID +# define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */ +#endif /* ! USESETEUID */ + +#ifndef HASSETRLIMIT +# define HASSETRLIMIT 0 /* assume no setrlimit(2) support */ +#endif /* ! HASSETRLIMIT */ + +#ifndef HASULIMIT +# define HASULIMIT 0 /* assume no ulimit(2) support */ +#endif /* ! HASULIMIT */ + +#ifndef SECUREWARE +# define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */ +#endif /* ! SECUREWARE */ + +#ifndef USE_SIGLONGJMP +# define USE_SIGLONGJMP 0 /* assume setjmp handles signals properly */ +#endif /* ! USE_SIGLONGJMP */ + +#ifndef FDSET_CAST +# define FDSET_CAST /* (empty) cast for fd_set arg to select */ +#endif /* ! FDSET_CAST */ + +/* +** Pick a mailer setuid method for changing the current uid +*/ + +#define USE_SETEUID 0 +#define USE_SETREUID 1 +#define USE_SETUID 2 + +#if USESETEUID +# define MAILER_SETUID_METHOD USE_SETEUID +#else /* USESETEUID */ +# if HASSETREUID +# define MAILER_SETUID_METHOD USE_SETREUID +# else /* HASSETREUID */ +# define MAILER_SETUID_METHOD USE_SETUID +# endif /* HASSETREUID */ +#endif /* USESETEUID */ + +/* +** 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 /* ! GIDSET_T */ + +#ifndef UID_T +# define UID_T uid_t +#endif /* ! UID_T */ + +#ifndef GID_T +# define GID_T gid_t +#endif /* ! GID_T */ + +#ifndef SIZE_T +# define SIZE_T size_t +#endif /* ! SIZE_T */ + +#ifndef MODE_T +# define MODE_T mode_t +#endif /* ! MODE_T */ + +#ifndef ARGV_T +# define ARGV_T char ** +#endif /* ! ARGV_T */ + +#ifndef SOCKADDR_LEN_T +# define SOCKADDR_LEN_T int +#endif /* ! SOCKADDR_LEN_T */ + +#ifndef SOCKOPT_LEN_T +# define SOCKOPT_LEN_T int +#endif /* ! SOCKOPT_LEN_T */ + +#ifndef QUAD_T +# define QUAD_T unsigned long +#endif /* ! QUAD_T */ + /********************************************************************** +** 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 /* ! S_ISREG */ +#ifndef S_ISDIR +# define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR) +#endif /* ! S_ISDIR */ +#if !defined(S_ISLNK) && defined(S_IFLNK) +# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) +#endif /* !defined(S_ISLNK) && defined(S_IFLNK) */ +#if !defined(S_ISFIFO) +# if defined(S_IFIFO) +# define S_ISFIFO(foo) ((foo & S_IFMT) == S_IFIFO) +# else /* defined(S_IFIFO) */ +# define S_ISFIFO(foo) FALSE +# endif /* defined(S_IFIFO) */ +#endif /* !defined(S_ISFIFO) */ +#ifndef S_IRUSR +# define S_IRUSR 0400 +#endif /* ! S_IRUSR */ +#ifndef S_IWUSR +# define S_IWUSR 0200 +#endif /* ! S_IWUSR */ +#ifndef S_IRGRP +# define S_IRGRP 0040 +#endif /* ! S_IRGRP */ +#ifndef S_IWGRP +# define S_IWGRP 0020 +#endif /* ! S_IWGRP */ +#ifndef S_IROTH +# define S_IROTH 0004 +#endif /* ! S_IROTH */ +#ifndef S_IWOTH +# define S_IWOTH 0002 +#endif /* ! S_IWOTH */ + +/* close-on-exec flag */ +#ifndef FD_CLOEXEC +# define FD_CLOEXEC 1 +#endif /* ! FD_CLOEXEC */ + +/* +** 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 /* ! EX_CONFIG */ + +/* pseudo-codes */ +#define EX_QUIT 22 /* drop out of server immediately */ +#define EX_RESTART 23 /* restart sendmail daemon */ +#define EX_SHUTDOWN 24 /* shutdown sendmail daemon */ + +/* pseudo-code used for mci_setstat */ +#define EX_NOTSTICKY -5 /* don't save persistent status */ + + +/* +** An "impossible" file mode to indicate that the file does not exist. +*/ + +#define ST_MODE_NOFILE 0171147 /* unlikely to occur */ + + +/* type of arbitrary pointer */ +#ifndef ARBPTR_T +# define ARBPTR_T void * +#endif /* ! ARBPTR_T */ + +#ifndef __P +# include "sendmail/cdefs.h" +#endif /* ! __P */ + +#if HESIOD && !defined(NAMED_BIND) +# define NAMED_BIND 1 /* not one without the other */ +#endif /* HESIOD && !defined(NAMED_BIND) */ + +#if NAMED_BIND && !defined(__ksr__) && !defined(h_errno) +extern int h_errno; +#endif /* NAMED_BIND && !defined(__ksr__) && !defined(h_errno) */ + +#ifdef LDAPMAP +# include +# include +# include + +/* Some LDAP constants */ +# define LDAPMAP_FALSE 0 +# define LDAPMAP_TRUE 1 + +/* +** ldap_init(3) is broken in Umich 3.x and OpenLDAP 1.0/1.1. +** Use the lack of LDAP_OPT_SIZELIMIT to detect old API implementations +** and assume (falsely) that all old API implementations are broken. +** (OpenLDAP 1.2 and later have a working ldap_init(), add -DUSE_LDAP_INIT) +*/ + +# if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) +# define USE_LDAP_INIT 1 +# endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_INIT) */ + +/* +** LDAP_OPT_SIZELIMIT is not defined under Umich 3.x nor OpenLDAP 1.x, +** hence ldap_set_option() must not exist. +*/ + +# if defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) +# define USE_LDAP_SET_OPTION 1 +# endif /* defined(LDAP_OPT_SIZELIMIT) && !defined(USE_LDAP_SET_OPTION) */ + +#endif /* LDAPMAP */ + +/* +** Do some required dependencies +*/ + +#if NETINET || NETINET6 || NETISO +# ifndef SMTP +# define SMTP 1 /* enable user and server SMTP */ +# endif /* ! SMTP */ +# ifndef QUEUE +# define QUEUE 1 /* enable queueing */ +# endif /* ! QUEUE */ +# ifndef DAEMON +# define DAEMON 1 /* include the daemon (requires IPC & SMTP) */ +# endif /* ! DAEMON */ +#endif /* NETINET || NETINET6 || NETISO */ + + +/* +** Arrange to use either varargs or stdargs +*/ + +#ifdef __STDC__ + +# include + +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap, f) +# define VA_END va_end(ap) + +#else /* __STDC__ */ + +# include + +# define VA_LOCAL_DECL va_list ap; +# define VA_START(f) va_start(ap) +# define VA_END va_end(ap) + +#endif /* __STDC__ */ + +#if HASUNAME +# include +# ifdef newstr +# undef newstr +# endif /* newstr */ +#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_SYSTEM_V) +# define MAXHOSTNAMELEN 256 +#endif /* !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V) */ + +#if !defined(SIGCHLD) && defined(SIGCLD) +# define SIGCHLD SIGCLD +#endif /* !defined(SIGCHLD) && defined(SIGCLD) */ + +#ifndef STDIN_FILENO +# define STDIN_FILENO 0 +#endif /* ! STDIN_FILENO */ + +#ifndef STDOUT_FILENO +# define STDOUT_FILENO 1 +#endif /* ! STDOUT_FILENO */ + +#ifndef STDERR_FILENO +# define STDERR_FILENO 2 +#endif /* ! STDERR_FILENO */ + +#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 /* ! LOCK_SH */ + +#ifndef S_IXOTH +# define S_IXOTH (S_IEXEC >> 6) +#endif /* ! S_IXOTH */ + +#ifndef S_IXGRP +# define S_IXGRP (S_IEXEC >> 3) +#endif /* ! S_IXGRP */ + +#ifndef S_IXUSR +# define S_IXUSR (S_IEXEC) +#endif /* ! S_IXUSR */ + +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif /* ! SEEK_SET */ + +#ifndef SIG_ERR +# define SIG_ERR ((void (*)()) -1) +#endif /* ! SIG_ERR */ + +#ifndef WEXITSTATUS +# define WEXITSTATUS(st) (((st) >> 8) & 0377) +#endif /* ! WEXITSTATUS */ +#ifndef WIFEXITED +# define WIFEXITED(st) (((st) & 0377) == 0) +#endif /* ! WIFEXITED */ +#ifndef WIFSTOPPED +# define WIFSTOPPED(st) (((st) & 0100) == 0) +#endif /* ! WIFSTOPPED */ +#ifndef WCOREDUMP +# define WCOREDUMP(st) (((st) & 0200) != 0) +#endif /* ! WCOREDUMP */ +#ifndef WTERMSIG +# define WTERMSIG(st) (((st) & 0177)) +#endif /* ! WTERMSIG */ + +#ifndef SIGFUNC_DEFINED +typedef void (*sigfunc_t) __P((int)); +#endif /* ! SIGFUNC_DEFINED */ +#ifndef SIGFUNC_RETURN +# define SIGFUNC_RETURN +#endif /* ! SIGFUNC_RETURN */ +#ifndef SIGFUNC_DECL +# define SIGFUNC_DECL void +#endif /* ! SIGFUNC_DECL */ + +/* size of syslog buffer */ +#ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 +#endif /* ! SYSLOG_BUFSIZE */ + +/* +** 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 fork /* function to call to fork mailer */ +#endif /* ! FORK */ + + +/* random routine -- set above using #ifdef _osname_ or in Makefile */ +#if HASRANDOM +# define get_random() random() +#else /* HASRANDOM */ +# define get_random() ((long) rand()) +# ifndef RANDOMSHIFT +# define RANDOMSHIFT 8 +# endif /* RANDOMSHIFT */ +#endif /* HASRANDOM */ + +/* +** Default to using scanf in readcf. +*/ + +#ifndef SCANF +# define SCANF 1 +#endif /* ! SCANF */ + +#if _FFR_MILTER +/* 32 bit type */ +# ifndef SM_INT32 +# define SM_INT32 int32_t +# endif /* SM_INT32 */ +#endif /* _FFR_MILTER */ + +/* +** SVr4 and similar systems use different routines for setjmp/longjmp +** with signal support +*/ + +#if USE_SIGLONGJMP +# ifdef jmp_buf +# undef jmp_buf +# endif /* jmp_buf */ +# define jmp_buf sigjmp_buf +# ifdef setjmp +# undef setjmp +# endif /* setjmp */ +# define setjmp(env) sigsetjmp(env, 1) +# ifdef longjmp +# undef longjmp +# endif /* longjmp */ +# define longjmp(env, val) siglongjmp(env, val) +#endif /* USE_SIGLONGJMP */ + +#if !defined(NGROUPS_MAX) && defined(NGROUPS) +# define NGROUPS_MAX NGROUPS /* POSIX naming convention */ +#endif /* !defined(NGROUPS_MAX) && defined(NGROUPS) */ + +/* +** If we don't have a system syslog, simulate it. +*/ + +#if !LOG +# define LOG_EMERG 0 /* system is unusable */ +# define LOG_ALERT 1 /* action must be taken immediately */ +# define LOG_CRIT 2 /* critical conditions */ +# define LOG_ERR 3 /* error conditions */ +# define LOG_WARNING 4 /* warning conditions */ +# define LOG_NOTICE 5 /* normal but significant condition */ +# define LOG_INFO 6 /* informational */ +# define LOG_DEBUG 7 /* debug-level messages */ +#endif /* !LOG */ + + +#endif /* CONF_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/control.c b/gnu/usr.sbin/sendmail/sendmail/control.c new file mode 100644 index 00000000000..42965243bfa --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/control.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: control.c,v 8.44 1999/11/29 22:03:49 ca Exp $"; +#endif /* ! lint */ + +#include + +int ControlSocket = -1; + + /* +** OPENCONTROLSOCKET -- create/open the daemon control named socket +** +** Creates and opens a named socket for external control over +** the sendmail daemon. +** +** Parameters: +** none. +** +** Returns: +** 0 if successful, -1 otherwise +*/ + +int +opencontrolsocket() +{ +#if NETUNIX + int save_errno; + int rval; + long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN; + struct sockaddr_un controladdr; + + if (ControlSocketName == NULL) + return 0; + + if (strlen(ControlSocketName) >= sizeof controladdr.sun_path) + { + errno = ENAMETOOLONG; + return -1; + } + + rval = safefile(ControlSocketName, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR|S_IWUSR, NULL); + + /* if not safe, don't create */ + if (rval != 0) + { + errno = rval; + return -1; + } + + ControlSocket = socket(AF_UNIX, SOCK_STREAM, 0); + if (ControlSocket < 0) + return -1; + + (void) unlink(ControlSocketName); + memset(&controladdr, '\0', sizeof controladdr); + controladdr.sun_family = AF_UNIX; + (void) strlcpy(controladdr.sun_path, ControlSocketName, + sizeof controladdr.sun_path); + + if (bind(ControlSocket, (struct sockaddr *) &controladdr, + sizeof controladdr) < 0) + { + save_errno = errno; + clrcontrol(); + errno = save_errno; + return -1; + } + + if (geteuid() == 0 && TrustedUid != 0) + { + if (chown(ControlSocketName, TrustedUid, -1) < 0) + { + save_errno = errno; + sm_syslog(LOG_ALERT, NOQID, + "ownership change on %s failed: %s", + ControlSocketName, errstring(save_errno)); + message("050 ownership change on %s failed: %s", + ControlSocketName, errstring(save_errno)); + closecontrolsocket(TRUE); + errno = save_errno; + return -1; + } + } + + if (chmod(ControlSocketName, S_IRUSR|S_IWUSR) < 0) + { + save_errno = errno; + closecontrolsocket(TRUE); + errno = save_errno; + return -1; + } + + if (listen(ControlSocket, 8) < 0) + { + save_errno = errno; + closecontrolsocket(TRUE); + errno = save_errno; + return -1; + } +#endif /* NETUNIX */ + return 0; +} + /* +** CLOSECONTROLSOCKET -- close the daemon control named socket +** +** Close a named socket. +** +** Parameters: +** fullclose -- if set, close the socket and remove it; +** otherwise, just remove it +** +** Returns: +** none. +*/ + +void +closecontrolsocket(fullclose) + bool fullclose; +{ +#if NETUNIX + long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN; + + if (ControlSocket >= 0) + { + int rval; + + if (fullclose) + { + (void) close(ControlSocket); + ControlSocket = -1; + } + + rval = safefile(ControlSocketName, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR|S_IWUSR, NULL); + + /* if not safe, don't unlink */ + if (rval != 0) + return; + + if (unlink(ControlSocketName) < 0) + { + sm_syslog(LOG_WARNING, NOQID, + "Could not remove control socket: %s", + errstring(errno)); + return; + } + } +#endif /* NETUNIX */ + return; +} + /* +** CLRCONTROL -- reset the control connection +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** releases any resources used by the control interface. +*/ + +void +clrcontrol() +{ +#if NETUNIX + if (ControlSocket >= 0) + (void) close(ControlSocket); + ControlSocket = -1; +#endif /* NETUNIX */ +} + +#ifndef NOT_SENDMAIL + + /* +** CONTROL_COMMAND -- read and process command from named socket +** +** Read and process the command from the opened socket. +** Exits when done since it is running in a forked child. +** +** Parameters: +** sock -- the opened socket from getrequests() +** e -- the current envelope +** +** Returns: +** none. +*/ + +struct cmd +{ + char *cmd_name; /* command name */ + int cmd_code; /* internal code, see below */ +}; + +/* values for cmd_code */ +# define CMDERROR 0 /* bad command */ +# define CMDRESTART 1 /* restart daemon */ +# define CMDSHUTDOWN 2 /* end daemon */ +# define CMDHELP 3 /* help */ +# define CMDSTATUS 4 /* daemon status */ + +static struct cmd CmdTab[] = +{ + { "help", CMDHELP }, + { "restart", CMDRESTART }, + { "shutdown", CMDSHUTDOWN }, + { "status", CMDSTATUS }, + { NULL, CMDERROR } +}; + +static jmp_buf CtxControlTimeout; + +static void +controltimeout(timeout) + time_t timeout; +{ + longjmp(CtxControlTimeout, 1); +} + +void +control_command(sock, e) + int sock; + ENVELOPE *e; +{ + volatile int exitstat = EX_OK; + FILE *s = NULL; + EVENT *ev = NULL; + FILE *traffic; + FILE *oldout; + char *cmd; + char *p; + struct cmd *c; + char cmdbuf[MAXLINE]; + char inp[MAXLINE]; + + sm_setproctitle(FALSE, e, "control cmd read"); + + if (TimeOuts.to_control > 0) + { + /* handle possible input timeout */ + if (setjmp(CtxControlTimeout) != 0) + { + if (LogLevel > 2) + sm_syslog(LOG_NOTICE, e->e_id, + "timeout waiting for input during control command"); + exit(EX_IOERR); + } + ev = setevent(TimeOuts.to_control, controltimeout, + TimeOuts.to_control); + } + + s = fdopen(sock, "r+"); + if (s == NULL) + { + int save_errno = errno; + + (void) close(sock); + errno = save_errno; + exit(EX_IOERR); + } + setbuf(s, NULL); + + if (fgets(inp, sizeof inp, s) == NULL) + { + (void) fclose(s); + exit(EX_IOERR); + } + (void) fflush(s); + + /* clean up end of line */ + fixcrlf(inp, TRUE); + + sm_setproctitle(FALSE, e, "control: %s", 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->cmd_name != NULL; c++) + { + if (!strcasecmp(c->cmd_name, cmdbuf)) + break; + } + + switch (c->cmd_code) + { + case CMDHELP: /* get help */ + traffic = TrafficLogFile; + TrafficLogFile = NULL; + oldout = OutChannel; + OutChannel = s; + help("control", e); + TrafficLogFile = traffic; + OutChannel = oldout; + break; + + case CMDRESTART: /* restart the daemon */ + fprintf(s, "OK\r\n"); + exitstat = EX_RESTART; + break; + + case CMDSHUTDOWN: /* kill the daemon */ + fprintf(s, "OK\r\n"); + exitstat = EX_SHUTDOWN; + break; + + case CMDSTATUS: /* daemon status */ + proc_list_probe(); + fprintf(s, "%d/%d/%ld/%d\r\n", CurChildren, MaxChildren, + freediskspace(QueueDir, NULL), sm_getla(NULL)); + proc_list_display(s); + break; + + case CMDERROR: /* unknown command */ + fprintf(s, "Bad command (%s)\r\n", cmdbuf); + break; + } + (void) fclose(s); + if (ev != NULL) + clrevent(ev); + exit(exitstat); +} +#endif /* ! NOT_SENDMAIL */ diff --git a/gnu/usr.sbin/sendmail/sendmail/convtime.c b/gnu/usr.sbin/sendmail/sendmail/convtime.c new file mode 100644 index 00000000000..5e2c885fa68 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/convtime.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: convtime.c,v 8.25 1999/06/16 21:11:26 ca Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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; + int units; +{ + register time_t t, r; + register char c; + + r = 0; + if (strcasecmp(p, "now") == 0) + return NOW; + 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; + /* FALLTHROUGH */ + + case 'd': /* days */ + /* FALLTHROUGH */ + default: + t *= 24; + /* FALLTHROUGH */ + + case 'h': /* hours */ + t *= 60; + /* FALLTHROUGH */ + + case 'm': /* minutes */ + t *= 60; + /* FALLTHROUGH */ + + 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"; + if (intvl == NOW) + return "too long"; + + /* 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; + wk = 0; + } + else + { + dy = intvl % 7; + intvl /= 7; + wk = intvl; + } + + /* now turn it into a sexy form */ + p = buf; + if (brief) + { + if (dy > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), "%d+", dy); + p += strlen(p); + } + (void) snprintf(p, SPACELEFT(buf, p), "%02d:%02d:%02d", + hr, mi, se); + return buf; + } + + /* use the verbose form */ + if (wk > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), ", %d week%s", wk, PLURAL(wk)); + p += strlen(p); + } + if (dy > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), ", %d day%s", dy, PLURAL(dy)); + p += strlen(p); + } + if (hr > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), ", %d hour%s", hr, PLURAL(hr)); + p += strlen(p); + } + if (mi > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), ", %d minute%s", mi, PLURAL(mi)); + p += strlen(p); + } + if (se > 0) + { + (void) snprintf(p, SPACELEFT(buf, p), ", %d second%s", se, PLURAL(se)); + p += strlen(p); + } + + return (buf + 2); +} diff --git a/gnu/usr.sbin/sendmail/sendmail/daemon.c b/gnu/usr.sbin/sendmail/sendmail/daemon.c new file mode 100644 index 00000000000..b4f806cfee3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/daemon.c @@ -0,0 +1,3308 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# ifdef DAEMON +static char id[] = "@(#)$Sendmail: daemon.c,v 8.399 2000/03/01 18:14:06 gshapiro Exp $ (with daemon mode)"; +# else /* DAEMON */ +static char id[] = "@(#)$Sendmail: daemon.c,v 8.399 2000/03/01 18:14:06 gshapiro Exp $ (without daemon mode)"; +# endif /* DAEMON */ +#endif /* ! lint */ + +#if defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) +# define USE_SOCK_STREAM 1 +#endif /* defined(SOCK_STREAM) || defined(__GNU_LIBRARY__) */ + +#if DAEMON || defined(USE_SOCK_STREAM) +# if NETINET || NETINET6 +# include +# endif /* NETINET || NETINET6 */ +# if NAMED_BIND +# ifndef NO_DATA +# define NO_DATA NO_ADDRESS +# endif /* ! NO_DATA */ +# endif /* NAMED_BIND */ +#endif /* DAEMON || defined(USE_SOCK_STREAM) */ + +#if DAEMON + +# include + +# if IP_SRCROUTE && NETINET +# include +# include +# if HAS_IN_H +# include +# ifndef IPOPTION +# define IPOPTION ip_opts +# define IP_LIST ip_opts +# define IP_DST ip_dst +# endif /* ! IPOPTION */ +# else /* HAS_IN_H */ +# include +# ifndef IPOPTION +# define IPOPTION ipoption +# define IP_LIST ipopt_list +# define IP_DST ipopt_dst +# endif /* ! IPOPTION */ +# endif /* HAS_IN_H */ +# endif /* IP_SRCROUTE && NETINET */ + +/* structure to describe a daemon */ +struct daemon +{ + int d_socket; /* fd for socket */ + SOCKADDR d_addr; /* socket for incoming */ + u_short d_port; /* port number */ + int d_listenqueue; /* size of listen queue */ + int d_tcprcvbufsize; /* size of TCP receive buffer */ + int d_tcpsndbufsize; /* size of TCP send buffer */ + time_t d_refuse_connections_until; + bool d_firsttime; + int d_socksize; + BITMAP256 d_flags; /* flags; see sendmail.h */ + char *d_mflags; /* flags for use in macro */ + char *d_name; /* user-supplied name */ +}; + +typedef struct daemon DAEMON_T; + +static void connecttimeout __P((void)); +static int opendaemonsocket __P((struct daemon *, bool)); +static u_short setupdaemon __P((SOCKADDR *)); + +/* +** 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(e) +** 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, e) +** 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. +*/ + +static DAEMON_T Daemons[MAXDAEMONS]; +static int ndaemons = 0; /* actual number of daemons */ + +/* options for client */ +static int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ +static int TcpSndBufferSize = 0; /* size of TCP send buffer */ + + /* +** GETREQUESTS -- open mail IPC port and get requests. +** +** Parameters: +** e -- the current envelope. +** +** Returns: +** pointer to flags. +** +** 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. +*/ + +BITMAP256 * +getrequests(e) + ENVELOPE *e; +{ + int t; + time_t last_disk_space_check = 0; + int idx, curdaemon = -1; + int i, olddaemon = 0; +# if XDEBUG + bool j_has_dot; +# endif /* XDEBUG */ + char status[MAXLINE]; + SOCKADDR sa; + SOCKADDR_LEN_T len = sizeof sa; +# if NETUNIX + extern int ControlSocket; +# endif /* NETUNIX */ + extern ENVELOPE BlankEnvelope; + +#define D(x,idx) x[idx] + + for (idx = 0; idx < ndaemons; idx++) + { + Daemons[idx].d_port = setupdaemon(&(Daemons[idx].d_addr)); + Daemons[idx].d_firsttime = TRUE; + Daemons[idx].d_refuse_connections_until = (time_t) 0; + } + /* + ** Try to actually open the connection. + */ + + if (tTd(15, 1)) + { + for (idx = 0; idx < ndaemons; idx++) + dprintf("getrequests: daemon %s: port %d\n", + Daemons[idx].d_name, + ntohs(Daemons[idx].d_port)); + } + + /* get a socket for the SMTP connection */ + for (idx = 0; idx < ndaemons; idx++) + Daemons[idx].d_socksize = opendaemonsocket(&Daemons[idx], TRUE); + + if (opencontrolsocket() < 0) + sm_syslog(LOG_WARNING, NOQID, + "daemon could not open control socket %s: %s", + ControlSocketName, errstring(errno)); + + (void) setsignal(SIGCHLD, reapchild); + + /* write the pid to file */ + log_sendmail_pid(e); + +# if XDEBUG + { + char jbuf[MAXHOSTNAMELEN]; + + expand("\201j", jbuf, sizeof jbuf, e); + j_has_dot = strchr(jbuf, '.') != NULL; + } +# endif /* XDEBUG */ + + /* Add parent process as first item */ + proc_list_add(getpid(), "Sendmail daemon", PROC_DAEMON); + + if (tTd(15, 1)) + { + for (idx = 0; idx < ndaemons; idx++) + dprintf("getrequests: daemon %s: %d\n", + Daemons[idx].d_name, + Daemons[idx].d_socket); + } + + for (;;) + { + register pid_t pid; + auto SOCKADDR_LEN_T lotherend; + bool timedout = FALSE; + bool control = FALSE; + int save_errno; + int pipefd[2]; + + /* see if we are rejecting connections */ + (void) blocksignal(SIGALRM); + + for (idx = 0; idx < ndaemons; idx++) + { + if (curtime() < Daemons[idx].d_refuse_connections_until) + continue; + if (refuseconnections(Daemons[idx].d_name, e, idx)) + { + if (Daemons[idx].d_socket >= 0) + { + /* close socket so peer fails quickly */ + (void) close(Daemons[idx].d_socket); + Daemons[idx].d_socket = -1; + } + + /* refuse connections for next 15 seconds */ + Daemons[idx].d_refuse_connections_until = curtime() + 15; + } + else if (Daemons[idx].d_socket < 0 || + Daemons[idx].d_firsttime) + { + if (!Daemons[idx].d_firsttime && LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "accepting connections again for daemon %s", + Daemons[idx].d_name); + + /* arrange to (re)open the socket if needed */ + (void) opendaemonsocket(&Daemons[idx], FALSE); + Daemons[idx].d_firsttime = FALSE; + } + } + if (curtime() >= last_disk_space_check) + { + if (!enoughdiskspace(MinBlocksFree + 1, FALSE)) + { + if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + { + /* log only if not logged before */ + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "rejecting new messages: min free: %d", + MinBlocksFree); + sm_setproctitle(TRUE, e, + "rejecting new messages: min free: %d", + MinBlocksFree); + setbitn(D_ETRNONLY, Daemons[idx].d_flags); + } + } + else if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + { + /* log only if not logged before */ + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "accepting new messages (again)"); + /* title will be set below */ + clrbitn(D_ETRNONLY, Daemons[idx].d_flags); + } + /* only check disk space once a minute */ + last_disk_space_check = curtime() + 60; + } + +# if XDEBUG + /* check for disaster */ + { + char jbuf[MAXHOSTNAMELEN]; + + expand("\201j", jbuf, sizeof jbuf, e); + if (!wordinclass(jbuf, 'w')) + { + dumpstate("daemon lost $j"); + sm_syslog(LOG_ALERT, NOQID, + "daemon process doesn't have $j in $=w; see syslog"); + abort(); + } + else if (j_has_dot && strchr(jbuf, '.') == NULL) + { + dumpstate("daemon $j lost dot"); + sm_syslog(LOG_ALERT, NOQID, + "daemon process $j lost dot; see syslog"); + abort(); + } + } +# endif /* XDEBUG */ + +# if 0 + /* + ** Andrew Sun claims that this will + ** fix the SVr4 problem. But it seems to have gone away, + ** so is it worth doing this? + */ + + if (DaemonSocket >= 0 && + SetNonBlocking(DaemonSocket, FALSE) < 0) + log an error here; +# endif /* 0 */ + (void) releasesignal(SIGALRM); + + for (;;) + { + int highest = -1; + fd_set readfds; + struct timeval timeout; + + FD_ZERO(&readfds); + + for (idx = 0; idx < ndaemons; idx++) + { + /* wait for a connection */ + if (Daemons[idx].d_socket >= 0) + { + if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + { + sm_setproctitle(TRUE, e, + "accepting connections"); + } + if (Daemons[idx].d_socket > highest) + highest = Daemons[idx].d_socket; + FD_SET(Daemons[idx].d_socket, &readfds); + } + } + +# if NETUNIX + if (ControlSocket >= 0) + { + if (ControlSocket > highest) + highest = ControlSocket; + FD_SET(ControlSocket, &readfds); + } +# endif /* NETUNIX */ + + /* + ** if one socket is closed, set the timeout + ** to 5 seconds (so it might get reopened soon), + ** otherwise (all sockets open) 60. + */ + idx = 0; + while (idx < ndaemons && Daemons[idx].d_socket >= 0) + idx++; + if (idx < ndaemons) + timeout.tv_sec = 5; + else + timeout.tv_sec = 60; + timeout.tv_usec = 0; + + t = select(highest + 1, FDSET_CAST &readfds, + NULL, NULL, &timeout); + + if (DoQueueRun) + (void) runqueue(TRUE, FALSE); + if (t <= 0) + { + timedout = TRUE; + break; + } + + control = FALSE; + errno = 0; + curdaemon = -1; + + /* look "round-robin" for an active socket */ + if ((idx = olddaemon + 1) >= ndaemons) + idx = 0; + for (i = 0; i < ndaemons; i++) + { + if (Daemons[idx].d_socket >= 0 && + FD_ISSET(Daemons[idx].d_socket, &readfds)) + { + lotherend = Daemons[idx].d_socksize; + t = accept(Daemons[idx].d_socket, + (struct sockaddr *)&RealHostAddr, + &lotherend); + olddaemon = curdaemon = idx; + break; + } + if (++idx >= ndaemons) + idx = 0; + } +# if NETUNIX + if (curdaemon == -1 && ControlSocket >= 0 && + FD_ISSET(ControlSocket, &readfds)) + { + struct sockaddr_un sa_un; + + lotherend = sizeof sa_un; + t = accept(ControlSocket, + (struct sockaddr *)&sa_un, + &lotherend); + control = TRUE; + } +# endif /* NETUNIX */ + if (t >= 0 || errno != EINTR) + break; + } + if (timedout) + { + timedout = FALSE; + continue; + } + save_errno = errno; + (void) blocksignal(SIGALRM); + if (t < 0) + { + errno = save_errno; + syserr("getrequests: accept"); + + /* arrange to re-open the socket next time around */ + (void) close(Daemons[curdaemon].d_socket); + Daemons[curdaemon].d_socket = -1; + continue; + } + + if (!control) + { + /* set some daemon related macros */ + switch (Daemons[curdaemon].d_addr.sa.sa_family) + { + case AF_UNSPEC: + define(macid("{daemon_family}", NULL), + "unspec", &BlankEnvelope); + break; +# if NETINET + case AF_INET: + define(macid("{daemon_family}", NULL), + "inet", &BlankEnvelope); + break; +# endif /* NETINET */ +# if NETINET6 + case AF_INET6: + define(macid("{daemon_family}", NULL), + "inet6", &BlankEnvelope); + break; +# endif /* NETINET6 */ +# if NETISO + case AF_ISO: + define(macid("{daemon_family}", NULL), + "iso", &BlankEnvelope); + break; +# endif /* NETISO */ +# if NETNS + case AF_NS: + define(macid("{daemon_family}", NULL), + "ns", &BlankEnvelope); + break; +# endif /* NETNS */ +# if NETX25 + case AF_CCITT: + define(macid("{daemon_family}", NULL), + "x.25", &BlankEnvelope); + break; +# endif /* NETX25 */ + } + define(macid("{daemon_name}", NULL), + Daemons[curdaemon].d_name, &BlankEnvelope); + if (Daemons[curdaemon].d_mflags != NULL) + define(macid("{daemon_flags}", NULL), + Daemons[curdaemon].d_mflags, + &BlankEnvelope); + else + define(macid("{daemon_flags}", NULL), + "", &BlankEnvelope); + } + + /* + ** Create a subprocess to process the mail. + */ + + if (tTd(15, 2)) + dprintf("getrequests: forking (fd = %d)\n", t); + + /* + ** advance state of PRNG + ** this is necessary because otherwise all child processes + ** will produce the same PRN sequence and hence the selection + ** of a queue directory (and other things, e.g., MX selection) + ** are not "really" random. + */ + (void) get_random(); + + /* + ** Create a pipe to keep the child from writing to the + ** socket until after the parent has closed it. Otherwise + ** the parent may hang if the child has closed it first. + */ + + if (pipe(pipefd) < 0) + pipefd[0] = pipefd[1] = -1; + + (void) blocksignal(SIGCHLD); + pid = fork(); + if (pid < 0) + { + syserr("daemon: cannot fork"); + if (pipefd[0] != -1) + { + (void) close(pipefd[0]); + (void) close(pipefd[1]); + } + (void) releasesignal(SIGCHLD); + (void) sleep(10); + (void) close(t); + continue; + } + + if (pid == 0) + { + char *p; + FILE *inchannel, *outchannel = NULL; + + /* + ** CHILD -- return to caller. + ** Collect verified idea of sending host. + ** Verify calling user id if possible here. + */ + + if (!control) + { + define(macid("{daemon_addr}", NULL), + newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)), + &BlankEnvelope); + (void) snprintf(status, sizeof status, "%d", + ntohs(Daemons[curdaemon].d_port)); + define(macid("{daemon_port}", NULL), + newstr(status), &BlankEnvelope); + } + + (void) releasesignal(SIGALRM); + (void) releasesignal(SIGCHLD); + (void) setsignal(SIGCHLD, SIG_DFL); + (void) setsignal(SIGHUP, intsig); + for (idx = 0; idx < ndaemons; idx++) + { + if (Daemons[idx].d_socket >= 0) + (void) close(Daemons[idx].d_socket); + } + clrcontrol(); + + /* Avoid SMTP daemon actions if control command */ + if (control) + { + /* Add control socket process */ + proc_list_add(getpid(), "console socket child", + PROC_CONTROL_CHILD); + } + else + { + proc_list_clear(); + + /* Add parent process as first child item */ + proc_list_add(getpid(), "daemon child", + PROC_DAEMON_CHILD); + + /* don't schedule queue runs if ETRN */ + QueueIntvl = 0; + + sm_setproctitle(TRUE, e, "startup with %s", + anynet_ntoa(&RealHostAddr)); + } + + if (pipefd[0] != -1) + { + auto char c; + + /* + ** Wait for the parent to close the write end + ** of the pipe, which we will see as an EOF. + ** This guarantees that we won't write to the + ** socket until after the parent has closed + ** the pipe. + */ + + /* close the write end of the pipe */ + (void) close(pipefd[1]); + + /* we shouldn't be interrupted, but ... */ + while (read(pipefd[0], &c, 1) < 0 && + errno == EINTR) + continue; + (void) close(pipefd[0]); + } + + /* control socket processing */ + if (control) + { + control_command(t, e); + /* NOTREACHED */ + exit(EX_SOFTWARE); + } + + /* determine host name */ + p = hostnamebyanyaddr(&RealHostAddr); + if (strlen(p) > (SIZE_T) MAXNAME) + p[MAXNAME] = '\0'; + RealHostName = newstr(p); + if (RealHostName[0] == '[') + { + /* TEMP, FAIL: which one? */ + define(macid("{client_resolve}", NULL), + (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL", + &BlankEnvelope); + } + else + define(macid("{client_resolve}", NULL), "OK", + &BlankEnvelope); + sm_setproctitle(TRUE, e, "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); + finis(FALSE, EX_OK); + } + + InChannel = inchannel; + OutChannel = outchannel; + DisConnected = FALSE; + +# ifdef XLA + if (!xla_host_ok(RealHostName)) + { + message("421 4.4.5 Too many SMTP sessions for this host"); + finis(FALSE, EX_OK); + } +# endif /* XLA */ + /* find out name for interface of connection */ + if (getsockname(fileno(InChannel), &sa.sa, + &len) == 0) + { + p = hostnamebyanyaddr(&sa); + if (tTd(15, 9)) + dprintf("getreq: got name %s\n", p); + define(macid("{if_name}", NULL), + newstr(p), &BlankEnvelope); + + /* do this only if it is not the loopback */ + /* interface: how to figure out? XXX */ + if (!isloopback(sa)) + { + define(macid("{if_addr}", NULL), + newstr(anynet_ntoa(&sa)), + &BlankEnvelope); + p = xalloc(5); + snprintf(p, 4, "%d", sa.sa.sa_family); + define(macid("{if_family}", NULL), p, + &BlankEnvelope); + if (tTd(15, 7)) + dprintf("getreq: got addr %s and family %s\n", + macvalue(macid("{if_addr}", NULL), + &BlankEnvelope), + macvalue(macid("{if_addr}", NULL), + &BlankEnvelope)); + } + else + { + define(macid("{if_addr}", NULL), NULL, + &BlankEnvelope); + define(macid("{if_family}", NULL), NULL, + &BlankEnvelope); + } + } + else + { + if (tTd(15, 7)) + dprintf("getreq: getsockname failed\n"); + define(macid("{if_name}", NULL), NULL, + &BlankEnvelope); + define(macid("{if_addr}", NULL), NULL, + &BlankEnvelope); + define(macid("{if_family}", NULL), NULL, + &BlankEnvelope); + } + break; + } + + /* parent -- keep track of children */ + if (control) + { + snprintf(status, sizeof status, + "control socket server child"); + proc_list_add(pid, status, PROC_CONTROL); + } + else + { + snprintf(status, sizeof status, + "SMTP server child for %s", + anynet_ntoa(&RealHostAddr)); + proc_list_add(pid, status, PROC_DAEMON); + } + (void) releasesignal(SIGCHLD); + + /* close the read end of the synchronization pipe */ + if (pipefd[0] != -1) + (void) close(pipefd[0]); + + /* close the port so that others will hang (for a while) */ + (void) close(t); + + /* release the child by closing the read end of the sync pipe */ + if (pipefd[1] != -1) + (void) close(pipefd[1]); + } + if (tTd(15, 2)) + dprintf("getreq: returning\n"); + return &Daemons[curdaemon].d_flags; +} + /* +** OPENDAEMONSOCKET -- open SMTP socket +** +** Deals with setting all appropriate options. +** +** Parameters: +** d -- the structure for the daemon to open. +** 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 */ + +static int +opendaemonsocket(d, firsttime) + struct daemon *d; + bool firsttime; +{ + int on = 1; + int fdflags; + SOCKADDR_LEN_T socksize = 0; + int ntries = 0; + int save_errno; + + if (tTd(15, 2)) + dprintf("opendaemonsocket(%s)\n", d->d_name); + + do + { + if (ntries > 0) + (void) sleep(5); + if (firsttime || d->d_socket < 0) + { + d->d_socket = socket(d->d_addr.sa.sa_family, + SOCK_STREAM, 0); + if (d->d_socket < 0) + { + save_errno = errno; + syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name); + severe: + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "daemon %s: problem creating SMTP socket", d->d_name); + d->d_socket = -1; + continue; + } + + /* turn on network debugging? */ + if (tTd(15, 101)) + (void) setsockopt(d->d_socket, SOL_SOCKET, + SO_DEBUG, (char *)&on, + sizeof on); + + (void) setsockopt(d->d_socket, SOL_SOCKET, + SO_REUSEADDR, (char *)&on, sizeof on); + (void) setsockopt(d->d_socket, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof on); + +# ifdef SO_RCVBUF + if (d->d_tcprcvbufsize > 0) + { + if (setsockopt(d->d_socket, SOL_SOCKET, + SO_RCVBUF, + (char *) &d->d_tcprcvbufsize, + sizeof(d->d_tcprcvbufsize)) < 0) + syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name); + } +# endif /* SO_RCVBUF */ +# ifdef SO_SNDBUF + if (d->d_tcpsndbufsize > 0) + { + if (setsockopt(d->d_socket, SOL_SOCKET, + SO_SNDBUF, + (char *) &d->d_tcpsndbufsize, + sizeof(d->d_tcpsndbufsize)) < 0) + syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name); + } +# endif /* SO_SNDBUF */ + + if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 || + fcntl(d->d_socket, F_SETFD, + fdflags | FD_CLOEXEC) == -1) + { + save_errno = errno; + syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s", + d->d_name, + fdflags == -1 ? "get" : "set", + strerror(save_errno)); + (void) close(d->d_socket); + goto severe; + } + + switch (d->d_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + socksize = sizeof d->d_addr.sin; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + socksize = sizeof d->d_addr.sin6; + break; +# endif /* NETINET6 */ + +# if NETISO + case AF_ISO: + socksize = sizeof d->d_addr.siso; + break; +# endif /* NETISO */ + + default: + socksize = sizeof d->d_addr; + break; + } + + if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0) + { + /* probably another daemon already */ + save_errno = errno; + syserr("opendaemonsocket: daemon %s: cannot bind", + d->d_name); + (void) close(d->d_socket); + goto severe; + } + } + if (!firsttime && + listen(d->d_socket, d->d_listenqueue) < 0) + { + save_errno = errno; + syserr("opendaemonsocket: daemon %s: cannot listen", + d->d_name); + (void) close(d->d_socket); + goto severe; + } + return socksize; + } while (ntries++ < MAXOPENTRIES && transienterror(save_errno)); + syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting", + d->d_name); + /* NOTREACHED */ + return -1; /* avoid compiler warning on IRIX */ +} + /* +** SETUPDAEMON -- setup socket for daemon +** +** Parameters: +** daemonaddr -- socket for daemon +** daemon -- number of daemon +** +** Returns: +** port number on which daemon should run +** +*/ +static u_short +setupdaemon(daemonaddr) + SOCKADDR *daemonaddr; +{ + u_short port; + + /* + ** Set up the address for the mailer. + */ + + if (daemonaddr->sa.sa_family == AF_UNSPEC) + { + memset(daemonaddr, '\0', sizeof *daemonaddr); + daemonaddr->sa.sa_family = InetMode; + } + + switch (daemonaddr->sa.sa_family) + { +# if NETINET + case AF_INET: + if (daemonaddr->sin.sin_addr.s_addr == 0) + daemonaddr->sin.sin_addr.s_addr = INADDR_ANY; + port = daemonaddr->sin.sin_port; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr)) + daemonaddr->sin6.sin6_addr = in6addr_any; + port = daemonaddr->sin6.sin6_port; + break; +# endif /* NETINET6 */ + + default: + /* unknown protocol */ + port = 0; + break; + } + if (port == 0) + { +# ifdef NO_GETSERVBYNAME + port = htons(25); +# else /* NO_GETSERVBYNAME */ + { + register struct servent *sp; + + sp = getservbyname("smtp", "tcp"); + if (sp == NULL) + { + syserr("554 5.3.5 service \"smtp\" unknown"); + port = htons(25); + } + else + port = sp->s_port; + } +# endif /* NO_GETSERVBYNAME */ + } + + switch (daemonaddr->sa.sa_family) + { +# if NETINET + case AF_INET: + daemonaddr->sin.sin_port = port; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + daemonaddr->sin6.sin6_port = port; + break; +# endif /* NETINET6 */ + + default: + /* unknown protocol */ + break; + } + return(port); +} + /* +** CLRDAEMON -- reset the daemon connection +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** releases any resources used by the passive daemon. +*/ + +void +clrdaemon() +{ + int i; + + for (i = 0; i < ndaemons; i++) + { + if (Daemons[i].d_socket >= 0) + (void) close(Daemons[i].d_socket); + Daemons[i].d_socket = -1; + } +} + /* +** SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client) +** +** Parameters: +** p -- the options line. +** d -- the daemon structure to fill in. +** +** Returns: +** none. +*/ + +static void +setsockaddroptions(p, d) + register char *p; + struct daemon *d; +{ +# if NETISO + short port; +# endif /* NETISO */ + int l; + char *h, *flags; + + if (d->d_addr.sa.sa_family == AF_UNSPEC) + d->d_addr.sa.sa_family = InetMode; + + 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)) + d->d_addr.sa.sa_family = atoi(v); +# if NETINET + else if (strcasecmp(v, "inet") == 0) + d->d_addr.sa.sa_family = AF_INET; +# endif /* NETINET */ +# if NETINET6 + else if (strcasecmp(v, "inet6") == 0) + d->d_addr.sa.sa_family = AF_INET6; +# endif /* NETINET6 */ +# if NETISO + else if (strcasecmp(v, "iso") == 0) + d->d_addr.sa.sa_family = AF_ISO; +# endif /* NETISO */ +# if NETNS + else if (strcasecmp(v, "ns") == 0) + d->d_addr.sa.sa_family = AF_NS; +# endif /* NETNS */ +# if NETX25 + else if (strcasecmp(v, "x.25") == 0) + d->d_addr.sa.sa_family = AF_CCITT; +# endif /* NETX25 */ + else + syserr("554 5.3.5 Unknown address family %s in Family=option", + v); + break; + + case 'A': /* address */ + switch (d->d_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (!isascii(*v) || !isdigit(*v) || + ((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE)) + { + register struct hostent *hp; + + hp = sm_gethostbyname(v, AF_INET); + if (hp == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + v); + else + { + while (*(hp->h_addr_list) && + hp->h_addrtype != AF_INET) + hp->h_addr_list++; + if (*(hp->h_addr_list) == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + v); + else + memmove(&d->d_addr.sin.sin_addr, + *(hp->h_addr_list), + INADDRSZ); + } + } + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (!isascii(*v) || !isxdigit(*v) || + inet_pton(AF_INET6, v, + &d->d_addr.sin6.sin6_addr) != 1) + { + register struct hostent *hp; + + hp = sm_gethostbyname(v, AF_INET6); + if (hp == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + v); + else + { + while (*(hp->h_addr_list) && + hp->h_addrtype != AF_INET6) + hp->h_addr_list++; + if (*(hp->h_addr_list) == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + v); + else + memmove(&d->d_addr.sin6.sin6_addr, + *(hp->h_addr_list), + IN6ADDRSZ); + } + } + break; +# endif /* NETINET6 */ + + default: + syserr("554 5.3.5 address= option unsupported for family %d", + d->d_addr.sa.sa_family); + break; + } + break; + + case 'P': /* port */ + switch (d->d_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (isascii(*v) && isdigit(*v)) + d->d_addr.sin.sin_port = htons(atoi(v)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + v); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(v, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + v); + else + d->d_addr.sin.sin_port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (isascii(*v) && isdigit(*v)) + d->d_addr.sin6.sin6_port = htons(atoi(v)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + v); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(v, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + v); + else + d->d_addr.sin6.sin6_port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + break; +# endif /* NETINET6 */ + +# if NETISO + case AF_ISO: + /* assume two byte transport selector */ + if (isascii(*v) && isdigit(*v)) + port = htons(atoi(v)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + v); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(v, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + v); + else + port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + memmove(TSEL(&d->d_addr.siso), + (char *) &port, 2); + break; +# endif /* NETISO */ + + default: + syserr("554 5.3.5 Port= option unsupported for family %d", + d->d_addr.sa.sa_family); + break; + } + break; + + case 'L': /* listen queue size */ + d->d_listenqueue = atoi(v); + break; + + case 'M': /* modifiers (flags) */ + l = 3 * strlen(v) + 3; + h = v; + flags = xalloc(l); + d->d_mflags = flags; + for (; *h != '\0'; h++) + { + if (!(isascii(*h) && isspace(*h))) + { + if (flags != d->d_mflags) + *f++ = ' '; + *flags++ = *h; + if (isupper(*h)) + *flags++ = *h; + } + } + *flags++ = '\0'; + for (; *v != '\0'; v++) + if (!(isascii(*v) && isspace(*v))) + setbitn(*v, d->d_flags); + break; + + case 'S': /* send buffer size */ + d->d_tcpsndbufsize = atoi(v); + break; + + case 'R': /* receive buffer size */ + d->d_tcprcvbufsize = atoi(v); + break; + + case 'N': /* name */ + d->d_name = v; + break; + + default: + syserr("554 5.3.5 PortOptions parameter \"%s\" unknown", + f); + } + } +} + /* +** SETDAEMONOPTIONS -- set options for running the MTA daemon +** +** Parameters: +** p -- the options line. +** +** Returns: +** TRUE if successful, FALSE otherwise. +*/ + +bool +setdaemonoptions(p) + register char *p; +{ + if (ndaemons >= MAXDAEMONS) + return FALSE; + Daemons[ndaemons].d_socket = -1; + Daemons[ndaemons].d_listenqueue = 10; + clrbitmap(Daemons[ndaemons].d_flags); + setsockaddroptions(p, &Daemons[ndaemons]); + + if (Daemons[ndaemons].d_name != NULL) + Daemons[ndaemons].d_name = newstr(Daemons[ndaemons].d_name); + else + { + char num[30]; + + snprintf(num, sizeof num, "Daemon%d", ndaemons); + Daemons[ndaemons].d_name = newstr(num); + } + + if (tTd(37, 1)) + { + dprintf("Daemon %s flags: ", Daemons[ndaemons].d_name); + if (bitnset(D_ETRNONLY, Daemons[ndaemons].d_flags)) + dprintf("ETRNONLY "); + if (bitnset(D_NOETRN, Daemons[ndaemons].d_flags)) + dprintf("NOETRN "); + dprintf("\n"); + } + ++ndaemons; + return TRUE; +} + /* +** INITDAEMON -- initialize daemon if not yet done. +** +** Parameters: +** none +** +** Returns: +** none +** +** Side Effects: +** initializes structure for one daemon. +*/ +void +initdaemon() +{ + if (ndaemons == 0) + { + Daemons[ndaemons].d_socket = -1; + Daemons[ndaemons].d_listenqueue = 10; + Daemons[ndaemons].d_name = "Daemon0"; + ndaemons = 1; + } +} + /* +** SETCLIENTOPTIONS -- set options for running the client +** +** Parameters: +** p -- the options line. +** +** Returns: +** none. +*/ + +static SOCKADDR ClientAddr; /* address for client */ + +void +setclientoptions(p) + register char *p; +{ + struct daemon d; + extern ENVELOPE BlankEnvelope; + + memset(&d, '\0', sizeof d); + setsockaddroptions(p, &d); + + /* grab what we need */ + memcpy(&ClientAddr, &d.d_addr, sizeof ClientAddr); + TcpSndBufferSize = d.d_tcpsndbufsize; + TcpRcvBufferSize = d.d_tcprcvbufsize; + if (d.d_mflags != NULL) + define(macid("{client_flags}", NULL), d.d_mflags, + &BlankEnvelope); + else + define(macid("{client_flags}", NULL), "", &BlankEnvelope); +} + /* +** MAKECONNECTION -- make a connection to an SMTP socket on a 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. +** e -- the current envelope. +** +** Returns: +** An exit code telling whether the connection could be +** made and if not why not. +** +** Side Effects: +** none. +*/ + +static jmp_buf CtxConnectTimeout; + +SOCKADDR CurHostAddr; /* address of current host */ + +int +makeconnection(host, port, mci, e) + char *host; + volatile u_int port; + register MCI *mci; + ENVELOPE *e; +{ + register volatile int addrno = 0; + register volatile int s; + register struct hostent *volatile hp = (struct hostent *)NULL; + SOCKADDR addr; + SOCKADDR clt_addr; + int save_errno = 0; + volatile SOCKADDR_LEN_T addrlen; + volatile bool firstconnect; + EVENT *volatile ev = NULL; +# if NETINET6 + volatile bool v6found = FALSE; +# endif /* NETINET6 */ + volatile int family = InetMode; + SOCKADDR_LEN_T len; + volatile SOCKADDR_LEN_T socksize = 0; + volatile bool clt_bind; + BITMAP256 d_flags; + char *p; + extern ENVELOPE BlankEnvelope; + + /* retranslate ${daemon_flags} into bitmap */ + clrbitmap(d_flags); + if ((p = macvalue(macid("{daemon_flags}", NULL), e)) != NULL) + { + for (; *p != '\0'; p++) + { + if (!(isascii(*p) && isspace(*p))) + setbitn(*p, d_flags); + } + } + + /* "add" ${client_flags} to bitmap */ + if ((p = macvalue(macid("{client_flags}", NULL), e)) != NULL) + { + for (; *p != '\0'; p++) + { + /* look for just this one flag */ + if (*p == D_IFNHELO) + { + setbitn(*p, d_flags); + break; + } + } + } + +# if NETINET6 + v4retry: +# endif /* NETINET6 */ + clt_bind = FALSE; + + /* Set up the address for outgoing connection. */ + if (bitnset(D_BINDIF, d_flags) && + (p = macvalue(macid("{if_addr}", NULL), e)) != NULL) + { + char *f; +# if NETINET6 + char p6[INET6_ADDRSTRLEN]; +# endif /* NETINET6 */ + + memset(&clt_addr, '\0', sizeof clt_addr); + + /* XXX set all necessary values... */ + if ((f = macvalue(macid("{if_family}", NULL), e)) != NULL) + clt_addr.sa.sa_family = atoi(f); + else + clt_addr.sa.sa_family = family; + switch (clt_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p)) + != INADDR_NONE) + { + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in); + } + else if (clt_addr.sin.sin_port != 0) + { + clt_addr.sin.sin_addr.s_addr = INADDR_ANY; + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in); + } + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (inet_addr(p) != INADDR_NONE) + snprintf(p6, sizeof p6, "::ffff:%s", p); + else + strlcpy(p6, p, sizeof p6); + if (inet_pton(AF_INET6, p6, + &clt_addr.sin6.sin6_addr) == 1) + { + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in6); + } + else if (clt_addr.sin6.sin6_port != 0) + { + if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) + clt_addr.sin6.sin6_addr = in6addr_any; + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in6); + } + break; +# endif /* NETINET6 */ + +# if 0 + default: + syserr("554 5.3.5 Address= option unsupported for family %d", + clt_addr.sa.sa_family); + break; +# endif /* 0 */ + } + } + else + { + STRUCTCOPY(ClientAddr, clt_addr); + if (clt_addr.sa.sa_family == AF_UNSPEC) + clt_addr.sa.sa_family = InetMode; + switch (clt_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (clt_addr.sin.sin_addr.s_addr == 0) + clt_addr.sin.sin_addr.s_addr = INADDR_ANY; + else + clt_bind = TRUE; + if (clt_addr.sin.sin_port != 0) + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in); + break; +# endif /* NETINET */ +# if NETINET6 + case AF_INET6: + if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) + clt_addr.sin6.sin6_addr = in6addr_any; + else + clt_bind = TRUE; + socksize = sizeof (struct sockaddr_in6); + if (clt_addr.sin6.sin6_port != 0) + clt_bind = TRUE; + break; +# endif /* NETINET6 */ +# if NETISO + case AF_ISO: + socksize = sizeof clt_addr.siso; + clt_bind = TRUE; + break; +# endif /* NETISO */ + default: + break; + } + } + + /* + ** Set up the address for the mailer. + ** Accept "[a.b.c.d]" syntax for host name. + */ + +# if NAMED_BIND + h_errno = 0; +# endif /* NAMED_BIND */ + errno = 0; + memset(&CurHostAddr, '\0', sizeof CurHostAddr); + memset(&addr, '\0', sizeof addr); + SmtpPhase = mci->mci_phase = "initial connection"; + CurHostName = host; + + if (host[0] == '[') + { + p = strchr(host, ']'); + if (p != NULL) + { +# if NETINET + unsigned long hid = INADDR_NONE; +# endif /* NETINET */ +# if NETINET6 + struct sockaddr_in6 hid6; +# endif /* NETINET6 */ + + *p = '\0'; +# if NETINET6 + memset(&hid6, '\0', sizeof hid6); +# endif /* NETINET6 */ +# if NETINET + if (family == AF_INET && + (hid = inet_addr(&host[1])) != INADDR_NONE) + { + addr.sin.sin_family = AF_INET; + addr.sin.sin_addr.s_addr = hid; + } + else +# endif /* NETINET */ +# if NETINET6 + if (family == AF_INET6 && + inet_pton(AF_INET6, &host[1], + &hid6.sin6_addr) == 1) + { + addr.sin6.sin6_family = AF_INET6; + addr.sin6.sin6_addr = hid6.sin6_addr; + } + else +# endif /* NETINET6 */ + { + /* try it as a host name (avoid MX lookup) */ + hp = sm_gethostbyname(&host[1], family); + if (hp == NULL && p[-1] == '.') + { +# if NAMED_BIND + int oldopts = _res.options; + + _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); +# endif /* NAMED_BIND */ + p[-1] = '\0'; + hp = sm_gethostbyname(&host[1], + family); + p[-1] = '.'; +# if NAMED_BIND + _res.options = oldopts; +# endif /* NAMED_BIND */ + } + *p = ']'; + goto gothostent; + } + *p = ']'; + } + if (p == NULL) + { + extern char MsgBuf[]; + + usrerrenh("5.1.2", + "553 Invalid numeric domain spec \"%s\"", + host); + mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf); + errno = EINVAL; + return EX_NOHOST; + } + } + else + { + /* contortion to get around SGI cc complaints */ + { + p = &host[strlen(host) - 1]; + hp = sm_gethostbyname(host, family); + if (hp == NULL && *p == '.') + { +# if NAMED_BIND + int oldopts = _res.options; + + _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); +# endif /* NAMED_BIND */ + *p = '\0'; + hp = sm_gethostbyname(host, family); + *p = '.'; +# if NAMED_BIND + _res.options = oldopts; +# endif /* NAMED_BIND */ + } + } +gothostent: + if (hp == NULL) + { +# if NAMED_BIND + /* check for name server timeouts */ + if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || + (errno == ECONNREFUSED && UseNameServer)) + { + save_errno = errno; + mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL); + errno = save_errno; + return EX_TEMPFAIL; + } +# endif /* NAMED_BIND */ +# if NETINET6 + /* + ** Try v6 first, then fall back to v4. + ** If we found a v6 address, but no v4 + ** addresses, then TEMPFAIL. + */ + + if (family == AF_INET6) + { + family = AF_INET; + goto v4retry; + } + if (v6found) + goto v6tempfail; +# endif /* NETINET6 */ + save_errno = errno; + mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); + errno = save_errno; + return EX_NOHOST; + } + addr.sa.sa_family = hp->h_addrtype; + switch (hp->h_addrtype) + { +# if NETINET + case AF_INET: + memmove(&addr.sin.sin_addr, + hp->h_addr, + INADDRSZ); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + hp->h_addr, + IN6ADDRSZ); + break; +# endif /* NETINET6 */ + + default: + if (hp->h_length > sizeof addr.sa.sa_data) + { + syserr("makeconnection: long sa_data: family %d len %d", + hp->h_addrtype, hp->h_length); + mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); + errno = EINVAL; + return EX_NOHOST; + } + memmove(addr.sa.sa_data, + hp->h_addr, + hp->h_length); + break; + } + addrno = 1; + } + + /* + ** Determine the port number. + */ + + if (port == 0) + { +# ifdef NO_GETSERVBYNAME + port = htons(25); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp = getservbyname("smtp", "tcp"); + + if (sp == NULL) + { + if (LogLevel > 2) + sm_syslog(LOG_ERR, NOQID, + "makeconnection: service \"smtp\" unknown"); + port = htons(25); + } + else + port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + + switch (addr.sa.sa_family) + { +# if NETINET + case AF_INET: + addr.sin.sin_port = port; + addrlen = sizeof (struct sockaddr_in); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + addr.sin6.sin6_port = port; + addrlen = sizeof (struct sockaddr_in6); + break; +# endif /* NETINET6 */ + +# if NETISO + case AF_ISO: + /* assume two byte transport selector */ + memmove(TSEL((struct sockaddr_iso *) &addr), (char *) &port, 2); + addrlen = sizeof (struct sockaddr_iso); + break; +# endif /* NETISO */ + + default: + syserr("Can't connect to address family %d", addr.sa.sa_family); + mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); + errno = EINVAL; + 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 /* XLA */ + + firstconnect = TRUE; + for (;;) + { + if (tTd(16, 1)) + dprintf("makeconnection (%s [%s])\n", + host, anynet_ntoa(&addr)); + + /* save for logging */ + CurHostAddr = addr; + + if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags)) + { + int rport = IPPORT_RESERVED - 1; + + s = rresvport(&rport); + } + else + { + s = socket(addr.sa.sa_family, SOCK_STREAM, 0); + } + if (s < 0) + { + save_errno = errno; + syserr("makeconnection: cannot create socket"); +# ifdef XLA + xla_host_end(host); +# endif /* XLA */ + mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + errno = save_errno; + return EX_TEMPFAIL; + } + +# ifdef SO_SNDBUF + if (TcpSndBufferSize > 0) + { + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, + (char *) &TcpSndBufferSize, + sizeof(TcpSndBufferSize)) < 0) + syserr("makeconnection: setsockopt(SO_SNDBUF)"); + } +# endif /* SO_SNDBUF */ +# ifdef SO_RCVBUF + if (TcpRcvBufferSize > 0) + { + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, + (char *) &TcpRcvBufferSize, + sizeof(TcpRcvBufferSize)) < 0) + syserr("makeconnection: setsockopt(SO_RCVBUF)"); + } +# endif /* SO_RCVBUF */ + + + if (tTd(16, 1)) + dprintf("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 (e->e_xfp != NULL) + (void) fflush(e->e_xfp); /* for debugging */ + errno = 0; /* for debugging */ + + if (clt_bind) + { + int on = 1; + + switch (clt_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (clt_addr.sin.sin_port != 0) + (void) setsockopt(s, SOL_SOCKET, + SO_REUSEADDR, + (char *) &on, + sizeof on); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (clt_addr.sin6.sin6_port != 0) + (void) setsockopt(s, SOL_SOCKET, + SO_REUSEADDR, + (char *) &on, + sizeof on); + break; +# endif /* NETINET6 */ + } + + if (bind(s, &clt_addr.sa, socksize) < 0) + { + save_errno = errno; + (void) close(s); + errno = save_errno; + syserr("makeconnection: cannot bind socket [%s]", + anynet_ntoa(&clt_addr)); + errno = save_errno; + return EX_TEMPFAIL; + } + } + + /* + ** Linux seems to hang in connect for 90 minutes (!!!). + ** Time out the connect to avoid this problem. + */ + + if (setjmp(CtxConnectTimeout) == 0) + { + int i; + + if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) + ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); + else if (TimeOuts.to_connect != 0) + ev = setevent(TimeOuts.to_connect, connecttimeout, 0); + else + ev = NULL; + + switch (ConnectOnlyTo.sa.sa_family) + { +# if NETINET + case AF_INET: + addr.sin.sin_addr.s_addr = ConnectOnlyTo.sin.sin_addr.s_addr; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + &ConnectOnlyTo.sin6.sin6_addr, + IN6ADDRSZ); + break; +# endif /* NETINET6 */ + } + i = connect(s, (struct sockaddr *) &addr, addrlen); + save_errno = errno; + if (ev != NULL) + clrevent(ev); + if (i >= 0) + break; + } + else + save_errno = errno; + + /* if running demand-dialed connection, try again */ + if (DialDelay > 0 && firstconnect) + { + if (tTd(16, 1)) + dprintf("Connect failed (%s); trying again...\n", + errstring(save_errno)); + firstconnect = FALSE; + (void) sleep(DialDelay); + continue; + } + + /* couldn't connect.... figure out why */ + (void) close(s); + + if (LogLevel >= 14) + sm_syslog(LOG_INFO, e->e_id, + "makeconnection (%s [%s]) failed: %s", + host, anynet_ntoa(&addr), + errstring(save_errno)); + + if (hp != NULL && hp->h_addr_list[addrno] != NULL) + { + if (tTd(16, 1)) + dprintf("Connect failed (%s); trying new address....\n", + errstring(save_errno)); + switch (addr.sa.sa_family) + { +# if NETINET + case AF_INET: + memmove(&addr.sin.sin_addr, + hp->h_addr_list[addrno++], + INADDRSZ); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + hp->h_addr_list[addrno++], + IN6ADDRSZ); + break; +# endif /* NETINET6 */ + + default: + memmove(addr.sa.sa_data, + hp->h_addr_list[addrno++], + hp->h_length); + break; + } + continue; + } + +# if NETINET6 + if (family == AF_INET6) + { + if (tTd(16, 1)) + dprintf("Connect failed (%s); retrying with AF_INET....\n", + errstring(save_errno)); + v6found = TRUE; + family = AF_INET; + goto v4retry; + } + v6tempfail: +# endif /* NETINET6 */ + /* couldn't open connection */ +# if NETINET6 + /* Don't clobber an already saved errno from v4retry */ + if (errno > 0) +# endif /* NETINET6 */ + save_errno = errno; + if (tTd(16, 1)) + dprintf("Connect failed (%s)\n", errstring(save_errno)); +# ifdef XLA + xla_host_end(host); +# endif /* XLA */ + mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); + errno = save_errno; + return EX_TEMPFAIL; + } + + /* connection ok, put it into canonical form */ + mci->mci_out = NULL; + if ((mci->mci_out = fdopen(s, "w")) == NULL || + (s = dup(s)) < 0 || + (mci->mci_in = fdopen(s, "r")) == NULL) + { + save_errno = errno; + syserr("cannot open SMTP client channel, fd=%d", s); + mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + if (mci->mci_out != NULL) + (void) fclose(mci->mci_out); + (void) close(s); + errno = save_errno; + return EX_TEMPFAIL; + } + + /* find out name for Interface through which we connect */ + len = sizeof addr; + if (getsockname(s, &addr.sa, &len) == 0) + { + char *name; + + define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)), + &BlankEnvelope); + name = hostnamebyanyaddr(&addr); + define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope); + if (LogLevel > 11) + { + /* log connection information */ + sm_syslog(LOG_INFO, e->e_id, + "SMTP outgoing connect on %.40s", name); + } + if (bitnset(D_IFNHELO, d_flags)) + { + if (name[0] != '[' && strchr(name, '.') != NULL) + mci->mci_heloname = newstr(name); + } + } + else + { + define(macid("{if_name}", NULL), NULL, &BlankEnvelope); + define(macid("{if_addr}", NULL), NULL, &BlankEnvelope); + } + mci_setstat(mci, EX_OK, NULL, NULL); + return EX_OK; +} + +static void +connecttimeout() +{ + errno = ETIMEDOUT; + longjmp(CtxConnectTimeout, 1); +} + /* +** MAKECONNECTION_DS -- make a connection to a domain socket. +** +** Parameters: +** mux_path -- the path of the socket to connect to. +** mci -- a pointer to the mail connection information +** structure to be filled in. +** +** Returns: +** An exit code telling whether the connection could be +** made and if not why not. +** +** Side Effects: +** none. +*/ + +# if NETUNIX +int makeconnection_ds(mux_path, mci) + char *mux_path; + register MCI *mci; +{ + int sock; + int rval, save_errno; + long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_ROOTOK|SFF_EXECOK; + struct sockaddr_un unix_addr; + + /* if not safe, don't connect */ + rval = safefile(mux_path, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR|S_IWUSR, NULL); + + if (rval != 0) + { + syserr("makeconnection_ds: unsafe domain socket"); + mci_setstat(mci, EX_TEMPFAIL, "4.3.5", NULL); + errno = rval; + return EX_TEMPFAIL; + } + + /* prepare address structure */ + memset(&unix_addr, '\0', sizeof unix_addr); + unix_addr.sun_family = AF_UNIX; + + if (strlen(mux_path) >= sizeof unix_addr.sun_path) + { + syserr("makeconnection_ds: domain socket name too long"); + /* XXX why TEMPFAIL ? */ + mci_setstat(mci, EX_TEMPFAIL, "5.3.5", NULL); + errno = ENAMETOOLONG; + return EX_UNAVAILABLE; + } + (void) strlcpy(unix_addr.sun_path, mux_path, sizeof unix_addr.sun_path); + + /* initialize domain socket */ + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock == -1) + { + save_errno = errno; + syserr("makeconnection_ds: could not create domain socket"); + mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + errno = save_errno; + return EX_TEMPFAIL; + } + + /* connect to server */ + if (connect(sock, (struct sockaddr *) &unix_addr, + sizeof(unix_addr)) == -1) + { + save_errno = errno; + syserr("Could not connect to socket %s", mux_path); + mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); + (void) close(sock); + errno = save_errno; + return EX_TEMPFAIL; + } + + /* connection ok, put it into canonical form */ + mci->mci_out = NULL; + if ((mci->mci_out = fdopen(sock, "w")) == NULL || + (sock = dup(sock)) < 0 || + (mci->mci_in = fdopen(sock, "r")) == NULL) + { + save_errno = errno; + syserr("cannot open SMTP client channel, fd=%d", sock); + mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + if (mci->mci_out != NULL) + (void) fclose(mci->mci_out); + (void) close(sock); + errno = save_errno; + return EX_TEMPFAIL; + } + + mci_setstat(mci, EX_OK, NULL, NULL); + errno = 0; + return EX_OK; +} +# endif /* NETUNIX */ + /* +** 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; + + if (gethostname(hostbuf, size) < 0) + { + (void) strlcpy(hostbuf, "localhost", size); + } + hp = sm_gethostbyname(hostbuf, InetMode); + if (hp == NULL) + return NULL; + if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) + (void) cleanstrcpy(hostbuf, hp->h_name, size); + +# if NETINFO + if (strchr(hostbuf, '.') == NULL) + { + char *domainname; + + domainname = ni_propval("/locations", NULL, "resolver", + "domain", '\0'); + if (domainname != NULL && + strlen(domainname) + strlen(hostbuf) + 1 < size) + { + (void) strlcat(hostbuf, ".", size); + (void) strlcat(hostbuf, domainname, size); + } + } +# endif /* NETINFO */ + + /* + ** 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 != NULL; ha++) + { + if (strchr(*ha, '.') != NULL) + { + (void) cleanstrcpy(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)) + { + sm_syslog(LOG_CRIT, NOQID, + "My unqualified host name (%s) unknown; sleeping for retry", + hostbuf); + message("My unqualified host name (%s) unknown; sleeping for retry", + hostbuf); + (void) sleep(60); + if (!getcanonname(hostbuf, size, TRUE)) + { + sm_syslog(LOG_ALERT, NOQID, + "unable to qualify my own domain name (%s) -- using short name", + hostbuf); + message("WARNING: unable to qualify my own domain name (%s) -- using short name", + hostbuf); + } + } + return hp; +} + /* +** ADDRCMP -- compare two host addresses +** +** Parameters: +** hp -- hostent structure for the first address +** ha -- actual first address +** sa -- second address +** +** Returns: +** 0 -- if ha and sa match +** else -- they don't match +*/ + +static int +addrcmp(hp, ha, sa) + struct hostent *hp; + char *ha; + SOCKADDR *sa; +{ +# if NETINET6 + u_char *a; +# endif /* NETINET6 */ + + switch (sa->sa.sa_family) + { +# if NETINET + case AF_INET: + if (hp->h_addrtype == AF_INET) + return memcmp(ha, (char *) &sa->sin.sin_addr, INADDRSZ); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + a = (u_char *) &sa->sin6.sin6_addr; + + /* Straight binary comparison */ + if (hp->h_addrtype == AF_INET6) + return memcmp(ha, a, IN6ADDRSZ); + + /* If IPv4-mapped IPv6 address, compare the IPv4 section */ + if (hp->h_addrtype == AF_INET && + IN6_IS_ADDR_V4MAPPED(&sa->sin6.sin6_addr)) + return memcmp(a + IN6ADDRSZ - INADDRSZ, ha, INADDRSZ); + break; +# endif /* NETINET6 */ + } + return -1; +} + /* +** GETAUTHINFO -- get the real host name associated with a file descriptor +** +** Uses RFC1413 protocol to try to get info from the other end. +** +** Parameters: +** fd -- the descriptor +** may_be_forged -- an outage that is set to TRUE if the +** forward lookup of RealHostName does not match +** RealHostAddr; set to FALSE if they do match. +** +** Returns: +** The user@host information associated with this descriptor. +*/ + +static jmp_buf CtxAuthTimeout; + +static void +authtimeout() +{ + longjmp(CtxAuthTimeout, 1); +} + +char * +getauthinfo(fd, may_be_forged) + int fd; + bool *may_be_forged; +{ + SOCKADDR_LEN_T falen; + register char *volatile p = NULL; + SOCKADDR la; + SOCKADDR_LEN_T lalen; + register struct servent *sp; + volatile int s; + int i = 0; + EVENT *ev; + int nleft; + struct hostent *hp; + char *ostype = NULL; + char **ha; + char ibuf[MAXNAME + 1]; + static char hbuf[MAXNAME * 2 + 11]; + + *may_be_forged = FALSE; + falen = sizeof RealHostAddr; + if (isatty(fd) || (i = getpeername(fd, &RealHostAddr.sa, &falen)) < 0 || + falen <= 0 || RealHostAddr.sa.sa_family == 0) + { + if (i < 0 && errno != ENOTSOCK) + return NULL; + (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", + RealUserName); + if (tTd(9, 1)) + dprintf("getauthinfo: %s\n", hbuf); + return hbuf; + } + + if (RealHostName == NULL) + { + /* translate that to a host name */ + RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); + if (strlen(RealHostName) > MAXNAME) + RealHostName[MAXNAME] = '\0'; + } + + /* cross check RealHostName with forward DNS lookup */ + if (anynet_ntoa(&RealHostAddr)[0] == '[' || + RealHostName[0] == '[') + { + /* + ** address is not a socket or have an + ** IP address with no forward lookup + */ + *may_be_forged = FALSE; + } + else + { + /* try to match the reverse against the forward lookup */ + hp = sm_gethostbyname(RealHostName, + RealHostAddr.sa.sa_family); + + if (hp == NULL) + *may_be_forged = TRUE; + else + { + for (ha = hp->h_addr_list; *ha != NULL; ha++) + if (addrcmp(hp, *ha, &RealHostAddr) == 0) + break; + *may_be_forged = *ha == NULL; + } + } + + if (TimeOuts.to_ident == 0) + goto noident; + + lalen = sizeof la; + switch (RealHostAddr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (getsockname(fd, &la.sa, &lalen) < 0 || + lalen <= 0 || + la.sa.sa_family != AF_INET) + { + /* no ident info */ + goto noident; + } + + /* create ident query */ + (void) snprintf(ibuf, sizeof 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 */ +# ifdef NO_GETSERVBYNAME + RealHostAddr.sin.sin_port = htons(113); +# else /* NO_GETSERVBYNAME */ + sp = getservbyname("auth", "tcp"); + if (sp != NULL) + RealHostAddr.sin.sin_port = sp->s_port; + else + RealHostAddr.sin.sin_port = htons(113); + break; +# endif /* NO_GETSERVBYNAME */ +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (getsockname(fd, &la.sa, &lalen) < 0 || + lalen <= 0 || + la.sa.sa_family != AF_INET6) + { + /* no ident info */ + goto noident; + } + + /* create ident query */ + (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", + ntohs(RealHostAddr.sin6.sin6_port), + ntohs(la.sin6.sin6_port)); + + /* create local address */ + la.sin6.sin6_port = 0; + + /* create foreign address */ +# ifdef NO_GETSERVBYNAME + RealHostAddr.sin6.sin6_port = htons(113); +# else /* NO_GETSERVBYNAME */ + sp = getservbyname("auth", "tcp"); + if (sp != NULL) + RealHostAddr.sin6.sin6_port = sp->s_port; + else + RealHostAddr.sin6.sin6_port = htons(113); + break; +# endif /* NO_GETSERVBYNAME */ +# endif /* NETINET6 */ + default: + /* no ident info */ + goto noident; + } + + 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(la.sa.sa_family, SOCK_STREAM, 0); + if (s < 0) + { + clrevent(ev); + goto noident; + } + if (bind(s, &la.sa, lalen) < 0 || + connect(s, &RealHostAddr.sa, lalen) < 0) + { + goto closeident; + } + + if (tTd(9, 10)) + dprintf("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; + *p = '\0'; + if (strchr(ibuf, '\n') != NULL) + break; + } + (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)) + dprintf("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++; + ostype = p; + p = strchr(p, ':'); + if (p == NULL) + { + /* malformed response */ + goto noident; + } + else + { + char *charset; + + *p = '\0'; + charset = strchr(ostype, ','); + if (charset != NULL) + *charset = '\0'; + } + + /* 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 */ + if (strncasecmp(ostype, "other", 5) == 0 && + (ostype[5] == ' ' || ostype[5] == '\0')) + { + snprintf(hbuf, sizeof hbuf, "IDENT:"); + cleanstrcpy(&hbuf[6], p, MAXNAME); + } + else + cleanstrcpy(hbuf, p, MAXNAME); + i = strlen(hbuf); + snprintf(&hbuf[i], sizeof hbuf - i, "@%s", + RealHostName == NULL ? "localhost" : RealHostName); + goto postident; + +closeident: + (void) close(s); + clrevent(ev); + +noident: + if (RealHostName == NULL) + { + if (tTd(9, 1)) + dprintf("getauthinfo: NULL\n"); + return NULL; + } + snprintf(hbuf, sizeof hbuf, "%s", RealHostName); + +postident: +# if IP_SRCROUTE +# ifndef GET_IPOPT_DST +# define GET_IPOPT_DST(dst) (dst) +# endif /* ! GET_IPOPT_DST */ + /* + ** 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) + { + SOCKOPT_LEN_T ipoptlen; + int j; + u_char *q; + u_char *o; + int l; + 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.IP_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: + /* + ** Source routing. + ** o[0] is the option type (loose/strict). + ** o[1] is the length of this option, + ** including option type and + ** length. + ** o[2] is the pointer into the route + ** data. + ** o[3] begins the route data. + */ + + p = &hbuf[strlen(hbuf)]; + l = sizeof hbuf - (hbuf - p) - 6; + snprintf(p, SPACELEFT(hbuf, p), " [%s@%.*s", + *o == IPOPT_SSRR ? "!" : "", + l > 240 ? 120 : l / 2, + inet_ntoa(GET_IPOPT_DST(ipopt.IP_DST))); + i = strlen(p); + p += i; + l -= strlen(p); + + j = o[1] / sizeof(struct in_addr) - 1; + + /* q skips length and router pointer to data */ + q = &o[3]; + for ( ; j >= 0; j--) + { + struct in_addr addr; + + memcpy(&addr, q, sizeof(addr)); + snprintf(p, SPACELEFT(hbuf, p), + "%c%.*s", + j != 0 ? '@' : ':', + l > 240 ? 120 : + j == 0 ? l : l / 2, + inet_ntoa(addr)); + i = strlen(p); + p += i; + l -= i + 1; + q += sizeof(struct in_addr); + } + o += o[1]; + break; + + default: + /* Skip over option */ + o += o[1]; + break; + } + } + snprintf(p, SPACELEFT(hbuf, p), "]"); + goto postipsr; + } + +noipsr: +# endif /* IP_SRCROUTE */ + if (RealHostName != NULL && RealHostName[0] != '[') + { + p = &hbuf[strlen(hbuf)]; + (void) snprintf(p, SPACELEFT(hbuf, p), " [%.100s]", + anynet_ntoa(&RealHostAddr)); + } + if (*may_be_forged) + { + p = &hbuf[strlen(hbuf)]; + (void) snprintf(p, SPACELEFT(hbuf, p), " (may be forged)"); + } + +# if IP_SRCROUTE +postipsr: +# endif /* IP_SRCROUTE */ + if (tTd(9, 1)) + dprintf("getauthinfo: %s\n", hbuf); + return hbuf; +} + /* +** HOST_MAP_LOOKUP -- turn a hostname into canonical form +** +** Parameters: +** map -- a pointer to this map. +** 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 (unless MF_MATCHONLY is set, which will cause the +** status only to be returned). +*/ + +char * +host_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + register struct hostent *hp; +# if NETINET + struct in_addr in_addr; +# endif /* NETINET */ +# if NETINET6 + struct in6_addr in6_addr; +# endif /* NETINET6 */ + char *cp, *ans = NULL; + 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)) + dprintf("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 /* NAMED_BIND */ + *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)); + } + if (*statp != EX_OK) + return NULL; + if (s->s_namecanon.nc_cname == NULL) + { + syserr("host_map_lookup(%s): bogus NULL cache entry, errno = %d, h_errno = %d", + name, + s->s_namecanon.nc_errno, + s->s_namecanon.nc_herrno); + return NULL; + } + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, + s->s_namecanon.nc_cname, + strlen(s->s_namecanon.nc_cname), + av); + return cp; + } + + /* + ** 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 && + bitset(MF_DEFER, map->map_mflags)) + { + if (tTd(9, 1)) + dprintf("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 (tTd(9, 1)) + dprintf("host_map_lookup(%s) => ", name); + if (*name != '[') + { + snprintf(hbuf, sizeof hbuf, "%s", name); + if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) + ans = hbuf; + } + else + { + if ((cp = strchr(name, ']')) == NULL) + return NULL; + *cp = '\0'; + + hp = NULL; +# if NETINET + if ((in_addr.s_addr = inet_addr(&name[1])) != INADDR_NONE) + hp = sm_gethostbyaddr((char *)&in_addr, + INADDRSZ, AF_INET); +# endif /* NETINET */ +# if NETINET6 + if (hp == NULL && + inet_pton(AF_INET6, &name[1], &in6_addr) == 1) + hp = sm_gethostbyaddr((char *)&in6_addr, + IN6ADDRSZ, AF_INET6); +# endif /* NETINET6 */ + *cp = ']'; + + if (hp != NULL) + { + /* found a match -- copy out */ + ans = denlstring((char *) hp->h_name, TRUE, TRUE); + } + } + + s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ + + /* Found an answer */ + if (ans != NULL) + { + s->s_namecanon.nc_stat = *statp = EX_OK; + s->s_namecanon.nc_cname = newstr(ans); + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, ans, strlen(ans), av); + return cp; + } + + + /* No match found */ + s->s_namecanon.nc_errno = errno; +# if NAMED_BIND + s->s_namecanon.nc_herrno = h_errno; + if (tTd(9, 1)) + dprintf("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 /* NAMED_BIND */ + if (tTd(9, 1)) + dprintf("FAIL\n"); + *statp = EX_NOHOST; +# endif /* NAMED_BIND */ + s->s_namecanon.nc_stat = *statp; + return NULL; +} +#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 associated with a file descriptor +** +** Parameters: +** fd -- the descriptor +** may_be_forged -- an outage that is set to TRUE if the +** forward lookup of RealHostName does not match +** RealHostAddr; set to FALSE if they do match. +** +** Returns: +** The host name associated with this descriptor, if it can +** be determined. +** NULL otherwise. +** +** Side Effects: +** none +*/ + +char * +getauthinfo(fd, may_be_forged) + int fd; + bool *may_be_forged; +{ + *may_be_forged = FALSE; + return NULL; +} + /* +** HOST_MAP_LOOKUP -- 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 = NULL; + char *cp; + + hp = sm_gethostbyname(name, InetMode); + if (hp == NULL && InetMode != AF_INET) + hp = sm_gethostbyname(name, AF_INET); + if (hp == NULL) + { +# if NAMED_BIND + if (tTd(9, 1)) + dprintf("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 /* NAMED_BIND */ + *statp = EX_NOHOST; +#endif /* NAMED_BIND */ + return NULL; + } + if (bitset(MF_MATCHONLY, map->map_mflags)) + cp = map_rewrite(map, name, strlen(name), NULL); + else + cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); + return cp; +} + +#endif /* DAEMON */ + /* +** HOST_MAP_INIT -- initialize host class structures +*/ + +bool +host_map_init(map, args) + MAP *map; + char *args; +{ + register char *p = args; + + for (;;) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p != '-') + break; + switch (*++p) + { + case 'a': + map->map_app = ++p; + break; + + case 'T': + map->map_tapp = ++p; + break; + + case 'm': + map->map_mflags |= MF_MATCHONLY; + break; + + case 't': + map->map_mflags |= MF_NODEFER; + break; + + case 'S': /* only for consistency */ + map->map_spacesub = *++p; + break; + + case 'D': + map->map_mflags |= MF_DEFER; + break; + } + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + if (map->map_app != NULL) + map->map_app = newstr(map->map_app); + if (map->map_tapp != NULL) + map->map_tapp = newstr(map->map_tapp); + return TRUE; +} + +#if NETINET6 +/* +** ANYNET_NTOP -- convert an IPv6 network address to printable form. +** +** Parameters: +** s6a -- a pointer to an in6_addr structure. +** dst -- buffer to store result in +** dst_len -- size of dst buffer +** +** Returns: +** A printable version of that structure. +*/ +char * +anynet_ntop(s6a, dst, dst_len) + struct in6_addr *s6a; + char *dst; + size_t dst_len; +{ + register char *ap; + + if (IN6_IS_ADDR_V4MAPPED(s6a)) + ap = (char *) inet_ntop(AF_INET, + &s6a->s6_addr[IN6ADDRSZ - INADDRSZ], + dst, dst_len); + else + ap = (char *) inet_ntop(AF_INET6, s6a, dst, dst_len); + return ap; +} +#endif /* NETINET6 */ + /* +** ANYNET_NTOA -- convert a network address to printable form. +** +** Parameters: +** sap -- a pointer to a sockaddr structure. +** +** Returns: +** A printable version of that sockaddr. +*/ + +#ifdef USE_SOCK_STREAM + +# if NETLINK +# include +# endif /* NETLINK */ + +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') + snprintf(buf, sizeof buf, "[UNIX: %.64s]", + sap->sunix.sun_path); + else + snprintf(buf, sizeof buf, "[UNIX: localhost]"); + return buf; +# endif /* NETUNIX */ + +# if NETINET + case AF_INET: + return (char *) inet_ntoa(sap->sin.sin_addr); +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + ap = anynet_ntop(&sap->sin6.sin6_addr, buf, sizeof buf); + if (ap != NULL) + return ap; + break; +# endif /* NETINET6 */ + +# if NETLINK + case AF_LINK: + snprintf(buf, sizeof buf, "[LINK: %s]", + link_ntoa((struct sockaddr_dl *) &sap->sa)); + return buf; +# endif /* NETLINK */ + default: + /* this case is needed when nothing is #defined */ + /* in order to keep the switch syntactically correct */ + break; + } + + /* unknown family -- just dump bytes */ + (void) snprintf(buf, sizeof 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) snprintf(bp, SPACELEFT(buf, 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; +# if NAMED_BIND + int saveretry; +# endif /* NAMED_BIND */ +# if NETINET6 + struct in6_addr in6_addr; +# endif /* NETINET6 */ + +# if NAMED_BIND + /* shorten name server timeout to avoid higher level timeouts */ + saveretry = _res.retry; + if (_res.retry * _res.retrans > 20) + _res.retry = 20 / _res.retrans; +# 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 /* NETINET */ + +# if NETINET6 + case AF_INET6: + hp = sm_gethostbyaddr((char *) &sap->sin6.sin6_addr, + IN6ADDRSZ, + AF_INET6); + break; +# endif /* NETINET6 */ + +# if NETISO + case AF_ISO: + hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, + sizeof sap->siso.siso_addr, + AF_ISO); + break; +# endif /* NETISO */ + +# if NETUNIX + case AF_UNIX: + hp = NULL; + break; +# endif /* NETUNIX */ + + 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 NETINET || NETINET6 + if (hp != NULL && hp->h_name[0] != '[' +# if NETINET6 + && inet_pton(AF_INET6, hp->h_name, &in6_addr) != 1 +# endif /* NETINET6 */ +# if NETINET + && inet_addr(hp->h_name) == INADDR_NONE +# endif /* NETINET */ + ) + return denlstring((char *) hp->h_name, TRUE, TRUE); +# endif /* NETINET || NETINET6 */ +# if NETUNIX + if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') + return "localhost"; +# endif /* NETUNIX */ + { + static char buf[203]; + + (void) snprintf(buf, sizeof buf, "[%.200s]", anynet_ntoa(sap)); + return buf; + } +} +#endif /* USE_SOCK_STREAM */ diff --git a/gnu/usr.sbin/sendmail/sendmail/deliver.c b/gnu/usr.sbin/sendmail/sendmail/deliver.c new file mode 100644 index 00000000000..a63529243a8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/deliver.c @@ -0,0 +1,4497 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: deliver.c,v 8.594 2000/02/10 20:40:06 ca Exp $"; +#endif /* ! lint */ + +#include + +#if HASSETUSERCONTEXT +# include +#endif /* HASSETUSERCONTEXT */ + + +static int deliver __P((ENVELOPE *, ADDRESS *)); +static void dup_queue_file __P((ENVELOPE *, ENVELOPE *, int)); +static void mailfiletimeout __P((void)); +static void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int, bool)); +static int parse_hostsignature __P((char *, char **, MAILER *)); +static void sendenvelope __P((ENVELOPE *, int)); +static char *hostsignature __P((MAILER *, char *)); + +#if SMTP +#endif /* SMTP */ + +/* +** 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; + int mode; +{ + register ADDRESS *q; + char *owner; + int otherowners; + int save_errno; + register ENVELOPE *ee; + ENVELOPE *splitenv = NULL; + int oldverbose = Verbose; + bool somedeliveries = FALSE, expensive = FALSE; + pid_t pid; + + /* + ** If this message is to be discarded, don't bother sending + ** the message at all. + */ + + if (bitset(EF_DISCARD, e->e_flags)) + { + if (tTd(13, 1)) + dprintf("sendall: discarding id %s\n", e->e_id); + e->e_flags |= EF_CLRQUEUE; + if (LogLevel > 4) + sm_syslog(LOG_INFO, e->e_id, "discarded"); + markstats(e, NULL, TRUE); + return; + } + + /* + ** 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 */ + 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)) + { + dprintf("\n===== SENDALL: mode %c, id %s, e_from ", + mode, e->e_id); + printaddr(&e->e_from, FALSE); + dprintf("\te_flags = "); + printenvflags(e); + dprintf("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 (tTd(62, 1)) + checkfds(NULL); + + if (e->e_hopcount > MaxHopCount) + { + errno = 0; +#if QUEUE + queueup(e, mode == SM_QUEUE || mode == SM_DEFER); +#endif /* QUEUE */ + e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE; + ExitStat = EX_UNAVAILABLE; + syserr("554 5.0.0 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); + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_DEAD(q->q_state)) + continue; + q->q_status = "5.4.6"; + } + return; + } + + /* + ** Do sender deletion. + ** + ** If the sender should be queued up, 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) && + !QS_IS_QUEUEUP(e->e_from.q_state)) + { + if (tTd(13, 5)) + { + dprintf("sendall: QS_SENDER "); + printaddr(&e->e_from, FALSE); + } + e->e_from.q_state = QS_SENDER; + (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 && + !QS_IS_DEAD(q->q_state) && + strcmp(q->q_owner, e->e_from.q_paddr) == 0) + q->q_owner = NULL; + } + + if (tTd(13, 25)) + { + dprintf("\nAfter first owner pass, sendq =\n"); + printaddr(e->e_sendqueue, TRUE); + } + + owner = ""; + otherowners = 1; + while (owner != NULL && otherowners > 0) + { + if (tTd(13, 28)) + dprintf("owner = \"%s\", otherowners = %d\n", + owner, otherowners); + owner = NULL; + otherowners = bitset(EF_SENDRECEIPT, e->e_flags) ? 1 : 0; + + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (tTd(13, 30)) + { + dprintf("Checking "); + printaddr(q, FALSE); + } + if (QS_IS_DEAD(q->q_state)) + { + if (tTd(13, 30)) + dprintf(" ... QS_IS_DEAD\n"); + continue; + } + if (tTd(13, 29) && !tTd(13, 30)) + { + dprintf("Checking "); + printaddr(q, FALSE); + } + + if (q->q_owner != NULL) + { + if (owner == NULL) + { + if (tTd(13, 40)) + dprintf(" ... First owner = \"%s\"\n", + q->q_owner); + owner = q->q_owner; + } + else if (owner != q->q_owner) + { + if (strcmp(owner, q->q_owner) == 0) + { + if (tTd(13, 40)) + dprintf(" ... Same owner = \"%s\"\n", + owner); + + /* make future comparisons cheap */ + q->q_owner = owner; + } + else + { + if (tTd(13, 40)) + dprintf(" ... Another owner \"%s\"\n", + q->q_owner); + otherowners++; + } + owner = q->q_owner; + } + else if (tTd(13, 40)) + dprintf(" ... Same owner = \"%s\"\n", + owner); + } + else + { + if (tTd(13, 40)) + dprintf(" ... Null owner\n"); + otherowners++; + } + + if (QS_IS_BADADDR(q->q_state)) + { + if (tTd(13, 30)) + dprintf(" ... QS_IS_BADADDR\n"); + continue; + } + + if (QS_IS_QUEUEUP(q->q_state)) + { + MAILER *m = q->q_mailer; + + /* + ** If we have temporary address failures + ** (e.g., dns failure) and a fallback MX is + ** set, send directly to the fallback MX host. + */ + + if (FallBackMX != NULL && + !wordinclass(FallBackMX, 'w') && + mode != SM_VERIFY && + (strcmp(m->m_mailer, "[IPC]") == 0 || + strcmp(m->m_mailer, "[TCP]") == 0) && + m->m_argv[0] != NULL && + (strcmp(m->m_argv[0], "TCP") == 0 || + strcmp(m->m_argv[0], "IPC") == 0)) + { + int len; + char *p; + + if (tTd(13, 30)) + dprintf(" ... FallBackMX\n"); + + len = strlen(FallBackMX) + 3; + p = xalloc(len); + snprintf(p, len, "[%s]", FallBackMX); + q->q_state = QS_OK; + q->q_host = p; + } + else + { + if (tTd(13, 30)) + dprintf(" ... QS_IS_QUEUEUP\n"); + continue; + } + } + + /* + ** 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 (NoConnect && !Verbose && + bitnset(M_EXPENSIVE, q->q_mailer->m_flags)) + { + if (tTd(13, 30)) + dprintf(" ... expensive\n"); + q->q_state = QS_QUEUEUP; + expensive = TRUE; + } + else if (bitnset(M_HOLD, q->q_mailer->m_flags) && + QueueLimitId == NULL && + QueueLimitSender == NULL && + QueueLimitRecipient == NULL) + { + if (tTd(13, 30)) + dprintf(" ... hold\n"); + q->q_state = QS_QUEUEUP; + expensive = TRUE; + } + else + { + if (tTd(13, 30)) + dprintf(" ... deliverable\n"); + somedeliveries = TRUE; + } + } + + if (owner != NULL && otherowners > 0) + { + /* + ** Split this envelope into two. + */ + + ee = (ENVELOPE *) xalloc(sizeof *ee); + *ee = *e; + ee->e_message = NULL; + ee->e_id = NULL; + assign_queueid(ee); + + if (tTd(13, 1)) + dprintf("sendall: split %s into %s, owner = \"%s\", otherowners = %d\n", + e->e_id, ee->e_id, owner, otherowners); + + 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, '\0', TRUE); + if (tTd(13, 5)) + { + dprintf("sendall(split): QS_SENDER "); + printaddr(&ee->e_from, FALSE); + } + ee->e_from.q_state = QS_SENDER; + ee->e_dfp = NULL; + ee->e_lockfp = NULL; + ee->e_xfp = NULL; + ee->e_queuedir = e->e_queuedir; + ee->e_errormode = EM_MAIL; + ee->e_sibling = splitenv; + ee->e_statmsg = NULL; + splitenv = ee; + + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (q->q_owner == owner) + { + q->q_state = QS_CLONED; + if (tTd(13, 6)) + dprintf("\t... stripping %s from original envelope\n", + q->q_paddr); + } + } + for (q = ee->e_sendqueue; q != NULL; q = q->q_next) + { + if (q->q_owner != owner) + { + q->q_state = QS_CLONED; + if (tTd(13, 6)) + dprintf("\t... dropping %s from cloned envelope\n", + q->q_paddr); + } + else + { + /* clear DSN parameters */ + q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); + q->q_flags |= DefaultNotify & ~QPINGONSUCCESS; + if (tTd(13, 6)) + dprintf("\t... moving %s to cloned envelope\n", + q->q_paddr); + } + } + + if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags)) + dup_queue_file(e, ee, 'd'); + + /* + ** Give the split envelope access to the parent + ** transcript file for errors obtained while + ** processing the recipients (done before the + ** envelope splitting). + */ + + if (e->e_xfp != NULL) + ee->e_xfp = bfdup(e->e_xfp); + + /* failed to dup e->e_xfp, start a new transcript */ + if (ee->e_xfp == NULL) + openxscript(ee); + + if (mode != SM_VERIFY && LogLevel > 4) + sm_syslog(LOG_INFO, ee->e_id, + "clone %s, owner=%s", + e->e_id, owner); + } + } + + if (owner != NULL) + { + setsender(owner, e, NULL, '\0', TRUE); + if (tTd(13, 5)) + { + dprintf("sendall(owner): QS_SENDER "); + printaddr(&e->e_from, FALSE); + } + e->e_from.q_state = QS_SENDER; + e->e_errormode = EM_MAIL; + e->e_flags |= EF_NORECEIPT; + e->e_flags &= ~EF_FATALERRS; + } + + /* if nothing to be delivered, just queue up everything */ + if (!somedeliveries && mode != SM_QUEUE && mode != SM_DEFER && + mode != SM_VERIFY) + { + if (tTd(13, 29)) + dprintf("No deliveries: auto-queuing\n"); + mode = SM_QUEUE; + + /* treat this as a delivery in terms of counting tries */ + e->e_dtime = curtime(); + if (!expensive) + e->e_ntries++; + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + ee->e_dtime = curtime(); + if (!expensive) + ee->e_ntries++; + } + } + +#if QUEUE + if ((mode == SM_QUEUE || mode == SM_DEFER || mode == SM_FORK || + (mode != SM_VERIFY && SuperSafe)) && + (!bitset(EF_INQUEUE, e->e_flags) || splitenv != NULL)) + { + /* 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 (tTd(62, 10)) + checkfds("after envelope splitting"); + + /* + ** If we belong in background, fork now. + */ + + if (tTd(13, 20)) + { + dprintf("sendall: final mode = %c\n", mode); + if (tTd(13, 21)) + { + dprintf("\n================ Final Send Queue(s) =====================\n"); + dprintf("\n *** Envelope %s, e_from=%s ***\n", + e->e_id, e->e_from.q_paddr); + printaddr(e->e_sendqueue, TRUE); + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + dprintf("\n *** Envelope %s, e_from=%s ***\n", + ee->e_id, ee->e_from.q_paddr); + printaddr(ee->e_sendqueue, TRUE); + } + dprintf("==========================================================\n\n"); + } + } + switch (mode) + { + case SM_VERIFY: + Verbose = 2; + break; + + case SM_QUEUE: + case SM_DEFER: +#if HASFLOCK + queueonly: +#endif /* HASFLOCK */ + if (e->e_nrcpts > 0) + e->e_flags |= EF_INQUEUE; + dropenvelope(e, splitenv != NULL); + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + if (ee->e_nrcpts > 0) + ee->e_flags |= EF_INQUEUE; + dropenvelope(ee, FALSE); + } + 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, splitenv != NULL); + + /* arrange to reacquire lock after fork */ + e->e_id = qid; + } + + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + /* save id for future use */ + char *qid = ee->e_id; + + /* drop envelope in parent */ + ee->e_flags |= EF_INQUEUE; + dropenvelope(ee, FALSE); + + /* and save qid for reacquisition */ + ee->e_id = qid; + } + +#endif /* !HASFLOCK */ + + /* + ** Since the delivery may happen in a child and the parent + ** does not wait, the parent may close the maps thereby + ** removing any shared memory used by the map. Therefore, + ** close the maps now so the child will dynamically open + ** them if necessary. + */ + + closemaps(); + + pid = fork(); + if (pid < 0) + { + syserr("deliver: fork 1"); +#if HASFLOCK + goto queueonly; +#else /* HASFLOCK */ + e->e_id = NULL; + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + ee->e_id = NULL; + return; +#endif /* HASFLOCK */ + } + else if (pid > 0) + { +#if HASFLOCK + /* be sure we leave the temp files to our child */ + /* close any random open files in the envelope */ + closexscript(e); + if (e->e_dfp != NULL) + (void) bfclose(e->e_dfp); + e->e_dfp = NULL; + e->e_flags &= ~EF_HAS_DF; + + /* can't call unlockqueue to avoid unlink of xfp */ + if (e->e_lockfp != NULL) + (void) fclose(e->e_lockfp); + else + syserr("%s: sendall: null lockfp", e->e_id); + e->e_lockfp = NULL; +#endif /* HASFLOCK */ + + /* make sure the parent doesn't own the envelope */ + e->e_id = NULL; + + /* catch intermediate zombie */ + (void) waitfor(pid); + return; + } + + /* double fork to avoid zombies */ + pid = fork(); + if (pid > 0) + exit(EX_OK); + save_errno = errno; + + /* be sure we are immune from the terminal */ + disconnect(2, e); + clearstats(); + + /* prevent parent from waiting if there was an error */ + if (pid < 0) + { + errno = save_errno; + syserr("deliver: fork 2"); +#if HASFLOCK + e->e_flags |= EF_INQUEUE; +#else /* HASFLOCK */ + e->e_id = NULL; +#endif /* HASFLOCK */ + finis(TRUE, ExitStat); + } + + /* be sure to give error messages in child */ + QuickAbort = FALSE; + + /* + ** 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); + +#if HASFLOCK + break; +#else /* HASFLOCK */ + + /* + ** Now reacquire and run the various queue files. + */ + + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + ENVELOPE *sibling = ee->e_sibling; + + (void) dowork(ee->e_queuedir, ee->e_id, + FALSE, FALSE, ee); + ee->e_sibling = sibling; + } + (void) dowork(e->e_queuedir, e->e_id, + FALSE, FALSE, e); + finis(TRUE, ExitStat); +#endif /* HASFLOCK */ + } + + sendenvelope(e, mode); + dropenvelope(e, TRUE); + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + CurEnv = ee; + if (mode != SM_VERIFY) + openxscript(ee); + sendenvelope(ee, mode); + dropenvelope(ee, TRUE); + } + CurEnv = e; + + Verbose = oldverbose; + if (mode == SM_FORK) + finis(TRUE, ExitStat); +} + +static void +sendenvelope(e, mode) + register ENVELOPE *e; + int mode; +{ + register ADDRESS *q; + bool didany; + + if (tTd(13, 10)) + dprintf("sendenvelope(%s) e_flags=0x%lx\n", + e->e_id == NULL ? "[NOQUEUE]" : e->e_id, + e->e_flags); + if (LogLevel > 80) + sm_syslog(LOG_DEBUG, e->e_id, + "sendenvelope, flags=0x%lx", + e->e_flags); + + /* + ** 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; + } + + /* Don't attempt deliveries if we want to bounce now */ + if (!bitset(EF_RESPONSE, e->e_flags) && + TimeOuts.to_q_return[e->e_timeoutclass] == NOW) + 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; + + define(macid("{envid}", NULL), e->e_envid, e); + define(macid("{bodytype}", NULL), e->e_bodytype, e); + 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) snprintf(wbuf, sizeof wbuf, "sendall(%.*s)", + MAXNAME, q->q_paddr); + checkfd012(wbuf); +#endif /* XDEBUG */ + if (mode == SM_VERIFY) + { + e->e_to = q->q_paddr; + if (QS_IS_SENDABLE(q->q_state)) + { + 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 (QS_IS_OK(q->q_state)) + { +#if 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 /* XDEBUG */ +} + /* +** DUP_QUEUE_FILE -- duplicate a queue file into a split queue +** +** Parameters: +** e -- the existing envelope +** ee -- the new envelope +** type -- the queue file type (e.g., 'd') +** +** Returns: +** none +*/ + +static void +dup_queue_file(e, ee, type) + struct envelope *e, *ee; + int type; +{ + char f1buf[MAXPATHLEN], f2buf[MAXPATHLEN]; + + ee->e_dfp = NULL; + ee->e_xfp = NULL; + + /* + ** Make sure both are in the same directory. + */ + + snprintf(f1buf, sizeof f1buf, "%s", queuename(e, type)); + snprintf(f2buf, sizeof f2buf, "%s", queuename(ee, type)); + if (link(f1buf, f2buf) < 0) + { + int save_errno = errno; + + syserr("sendall: link(%s, %s)", f1buf, f2buf); + if (save_errno == EEXIST) + { + if (unlink(f2buf) < 0) + { + syserr("!sendall: unlink(%s): permanent", + f2buf); + /* NOTREACHED */ + } + if (link(f1buf, f2buf) < 0) + { + syserr("!sendall: link(%s, %s): permanent", + f1buf, f2buf); + /* NOTREACHED */ + } + } + } +} + /* +** 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 /* ! FORK */ + +#define DOFORK(fORKfN) \ +{\ + register int i;\ +\ + for (i = NFORKTRIES; --i >= 0; )\ + {\ + pid = fORKfN();\ + if (pid >= 0)\ + break;\ + if (i > 0)\ + (void) 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 pid_t 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. +*/ + +#ifndef NO_UID +# define NO_UID -1 +#endif /* ! NO_UID */ +#ifndef NO_GID +# define NO_GID -1 +#endif /* ! NO_GID */ + +static 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; + ADDRESS *volatile contextaddr = NULL; + 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 */ + int lmtp_rcode = EX_OK; + int nummxhosts = 0; /* number of MX hosts available */ + int hostnum = 0; /* current MX host index */ + char *firstsig; /* signature of firstto */ + pid_t pid = -1; + char *volatile curhost; + register u_short port = 0; +#if NETUNIX + char *mux_path = NULL; /* path to UNIX domain socket */ +#endif /* NETUNIX */ + time_t xstart; + bool suidwarn; + bool anyok; /* at least one address was OK */ + bool goodmxfound = FALSE; /* at least one MX was OK */ + bool ovr; + int mpvect[2]; + int rpvect[2]; + char *mxhosts[MAXMXHOSTS + 1]; + char *pv[MAXPV + 1]; + char tobuf[TOBUFSIZE]; /* text line of to people */ + char buf[MAXNAME + 1]; + char rpathbuf[MAXNAME + 1]; /* translated return path */ + + errno = 0; + if (!QS_IS_OK(to->q_state)) + return 0; + + suidwarn = geteuid() == 0; + + m = to->q_mailer; + host = to->q_host; + CurEnv = e; /* just in case */ + e->e_statmsg = NULL; +#if SMTP + SmtpError[0] = '\0'; +#endif /* SMTP */ + xstart = curtime(); + + if (tTd(10, 1)) + dprintf("\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); + + /* + ** Clear $&{client_*} macros if this is a bounce message to + ** prevent rejection by check_compat ruleset. + */ + + if (bitset(EF_RESPONSE, e->e_flags)) + { + define(macid("{client_name}", NULL), "", e); + define(macid("{client_addr}", NULL), "", e); + define(macid("{client_port}", NULL), "", e); + } + + /* + ** 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; + p = remotename(p, m, RF_SENDERADDR|RF_CANONICAL, &rcode, e); + if (strlen(p) >= (SIZE_T) sizeof rpathbuf) + { + p = shortenstring(p, MAXSHORTSTR); + syserr("remotename: huge return %s", p); + } + snprintf(rpathbuf, sizeof rpathbuf, "%s", p); + 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 5.3.5 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 */ +#if SMTP + clever = TRUE; + *pvp = NULL; +#else /* SMTP */ + /* oops! we don't implement SMTP */ + syserr("554 5.3.5 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); + 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 (!QS_IS_OK(to->q_state) || + to->q_mailer != firstto->q_mailer || + strcmp(hostsignature(to->q_mailer, to->q_host), + firstsig) != 0) + continue; + + /* avoid overflowing tobuf */ + if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) + break; + + if (tTd(10, 1)) + { + dprintf("\nsend to "); + printaddr(to, FALSE); + } + + /* compute effective uid/gid when sending */ + if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags)) + contextaddr = ctladdr = getctladdr(to); + + if (tTd(10, 2)) + { + dprintf("ctladdr="); + printaddr(ctladdr, FALSE); + } + + user = to->q_user; + e->e_to = to->q_paddr; + + /* + ** 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; + if (bitnset(M_LOCALMAILER, to->q_mailer->m_flags)) + to->q_status = "5.2.3"; + else + to->q_status = "5.3.4"; + /* set to->q_rstatus = NULL; or to the following? */ + usrerrenh(to->q_status, + "552 Message is too large; %ld bytes max", + m->m_maxsize); + markfailure(e, to, NULL, EX_UNAVAILABLE, FALSE); + giveresponse(EX_UNAVAILABLE, to->q_status, m, + NULL, ctladdr, xstart, e); + continue; + } +#if NAMED_BIND + h_errno = 0; +#endif /* NAMED_BIND */ + + ovr = TRUE; + /* do config file checking of compatibility */ + rcode = rscheck("check_compat", + e->e_from.q_paddr, to->q_paddr, e, TRUE, TRUE); + if (rcode == EX_OK) + { + /* do in-code checking if not discarding */ + if (!bitset(EF_DISCARD, e->e_flags)) + { + rcode = checkcompat(to, e); + ovr = FALSE; + } + } + if (rcode != EX_OK) + { + markfailure(e, to, NULL, rcode, ovr); + giveresponse(rcode, to->q_status, m, + NULL, ctladdr, xstart, e); + continue; + } + if (bitset(EF_DISCARD, e->e_flags)) + { + if (tTd(10, 5)) + { + dprintf("deliver: discarding recipient "); + printaddr(to, FALSE); + } + + /* pretend the message was sent */ + /* XXX should we log something here? */ + to->q_state = QS_DISCARDED; + + /* + ** Remove discard bit to prevent discard of + ** future recipients. This is safe because the + ** true "global discard" has been handled before + ** we get here. + */ + + e->e_flags &= ~EF_DISCARD; + 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 (!QS_IS_OK(to->q_state)) + continue; + + /* + ** 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) + { + 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(m->m_argv[1], buf, sizeof buf, e); + if (strlen(buf) > 0) + rcode = mailfile(buf, m, ctladdr, SFF_CREAT, e); + else + { + syserr("empty filename specification for mailer %s", + m->m_name); + rcode = EX_CONFIG; + } + giveresponse(rcode, to->q_status, m, NULL, + ctladdr, xstart, e); + markfailure(e, to, NULL, rcode, TRUE); + e->e_nsent++; + if (rcode == EX_OK) + { + to->q_state = QS_SENT; + if (bitnset(M_LOCALMAILER, m->m_flags) && + 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(); + markstats(e, to, FALSE); + 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) strlcat(tobuf, ",", sizeof tobuf); + (void) strlcat(tobuf, to->q_paddr, sizeof tobuf); + 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 */ + + /* set the ${dsn_notify} macro if applicable */ + if (bitset(QHASNOTIFY, to->q_flags)) + { + char notify[MAXLINE]; + + notify[0] = '\0'; + if (bitset(QPINGONSUCCESS, to->q_flags)) + (void) strlcat(notify, "SUCCESS,", + sizeof notify); + if (bitset(QPINGONFAILURE, to->q_flags)) + (void) strlcat(notify, "FAILURE,", + sizeof notify); + if (bitset(QPINGONDELAY, to->q_flags)) + (void) strlcat(notify, "DELAY,", sizeof notify); + + /* Set to NEVER or drop trailing comma */ + if (notify[0] == '\0') + (void) strlcat(notify, "NEVER", sizeof notify); + else + notify[strlen(notify) - 1] = '\0'; + + define(macid("{dsn_notify}", NULL), newstr(notify), e); + } + else + define(macid("{dsn_notify}", NULL), NULL, e); + + /* + ** 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 5.3.0 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 /* NAMED_BIND */ + + if (tTd(11, 1)) + { + dprintf("openmailer:"); + printav(pv); + } + errno = 0; +#if NAMED_BIND + h_errno = 0; +#endif /* NAMED_BIND */ + + 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 */ + snprintf(wbuf, sizeof wbuf, "%s... openmailer(%s)", + shortenstring(e->e_to, MAXSHORTSTR), m->m_name); + checkfd012(wbuf); + } +#endif /* XDEBUG */ + + /* 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))))) + { + e->e_status = "5.6.3"; + usrerrenh(e->e_status, + "554 Cannot send 8-bit data to 7-bit destination"); + rcode = EX_DATAERR; + goto give_up; + } + + if (tTd(62, 8)) + checkfds("before delivery"); + + /* check for Local Person Communication -- not for mortals!!! */ + if (strcmp(m->m_mailer, "[LPC]") == 0) + { + mci = (MCI *) xalloc(sizeof *mci); + memset((char *) mci, '\0', 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) + { +#if DAEMON + register int i; + + if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0') + { + syserr("null destination for %s mailer", m->m_mailer); + rcode = EX_CONFIG; + goto give_up; + } + +# if NETUNIX + if (strcmp(pv[0], "FILE") == 0) + { + curhost = CurHostName = "localhost"; + mux_path = pv[1]; + } + else +# endif /* NETUNIX */ + { + CurHostName = pv[1]; + curhost = hostsignature(m, pv[1]); + } + + if (curhost == NULL || curhost[0] == '\0') + { + syserr("null host signature for %s", pv[1]); + rcode = EX_CONFIG; + goto give_up; + } + + if (!clever) + { + syserr("554 5.3.5 non-clever IPC"); + rcode = EX_CONFIG; + goto give_up; + } + if (pv[2] != NULL +# if NETUNIX + && mux_path == NULL +# endif /* NETUNIX */ + ) + { + port = htons(atoi(pv[2])); + if (port == 0) + { +# ifdef NO_GETSERVBYNAME + syserr("Invalid port number: %s", pv[2]); +# else /* NO_GETSERVBYNAME */ + struct servent *sp = getservbyname(pv[2], "tcp"); + + if (sp == NULL) + syserr("Service %s unknown", pv[2]); + else + port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + } + + nummxhosts = parse_hostsignature(curhost, mxhosts, m); +tryhost: + while (hostnum < nummxhosts) + { + char sep = ':'; + char *endp; + static char hostbuf[MAXNAME + 1]; + +# if NETINET6 + if (*mxhosts[hostnum] == '[') + { + endp = strchr(mxhosts[hostnum] + 1, ']'); + if (endp != NULL) + endp = strpbrk(endp + 1, ":,"); + } + else + endp = strpbrk(mxhosts[hostnum], ":,"); +# else /* NETINET6 */ + endp = strpbrk(mxhosts[hostnum], ":,"); +# endif /* NETINET6 */ + if (endp != NULL) + { + sep = *endp; + *endp = '\0'; + } + + if (*mxhosts[hostnum] == '\0') + { + syserr("deliver: null host name in signature"); + hostnum++; + if (endp != NULL) + *endp = sep; + continue; + } + (void) strlcpy(hostbuf, mxhosts[hostnum], + sizeof hostbuf); + hostnum++; + if (endp != NULL) + *endp = sep; + + /* 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)) + { + dprintf("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); + mci->mci_deliveries++; + break; + } + mci->mci_mailer = m; + if (mci->mci_exitstat != EX_OK) + { + if (mci->mci_exitstat == EX_TEMPFAIL) + goodmxfound = TRUE; + continue; + } + + if (mci_lock_host(mci) != EX_OK) + { + mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); + goodmxfound = TRUE; + continue; + } + + /* try the connection */ + sm_setproctitle(TRUE, e, "%s %s: %s", + qid_printname(e), + hostbuf, "user open"); +# if NETUNIX + if (mux_path != NULL) + { + message("Connecting to %s via %s...", + mux_path, m->m_name); + i = makeconnection_ds(mux_path, mci); + } + else +# endif /* NETUNIX */ + { + if (port == 0) + message("Connecting to %s via %s...", + hostbuf, m->m_name); + else + message("Connecting to %s port %d via %s...", + hostbuf, ntohs(port), + m->m_name); + i = makeconnection(hostbuf, port, mci, e); + } + mci->mci_lastuse = curtime(); + mci->mci_deliveries = 0; + mci->mci_exitstat = i; + mci->mci_errno = errno; +# if NAMED_BIND + mci->mci_herrno = h_errno; +# endif /* NAMED_BIND */ + if (i == EX_OK) + { + goodmxfound = TRUE; + mci->mci_state = MCIS_OPENING; + mci_cache(mci); + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d === CONNECT %s\n", + (int) getpid(), hostbuf); + break; + } + else + { + if (tTd(11, 1)) + dprintf("openmailer: makeconnection => stat=%d, errno=%d\n", + i, errno); + if (i == EX_TEMPFAIL) + goodmxfound = TRUE; + mci_unlock_host(mci); + } + + /* 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_SOFTWARE; + goto give_up; + } + mci->mci_pid = 0; +#else /* DAEMON */ + syserr("554 5.3.5 openmailer: no IPC"); + if (tTd(11, 1)) + dprintf("openmailer: NULL\n"); + rcode = EX_UNAVAILABLE; + goto give_up; +#endif /* DAEMON */ + } + else + { + /* flush any expired connections */ + (void) mci_scan(NULL); + mci = NULL; + +#if SMTP + if (bitnset(M_LMTP, m->m_flags)) + { + /* try to get a cached connection */ + mci = mci_get(m->m_name, m); + if (mci->mci_host == NULL) + mci->mci_host = m->m_name; + CurHostName = mci->mci_host; + if (mci->mci_state != MCIS_CLOSED) + { + message("Using cached LMTP connection for %s...", + m->m_name); + mci->mci_deliveries++; + goto do_transfer; + } + } +#endif /* SMTP */ + + /* 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", (int) getpid()); + for (av = pv; *av != NULL; av++) + fprintf(TrafficLogFile, " %s", *av); + fprintf(TrafficLogFile, "\n"); + } + +#if XDEBUG + checkfd012("before creating mail pipe"); +#endif /* XDEBUG */ + + /* create a pipe to shove the mail through */ + if (pipe(mpvect) < 0) + { + syserr("%s... openmailer(%s): pipe (to mailer)", + shortenstring(e->e_to, MAXSHORTSTR), m->m_name); + if (tTd(11, 1)) + dprintf("openmailer: NULL\n"); + rcode = EX_OSERR; + goto give_up; + } + +#if XDEBUG + /* make sure we didn't get one of the standard I/O files */ + if (mpvect[0] < 3 || mpvect[1] < 3) + { + syserr("%s... openmailer(%s): bogus mpvect %d %d", + shortenstring(e->e_to, MAXSHORTSTR), m->m_name, + mpvect[0], mpvect[1]); + printopenfds(TRUE); + if (tTd(11, 1)) + dprintf("openmailer: NULL\n"); + rcode = EX_OSERR; + goto give_up; + } + + /* make sure system call isn't dead meat */ + checkfdopen(mpvect[0], "mpvect[0]"); + checkfdopen(mpvect[1], "mpvect[1]"); + if (mpvect[0] == mpvect[1] || + (e->e_lockfp != NULL && + (mpvect[0] == fileno(e->e_lockfp) || + mpvect[1] == fileno(e->e_lockfp)))) + { + if (e->e_lockfp == NULL) + syserr("%s... openmailer(%s): overlapping mpvect %d %d", + shortenstring(e->e_to, MAXSHORTSTR), + m->m_name, mpvect[0], mpvect[1]); + else + syserr("%s... openmailer(%s): overlapping mpvect %d %d, lockfp = %d", + shortenstring(e->e_to, MAXSHORTSTR), + m->m_name, mpvect[0], mpvect[1], + fileno(e->e_lockfp)); + } +#endif /* XDEBUG */ + + /* create a return pipe */ + if (pipe(rpvect) < 0) + { + syserr("%s... openmailer(%s): pipe (from mailer)", + shortenstring(e->e_to, MAXSHORTSTR), + m->m_name); + (void) close(mpvect[0]); + (void) close(mpvect[1]); + if (tTd(11, 1)) + dprintf("openmailer: NULL\n"); + rcode = EX_OSERR; + goto give_up; + } +#if XDEBUG + checkfdopen(rpvect[0], "rpvect[0]"); + checkfdopen(rpvect[1], "rpvect[1]"); +#endif /* XDEBUG */ + + /* + ** Actually fork the mailer process. + ** DOFORK is clever about retrying. + ** + ** Dispose of SIGCHLD signal catchers that may be laying + ** around so that endmailer will get it. + */ + + if (e->e_xfp != NULL) + (void) fflush(e->e_xfp); /* for debugging */ + (void) fflush(stdout); + (void) setsignal(SIGCHLD, SIG_DFL); + DOFORK(FORK); + /* pid is set by DOFORK */ + if (pid < 0) + { + /* failure */ + syserr("%s... openmailer(%s): cannot fork", + shortenstring(e->e_to, MAXSHORTSTR), m->m_name); + (void) close(mpvect[0]); + (void) close(mpvect[1]); + (void) close(rpvect[0]); + (void) close(rpvect[1]); + if (tTd(11, 1)) + dprintf("openmailer: NULL\n"); + rcode = EX_OSERR; + goto give_up; + } + else if (pid == 0) + { + int i; + int save_errno; + int new_euid = NO_UID; + int new_ruid = NO_UID; + int new_gid = NO_GID; + 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; + +#if HASSETUSERCONTEXT + /* + ** Set user resources. + */ + + if (contextaddr != NULL) + { + struct passwd *pwd; + + if (contextaddr->q_ruser != NULL) + pwd = sm_getpwnam(contextaddr->q_ruser); + else + pwd = sm_getpwnam(contextaddr->q_user); + if (pwd != NULL) + (void) setusercontext(NULL, + pwd, pwd->pw_uid, + LOGIN_SETRESOURCES|LOGIN_SETPRIORITY); + } +#endif /* HASSETUSERCONTEXT */ + + /* tweak niceness */ + if (m->m_nice != 0) + (void) nice(m->m_nice); + + /* reset group id */ + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + new_gid = m->m_gid; + else if (bitset(S_ISGID, stb.st_mode)) + new_gid = stb.st_gid; + else if (ctladdr != NULL && ctladdr->q_gid != 0) + { + if (!DontInitGroups) + { + char *u = ctladdr->q_ruser; + + if (u == NULL) + u = ctladdr->q_user; + + if (initgroups(u, ctladdr->q_gid) == -1 && suidwarn) + syserr("openmailer: initgroups(%s, %d) failed", + u, ctladdr->q_gid); + } + else + { + GIDSET_T gidset[1]; + + gidset[0] = ctladdr->q_gid; + if (setgroups(1, gidset) == -1 && suidwarn) + syserr("openmailer: setgroups() failed"); + } + new_gid = ctladdr->q_gid; + } + else + { + if (!DontInitGroups) + { + if (initgroups(DefUser, DefGid) == -1 && suidwarn) + syserr("openmailer: initgroups(%s, %d) failed", + DefUser, DefGid); + } + else + { + GIDSET_T gidset[1]; + + gidset[0] = DefGid; + if (setgroups(1, gidset) == -1 && suidwarn) + syserr("openmailer: setgroups() failed"); + } + if (m->m_gid == 0) + new_gid = DefGid; + else + new_gid = m->m_gid; + } + if (new_gid != NO_GID && setgid(new_gid) < 0 && suidwarn) + syserr("openmailer: setgid(%ld) failed", + (long) new_gid); + + /* change root to some "safe" directory */ + if (m->m_rootdir != NULL) + { + expand(m->m_rootdir, buf, sizeof buf, e); + if (tTd(11, 20)) + dprintf("openmailer: chroot %s\n", + buf); + if (chroot(buf) < 0) + syserr("openmailer: Cannot chroot(%s)", + buf); + if (chdir("/") < 0) + syserr("openmailer: cannot chdir(/)"); + } + + /* reset user id */ + endpwent(); + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + new_euid = m->m_uid; + else if (bitset(S_ISUID, stb.st_mode)) + new_ruid = stb.st_uid; + else if (ctladdr != NULL && ctladdr->q_uid != 0) + new_ruid = ctladdr->q_uid; + else if (m->m_uid != 0) + new_ruid = m->m_uid; + else + new_ruid = DefUid; + if (new_euid != NO_UID) + { + vendor_set_uid(new_euid); +#if MAILER_SETUID_METHOD == USE_SETEUID + if (seteuid(new_euid) < 0 && suidwarn) + syserr("openmailer: seteuid(%ld) failed", + (long) new_euid); +#endif /* MAILER_SETUID_METHOD == USE_SETEUID */ +#if MAILER_SETUID_METHOD == USE_SETREUID + if (setreuid(new_ruid, new_euid) < 0 && suidwarn) + syserr("openmailer: setreuid(%ld, %ld) failed", + (long) new_ruid, (long) new_euid); +#endif /* MAILER_SETUID_METHOD == USE_SETREUID */ +#if MAILER_SETUID_METHOD == USE_SETUID + if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn) + syserr("openmailer: setuid(%ld) failed", + (long) new_euid); +#endif /* MAILER_SETUID_METHOD == USE_SETUID */ + } + else if (new_ruid != NO_UID) + { + vendor_set_uid(new_ruid); + if (setuid(new_ruid) < 0 && suidwarn) + syserr("openmailer: setuid(%ld) failed", + (long) new_ruid); + } + + if (tTd(11, 2)) + dprintf("openmailer: running as r/euid=%d/%d, r/egid=%d/%d\n", + (int) getuid(), (int) geteuid(), + (int) getgid(), (int) getegid()); + + /* move into some "safe" directory */ + if (m->m_execdir != NULL) + { + char *q; + + 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)) + dprintf("openmailer: trydir %s\n", + buf); + if (buf[0] != '\0' && chdir(buf) >= 0) + break; + } + } + + /* arrange to filter std & diag output of command */ + (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, MAXSHORTSTR), + m->m_name, rpvect[1]); + _exit(EX_OSERR); + } + (void) close(rpvect[1]); + + if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) + { + syserr("%s... openmailer(%s): cannot dup stdout for stderr", + shortenstring(e->e_to, MAXSHORTSTR), + 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, MAXSHORTSTR), + 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 | FD_CLOEXEC); + } + + /* run disconnected from terminal */ + (void) setsid(); + + /* try to execute the mailer */ + (void) execve(m->m_mailer, (ARGV_T) pv, + (ARGV_T) UserEnviron); + save_errno = errno; + syserr("Cannot exec %s", m->m_mailer); + if (bitnset(M_LOCALMAILER, m->m_flags) || + transienterror(save_errno)) + _exit(EX_OSERR); + _exit(EX_UNAVAILABLE); + } + + /* + ** Set up return value. + */ + + if (mci == NULL) + { + mci = (MCI *) xalloc(sizeof *mci); + memset((char *) mci, '\0', sizeof *mci); + } + mci->mci_mailer = m; + if (clever) + { + mci->mci_state = MCIS_OPENING; + mci_cache(mci); + } + else + { + mci->mci_state = 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]); + (void) close(rpvect[0]); + (void) close(rpvect[1]); + rcode = EX_OSERR; + goto give_up; + } + + (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]); + (void) fclose(mci->mci_out); + mci->mci_out = NULL; + rcode = EX_OSERR; + goto give_up; + } + + /* Don't cache non-clever connections */ + if (!clever) + mci->mci_flags |= MCIF_TEMP; + } + + /* + ** If we are in SMTP opening state, send initial protocol. + */ + + if (bitnset(M_7BITS, m->m_flags) && + (!clever || mci->mci_state == MCIS_OPENING)) + mci->mci_flags |= MCIF_7BIT; +#if SMTP + if (clever && mci->mci_state != MCIS_CLOSED) + { + static u_short again = 0; +# define ONLY_HELO_B 0x04 +# define ONLY_HELO bitset(ONLY_HELO_B, again) +# define SET_HELO again |= ONLY_HELO_B +# define CLR_HELO again &= ~ONLY_HELO_B + + +# if SASL + mci->mci_saslcap = NULL; +# endif /* SASL */ + smtpinit(m, mci, e, ONLY_HELO); + CLR_HELO; + +# if SASL + /* if other server supports authentication let's authenticate */ + if (mci->mci_state != MCIS_CLOSED && + mci->mci_saslcap != NULL && + SASLInfo != NULL) + { + /* + ** should we require some minimum authentication? + ** XXX ignore result? + */ + if (smtpauth(m, mci, e) == EX_OK) + { + mci->mci_flags |= MCIF_AUTHACT; + + } + } +# endif /* SASL */ + } + +#endif /* SMTP */ + +do_transfer: + /* clear out per-message flags from connection structure */ + mci->mci_flags &= ~(MCIF_CVT7TO8|MCIF_CVT8TO7); + + 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; + +#if MIME7TO8 + if (bitnset(M_MAKE8BIT, m->m_flags) && + !bitset(MCIF_7BIT, mci->mci_flags) && + (p = hvalue("Content-Transfer-Encoding", e->e_header)) != NULL && + (strcasecmp(p, "quoted-printable") == 0 || + strcasecmp(p, "base64") == 0) && + (p = hvalue("Content-Type", e->e_header)) != NULL) + { + /* may want to convert 7 -> 8 */ + /* XXX should really parse it here -- and use a class XXX */ + if (strncasecmp(p, "text/plain", 10) == 0 && + (p[10] == '\0' || p[10] == ' ' || p[10] == ';')) + mci->mci_flags |= MCIF_CVT7TO8; + } +#endif /* MIME7TO8 */ + + if (tTd(11, 1)) + { + dprintf("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 /* NAMED_BIND */ + if (rcode == EX_OK) + { + /* shouldn't happen */ + syserr("554 5.3.5 deliver: mci=%lx rcode=%d errno=%d state=%d sig=%s", + (u_long) mci, rcode, errno, mci->mci_state, + firstsig); + mci_dump_all(TRUE); + rcode = EX_SOFTWARE; + } +#if DAEMON + else if (nummxhosts > hostnum) + { + /* try next MX site */ + goto tryhost; + } +#endif /* DAEMON */ + } + else if (!clever) + { + /* + ** Format and send message. + */ + + putfromline(mci, e); + (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER); + (*e->e_putbody)(mci, e, NULL); + + /* get the exit status */ + rcode = endmailer(mci, e, pv); + } + else +#if 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 (strlen(to->q_paddr) + + (t - tobuf) + 2 > sizeof tobuf) + { + /* not enough room */ + continue; + } + else if ((i = smtprcpt(to, m, mci, e)) != EX_OK) + { + markfailure(e, to, mci, i, FALSE); + giveresponse(i, to->q_status, 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); + } + } +# if DAEMON + if (rcode == EX_TEMPFAIL && nummxhosts > hostnum) + { + /* try next MX site */ + goto tryhost; + } +# endif /* DAEMON */ + } +#else /* SMTP */ + { + syserr("554 5.3.5 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 /* NAMED_BIND */ + + if (tTd(62, 1)) + checkfds("after delivery"); + + /* + ** 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 SMTP + if (bitnset(M_LMTP, m->m_flags)) + { + lmtp_rcode = rcode; + tobuf[0] = '\0'; + anyok = FALSE; + } + else +#endif /* SMTP */ + anyok = rcode == EX_OK; + + for (to = tochain; to != NULL; to = to->q_tchain) + { + /* see if address already marked */ + if (!QS_IS_OK(to->q_state)) + continue; + +#if SMTP + /* if running LMTP, get the status for each address */ + if (bitnset(M_LMTP, m->m_flags)) + { + if (lmtp_rcode == EX_OK) + rcode = smtpgetstat(m, mci, e); + if (rcode == EX_OK) + { + if (strlen(to->q_paddr) + + strlen(tobuf) + 2 > sizeof tobuf) + { + syserr("LMTP tobuf overflow"); + } + else + { + (void) strlcat(tobuf, ",", + sizeof tobuf); + (void) strlcat(tobuf, to->q_paddr, + sizeof tobuf); + } + anyok = TRUE; + } + else + { + e->e_to = to->q_paddr; + markfailure(e, to, mci, rcode, TRUE); + giveresponse(rcode, to->q_status, m, mci, + ctladdr, xstart, e); + e->e_to = tobuf + 1; + continue; + } + } + else +#endif /* SMTP */ + { + /* mark bad addresses */ + if (rcode != EX_OK) + { + if (goodmxfound && rcode == EX_NOHOST) + rcode = EX_TEMPFAIL; + markfailure(e, to, mci, rcode, TRUE); + continue; + } + } + + /* successful delivery */ + to->q_state = QS_SENT; + to->q_statdate = curtime(); + e->e_nsent++; + +#if QUEUE + /* + ** Checkpoint the send list every few addresses + */ + + if (e->e_nsent >= CheckpointInterval) + { + queueup(e, FALSE); + e->e_nsent = 0; + } +#endif /* QUEUE */ + + if (bitnset(M_LOCALMAILER, m->m_flags) && + 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); + } + } + +#if SMTP + if (bitnset(M_LMTP, m->m_flags)) + { + /* + ** Global information applies to the last recipient only; + ** clear it out to avoid bogus errors. + */ + + rcode = EX_OK; + e->e_statmsg = NULL; + + /* reset the mci state for the next transaction */ + if (mci != NULL && mci->mci_state == MCIS_ACTIVE) + mci->mci_state = MCIS_OPEN; + } +#endif /* SMTP */ + + if (tobuf[0] != '\0') + giveresponse(rcode, NULL, m, mci, ctladdr, xstart, e); + if (anyok) + markstats(e, tochain, FALSE); + mci_store_persistent(mci); + +#if SMTP + /* now close the connection */ + if (clever && mci != NULL && mci->mci_state != MCIS_CLOSED && + !bitset(MCIF_CACHED, mci->mci_flags)) + smtpquit(m, mci, e); +#endif /* SMTP */ + + /* + ** Restore state and return. + */ + +#if XDEBUG + { + char wbuf[MAXLINE]; + + /* make absolutely certain 0, 1, and 2 are in use */ + snprintf(wbuf, sizeof wbuf, "%s... end of deliver(%s)", + e->e_to == NULL ? "NO-TO-LIST" + : shortenstring(e->e_to, MAXSHORTSTR), + m->m_name); + checkfd012(wbuf); + } +#endif /* XDEBUG */ + + 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. +** ovr -- override an existing code? +** +** 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. +*/ + +static void +markfailure(e, q, mci, rcode, ovr) + register ENVELOPE *e; + register ADDRESS *q; + register MCI *mci; + int rcode; + bool ovr; +{ + char *status = NULL; + char *rstatus = NULL; + + switch (rcode) + { + case EX_OK: + break; + + case EX_TEMPFAIL: + case EX_IOERR: + case EX_OSERR: + q->q_state = QS_QUEUEUP; + break; + + default: + q->q_state = QS_BADADDR; + break; + } + + /* find most specific error code possible */ + if (mci != NULL && mci->mci_status != NULL) + { + status = mci->mci_status; + if (mci->mci_rstatus != NULL) + rstatus = newstr(mci->mci_rstatus); + else + rstatus = NULL; + } + else if (e->e_status != NULL) + { + status = e->e_status; + rstatus = NULL; + } + else + { + switch (rcode) + { + case EX_USAGE: + status = "5.5.4"; + break; + + case EX_DATAERR: + status = "5.5.2"; + break; + + case EX_NOUSER: + status = "5.1.1"; + break; + + case EX_NOHOST: + status = "5.1.2"; + break; + + case EX_NOINPUT: + case EX_CANTCREAT: + case EX_NOPERM: + status = "5.3.0"; + break; + + case EX_UNAVAILABLE: + case EX_SOFTWARE: + case EX_OSFILE: + case EX_PROTOCOL: + case EX_CONFIG: + status = "5.5.0"; + break; + + case EX_OSERR: + case EX_IOERR: + status = "4.5.0"; + break; + + case EX_TEMPFAIL: + status = "4.2.0"; + break; + } + } + + /* new status? */ + if (status != NULL && *status != '\0' && (ovr || q->q_status == NULL || + *q->q_status == '\0' || *q->q_status < *status)) + { + q->q_status = status; + q->q_rstatus = rstatus; + } + if (rcode != EX_OK && q->q_rstatus == NULL && + q->q_mailer != NULL && q->q_mailer->m_diagtype != NULL && + strcasecmp(q->q_mailer->m_diagtype, "X-UNIX") == 0) + { + char buf[16]; + + (void) snprintf(buf, sizeof buf, "%d", rcode); + q->q_rstatus = newstr(buf); + } + + q->q_statdate = curtime(); + if (CurHostName != NULL && CurHostName[0] != '\0' && + mci != NULL && !bitset(M_LOCALMAILER, mci->mci_flags)) + q->q_statmta = newstr(CurHostName); +} + /* +** 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. +*/ + +static jmp_buf EndWaitTimeout; + +static void +endwaittimeout() +{ + errno = ETIMEDOUT; + longjmp(EndWaitTimeout, 1); +} + +int +endmailer(mci, e, pv) + register MCI *mci; + register ENVELOPE *e; + char **pv; +{ + int st; + int save_errno = errno; + char buf[MAXLINE]; + EVENT *ev = NULL; + + mci_unlock_host(mci); + +#if SASL + /* shutdown SASL */ + if (bitset(MCIF_AUTHACT, mci->mci_flags)) + { + sasl_dispose(&mci->mci_conn); + mci->mci_flags &= ~MCIF_AUTHACT; + } +#endif /* SASL */ + + + /* close output to mailer */ + if (mci->mci_out != NULL) + (void) fclose(mci->mci_out); + + /* copy any remaining input to transcript */ + if (mci->mci_in != NULL && e->e_xfp != NULL) + { + while (sfgets(buf, sizeof buf, mci->mci_in, + TimeOuts.to_quit, "Draining Input") != NULL) + /* while (fgets(buf, sizeof buf, mci->mci_in) != NULL) */ + (void) fputs(buf, e->e_xfp); + } + + /* now close the input */ + if (mci->mci_in != NULL) + (void) fclose(mci->mci_in); + mci->mci_in = mci->mci_out = NULL; + mci->mci_state = MCIS_CLOSED; + + errno = save_errno; + + /* in the IPC case there is nothing to wait for */ + if (mci->mci_pid == 0) + return EX_OK; + + /* put a timeout around the wait */ + if (mci->mci_mailer->m_wait > 0) + { + if (setjmp(EndWaitTimeout) == 0) + ev = setevent(mci->mci_mailer->m_wait, + endwaittimeout, 0); + else + { + syserr("endmailer %s: wait timeout (%d)", + mci->mci_mailer->m_name, + mci->mci_mailer->m_wait); + return EX_TEMPFAIL; + } + } + + /* wait for the mailer process, collect status */ + st = waitfor(mci->mci_pid); + save_errno = errno; + if (ev != NULL) + clrevent(ev); + errno = save_errno; + + if (st == -1) + { + syserr("endmailer %s: wait", mci->mci_mailer->m_name); + return EX_SOFTWARE; + } + + if (WIFEXITED(st)) + { + /* normal death -- return status */ + return (WEXITSTATUS(st)); + } + + /* it died a horrid death */ + syserr("451 4.3.0 mailer %s died with signal %d%s", + mci->mci_mailer->m_name, WTERMSIG(st), + WCOREDUMP(st) ? " (core dumped)" : + (WIFSTOPPED(st) ? " (stopped)" : "")); + + /* 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: +** status -- the status code from the mailer (high byte +** only; core dumps must have been taken care of +** already). +** dsn -- the DSN associated with the address, if any. +** 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(status, dsn, m, mci, ctladdr, xstart, e) + int status; + char *dsn; + register MAILER *m; + register MCI *mci; + ADDRESS *ctladdr; + time_t xstart; + ENVELOPE *e; +{ + register const char *statmsg; + extern char *SysExMsg[]; + register int i; + int errnum = errno; + int off = 4; + extern int N_SysEx; + char dsnbuf[ENHSCLEN]; + char buf[MAXLINE]; + + if (e == NULL) + syserr("giveresponse: null envelope"); + + /* + ** Compute status message from code. + */ + + i = status - EX__BASE; + if (status == 0) + { + statmsg = "250 2.0.0 Sent"; + if (e->e_statmsg != NULL) + { + (void) snprintf(buf, sizeof buf, "%s (%s)", + statmsg, + shortenstring(e->e_statmsg, 403)); + statmsg = buf; + } + } + else if (i < 0 || i >= N_SysEx) + { + (void) snprintf(buf, sizeof buf, + "554 5.3.0 unknown mailer error %d", + status); + status = EX_UNAVAILABLE; + statmsg = buf; + } + else if (status == EX_TEMPFAIL) + { + char *bp = buf; + + snprintf(bp, SPACELEFT(buf, bp), "%s", SysExMsg[i] + 1); + bp += strlen(bp); +#if NAMED_BIND + if (h_errno == TRY_AGAIN) + statmsg = errstring(h_errno+E_DNSBASE); + else +#endif /* NAMED_BIND */ + { + if (errnum != 0) + statmsg = errstring(errnum); + else + { +#if SMTP + statmsg = SmtpError; +#else /* SMTP */ + statmsg = NULL; +#endif /* SMTP */ + } + } + if (statmsg != NULL && statmsg[0] != '\0') + { + switch (errnum) + { +#ifdef ENETDOWN + case ENETDOWN: /* Network is down */ +#endif /* ENETDOWN */ +#ifdef ENETUNREACH + case ENETUNREACH: /* Network is unreachable */ +#endif /* ENETUNREACH */ +#ifdef ENETRESET + case ENETRESET: /* Network dropped connection on reset */ +#endif /* ENETRESET */ +#ifdef ECONNABORTED + case ECONNABORTED: /* Software caused connection abort */ +#endif /* ECONNABORTED */ +#ifdef EHOSTDOWN + case EHOSTDOWN: /* Host is down */ +#endif /* EHOSTDOWN */ +#ifdef EHOSTUNREACH + case EHOSTUNREACH: /* No route to host */ +#endif /* EHOSTUNREACH */ + if (mci->mci_host != NULL) + { + snprintf(bp, SPACELEFT(buf, bp), + ": %s", mci->mci_host); + bp += strlen(bp); + } + break; + } + snprintf(bp, SPACELEFT(buf, bp), ": %s", statmsg); + } + statmsg = buf; + } +#if NAMED_BIND + else if (status == EX_NOHOST && h_errno != 0) + { + statmsg = errstring(h_errno + E_DNSBASE); + (void) snprintf(buf, sizeof buf, "%s (%s)", + SysExMsg[i] + 1, statmsg); + statmsg = buf; + } +#endif /* NAMED_BIND */ + else + { + statmsg = SysExMsg[i]; + if (*statmsg++ == ':' && errnum != 0) + { + (void) snprintf(buf, sizeof buf, "%s: %s", + statmsg, errstring(errnum)); + statmsg = buf; + } + } + + /* + ** Print the message as appropriate + */ + + if (status == EX_OK || status == EX_TEMPFAIL) + { + extern char MsgBuf[]; + + if ((off = isenhsc(statmsg + 4, ' ')) > 0) + { + if (dsn == NULL) + { + snprintf(dsnbuf, sizeof dsnbuf, + "%.*s", off, statmsg + 4); + dsn = dsnbuf; + } + off += 5; + } + else + { + off = 4; + } + message("%s", statmsg + off); + if (status == EX_TEMPFAIL && e->e_xfp != NULL) + fprintf(e->e_xfp, "%s\n", &MsgBuf[4]); + } + else + { + char mbuf[ENHSCLEN + 4]; + + Errors++; + if ((off = isenhsc(statmsg + 4, ' ')) > 0 && + off < sizeof mbuf - 4) + { + if (dsn == NULL) + { + snprintf(dsnbuf, sizeof dsnbuf, + "%.*s", off, statmsg + 4); + dsn = dsnbuf; + } + off += 5; + (void) strlcpy(mbuf, statmsg, off); + (void) strlcat(mbuf, " %s", sizeof mbuf); + } + else + { + dsnbuf[0] = '\0'; + (void) snprintf(mbuf, sizeof mbuf, "%.3s %%s", statmsg); + off = 4; + } + usrerr(mbuf, &statmsg[off]); + } + + /* + ** Final cleanup. + ** Log a record of the transaction. Compute the new + ** ExitStat -- if we already had an error, stick with + ** that. + */ + + if (OpMode != MD_VERIFY && !bitset(EF_VRFYONLY, e->e_flags) && + LogLevel > ((status == EX_TEMPFAIL) ? 8 : (status == EX_OK) ? 7 : 6)) + logdelivery(m, mci, dsn, statmsg + off, ctladdr, xstart, e); + + if (tTd(11, 2)) + dprintf("giveresponse: status=%d, dsn=%s, e->e_message=%s\n", + status, + dsn == NULL ? "" : dsn, + e->e_message == NULL ? "" : e->e_message); + + if (status != EX_TEMPFAIL) + setstat(status); + if (status != EX_OK && (status != EX_TEMPFAIL || e->e_message == NULL)) + { + if (e->e_message != NULL) + free(e->e_message); + e->e_message = newstr(statmsg + off); + } + errno = 0; +#if NAMED_BIND + h_errno = 0; +#endif /* NAMED_BIND */ +} + /* +** 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 occurring when no connection is active. +** dsn -- the DSN attached to the status. +** status -- 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 +*/ + +void +logdelivery(m, mci, dsn, status, ctladdr, xstart, e) + MAILER *m; + register MCI *mci; + char *dsn; + const char *status; + ADDRESS *ctladdr; + time_t xstart; + register ENVELOPE *e; +{ + register char *bp; + register char *p; + int l; + char buf[1024]; + +#if (SYSLOG_BUFSIZE) >= 256 + /* ctladdr: max 106 bytes */ + bp = buf; + if (ctladdr != NULL) + { + snprintf(bp, SPACELEFT(buf, bp), ", ctladdr=%s", + shortenstring(ctladdr->q_paddr, 83)); + bp += strlen(bp); + if (bitset(QGOODUID, ctladdr->q_flags)) + { + (void) snprintf(bp, SPACELEFT(buf, bp), " (%d/%d)", + (int) ctladdr->q_uid, + (int) ctladdr->q_gid); + bp += strlen(bp); + } + } + + /* delay & xdelay: max 41 bytes */ + snprintf(bp, SPACELEFT(buf, bp), ", delay=%s", + pintvl(curtime() - e->e_ctime, TRUE)); + bp += strlen(bp); + + if (xstart != (time_t) 0) + { + snprintf(bp, SPACELEFT(buf, 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(buf, bp), ", mailer=%s", m->m_name); + bp += strlen(bp); + } + + /* pri: changes with each delivery attempt */ + snprintf(bp, SPACELEFT(buf, bp), ", pri=%ld", e->e_msgpriority); + bp += strlen(bp); + + /* relay: max 66 bytes for IPv4 addresses */ + if (mci != NULL && mci->mci_host != NULL) + { +# if DAEMON + extern SOCKADDR CurHostAddr; +# endif /* DAEMON */ + + snprintf(bp, SPACELEFT(buf, bp), ", relay=%s", + shortenstring(mci->mci_host, 40)); + bp += strlen(bp); + +# if DAEMON + if (CurHostAddr.sa.sa_family != 0) + { + snprintf(bp, SPACELEFT(buf, bp), " [%s]", + anynet_ntoa(&CurHostAddr)); + } +# endif /* DAEMON */ + } + else if (strcmp(status, "queued") != 0) + { + p = macvalue('h', e); + if (p != NULL && p[0] != '\0') + { + snprintf(bp, SPACELEFT(buf, bp), ", relay=%s", + shortenstring(p, 40)); + } + } + bp += strlen(bp); + + /* dsn */ + if (dsn != NULL && *dsn != '\0') + { + snprintf(bp, SPACELEFT(buf, bp), ", dsn=%s", + shortenstring(dsn, ENHSCLEN)); + bp += strlen(bp); + } + +# define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4) +# if (STATLEN) < 63 +# undef STATLEN +# define STATLEN 63 +# endif /* (STATLEN) < 63 */ +# if (STATLEN) > 203 +# undef STATLEN +# define STATLEN 203 +# endif /* (STATLEN) > 203 */ + + /* stat: max 210 bytes */ + if ((bp - buf) > (sizeof buf - ((STATLEN) + 20))) + { + /* desperation move -- truncate data */ + bp = buf + sizeof buf - ((STATLEN) + 17); + (void) strlcpy(bp, "...", SPACELEFT(buf, bp)); + bp += 3; + } + + (void) strlcpy(bp, ", stat=", SPACELEFT(buf, bp)); + bp += strlen(bp); + + (void) strlcpy(bp, shortenstring(status, STATLEN), SPACELEFT(buf, bp)); + + /* 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; + sm_syslog(LOG_INFO, e->e_id, + "to=%.*s [more]%s", + ++q - p, p, buf); + p = q; + } + sm_syslog(LOG_INFO, e->e_id, "to=%s%s", p, buf); + +#else /* (SYSLOG_BUFSIZE) >= 256 */ + + l = SYSLOG_BUFSIZE - 85; + p = e->e_to; + while (strlen(p) >= (SIZE_T) l) + { + register char *q = strchr(p + l, ','); + + if (q == NULL) + break; + sm_syslog(LOG_INFO, e->e_id, + "to=%.*s [more]", + ++q - p, p); + p = q; + } + sm_syslog(LOG_INFO, e->e_id, "to=%s", p); + + if (ctladdr != NULL) + { + bp = buf; + snprintf(bp, SPACELEFT(buf, bp), "ctladdr=%s", + shortenstring(ctladdr->q_paddr, 83)); + bp += strlen(bp); + if (bitset(QGOODUID, ctladdr->q_flags)) + { + (void) snprintf(bp, SPACELEFT(buf, bp), " (%d/%d)", + ctladdr->q_uid, ctladdr->q_gid); + bp += strlen(bp); + } + sm_syslog(LOG_INFO, e->e_id, "%s", buf); + } + bp = buf; + snprintf(bp, SPACELEFT(buf, bp), "delay=%s", + pintvl(curtime() - e->e_ctime, TRUE)); + bp += strlen(bp); + if (xstart != (time_t) 0) + { + snprintf(bp, SPACELEFT(buf, bp), ", xdelay=%s", + pintvl(curtime() - xstart, TRUE)); + bp += strlen(bp); + } + + if (m != NULL) + { + snprintf(bp, SPACELEFT(buf, bp), ", mailer=%s", m->m_name); + bp += strlen(bp); + } + sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf); + + buf[0] = '\0'; + bp = buf; + if (mci != NULL && mci->mci_host != NULL) + { +# if DAEMON + extern SOCKADDR CurHostAddr; +# endif /* DAEMON */ + + snprintf(bp, SPACELEFT(buf, bp), "relay=%.100s", mci->mci_host); + bp += strlen(bp); + +# if DAEMON + if (CurHostAddr.sa.sa_family != 0) + snprintf(bp, SPACELEFT(buf, bp), " [%.100s]", + anynet_ntoa(&CurHostAddr)); +# endif /* DAEMON */ + } + else if (strcmp(status, "queued") != 0) + { + p = macvalue('h', e); + if (p != NULL && p[0] != '\0') + snprintf(buf, sizeof buf, "relay=%.100s", p); + } + if (buf[0] != '\0') + sm_syslog(LOG_INFO, e->e_id, "%.1000s", buf); + + sm_syslog(LOG_INFO, e->e_id, "stat=%s", shortenstring(status, 63)); +#endif /* (SYSLOG_BUFSIZE) >= 256 */ +} + /* +** 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 " 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]; + char xbuf[MAXLINE]; + + if (bitnset(M_NHDR, mci->mci_mailer->m_flags)) + return; + + mci->mci_flags |= MCIF_INHEADER; + + if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags)) + { + char *bang; + + expand("\201g", buf, sizeof buf, e); + bang = strchr(buf, '!'); + if (bang == NULL) + { + char *at; + char hname[MAXNAME]; + + /* + ** If we can construct a UUCP path, do so + */ + + at = strrchr(buf, '@'); + if (at == NULL) + { + expand("\201k", hname, sizeof hname, e); + at = hname; + } + else + *at++ = '\0'; + (void) snprintf(xbuf, sizeof xbuf, + "From %.800s \201d remote from %.100s\n", + buf, at); + } + else + { + *bang++ = '\0'; + (void) snprintf(xbuf, sizeof xbuf, + "From %.800s \201d remote from %.100s\n", + bang, buf); + template = xbuf; + } + } + expand(template, buf, sizeof buf, e); + putxline(buf, strlen(buf), mci, PXLF_HEADER); +} + /* +** 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; +{ + bool dead = FALSE; + char buf[MAXLINE]; + char *boundaries[MAXMIMENESTING + 1]; + + /* + ** 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; + } + } + + /* paranoia: the df file should always be in a rewound state */ + (void) bfrewind(e->e_dfp); + +#if MIME8TO7 + if (bitset(MCIF_CVT8TO7, mci->mci_flags)) + { + /* + ** 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) + { + snprintf(buf, sizeof buf, + "Content-Type: text/plain; charset=%s", + defcharset(e)); + putline(buf, mci); + } + + /* now do the hard work */ + boundaries[0] = NULL; + mci->mci_flags |= MCIF_INHEADER; + (void) mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER); + } +# if MIME7TO8 + else if (bitset(MCIF_CVT7TO8, mci->mci_flags)) + { + (void) mime7to8(mci, e->e_header, e); + } +# endif /* MIME7TO8 */ + else if (MaxMimeHeaderLength > 0 || MaxMimeFieldLength > 0) + { + bool oldsuprerrs = SuprErrs; + + /* Use mime8to7 to check multipart for MIME header overflows */ + boundaries[0] = NULL; + mci->mci_flags |= MCIF_INHEADER; + + /* + ** If EF_DONT_MIME is set, we have a broken MIME message + ** and don't want to generate a new bounce message whose + ** body propagates the broken MIME. We can't just not call + ** mime8to7() as is done above since we need the security + ** checks. The best we can do is suppress the errors. + */ + + if (bitset(EF_DONT_MIME, e->e_flags)) + SuprErrs = TRUE; + + (void) mime8to7(mci, e->e_header, e, boundaries, + M87F_OUTER|M87F_NO8TO7); + + /* restore SuprErrs */ + SuprErrs = oldsuprerrs; + } + else +#endif /* MIME8TO7 */ + { + int ostate; + register char *bp; + register char *pbp; + register int c; + register char *xp; + int padc; + char *buflim; + int pos = 0; + char peekbuf[12]; + + 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)) + { + 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 _FFR_NONULLS + if (c == '\0' && + bitnset(M_NONULLS, mci->mci_mailer->m_flags)) + break; +#endif /* _FFR_NONULLS */ + 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 >>> ", + (int) getpid()); + if (padc != EOF) + (void) putc(padc, + TrafficLogFile); + for (xp = buf; xp < bp; xp++) + (void) putc(*xp, TrafficLogFile); + if (c == '\n') + (void) fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + if (padc != EOF) + { + if (putc(padc, mci->mci_out) == EOF) + continue; + pos++; + } + for (xp = buf; xp < bp; xp++) + { + if (putc(*xp, mci->mci_out) == EOF) + { + dead = TRUE; + break; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } + if (dead) + continue; + if (c == '\n') + { + if (fputs(mci->mci_mailer->m_eol, + mci->mci_out) == EOF) + break; + pos = 0; + } + else + { + pos += bp - buf; + if (c != '\r') + *pbp++ = c; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + 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 */ + if (fputs(mci->mci_mailer->m_eol, + mci->mci_out) == EOF) + continue; + + /* record progress for DATA timeout */ + DataProgress = TRUE; + + if (TrafficLogFile != NULL) + { + (void) fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + ostate = OS_HEAD; + continue; + } + + /* had a naked carriage return */ + *pbp++ = c; + c = '\r'; + ostate = OS_INLINE; + goto putch; + + case OS_INLINE: + if (c == '\r') + { + ostate = OS_CR; + continue; + } +#if _FFR_NONULLS + if (c == '\0' && + bitnset(M_NONULLS, mci->mci_mailer->m_flags)) + break; +#endif /* _FFR_NONULLS */ +putch: + if (mci->mci_mailer->m_linelimit > 0 && + pos >= mci->mci_mailer->m_linelimit - 1 && + c != '\n') + { + int d; + + /* check next character for EOL */ + if (pbp > peekbuf) + d = *(pbp - 1); + else if ((d = getc(e->e_dfp)) != EOF) + *pbp++ = d; + + if (d == '\n' || d == EOF) + { + if (TrafficLogFile != NULL) + (void) putc(c, TrafficLogFile); + if (putc(c, mci->mci_out) == EOF) + continue; + pos++; + continue; + } + + if (putc('!', mci->mci_out) == EOF || + fputs(mci->mci_mailer->m_eol, + mci->mci_out) == EOF) + continue; + + /* record progress for DATA timeout */ + DataProgress = TRUE; + + if (TrafficLogFile != NULL) + { + fprintf(TrafficLogFile, "!%s", + mci->mci_mailer->m_eol); + } + ostate = OS_HEAD; + *pbp++ = c; + continue; + } + if (c == '\n') + { + if (TrafficLogFile != NULL) + (void) fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + if (fputs(mci->mci_mailer->m_eol, + mci->mci_out) == EOF) + continue; + pos = 0; + ostate = OS_HEAD; + } + else + { + if (TrafficLogFile != NULL) + (void) putc(c, TrafficLogFile); + if (putc(c, mci->mci_out) == EOF) + continue; + pos++; + ostate = OS_INLINE; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + break; + } + } + + /* make sure we are at the beginning of a line */ + if (bp > buf) + { + if (TrafficLogFile != NULL) + { + for (xp = buf; xp < bp; xp++) + (void) putc(*xp, TrafficLogFile); + } + for (xp = buf; xp < bp; xp++) + { + if (putc(*xp, mci->mci_out) == EOF) + { + dead = TRUE; + break; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } + pos += bp - buf; + } + if (!dead && pos > 0) + { + if (TrafficLogFile != NULL) + (void) fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + (void) fputs(mci->mci_mailer->m_eol, mci->mci_out); + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } + } + + if (ferror(e->e_dfp)) + { + syserr("putbody: %s/df%s: read error", + qid_printqueue(e->e_queuedir), e->e_id); + ExitStat = EX_IOERR; + } + +endofmessage: + /* + ** Since mailfile() uses e_dfp in a child process, + ** the file offset in the stdio library for the + ** parent process will not agree with the in-kernel + ** file offset since the file descriptor is shared + ** between the processes. Therefore, it is vital + ** that the file always be rewound. This forces the + ** kernel offset (lseek) and stdio library (ftell) + ** offset to match. + */ + + if (e->e_dfp != NULL) + (void) bfrewind(e->e_dfp); + + /* 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. +** mailer -- mailer definition for recipient -- if NULL, +** use FileMailer. +** 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. +*/ + +static jmp_buf CtxMailfileTimeout; + +int +mailfile(filename, mailer, ctladdr, sfflags, e) + char *volatile filename; + MAILER *volatile mailer; + ADDRESS *ctladdr; + volatile long sfflags; + register ENVELOPE *e; +{ + register FILE *f; + register pid_t pid = -1; + volatile int mode; + int len; + off_t curoff; + bool suidwarn = geteuid() == 0; + char *p; + char *volatile realfile; + EVENT *ev; + char buf[MAXLINE + 1]; + char targetfile[MAXPATHLEN + 1]; + + if (tTd(11, 1)) + { + dprintf("mailfile %s\n ctladdr=", filename); + printaddr(ctladdr, FALSE); + } + + if (mailer == NULL) + mailer = FileMailer; + + if (e->e_xfp != NULL) + (void) fflush(e->e_xfp); + + /* + ** Special case /dev/null. This allows us to restrict file + ** delivery to regular files only. + */ + + if (strcmp(filename, "/dev/null") == 0) + return EX_OK; + + /* check for 8-bit available */ + if (bitset(EF_HAS8BIT, e->e_flags) && + bitnset(M_7BITS, mailer->m_flags) && + (bitset(EF_DONT_MIME, e->e_flags) || + !(bitset(MM_MIME8BIT, MimeMode) || + (bitset(EF_IS_MIME, e->e_flags) && + bitset(MM_CVTMIME, MimeMode))))) + { + e->e_status = "5.6.3"; + usrerrenh(e->e_status, + "554 Cannot send 8-bit data to 7-bit destination"); + return EX_DATAERR; + } + + /* Find the actual file */ + if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0') + { + len = strlen(SafeFileEnv); + + if (strncmp(SafeFileEnv, filename, len) == 0) + filename += len; + + if (len + strlen(filename) + 1 > MAXPATHLEN) + { + syserr("mailfile: filename too long (%s/%s)", + SafeFileEnv, filename); + return EX_CANTCREAT; + } + (void) strlcpy(targetfile, SafeFileEnv, sizeof targetfile); + realfile = targetfile + len; + if (targetfile[len - 1] != '/') + (void) strlcat(targetfile, "/", sizeof targetfile); + if (*filename == '/') + filename++; + (void) strlcat(targetfile, filename, sizeof targetfile); + } + else if (mailer->m_rootdir != NULL) + { + expand(mailer->m_rootdir, targetfile, sizeof targetfile, e); + len = strlen(targetfile); + + if (strncmp(targetfile, filename, len) == 0) + filename += len; + + if (len + strlen(filename) + 1 > MAXPATHLEN) + { + syserr("mailfile: filename too long (%s/%s)", + targetfile, filename); + return EX_CANTCREAT; + } + realfile = targetfile + len; + if (targetfile[len - 1] != '/') + (void) strlcat(targetfile, "/", sizeof targetfile); + if (*filename == '/') + (void) strlcat(targetfile, filename + 1, + sizeof targetfile); + else + (void) strlcat(targetfile, filename, sizeof targetfile); + } + else + { + if (strlen(filename) > MAXPATHLEN) + { + syserr("mailfile: filename too long (%s)", filename); + return EX_CANTCREAT; + } + (void) strlcpy(targetfile, filename, sizeof targetfile); + realfile = targetfile; + } + + /* + ** 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; + MCI mcibuf; + int err; + volatile 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; + + if (setjmp(CtxMailfileTimeout) != 0) + { + exit(EX_TEMPFAIL); + } + + if (TimeOuts.to_fileopen > 0) + ev = setevent(TimeOuts.to_fileopen, mailfiletimeout, 0); + else + ev = NULL; + + /* check file mode to see if setuid */ + if (stat(targetfile, &stb) < 0) + mode = FileMode; + else + mode = stb.st_mode; + + /* limit the errors to those actually caused in the child */ + errno = 0; + ExitStat = EX_OK; + + /* Allow alias expansions to use the S_IS{U,G}ID bits */ + if ((ctladdr != NULL && !bitset(QALIAS, ctladdr->q_flags)) || + bitset(SFF_RUNASREALUID, sfflags)) + { + /* ignore setuid and setgid bits */ + mode &= ~(S_ISGID|S_ISUID); + if (tTd(11, 20)) + dprintf("mailfile: ignoring setuid/setgid bits\n"); + } + + /* 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 (bitnset(M_SPECIFIC_UID, mailer->m_flags)) + { + RealUserName = NULL; + RealUid = mailer->m_uid; + } + else 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 (mailer != NULL && mailer->m_uid != 0) + { + RealUserName = DefUser; + RealUid = mailer->m_uid; + } + else + { + RealUserName = DefUser; + RealUid = DefUid; + } + + /* select a new group to run as */ + if (bitnset(M_SPECIFIC_UID, mailer->m_flags)) + RealGid = mailer->m_gid; + else if (bitset(S_ISGID, mode)) + RealGid = stb.st_gid; + else if (ctladdr != NULL && ctladdr->q_uid != 0) + RealGid = ctladdr->q_gid; + else if (ctladdr != NULL && + ctladdr->q_uid == DefUid && + ctladdr->q_gid == 0) + RealGid = DefGid; + else if (mailer != NULL && mailer->m_gid != 0) + RealGid = mailer->m_gid; + else + RealGid = DefGid; + } + + /* last ditch */ + if (!bitset(SFF_ROOTOK, sfflags)) + { + if (RealUid == 0) + RealUid = DefUid; + if (RealGid == 0) + RealGid = DefGid; + } + + /* set group id list (needs /etc/group access) */ + if (RealUserName != NULL && !DontInitGroups) + { + if (initgroups(RealUserName, RealGid) == -1 && suidwarn) + syserr("mailfile: initgroups(%s, %d) failed", + RealUserName, RealGid); + } + else + { + GIDSET_T gidset[1]; + + gidset[0] = RealGid; + if (setgroups(1, gidset) == -1 && suidwarn) + syserr("mailfile: setgroups() failed"); + } + + /* + ** If you have a safe environment, go into it. + */ + + if (realfile != targetfile) + { + *realfile = '\0'; + if (tTd(11, 20)) + dprintf("mailfile: chroot %s\n", targetfile); + if (chroot(targetfile) < 0) + { + syserr("mailfile: Cannot chroot(%s)", + targetfile); + exit(EX_CANTCREAT); + } + *realfile = '/'; + } + + if (tTd(11, 40)) + dprintf("mailfile: deliver to %s\n", realfile); + + if (chdir("/") < 0) + syserr("mailfile: cannot chdir(/)"); + + /* now reset the group and user ids */ + endpwent(); + if (setgid(RealGid) < 0 && suidwarn) + syserr("mailfile: setgid(%ld) failed", (long) RealGid); + vendor_set_uid(RealUid); + if (setuid(RealUid) < 0 && suidwarn) + syserr("mailfile: setuid(%ld) failed", (long) RealUid); + + if (tTd(11, 2)) + dprintf("mailfile: running as r/euid=%d/%d, r/egid=%d/%d\n", + (int) getuid(), (int) geteuid(), + (int) getgid(), (int) getegid()); + + + /* move into some "safe" directory */ + if (mailer->m_execdir != NULL) + { + char *q; + + for (p = mailer->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)) + dprintf("mailfile: trydir %s\n", buf); + if (buf[0] != '\0' && chdir(buf) >= 0) + break; + } + } + + /* + ** Recheck the file after we have assumed the ID of the + ** delivery user to make sure we can deliver to it as + ** that user. This is necessary if sendmail is running + ** as root and the file is on an NFS mount which treats + ** root as nobody. + */ + +#if HASLSTAT + if (bitnset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail)) + err = stat(realfile, &stb); + else + err = lstat(realfile, &stb); +#else /* HASLSTAT */ + err = stat(realfile, &stb); +#endif /* HASLSTAT */ + + if (err < 0) + { + stb.st_mode = ST_MODE_NOFILE; + mode = FileMode; + oflags |= O_CREAT|O_EXCL; + } + else if (bitset(S_IXUSR|S_IXGRP|S_IXOTH, mode) || + (!bitnset(DBS_FILEDELIVERYTOHARDLINK, + DontBlameSendmail) && + stb.st_nlink != 1) || + (realfile != targetfile && !S_ISREG(mode))) + exit(EX_CANTCREAT); + else + mode = stb.st_mode; + + if (!bitnset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail)) + sfflags |= SFF_NOSLINK; + if (!bitnset(DBS_FILEDELIVERYTOHARDLINK, DontBlameSendmail)) + sfflags |= SFF_NOHLINK; + sfflags &= ~SFF_OPENASROOT; + f = safefopen(realfile, oflags, mode, sfflags); + if (f == NULL) + { + if (transienterror(errno)) + { + usrerr("454 4.3.0 cannot open %s: %s", + shortenstring(realfile, MAXSHORTSTR), + errstring(errno)); + exit(EX_TEMPFAIL); + } + else + { + usrerr("554 5.3.0 cannot open %s: %s", + shortenstring(realfile, MAXSHORTSTR), + errstring(errno)); + exit(EX_CANTCREAT); + } + } + if (filechanged(realfile, fileno(f), &stb)) + { + syserr("554 5.3.0 file changed after open"); + exit(EX_CANTCREAT); + } + if (fstat(fileno(f), &stb) < 0) + { + syserr("554 5.3.0 cannot fstat %s", errstring(errno)); + exit(EX_CANTCREAT); + } + + curoff = stb.st_size; + + if (ev != NULL) + clrevent(ev); + + memset(&mcibuf, '\0', sizeof mcibuf); + mcibuf.mci_mailer = mailer; + mcibuf.mci_out = f; + if (bitnset(M_7BITS, mailer->m_flags)) + mcibuf.mci_flags |= MCIF_7BIT; + + /* clear out per-message flags from connection structure */ + mcibuf.mci_flags &= ~(MCIF_CVT7TO8|MCIF_CVT8TO7); + + if (bitset(EF_HAS8BIT, e->e_flags) && + !bitset(EF_DONT_MIME, e->e_flags) && + bitnset(M_7BITS, mailer->m_flags)) + mcibuf.mci_flags |= MCIF_CVT8TO7; + +#if MIME7TO8 + if (bitnset(M_MAKE8BIT, mailer->m_flags) && + !bitset(MCIF_7BIT, mcibuf.mci_flags) && + (p = hvalue("Content-Transfer-Encoding", e->e_header)) != NULL && + (strcasecmp(p, "quoted-printable") == 0 || + strcasecmp(p, "base64") == 0) && + (p = hvalue("Content-Type", e->e_header)) != NULL) + { + /* may want to convert 7 -> 8 */ + /* XXX should really parse it here -- and use a class XXX */ + if (strncasecmp(p, "text/plain", 10) == 0 && + (p[10] == '\0' || p[10] == ' ' || p[10] == ';')) + mcibuf.mci_flags |= MCIF_CVT7TO8; + } +#endif /* MIME7TO8 */ + + putfromline(&mcibuf, e); + (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER); + (*e->e_putbody)(&mcibuf, e, NULL); + putline("\n", &mcibuf); + if (fflush(f) < 0 || + (SuperSafe && fsync(fileno(f)) < 0) || + ferror(f)) + { + setstat(EX_IOERR); +#if !NOFTRUNCATE + (void) ftruncate(fileno(f), curoff); +#endif /* !NOFTRUNCATE */ + } + + /* reset ISUID & ISGID bits for paranoid systems */ +#if HASFCHMOD + (void) fchmod(fileno(f), (MODE_T) mode); +#else /* HASFCHMOD */ + (void) chmod(filename, (MODE_T) mode); +#endif /* HASFCHMOD */ + if (fclose(f) < 0) + setstat(EX_IOERR); + (void) fflush(stdout); + (void) setuid(RealUid); + exit(ExitStat); + /* NOTREACHED */ + } + else + { + /* parent -- wait for exit status */ + int st; + + st = waitfor(pid); + if (st == -1) + { + syserr("mailfile: %s: wait", mailer->m_name); + return EX_SOFTWARE; + } + if (WIFEXITED(st)) + return (WEXITSTATUS(st)); + else + { + syserr("mailfile: %s: child died on signal %d", + mailer->m_name, st); + return EX_UNAVAILABLE; + } + /* NOTREACHED */ + } + return EX_UNAVAILABLE; /* avoid compiler warning on IRIX */ +} + +static void +mailfiletimeout() +{ + longjmp(CtxMailfileTimeout, 1); +} + /* +** 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. +** +** Returns: +** The signature for this host. +** +** Side Effects: +** Can tweak the symbol table. +*/ +#define MAXHOSTSIGNATURE 8192 /* max len of hostsignature */ + +static char * +hostsignature(m, host) + register MAILER *m; + char *host; +{ + register char *p; + register STAB *s; +#if NAMED_BIND + char sep = ':'; + char prevsep = ':'; + int i; + int len; + int nmx; + int hl; + char *hp; + char *endp; + int oldoptions = _res.options; + char *mxhosts[MAXMXHOSTS + 1]; + u_short mxprefs[MAXMXHOSTS + 1]; +#endif /* NAMED_BIND */ + + if (tTd(17, 3)) + dprintf("hostsignature(%s)\n", host); + + /* + ** If local delivery, just return a constant. + */ + + if (bitnset(M_LOCALMAILER, m->m_flags)) + return "localhost"; + + /* + ** 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; + } +#if NETUNIX + else if (m->m_argv[0] != NULL && + strcmp(m->m_argv[0], "FILE") == 0) + { + /* rendezvous in the file system, no MX records */ + return host; + } +#endif /* NETUNIX */ + + /* + ** Look it up in the symbol table. + */ + + s = stab(host, ST_HOSTSIG, ST_ENTER); + if (s->s_hostsig != NULL) + { + if (tTd(17, 3)) + dprintf("hostsignature(): stab(%s) found %s\n", host, + s->s_hostsig); + 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) + { +#if NETINET6 + if (*hp == '[') + { + endp = strchr(hp + 1, ']'); + if (endp != NULL) + endp = strpbrk(endp + 1, ":,"); + } + else + endp = strpbrk(hp, ":,"); +#else /* NETINET6 */ + endp = strpbrk(hp, ":,"); +#endif /* NETINET6 */ + if (endp != NULL) + { + sep = *endp; + *endp = '\0'; + } + + if (bitnset(M_NOMX, m->m_flags)) + { + /* skip MX lookups */ + nmx = 1; + mxhosts[0] = hp; + } + else + { + auto int rcode; + + nmx = getmxrr(hp, mxhosts, mxprefs, TRUE, &rcode); + if (nmx <= 0) + { + register MCI *mci; + + /* update the connection info for this host */ + mci = mci_get(hp, m); + mci->mci_errno = errno; + mci->mci_herrno = h_errno; + mci->mci_lastuse = curtime(); + if (rcode == EX_NOHOST) + mci_setstat(mci, rcode, "5.1.2", + "550 Host unknown"); + else + mci_setstat(mci, rcode, NULL, NULL); + + /* use the original host name as signature */ + nmx = 1; + mxhosts[0] = hp; + } + if (tTd(17, 3)) + dprintf("hostsignature(): getmxrr() returned %d, mxhosts[0]=%s\n", + nmx, mxhosts[0]); + } + + len = 0; + for (i = 0; i < nmx; i++) + len += strlen(mxhosts[i]) + 1; + if (s->s_hostsig != NULL) + len += strlen(s->s_hostsig) + 1; + if (len >= MAXHOSTSIGNATURE) + { + sm_syslog(LOG_WARNING, NOQID, "hostsignature for host '%s' exceeds maxlen (%d): %d", + host, MAXHOSTSIGNATURE, len); + len = MAXHOSTSIGNATURE; + } + p = xalloc(len); + if (s->s_hostsig != NULL) + { + (void) strlcpy(p, s->s_hostsig, len); + free(s->s_hostsig); + s->s_hostsig = p; + hl = strlen(p); + p += hl; + *p++ = prevsep; + len -= hl + 1; + } + else + s->s_hostsig = p; + for (i = 0; i < nmx; i++) + { + hl = strlen(mxhosts[i]); + if (len - 1 < hl || len <= 1) + { + /* force to drop out of outer loop */ + len = -1; + break; + } + if (i != 0) + { + if (mxprefs[i] == mxprefs[i - 1]) + *p++ = ','; + else + *p++ = ':'; + len--; + } + (void) strlcpy(p, mxhosts[i], len); + p += hl; + len -= hl; + } + + /* + ** break out of loop if len exceeded MAXHOSTSIGNATURE + ** because we won't have more space for further hosts + ** anyway (separated by : in the .cf file). + */ + + if (len < 0) + break; + if (endp != NULL) + *endp++ = sep; + prevsep = sep; + } + makelower(s->s_hostsig); + if (ConfigLevel < 2) + _res.options = oldoptions; +#else /* NAMED_BIND */ + /* not using BIND -- the signature is just the host name */ + s->s_hostsig = host; +#endif /* NAMED_BIND */ + if (tTd(17, 1)) + dprintf("hostsignature(%s) = %s\n", host, s->s_hostsig); + return s->s_hostsig; +} + /* +** PARSE_HOSTSIGNATURE -- parse the "signature" and return MX host array. +** +** 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 which must be randomized for equal +** MX preference values. +** +** Parameters: +** sig -- the host signature. +** mxhosts -- array to populate. +** +** Returns: +** The number of hosts inserted into mxhosts array. +** +** Side Effects: +** Randomizes equal MX preference hosts in mxhosts. +*/ + +static int +parse_hostsignature(sig, mxhosts, mailer) + char *sig; + char **mxhosts; + MAILER *mailer; +{ + int nmx = 0; + int curpref = 0; + int i, j; + char *hp, *endp; + u_short prefer[MAXMXHOSTS]; + long rndm[MAXMXHOSTS]; + + for (hp = sig; hp != NULL; hp = endp) + { + char sep = ':'; + +#if NETINET6 + if (*hp == '[') + { + endp = strchr(hp + 1, ']'); + if (endp != NULL) + endp = strpbrk(endp + 1, ":,"); + } + else + endp = strpbrk(hp, ":,"); +#else /* NETINET6 */ + endp = strpbrk(hp, ":,"); +#endif /* NETINET6 */ + if (endp != NULL) + { + sep = *endp; + *endp = '\0'; + } + + mxhosts[nmx] = hp; + prefer[nmx] = curpref; + if (mci_match(hp, mailer)) + rndm[nmx] = 0; + else + rndm[nmx] = get_random(); + + if (endp != NULL) + { + /* + ** Since we don't have the original MX prefs, + ** make our own. If the separator is a ':', that + ** means the preference for the next host will be + ** higher than this one, so simply increment curpref. + */ + + if (sep == ':') + curpref++; + + *endp++ = sep; + } + if (++nmx >= MAXMXHOSTS) + break; + } + + /* sort the records using the random factor for equal preferences */ + for (i = 0; i < nmx; i++) + { + for (j = i + 1; j < nmx; j++) + { + /* + ** List is already sorted by MX preference, only + ** need to look for equal preference MX records + */ + + if (prefer[i] < prefer[j]) + break; + + if (prefer[i] > prefer[j] || + (prefer[i] == prefer[j] && rndm[i] > rndm[j])) + { + register u_short tempp; + register long tempr; + register char *temp1; + + tempp = prefer[i]; + prefer[i] = prefer[j]; + prefer[j] = tempp; + temp1 = mxhosts[i]; + mxhosts[i] = mxhosts[j]; + mxhosts[j] = temp1; + tempr = rndm[i]; + rndm[i] = rndm[j]; + rndm[j] = tempr; + } + } + } + return nmx; +} + +#if SMTP +#endif /* SMTP */ diff --git a/gnu/usr.sbin/sendmail/sendmail/domain.c b/gnu/usr.sbin/sendmail/sendmail/domain.c new file mode 100644 index 00000000000..a1b065d4224 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/domain.c @@ -0,0 +1,1009 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# if NAMED_BIND +static char id[] = "@(#)$Sendmail: domain.c,v 8.114 2000/02/01 05:49:56 gshapiro Exp $ (with name server)"; +# else /* NAMED_BIND */ +static char id[] = "@(#)$Sendmail: domain.c,v 8.114 2000/02/01 05:49:56 gshapiro Exp $ (without name server)"; +# endif /* NAMED_BIND */ +#endif /* ! lint */ + +#if NAMED_BIND + +# include + +/* +** The standard udp packet size PACKETSZ (512) is not sufficient for some +** nameserver answers containing very many resource records. The resolver +** may switch to tcp and retry if it detects udp packet overflow. +** Also note that the resolver routines res_query and res_search return +** the size of the *un*truncated answer in case the supplied answer buffer +** it not big enough to accommodate the entire answer. +*/ + +# ifndef MAXPACKET +# define MAXPACKET 8192 /* max packet size used internally by BIND */ +# endif /* ! MAXPACKET */ + +typedef union +{ + HEADER qb1; + u_char qb2[MAXPACKET]; +} querybuf; + +# ifndef MXHOSTBUFSIZE +# define MXHOSTBUFSIZE (128 * MAXMXHOSTS) +# endif /* ! MXHOSTBUFSIZE */ + +static char MXHostBuf[MXHOSTBUFSIZE]; + +# ifndef MAXDNSRCH +# define MAXDNSRCH 6 /* number of possible domains to search */ +# endif /* ! MAXDNSRCH */ + +# ifndef RES_DNSRCH_VARIABLE +# define RES_DNSRCH_VARIABLE _res.dnsrch +# endif /* ! RES_DNSRCH_VARIABLE */ + +# ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +# endif /* ! MAX */ + +# ifndef NO_DATA +# define NO_DATA NO_ADDRESS +# endif /* ! NO_DATA */ + +# ifndef HFIXEDSZ +# define HFIXEDSZ 12 /* sizeof(HEADER) */ +# endif /* ! HFIXEDSZ */ + +# define MAXCNAMEDEPTH 10 /* maximum depth of CNAME recursion */ + +# if defined(__RES) && (__RES >= 19940415) +# define RES_UNC_T char * +# else /* defined(__RES) && (__RES >= 19940415) */ +# define RES_UNC_T u_char * +# endif /* defined(__RES) && (__RES >= 19940415) */ + +static char *gethostalias __P((char *)); +static int mxrand __P((char *)); + + /* +** 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. +** mxprefs -- a pointer to a return buffer of MX preferences. +** If NULL, don't try to populate. +** 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, mxprefs, droplocalhost, rcode) + char *host; + char **mxhosts; + u_short *mxprefs; + 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; + bool trycanon = FALSE; + u_short *prefs; + int (*resfunc)(); + u_short prefer[MAXMXHOSTS]; + int weight[MAXMXHOSTS]; + extern int res_query(), res_search(); + + if (tTd(8, 2)) + dprintf("getmxrr(%s, droplocalhost=%d)\n", + host, droplocalhost); + + if (fallbackMX != NULL && droplocalhost && + wordinclass(fallbackMX, 'w')) + { + /* don't use fallback for this pass */ + fallbackMX = NULL; + } + + *rcode = EX_OK; + + if (mxprefs != NULL) + prefs = mxprefs; + else + prefs = prefer; + + + /* 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)) + dprintf("getmxrr: res_search(%s) failed (errno=%d, h_errno=%d)\n", + (host == NULL) ? "" : host, errno, h_errno); + switch (h_errno) + { + case NO_DATA: + trycanon = TRUE; + /* FALLTHROUGH */ + + 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 /* BROKEN_RES_SEARCH */ + /* host doesn't exist in DNS; might be in /etc/hosts */ + trycanon = TRUE; + *rcode = EX_NOHOST; + goto punt; + + case TRY_AGAIN: + case -1: + /* couldn't connect to the name server */ + if (fallbackMX != NULL) + { + /* name server is hosed -- push to fallback */ + if (nmx > 0) + prefs[nmx] = prefs[nmx - 1] + 1; + else + prefs[nmx] = 0; + 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; + } + + /* avoid problems after truncation in tcp packets */ + if (n > sizeof(answer)) + n = sizeof(answer); + + /* 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) + dprintf("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)) + dprintf("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); + prefs[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 (prefs[i] > prefs[j] || + (prefs[i] == prefs[j] && weight[i] > weight[j])) + { + register int temp; + register char *temp1; + + temp = prefs[i]; + prefs[i] = prefs[j]; + prefs[j] = temp; + temp1 = mxhosts[i]; + mxhosts[i] = mxhosts[j]; + mxhosts[j] = temp1; + temp = weight[i]; + weight[i] = weight[j]; + weight[j] = temp; + } + } + if (seenlocal && prefs[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]; + prefs[j] = prefs[j + 1]; + } + nmx--; + } + } + + if (nmx == 0) + { +punt: + if (seenlocal && + (!TryNullMXList || + (sm_gethostbyname(host, AF_INET) == NULL +# if NETINET6 + && sm_gethostbyname(host, AF_INET6) == NULL +# endif /* NETINET6 */ + ))) + { + /* + ** 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; + } + if (strlen(host) >= (SIZE_T) sizeof MXHostBuf) + { + *rcode = EX_CONFIG; + syserr("Host name %s too long", + shortenstring(host, MAXSHORTSTR)); + return -1; + } + snprintf(MXHostBuf, sizeof MXHostBuf, "%s", host); + mxhosts[0] = MXHostBuf; + prefs[0] = 0; + if (host[0] == '[') + { + register char *p; +# if NETINET6 + struct sockaddr_in6 tmp6; +# endif /* NETINET6 */ + + /* this may be an MX suppression-style address */ + p = strchr(MXHostBuf, ']'); + if (p != NULL) + { + *p = '\0'; + + if (inet_addr(&MXHostBuf[1]) != INADDR_NONE) + { + nmx++; + *p = ']'; + } +# if NETINET6 + else if (inet_pton(AF_INET6, &MXHostBuf[1], + &tmp6.sin6_addr) == 1) + { + nmx++; + *p = ']'; + } +# endif /* NETINET6 */ + 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) + { + if (nmx > 0) + prefs[nmx] = prefs[nmx - 1] + 1; + else + prefs[nmx] = 0; + 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. +*/ + +static 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)) + dprintf("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)) + dprintf(" = %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. +*/ + +/* ARGSUSED3 */ +char * +bestmx_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int nmx; + int saveopts = _res.options; + int i, len = 0; + char *p; + char *mxhosts[MAXMXHOSTS + 1]; + char buf[PSBUFSIZE / 2]; + + _res.options &= ~(RES_DNSRCH|RES_DEFNAMES); + nmx = getmxrr(name, mxhosts, NULL, FALSE, statp); + _res.options = saveopts; + if (nmx <= 0) + return NULL; + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + if ((map->map_coldelim == '\0') || (nmx == 1)) + return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); + + /* + ** We were given a -z flag (return all MXs) and there are multiple + ** ones. We need to build them all into a list. + */ + p = buf; + for (i = 0; i < nmx; i++) + { + int slen; + + if (strchr(mxhosts[i], map->map_coldelim) != NULL) + { + syserr("bestmx_map_lookup: MX host %.64s includes map delimiter character 0x%02X", + mxhosts[i], map->map_coldelim); + return NULL; + } + slen = strlen(mxhosts[i]); + if (len + slen + 2 > sizeof buf) + break; + if (i > 0) + { + *p++ = map->map_coldelim; + len++; + } + (void) strlcpy(p, mxhosts[i], sizeof buf - len); + p += slen; + len += slen; + } + return map_rewrite(map, buf, len, 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(MAXPACKET, MAXDNAME*2+2)]; + char *searchlist[MAXDNSRCH+2]; + + if (tTd(8, 2)) + dprintf("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). Note that there is no + ** longer a country named Czechoslovakia but this type of problem + ** is still present. + ** + ** 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 + { + (void) strlcpy(host, xp, hbsize); + 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)) + { + /* make sure there are less than MAXDNSRCH domains */ + for (domain = RES_DNSRCH_VARIABLE, ret = 0; + *domain != NULL && ret < MAXDNSRCH; + ret++) + *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)) + dprintf("dns_getcanonname: trying %s.%s (%s)\n", + host, *dp, + qtype == T_ANY ? "ANY" : +# if NETINET6 + qtype == T_AAAA ? "AAAA" : +# endif /* NETINET6 */ + 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)) + dprintf("\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; + + /* + ** If the ANY query is larger than the + ** UDP packet size, the resolver will + ** fall back to TCP. However, some + ** misconfigured firewalls black 53/TCP + ** so the ANY lookup fails whereas an MX + ** or A record might work. Therefore, + ** don't fail on ANY queries. + ** + ** The ANY query is really meant to prime + ** the cache so this isn't dangerous. + */ + + if (qtype != T_ANY) + return FALSE; + } + + if (h_errno != HOST_NOT_FOUND) + { + /* might have another type of interest */ + if (qtype == T_ANY) + { +# if NETINET6 + qtype = T_AAAA; +# else /* NETINET6 */ + qtype = T_A; +# endif /* NETINET6 */ + continue; + } +# if NETINET6 + else if (qtype == T_AAAA) + { + qtype = T_A; + continue; + } +# endif /* NETINET6 */ + else if (qtype == T_A && !gotmx && + (trymx || **dp == '\0')) + { + qtype = T_MX; + continue; + } + } + + /* definite no -- try the next domain */ + dp++; + qtype = T_ANY; + continue; + } + else if (tTd(8, 7)) + dprintf("\tYES\n"); + + /* avoid problems after truncation in tcp packets */ + if (ret > sizeof(answer)) + ret = sizeof(answer); + + /* + ** 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)) + dprintf("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. + */ + /* FALLTHROUGH */ + +# if NETINET6 + case T_AAAA: + /* Flag that a good match was found */ + amatch = TRUE; + + /* continue in case a CNAME also exists */ + continue; +# endif /* NETINET6 */ + + 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]; + + snprintf(ebuf, sizeof 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)strlcpy(host, nbuf, hbsize); + + /* + ** 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) + { +# if NETINET6 + qtype = T_AAAA; +# else /* NETINET6 */ + qtype = T_A; +# endif /* NETINET6 */ + } +# if NETINET6 + else if (qtype == T_AAAA) + qtype = T_A; +# endif /* NETINET6 */ + else if (qtype == T_A && !gotmx && (trymx || **dp == '\0')) + 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) snprintf(nbuf, sizeof nbuf, "%.*s%s%.*s", MAXDNAME, host, + *mxmatch == '\0' ? "" : ".", + MAXDNAME, mxmatch); + (void) strlcpy(host, nbuf, hbsize); + if (tTd(8, 5)) + dprintf("dns_getcanonname: %s\n", host); + *statp = EX_OK; + return TRUE; +} + +static char * +gethostalias(host) + char *host; +{ + char *fname; + FILE *fp; + register char *p = NULL; + long sff = SFF_REGONLY; + char buf[MAXLINE]; + static char hbuf[MAXDNAME]; + + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + fname = getenv("HOSTALIASES"); + if (fname == NULL || + (fp = safefopen(fname, O_RDONLY, 0, sff)) == 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 */ + (void) fclose(fp); + return NULL; + } + (void) fclose(fp); + + /* 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'; + (void) strlcpy(hbuf, host, sizeof hbuf); + return hbuf; +} +#endif /* NAMED_BIND */ diff --git a/gnu/usr.sbin/sendmail/sendmail/envelope.c b/gnu/usr.sbin/sendmail/sendmail/envelope.c new file mode 100644 index 00000000000..696ea88d755 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/envelope.c @@ -0,0 +1,974 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: envelope.c,v 8.180 1999/12/03 03:39:44 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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) + memmove((char *) &e->e_from, + (char *) &NullAddress, + sizeof e->e_from); + else + memmove((char *) &e->e_from, + (char *) &CurEnv->e_from, + sizeof e->e_from); + e->e_parent = parent; + assign_queueid(e); + 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. +** fulldrop -- if set, do return receipts. +** +** Returns: +** none. +** +** Side Effects: +** housekeeping necessary to dispose of an envelope. +** Unlocks this queue file. +*/ + +void +dropenvelope(e, fulldrop) + register ENVELOPE *e; + bool fulldrop; +{ + bool queueit = FALSE; + bool message_timeout = FALSE; + bool failure_return = FALSE; + bool delay_return = FALSE; + bool success_return = FALSE; + bool pmnotify = bitset(EF_PM_NOTIFY, e->e_flags); + register ADDRESS *q; + char *id = e->e_id; + char buf[MAXLINE]; + + if (tTd(50, 1)) + { + dprintf("dropenvelope %lx: id=", (u_long) e); + xputs(e->e_id); + dprintf(", flags="); + printenvflags(e); + if (tTd(50, 10)) + { + dprintf("sendq="); + printaddr(e->e_sendqueue, TRUE); + } + } + + if (LogLevel > 84) + sm_syslog(LOG_DEBUG, id, + "dropenvelope, e_flags=0x%lx, OpMode=%c, pid=%d", + e->e_flags, OpMode, getpid()); + + /* 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. + */ + + if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass]) + message_timeout = TRUE; + + if (TimeOuts.to_q_return[e->e_timeoutclass] == NOW && + !bitset(EF_RESPONSE, e->e_flags)) + { + message_timeout = TRUE; + e->e_flags |= EF_FATALERRS|EF_CLRQUEUE; + } + + e->e_flags &= ~EF_QUEUERUN; + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_UNDELIVERED(q->q_state)) + queueit = TRUE; + + /* see if a notification is needed */ + if (bitset(QPINGONFAILURE, q->q_flags) && + ((message_timeout && QS_IS_QUEUEUP(q->q_state)) || + QS_IS_BADADDR(q->q_state))) + { + failure_return = TRUE; + if (q->q_owner == NULL && !emptyaddr(&e->e_from)) + (void) sendtolist(e->e_from.q_paddr, NULLADDR, + &e->e_errorqueue, 0, e); + } + else if (bitset(QPINGONSUCCESS, q->q_flags) && + ((QS_IS_SENT(q->q_state) && + 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) + /* EMPTY */ + /* nothing to do */ ; + else if (message_timeout) + { + if (failure_return) + { + (void) snprintf(buf, sizeof buf, + "Cannot send message within %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; + } + 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 (QS_IS_UNDELIVERED(q->q_state)) + { + q->q_state = QS_BADADDR; + 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]) + { + if (!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)) + { + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_QUEUEUP(q->q_state) && +#if _FFR_NODELAYDSN_ON_HOLD + !bitnset(M_HOLD, q->q_mailer->m_flags) && +#endif /* _FFR_NODELAYDSN_ON_HOLD */ + bitset(QPINGONDELAY, q->q_flags)) + { + q->q_flags |= QDELAYED; + delay_return = TRUE; + } + } + } + if (delay_return) + { + (void) snprintf(buf, sizeof 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; + } + 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)) + dprintf("failure_return=%d delay_return=%d success_return=%d queueit=%d\n", + failure_return, delay_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) + { + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_UNDELIVERED(q->q_state) && + bitset(QPINGONFAILURE, q->q_flags)) + { + failure_return = TRUE; + q->q_state = QS_BADADDR; + } + } + } + + /* + ** Send back return receipts as requested. + */ + + if (success_return && !failure_return && !delay_return && fulldrop && + !bitset(PRIV_NORECEIPTS, PrivacyFlags) && + strcmp(e->e_from.q_paddr, "<>") != 0) + { + auto ADDRESS *rlist = NULL; + + if (tTd(50, 8)) + dprintf("dropenvelope(%s): sending return receipt\n", + id); + e->e_flags |= EF_SENDRECEIPT; + (void) sendtolist(e->e_from.q_paddr, NULLADDR, &rlist, 0, e); + (void) returntosender("Return receipt", rlist, RTSF_NO_BODY, e); + } + e->e_flags &= ~EF_SENDRECEIPT; + + /* + ** Arrange to send error messages if there are fatal errors. + */ + + if ((failure_return || delay_return) && e->e_errormode != EM_QUIET) + { + if (tTd(50, 8)) + dprintf("dropenvelope(%s): saving mail\n", id); + savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags)); + } + + /* + ** Arrange to send warning messages to postmaster as requested. + */ + + if ((failure_return || pmnotify) && + PostMasterCopy != NULL && + !bitset(EF_RESPONSE, e->e_flags) && + e->e_class >= 0) + { + auto ADDRESS *rlist = NULL; + char pcopy[MAXNAME]; + + if (failure_return) + { + expand(PostMasterCopy, pcopy, sizeof pcopy, e); + + if (tTd(50, 8)) + dprintf("dropenvelope(%s): sending postmaster copy to %s\n", + id, pcopy); + (void) sendtolist(pcopy, NULLADDR, &rlist, 0, e); + } + if (pmnotify) + (void) sendtolist("postmaster", NULLADDR, + &rlist, 0, e); + (void) returntosender(e->e_message, rlist, + RTSF_PM_BOUNCE|RTSF_NO_BODY, e); + } + + /* + ** Instantiate or deinstantiate the queue. + */ + +simpledrop: + if (tTd(50, 8)) + dprintf("dropenvelope(%s): at simpledrop, queueit=%d\n", + id, queueit); + if (!queueit || bitset(EF_CLRQUEUE, e->e_flags)) + { + if (tTd(50, 1)) + { + dprintf("\n===== Dropping [dq]f%s... queueit=%d, e_flags=", + e->e_id, queueit); + printenvflags(e); + } + xunlink(queuename(e, 'd')); + xunlink(queuename(e, 'q')); + + if (e->e_ntries > 0 && LogLevel > 9) + sm_syslog(LOG_INFO, id, "done; delay=%s, ntries=%d", + pintvl(curtime() - e->e_ctime, TRUE), + e->e_ntries); + } + else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) + { +#if QUEUE + queueup(e, FALSE); +#else /* QUEUE */ + syserr("554 5.3.0 dropenvelope: queueup"); +#endif /* QUEUE */ + } + + /* now unlock the job */ + if (tTd(50, 8)) + dprintf("dropenvelope(%s): unlocking job\n", id); + closexscript(e); + unlockqueue(e); + + /* make sure that this envelope is marked unused */ + if (e->e_dfp != NULL) + (void) bfclose(e->e_dfp); + 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) bfclose(e->e_xfp); + if (e->e_dfp != NULL) + (void) bfclose(e->e_dfp); + e->e_xfp = e->e_dfp = NULL; + } + + /* now clear out the data */ + STRUCTCOPY(BlankEnvelope, *e); + e->e_message = NULL; + if (Verbose) + set_delivery_mode(SM_DELIVER, e); + bh = BlankEnvelope.e_header; + nhp = &e->e_header; + while (bh != NULL) + { + *nhp = (HDR *) xalloc(sizeof *bh); + memmove((char *) *nhp, (char *) bh, 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: +** e -- the envelope to use. +** +** 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; + extern char *ttyname(); +#endif /* TTYNAME */ + + /* + ** Give this envelope a reality. + ** I.e., an id, a transcript, and a creation time. + */ + + setnewqueue(e); + openxscript(e); + e->e_ctime = curtime(); +#if _FFR_QUEUEDELAY + e->e_queuealg = QueueAlg; + e->e_queuedelay = QueueInitDelay; +#endif /* _FFR_QUEUEDELAY */ + + /* + ** 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) snprintf(pbuf, sizeof pbuf, "%d", (int) getpid()); + define('p', newstr(pbuf), e); + + /* hop count */ + (void) snprintf(cbuf, sizeof cbuf, "%d", e->e_hopcount); + define('c', newstr(cbuf), e); + + /* time as integer, unix time, arpa time */ + settime(e); + + /* Load average */ + (void)sm_getla(e); + +#ifdef TTYNAME + /* tty name */ + if (macvalue('y', e) == NULL) + { + p = ttyname(2); + if (p != NULL) + { + if (strrchr(p, '/') != NULL) + p = strrchr(p, '/') + 1; + snprintf(ybuf, sizeof ybuf, "%s", p); + define('y', ybuf, e); + } + } +#endif /* TTYNAME */ +} + /* +** SETTIME -- set the current time. +** +** Parameters: +** e -- the envelope in which the macros should be set. +** +** 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; + + now = curtime(); + tm = gmtime(&now); + (void) snprintf(tbuf, sizeof 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) strlcpy(dbuf, ctime(&now), sizeof dbuf); + 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 /* ! O_APPEND */ + +void +openxscript(e) + register ENVELOPE *e; +{ + register char *p; + + if (e->e_xfp != NULL) + return; + +#if 0 + if (e->e_lockfp == NULL && bitset(EF_INQUEUE, e->e_flags)) + syserr("openxscript: job not locked"); +#endif /* 0 */ + + p = queuename(e, 'x'); + e->e_xfp = bfopen(p, FileMode, XscriptFileBufferSize, + SFF_NOTEXCL|SFF_OPENASROOT); + if (e->e_xfp == NULL) + { + syserr("Can't create transcript file %s", p); + e->e_xfp = fopen("/dev/null", "r+"); + if (e->e_xfp == NULL) + syserr("!Can't open /dev/null"); + } +#if HASSETVBUF + (void) setvbuf(e->e_xfp, NULL, _IOLBF, 0); +#else /* HASSETVBUF */ + (void) setlinebuf(e->e_xfp); +#endif /* HASSETVBUF */ + if (tTd(46, 9)) + { + dprintf("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; +#if 0 + if (e->e_lockfp == NULL) + syserr("closexscript: job not locked"); +#endif /* 0 */ + (void) bfclose(e->e_xfp); + 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. +** delimchar -- the character that will delimit the sender +** address. +** 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, delimchar, internal) + char *from; + register ENVELOPE *e; + char **delimptr; + int delimchar; + bool internal; +{ + register char **pvp; + char *realname = NULL; + register struct passwd *pw; + char *bp; + char buf[MAXNAME + 2]; + char pvpbuf[PSBUFSIZE]; + extern char *FullName; + + if (tTd(45, 1)) + dprintf("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; + +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e s", e); +#endif /* _FFR_ADDR_TYPE */ + /* preset state for then clause in case from == NULL */ + e->e_from.q_state = QS_BADADDR; + e->e_from.q_flags = 0; + if (from == NULL || + parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR, + delimchar, delimptr, e) == NULL || + QS_IS_BADADDR(e->e_from.q_state) || + e->e_from.q_mailer == ProgMailer || + e->e_from.q_mailer == FileMailer || + e->e_from.q_mailer == InclMailer) + { + /* log garbage addresses for traceback */ + 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) snprintf(ebuf, sizeof ebuf, "%.*s@%.*s", + MAXNAME, realname, + MAXNAME, host); + p = ebuf; + } + sm_syslog(LOG_NOTICE, e->e_id, + "setsender: %s: invalid or unparsable, received from %s", + shortenstring(from, 83), p); + } + if (from != NULL) + { + if (!QS_IS_BADADDR(e->e_from.q_state)) + { + /* it was a bogus mailer in the from addr */ + e->e_status = "5.1.7"; + usrerrenh(e->e_status, + "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 5.3.0 setsender: can't even parse postmaster!"); + } + } + else + FromFlag = TRUE; + e->e_from.q_state = QS_SENDER; + if (tTd(45, 5)) + { + dprintf("setsender: QS_SENDER "); + printaddr(&e->e_from, FALSE); + } + SuprErrs = FALSE; + +#if USERDB + if (bitnset(M_CHECKUDB, e->e_from.q_mailer->m_flags)) + { + register char *p; + + 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 (e->e_from.q_user[0] != '\0' && + (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, sizeof buf); + if (buf[0] != '\0') + FullName = newstr(buf); + } + } + else + { + e->e_from.q_home = NULL; + } + if (FullName != NULL && !internal) + define('x', FullName, e); + } + else if (!internal && OpMode != MD_DAEMON && OpMode != MD_SMTP) + { + 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 */ + if (LogLevel > 2) + sm_syslog(LOG_NOTICE, e->e_id, + "cannot prescan from (%s)", + shortenstring(from, MAXSHORTSTR)); + finis(TRUE, ExitStat); + } + (void) rewrite(pvp, 3, 0, e); + (void) rewrite(pvp, 1, 0, e); + (void) rewrite(pvp, 4, 0, e); +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), NULL, e); +#endif /* _FFR_ADDR_TYPE */ + 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 */ + (void) strlcat(bp, ">", sizeof buf - 1); + *--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; + + /* get rid of any pesky angle brackets */ +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e s", e); +#endif /* _FFR_ADDR_TYPE */ + (void) rewrite(pvp, 3, 0, e); + (void) rewrite(pvp, 1, 0, e); + (void) rewrite(pvp, 4, 0, e); +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), NULL, e); +#endif /* _FFR_ADDR_TYPE */ + + /* 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)) + { + dprintf("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; +}; + +static 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/gnu/usr.sbin/sendmail/sendmail/err.c b/gnu/usr.sbin/sendmail/sendmail/err.c new file mode 100644 index 00000000000..1aad46a7afc --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/err.c @@ -0,0 +1,1016 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: err.c,v 8.120 2000/02/17 21:32:05 ca Exp $"; +#endif /* ! lint */ + +#include +#ifdef LDAPMAP +# include +# include /* for LDAP error codes */ +#endif /* LDAPMAP */ + +static void putoutmsg __P((char *, bool, bool)); +static void puterrmsg __P((char *)); +static char *fmtmsg __P((char *, const char *, const char *, const char *, + int, const char *, va_list)); + +/* +** SYSERR -- Print error message. +** +** Prints an error message via printf to the diagnostic output. +** +** 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 */ +static char HeldMessageBuf[sizeof MsgBuf]; /* for held messages */ + +#if NAMED_BIND && !defined(NO_DATA) +# define NO_DATA NO_ADDRESS +#endif /* NAMED_BIND && !defined(NO_DATA) */ + +void +/*VARARGS1*/ +#ifdef __STDC__ +syserr(const char *fmt, ...) +#else /* __STDC__ */ +syserr(fmt, va_alist) + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + register char *p; + int save_errno = errno; + bool panic; + char *user; + char *enhsc; + char *errtxt; + struct passwd *pw; + char ubuf[80]; + VA_LOCAL_DECL + + panic = *fmt == '!'; + if (panic) + { + fmt++; + HoldErrs = FALSE; + } + + /* format and output the error message */ + if (save_errno == 0) + { + p = "554"; + enhsc = "5.0.0"; + } + else + { + p = "451"; + enhsc = "4.0.0"; + } + VA_START(fmt); + errtxt = fmtmsg(MsgBuf, (char *) NULL, p, enhsc, save_errno, fmt, ap); + VA_END; + puterrmsg(MsgBuf); + + /* save this message for mailq printing */ + if (!panic && CurEnv != NULL) + { + if (CurEnv->e_message != NULL) + free(CurEnv->e_message); + CurEnv->e_message = newstr(errtxt); + } + + /* determine exit status if not already set */ + if (ExitStat == EX_OK) + { + if (save_errno == 0) + ExitStat = EX_SOFTWARE; + else + ExitStat = EX_OSERR; + if (tTd(54, 1)) + dprintf("syserr: ExitStat = %d\n", ExitStat); + } + + pw = sm_getpwuid(getuid()); + if (pw != NULL) + user = pw->pw_name; + else + { + user = ubuf; + snprintf(ubuf, sizeof ubuf, "UID%d", (int) getuid()); + } + + if (LogLevel > 0) + sm_syslog(panic ? LOG_ALERT : LOG_CRIT, + CurEnv == NULL ? NOQID : CurEnv->e_id, + "SYSERR(%s): %.900s", + user, errtxt); + switch (save_errno) + { + case EBADF: + case ENFILE: + case EMFILE: + case ENOTTY: +#ifdef EFBIG + case EFBIG: +#endif /* EFBIG */ +#ifdef ESPIPE + case ESPIPE: +#endif /* ESPIPE */ +#ifdef EPIPE + case EPIPE: +#endif /* EPIPE */ +#ifdef ENOBUFS + case ENOBUFS: +#endif /* ENOBUFS */ +#ifdef ESTALE + case ESTALE: +#endif /* ESTALE */ + printopenfds(TRUE); + mci_dump_all(TRUE); + break; + } + if (panic) + { +#ifdef XLA + xla_all_end(); +#endif /* XLA */ + sync_queue_time(); + 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 /* __STDC__ */ +usrerr(fmt, va_alist) + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + char *enhsc; + char *errtxt; + VA_LOCAL_DECL + + if (fmt[0] == '5' || fmt[0] == '6') + enhsc = "5.0.0"; + else if (fmt[0] == '4' || fmt[0] == '8') + enhsc = "4.0.0"; + else if (fmt[0] == '2') + enhsc = "2.0.0"; + else + enhsc = NULL; + VA_START(fmt); + errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap); + VA_END; + + if (SuprErrs) + return; + + /* save this message for mailq printing */ + switch (MsgBuf[0]) + { + case '4': + case '8': + if (CurEnv->e_message != NULL) + break; + + /* FALLTHROUGH */ + + case '5': + case '6': + if (CurEnv->e_message != NULL) + free(CurEnv->e_message); + if (MsgBuf[0] == '6') + { + char buf[MAXLINE]; + + snprintf(buf, sizeof buf, "Postmaster warning: %.*s", + (int) sizeof buf - 22, errtxt); + CurEnv->e_message = newstr(buf); + } + else + { + CurEnv->e_message = newstr(errtxt); + } + break; + } + + puterrmsg(MsgBuf); + + if (LogLevel > 3 && LogUsrErrs) + sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); + + if (QuickAbort) + longjmp(TopFrame, 1); +} + /* +** USRERRENH -- Signal user error. +** +** Same as usrerr but with enhanced status code. +** +** Parameters: +** enhsc -- the enhanced status code. +** 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__ +usrerrenh(char *enhsc, const char *fmt, ...) +#else /* __STDC__ */ +usrerrenh(enhsc, fmt, va_alist) + char *enhsc; + const char *fmt; + va_dcl +#endif /* __STDC__ */ +{ + char *errtxt; + VA_LOCAL_DECL + + if (enhsc == NULL || *enhsc == '\0') + { + if (fmt[0] == '5' || fmt[0] == '6') + enhsc = "5.0.0"; + else if (fmt[0] == '4' || fmt[0] == '8') + enhsc = "4.0.0"; + else if (fmt[0] == '2') + enhsc = "2.0.0"; + } + VA_START(fmt); + errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "501", enhsc, 0, fmt, ap); + VA_END; + + if (SuprErrs) + return; + + /* save this message for mailq printing */ + switch (MsgBuf[0]) + { + case '4': + case '8': + if (CurEnv->e_message != NULL) + break; + + /* FALLTHROUGH */ + + case '5': + case '6': + if (CurEnv->e_message != NULL) + free(CurEnv->e_message); + if (MsgBuf[0] == '6') + { + char buf[MAXLINE]; + + snprintf(buf, sizeof buf, "Postmaster warning: %.*s", + (int) sizeof buf - 22, errtxt); + CurEnv->e_message = newstr(buf); + } + else + { + CurEnv->e_message = newstr(errtxt); + } + break; + } + + puterrmsg(MsgBuf); + + if (LogLevel > 3 && LogUsrErrs) + sm_syslog(LOG_NOTICE, CurEnv->e_id, "%.900s", errtxt); + + 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. +*/ + +/*VARARGS1*/ +void +#ifdef __STDC__ +message(const char *msg, ...) +#else /* __STDC__ */ +message(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + char *errtxt; + VA_LOCAL_DECL + + errno = 0; + VA_START(msg); + errtxt = fmtmsg(MsgBuf, CurEnv->e_to, "050", (char *) NULL, 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; + /* FALLTHROUGH */ + + case '5': + if (CurEnv->e_message != NULL) + free(CurEnv->e_message); + CurEnv->e_message = newstr(errtxt); + 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. +*/ + +/*VARARGS1*/ +void +#ifdef __STDC__ +nmessage(const char *msg, ...) +#else /* __STDC__ */ +nmessage(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + char *errtxt; + VA_LOCAL_DECL + + errno = 0; + VA_START(msg); + errtxt = fmtmsg(MsgBuf, (char *) NULL, "050", + (char *) NULL, 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; + /* FALLTHROUGH */ + + case '5': + if (CurEnv->e_message != NULL) + free(CurEnv->e_message); + CurEnv->e_message = newstr(errtxt); + 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. +*/ + +static void +putoutmsg(msg, holdmsg, heldmsg) + char *msg; + bool holdmsg; + bool heldmsg; +{ + char *errtxt = msg; + char msgcode = msg[0]; + + /* display for debugging */ + if (tTd(54, 8)) + dprintf("--- %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 != NULL && CurEnv->e_xfp != NULL && + strchr("45", msg[0]) != NULL) + fprintf(CurEnv->e_xfp, "%s\n", msg); + + if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) + sm_syslog(LOG_INFO, CurEnv->e_id, + "--> %s%s", + msg, holdmsg ? " (held)" : ""); + + 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; + if (HeldMessageBuf[0] == '5' && msgcode == '4') + return; + snprintf(HeldMessageBuf, sizeof HeldMessageBuf, "%s", msg); + return; + } + + (void) fflush(stdout); + + if (OutChannel == NULL) + return; + + /* find actual text of error (after SMTP status codes) */ + if (ISSMTPREPLY(errtxt)) + { + int l; + + errtxt += 4; + l = isenhsc(errtxt, ' '); + if (l <= 0) + l = isenhsc(errtxt, '\0'); + if (l > 0) + errtxt += l + 1; + } + + /* 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", errtxt); + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d >>> %s\n", (int) getpid(), + (OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : errtxt); + 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 (InChannel == NULL || feof(InChannel) || ferror(InChannel) || + strncmp(msg, "221", 3) == 0) + return; + + /* can't call syserr, 'cause we are using MsgBuf */ + HoldErrs = TRUE; + if (LogLevel > 0) + sm_syslog(LOG_CRIT, CurEnv->e_id, + "SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %s", + CurHostName == NULL ? "NO-HOST" : CurHostName, + shortenstring(msg, MAXSHORTSTR), errstring(errno)); +} + /* +** 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. +*/ + +static void +puterrmsg(msg) + char *msg; +{ + char msgcode = msg[0]; + + /* output the message as usual */ + putoutmsg(msg, HoldErrs, FALSE); + + /* be careful about multiple error messages */ + if (OnlyOneError) + HoldErrs = TRUE; + + /* signal the error */ + Errors++; + + if (CurEnv == NULL) + return; + + 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; + } +} + /* +** ISENHSC -- check whether a string contains an enhanced status code +** +** Parameters: +** s -- string with possible enhanced status code. +** delim -- delim for enhanced status code. +** +** Returns: +** 0 -- no enhanced status code. +** >4 -- length of enhanced status code. +** +** Side Effects: +** none. +*/ +int +isenhsc(s, delim) + const char *s; + int delim; +{ + int l, h; + + if (s == NULL) + return 0; + if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) + return 0; + h = 0; + l = 2; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + ++h; + if (h == 0 || s[l + h] != '.') + return 0; + l += h + 1; + h = 0; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + ++h; + if (h == 0 || s[l + h] != delim) + return 0; + return l + h; +} + /* +** EXTENHSC -- check and extract an enhanced status code +** +** Parameters: +** s -- string with possible enhanced status code. +** delim -- delim for enhanced status code. +** e -- pointer to storage for enhanced status code. +** must be != NULL and have space for at least +** 10 characters ([245].[0-9]{1,3}.[0-9]{1,3}) +** +** Returns: +** 0 -- no enhanced status code. +** >4 -- length of enhanced status code. +** +** Side Effects: +** fills e with enhanced status code. +*/ +int +extenhsc(s, delim, e) + const char *s; + int delim; + char *e; +{ + int l, h; + + if (s == NULL) + return 0; + if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.')) + return 0; + h = 0; + l = 2; + e[0] = s[0]; + e[1] = '.'; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + { + e[l + h] = s[l + h]; + ++h; + } + if (h == 0 || s[l + h] != '.') + return 0; + e[l + h] = '.'; + l += h + 1; + h = 0; + while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h])) + { + e[l + h] = s[l + h]; + ++h; + } + if (h == 0 || s[l + h] != delim) + return 0; + e[l + h] = '\0'; + return l + h; +} + /* +** FMTMSG -- format a message into buffer. +** +** Parameters: +** eb -- error buffer to get result -- MUST BE MsgBuf. +** to -- the recipient tag for this message. +** num -- default three digit SMTP reply code. +** enhsc -- enhanced status code. +** en -- the error number to display. +** fmt -- format of string. +** ap -- arguments for fmt. +** +** Returns: +** pointer to error text beyond status codes. +** +** Side Effects: +** none. +*/ + +static char * +fmtmsg(eb, to, num, enhsc, eno, fmt, ap) + register char *eb; + const char *to; + const char *num; + const char *enhsc; + int eno; + const char *fmt; + va_list ap; +{ + char del; + int l; + int spaceleft = sizeof MsgBuf; + char *errtxt; + + /* output the reply code */ + if (ISSMTPCODE(fmt)) + { + num = fmt; + fmt += 4; + } + if (num[3] == '-') + del = '-'; + else + del = ' '; + (void) snprintf(eb, spaceleft, "%3.3s%c", num, del); + eb += 4; + spaceleft -= 4; + + if ((l = isenhsc(fmt, ' ' )) > 0 && l < spaceleft - 4) + { + /* copy enh.status code including trailing blank */ + l++; + (void) strlcpy(eb, fmt, l + 1); + eb += l; + spaceleft -= l; + fmt += l; + } + else if ((l = isenhsc(enhsc, '\0')) > 0 && l < spaceleft - 4) + { + /* copy enh.status code */ + (void) strlcpy(eb, enhsc, l + 1); + eb[l] = ' '; + eb[++l] = '\0'; + eb += l; + spaceleft -= l; + } + errtxt = eb; + + /* 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' && + strncmp(num, "551", 3) != 0 && + strncmp(num, "251", 3) != 0) + { + (void) snprintf(eb, spaceleft, "%s... ", + shortenstring(to, MAXSHORTSTR)); + spaceleft -= strlen(eb); + while (*eb != '\0') + *eb++ &= 0177; + } + + /* 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)); + + return errtxt; +} + /* +** 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; + char *bp; + static char buf[MAXLINE]; +#if !HASSTRERROR && !defined(ERRLIST_PREDEFINED) + extern char *sys_errlist[]; + extern int sys_nerr; +#endif /* !HASSTRERROR && !defined(ERRLIST_PREDEFINED) */ + + /* + ** 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: + bp = buf; +# if HASSTRERROR + snprintf(bp, SPACELEFT(buf, bp), "%s", strerror(errnum)); +# else /* HASSTRERROR */ + if (errnum >= 0 && errnum < sys_nerr) + snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]); + else + snprintf(bp, SPACELEFT(buf, bp), "Error %d", errnum); +# endif /* HASSTRERROR */ + bp += strlen(bp); + if (CurHostName != NULL) + { + if (errnum == ETIMEDOUT) + { + snprintf(bp, SPACELEFT(buf, bp), " with "); + bp += strlen(bp); + } + else + { + bp = buf; + snprintf(bp, SPACELEFT(buf, bp), + "Connection reset by "); + bp += strlen(bp); + } + snprintf(bp, SPACELEFT(buf, bp), "%s", + shortenstring(CurHostName, MAXSHORTSTR)); + bp += strlen(buf); + } + if (SmtpPhase != NULL) + { + snprintf(bp, SPACELEFT(buf, bp), " during %s", + SmtpPhase); + } + return buf; + + case EHOSTDOWN: + if (CurHostName == NULL) + break; + (void) snprintf(buf, sizeof buf, "Host %s is down", + shortenstring(CurHostName, MAXSHORTSTR)); + return buf; + + case ECONNREFUSED: + if (CurHostName == NULL) + break; + (void) snprintf(buf, sizeof buf, "Connection refused by %s", + shortenstring(CurHostName, MAXSHORTSTR)); + return buf; +#endif /* defined(DAEMON) && defined(ETIMEDOUT) */ + +#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 /* NAMED_BIND */ + + case EPERM: + /* SunOS gives "Not owner" -- this is the POSIX message */ + return "Operation not permitted"; + + /* + ** Error messages used internally in sendmail. + */ + + case E_SM_OPENTIMEOUT: + return "Timeout on file open"; + + case E_SM_NOSLINK: + return "Symbolic links not allowed"; + + case E_SM_NOHLINK: + return "Hard links not allowed"; + + case E_SM_REGONLY: + return "Regular files only"; + + case E_SM_ISEXEC: + return "Executable files not allowed"; + + case E_SM_WWDIR: + return "World writable directory"; + + case E_SM_GWDIR: + return "Group writable directory"; + + case E_SM_FILECHANGE: + return "File changed after open"; + + case E_SM_WWFILE: + return "World writable file"; + + case E_SM_GWFILE: + return "Group writable file"; + + case E_SM_GRFILE: + return "Group readable file"; + + case E_SM_WRFILE: + return "World readable file"; + } + + if (dnsmsg != NULL) + { + bp = buf; + bp += strlcpy(bp, "Name server: ", sizeof buf); + if (CurHostName != NULL) + { + snprintf(bp, SPACELEFT(buf, bp), "%s: ", + shortenstring(CurHostName, MAXSHORTSTR)); + bp += strlen(bp); + } + snprintf(bp, SPACELEFT(buf, bp), "%s", dnsmsg); + return buf; + } + +#ifdef LDAPMAP + if (errnum >= E_LDAPBASE) + return ldap_err2string(errnum - E_LDAPBASE); +#endif /* LDAPMAP */ + +#if HASSTRERROR + return strerror(errnum); +#else /* HASSTRERROR */ + if (errnum > 0 && errnum < sys_nerr) + return sys_errlist[errnum]; + + (void) snprintf(buf, sizeof buf, "Error %d", errnum); + return buf; +#endif /* HASSTRERROR */ +} diff --git a/gnu/usr.sbin/sendmail/sendmail/headers.c b/gnu/usr.sbin/sendmail/sendmail/headers.c new file mode 100644 index 00000000000..3ef74094b7a --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/headers.c @@ -0,0 +1,1896 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: headers.c,v 8.202 2000/02/17 17:18:17 ca Exp $"; +#endif /* ! lint */ + +#include + +static bool fix_mime_header __P((char *)); +static int priencode __P((char *)); +static void put_vanilla_header __P((HDR *, char *, MCI *)); + +/* +** SETUPHEADERS -- initialize headers in symbol table +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +setupheaders() +{ + struct hdrinfo *hi; + STAB *s; + + for (hi = HdrInfo; hi->hi_field != NULL; hi++) + { + s = stab(hi->hi_field, ST_HEADER, ST_ENTER); + s->s_header.hi_flags = hi->hi_flags; + s->s_header.hi_ruleset = NULL; + } +} + /* +** CHOMPHEADER -- process and save a header line. +** +** Called by collect, readcf, and readqf to deal with header lines. +** +** Parameters: +** line -- header as a text line. +** pflag -- flags: +** CHHDR_DEF: this is a default value. +** CHHDR_CHECK: call rulesets. +** 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. +*/ + +static struct hdrinfo NormalHeader = { NULL, 0, NULL }; + +u_long +chompheader(line, pflag, hdrp, e) + char *line; + int *pflag; + HDR **hdrp; + register ENVELOPE *e; +{ + u_char mid = '\0'; + register char *p; + register HDR *h; + HDR **hp; + char *fname; + char *fvalue; + bool cond = FALSE; + bool headeronly; + STAB *s; + struct hdrinfo *hi; + bool nullheader = FALSE; + BITMAP256 mopts; + + if (tTd(31, 6)) + { + dprintf("chompheader: "); + xputs(line); + dprintf("\n"); + } + + headeronly = hdrp != NULL; + if (!headeronly) + hdrp = &e->e_header; + + /* strip off options */ + clrbitmap(mopts); + p = line; + if (!bitset(*pflag, CHHDR_USER) && *p == '?') + { + int c; + register char *q; + + q = strchr(++p, '?'); + if (q == NULL) + goto hse; + + *q = '\0'; + c = *p & 0377; + + /* possibly macro conditional */ + if (c == MACROEXPAND) + { + /* catch ?$? */ + if (*++p == '\0') + { + *q = '?'; + goto hse; + } + + mid = (u_char) *p++; + + /* catch ?$abc? */ + if (*p != '\0') + { + *q = '?'; + goto hse; + } + } + else if (*p == '$') + { + /* catch ?$? */ + if (*++p == '\0') + { + *q = '?'; + goto hse; + } + + mid = (u_char)macid(p, NULL); + if (bitset(0200, mid)) + p += strlen(macname(mid)) + 2; + else + p++; + + /* catch ?$abc? */ + if (*p != '\0') + { + *q = '?'; + goto hse; + } + + } + else + { + while (*p != '\0') + { + if (!isascii(*p)) + { + *q = '?'; + goto hse; + } + + setbitn(*p, mopts); + cond = TRUE; + p++; + } + } + p = q + 1; + } + + /* find canonical name */ + fname = p; + while (isascii(*p) && isgraph(*p) && *p != ':') + p++; + fvalue = p; + while (isascii(*p) && isspace(*p)) + p++; + if (*p++ != ':' || fname == fvalue) + { +hse: + syserr("553 5.3.0 header syntax error, line \"%s\"", line); + return 0; + } + *fvalue = '\0'; + + /* strip field value on front */ + if (*p == ' ') + p++; + fvalue = p; + + /* if the field is null, go ahead and use the default */ + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + nullheader = TRUE; + + /* security scan: long field names are end-of-header */ + if (strlen(fname) > 100) + return H_EOH; + + /* check to see if it represents a ruleset call */ + if (bitset(*pflag, CHHDR_DEF)) + { + char hbuf[50]; + + (void) expand(fvalue, hbuf, sizeof hbuf, e); + for (p = hbuf; isascii(*p) && isspace(*p); ) + p++; + if ((*p++ & 0377) == CALLSUBR) + { + auto char *endp; + bool strc; + + strc = *p == '+'; /* strip comments? */ + if (strc) + ++p; + if (strtorwset(p, &endp, ST_ENTER) > 0) + { + *endp = '\0'; + s = stab(fname, ST_HEADER, ST_ENTER); + s->s_header.hi_ruleset = newstr(p); + if (!strc) + s->s_header.hi_flags |= H_STRIPCOMM; + } + return 0; + } + } + + /* see if it is a known type */ + s = stab(fname, ST_HEADER, ST_FIND); + if (s != NULL) + hi = &s->s_header; + else + hi = &NormalHeader; + + if (tTd(31, 9)) + { + if (s == NULL) + dprintf("no header flags match\n"); + else + dprintf("header match, flags=%lx, ruleset=%s\n", + hi->hi_flags, + hi->hi_ruleset == NULL ? "" : hi->hi_ruleset); + } + + /* see if this is a resent message */ + if (!bitset(*pflag, CHHDR_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 && !bitset(*pflag, CHHDR_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 (!headeronly && bitset(H_EOH, hi->hi_flags)) + return hi->hi_flags; + + /* + ** Horrible hack to work around problem with Lotus Notes SMTP + ** mail gateway, which generates From: headers with newlines in + ** them and the
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 = ' '; + } + + /* + ** If there is a check ruleset, verify it against the header. + */ + + if (bitset(*pflag, CHHDR_CHECK)) + { + bool stripcom = FALSE; + char *rs; + + /* no ruleset? look for default */ + rs = hi->hi_ruleset; + if (rs == NULL) + { + s = stab("*", ST_HEADER, ST_FIND); + if (s != NULL) + { + rs = (&s->s_header)->hi_ruleset; + stripcom = bitset((&s->s_header)->hi_flags, + H_STRIPCOMM); + } + } + else + stripcom = bitset(hi->hi_flags, H_STRIPCOMM); + if (rs != NULL) + { + int l; + char qval[MAXNAME]; + char hlen[16]; + char *sp, *dp; + + dp = qval; + l = 0; + dp[l++] = '"'; + for (sp = fvalue; *sp != '\0' && l < MAXNAME - 2; sp++) + { + switch(*sp) + { + case '\011': /* ht */ + case '\012': /* nl */ + case '\013': /* vt */ + case '\014': /* np */ + case '\015': /* cr */ + dp[l++] = ' '; + break; + case '"': + dp[l++] = '\\'; + /* FALLTHROUGH */ + default: + dp[l++] = *sp; + break; + } + } + dp[l++] = '"'; + dp[l++] = '\0'; + l = strlen(fvalue); + snprintf(hlen, sizeof hlen, "%d", l); + define(macid("{hdrlen}", NULL), newstr(hlen), e); + if (l >= MAXNAME) + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "Warning: truncated header '%s' before check with '%s' len=%d max=%d", + fname, rs, l, MAXNAME); + } + if ((sp = macvalue(macid("{currHeader}", NULL), e)) != + NULL) + free(sp); + define(macid("{currHeader}", NULL), newstr(qval), e); + define(macid("{hdr_name}", NULL), newstr(fname), e); + (void) rscheck(rs, fvalue, NULL, e, stripcom, TRUE); + } + } + +#if _FFR_MILTER + /* Call milter */ + if (bitset(*pflag, CHHDR_MILTER) && + !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + response = milter_header(fname, fvalue, e, &state); + switch (state) + { + case SMFIR_REPLYCODE: + *pflag &= ~CHHDR_MILTER; + usrerr(response); + break; + + case SMFIR_REJECT: + *pflag &= ~CHHDR_MILTER; + usrerr("554 5.7.1 Message rejected"); + break; + + case SMFIR_DISCARD: + *pflag &= ~CHHDR_MILTER; + e->e_flags |= EF_DISCARD; + break; + + case SMFIR_TEMPFAIL: + *pflag &= ~CHHDR_MILTER; + usrerr("451 4.7.1 Try again later"); + break; + } + if (response != NULL) + free(response); + } +#endif /* _FFR_MILTER */ + + /* + ** 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 (!bitset(*pflag, CHHDR_DEF) && !headeronly && + !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0) + { + if (tTd(31, 2)) + { + dprintf("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 && + e->e_from.q_mailer != NULL && + bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) && + (strcmp(fvalue, e->e_from.q_paddr) == 0 || + strcmp(fvalue, e->e_from.q_user) == 0)) + return hi->hi_flags; + } + + /* 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)) + { + if (nullheader) + { + /* user-supplied value was null */ + return 0; + } + h->h_value = NULL; + if (!cond) + { + /* copy conditions from default case */ + memmove((char *)mopts, (char *)h->h_mflags, + sizeof mopts); + } + h->h_macro = mid; + } + } + + /* create a new node */ + h = (HDR *) xalloc(sizeof *h); + h->h_field = newstr(fname); + h->h_value = newstr(fvalue); + h->h_link = NULL; + memmove((char *) h->h_mflags, (char *) mopts, sizeof mopts); + h->h_macro = mid; + *hp = h; + h->h_flags = hi->hi_flags; + + /* strip EOH flag if parsing MIME headers */ + if (headeronly) + h->h_flags &= ~H_EOH; + if (bitset(*pflag, CHHDR_DEF)) + h->h_flags |= H_DEFAULT; + if (cond || mid != '\0') + h->h_flags |= H_CHECK; + + /* hack to see if this is a new format message */ + if (!bitset(*pflag, CHHDR_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. +** hdrlist -- 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; + STAB *s; + HDR **hp; + + /* find info struct */ + s = stab(field, ST_HEADER, ST_FIND); + + /* 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 = H_DEFAULT; + if (s != NULL) + h->h_flags |= s->s_header.hi_flags; + clrbitmap(h->h_mflags); + h->h_macro = '\0'; + *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) + { + if (!rfc822_string(p)) + { + /* + ** Quote a full name with special characters + ** as a comment so crackaddr() doesn't destroy + ** the name portion of the address. + */ + p = addquotes(p); + } + define('x', p, e); + } + + if (tTd(32, 1)) + dprintf("----- collected header -----\n"); + msgid = NULL; + for (h = e->e_header; h != NULL; h = h->h_link) + { + if (tTd(32, 1)) + dprintf("%s: ", h->h_field); + if (h->h_value == NULL) + { + if (tTd(32, 1)) + dprintf("\n"); + continue; + } + + /* do early binding */ + if (bitset(H_DEFAULT, h->h_flags) && + !bitset(H_BINDLATE, h->h_flags)) + { + if (tTd(32, 1)) + { + dprintf("("); + xputs(h->h_value); + dprintf(") "); + } + expand(h->h_value, buf, sizeof buf, e); + if (buf[0] != '\0') + { + if (bitset(H_FROM, h->h_flags)) + 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); + dprintf("\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))) + { +#if 0 + int saveflags = e->e_flags; +#endif /* 0 */ + + (void) sendtolist(h->h_value, NULLADDR, + &e->e_sendqueue, 0, e); + +#if 0 + /* + ** Change functionality so a fatal error on an + ** address doesn't affect the entire envelope. + */ + + /* delete fatal errors generated by this address */ + if (!bitset(EF_FATALERRS, saveflags)) + e->e_flags &= ~EF_FATALERRS; +#endif /* 0 */ + } + + /* 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++; + } + } + if (tTd(32, 1)) + dprintf("----------------------------\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") == 0) + e->e_timeoutclass = TOC_URGENT; + else if (strcasecmp(p, "normal") == 0) + e->e_timeoutclass = TOC_NORMAL; + else if (strcasecmp(p, "non-urgent") == 0) + 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)) + dprintf("eatheader: setsender(*%s == %s)\n", + hi->hi_field, p); + setsender(p, e, NULL, '\0', TRUE); + } + } + + /* + ** Log collection information. + */ + + if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) + logsender(e, msgid); + 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; +{ + 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; + memmove(mbuf, msgid, 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) + /* EMPTY */ + ; + else if (RealHostName == NULL) + name = "localhost"; + else if (RealHostName[0] == '[') + name = RealHostName; + else + { + name = hbuf; + (void) snprintf(hbuf, sizeof hbuf, "%.80s", RealHostName); + if (RealHostAddr.sa.sa_family != 0) + { + p = &hbuf[strlen(hbuf)]; + (void) snprintf(p, SPACELEFT(hbuf, p), " (%.100s)", + anynet_ntoa(&RealHostAddr)); + } + } + + /* some versions of syslog only take 5 printf args */ +#if (SYSLOG_BUFSIZE) >= 256 + sbp = sbuf; + snprintf(sbp, SPACELEFT(sbuf, sbp), + "from=%.200s, size=%ld, class=%d, nrcpts=%d", + e->e_from.q_paddr == NULL ? "" : e->e_from.q_paddr, + e->e_msgsize, e->e_class, e->e_nrcpts); + sbp += strlen(sbp); + if (msgid != NULL) + { + snprintf(sbp, SPACELEFT(sbuf, sbp), ", msgid=%.100s", mbuf); + sbp += strlen(sbp); + } + if (e->e_bodytype != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", bodytype=%.20s", + e->e_bodytype); + sbp += strlen(sbp); + } + p = macvalue('r', e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", proto=%.20s", p); + sbp += strlen(sbp); + } + p = macvalue(macid("{daemon_name}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", daemon=%.20s", p); + sbp += strlen(sbp); + } +# if SASL + p = macvalue(macid("{auth_type}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", mech=%.10s", p); + sbp += strlen(sbp); + } + p = macvalue(macid("{auth_author}", NULL), e); + if (p != NULL) + { + (void) snprintf(sbp, SPACELEFT(sbuf, sbp), ", auth=%.30s", p); + sbp += strlen(sbp); + } +# endif /* SASL */ + sm_syslog(LOG_INFO, e->e_id, + "%.850s, relay=%.100s", + sbuf, name); + +#else /* (SYSLOG_BUFSIZE) >= 256 */ + + sm_syslog(LOG_INFO, e->e_id, + "from=%s", + e->e_from.q_paddr == NULL ? "" + : shortenstring(e->e_from.q_paddr, 83)); + sm_syslog(LOG_INFO, e->e_id, + "size=%ld, class=%ld, nrcpts=%d", + e->e_msgsize, e->e_class, e->e_nrcpts); + if (msgid != NULL) + sm_syslog(LOG_INFO, e->e_id, + "msgid=%s", + shortenstring(mbuf, 83)); + sbp = sbuf; + *sbp = '\0'; + if (e->e_bodytype != NULL) + { + snprintf(sbp, SPACELEFT(sbuf, sbp), "bodytype=%.20s, ", e->e_bodytype); + sbp += strlen(sbp); + } + p = macvalue('r', e); + if (p != NULL) + { + snprintf(sbp, SPACELEFT(sbuf, sbp), "proto=%.20s, ", p); + sbp += strlen(sbp); + } + sm_syslog(LOG_INFO, e->e_id, + "%.400srelay=%.100s", sbuf, name); +#endif /* (SYSLOG_BUFSIZE) >= 256 */ +} + /* +** PRIENCODE -- encode external priority names into internal values. +** +** Parameters: +** p -- priority in ascii. +** +** Returns: +** priority as a numeric level. +** +** Side Effects: +** none. +*/ + +static 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; + int bracklev; + 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)) + dprintf("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 - 7]; + p = addrhead = addr; + copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0; + bracklev = 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) + { + if (bp != bufhead) + *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--; + } + + /* count nesting on [ ... ] (for IPv6 domain literals) */ + if (c == '[') + bracklev++; + else if (c == ']') + bracklev--; + + /* check for group: list; syntax */ + if (c == ':' && anglelev <= 0 && bracklev <= 0 && + !gotcolon && !ColonOkInAddr) + { + register char *q; + + /* + ** Check for DECnet phase IV ``::'' (host::user) + ** or ** DECnet phase V ``:.'' syntaxes. The latter + ** covers ``user@DEC:.tay.myhost'' and + ** ``DEC:.tay.myhost::user'' syntaxes (bletch). + */ + + if (*p == ':' || *p == '.') + { + if (cmtlev <= 0 && !qmode) + quoteit = TRUE; + if (copylev > 0 && !skipping) + { + *bp++ = c; + *bp++ = *p; + } + 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) + { + if (bp > bufhead && bp[-1] == ')') + *bp++ = ' '; + *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)) + { + dprintf("crackaddr=>`"); + xputs(buf); + dprintf("'\n"); + } + + return buf; +} + /* +** PUTHEADER -- put the header part of a message from the in-core copy +** +** Parameters: +** mci -- the connection information. +** hdr -- the header to put. +** e -- envelope to use. +** flags -- MIME conversion flags. +** +** 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 /* ! MAX */ + +void +putheader(mci, hdr, e, flags) + register MCI *mci; + HDR *hdr; + register ENVELOPE *e; + int flags; +{ + register HDR *h; + char buf[MAX(MAXLINE,BUFSIZ)]; + char obuf[MAXLINE]; + + if (tTd(34, 1)) + dprintf("--- putheader, mailer = %s ---\n", + mci->mci_mailer->m_name); + + /* + ** If we're in MIME mode, we're not really in the header of the + ** message, just the header of one of the parts of the body of + ** the message. Therefore MCIF_INHEADER should not be turned on. + */ + + if (!bitset(MCIF_INMIME, mci->mci_flags)) + mci->mci_flags |= MCIF_INHEADER; + + for (h = hdr; h != NULL; h = h->h_link) + { + register char *p = h->h_value; + + if (tTd(34, 11)) + { + dprintf(" %s: ", h->h_field); + xputs(p); + } + + /* heuristic shortening of MIME fields to avoid MUA overflows */ + if (MaxMimeFieldLength > 0 && + wordinclass(h->h_field, + macid("{checkMIMEFieldHeaders}", NULL))) + { + if (fix_mime_header(h->h_value)) + { + sm_syslog(LOG_ALERT, e->e_id, + "Truncated MIME %s header due to field size (possible attack)", + h->h_field); + if (tTd(34, 11)) + dprintf(" truncated MIME %s header due to field size (possible attack)\n", + h->h_field); + } + } + + if (MaxMimeHeaderLength > 0 && + wordinclass(h->h_field, + macid("{checkMIMETextHeaders}", NULL))) + { + if (strlen(h->h_value) > MaxMimeHeaderLength) + { + h->h_value[MaxMimeHeaderLength - 1] = '\0'; + sm_syslog(LOG_ALERT, e->e_id, + "Truncated long MIME %s header (possible attack)", + h->h_field); + if (tTd(34, 11)) + dprintf(" truncated long MIME %s header (possible attack)\n", + h->h_field); + } + } + + if (MaxMimeHeaderLength > 0 && + wordinclass(h->h_field, + macid("{checkMIMEHeaders}", NULL))) + { + if (shorten_rfc822_string(h->h_value, MaxMimeHeaderLength)) + { + sm_syslog(LOG_ALERT, e->e_id, + "Truncated long MIME %s header (possible attack)", + h->h_field); + if (tTd(34, 11)) + dprintf(" truncated long MIME %s header (possible attack)\n", + h->h_field); + } + } + + /* + ** Suppress Content-Transfer-Encoding: if we are MIMEing + ** and we are potentially converting from 8 bit to 7 bit + ** MIME. If converting, add a new CTE header in + ** mime8to7(). + */ + if (bitset(H_CTE, h->h_flags) && + bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, + mci->mci_flags) && + !bitset(M87F_NO8TO7, flags)) + { + if (tTd(34, 11)) + dprintf(" (skipped (content-transfer-encoding))\n"); + continue; + } + + if (bitset(MCIF_INMIME, mci->mci_flags)) + { + if (tTd(34, 11)) + dprintf("\n"); + put_vanilla_header(h, p, mci); + continue; + } + + if (bitset(H_CHECK|H_ACHECK, h->h_flags) && + !bitintersect(h->h_mflags, mci->mci_mailer->m_flags) && + (h->h_macro == '\0' || + macvalue(h->h_macro & 0377, e) == NULL)) + { + if (tTd(34, 11)) + dprintf(" (skipped)\n"); + continue; + } + + /* handle Resent-... headers specially */ + if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags)) + { + if (tTd(34, 11)) + dprintf(" (skipped (resent))\n"); + continue; + } + + /* suppress return receipts if requested */ + if (bitset(H_RECEIPTTO, h->h_flags) && + (RrtImpliesDsn || bitset(EF_NORECEIPT, e->e_flags))) + { + if (tTd(34, 11)) + dprintf(" (skipped (receipt))\n"); + continue; + } + + /* macro expand value if generated internally */ + if (bitset(H_DEFAULT, h->h_flags) || + bitset(H_BINDLATE, h->h_flags)) + { + expand(p, buf, sizeof buf, e); + p = buf; + if (*p == '\0') + { + if (tTd(34, 11)) + dprintf(" (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)) + dprintf(" (skipped -- bcc)\n"); + } + else + { + /* no other recipient headers: truncate value */ + (void) snprintf(obuf, sizeof obuf, "%s:", + h->h_field); + putline(obuf, mci); + } + continue; + } + + if (tTd(34, 11)) + dprintf("\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 + { + put_vanilla_header(h, p, mci); + } + } + + /* + ** If we are converting this to a MIME message, add the + ** MIME headers (but not in MIME mode!). + */ + +#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|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags) && + hvalue("MIME-Version", e->e_header) == NULL) + { + putline("MIME-Version: 1.0", mci); + if (hvalue("Content-Type", e->e_header) == NULL) + { + snprintf(obuf, sizeof 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 /* MIME8TO7 */ +} + /* +** PUT_VANILLA_HEADER -- output a fairly ordinary header +** +** Parameters: +** h -- the structure describing this header +** v -- the value of this header +** mci -- the connection info for output +** +** Returns: +** none. +*/ + +static void +put_vanilla_header(h, v, mci) + HDR *h; + char *v; + MCI *mci; +{ + register char *nlp; + register char *obp; + int putflags; + char obuf[MAXLINE]; + + putflags = PXLF_HEADER; + if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) + putflags |= PXLF_STRIP8BIT; + (void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field); + obp = obuf + strlen(obuf); + while ((nlp = strchr(v, '\n')) != NULL) + { + int l; + + l = nlp - v; + if (SPACELEFT(obuf, obp) - 1 < l) + l = SPACELEFT(obuf, obp) - 1; + + snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v); + putxline(obuf, strlen(obuf), mci, putflags); + v += l + 1; + obp = obuf; + if (*v != ' ' && *v != '\t') + *obp++ = ' '; + } + snprintf(obp, SPACELEFT(obuf, obp), "%.*s", + (int) sizeof obuf - (obp - obuf) - 1, v); + putxline(obuf, strlen(obuf), mci, putflags); +} + /* +** 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; + int putflags = PXLF_HEADER; + char obuf[MAXLINE + 3]; + + /* + ** Output the address list translated by the + ** mailer and with commas. + */ + + if (tTd(14, 2)) + dprintf("commaize(%s: %s)\n", h->h_field, p); + + if (bitnset(M_7BITHDRS, mci->mci_mailer->m_flags)) + putflags |= PXLF_STRIP8BIT; + + obp = obuf; + (void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ", h->h_field); + opos = strlen(h->h_field) + 2; + if (opos > 202) + opos = 202; + 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 status; + + /* + ** 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)) + { + char *q; + + q = udbsender(name); + if (q != NULL) + name = q; + } +#endif /* USERDB */ + status = EX_OK; + name = remotename(name, mci->mci_mailer, flags, &status, e); + if (*name == '\0') + { + *p = savechar; + continue; + } + name = denlstring(name, FALSE, TRUE); + + /* + ** record data progress so DNS timeouts + ** don't cause DATA timeouts + */ + + DataProgress = TRUE; + + /* output the name with nice formatting */ + opos += strlen(name); + if (!firstone) + opos += 2; + if (opos > omax && !firstone) + { + snprintf(obp, SPACELEFT(obuf, obp), ",\n"); + putxline(obuf, strlen(obuf), mci, putflags); + obp = obuf; + (void) strlcpy(obp, " ", sizeof obp); + opos = strlen(obp); + obp += opos; + opos += strlen(name); + } + else if (!firstone) + { + snprintf(obp, SPACELEFT(obuf, obp), ", "); + obp += 2; + } + + while ((c = *name++) != '\0' && obp < &obuf[MAXLINE]) + *obp++ = c; + firstone = FALSE; + *p = savechar; + } + *obp = '\0'; + putxline(obuf, strlen(obuf), mci, putflags); +} + /* +** 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 *newhdr); + STRUCTCOPY(*header, *newhdr); + *tail = newhdr; + tail = &newhdr->h_link; + header = header->h_link; + } + *tail = NULL; + + return ret; +} + /* +** FIX_MIME_HEADER -- possibly truncate/rebalance parameters in a MIME header +** +** Run through all of the parameters of a MIME header and +** possibly truncate and rebalance the parameter according +** to MaxMimeFieldLength. +** +** Parameters: +** string -- the full header +** +** Returns: +** TRUE if the header was modified, FALSE otherwise +** +** Side Effects: +** string modified in place +*/ + +static bool +fix_mime_header(string) + char *string; +{ + bool modified = FALSE; + char *begin = string; + char *end; + + if (string == NULL || *string == '\0') + return FALSE; + + /* Split on each ';' */ + while ((end = find_character(begin, ';')) != NULL) + { + char save = *end; + char *bp; + + *end = '\0'; + + /* Shorten individual parameter */ + if (shorten_rfc822_string(begin, MaxMimeFieldLength)) + modified = TRUE; + + /* Collapse the possibly shortened string with rest */ + bp = begin + strlen(begin); + if (bp != end) + { + char *ep = end; + + *end = save; + end = bp; + + /* copy character by character due to overlap */ + while (*ep != '\0') + *bp++ = *ep++; + *bp = '\0'; + } + else + *end = save; + if (*end == '\0') + break; + + /* Move past ';' */ + begin = end + 1; + } + return modified; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/helpfile b/gnu/usr.sbin/sendmail/sendmail/helpfile new file mode 100644 index 00000000000..b6fefa6dc87 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/helpfile @@ -0,0 +1,130 @@ +#vers 2 +cpyr +cpyr Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +cpyr All rights reserved. +cpyr Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. +cpyr Copyright (c) 1988, 1993 +cpyr The Regents of the University of California. All rights reserved. +cpyr +cpyr +cpyr By using this file, you agree to the terms and conditions set +cpyr forth in the LICENSE file which can be found at the top level of +cpyr the sendmail distribution. +cpyr +cpyr $$Sendmail: helpfile,v 8.31 1999/11/14 21:42:03 gshapiro Exp $$ +cpyr +smtp This is sendmail version $v +smtp Topics: +smtp HELO EHLO MAIL RCPT DATA +smtp RSET NOOP QUIT HELP VRFY +smtp EXPN VERB ETRN DSN AUTH +smtp For more info use "HELP ". +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 [ ] +help The HELP command gives help info. +helo HELO +helo Introduce yourself. +ehlo EHLO +ehlo Introduce yourself, and request extended SMTP mode. +ehlo Possible replies include: +ehlo SEND Send as mail [RFC821] +ehlo SOML Send as mail or terminal [RFC821] +ehlo SAML Send as mail and terminal [RFC821] +ehlo EXPN Expand the mailing list [RFC821] +ehlo HELP Supply helpful information [RFC821] +ehlo TURN Turn the operation around [RFC821] +ehlo 8BITMIME Use 8-bit data [RFC1652] +ehlo SIZE Message size declaration [RFC1870] +ehlo VERB Verbose [Allman] +ehlo ONEX One message transaction only [Allman] +ehlo CHUNKING Chunking [RFC1830] +ehlo BINARYMIME Binary MIME [RFC1830] +ehlo PIPELINING Command Pipelining [RFC1854] +ehlo DSN Delivery Status Notification [RFC1891] +ehlo ETRN Remote Message Queue Starting [RFC1985] +ehlo XUSR Initial (user) submission [Allman] +mail MAIL FROM: [ ] +mail Specifies the sender. Parameters are ESMTP extensions. +mail See "HELP DSN" for details. +rcpt RCPT TO: [ ] +rcpt Specifies the recipient. Can be used any number of times. +rcpt Parameters are ESMTP extensions. See "HELP DSN" for details. +data DATA +data Following text is collected as the message. +data End with a single dot. +rset RSET +rset Resets the system. +quit QUIT +quit Exit sendmail (SMTP). +auth AUTH mechanism [initial-response] +auth Start authentication. +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 +vrfy Verify an address. If you want to see what it aliases +vrfy to, use EXPN instead. +expn EXPN +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: +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: +soml Send or mail. If the user is logged in, send directly, +soml otherwise mail. Not supported in this implementation. +saml SAML FROM: +saml Send and mail. Send directly to the user's terminal, +saml and also mail a letter. Not supported in this +saml implementation. +turn TURN +turn Reverses the direction of the connection. Not currently +turn implemented. +etrn ETRN [ | @ | # ] +etrn Run the queue for the specified , or +etrn all hosts within a given , or a specially-named +etrn (implementation-specific). +dsn MAIL FROM: [ RET={ FULL | HDRS} ] [ ENVID= ] +dsn RCPT TO: [ NOTIFY={NEVER,SUCCESS,FAILURE,DELAY} ] +dsn [ ORCPT= ] +dsn SMTP Delivery Status Notifications. +dsn Descriptions: +dsn RET Return either the full message or only headers. +dsn ENVID Sender's "envelope identifier" for tracking. +dsn NOTIFY When to send a DSN. Multiple options are OK, comma- +dsn delimited. NEVER must appear by itself. +dsn ORCPT Original recipient. +-bt Help for test mode: +-bt ? :this help message. +-bt .Dmvalue :define macro `m' to `value'. +-bt .Ccvalue :add `value' to class `c'. +-bt =Sruleset :dump the contents of the indicated ruleset. +-bt =M :display the known mailers. +-bt -ddebug-spec :equivalent to the command-line -d debug flag. +-bt $$m :print the value of macro $$m. +-bt $$=c :print the contents of class $$=c. +-bt /mx host :returns the MX records for `host'. +-bt /parse address :parse address, returning the value of crackaddr, and +-bt the parsed address. +-bt /try mailer addr :rewrite address into the form it will have when +-bt presented to the indicated mailer. +-bt /tryflags flags :set flags used by parsing. The flags can be `H' for +-bt Header or `E' for Envelope, and `S' for Sender or `R' +-bt for Recipient. These can be combined, `HR' sets +-bt flags for header recipients. +-bt /canon hostname :try to canonify hostname. +-bt /map mapname key :look up `key' in the indicated `mapname'. +-bt /quit :quit address test mode. +-bt rules addr :run the indicated address through the named rules. +-bt Rules can be a comma separated list of rules. +control Help for smcontrol: +control help This message. +control restart Restart sendmail. +control shutdown Shutdown sendmail. +control status Show sendmail status. diff --git a/gnu/usr.sbin/sendmail/sendmail/macro.c b/gnu/usr.sbin/sendmail/sendmail/macro.c new file mode 100644 index 00000000000..157e96b20e9 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/macro.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: macro.c,v 8.40 1999/11/22 19:10:16 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +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 skiplev; /* skipping nesting level */ + int iflev; /* if nesting level */ + char xbuf[MACBUFSIZE]; + static int explevel = 0; + + if (tTd(35, 24)) + { + dprintf("expand("); + xputs(s); + dprintf(")\n"); + } + + skipping = FALSE; + skiplev = 0; + 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 */ + iflev++; + c = *++s; + if (skipping) + skiplev++; + else + { + char *mv; + + mv = macvalue(c, e); + skipping = (mv == NULL || *mv == '\0'); + } + continue; + + case CONDELSE: /* change state of skipping */ + if (iflev == 0) + break; + if (skiplev == 0) + skipping = !skipping; + continue; + + case CONDFI: /* stop skipping */ + if (iflev == 0) + break; + iflev--; + if (skiplev == 0) + skipping = FALSE; + if (skipping) + skiplev--; + 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 - 1]) + 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)) + { + dprintf("expand ==> "); + xputs(xbuf); + dprintf("\n"); + } + + /* recurse as appropriate */ + if (recurse) + { + if (explevel < MaxMacroRecursion) + { + explevel++; + expand(xbuf, buf, bufsize, e); + explevel--; + return; + } + syserr("expand: recursion too deep (%d max)", + MaxMacroRecursion); + } + + /* copy results out */ + i = xp - xbuf; + if (i >= bufsize) + i = bufsize - 1; + memmove(buf, xbuf, 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+ +** (set via OperatorChars option in V6 or later +** sendmail.cf files) +** $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; +{ + int m; + + m = n & 0377; + if (tTd(35, 9)) + { + dprintf("%sdefine(%s as ", + (e->e_macro[m] == NULL) ? "" + : "re", macname(n)); + xputs(v); + dprintf(")\n"); + } + e->e_macro[m] = v; + +#if _FFR_RESET_MACRO_GLOBALS + switch (m) + { + case 'j': + MyHostName = v; + break; + } +#endif /* _FFR_RESET_MACRO_GLOBALS */ +} + /* +** 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[MAXMACNAMELEN + 1]; + + if (tTd(35, 14)) + { + dprintf("macid("); + xputs(p); + dprintf(") => "); + } + + if (*p == '\0' || (p[0] == '{' && p[1] == '}')) + { + syserr("Name required for macro/class"); + if (ep != NULL) + *ep = p; + if (tTd(35, 14)) + dprintf("NULL\n"); + return '\0'; + } + if (*p != '{') + { + /* the macro is its own code */ + if (ep != NULL) + *ep = p + 1; + if (tTd(35, 14)) + dprintf("%c\n", *p); + return *p; + } + bp = mbuf; + while (*++p != '\0' && *p != '}' && bp < &mbuf[sizeof mbuf - 1]) + { + 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 > MAXMACROID) + { + 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)) + dprintf("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/gnu/usr.sbin/sendmail/sendmail/mailq.0 b/gnu/usr.sbin/sendmail/sendmail/mailq.0 new file mode 100644 index 00000000000..528be968e7c --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/mailq.0 @@ -0,0 +1,66 @@ + + + +MAILQ(1) MAILQ(1) + + +NNAAMMEE + mmaaiillqq - print the mail queue + +SSYYNNOOPPSSIISS + mmaaiillqq [--vv] + +DDEESSCCRRIIPPTTIIOONN + MMaaiillqq prints a summary of the mail messages queued for + future delivery. + + The first line printed for each message shows the internal + identifier used on this host for the message, the size of + the message in bytes, the date and time the message was + accepted into the queue, and the envelope sender of the + message. The second line shows the error message that + caused this message to be retained in the queue; it will + not be present if the message is being processed for the + first time. The following lines show message recipients, + one per line. + + MMaaiillqq is identical to ``sendmail -bp''. + + The options are as follows: + + --vv Print verbose information. This adds the priority + of the message and a single character indicator + (``+'' or blank) indicating whether a warning mes- + sage has been sent on the first line of the mes- + sage. Additionally, extra lines may be intermixed + with the recipients indicating the ``controlling + user'' information; this shows who will own any + programs that are executed on behalf of this mes- + sage and the name of the alias this command + expanded from, if any. + + The mmaaiillqq utility exits 0 on success, and >0 if an error + occurs. + +SSEEEE AALLSSOO + sendmail(8) + +HHIISSTTOORRYY + The mmaaiillqq command appeared in 4.0BSD. + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:45 $ 1 + + diff --git a/gnu/usr.sbin/sendmail/sendmail/mailq.1 b/gnu/usr.sbin/sendmail/sendmail/mailq.1 new file mode 100644 index 00000000000..d4ae562457f --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/mailq.1 @@ -0,0 +1,64 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1985, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: mailq.1,v 8.14 1999/06/22 20:41:34 tony Exp $ +.\" +.TH MAILQ 1 "$Date: 2000/04/02 19:05:45 $" +.SH NAME +.B mailq +\- print the mail queue +.SH SYNOPSIS +.B mailq +.RB [ \-v ] +.SH DESCRIPTION +.B Mailq +prints a summary of the mail messages queued for future delivery. +.PP +The first line printed for each message +shows the internal identifier used on this host +for the message, +the size of the message in bytes, +the date and time the message was accepted into the queue, +and the envelope sender of the message. +The second line shows the error message that caused this message +to be retained in the queue; +it will not be present if the message is being processed +for the first time. +The following lines show message recipients, +one per line. +.PP +.B Mailq +is identical to ``sendmail -bp''. +.PP +The options are as follows: +.TP +.B \-v +Print verbose information. +This adds the priority of the message and +a single character indicator (``+'' or blank) +indicating whether a warning message has been sent +on the first line of the message. +Additionally, extra lines may be intermixed with the recipients +indicating the ``controlling user'' information; +this shows who will own any programs that are executed +on behalf of this message +and the name of the alias this command expanded from, if any. +.PP +The +.B mailq +utility exits 0 on success, and >0 if an error occurs. +.SH SEE ALSO +sendmail(8) +.SH HISTORY +The +.B mailq +command appeared in +4.0BSD. diff --git a/gnu/usr.sbin/sendmail/sendmail/main.c b/gnu/usr.sbin/sendmail/sendmail/main.c new file mode 100644 index 00000000000..f01e8be3ecd --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/main.c @@ -0,0 +1,3071 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: main.c,v 8.483 2000/02/26 01:32:26 gshapiro Exp $"; +#endif /* ! lint */ + +#define _DEFINE + +#include +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + +static void dump_class __P((STAB *, int)); +static void obsolete __P((char **)); +static void testmodeline __P((char *, ENVELOPE *)); + +/* +** 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 settings read in from /etc/mail/sendmail.cf +** (read by readcf.c). +** +** 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 (11/81 - 10/88). +** International Computer Science Institute +** (11/88 - 9/89). +** UCB/Mammoth Project (10/89 - 7/95). +** InReference, Inc. (8/95 - 1/97). +** Sendmail, Inc. (1/98 - present). +** The support of the my employers is gratefully acknowledged. +** Few of them (Britton-Lee in particular) have had +** anything 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 */ +static 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 int MissingFds = 0; /* bit map of fds missing on startup */ + +#ifdef NGROUPS_MAX +GIDSET_T InitialGidSet[NGROUPS_MAX]; +#endif /* NGROUPS_MAX */ + +#if DAEMON && !SMTP +ERROR %%%% Cannot have DAEMON mode without SMTP %%%% ERROR +#endif /* DAEMON && !SMTP */ +#if SMTP && !QUEUE +ERROR %%%% Cannot have SMTP mode without QUEUE %%%% ERROR +#endif /* SMTP && !QUEUE */ + +#define MAXCONFIGLEVEL 9 /* highest config version level known */ + +#if SASL +static sasl_callback_t srvcallbacks[] = { + { SASL_CB_VERIFYFILE, &safesaslfile, NULL }, + { SASL_CB_PROXY_POLICY, &proxy_policy, NULL }, + { SASL_CB_LIST_END, NULL, NULL } +}; +#endif /* SASL */ + +int SubmitMode; + +int +main(argc, argv, envp) + int argc; + char **argv; + char **envp; +{ + register char *p; + char **av; + extern char Version[]; + char *ep, *from; + STAB *st; + register int i; + int j; + bool safecf = TRUE; + BITMAP256 *p_flags = NULL; /* daemon flags */ + bool warn_C_flag = FALSE; + bool auth = TRUE; /* whether to set e_auth_param */ + char warn_f_flag = '\0'; + bool run_in_foreground = FALSE; /* -bD mode */ + static bool reenter = FALSE; + struct passwd *pw; + struct hostent *hp; + char *nullserver = NULL; + char *authinfo = NULL; + char *sysloglabel = NULL; /* label for syslog */ + bool forged; + struct stat traf_st; /* for TrafficLog FIFO check */ + char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */ + static char rnamebuf[MAXNAME]; /* holds RealUserName */ + char *emptyenviron[1]; + QUEUE_CHAR *new; + extern int DtableSize; + extern int optind; + extern int opterr; + extern char *optarg; + extern char **environ; + + /* + ** 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; + + /* avoid null pointer dereferences */ + TermEscape.te_rv_on = TermEscape.te_rv_off = ""; + + /* do machine-dependent initializations */ + init_md(argc, argv); + + /* 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. + */ + + fill_fd(STDIN_FILENO, NULL); + fill_fd(STDOUT_FILENO, NULL); + fill_fd(STDERR_FILENO, NULL); + + i = DtableSize; + while (--i > 0) + { + if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO) + (void) close(i); + } + errno = 0; + +#if LOG +# ifdef LOG_MAIL + openlog("sendmail", LOG_PID, LOG_MAIL); +# else /* LOG_MAIL */ + openlog("sendmail", LOG_PID); +# endif /* LOG_MAIL */ +#endif /* LOG */ + + if (MissingFds != 0) + { + char mbuf[MAXLINE]; + + mbuf[0] = '\0'; + if (bitset(1 << STDIN_FILENO, MissingFds)) + (void) strlcat(mbuf, ", stdin", sizeof mbuf); + if (bitset(1 << STDOUT_FILENO, MissingFds)) + (void) strlcat(mbuf, ", stdout", sizeof mbuf); + if (bitset(1 << STDERR_FILENO, MissingFds)) + (void) strlcat(mbuf, ", stderr", sizeof mbuf); + syserr("File descriptors missing on startup: %s", &mbuf[2]); + } + + /* reset status from syserr() calls for missing file descriptors */ + Errors = 0; + ExitStat = EX_OK; + + SubmitMode = SUBMIT_UNKNOWN; +#if XDEBUG + checkfd012("after openlog"); +#endif /* XDEBUG */ + + /* + ** Seed the random number generator. + ** Used for queue file names, picking a queue directory, and + ** MX randomization. + */ + + seed_random(); + + tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); + +#ifdef NGROUPS_MAX + /* save initial group set for future checks */ + i = getgroups(NGROUPS_MAX, InitialGidSet); + if (i == 0) + InitialGidSet[0] = (GID_T) -1; + while (i < NGROUPS_MAX) + InitialGidSet[i++] = InitialGidSet[0]; +#endif /* NGROUPS_MAX */ + + /* drop group id privileges (RunAsUser not yet set) */ + (void) drop_privileges(FALSE); + +#ifdef SIGUSR1 + /* arrange to dump state on user-1 signal */ + (void) setsignal(SIGUSR1, sigusr1); +#endif /* SIGUSR1 */ + + /* initialize for setproctitle */ + initsetproctitle(argc, argv, envp); + + /* 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:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:x" +#endif /* defined(__osf__) || defined(_AIX3) */ +#if defined(sony_news) +# define OPTIONS "B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtUV:vX:" +#endif /* defined(sony_news) */ +#ifndef OPTIONS +# define OPTIONS "B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtUV:vX:" +#endif /* ! OPTIONS */ + opterr = 0; + while ((j = getopt(argc, argv, OPTIONS)) != -1) + { + switch (j) + { + case 'd': + /* hack attack -- see if should use ANSI mode */ + if (strcmp(optarg, "ANSI") == 0) + { + TermEscape.te_rv_on = "\033[7m"; + TermEscape.te_rv_off = "\033[0m"; + break; + } + tTflag(optarg); + setbuf(stdout, (char *) NULL); + break; + + case 'G': /* relay (gateway) submission */ + SubmitMode |= SUBMIT_MTA; + break; + + case 'L': + sysloglabel = optarg; + break; + + case 'U': /* initial (user) submission */ + SubmitMode |= SUBMIT_MSA; + break; + } + } + opterr = 1; + + if (sysloglabel != NULL) + { + if (strlen(sysloglabel) > 24) + sysloglabel[24] = '\0'; +#if LOG + closelog(); +# ifdef LOG_MAIL + openlog(sysloglabel, LOG_PID, LOG_MAIL); +# else /* LOG_MAIL */ + openlog(sysloglabel, LOG_PID); +# endif /* LOG_MAIL */ +#endif /* LOG */ + } + + + /* 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) snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); + else + (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", + (int) RealUid); + RealUserName = rnamebuf; + + if (tTd(0, 101)) + { + dprintf("Version %s\n", Version); + finis(FALSE, EX_OK); + } + + /* + ** if running non-setuid binary as non-root, pretend + ** we are the RunAsUid + */ + if (RealUid != 0 && geteuid() == RealUid) + { + if (tTd(47, 1)) + dprintf("Non-setuid binary: RunAsUid = RealUid = %d\n", + (int)RealUid); + RunAsUid = RealUid; + } + else if (geteuid() != 0) + RunAsUid = geteuid(); + + if (RealUid != 0 && getegid() == RealGid) + RunAsGid = RealGid; + + if (tTd(47, 5)) + { + dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n", + (int)geteuid(), (int)getuid(), + (int)getegid(), (int)getgid()); + dprintf("main: RunAsUser = %d:%d\n", + (int)RunAsUid, (int)RunAsGid); + } + + /* save command line arguments */ + j = 0; + for (av = argv; *av != NULL; ) + j += strlen(*av++) + 1; + SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1)); + CommandLineArgs = xalloc(j); + p = CommandLineArgs; + for (av = argv, i = 0; *av != NULL; ) + { + int h; + + SaveArgv[i++] = newstr(*av); + if (av != argv) + *p++ = ' '; + (void) strlcpy(p, *av++, j); + h = strlen(p); + p += h; + j -= h + 1; + } + SaveArgv[i] = NULL; + + if (tTd(0, 1)) + { + int ll; + extern char *CompileOptions[]; + + dprintf("Version %s\n Compiled with:", Version); + av = CompileOptions; + ll = 7; + while (*av != NULL) + { + if (ll + strlen(*av) > 63) + { + dprintf("\n"); + ll = 0; + } + if (ll == 0) + dprintf("\t\t"); + else + dprintf(" "); + dprintf("%s", *av); + ll += strlen(*av++) + 1; + } + dprintf("\n"); + } + if (tTd(0, 10)) + { + int ll; + extern char *OsCompileOptions[]; + + dprintf(" OS Defines:"); + av = OsCompileOptions; + ll = 7; + while (*av != NULL) + { + if (ll + strlen(*av) > 63) + { + dprintf("\n"); + ll = 0; + } + if (ll == 0) + dprintf("\t\t"); + else + dprintf(" "); + dprintf("%s", *av); + ll += strlen(*av++) + 1; + } + dprintf("\n"); +#ifdef _PATH_UNIX + dprintf("Kernel symbols:\t%s\n", _PATH_UNIX); +#endif /* _PATH_UNIX */ + dprintf(" Def Conf file:\t%s\n", getcfname()); + dprintf(" Def Pid file:\t%s\n", PidFile); + } + + InChannel = stdin; + OutChannel = stdout; + + /* clear sendmail's environment */ + ExternalEnviron = environ; + emptyenviron[0] = NULL; + environ = emptyenviron; + + /* + ** restore any original TZ setting until TimeZoneSpec has been + ** determined - or early log messages may get bogus time stamps + */ + if ((p = getextenv("TZ")) != NULL) + { + char *tz; + int tzlen; + + tzlen = strlen(p) + 4; + tz = xalloc(tzlen); + (void) snprintf(tz, tzlen, "TZ=%s", p); + (void) putenv(tz); + } + + /* 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 = getextenv("NAME"); + + /* + ** Initialize name server if it is going to be used. + */ + +#if NAMED_BIND + if (!bitset(RES_INIT, _res.options)) + (void) res_init(); + if (tTd(8, 8)) + _res.options |= RES_DEBUG; + else + _res.options &= ~RES_DEBUG; +# ifdef RES_NOALIASES + _res.options |= RES_NOALIASES; +# endif /* RES_NOALIASES */ + TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry; + TimeOuts.res_retry[RES_TO_FIRST] = _res.retry; + TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry; + TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans; + TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans; + TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans; +#endif /* NAMED_BIND */ + + 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)) + dprintf("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'; + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", jbuf); + setclass('w', jbuf); + *p++ = '.'; + p = strchr(p, '.'); + } + } + + if (uname(&utsname) >= 0) + p = utsname.nodename; + else + { + if (tTd(0, 22)) + dprintf("uname failed (%s)\n", + errstring(errno)); + makelower(jbuf); + p = jbuf; + } + if (tTd(0, 4)) + dprintf(" 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)) + dprintf("\ta.k.a.: %s\n", *av); + setclass('w', *av); + } +#if NETINET || NETINET6 + for (i = 0; hp->h_addr_list[i] != NULL; i++) + { +# if NETINET6 + char *addr; + char buf6[INET6_ADDRSTRLEN]; + struct in6_addr ia6; +# endif /* NETINET6 */ +# if NETINET + struct in_addr ia; +# endif /* NETINET */ + char ipbuf[103]; + + ipbuf[0] = '\0'; + switch (hp->h_addrtype) + { +# if NETINET + case AF_INET: + if (hp->h_length != INADDRSZ) + break; + + memmove(&ia, hp->h_addr_list[i], INADDRSZ); + (void) snprintf(ipbuf, sizeof ipbuf, + "[%.100s]", inet_ntoa(ia)); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (hp->h_length != IN6ADDRSZ) + break; + + memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ); + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + if (addr != NULL) + (void) snprintf(ipbuf, sizeof ipbuf, + "[%.100s]", addr); + break; +# endif /* NETINET6 */ + } + if (ipbuf[0] == '\0') + break; + + if (tTd(0, 4)) + dprintf("\ta.k.a.: %s\n", ipbuf); + setclass('w', ipbuf); + } +#endif /* NETINET || NETINET6 */ + } + + /* current time */ + define('b', arpadate((char *) NULL), CurEnv); + /* current load average */ + CurrentLA = sm_getla(CurEnv); + + QueueLimitRecipient = (QUEUE_CHAR *) NULL; + QueueLimitSender = (QUEUE_CHAR *) NULL; + QueueLimitId = (QUEUE_CHAR *) NULL; + + /* + ** 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; + else if (strcmp(p, "hoststat") == 0) + OpMode = MD_HOSTSTAT; + else if (strcmp(p, "purgestat") == 0) + OpMode = MD_PURGESTAT; + + optind = 1; + while ((j = getopt(argc, argv, OPTIONS)) != -1) + { + switch (j) + { + case 'b': /* operations mode */ + switch (j = *optarg) + { + case MD_DAEMON: + case MD_FGDAEMON: +#if !DAEMON + usrerr("Daemon mode not implemented"); + ExitStat = EX_USAGE; + break; +#endif /* !DAEMON */ + case MD_SMTP: +#if !SMTP + usrerr("I don't speak SMTP"); + ExitStat = EX_USAGE; + break; +#endif /* !SMTP */ + + case MD_INITALIAS: + case MD_DELIVER: + case MD_VERIFY: + case MD_TEST: + case MD_PRINT: + case MD_HOSTSTAT: + case MD_PURGESTAT: + 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; + (void) drop_privileges(TRUE); + 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 'G': /* relay (gateway) submission */ + /* already set */ + break; + + case 'h': /* hop count */ + CurEnv->e_hopcount = strtol(optarg, &ep, 10); + if (*ep) + { + usrerr("Bad hop count (%s)", optarg); + ExitStat = EX_USAGE; + } + break; + + case 'L': /* program label */ + /* already set */ + break; + + case 'n': /* don't alias */ + NoAlias = TRUE; + break; + + case 'N': /* delivery status notifications */ + DefaultNotify |= QHASNOTIFY; + define(macid("{dsn_notify}", NULL), + newstr(optarg), CurEnv); + if (strcasecmp(optarg, "never") == 0) + break; + for (p = optarg; p != NULL; optarg = p) + { + p = strchr(p, ','); + if (p != NULL) + *p++ = '\0'; + if (strcasecmp(optarg, "success") == 0) + DefaultNotify |= QPINGONSUCCESS; + else if (strcasecmp(optarg, "failure") == 0) + DefaultNotify |= QPINGONFAILURE; + else if (strcasecmp(optarg, "delay") == 0) + DefaultNotify |= QPINGONDELAY; + else + { + usrerr("Invalid -N argument"); + ExitStat = EX_USAGE; + } + } + 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 */ +#if QUEUE + /* sanity check */ + if (OpMode != MD_DELIVER && + OpMode != MD_DAEMON && + OpMode != MD_FGDAEMON && + OpMode != MD_PRINT && + OpMode != MD_QUEUERUN) + { + usrerr("Can not use -q with -b%c", OpMode); + ExitStat = EX_USAGE; + break; + } + + /* don't override -bd, -bD or -bp */ + if (OpMode == MD_DELIVER) + OpMode = MD_QUEUERUN; + + FullName = NULL; + + switch (optarg[0]) + { + case 'I': + new = (QUEUE_CHAR *) xalloc(sizeof *new); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitId; + QueueLimitId = new; + break; + + case 'R': + new = (QUEUE_CHAR *) xalloc(sizeof *new); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitRecipient; + QueueLimitRecipient = new; + break; + + case 'S': + new = (QUEUE_CHAR *) xalloc(sizeof *new); + new->queue_match = newstr(&optarg[1]); + new->queue_next = QueueLimitSender; + QueueLimitSender = new; + break; + + default: + i = Errors; + QueueIntvl = convtime(optarg, 'm'); + + /* check for bad conversion */ + if (i < Errors) + ExitStat = EX_USAGE; + break; + } +#else /* QUEUE */ + usrerr("I don't know about queues"); + ExitStat = EX_USAGE; +#endif /* QUEUE */ + break; + + case 'R': /* DSN RET: what to return */ + if (bitset(EF_RET_PARAM, CurEnv->e_flags)) + { + usrerr("Duplicate -R flag"); + ExitStat = EX_USAGE; + break; + } + CurEnv->e_flags |= EF_RET_PARAM; + if (strcasecmp(optarg, "hdrs") == 0) + CurEnv->e_flags |= EF_NO_BODY_RETN; + else if (strcasecmp(optarg, "full") != 0) + { + usrerr("Invalid -R value"); + ExitStat = EX_USAGE; + } + define(macid("{dsn_ret}", NULL), + newstr(optarg), CurEnv); + break; + + case 't': /* read recipients from message */ + GrabTo = TRUE; + break; + + case 'U': /* initial (user) submission */ + /* already set */ + break; + + case 'V': /* DSN ENVID: set "original" envelope id */ + if (!xtextok(optarg)) + { + usrerr("Invalid syntax in -V flag"); + ExitStat = EX_USAGE; + } + else + { + CurEnv->e_envid = newstr(optarg); + define(macid("{dsn_envid}", NULL), + newstr(optarg), CurEnv); + } + break; + + case 'X': /* traffic log file */ + (void) drop_privileges(TRUE); + if (stat(optarg, &traf_st) == 0 && + S_ISFIFO(traf_st.st_mode)) + TrafficLogFile = fopen(optarg, "w"); + else + TrafficLogFile = fopen(optarg, "a"); + if (TrafficLogFile == NULL) + { + syserr("cannot open %s", optarg); + ExitStat = EX_CANTCREAT; + break; + } +#if HASSETVBUF + (void) setvbuf(TrafficLogFile, NULL, _IOLBF, 0); +#else /* HASSETVBUF */ + (void) setlinebuf(TrafficLogFile); +#endif /* HASSETVBUF */ + 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 /* defined(__osf__) || defined(_AIX3) */ +#if defined(sony_news) + case 'E': + case 'J': /* ignore flags for Japanese code conversion + implemented on Sony NEWS */ + break; +#endif /* defined(sony_news) */ + + default: + finis(TRUE, EX_USAGE); + break; + } + } + av += optind; + + if (bitset(SUBMIT_MTA, SubmitMode) && + bitset(SUBMIT_MSA, SubmitMode)) + { + /* sanity check */ + errno = 0; /* reset to avoid bogus error messages */ + syserr("Cannot use both -G and -U together"); + } + else if (bitset(SUBMIT_MTA, SubmitMode)) + define(macid("{daemon_flags}", NULL), "CC f", CurEnv); + else if (bitset(SUBMIT_MSA, SubmitMode)) + { + define(macid("{daemon_flags}", NULL), "c u", CurEnv); + + /* check for wrong OpMode */ + if (OpMode != MD_DELIVER && OpMode != MD_SMTP) + { + errno = 0; /* reset to avoid bogus error msgs */ + syserr("Cannot use -U and -b%c", OpMode); + } + } + else + { +#if _FFR_DEFAULT_SUBMIT_TO_MSA + define(macid("{daemon_flags}", NULL), "c u", CurEnv); +#else /* _FFR_DEFAULT_SUBMIT_TO_MSA */ + /* EMPTY */ +#endif /* _FFR_DEFAULT_SUBMIT_TO_MSA */ + } + + /* + ** 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 /* XDEBUG */ + vendor_pre_defaults(CurEnv); + + readcf(getcfname(), safecf, CurEnv); + ConfigFileRead = TRUE; + vendor_post_defaults(CurEnv); + + /* 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(); + + /* avoid denial-of-service attacks */ + resetlimits(); + + if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON) + { + /* drop privileges -- daemon mode done after socket/bind */ + (void) drop_privileges(FALSE); + } + +#if NAMED_BIND + _res.retry = TimeOuts.res_retry[RES_TO_DEFAULT]; + _res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT]; +#endif /* NAMED_BIND */ + + /* + ** Find our real host name for future logging. + */ + + authinfo = getauthinfo(STDIN_FILENO, &forged); + define('_', authinfo, 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); + + /* probe interfaces and locate any additional names */ + if (!DontProbeInterfaces) + load_if_names(); + + if (tTd(0, 1)) + { + dprintf("\n============ SYSTEM IDENTITY (after readcf) ============"); + dprintf("\n (short domain name) $w = "); + xputs(macvalue('w', CurEnv)); + dprintf("\n (canonical domain name) $j = "); + xputs(macvalue('j', CurEnv)); + dprintf("\n (subdomain name) $m = "); + xputs(macvalue('m', CurEnv)); + dprintf("\n (node name) $k = "); + xputs(macvalue('k', CurEnv)); + dprintf("\n========================================================\n\n"); + } + + /* + ** 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 && !wordinclass(RealUserName, 't')) + auth_warning(CurEnv, "Processed from queue %s", QueueDir); + + /* check body type for legality */ + if (CurEnv->e_bodytype == NULL) + /* EMPTY */ + /* 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; + } + + /* tweak default DSN notifications */ + if (DefaultNotify == 0) + DefaultNotify = QPINGONFAILURE|QPINGONDELAY; + + /* be sure we don't pick up bogus HOSTALIASES environment variable */ + if (OpMode == MD_QUEUERUN && RealUid != 0) + (void) unsetenv("HOSTALIASES"); + + /* check for sane configuration level */ + if (ConfigLevel > MAXCONFIGLEVEL) + { + syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)", + ConfigLevel, Version, MAXCONFIGLEVEL); + } + + /* need MCI cache to have persistence */ + if (HostStatDir != NULL && MaxMciCache == 0) + { + HostStatDir = NULL; + printf("Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n"); + } + + /* need HostStatusDir in order to have SingleThreadDelivery */ + if (SingleThreadDelivery && HostStatDir == NULL) + { + SingleThreadDelivery = FALSE; + printf("Warning: HostStatusDirectory required for SingleThreadDelivery\n"); + } + + /* check for permissions */ + if ((OpMode == MD_DAEMON || + OpMode == MD_FGDAEMON || + OpMode == MD_PURGESTAT) && + RealUid != 0 && + RealUid != TrustedUid) + { + if (LogLevel > 1) + sm_syslog(LOG_ALERT, NOQID, + "user %d attempted to %s", + RealUid, + OpMode != MD_PURGESTAT ? "run daemon" + : "purge host status"); + usrerr("Permission denied"); + finis(FALSE, EX_USAGE); + } + if (OpMode == MD_INITALIAS && + RealUid != 0 && + RealUid != TrustedUid && + !wordinclass(RealUserName, 't')) + { + if (LogLevel > 1) + sm_syslog(LOG_ALERT, NOQID, + "user %d attempted to rebuild the alias map", + RealUid); + usrerr("Permission denied"); + finis(FALSE, EX_USAGE); + } + + if (MeToo) + BlankEnvelope.e_flags |= EF_METOO; + + switch (OpMode) + { + case MD_TEST: + /* don't have persistent host status in test mode */ + HostStatDir = NULL; + if (Verbose == 0) + Verbose = 2; + CurEnv->e_errormode = EM_PRINT; + HoldErrs = FALSE; + break; + + case MD_VERIFY: + CurEnv->e_errormode = EM_PRINT; + HoldErrs = FALSE; + /* arrange to exit cleanly on hangup signal */ + if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) + (void) setsignal(SIGHUP, intsig); + break; + + case MD_FGDAEMON: + run_in_foreground = TRUE; + OpMode = MD_DAEMON; + /* FALLTHROUGH */ + + case MD_DAEMON: + vendor_daemon_setup(CurEnv); + + /* remove things that don't make sense in daemon mode */ + FullName = NULL; + GrabTo = FALSE; + + /* arrange to restart on hangup signal */ + if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/') + sm_syslog(LOG_WARNING, NOQID, + "daemon invoked without full pathname; kill -1 won't work"); + (void) setsignal(SIGHUP, sighup); + + /* workaround: can't seem to release the signal in the parent */ + (void) releasesignal(SIGHUP); + break; + + case MD_INITALIAS: + Verbose = 2; + CurEnv->e_errormode = EM_PRINT; + HoldErrs = FALSE; + /* FALLTHROUGH */ + + default: + /* arrange to exit cleanly on hangup signal */ + if (setsignal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) + (void) setsignal(SIGHUP, intsig); + break; + } + + /* special considerations for FullName */ + if (FullName != NULL) + { + char *full = NULL; + + /* full names can't have newlines */ + if (strchr(FullName, '\n') != NULL) + { + FullName = full = newstr(denlstring(FullName, TRUE, TRUE)); + } + /* check for characters that may have to be quoted */ + if (!rfc822_string(FullName)) + { + /* + ** Quote a full name with special characters + ** as a comment so crackaddr() doesn't destroy + ** the name portion of the address. + */ + FullName = addquotes(FullName); + if (full != NULL) + free(full); + } + } + + /* 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); + } + +#ifdef VENDOR_CODE + /* check for vendor mismatch */ + if (VendorCode != VENDOR_CODE) + { + message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s", + getvendor(VENDOR_CODE), getvendor(VendorCode)); + } +#endif /* VENDOR_CODE */ + + /* check for out of date configuration level */ + if (ConfigLevel < MAXCONFIGLEVEL) + { + message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d", + Version, MAXCONFIGLEVEL, ConfigLevel); + } + + 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"; + } + SmtpError[0] = '\0'; + + /* 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); + } + if (ConfigLevel < 7) + { + if (LocalMailer != NULL) + setbitn(M_VRFY250, LocalMailer->m_flags); + if (ProgMailer != NULL) + setbitn(M_VRFY250, ProgMailer->m_flags); + if (FileMailer != NULL) + setbitn(M_VRFY250, FileMailer->m_flags); + } + + /* MIME Content-Types that cannot be transfer encoded */ + setclass('n', "multipart/signed"); + + /* MIME message/xxx 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"); + +#ifdef USE_B_CLASS + /* MIME Content-Types that should be treated as binary */ + setclass('b', "image"); + setclass('b', "audio"); + setclass('b', "video"); + setclass('b', "application/octet-stream"); +#endif /* USE_B_CLASS */ + + /* MIME headers which have fields to check for overflow */ + setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-disposition"); + setclass(macid("{checkMIMEFieldHeaders}", NULL), "content-type"); + + /* MIME headers to check for length overflow */ + setclass(macid("{checkMIMETextHeaders}", NULL), "content-description"); + + /* MIME headers to check for overflow and rebalance */ + setclass(macid("{checkMIMEHeaders}", NULL), "content-disposition"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-id"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-transfer-encoding"); + setclass(macid("{checkMIMEHeaders}", NULL), "content-type"); + setclass(macid("{checkMIMEHeaders}", NULL), "mime-version"); + + /* Macros to save in the qf file -- don't remove any */ + setclass(macid("{persistentMacros}", NULL), "r"); + setclass(macid("{persistentMacros}", NULL), "s"); + setclass(macid("{persistentMacros}", NULL), "_"); + setclass(macid("{persistentMacros}", NULL), "{if_addr}"); + setclass(macid("{persistentMacros}", NULL), "{if_family}"); + setclass(macid("{persistentMacros}", NULL), "{daemon_flags}"); + setclass(macid("{persistentMacros}", NULL), "{client_flags}"); + + /* operate in queue directory */ + if (QueueDir == NULL) + { + if (OpMode != MD_TEST) + { + syserr("QueueDirectory (Q) option must be set"); + ExitStat = EX_CONFIG; + } + } + else + { + /* + ** If multiple queues wildcarded, use one for + ** the daemon's home. Note that this preconditions + ** a wildcarded QueueDir to a real pathname. + */ + + if (OpMode != MD_TEST) + multiqueue_cache(); + } + + /* check host status directory for validity */ + if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE)) + { + /* cannot use this value */ + if (tTd(0, 2)) + dprintf("Cannot use HostStatusDirectory = %s: %s\n", + HostStatDir, errstring(errno)); + HostStatDir = NULL; + } + +#if QUEUE + if (OpMode == MD_QUEUERUN && 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"); + finis(FALSE, EX_NOPERM); + } + } +#endif /* QUEUE */ + +#if _FFR_MILTER + /* sanity checks on milter filters */ + if (OpMode == MD_DAEMON || OpMode == MD_SMTP) + milter_parse_list(InputFilterList, InputFilters, MAXFILTERS); +#endif /* _FFR_MILTER */ + + /* if we've had errors so far, exit now */ + if (ExitStat != EX_OK && OpMode != MD_TEST) + finis(FALSE, ExitStat); + +#if XDEBUG + checkfd012("before main() initmaps"); +#endif /* XDEBUG */ + + /* + ** Do operation-mode-dependent initialization. + */ + + switch (OpMode) + { + case MD_PRINT: + /* print the queue */ +#if QUEUE + dropenvelope(CurEnv, TRUE); + (void) setsignal(SIGPIPE, quiesce); + printqueue(); + finis(FALSE, EX_OK); +#else /* QUEUE */ + usrerr("No queue to print"); + finis(FALSE, EX_UNAVAILABLE); +#endif /* QUEUE */ + break; + + case MD_HOSTSTAT: + (void) setsignal(SIGPIPE, quiesce); + (void) mci_traverse_persistent(mci_print_persistent, NULL); + finis(FALSE, EX_OK); + break; + + case MD_PURGESTAT: + (void) mci_traverse_persistent(mci_purge_persistent, NULL); + finis(FALSE, EX_OK); + break; + + case MD_INITALIAS: + /* initialize maps */ + initmaps(); + finis(FALSE, ExitStat); + break; + + case MD_SMTP: + case MD_DAEMON: + /* reset DSN parameters */ + DefaultNotify = QPINGONFAILURE|QPINGONDELAY; + define(macid("{dsn_notify}", NULL), NULL, CurEnv); + CurEnv->e_envid = NULL; + define(macid("{dsn_envid}", NULL), NULL, CurEnv); + CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN); + define(macid("{dsn_ret}", NULL), NULL, CurEnv); + + /* don't open maps for daemon -- done below in child */ + 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]; + + if (isatty(fileno(stdin))) + Verbose = 2; + + if (Verbose) + { + printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n"); + printf("Enter
\n"); + } + if (setjmp(TopFrame) > 0) + printf("\n"); + (void) setsignal(SIGINT, intindebug); + for (;;) + { + if (Verbose == 2) + printf("> "); + (void) fflush(stdout); + if (fgets(buf, sizeof buf, stdin) == NULL) + testmodeline("/quit", CurEnv); + p = strchr(buf, '\n'); + if (p != NULL) + *p = '\0'; + if (Verbose < 2) + printf("> %s\n", buf); + testmodeline(buf, CurEnv); + } + } + +#if SMTP +#endif /* SMTP */ + +#if QUEUE + /* + ** If collecting stuff from the queue, go start doing that. + */ + + if (OpMode == MD_QUEUERUN && QueueIntvl == 0) + { +# if SMTP +# endif /* SMTP */ + (void) runqueue(FALSE, Verbose); + finis(TRUE, ExitStat); + } +#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 (!run_in_foreground && !tTd(99, 100)) + { + /* put us in background */ + i = fork(); + if (i < 0) + syserr("daemon: cannot fork"); + if (i != 0) + finis(FALSE, EX_OK); + + /* disconnect from our controlling tty */ + disconnect(2, CurEnv); + } + + dtype[0] = '\0'; + if (OpMode == MD_DAEMON) + (void) strlcat(dtype, "+SMTP", sizeof dtype); + if (QueueIntvl != 0) + { + (void) strlcat(dtype, "+queueing@", sizeof dtype); + (void) strlcat(dtype, pintvl(QueueIntvl, TRUE), + sizeof dtype); + } + if (tTd(0, 1)) + (void) strlcat(dtype, "+debugging", sizeof dtype); + + sm_syslog(LOG_INFO, NOQID, + "starting daemon (%s): %s", Version, dtype + 1); +#ifdef XLA + xla_create_file(); +#endif /* XLA */ + + /* save daemon type in a macro for possible PidFile use */ + define(macid("{daemon_info}", NULL), + newstr(dtype + 1), &BlankEnvelope); + + /* save queue interval in a macro for possible PidFile use */ + define(macid("{queue_interval}", NULL), + newstr(pintvl(QueueIntvl, TRUE)), CurEnv); + +#if QUEUE + if (QueueIntvl != 0) + { + (void) runqueue(TRUE, FALSE); + if (OpMode != MD_DAEMON) + { + /* write the pid to file */ + log_sendmail_pid(CurEnv); + for (;;) + { + (void) pause(); + if (DoQueueRun) + (void) runqueue(TRUE, FALSE); + } + } + } +#endif /* QUEUE */ + dropenvelope(CurEnv, TRUE); + +#if DAEMON + p_flags = getrequests(CurEnv); + + /* drop privileges */ + (void) drop_privileges(FALSE); + + /* at this point we are in a child: reset state */ + (void) newenvelope(CurEnv, CurEnv); + + /* + ** Get authentication data + */ + + authinfo = getauthinfo(fileno(InChannel), &forged); + define('_', authinfo, &BlankEnvelope); +#endif /* DAEMON */ + } + + if (LogLevel > 9) + { + /* log connection information */ + sm_syslog(LOG_INFO, CurEnv->e_id, + "connect from %.100s", authinfo); + } + +#if SMTP + /* + ** If running SMTP protocol, start collecting and executing + ** commands. This will never return. + */ + + if (OpMode == MD_SMTP || OpMode == MD_DAEMON) + { + char pbuf[20]; + + /* + ** Save some macros for check_* rulesets. + */ + + if (forged) + { + char ipbuf[103]; + + (void) snprintf(ipbuf, sizeof ipbuf, "[%.100s]", + anynet_ntoa(&RealHostAddr)); + define(macid("{client_name}", NULL), + newstr(ipbuf), &BlankEnvelope); + define(macid("{client_resolve}", NULL), + "FORGED", &BlankEnvelope); + } + else + define(macid("{client_name}", NULL), RealHostName, + &BlankEnvelope); + define(macid("{client_addr}", NULL), + newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope); + (void)sm_getla(&BlankEnvelope); + + switch(RealHostAddr.sa.sa_family) + { +# if NETINET + case AF_INET: + (void) snprintf(pbuf, sizeof pbuf, "%d", + RealHostAddr.sin.sin_port); + break; +# endif /* NETINET */ +# if NETINET6 + case AF_INET6: + (void) snprintf(pbuf, sizeof pbuf, "%d", + RealHostAddr.sin6.sin6_port); + break; +# endif /* NETINET6 */ + default: + (void) snprintf(pbuf, sizeof pbuf, "0"); + break; + } + define(macid("{client_port}", NULL), + newstr(pbuf), &BlankEnvelope); + +#if SASL + /* give a syserr or just disable AUTH ? */ + if (sasl_server_init(srvcallbacks, "Sendmail") != SASL_OK) + syserr("!sasl_server_init failed!"); +#endif /* SASL */ + + if (OpMode == MD_DAEMON) + { + /* validate the connection */ + HoldErrs = TRUE; + nullserver = validate_connection(&RealHostAddr, + RealHostName, CurEnv); + HoldErrs = FALSE; + } + else if (p_flags == NULL) + { + p_flags = (BITMAP256 *) xalloc(sizeof *p_flags); + clrbitmap(p_flags); + } + smtp(nullserver, *p_flags, CurEnv); + } +#endif /* SMTP */ + + clearenvelope(CurEnv, FALSE); + if (OpMode == MD_VERIFY) + { + set_delivery_mode(SM_VERIFY, CurEnv); + 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); + define(macid("{ntries}", NULL), "0", CurEnv); + setsender(from, CurEnv, NULL, '\0', FALSE); + if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') && + (!bitnset(M_LOCALMAILER, CurEnv->e_from.q_mailer->m_flags) || + strcmp(CurEnv->e_from.q_user, RealUserName) != 0)) + { + auth_warning(CurEnv, "%s set sender to %s using -%c", + RealUserName, from, warn_f_flag); +#if SASL + auth = FALSE; +#endif /* SASL */ + } + if (auth) + { + char *fv; + + /* set the initial sender for AUTH= to $f@$j */ + fv = macvalue('f', CurEnv); + if (fv == NULL || *fv == '\0') + CurEnv->e_auth_param = NULL; + else + { + if (strchr(fv, '@') == NULL) + { + i = strlen(fv) + strlen(macvalue('j', CurEnv)) + + 2; + p = xalloc(i); + (void) snprintf(p, i, "%s@%s", fv, + macvalue('j', CurEnv)); + } + else + p = newstr(fv); + CurEnv->e_auth_param = newstr(xtextify(p, NULL)); + } + } + if (macvalue('s', CurEnv) == NULL) + define('s', RealHostName, CurEnv); + + if (*av == NULL && !GrabTo) + { + CurEnv->e_to = NULL; + CurEnv->e_flags |= EF_GLOBALERRS; + HoldErrs = FALSE; + usrerr("Recipient names must be specified"); + + /* collect body for UUCP return */ + if (OpMode != MD_VERIFY) + collect(InChannel, FALSE, NULL, CurEnv); + finis(TRUE, EX_USAGE); + } + + /* + ** 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; + +#if _FFR_FIX_DASHT + /* + ** If using -t, force not sending to argv recipients, even + ** if they are mentioned in the headers. + */ + + if (GrabTo) + { + ADDRESS *q; + + for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) + q->q_state = QS_REMOVED; + } +#endif /* _FFR_FIX_DASHT */ + + /* + ** Read the input mail. + */ + + CurEnv->e_to = NULL; + if (OpMode != MD_VERIFY || GrabTo) + { + int savederrors = Errors; + long savedflags = CurEnv->e_flags & EF_FATALERRS; + + CurEnv->e_flags |= EF_GLOBALERRS; + CurEnv->e_flags &= ~EF_FATALERRS; + Errors = 0; + buffer_errors(); + collect(InChannel, FALSE, NULL, CurEnv); + + /* header checks failed */ + if (Errors > 0) + { + /* Log who the mail would have gone to */ + if (LogLevel > 8 && CurEnv->e_message != NULL && + !GrabTo) + { + ADDRESS *a; + + for (a = CurEnv->e_sendqueue; + a != NULL; + a = a->q_next) + { + if (!QS_IS_UNDELIVERED(a->q_state)) + continue; + + CurEnv->e_to = a->q_paddr; + logdelivery(NULL, NULL, NULL, + CurEnv->e_message, + NULL, (time_t) 0, CurEnv); + } + CurEnv->e_to = NULL; + } + flush_errors(TRUE); + finis(TRUE, ExitStat); + /* NOTREACHED */ + return -1; + } + + /* bail out if message too large */ + if (bitset(EF_CLRQUEUE, CurEnv->e_flags)) + { + finis(TRUE, ExitStat != EX_OK ? ExitStat : EX_DATAERR); + /* NOTREACHED */ + return -1; + } + Errors = savederrors; + CurEnv->e_flags |= savedflags; + } + errno = 0; + + if (tTd(1, 1)) + dprintf("From person = \"%s\"\n", CurEnv->e_from.q_paddr); + + /* + ** Actually send everything. + ** If verifying, just ack. + */ + + CurEnv->e_from.q_state = QS_SENDER; + if (tTd(1, 5)) + { + dprintf("main: QS_SENDER "); + printaddr(&CurEnv->e_from, FALSE); + } + CurEnv->e_to = NULL; + CurrentLA = sm_getla(CurEnv); + GrabTo = FALSE; +#if NAMED_BIND + _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; + _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; +#endif /* NAMED_BIND */ + sendall(CurEnv, SM_DEFAULT); + + /* + ** All done. + ** Don't send return error message if in VERIFY mode. + */ + + finis(TRUE, ExitStat); + /* NOTREACHED */ + return ExitStat; +} + +/* ARGSUSED */ +SIGFUNC_DECL +quiesce(sig) + int sig; +{ + clear_events(); + finis(FALSE, EX_OK); +} + +/* ARGSUSED */ +SIGFUNC_DECL +intindebug(sig) + int sig; +{ + longjmp(TopFrame, 1); + return SIGFUNC_RETURN; +} + /* +** FINIS -- Clean up and exit. +** +** Parameters: +** drop -- whether or not to drop CurEnv envelope +** exitstat -- exit status to use for exit() call +** +** Returns: +** never +** +** Side Effects: +** exits sendmail +*/ + +void +finis(drop, exitstat) + bool drop; + volatile int exitstat; +{ + + if (tTd(2, 1)) + { + dprintf("\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); + + /* if we fail in finis(), just exit */ + if (setjmp(TopFrame) != 0) + { + /* failed -- just give it up */ + goto forceexit; + } + + /* clean up temp files */ + CurEnv->e_to = NULL; + if (drop) + { + if (CurEnv->e_id != NULL) + dropenvelope(CurEnv, TRUE); + else + poststats(StatFile); + } + + /* flush any cached connections */ + mci_flush(TRUE, NULL); + + /* close maps belonging to this pid */ + closemaps(); + +#if USERDB + /* close UserDatabase */ + _udbx_close(); +#endif /* USERDB */ + +#ifdef XLA + /* clean up extended load average stuff */ + xla_all_end(); +#endif /* XLA */ + + /* and exit */ + forceexit: + if (LogLevel > 78) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "finis, pid=%d", + getpid()); + if (exitstat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) + exitstat = EX_OK; + + sync_queue_time(); + + /* reset uid for process accounting */ + endpwent(); + (void) setuid(RealUid); + exit(exitstat); +} + /* +** INTSIG -- clean up on interrupt +** +** This just arranges to exit. It pessimizes in that it +** may resend a message. +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** Unlocks the current job. +*/ + +/* ARGSUSED */ +SIGFUNC_DECL +intsig(sig) + int sig; +{ + bool drop = FALSE; + + clear_events(); + if (sig != 0 && LogLevel > 79) + sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); + FileName = NULL; + closecontrolsocket(TRUE); +#ifdef XLA + xla_all_end(); +#endif /* XLA */ + + /* Clean-up on aborted stdin message submission */ + if (CurEnv->e_id != NULL && + (OpMode == MD_SMTP || + OpMode == MD_DELIVER || + OpMode == MD_ARPAFTP)) + { + register ADDRESS *q; + + /* don't return an error indication */ + CurEnv->e_to = NULL; + CurEnv->e_flags &= ~EF_FATALERRS; + CurEnv->e_flags |= EF_CLRQUEUE; + + /* + ** Spin through the addresses and + ** mark them dead to prevent bounces + */ + + for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) + q->q_state = QS_DONTSEND; + + /* and don't try to deliver the partial message either */ + if (InChild) + ExitStat = EX_QUIT; + + drop = TRUE; + } + else + unlockqueue(CurEnv); + + finis(drop, 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 /dev/null. +** 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)) + dprintf("disconnect: In %d Out %d, e=%lx\n", + fileno(InChannel), fileno(OutChannel), (u_long) e); + if (tTd(52, 100)) + { + dprintf("don't\n"); + return; + } + if (LogLevel > 93) + sm_syslog(LOG_DEBUG, e->e_id, + "disconnect level %d", + droplev); + + /* 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 = 0; + DisConnected = TRUE; + + /* all input from /dev/null */ + if (InChannel != stdin) + { + (void) fclose(InChannel); + InChannel = stdin; + } + if (freopen("/dev/null", "r", stdin) == NULL) + sm_syslog(LOG_ERR, e->e_id, + "disconnect: freopen(\"/dev/null\") failed: %s", + errstring(errno)); + + /* output to the transcript */ + if (OutChannel != stdout) + { + (void) fclose(OutChannel); + OutChannel = stdout; + } + if (droplev > 0) + { + fd = open("/dev/null", O_WRONLY, 0666); + if (fd == -1) + sm_syslog(LOG_ERR, e->e_id, + "disconnect: open(\"/dev/null\") failed: %s", + errstring(errno)); + (void) fflush(stdout); + (void) dup2(fd, STDOUT_FILENO); + (void) dup2(fd, STDERR_FILENO); + (void) close(fd); + } + + /* drop our controlling TTY completely if possible */ + if (droplev > 1) + { + (void) setsid(); + errno = 0; + } + +#if XDEBUG + checkfd012("disconnect"); +#endif /* XDEBUG */ + + if (LogLevel > 71) + sm_syslog(LOG_DEBUG, e->e_id, + "in background, pid=%d", + getpid()); + + 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 /* defined(sony_news) */ + 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); + (void) snprintf(argv[0], sizeof(__DEFPATH) + 2, "-C%s", + __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 /* defined(sony_news) */ + } +} + /* +** 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 /* __STDC__ */ +auth_warning(e, msg, va_alist) + register ENVELOPE *e; + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + char buf[MAXLINE]; + VA_LOCAL_DECL + + if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags)) + { + register char *p; + static char hostbuf[48]; + + if (hostbuf[0] == '\0') + (void) myhostname(hostbuf, sizeof hostbuf); + + (void) snprintf(buf, sizeof buf, "%s: ", hostbuf); + p = &buf[strlen(buf)]; + VA_START(msg); + vsnprintf(p, SPACELEFT(buf, p), msg, ap); + VA_END; + addheader("X-Authentication-Warning", buf, &e->e_header); + if (LogLevel > 3) + sm_syslog(LOG_INFO, e->e_id, + "Authentication-Warning: %.400s", + buf); + } +} + /* +** GETEXTENV -- get from external environment +** +** Parameters: +** envar -- the name of the variable to retrieve +** +** Returns: +** The value, if any. +*/ + +char * +getextenv(envar) + const char *envar; +{ + char **envp; + int l; + + l = strlen(envar); + for (envp = ExternalEnviron; *envp != NULL; envp++) + { + if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=') + return &(*envp)[l + 1]; + } + return NULL; +} + /* +** 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, l; + char **evp = UserEnviron; + char *p; + + if (value == NULL) + { + value = getextenv(envar); + if (value == NULL) + return; + } + + i = strlen(envar) + 1; + l = strlen(value) + i + 1; + p = (char *) xalloc(l); + (void) snprintf(p, l, "%s=%s", envar, 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; +{ + register char *j = macvalue('j', CurEnv); + int rs; + extern int NextMacroId; + + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "--- dumping state on %s: $j = %s ---", + when, + j == NULL ? "" : j); + if (j != NULL) + { + if (!wordinclass(j, 'w')) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "*** $j not in $=w ***"); + } + sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)\n", + NextMacroId, MAXMACROID); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---"); + printopenfds(TRUE); + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---"); + mci_dump_all(TRUE); + rs = strtorwset("debug_dumpstate", NULL, ST_FIND); + if (rs > 0) + { + int status; + register char **pvp; + char *pv[MAXATOM + 1]; + + pv[0] = NULL; + status = rewrite(pv, rs, 0, CurEnv); + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "--- ruleset debug_dumpstate returns stat %d, pv: ---", + status); + for (pvp = pv; *pvp != NULL; pvp++) + sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp); + } + sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---"); +} + + +/* ARGSUSED */ +SIGFUNC_DECL +sigusr1(sig) + int sig; +{ + dumpstate("user signal"); + return SIGFUNC_RETURN; +} + + +/* ARGSUSED */ +SIGFUNC_DECL +sighup(sig) + int sig; +{ + int i; + extern int DtableSize; + + clear_events(); + (void) alarm(0); + if (SaveArgv[0][0] != '/') + { + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, + "could not restart: need full path"); + finis(FALSE, EX_OSFILE); + } + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, "restarting %s %s", + sig == 0 ? "due to control command" : "on signal", + SaveArgv[0]); + + /* Control socket restart? */ + if (sig != 0) + (void) releasesignal(SIGHUP); + + closecontrolsocket(TRUE); + if (drop_privileges(TRUE) != EX_OK) + { + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "could not set[ug]id(%d, %d): %m", + RunAsUid, RunAsGid); + finis(FALSE, EX_OSERR); + } + + /* 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 | FD_CLOEXEC); + } + + (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", + SaveArgv[0]); + finis(FALSE, EX_OSFILE); +} + /* +** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option +** +** Parameters: +** to_real_uid -- if set, drop to the real uid instead +** of the RunAsUser. +** +** Returns: +** EX_OSERR if the setuid failed. +** EX_OK otherwise. +*/ + +int +drop_privileges(to_real_uid) + bool to_real_uid; +{ + int rval = EX_OK; + GIDSET_T emptygidset[1]; + + if (tTd(47, 1)) + dprintf("drop_privileges(%d): Real[UG]id=%d:%d, RunAs[UG]id=%d:%d\n", + (int)to_real_uid, (int)RealUid, (int)RealGid, (int)RunAsUid, (int)RunAsGid); + + if (to_real_uid) + { + RunAsUserName = RealUserName; + RunAsUid = RealUid; + RunAsGid = RealGid; + } + + /* make sure no one can grab open descriptors for secret files */ + endpwent(); + + /* reset group permissions; these can be set later */ + emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid(); + if (setgroups(1, emptygidset) == -1 && geteuid() == 0) + rval = EX_OSERR; + + /* reset primary group and user id */ + if ((to_real_uid || RunAsGid != 0) && setgid(RunAsGid) < 0) + rval = EX_OSERR; + if ((to_real_uid || RunAsUid != 0) && setuid(RunAsUid) < 0) + rval = EX_OSERR; + if (tTd(47, 5)) + { + dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n", + (int)geteuid(), (int)getuid(), (int)getegid(), (int)getgid()); + dprintf("drop_privileges: RunAsUser = %d:%d\n", + (int)RunAsUid, (int)RunAsGid); + } + return rval; +} + /* +** FILL_FD -- make sure a file descriptor has been properly allocated +** +** Used to make sure that stdin/out/err are allocated on startup +** +** Parameters: +** fd -- the file descriptor to be filled. +** where -- a string used for logging. If NULL, this is +** being called on startup, and logging should +** not be done. +** +** Returns: +** none +*/ + +void +fill_fd(fd, where) + int fd; + char *where; +{ + int i; + struct stat stbuf; + + if (fstat(fd, &stbuf) >= 0 || errno != EBADF) + return; + + if (where != NULL) + syserr("fill_fd: %s: fd %d not open", where, fd); + else + MissingFds |= 1 << fd; + i = open("/dev/null", fd == 0 ? O_RDONLY : O_WRONLY, 0666); + if (i < 0) + { + syserr("!fill_fd: %s: cannot open /dev/null", + where == NULL ? "startup" : where); + } + if (fd != i) + { + (void) dup2(i, fd); + (void) close(i); + } +} + /* +** 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 +*/ + +static 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 u_char TokTypeNoC[]; + +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e r", e); +#endif /* _FFR_ADDR_TYPE */ + switch (line[0]) + { + case '#': + case '\0': + return; + + case '?': + help("-bt", e); + 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) + { + printf("Undefined ruleset %s\n", &line[2]); + return; + } + rw = RewriteRules[rs]; + if (rw == NULL) + return; + do + { + (void) putchar('R'); + s = rw->r_lhs; + while (*s != NULL) + { + xputs(*s++); + (void) putchar(' '); + } + (void) putchar('\t'); + (void) putchar('\t'); + s = rw->r_rhs; + while (*s != NULL) + { + xputs(*s++); + (void) putchar(' '); + } + (void) putchar('\n'); + } while ((rw = rw->r_next) != NULL); + 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], "quit") == 0) + { + CurEnv->e_id = NULL; + finis(TRUE, ExitStat); + } + 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, NULL, 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 /* NAMED_BIND */ + printf("No MX code compiled in\n"); +#endif /* NAMED_BIND */ + } + else if (strcasecmp(&line[1], "canon") == 0) + { + char host[MAXHOSTNAMELEN]; + + if (*p == '\0') + { + printf("Usage: /canon address\n"); + return; + } + else if (strlcpy(host, p, sizeof host) >= sizeof host) + { + printf("Name too long\n"); + return; + } + (void) getcanonname(host, sizeof host, HasWildcardMX); + printf("getcanonname(%s) returns %s\n", p, host); + } + else if (strcasecmp(&line[1], "map") == 0) + { + auto int rcode = EX_OK; + char *av[2]; + + if (*p == '\0') + { + printf("Usage: /map mapname key\n"); + return; + } + for (q = p; *q != '\0' && !(isascii(*q) && 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; + } + if (!bitset(MF_OPEN, map->s_map.map_mflags) && + !openmap(&(map->s_map))) + { + printf("Map named \"%s\" not open\n", p); + return; + } + printf("map_lookup: %s (%s) ", p, q); + av[0] = q; + av[1] = NULL; + p = (*map->s_map.map_class->map_lookup) + (&map->s_map, q, av, &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 *st; + 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; + } + st = stab(p, ST_MAILER, ST_FIND); + if (st == NULL) + { + printf("Unknown mailer %s\n", p); + return; + } + m = st->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 ? "" : p); + e->e_to = NULL; + } + 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; + } + } +#if _FFR_ADDR_TYPE + exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e'; + exbuf[1] = ' '; + exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r'; + exbuf[3] = '\0'; + define(macid("{addr_type}", NULL), newstr(exbuf), e); +#endif /* _FFR_ADDR_TYPE */ + } + 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); + e->e_to = NULL; + } + 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, ConfigLevel >= 9 ? TokTypeNoC : NULL); + if (pvp == NULL) + continue; + p = q; + while (*p != '\0') + { + int status; + + rs = strtorwset(p, NULL, ST_FIND); + if (rs < 0) + { + printf("Undefined ruleset %s\n", p); + break; + } + status = rewrite(pvp, rs, 0, e); + if (status != EX_OK) + printf("== Ruleset %s (%d) status %d\n", + p, rs, status); + while (*p != '\0' && *p++ != ',') + continue; + } + } while (*(p = delimptr) != '\0'); +} + +static 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/gnu/usr.sbin/sendmail/sendmail/makesendmail b/gnu/usr.sbin/sendmail/sendmail/makesendmail new file mode 100644 index 00000000000..4fe77fd8e11 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/makesendmail @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: makesendmail,v 8.4 1999/04/04 07:01:42 gshapiro Exp $ + +exec ./Build $* diff --git a/gnu/usr.sbin/sendmail/sendmail/map.c b/gnu/usr.sbin/sendmail/sendmail/map.c new file mode 100644 index 00000000000..6dfa7805b45 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/map.c @@ -0,0 +1,7131 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1992, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: map.c,v 8.413 2000/02/26 05:35:01 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +#ifdef NDBM +# include +# ifdef R_FIRST + ERROR README: You are running the Berkeley DB version of ndbm.h. See + ERROR README: the README file about tweaking Berkeley DB so it can + ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile + ERROR README: and use -DNEWDB instead. +# endif /* R_FIRST */ +#endif /* NDBM */ +#ifdef NEWDB +# include +# ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +# endif /* ! DB_VERSION_MAJOR */ +#endif /* NEWDB */ +#ifdef NIS + struct dom_binding; /* forward reference needed on IRIX */ +# include +# ifdef NDBM +# define NDBM_YP_COMPAT /* create YP-compatible NDBM files */ +# endif /* NDBM */ +#endif /* NIS */ + +#ifdef NEWDB +# if DB_VERSION_MAJOR < 2 +static bool db_map_open __P((MAP *, int, char *, DBTYPE, const void *)); +# endif /* DB_VERSION_MAJOR < 2 */ +# if DB_VERSION_MAJOR == 2 +static bool db_map_open __P((MAP *, int, char *, DBTYPE, DB_INFO *)); +# endif /* DB_VERSION_MAJOR == 2 */ +# if DB_VERSION_MAJOR > 2 +static bool db_map_open __P((MAP *, int, char *, DBTYPE, void **)); +# endif /* DB_VERSION_MAJOR > 2 */ +#endif /* NEWDB */ +static bool extract_canonname __P((char *, char *, char[], int)); +#ifdef LDAPMAP +static void ldapmap_clear __P((LDAPMAP_STRUCT *)); +static STAB *ldapmap_findconn __P((LDAPMAP_STRUCT *)); +static int ldapmap_geterrno __P((LDAP *)); +static void ldapmap_setopts __P((LDAP *, LDAPMAP_STRUCT *)); +static bool ldapmap_start __P((MAP *)); +static void ldaptimeout __P((int)); +#endif /* LDAPMAP */ +static void map_close __P((STAB *, int)); +static void map_init __P((STAB *, int)); +#ifdef NISPLUS +static bool nisplus_getcanonname __P((char *, int, int *)); +#endif /* NISPLUS */ +#ifdef NIS +static bool nis_getcanonname __P((char *, int, int *)); +#endif /* NIS */ +#if NETINFO +static bool ni_getcanonname __P((char *, int, int *)); +#endif /* NETINFO */ +static bool text_getcanonname __P((char *, int, int *)); + +/* +** 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 + +#ifndef EX_NOTFOUND +# define EX_NOTFOUND EX_NOHOST +#endif /* ! EX_NOTFOUND */ + +#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL +# define LOCK_ON_OPEN 1 /* we can open/create a locked file */ +#else /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ +# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */ +#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif /* ! O_ACCMODE */ + /* +** 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; + + /* + ** there is no check whether there is really an argument, + ** but that's not important enough to warrant extra code + */ + map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; + map->map_spacesub = SpaceSub; /* default value */ + 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 'T': + map->map_tapp = ++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; + + case 't': + map->map_mflags |= MF_NODEFER; + break; + + case 'S': + map->map_spacesub = *++p; + break; + + case 'D': + map->map_mflags |= MF_DEFER; + break; + + default: + syserr("Illegal option %c map %s", *p, map->map_mname); + break; + } + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + if (map->map_app != NULL) + map->map_app = newstr(map->map_app); + if (map->map_tapp != NULL) + map->map_tapp = newstr(map->map_tapp); + 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 const char *s; + size_t slen; + char **av; +{ + register char *bp; + register char c; + char **avp; + register char *ap; + size_t l; + size_t len; + static size_t buflen = 0; + static char *buf = NULL; + + if (tTd(39, 1)) + { + dprintf("map_rewrite(%.*s), av =", (int)slen, s); + if (av == NULL) + dprintf(" (nullv)"); + else + { + for (avp = av; *avp != NULL; avp++) + dprintf("\n\t%s", *avp); + } + dprintf("\n"); + } + + /* count expected size of output (can safely overestimate) */ + l = len = slen; + if (av != NULL) + { + const char *sp = s; + + while (l-- > 0 && (c = *sp++) != '\0') + { + if (c != '%') + continue; + if (l-- <= 0) + break; + c = *sp++; + 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) + { + memmove(bp, s, slen); + bp += slen; + + /* assert(len > slen); */ + len -= slen; + } + else + { + while (slen-- > 0 && (c = *s++) != '\0') + { + if (c != '%') + { + pushc: + if (--len <= 0) + break; + *bp++ = c; + continue; + } + if (slen-- <= 0 || (c = *s++) == '\0') + c = '%'; + if (c == '%') + goto pushc; + if (!(isascii(c) && isdigit(c))) + { + *bp++ = '%'; + --len; + 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' && len > 0; --len) + *bp++ = c; + } + } + if (map->map_app != NULL && len > 0) + (void) strlcpy(bp, map->map_app, len); + else + *bp = '\0'; + if (tTd(39, 1)) + dprintf("map_rewrite => %s\n", buf); + return buf; +} + /* +** INITMAPS -- rebuild alias maps +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +initmaps() +{ +#if XDEBUG + checkfd012("entering initmaps"); +#endif /* XDEBUG */ + stabapply(map_init, 0); +#if XDEBUG + checkfd012("exiting initmaps"); +#endif /* XDEBUG */ +} + /* +** MAP_INIT -- rebuild a map +** +** Parameters: +** s -- STAB entry: if map: try to rebuild +** unused -- unused variable +** +** Returns: +** none. +** +** Side Effects: +** will close already open rebuildable map. +*/ + +/* ARGSUSED1 */ +static void +map_init(s, unused) + register STAB *s; + int unused; +{ + 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)) + dprintf("map_init(%s:%s, %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); + + if (!bitset(MF_ALIAS, map->map_mflags) || + !bitset(MCF_REBUILDABLE, map->map_class->map_cflags)) + { + if (tTd(38, 3)) + dprintf("\tnot rebuildable\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); + } + + (void) rebuildaliases(map, FALSE); + return; +} + /* +** OPENMAP -- open a map +** +** Parameters: +** map -- map to open (it must not be open). +** +** Returns: +** whether open succeeded. +** +*/ + +bool +openmap(map) + MAP *map; +{ + bool restore = FALSE; + bool savehold = HoldErrs; + bool savequick = QuickAbort; + int saveerrors = Errors; + + if (!bitset(MF_VALID, map->map_mflags)) + return FALSE; + + /* better safe than sorry... */ + if (bitset(MF_OPEN, map->map_mflags)) + return TRUE; + + /* Don't send a map open error out via SMTP */ + if ((OnlyOneError || QuickAbort) && + (OpMode == MD_SMTP || OpMode == MD_DAEMON)) + { + restore = TRUE; + HoldErrs = TRUE; + QuickAbort = FALSE; + } + + errno = 0; + if (map->map_class->map_open(map, O_RDONLY)) + { + if (tTd(38, 4)) + dprintf("openmap()\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; + map->map_pid = getpid(); + } + else + { + if (tTd(38, 4)) + dprintf("openmap()\t%s:%s %s: invalid%s%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, + errno == 0 ? "" : ": ", + errno == 0 ? "" : errstring(errno)); + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + extern MAPCLASS BogusMapClass; + + map->map_class = &BogusMapClass; + map->map_mflags |= MF_OPEN; + map->map_pid = getpid(); + } + else + { + /* don't try again */ + map->map_mflags &= ~MF_VALID; + } + } + + if (restore) + { + Errors = saveerrors; + HoldErrs = savehold; + QuickAbort = savequick; + } + + return bitset(MF_OPEN, map->map_mflags); +} + /* +** CLOSEMAPS -- close all open maps opened by the current pid. +** +** Parameters: +** none +** +** Returns: +** none. +*/ + +void +closemaps() +{ + stabapply(map_close, 0); +} + /* +** MAP_CLOSE -- close a map opened by the current pid. +** +** Parameters: +** s -- STAB entry: if map: try to open +** second parameter is unused (required by stabapply()) +** +** Returns: +** none. +*/ + +/* ARGSUSED1 */ +static void +map_close(s, unused) + register STAB *s; + int unused; +{ + MAP *map; + + if (s->s_type != ST_MAP) + return; + + map = &s->s_map; + + if (!bitset(MF_VALID, map->map_mflags) || + !bitset(MF_OPEN, map->map_mflags) || + map->map_pid != getpid()) + return; + + if (tTd(38, 5)) + dprintf("closemaps: closing %s (%s)\n", + map->map_mname == NULL ? "NULL" : map->map_mname, + map->map_file == NULL ? "NULL" : map->map_file); + + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); +} + /* +** 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 status; + 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)) + dprintf("getcanonname(%s), trying %s\n", + host, maptype[mapno]); + if (strcmp("files", maptype[mapno]) == 0) + { + found = text_getcanonname(host, hbsize, &status); + } +#ifdef NIS + else if (strcmp("nis", maptype[mapno]) == 0) + { + found = nis_getcanonname(host, hbsize, &status); + } +#endif /* NIS */ +#ifdef NISPLUS + else if (strcmp("nisplus", maptype[mapno]) == 0) + { + found = nisplus_getcanonname(host, hbsize, &status); + } +#endif /* NISPLUS */ +#if NAMED_BIND + else if (strcmp("dns", maptype[mapno]) == 0) + { + found = dns_getcanonname(host, hbsize, trymx, &status); + } +#endif /* NAMED_BIND */ +#if NETINFO + else if (strcmp("netinfo", maptype[mapno]) == 0) + { + found = ni_getcanonname(host, hbsize, &status); + } +#endif /* NETINFO */ + else + { + found = FALSE; + status = 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 (status == EX_TEMPFAIL) + { + i = MA_TRYAGAIN; + got_tempfail = TRUE; + } + else if (status == EX_NOTFOUND) + i = MA_NOTFOUND; + else + i = MA_UNAVAIL; + if (bitset(1 << mapno, mapreturn[i])) + break; + } + + if (found) + { + char *d; + + if (tTd(38, 20)) + dprintf("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] != '.') + (void) strlcat(host, ".", hbsize); + (void) strlcat(host, d, hbsize); + } + else + return FALSE; + } + return TRUE; + } + + if (tTd(38, 20)) + dprintf("getcanonname(%s), failed, status=%d\n", host, status); + +#if NAMED_BIND + if (got_tempfail) + h_errno = TRY_AGAIN; + else + h_errno = HOST_NOT_FOUND; +#endif /* NAMED_BIND */ + + 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. +** cbuflen -- the size of cbuf. +** +** Returns: +** TRUE -- if the line matched the desired name. +** FALSE -- otherwise. +*/ + +static bool +extract_canonname(name, line, cbuf, cbuflen) + char *name; + char *line; + char cbuf[]; + int cbuflen; +{ + int i; + char *p; + bool found = FALSE; + + cbuf[0] = '\0'; + if (line[0] == '#') + return FALSE; + + for (i = 1; ; i++) + { + char nbuf[MAXNAME + 1]; + + p = get_column(line, i, '\0', nbuf, sizeof nbuf); + if (p == NULL) + break; + if (*p == '\0') + continue; + if (cbuf[0] == '\0' || + (strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL)) + { + snprintf(cbuf, cbuflen, "%s", 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) + (i = strlen(cbuf)) + 1 < cbuflen) + { + p = &cbuf[i]; + *p++ = '.'; + (void) strlcpy(p, domain, cbuflen - i - 1); + } + } + return found; +} + /* +** NDBM modules +*/ + +#ifdef NDBM + +/* +** NDBM_MAP_OPEN -- DBM-style map open +*/ + +bool +ndbm_map_open(map, mode) + MAP *map; + int mode; +{ + register DBM *dbm; + int save_errno; + int dfd; + int pfd; + long sff; + int ret; + int smode = S_IREAD; + char dirfile[MAXNAME + 1]; + char pagfile[MAXNAME + 1]; + struct stat st; + struct stat std, stp; + + if (tTd(38, 2)) + dprintf("ndbm_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + map->map_lockfd = -1; + mode &= O_ACCMODE; + + /* do initial file and directory checks */ + snprintf(dirfile, sizeof dirfile, "%s.dir", map->map_file); + snprintf(pagfile, sizeof pagfile, "%s.pag", map->map_file); + sff = SFF_ROOTOK|SFF_REGONLY; + if (mode == O_RDWR) + { + sff |= SFF_CREAT; + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + smode = S_IWRITE; + } + else + { + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + } + if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + ret = safefile(dirfile, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &std); + if (ret == 0) + ret = safefile(pagfile, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &stp); + +# if !_FFR_REMOVE_AUTOREBUILD + if (ret == ENOENT && AutoRebuild && + bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && + (bitset(MF_IMPL_NDBM, map->map_mflags) || + bitset(MF_ALIAS, map->map_mflags)) && + mode == O_RDONLY) + { + bool impl = bitset(MF_IMPL_NDBM, map->map_mflags); + + /* may be able to rebuild */ + map->map_mflags &= ~MF_IMPL_NDBM; + if (!rebuildaliases(map, TRUE)) + return FALSE; + if (impl) + return impl_map_open(map, O_RDONLY); + else + return ndbm_map_open(map, O_RDONLY); + } +# endif /* !_FFR_REMOVE_AUTOREBUILD */ + + if (ret != 0) + { + char *prob = "unsafe"; + + /* cannot open this map */ + if (ret == ENOENT) + prob = "missing"; + if (tTd(38, 2)) + dprintf("\t%s map file: %d\n", prob, ret); + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("dbm map \"%s\": %s map file %s", + map->map_mname, prob, map->map_file); + return FALSE; + } + if (std.st_mode == ST_MODE_NOFILE) + mode |= O_CREAT|O_EXCL; + +# if LOCK_ON_OPEN + if (mode == O_RDONLY) + mode |= O_SHLOCK; + else + mode |= O_TRUNC|O_EXLOCK; +# else /* LOCK_ON_OPEN */ + if ((mode & O_ACCMODE) == O_RDWR) + { +# if NOFTRUNCATE + /* + ** Warning: race condition. Try to lock the file as + ** quickly as possible after opening it. + ** This may also have security problems on some systems, + ** but there isn't anything we can do about it. + */ + + mode |= O_TRUNC; +# else /* NOFTRUNCATE */ + /* + ** This ugly code opens the map without truncating it, + ** locks the file, then truncates it. Necessary to + ** avoid race conditions. + */ + + int dirfd; + int pagfd; + long sff = SFF_CREAT|SFF_OPENASROOT; + + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + + dirfd = safeopen(dirfile, mode, DBMMODE, sff); + pagfd = safeopen(pagfile, mode, DBMMODE, sff); + + if (dirfd < 0 || pagfd < 0) + { + save_errno = errno; + if (dirfd >= 0) + (void) close(dirfd); + if (pagfd >= 0) + (void) close(pagfd); + errno = save_errno; + syserr("ndbm_map_open: cannot create database %s", + map->map_file); + return FALSE; + } + if (ftruncate(dirfd, (off_t) 0) < 0 || + ftruncate(pagfd, (off_t) 0) < 0) + { + save_errno = errno; + (void) close(dirfd); + (void) close(pagfd); + errno = save_errno; + syserr("ndbm_map_open: cannot truncate %s.{dir,pag}", + map->map_file); + return FALSE; + } + + /* if new file, get "before" bits for later filechanged check */ + if (std.st_mode == ST_MODE_NOFILE && + (fstat(dirfd, &std) < 0 || fstat(pagfd, &stp) < 0)) + { + save_errno = errno; + (void) close(dirfd); + (void) close(pagfd); + errno = save_errno; + syserr("ndbm_map_open(%s.{dir,pag}): cannot fstat pre-opened file", + map->map_file); + return FALSE; + } + + /* have to save the lock for the duration (bletch) */ + map->map_lockfd = dirfd; + (void) close(pagfd); + + /* twiddle bits for dbm_open */ + mode &= ~(O_CREAT|O_EXCL); +# endif /* NOFTRUNCATE */ + } +# endif /* LOCK_ON_OPEN */ + + /* open the database */ + dbm = dbm_open(map->map_file, mode, DBMMODE); + if (dbm == NULL) + { + save_errno = errno; + if (bitset(MF_ALIAS, map->map_mflags) && + aliaswait(map, ".pag", FALSE)) + return TRUE; +# if !LOCK_ON_OPEN && !NOFTRUNCATE + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ + errno = save_errno; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot open DBM database %s", map->map_file); + return FALSE; + } + dfd = dbm_dirfno(dbm); + pfd = dbm_pagfno(dbm); + if (dfd == pfd) + { + /* heuristic: if files are linked, this is actually gdbm */ + dbm_close(dbm); +# if !LOCK_ON_OPEN && !NOFTRUNCATE + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ + errno = 0; + syserr("dbm map \"%s\": cannot support GDBM", + map->map_mname); + return FALSE; + } + + if (filechanged(dirfile, dfd, &std) || + filechanged(pagfile, pfd, &stp)) + { + save_errno = errno; + dbm_close(dbm); +# if !LOCK_ON_OPEN && !NOFTRUNCATE + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN && !NOFTRUNCATE */ + errno = save_errno; + syserr("ndbm_map_open(%s): file changed after open", + map->map_file); + return FALSE; + } + + map->map_db1 = (ARBPTR_T) dbm; + + /* + ** Need to set map_mtime before the call to aliaswait() + ** as aliaswait() will call map_lookup() which requires + ** map_mtime to be set + */ + + if (fstat(dfd, &st) >= 0) + map->map_mtime = st.st_mtime; + + if (mode == O_RDONLY) + { +# if LOCK_ON_OPEN + if (dfd >= 0) + (void) lockfile(dfd, map->map_file, ".dir", LOCK_UN); + if (pfd >= 0) + (void) lockfile(pfd, map->map_file, ".pag", LOCK_UN); +# endif /* LOCK_ON_OPEN */ + if (bitset(MF_ALIAS, map->map_mflags) && + !aliaswait(map, ".pag", TRUE)) + return FALSE; + } + else + { + map->map_mflags |= MF_LOCKED; + if (geteuid() == 0 && TrustedUid != 0) + { +# if HASFCHOWN + if (fchown(dfd, TrustedUid, -1) < 0 || + fchown(pfd, TrustedUid, -1) < 0) + { + int err = errno; + + sm_syslog(LOG_ALERT, NOQID, + "ownership change on %s failed: %s", + map->map_file, errstring(err)); + message("050 ownership change on %s failed: %s", + map->map_file, errstring(err)); + } +# endif /* HASFCHOWN */ + } + } + return TRUE; +} + + +/* +** NDBM_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]; + struct stat stbuf; + + if (tTd(38, 20)) + dprintf("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; + memmove(keybuf, key.dptr, key.dsize); + keybuf[key.dsize] = '\0'; + makelower(keybuf); + key.dptr = keybuf; + } +lockdbm: + 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); + if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) + { + /* Reopen the database to sync the cache */ + int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR + : O_RDONLY; + + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, map->map_file, ".dir", LOCK_UN); + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + if (map->map_class->map_open(map, omode)) + { + map->map_mflags |= MF_OPEN; + map->map_pid = getpid(); + if ((omode && O_ACCMODE) == O_RDWR) + map->map_mflags |= MF_WRITABLE; + goto lockdbm; + } + else + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + extern MAPCLASS BogusMapClass; + + *statp = EX_TEMPFAIL; + map->map_class = &BogusMapClass; + map->map_mflags |= MF_OPEN; + map->map_pid = getpid(); + syserr("Cannot reopen NDBM database %s", + map->map_file); + } + return NULL; + } + } + 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); +} + + +/* +** NDBM_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 status; + char keybuf[MAXNAME + 1]; + + if (tTd(38, 12)) + dprintf("ndbm_map_store(%s, %s, %s)\n", + map->map_mname, lhs, rhs); + + key.dsize = strlen(lhs); + key.dptr = lhs; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + { + if (key.dsize > sizeof keybuf - 1) + key.dsize = sizeof keybuf - 1; + memmove(keybuf, key.dptr, key.dsize); + keybuf[key.dsize] = '\0'; + makelower(keybuf); + key.dptr = keybuf; + } + + data.dsize = strlen(rhs); + data.dptr = rhs; + + if (bitset(MF_INCLNULL, map->map_mflags)) + { + key.dsize++; + data.dsize++; + } + + status = dbm_store((DBM *) map->map_db1, key, data, DBM_INSERT); + if (status > 0) + { + if (!bitset(MF_APPEND, map->map_mflags)) + message("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, + (char **)NULL, &xstat); + if (old.dptr != NULL && *(char *) 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); + } + snprintf(buf, bufsiz, "%s,%s", + data.dptr, old.dptr); + data.dsize = data.dsize + old.dsize + 1; + data.dptr = buf; + if (tTd(38, 9)) + dprintf("ndbm_map_store append=%s\n", + data.dptr); + } + } + status = dbm_store((DBM *) map->map_db1, + key, data, DBM_REPLACE); + } + if (status != 0) + syserr("readaliases: dbm put (%s): %d", lhs, status); +} + + +/* +** NDBM_MAP_CLOSE -- close the database +*/ + +void +ndbm_map_close(map) + register MAP *map; +{ + if (tTd(38, 9)) + dprintf("ndbm_map_close(%s, %s, %lx)\n", + map->map_mname, map->map_file, map->map_mflags); + + if (bitset(MF_WRITABLE, map->map_mflags)) + { +# ifdef NDBM_YP_COMPAT + bool inclnull; + char buf[MAXHOSTNAMELEN]; + + inclnull = bitset(MF_INCLNULL, map->map_mflags); + map->map_mflags &= ~MF_INCLNULL; + + if (strstr(map->map_file, "/yp/") != NULL) + { + long save_mflags = map->map_mflags; + + map->map_mflags |= MF_NOFOLDCASE; + + (void) snprintf(buf, sizeof buf, "%010ld", curtime()); + ndbm_map_store(map, "YP_LAST_MODIFIED", buf); + + (void) gethostname(buf, sizeof buf); + ndbm_map_store(map, "YP_MASTER_NAME", buf); + + map->map_mflags = save_mflags; + } + + if (inclnull) + map->map_mflags |= MF_INCLNULL; +# endif /* NDBM_YP_COMPAT */ + + /* write out the distinguished alias */ + ndbm_map_store(map, "@", "@"); + } + dbm_close((DBM *) map->map_db1); + + /* release lock (if needed) */ +# if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN */ +} + +#endif /* NDBM */ + /* +** 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. +*/ + +/* these should be K line arguments */ +# if DB_VERSION_MAJOR < 2 +# define db_cachesize cachesize +# define h_nelem nelem +# ifndef DB_CACHE_SIZE +# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */ +# endif /* ! DB_CACHE_SIZE */ +# ifndef DB_HASH_NELEM +# define DB_HASH_NELEM 4096 /* (starting) size of hash table */ +# endif /* ! DB_HASH_NELEM */ +# endif /* DB_VERSION_MAJOR < 2 */ + +bool +bt_map_open(map, mode) + MAP *map; + int mode; +{ +# if DB_VERSION_MAJOR < 2 + BTREEINFO btinfo; +# endif /* DB_VERSION_MAJOR < 2 */ +# if DB_VERSION_MAJOR == 2 + DB_INFO btinfo; +# endif /* DB_VERSION_MAJOR == 2 */ +# if DB_VERSION_MAJOR > 2 + void *btinfo = NULL; +# endif /* DB_VERSION_MAJOR > 2 */ + + if (tTd(38, 2)) + dprintf("bt_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + +# if DB_VERSION_MAJOR < 3 + memset(&btinfo, '\0', sizeof btinfo); +# ifdef DB_CACHE_SIZE + btinfo.db_cachesize = DB_CACHE_SIZE; +# endif /* DB_CACHE_SIZE */ +# endif /* DB_VERSION_MAJOR < 3 */ + + return db_map_open(map, mode, "btree", DB_BTREE, &btinfo); +} + +bool +hash_map_open(map, mode) + MAP *map; + int mode; +{ +# if DB_VERSION_MAJOR < 2 + HASHINFO hinfo; +# endif /* DB_VERSION_MAJOR < 2 */ +# if DB_VERSION_MAJOR == 2 + DB_INFO hinfo; +# endif /* DB_VERSION_MAJOR == 2 */ +# if DB_VERSION_MAJOR > 2 + void *hinfo = NULL; +# endif /* DB_VERSION_MAJOR > 2 */ + + if (tTd(38, 2)) + dprintf("hash_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + +# if DB_VERSION_MAJOR < 3 + memset(&hinfo, '\0', sizeof hinfo); +# ifdef DB_HASH_NELEM + hinfo.h_nelem = DB_HASH_NELEM; +# endif /* DB_HASH_NELEM */ +# ifdef DB_CACHE_SIZE + hinfo.db_cachesize = DB_CACHE_SIZE; +# endif /* DB_CACHE_SIZE */ +# endif /* DB_VERSION_MAJOR < 3 */ + + return db_map_open(map, mode, "hash", DB_HASH, &hinfo); +} + +static bool +db_map_open(map, mode, mapclassname, dbtype, openinfo) + MAP *map; + int mode; + char *mapclassname; + DBTYPE dbtype; +# if DB_VERSION_MAJOR < 2 + const void *openinfo; +# endif /* DB_VERSION_MAJOR < 2 */ +# if DB_VERSION_MAJOR == 2 + DB_INFO *openinfo; +# endif /* DB_VERSION_MAJOR == 2 */ +# if DB_VERSION_MAJOR > 2 + void **openinfo; +# endif /* DB_VERSION_MAJOR > 2 */ +{ + DB *db = NULL; + int i; + int omode; + int smode = S_IREAD; + int fd; + long sff; + int save_errno; + struct stat st; + char buf[MAXNAME + 1]; + + /* do initial file and directory checks */ + (void) strlcpy(buf, map->map_file, sizeof buf - 3); + i = strlen(buf); + if (i < 3 || strcmp(&buf[i - 3], ".db") != 0) + (void) strlcat(buf, ".db", sizeof buf); + + mode &= O_ACCMODE; + omode = mode; + + sff = SFF_ROOTOK|SFF_REGONLY; + if (mode == O_RDWR) + { + sff |= SFF_CREAT; + if (!bitnset(DBS_WRITEMAPTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITEMAPTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + smode = S_IWRITE; + } + else + { + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + } + if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + i = safefile(buf, RunAsUid, RunAsGid, RunAsUserName, sff, smode, &st); + +# if !_FFR_REMOVE_AUTOREBUILD + if (i == ENOENT && AutoRebuild && + bitset(MCF_REBUILDABLE, map->map_class->map_cflags) && + (bitset(MF_IMPL_HASH, map->map_mflags) || + bitset(MF_ALIAS, map->map_mflags)) && + mode == O_RDONLY) + { + bool impl = bitset(MF_IMPL_HASH, map->map_mflags); + + /* may be able to rebuild */ + map->map_mflags &= ~MF_IMPL_HASH; + if (!rebuildaliases(map, TRUE)) + return FALSE; + if (impl) + return impl_map_open(map, O_RDONLY); + else + return db_map_open(map, O_RDONLY, mapclassname, + dbtype, openinfo); + } +# endif /* !_FFR_REMOVE_AUTOREBUILD */ + + if (i != 0) + { + char *prob = "unsafe"; + + /* cannot open this map */ + if (i == ENOENT) + prob = "missing"; + if (tTd(38, 2)) + dprintf("\t%s map file: %s\n", prob, errstring(i)); + errno = i; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("%s map \"%s\": %s map file %s", + mapclassname, map->map_mname, prob, buf); + return FALSE; + } + if (st.st_mode == ST_MODE_NOFILE) + omode |= O_CREAT|O_EXCL; + + map->map_lockfd = -1; + +# if LOCK_ON_OPEN + if (mode == O_RDWR) + omode |= O_TRUNC|O_EXLOCK; + else + omode |= O_SHLOCK; +# else /* LOCK_ON_OPEN */ + /* + ** 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) + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("db_map_open: cannot pre-open database %s", buf); + return FALSE; + } + + /* make sure no baddies slipped in just before the open... */ + if (filechanged(buf, fd, &st)) + { + save_errno = errno; + (void) close(fd); + errno = save_errno; + syserr("db_map_open(%s): file changed after pre-open", buf); + return FALSE; + } + + /* if new file, get the "before" bits for later filechanged check */ + if (st.st_mode == ST_MODE_NOFILE && fstat(fd, &st) < 0) + { + save_errno = errno; + (void) close(fd); + errno = save_errno; + syserr("db_map_open(%s): cannot fstat pre-opened file", + buf); + return FALSE; + } + + /* actually lock the pre-opened file */ + if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX)) + syserr("db_map_open: cannot lock %s", buf); + + /* set up mode bits for dbopen */ + if (mode == O_RDWR) + omode |= O_TRUNC; + omode &= ~(O_EXCL|O_CREAT); +# endif /* LOCK_ON_OPEN */ + +# if DB_VERSION_MAJOR < 2 + db = dbopen(buf, omode, DBMMODE, dbtype, openinfo); +# else /* DB_VERSION_MAJOR < 2 */ + { + int flags = 0; +# if DB_VERSION_MAJOR > 2 + int ret; +# endif /* DB_VERSION_MAJOR > 2 */ + + if (mode == O_RDONLY) + flags |= DB_RDONLY; + if (bitset(O_CREAT, omode)) + flags |= DB_CREATE; + if (bitset(O_TRUNC, omode)) + flags |= DB_TRUNCATE; + +# if !HASFLOCK && defined(DB_FCNTL_LOCKING) + flags |= DB_FCNTL_LOCKING; +# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ + +# if DB_VERSION_MAJOR > 2 + ret = db_create(&db, NULL, 0); +# ifdef DB_CACHE_SIZE + if (ret == 0 && db != NULL) + { + ret = db->set_cachesize(db, 0, DB_CACHE_SIZE, 0); + if (ret != 0) + { + (void) db->close(db, 0); + db = NULL; + } + } +# endif /* DB_CACHE_SIZE */ +# ifdef DB_HASH_NELEM + if (dbtype == DB_HASH && ret == 0 && db != NULL) + { + ret = db->set_h_nelem(db, DB_HASH_NELEM); + if (ret != 0) + { + (void) db->close(db, 0); + db = NULL; + } + } +# endif /* DB_HASH_NELEM */ + if (ret == 0 && db != NULL) + { + ret = db->open(db, buf, NULL, dbtype, flags, DBMMODE); + if (ret != 0) + { + (void) db->close(db, 0); + db = NULL; + } + } + errno = ret; +# else /* DB_VERSION_MAJOR > 2 */ + errno = db_open(buf, dbtype, flags, DBMMODE, + NULL, openinfo, &db); +# endif /* DB_VERSION_MAJOR > 2 */ + } +# endif /* DB_VERSION_MAJOR < 2 */ + save_errno = errno; + +# if !LOCK_ON_OPEN + if (mode == O_RDWR) + map->map_lockfd = fd; + else + (void) close(fd); +# endif /* !LOCK_ON_OPEN */ + + if (db == NULL) + { + if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) && + aliaswait(map, ".db", FALSE)) + return TRUE; +# if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN */ + errno = save_errno; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("Cannot open %s database %s", + mapclassname, buf); + return FALSE; + } + +# if DB_VERSION_MAJOR < 2 + fd = db->fd(db); +# else /* DB_VERSION_MAJOR < 2 */ + fd = -1; + errno = db->fd(db, &fd); +# endif /* DB_VERSION_MAJOR < 2 */ + if (filechanged(buf, fd, &st)) + { + save_errno = errno; +# if DB_VERSION_MAJOR < 2 + (void) db->close(db); +# else /* DB_VERSION_MAJOR < 2 */ + errno = db->close(db, 0); +# endif /* DB_VERSION_MAJOR < 2 */ +# if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN */ + errno = save_errno; + syserr("db_map_open(%s): file changed after open", buf); + return FALSE; + } + + if (mode == O_RDWR) + map->map_mflags |= MF_LOCKED; +# if LOCK_ON_OPEN + if (fd >= 0 && mode == O_RDONLY) + { + (void) lockfile(fd, buf, NULL, LOCK_UN); + } +# endif /* LOCK_ON_OPEN */ + + /* try to make sure that at least the database header is on disk */ + if (mode == O_RDWR) + { + (void) db->sync(db, 0); + if (geteuid() == 0 && TrustedUid != 0) + { +# if HASFCHOWN + if (fchown(fd, TrustedUid, -1) < 0) + { + int err = errno; + + sm_syslog(LOG_ALERT, NOQID, + "ownership change on %s failed: %s", + buf, errstring(err)); + message("050 ownership change on %s failed: %s", + buf, errstring(err)); + } +# endif /* HASFCHOWN */ + } + } + + map->map_db2 = (ARBPTR_T) db; + + /* + ** Need to set map_mtime before the call to aliaswait() + ** as aliaswait() will call map_lookup() which requires + ** map_mtime to be set + */ + + if (fd >= 0 && fstat(fd, &st) >= 0) + map->map_mtime = st.st_mtime; + + 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 i; + int st; + int save_errno; + int fd; + struct stat stbuf; + char keybuf[MAXNAME + 1]; + char buf[MAXNAME + 1]; + + memset(&key, '\0', sizeof key); + memset(&val, '\0', sizeof val); + + if (tTd(38, 20)) + dprintf("db_map_lookup(%s, %s)\n", + map->map_mname, name); + + i = strlen(map->map_file); + if (i > MAXNAME) + i = MAXNAME; + (void) strlcpy(buf, map->map_file, i + 1); + if (i > 3 && strcmp(&buf[i - 3], ".db") == 0) + buf[i - 3] = '\0'; + + key.size = strlen(name); + if (key.size > sizeof keybuf - 1) + key.size = sizeof keybuf - 1; + key.data = keybuf; + memmove(keybuf, name, key.size); + keybuf[key.size] = '\0'; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(keybuf); + lockdb: +# if DB_VERSION_MAJOR < 2 + fd = db->fd(db); +# else /* DB_VERSION_MAJOR < 2 */ + fd = -1; + errno = db->fd(db, &fd); +# endif /* DB_VERSION_MAJOR < 2 */ + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, buf, ".db", LOCK_SH); + if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime) + { + /* Reopen the database to sync the cache */ + int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR + : O_RDONLY; + + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, buf, ".db", LOCK_UN); + map->map_class->map_close(map); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + if (map->map_class->map_open(map, omode)) + { + map->map_mflags |= MF_OPEN; + map->map_pid = getpid(); + if ((omode && O_ACCMODE) == O_RDWR) + map->map_mflags |= MF_WRITABLE; + db = (DB *) map->map_db2; + goto lockdb; + } + else + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + extern MAPCLASS BogusMapClass; + + *statp = EX_TEMPFAIL; + map->map_class = &BogusMapClass; + map->map_mflags |= MF_OPEN; + map->map_pid = getpid(); + syserr("Cannot reopen DB database %s", + map->map_file); + } + return NULL; + } + } + + st = 1; + if (bitset(MF_TRY0NULL, map->map_mflags)) + { +# if DB_VERSION_MAJOR < 2 + st = db->get(db, &key, &val, 0); +# else /* DB_VERSION_MAJOR < 2 */ + errno = db->get(db, NULL, &key, &val, 0); + switch (errno) + { + case DB_NOTFOUND: + case DB_KEYEMPTY: + st = 1; + break; + + case 0: + st = 0; + break; + + default: + st = -1; + break; + } +# endif /* DB_VERSION_MAJOR < 2 */ + if (st == 0) + map->map_mflags &= ~MF_TRY1NULL; + } + if (st != 0 && bitset(MF_TRY1NULL, map->map_mflags)) + { + key.size++; +# if DB_VERSION_MAJOR < 2 + st = db->get(db, &key, &val, 0); +# else /* DB_VERSION_MAJOR < 2 */ + errno = db->get(db, NULL, &key, &val, 0); + switch (errno) + { + case DB_NOTFOUND: + case DB_KEYEMPTY: + st = 1; + break; + + case 0: + st = 0; + break; + + default: + st = -1; + break; + } +# endif /* DB_VERSION_MAJOR < 2 */ + if (st == 0) + map->map_mflags &= ~MF_TRY0NULL; + } + save_errno = errno; + if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags)) + (void) lockfile(fd, buf, ".db", LOCK_UN); + if (st != 0) + { + errno = save_errno; + 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 status; + DBT key; + DBT data; + register DB *db = map->map_db2; + char keybuf[MAXNAME + 1]; + + memset(&key, '\0', sizeof key); + memset(&data, '\0', sizeof data); + + if (tTd(38, 12)) + dprintf("db_map_store(%s, %s, %s)\n", + map->map_mname, lhs, rhs); + + key.size = strlen(lhs); + key.data = lhs; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + { + if (key.size > sizeof keybuf - 1) + key.size = sizeof keybuf - 1; + memmove(keybuf, key.data, key.size); + keybuf[key.size] = '\0'; + makelower(keybuf); + key.data = keybuf; + } + + data.size = strlen(rhs); + data.data = rhs; + + if (bitset(MF_INCLNULL, map->map_mflags)) + { + key.size++; + data.size++; + } + +# if DB_VERSION_MAJOR < 2 + status = db->put(db, &key, &data, R_NOOVERWRITE); +# else /* DB_VERSION_MAJOR < 2 */ + errno = db->put(db, NULL, &key, &data, DB_NOOVERWRITE); + switch (errno) + { + case DB_KEYEXIST: + status = 1; + break; + + case 0: + status = 0; + break; + + default: + status = -1; + break; + } +# endif /* DB_VERSION_MAJOR < 2 */ + if (status > 0) + { + if (!bitset(MF_APPEND, map->map_mflags)) + message("050 Warning: duplicate alias name %s", lhs); + else + { + static char *buf = NULL; + static int bufsiz = 0; + DBT old; + + memset(&old, '\0', sizeof old); + + old.data = db_map_lookup(map, key.data, + (char **)NULL, &status); + 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); + } + snprintf(buf, bufsiz, "%s,%s", + (char *) data.data, (char *) old.data); + data.size = data.size + old.size + 1; + data.data = buf; + if (tTd(38, 9)) + dprintf("db_map_store append=%s\n", + (char *) data.data); + } + } +# if DB_VERSION_MAJOR < 2 + status = db->put(db, &key, &data, 0); +# else /* DB_VERSION_MAJOR < 2 */ + status = errno = db->put(db, NULL, &key, &data, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + } + if (status != 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)) + dprintf("db_map_close(%s, %s, %lx)\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, "@", "@"); + } + + (void) db->sync(db, 0); + +# if !LOCK_ON_OPEN + if (map->map_lockfd >= 0) + (void) close(map->map_lockfd); +# endif /* !LOCK_ON_OPEN */ + +# if DB_VERSION_MAJOR < 2 + if (db->close(db) != 0) +# else /* DB_VERSION_MAJOR < 2 */ + /* + ** Berkeley DB can use internal shared memory + ** locking for its memory pool. Closing a map + ** opened by another process will interfere + ** with the shared memory and locks of the parent + ** process leaving things in a bad state. + */ + + /* + ** If this map was not opened by the current + ** process, do not close the map but recover + ** the file descriptor. + */ + if (map->map_pid != getpid()) + { + int fd = -1; + + errno = db->fd(db, &fd); + if (fd >= 0) + (void) close(fd); + return; + } + + if ((errno = db->close(db, 0)) != 0) +# endif /* DB_VERSION_MAJOR < 2 */ + syserr("db_map_close(%s, %s, %lx): db close failure", + map->map_mname, map->map_file, map->map_mflags); +} +#endif /* NEWDB */ + /* +** NIS Modules +*/ + +#ifdef NIS + +# ifndef YPERR_BUSY +# define YPERR_BUSY 16 +# endif /* ! YPERR_BUSY */ + +/* +** 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)) + dprintf("nis_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + /* issue a pseudo-error message */ +# ifdef ENOSYS + errno = ENOSYS; +# else /* ENOSYS */ +# ifdef EFTYPE + errno = EFTYPE; +# else /* EFTYPE */ + errno = ENXIO; +# endif /* EFTYPE */ +# endif /* ENOSYS */ + 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 4.3.5 NIS map %s specified, but NIS not running", + 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)) + dprintf("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 /* 0 */ + return TRUE; + } + + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + syserr("421 4.0.0 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 +*/ + +/* ARGSUSED3 */ +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)) + dprintf("nis_map_lookup(%s, %s)\n", + map->map_mname, name); + + buflen = strlen(name); + if (buflen > sizeof keybuf - 1) + buflen = sizeof keybuf - 1; + memmove(keybuf, name, buflen); + keybuf[buflen] = '\0'; + 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 +*/ + +static 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)) + dprintf("nis_getcanonname(%s)\n", name); + + if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) + { + *statp = EX_UNAVAILABLE; + return FALSE; + } + shorten_hostname(nbuf); + keylen = strlen(nbuf); + + if (yp_domain == NULL) + (void) 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; + } + (void) strlcpy(host_record, vp, sizeof host_record); + if (tTd(38, 44)) + dprintf("got record `%s'\n", host_record); + if (!extract_canonname(nbuf, host_record, cbuf, sizeof cbuf)) + { + /* this should not happen, but.... */ + *statp = EX_NOHOST; + return FALSE; + } + if (hbsize < strlen(cbuf)) + { + *statp = EX_UNAVAILABLE; + return FALSE; + } + (void) strlcpy(name, cbuf, hbsize); + *statp = EX_OK; + return TRUE; +} + +#endif /* NIS */ + /* +** NISPLUS Modules +** +** This code donated by Sun Microsystems. +*/ + +#ifdef NISPLUS + +# undef NIS /* symbol conflict in nis.h */ +# undef T_UNSPEC /* symbol conflict in nis.h -> ... -> sys/tiuser.h */ +# include +# include + +# 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; +{ + nis_result *res = NULL; + int retry_cnt, max_col, i; + char qbuf[MAXLINE + NIS_MAXNAMELEN]; + + if (tTd(38, 2)) + dprintf("nisplus_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + errno = EPERM; + 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 */ + map->map_domain = newstr(nisplus_default_domain()); + if (tTd(38, 2)) + dprintf("nisplus_map_open(%s): using domain %s\n", + map->map_file, map->map_domain); + } + if (!PARTIAL_NAME(map->map_file)) + { + map->map_domain = newstr(""); + snprintf(qbuf, sizeof qbuf, "%s", map->map_file); + } + else + { + /* check to see if this map actually exists */ + snprintf(qbuf, sizeof qbuf, "%s.%s", + map->map_file, map->map_domain); + } + + 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 = EAGAIN; + 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 4.0.0 Cannot find table %s.%s: %s", + map->map_file, map->map_domain, + nis_sperrno(res->status)); +# endif /* 0 */ + errno = EAGAIN; + return FALSE; + } + } + + if (NIS_RES_NUMOBJ(res) != 1 || + (NIS_RES_OBJECT(res)->zo_data.zo_type != TABLE_OBJ)) + { + if (tTd(38, 10)) + dprintf("nisplus_map_open: %s is not a table\n", qbuf); +# if 0 + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("421 4.0.0 %s.%s: %s is not a table", + map->map_file, map->map_domain, + nis_sperrno(res->status)); +# endif /* 0 */ + errno = EBADF; + 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)) + dprintf("nisplus_map_open(%s): can not find key column %s\n", + map->map_file, map->map_keycolnm); + errno = ENOENT; + 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)) + dprintf("nisplus_map_open(%s): can not find column %s\n", + map->map_file, map->map_keycolnm); + errno = ENOENT; + 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 *p; + auto int vsize; + char *skp; + int skleft; + char search_key[MAXNAME + 4]; + char qbuf[MAXLINE + NIS_MAXNAMELEN]; + nis_result *result; + + if (tTd(38, 20)) + dprintf("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; + map->map_pid = getpid(); + } + else + { + *statp = EX_UNAVAILABLE; + return NULL; + } + } + + /* + ** Copy the name to the key buffer, escaping double quote characters + ** by doubling them and quoting "]" and "," to avoid having the + ** NIS+ parser choke on them. + */ + + skleft = sizeof search_key - 4; + skp = search_key; + for (p = name; *p != '\0' && skleft > 0; p++) + { + switch (*p) + { + case ']': + case ',': + /* quote the character */ + *skp++ = '"'; + *skp++ = *p; + *skp++ = '"'; + skleft -= 3; + break; + + case '"': + /* double the quote */ + *skp++ = '"'; + skleft--; + /* FALLTHROUGH */ + + default: + *skp++ = *p; + skleft--; + break; + } + } + *skp = '\0'; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(search_key); + + /* construct the query */ + if (PARTIAL_NAME(map->map_file)) + snprintf(qbuf, sizeof qbuf, "[%s=%s],%s.%s", + map->map_keycolnm, search_key, map->map_file, + map->map_domain); + else + snprintf(qbuf, sizeof qbuf, "[%s=%s],%s", + map->map_keycolnm, search_key, map->map_file); + + if (tTd(38, 20)) + dprintf("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) + sm_syslog(LOG_WARNING, CurEnv->e_id, + "%s: lookup error, expected 1 entry, got %d", + map->map_file, count); + + /* ignore second entry */ + if (tTd(38, 20)) + dprintf("nisplus_map_lookup(%s), got %d entries, additional entries ignored\n", + name, count); + } + + p = ((NIS_RES_OBJECT(result))->EN_col(map->map_valcolno)); + /* set the length of the result */ + if (p == NULL) + p = ""; + vsize = strlen(p); + if (tTd(38, 20)) + dprintf("nisplus_map_lookup(%s), found %s\n", + name, p); + if (bitset(MF_MATCHONLY, map->map_mflags)) + str = map_rewrite(map, name, strlen(name), NULL); + else + str = map_rewrite(map, p, 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)) + dprintf("nisplus_map_lookup(%s), failed\n", name); + nis_freeresult(result); + return NULL; +} + + + +/* +** NISPLUS_GETCANONNAME -- look up canonical name in NIS+ +*/ + +static 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) strlcpy(nbuf, name, sizeof nbuf); + shorten_hostname(nbuf); + + p = strchr(nbuf, '.'); + if (p == NULL) + { + /* single token */ + snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir", nbuf); + } + else if (p[1] != '\0') + { + /* multi token -- take only first token in nbuf */ + *p = '\0'; + snprintf(qbuf, sizeof qbuf, "[name=%s],hosts.org_dir.%s", + nbuf, &p[1]); + } + else + { + *statp = EX_NOHOST; + return FALSE; + } + + if (tTd(38, 20)) + dprintf("\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 *domain; + + if ((count = NIS_RES_NUMOBJ(result)) != 1) + { + if (LogLevel > 10) + sm_syslog(LOG_WARNING, CurEnv->e_id, + "nisplus_getcanonname: lookup error, expected 1 entry, got %d", + count); + + /* ignore second entry */ + if (tTd(38, 20)) + dprintf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n", + name, count); + } + + if (tTd(38, 20)) + dprintf("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)) + dprintf("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') + (void) strlcpy(name, vp, hbsize); + else + snprintf(name, hbsize, "%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)) + dprintf("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(); + snprintf(default_domain, sizeof default_domain, "%s", p); + return default_domain; +} + +#endif /* NISPLUS */ + /* +** LDAP Modules +*/ + +/* +** LDAPMAP_DEQUOTE - helper routine for ldapmap_parseargs +*/ + +#if defined(LDAPMAP) || defined(PH_MAP) + +# ifdef PH_MAP +# define ph_map_dequote ldapmap_dequote +# endif /* PH_MAP */ + +char * +ldapmap_dequote(str) + char *str; +{ + char *p; + char *start; + + if (str == NULL) + return NULL; + + p = str; + if (*p == '"') + { + /* Should probably swallow initial whitespace here */ + start = ++p; + } + else + return str; + while (*p != '"' && *p != '\0') + p++; + if (*p != '\0') + *p = '\0'; + return start; +} +#endif /* defined(LDAPMAP) || defined(PH_MAP) */ + +#ifdef LDAPMAP + +LDAPMAP_STRUCT *LDAPDefaults = NULL; + +/* +** LDAPMAP_OPEN -- open LDAP map +** +** Connect to the LDAP server. Re-use existing connections since a +** single server connection to a host (with the same host, port, +** bind DN, and secret) can answer queries for multiple maps. +*/ + +bool +ldapmap_open(map, mode) + MAP *map; + int mode; +{ + LDAPMAP_STRUCT *lmap; + STAB *s; + + if (tTd(38, 2)) + dprintf("ldapmap_open(%s, %d)\n", map->map_mname, mode); + + mode &= O_ACCMODE; + + /* sendmail doesn't have the ability to write to LDAP (yet) */ + if (mode != O_RDONLY) + { + /* issue a pseudo-error message */ +# ifdef ENOSYS + errno = ENOSYS; +# else /* ENOSYS */ +# ifdef EFTYPE + errno = EFTYPE; +# else /* EFTYPE */ + errno = ENXIO; +# endif /* EFTYPE */ +# endif /* ENOSYS */ + return FALSE; + } + + /* Comma separate if used as an alias file */ + if (map->map_coldelim == '\0' && bitset(MF_ALIAS, map->map_mflags)) + map->map_coldelim = ','; + + lmap = (LDAPMAP_STRUCT *) map->map_db1; + + s = ldapmap_findconn(lmap); + if (s->s_ldap != NULL) + { + /* Already have a connection open to this LDAP server */ + lmap->ldap_ld = s->s_ldap; + return TRUE; + } + + /* No connection yet, connect */ + if (!ldapmap_start(map)) + return FALSE; + + /* Save connection for reuse */ + s->s_ldap = lmap->ldap_ld; + return TRUE; +} + +/* +** LDAPMAP_START -- actually connect to an LDAP server +** +** Parameters: +** map -- the map being opened. +** +** Returns: +** TRUE if connection is successful, FALSE otherwise. +** +** Side Effects: +** Populates lmap->ldap_ld. +*/ + +static jmp_buf LDAPTimeout; + +static bool +ldapmap_start(map) + MAP *map; +{ + register int bind_result; + int save_errno; + register EVENT *ev = NULL; + LDAPMAP_STRUCT *lmap; + LDAP *ld; + + if (tTd(38, 2)) + dprintf("ldapmap_start(%s)\n", map->map_mname); + + lmap = (LDAPMAP_STRUCT *) map->map_db1; + + if (tTd(38,9)) + dprintf("ldapmap_start(%s, %d)\n", + lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host, + lmap->ldap_port); + +# if USE_LDAP_INIT + ld = ldap_init(lmap->ldap_host, lmap->ldap_port); +# else /* USE_LDAP_INIT */ + /* + ** If using ldap_open(), the actual connection to the server + ** happens now so we need the timeout here. For ldap_init(), + ** the connection happens at bind time. + */ + + /* set the timeout */ + if (lmap->ldap_timeout.tv_sec != 0) + { + if (setjmp(LDAPTimeout) != 0) + { + if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "timeout conning to LDAP server %.100s", + lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); + return FALSE; + } + ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); + } + + ld = ldap_open(lmap->ldap_host, lmap->ldap_port); + save_errno = errno; + + /* clear the event if it has not sprung */ + if (ev != NULL) + clrevent(ev); +# endif /* USE_LDAP_INIT */ + + errno = save_errno; + if (ld == NULL) + { + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (bitset(MF_NODEFER, map->map_mflags)) + syserr("%s failed to %s in map %s", +# if USE_LDAP_INIT + "ldap_init", +# else /* USE_LDAP_INIT */ + "ldap_open", +# endif /* USE_LDAP_INIT */ + lmap->ldap_host == NULL ? "localhost" + : lmap->ldap_host, + map->map_mname); + else + syserr("421 4.0.0 %s failed to %s in map %s", +# if USE_LDAP_INIT + "ldap_init", +# else /* USE_LDAP_INIT */ + "ldap_open", +# endif /* USE_LDAP_INIT */ + lmap->ldap_host == NULL ? "localhost" + : lmap->ldap_host, + map->map_mname); + } + return FALSE; + } + + ldapmap_setopts(ld, lmap); + +# if USE_LDAP_INIT + /* + ** If using ldap_init(), the actual connection to the server + ** happens at ldap_bind_s() so we need the timeout here. + */ + + /* set the timeout */ + if (lmap->ldap_timeout.tv_sec != 0) + { + if (setjmp(LDAPTimeout) != 0) + { + if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "timeout conning to LDAP server %.100s", + lmap->ldap_host == NULL ? "localhost" + : lmap->ldap_host); + return FALSE; + } + ev = setevent(lmap->ldap_timeout.tv_sec, ldaptimeout, 0); + } +# endif /* USE_LDAP_INIT */ + + if (lmap->ldap_method == LDAP_AUTH_KRBV4 && + lmap->ldap_secret != NULL) + { + /* + ** Need to put ticket in environment here instead of + ** during parseargs as there may be different tickets + ** for different LDAP connections. + */ + + (void) putenv(lmap->ldap_secret); + } + + bind_result = ldap_bind_s(ld, lmap->ldap_binddn, + lmap->ldap_secret, lmap->ldap_method); + +# if USE_LDAP_INIT + /* clear the event if it has not sprung */ + if (ev != NULL) + clrevent(ev); +# endif /* USE_LDAP_INIT */ + + if (bind_result != LDAP_SUCCESS) + { + errno = bind_result + E_LDAPBASE; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + syserr("421 4.0.0 Cannot bind to map %s in ldap server %s", + map->map_mname, + lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host); + } + return FALSE; + } + + /* We need to cast ld into the map structure */ + lmap->ldap_ld = ld; + return TRUE; +} + +/* ARGSUSED */ +static void +ldaptimeout(sig_no) + int sig_no; +{ + longjmp(LDAPTimeout, 1); +} + +/* +** LDAPMAP_CLOSE -- close ldap map +*/ + +void +ldapmap_close(map) + MAP *map; +{ + LDAPMAP_STRUCT *lmap; + STAB *s; + + lmap = (LDAPMAP_STRUCT *) map->map_db1; + + /* Check if already closed */ + if (lmap->ldap_ld == NULL) + return; + + s = ldapmap_findconn(lmap); + + /* Check if already closed */ + if (s->s_ldap == NULL) + return; + + /* If same as saved connection, stored connection is going away */ + if (s->s_ldap == lmap->ldap_ld) + s->s_ldap = NULL; + + if (lmap->ldap_ld != NULL) + { + ldap_unbind(lmap->ldap_ld); + lmap->ldap_ld = NULL; + } +} + +# ifdef SUNET_ID +/* +** SUNET_ID_HASH -- Convert a string to it's Sunet_id canonical form +** This only makes sense at Stanford University. +*/ + +char * +sunet_id_hash(str) + char *str; +{ + char *p, *p_last; + + p = str; + p_last = p; + while (*p != '\0') + { + if (islower(*p) || isdigit(*p)) + { + *p_last = *p; + p_last++; + } + else if (isupper(*p)) + { + *p_last = tolower(*p); + p_last++; + } + ++p; + } + if (*p_last != '\0') + *p_last = '\0'; + return str; +} +# endif /* SUNET_ID */ + +/* +** LDAPMAP_LOOKUP -- look up a datum in a LDAP map +*/ + +char * +ldapmap_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int i; + int entries = 0; + int msgid; + int ret; + int vsize; + char *fp, *vp; + char *p, *q; + char *result = NULL; + LDAPMAP_STRUCT *lmap = NULL; + char keybuf[MAXNAME + 1]; + char filter[LDAPMAP_MAX_FILTER + 1]; + + if (tTd(38, 20)) + dprintf("ldapmap_lookup(%s, %s)\n", map->map_mname, name); + + /* Get ldap struct pointer from map */ + lmap = (LDAPMAP_STRUCT *) map->map_db1; + ldapmap_setopts(lmap->ldap_ld, lmap); + + (void) strlcpy(keybuf, name, sizeof keybuf); + + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + { +# ifdef SUNET_ID + sunet_id_hash(keybuf); +# else /* SUNET_ID */ + makelower(keybuf); +# endif /* SUNET_ID */ + } + + /* substitute keybuf into filter, perhaps multiple times */ + memset(filter, '\0', sizeof filter); + fp = filter; + p = lmap->ldap_filter; + while ((q = strchr(p, '%')) != NULL) + { + if (q[1] == 's') + { + snprintf(fp, SPACELEFT(filter, fp), "%.*s%s", + q - p, p, keybuf); + fp += strlen(fp); + p = q + 2; + } + else if (q[1] == '0') + { + char *k = keybuf; + + snprintf(fp, SPACELEFT(filter, fp), "%.*s", + q - p, p); + fp += strlen(fp); + p = q + 2; + + /* Properly escape LDAP special characters */ + while (SPACELEFT(filter, fp) > 0 && + *k != '\0') + { + if (*k == '*' || *k == '(' || + *k == ')' || *k == '\\') + { + (void) strlcat(fp, + (*k == '*' ? "\\2A" : + (*k == '(' ? "\\28" : + (*k == ')' ? "\\29" : + (*k == '\\' ? "\\5C" : + "\00")))), + SPACELEFT(filter, fp)); + fp += strlen(fp); + k++; + } + else + *fp++ = *k++; + } + } + else + { + snprintf(fp, SPACELEFT(filter, fp), "%.*s", + q - p + 1, p); + p = q + (q[1] == '%' ? 2 : 1); + fp += strlen(fp); + } + } + snprintf(fp, SPACELEFT(filter, fp), "%s", p); + if (tTd(38, 20)) + dprintf("ldap search filter=%s\n", filter); + + lmap->ldap_res = NULL; + msgid = ldap_search(lmap->ldap_ld, lmap->ldap_base, lmap->ldap_scope, + filter, + (lmap->ldap_attr[0] == NULL ? NULL : + lmap->ldap_attr), + lmap->ldap_attrsonly); + if (msgid == -1) + { + errno = ldapmap_geterrno(lmap->ldap_ld) + E_LDAPBASE; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (bitset(MF_NODEFER, map->map_mflags)) + syserr("Error in ldap_search_st using %s in map %s", + filter, map->map_mname); + else + syserr("421 4.0.0 Error in ldap_search_st using %s in map %s", + filter, map->map_mname); + } + *statp = EX_TEMPFAIL; + return NULL; + } + + *statp = EX_NOTFOUND; + vp = NULL; + + /* Get results (all if MF_NOREWRITE, otherwise one by one) */ + while ((ret = ldap_result(lmap->ldap_ld, msgid, + bitset(MF_NOREWRITE, map->map_mflags), + (lmap->ldap_timeout.tv_sec == 0 ? NULL : + &(lmap->ldap_timeout)), + &(lmap->ldap_res))) == LDAP_RES_SEARCH_ENTRY) + { + LDAPMessage *entry; + + if (bitset(MF_SINGLEMATCH, map->map_mflags)) + { + entries += ldap_count_entries(lmap->ldap_ld, + lmap->ldap_res); + if (entries > 1) + { + *statp = EX_NOTFOUND; + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + (void) ldap_abandon(lmap->ldap_ld, msgid); + if (vp != NULL) + free(vp); + if (tTd(38, 25)) + dprintf("ldap search found multiple on a single match query\n"); + return NULL; + } + } + + /* Cycle through all entries */ + for (entry = ldap_first_entry(lmap->ldap_ld, lmap->ldap_res); + entry != NULL; + entry = ldap_next_entry(lmap->ldap_ld, lmap->ldap_res)) + { + BerElement *ber; + char *attr; + char **vals; + + /* + ** If matching only and found an entry, + ** no need to spin through attributes + */ + + if (*statp == EX_OK && + bitset(MF_MATCHONLY, map->map_mflags)) + continue; + + for (attr = ldap_first_attribute(lmap->ldap_ld, entry, + &ber); + attr != NULL; + attr = ldap_next_attribute(lmap->ldap_ld, entry, + ber)) + { + char *tmp, *vp_tmp; + + vals = ldap_get_values(lmap->ldap_ld, entry, + attr); + if (vals == NULL) + { + errno = ldapmap_geterrno(lmap->ldap_ld); + if (errno == LDAP_SUCCESS) + continue; + + /* Must be an error */ + errno += E_LDAPBASE; + if (!bitset(MF_OPTIONAL, + map->map_mflags)) + { + if (bitset(MF_NODEFER, + map->map_mflags)) + syserr("Error getting LDAP values in map %s", + map->map_mname); + else + syserr("421 4.0.0 Error getting LDAP values in map %s", + map->map_mname); + } + *statp = EX_TEMPFAIL; +# if USING_NETSCAPE_LDAP + ldap_mem_free(attr); +# endif /* USING_NETSCAPE_LDAP */ + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + (void) ldap_abandon(lmap->ldap_ld, + msgid); + if (vp != NULL) + free(vp); + return NULL; + } + + *statp = EX_OK; + + /* + ** If matching only, + ** no need to spin through entries + */ + + if (bitset(MF_MATCHONLY, map->map_mflags)) + continue; + + /* + ** If we don't want multiple values, + ** return first found. + */ + + if (map->map_coldelim == '\0') + { + if (vals[0] == NULL) + { + ldap_value_free(vals); +# if USING_NETSCAPE_LDAP + ldap_mem_free(attr); +# endif /* USING_NETSCAPE_LDAP */ + continue; + } + + vp = newstr(vals[0]); + ldap_value_free(vals); +# if USING_NETSCAPE_LDAP + ldap_mem_free(attr); +# endif /* USING_NETSCAPE_LDAP */ + break; + } + + /* + ** If there is more than one, + ** munge then into a map_coldelim + ** separated string + */ + + vsize = 0; + for (i = 0; vals[i] != NULL; i++) + vsize += strlen(vals[i]) + 1; + vp_tmp = xalloc(vsize); + *vp_tmp = '\0'; + + p = vp_tmp; + for (i = 0; vals[i] != NULL; i++) + { + p += strlcpy(p, vals[i], + vsize - (p - vp_tmp)); + if (p >= vp_tmp + vsize) + syserr("ldapmap_lookup: Internal error: buffer too small for LDAP values"); + if (vals[i + 1] != NULL) + *p++ = map->map_coldelim; + } + + ldap_value_free(vals); +# if USING_NETSCAPE_LDAP + ldap_mem_free(attr); +# endif /* USING_NETSCAPE_LDAP */ + if (vp == NULL) + { + vp = vp_tmp; + continue; + } + vsize = strlen(vp) + strlen(vp_tmp) + 2; + tmp = xalloc(vsize); + snprintf(tmp, vsize, "%s%c%s", + vp, map->map_coldelim, vp_tmp); + + free(vp); + free(vp_tmp); + vp = tmp; + } + errno = ldapmap_geterrno(lmap->ldap_ld); + + /* + ** We check errno != LDAP_DECODING_ERROR since + ** OpenLDAP 1.X has a very ugly *undocumented* + ** hack of returning this error code from + ** ldap_next_attribute() if the library freed the + ** ber attribute. See: + ** http://www.openldap.org/lists/openldap-devel/9901/msg00064.html + */ + + if (errno != LDAP_SUCCESS && + errno != LDAP_DECODING_ERROR) + { + /* Must be an error */ + errno += E_LDAPBASE; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (bitset(MF_NODEFER, map->map_mflags)) + syserr("Error getting LDAP attributes in map %s", + map->map_mname); + else + syserr("421 4.0.0 Error getting LDAP attributes in map %s", + map->map_mname); + } + *statp = EX_TEMPFAIL; + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + (void) ldap_abandon(lmap->ldap_ld, msgid); + if (vp != NULL) + free(vp); + return NULL; + } + + /* We don't want multiple values and we have one */ + if (map->map_coldelim == '\0' && vp != NULL) + break; + } + errno = ldapmap_geterrno(lmap->ldap_ld); + if (errno != LDAP_SUCCESS) + { + /* Must be an error */ + errno += E_LDAPBASE; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (bitset(MF_NODEFER, map->map_mflags)) + syserr("Error getting LDAP entries in map %s", + map->map_mname); + else + syserr("421 4.0.0 Error getting LDAP entries in map %s", + map->map_mname); + } + *statp = EX_TEMPFAIL; + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + (void) ldap_abandon(lmap->ldap_ld, msgid); + if (vp != NULL) + free(vp); + return NULL; + } + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + + /* If we don't want multiple values and we have one, break */ + if (map->map_coldelim == '\0' && vp != NULL) + break; + } + + /* + ** If grabbing all results at once for MF_NOREWRITE and + ** only want a single match, make sure that's all we have + */ + + if (ret == LDAP_RES_SEARCH_RESULT && + bitset(MF_NOREWRITE|MF_SINGLEMATCH, map->map_mflags)) + { + entries += ldap_count_entries(lmap->ldap_ld, lmap->ldap_res); + if (entries > 1) + { + *statp = EX_NOTFOUND; + if (lmap->ldap_res != NULL) + { + ldap_msgfree(lmap->ldap_res); + lmap->ldap_res = NULL; + } + if (vp != NULL) + free(vp); + return NULL; + } + *statp = EX_OK; + } + + if (ret == 0) + errno = ETIMEDOUT; + else + errno = ldapmap_geterrno(lmap->ldap_ld); + if (errno != LDAP_SUCCESS) + { + /* Must be an error */ + if (ret != 0) + errno += E_LDAPBASE; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (bitset(MF_NODEFER, map->map_mflags)) + syserr("Error getting LDAP results in map %s", + map->map_mname); + else + syserr("421 4.0.0 Error getting LDAP results in map %s", + map->map_mname); + } + *statp = EX_TEMPFAIL; + if (vp != NULL) + free(vp); + return NULL; + } + + /* Did we match anything? */ + if (vp == NULL) + return NULL; + + /* + ** If MF_NOREWRITE, we are special map which doesn't + ** actually return a map value. Instead, we don't free + ** ldap_res and let the calling function process the LDAP + ** results. The caller should ldap_msgfree(lmap->ldap_res). + */ + + if (bitset(MF_NOREWRITE, map->map_mflags)) + { + /* vp != NULL due to test above */ + free(vp); + return ""; + } + + if (*statp == EX_OK) + { + /* vp != NULL due to test above */ + if (LogLevel > 9) + sm_syslog(LOG_INFO, CurEnv->e_id, + "ldap %.100s => %s", name, vp); + if (bitset(MF_MATCHONLY, map->map_mflags)) + result = map_rewrite(map, name, strlen(name), NULL); + else + result = map_rewrite(map, vp, strlen(vp), av); + free(vp); + } + return result; +} + +/* +** LDAPMAP_FINDCONN -- find an LDAP connection to the server +** +** Cache LDAP connections based on the host, port, bind DN, +** and secret so we don't have multiple connections open to +** the same server for different maps. +** +** Parameters: +** lmap -- LDAP map information +** +** Returns: +** Symbol table entry for the LDAP connection. +** +*/ + +static STAB * +ldapmap_findconn(lmap) + LDAPMAP_STRUCT *lmap; +{ + int len; + char *nbuf; + STAB *s; + + len = (lmap->ldap_host == NULL ? strlen("localhost") : + strlen(lmap->ldap_host)) + 1 + 8 + 1 + + (lmap->ldap_binddn == NULL ? 0 : strlen(lmap->ldap_binddn)) + + 1 + + (lmap->ldap_secret == NULL ? 0 : strlen(lmap->ldap_secret)) + + 1; + nbuf = xalloc(len); + snprintf(nbuf, len, "%s%c%d%c%s%c%s", + (lmap->ldap_host == NULL ? "localhost" : lmap->ldap_host), + CONDELSE, + lmap->ldap_port, + CONDELSE, + (lmap->ldap_binddn == NULL ? "" : lmap->ldap_binddn), + CONDELSE, + (lmap->ldap_secret == NULL ? "" : lmap->ldap_secret)); + s = stab(nbuf, ST_LDAP, ST_ENTER); + free(nbuf); + return s; +} + /* +** LDAPMAP_SETOPTS -- set LDAP options +** +** Parameters: +** ld -- LDAP session handle +** lmap -- LDAP map information +** +** Returns: +** None. +** +*/ + +static void +ldapmap_setopts(ld, lmap) + LDAP *ld; + LDAPMAP_STRUCT *lmap; +{ +# if USE_LDAP_SET_OPTION + ldap_set_option(ld, LDAP_OPT_DEREF, &lmap->ldap_deref); + if (bitset(LDAP_OPT_REFERRALS, lmap->ldap_options)) + ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_ON); + else + ldap_set_option(ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); + ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &lmap->ldap_sizelimit); + ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &lmap->ldap_timelimit); +# else /* USE_LDAP_SET_OPTION */ + /* From here on in we can use ldap internal timelimits */ + ld->ld_deref = lmap->ldap_deref; + ld->ld_options = lmap->ldap_options; + ld->ld_sizelimit = lmap->ldap_sizelimit; + ld->ld_timelimit = lmap->ldap_timelimit; +# endif /* USE_LDAP_SET_OPTION */ +} + /* +** LDAPMAP_GETERRNO -- get ldap errno value +** +** Parameters: +** ld -- LDAP session handle +** +** Returns: +** LDAP errno. +** +*/ + +static int +ldapmap_geterrno(ld) + LDAP *ld; +{ + int err = LDAP_SUCCESS; + +# if defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 + (void) ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); +# else /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ +# ifdef LDAP_OPT_SIZELIMIT + err = ldap_get_lderrno(ld, NULL, NULL); +# else /* LDAP_OPT_SIZELIMIT */ + err = ld->ld_errno; + + /* + ** Reset value to prevent lingering LDAP_DECODING_ERROR due to + ** OpenLDAP 1.X's hack (see above) + */ + + ld->ld_errno = LDAP_SUCCESS; +# endif /* LDAP_OPT_SIZELIMIT */ +# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */ + return err; +} + +/* +** LDAPX_MAP_PARSEARGS -- print warning about use of ldapx map. +*/ + +bool +ldapx_map_parseargs(map, args) + MAP *map; + char *args; +{ + printf("Warning: The \"ldapx\" map class is deprecated and will be removed in a future\n"); + printf(" version. Use the \"ldap\" map class instead for map \"%s\".\n", + map->map_mname); + return ldapmap_parseargs(map, args); +} + +/* +** LDAPMAP_PARSEARGS -- parse ldap map definition args. +*/ + +struct lamvalues LDAPAuthMethods[] = +{ + { "none", LDAP_AUTH_NONE }, + { "simple", LDAP_AUTH_SIMPLE }, + { "krbv4", LDAP_AUTH_KRBV4 }, + { NULL, 0 } +}; + +struct ladvalues LDAPAliasDereference[] = +{ + { "never", LDAP_DEREF_NEVER }, + { "always", LDAP_DEREF_ALWAYS }, + { "search", LDAP_DEREF_SEARCHING }, + { "find", LDAP_DEREF_FINDING }, + { NULL, 0 } +}; + +struct lssvalues LDAPSearchScope[] = +{ + { "base", LDAP_SCOPE_BASE }, + { "one", LDAP_SCOPE_ONELEVEL }, + { "sub", LDAP_SCOPE_SUBTREE }, + { NULL, 0 } +}; + +bool +ldapmap_parseargs(map, args) + MAP *map; + char *args; +{ + bool secretread = TRUE; + int i; + register char *p = args; + LDAPMAP_STRUCT *lmap; + struct lamvalues *lam; + struct ladvalues *lad; + struct lssvalues *lss; + char m_tmp[MAXPATHLEN + LDAPMAP_MAX_PASSWD]; + + /* Get ldap struct pointer from map */ + lmap = (LDAPMAP_STRUCT *) map->map_db1; + + /* Check if setting the initial LDAP defaults */ + if (lmap == NULL || lmap != LDAPDefaults) + { + /* We need to alloc an LDAPMAP_STRUCT struct */ + lmap = (LDAPMAP_STRUCT *) xalloc(sizeof *lmap); + if (LDAPDefaults == NULL) + ldapmap_clear(lmap); + else + STRUCTCOPY(*LDAPDefaults, *lmap); + } + + /* there is no check whether there is really an argument */ + map->map_mflags |= MF_TRY0NULL|MF_TRY1NULL; + map->map_spacesub = SpaceSub; /* default value */ + 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 'T': + map->map_tapp = ++p; + break; + + case 't': + map->map_mflags |= MF_NODEFER; + break; + + case 'S': + map->map_spacesub = *++p; + break; + + case 'D': + map->map_mflags |= MF_DEFER; + 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; + + /* Start of ldapmap specific args */ + case 'k': /* search field */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_filter = p; + break; + + case 'v': /* attr to return */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_attr[0] = p; + lmap->ldap_attr[1] = NULL; + break; + + case '1': + map->map_mflags |= MF_SINGLEMATCH; + break; + + /* args stolen from ldapsearch.c */ + case 'R': /* don't auto chase referrals */ +# ifdef LDAP_REFERRALS + lmap->ldap_options &= ~LDAP_OPT_REFERRALS; +# else /* LDAP_REFERRALS */ + syserr("compile with -DLDAP_REFERRALS for referral support\n"); +# endif /* LDAP_REFERRALS */ + break; + + case 'n': /* retrieve attribute names only */ + lmap->ldap_attrsonly = LDAPMAP_TRUE; + break; + + case 'r': /* alias dereferencing */ + while (isascii(*++p) && isspace(*p)) + continue; + + if (strncasecmp(p, "LDAP_DEREF_", 11) == 0) + p += 11; + + for (lad = LDAPAliasDereference; + lad != NULL && lad->lad_name != NULL; lad++) + { + if (strncasecmp(p, lad->lad_name, + strlen(lad->lad_name)) == 0) + break; + } + if (lad->lad_name != NULL) + lmap->ldap_deref = lad->lad_code; + else + { + /* bad config line */ + if (!bitset(MCF_OPTFILE, + map->map_class->map_cflags)) + { + char *ptr; + + if ((ptr = strchr(p, ' ')) != NULL) + *ptr = '\0'; + syserr("Deref must be [never|always|search|find] not %s in map %s", + p, map->map_mname); + if (ptr != NULL) + *ptr = ' '; + return FALSE; + } + } + break; + + case 's': /* search scope */ + while (isascii(*++p) && isspace(*p)) + continue; + + if (strncasecmp(p, "LDAP_SCOPE_", 11) == 0) + p += 11; + + for (lss = LDAPSearchScope; + lss != NULL && lss->lss_name != NULL; lss++) + { + if (strncasecmp(p, lss->lss_name, + strlen(lss->lss_name)) == 0) + break; + } + if (lss->lss_name != NULL) + lmap->ldap_scope = lss->lss_code; + else + { + /* bad config line */ + if (!bitset(MCF_OPTFILE, + map->map_class->map_cflags)) + { + char *ptr; + + if ((ptr = strchr(p, ' ')) != NULL) + *ptr = '\0'; + syserr("Scope must be [base|one|sub] not %s in map %s", + p, map->map_mname); + if (ptr != NULL) + *ptr = ' '; + return FALSE; + } + } + break; + + case 'h': /* ldap host */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_host = p; + break; + + case 'b': /* search base */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_base = p; + break; + + case 'p': /* ldap port */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_port = atoi(p); + break; + + case 'l': /* time limit */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_timelimit = atoi(p); + lmap->ldap_timeout.tv_sec = lmap->ldap_timelimit; + break; + + case 'Z': + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_sizelimit = atoi(p); + break; + + case 'd': /* Dn to bind to server as */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_binddn = p; + break; + + case 'M': /* Method for binding */ + while (isascii(*++p) && isspace(*p)) + continue; + + if (strncasecmp(p, "LDAP_AUTH_", 10) == 0) + p += 10; + + for (lam = LDAPAuthMethods; + lam != NULL && lam->lam_name != NULL; lam++) + { + if (strncasecmp(p, lam->lam_name, + strlen(lam->lam_name)) == 0) + break; + } + if (lam->lam_name != NULL) + lmap->ldap_method = lam->lam_code; + else + { + /* bad config line */ + if (!bitset(MCF_OPTFILE, + map->map_class->map_cflags)) + { + char *ptr; + + if ((ptr = strchr(p, ' ')) != NULL) + *ptr = '\0'; + syserr("Method for binding must be [none|simple|krbv4] not %s in map %s", + p, map->map_mname); + if (ptr != NULL) + *ptr = ' '; + return FALSE; + } + } + + break; + + /* + ** This is a string that is dependent on the + ** method used defined above. + */ + + case 'P': /* Secret password for binding */ + while (isascii(*++p) && isspace(*p)) + continue; + lmap->ldap_secret = p; + secretread = FALSE; + break; + + default: + syserr("Illegal option %c map %s", *p, map->map_mname); + break; + } + + /* need to account for quoted strings here */ + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + { + if (*p == '"') + { + while (*++p != '"' && *p != '\0') + continue; + if (*p != '\0') + p++; + } + else + p++; + } + + if (*p != '\0') + *p++ = '\0'; + } + + if (map->map_app != NULL) + map->map_app = newstr(ldapmap_dequote(map->map_app)); + if (map->map_tapp != NULL) + map->map_tapp = newstr(ldapmap_dequote(map->map_tapp)); + + /* + ** We need to swallow up all the stuff into a struct + ** and dump it into map->map_dbptr1 + */ + + if (lmap->ldap_host != NULL && + (LDAPDefaults == NULL || + LDAPDefaults == lmap || + LDAPDefaults->ldap_host != lmap->ldap_host)) + lmap->ldap_host = newstr(ldapmap_dequote(lmap->ldap_host)); + map->map_domain = lmap->ldap_host; + + if (lmap->ldap_binddn != NULL && + (LDAPDefaults == NULL || + LDAPDefaults == lmap || + LDAPDefaults->ldap_binddn != lmap->ldap_binddn)) + lmap->ldap_binddn = newstr(ldapmap_dequote(lmap->ldap_binddn)); + + if (lmap->ldap_secret != NULL && + (LDAPDefaults == NULL || + LDAPDefaults == lmap || + LDAPDefaults->ldap_secret != lmap->ldap_secret)) + { + FILE *sfd; + long sff = SFF_OPENASROOT|SFF_ROOTOK|SFF_NOWLINK|SFF_NOWWFILES|SFF_NOGWFILES; + + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + + /* need to use method to map secret to passwd string */ + switch (lmap->ldap_method) + { + case LDAP_AUTH_NONE: + /* Do nothing */ + break; + + case LDAP_AUTH_SIMPLE: + + /* + ** Secret is the name of a file with + ** the first line as the password. + */ + + /* Already read in the secret? */ + if (secretread) + break; + + sfd = safefopen(ldapmap_dequote(lmap->ldap_secret), + O_RDONLY, 0, sff); + if (sfd == NULL) + { + syserr("LDAP map: cannot open secret %s", + ldapmap_dequote(lmap->ldap_secret)); + return FALSE; + } + lmap->ldap_secret = sfgets(m_tmp, LDAPMAP_MAX_PASSWD, + sfd, 0, "ldapmap_parseargs"); + (void) fclose(sfd); + if (lmap->ldap_secret != NULL && + strlen(m_tmp) > 0) + { + /* chomp newline */ + if (m_tmp[strlen(m_tmp) - 1] == '\n') + m_tmp[strlen(m_tmp) - 1] = '\0'; + + lmap->ldap_secret = m_tmp; + } + break; + + case LDAP_AUTH_KRBV4: + + /* + ** Secret is where the ticket file is + ** stashed + */ + + snprintf(m_tmp, MAXPATHLEN + LDAPMAP_MAX_PASSWD, + "KRBTKFILE=%s", + ldapmap_dequote(lmap->ldap_secret)); + lmap->ldap_secret = m_tmp; + break; + + default: /* Should NEVER get here */ + syserr("LDAP map: Illegal value in lmap method"); + return FALSE; + break; + } + } + + if (lmap->ldap_secret != NULL && + (LDAPDefaults == NULL || + LDAPDefaults == lmap || + LDAPDefaults->ldap_secret != lmap->ldap_secret)) + lmap->ldap_secret = newstr(ldapmap_dequote(lmap->ldap_secret)); + + if (lmap->ldap_base != NULL && + (LDAPDefaults == NULL || + LDAPDefaults == lmap || + LDAPDefaults->ldap_base != lmap->ldap_base)) + lmap->ldap_base = newstr(ldapmap_dequote(lmap->ldap_base)); + + /* + ** Save the server from extra work. If request is for a single + ** match, tell the server to only return enough records to + ** determine if there is a single match or not. This can not + ** be one since the server would only return one and we wouldn't + ** know if there were others available. + */ + + if (bitset(MF_SINGLEMATCH, map->map_mflags)) + lmap->ldap_sizelimit = 2; + + /* If setting defaults, don't process ldap_filter and ldap_attr */ + if (lmap == LDAPDefaults) + return TRUE; + + if (lmap->ldap_filter != NULL) + lmap->ldap_filter = newstr(ldapmap_dequote(lmap->ldap_filter)); + else + { + if (!bitset(MCF_OPTFILE, map->map_class->map_cflags)) + { + syserr("No filter given in map %s", map->map_mname); + return FALSE; + } + } + + if (lmap->ldap_attr[0] != NULL) + { + i = 0; + p = ldapmap_dequote(lmap->ldap_attr[0]); + lmap->ldap_attr[0] = NULL; + + while (p != NULL) + { + char *v; + + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + v = p; + p = strchr(v, ','); + if (p != NULL) + *p++ = '\0'; + + if (i == LDAPMAP_MAX_ATTR) + { + syserr("Too many return attributes in %s (max %d)", + map->map_mname, LDAPMAP_MAX_ATTR); + return FALSE; + } + if (*v != '\0') + lmap->ldap_attr[i++] = newstr(v); + } + lmap->ldap_attr[i] = NULL; + } + + map->map_db1 = (ARBPTR_T) lmap; + return TRUE; +} + +/* +** LDAPMAP_CLEAR -- set default values for LDAPMAP_STRUCT +** +** Parameters: +** lmap -- pointer to LDAPMAP_STRUCT to clear +** +** Returns: +** None. +** +*/ + +static void +ldapmap_clear(lmap) + LDAPMAP_STRUCT *lmap; +{ + lmap->ldap_host = NULL; + lmap->ldap_port = LDAP_PORT; + lmap->ldap_deref = LDAP_DEREF_NEVER; + lmap->ldap_timelimit = LDAP_NO_LIMIT; + lmap->ldap_sizelimit = LDAP_NO_LIMIT; +# ifdef LDAP_REFERRALS + lmap->ldap_options = LDAP_OPT_REFERRALS; +# else /* LDAP_REFERRALS */ + lmap->ldap_options = 0; +# endif /* LDAP_REFERRALS */ + lmap->ldap_binddn = NULL; + lmap->ldap_secret = NULL; + lmap->ldap_method = LDAP_AUTH_SIMPLE; + lmap->ldap_base = NULL; + lmap->ldap_scope = LDAP_SCOPE_SUBTREE; + lmap->ldap_attrsonly = LDAPMAP_FALSE; + lmap->ldap_timeout.tv_sec = 0; + lmap->ldap_timeout.tv_usec = 0; + lmap->ldap_ld = NULL; + lmap->ldap_filter = NULL; + lmap->ldap_attr[0] = NULL; + lmap->ldap_res = NULL; +} + /* +** LDAPMAP_SET_DEFAULTS -- Read default map spec from LDAPDefaults in .cf +** +** Parameters: +** spec -- map argument string from LDAPDefaults option +** +** Returns: +** None. +** +*/ + +void +ldapmap_set_defaults(spec) + char *spec; +{ + MAP map; + + /* Allocate and set the default values */ + if (LDAPDefaults == NULL) + LDAPDefaults = (LDAPMAP_STRUCT *) xalloc(sizeof *LDAPDefaults); + ldapmap_clear(LDAPDefaults); + + memset(&map, '\0', sizeof map); + map.map_db1 = (ARBPTR_T) LDAPDefaults; + + (void) ldapmap_parseargs(&map, spec); + + /* These should never be set in LDAPDefaults */ + if (map.map_mflags != (MF_TRY0NULL|MF_TRY1NULL) || + map.map_spacesub != SpaceSub || + map.map_app != NULL || + map.map_tapp != NULL) + { + syserr("readcf: option LDAPDefaultSpec: Do not set non-LDAP specific flags"); + if (map.map_app != NULL) + { + free(map.map_app); + map.map_app = NULL; + } + if (map.map_tapp != NULL) + { + free(map.map_tapp); + map.map_tapp = NULL; + } + } + + if (LDAPDefaults->ldap_filter != NULL) + { + syserr("readcf: option LDAPDefaultSpec: Do not set the LDAP search filter"); + /* don't free, it isn't malloc'ed in parseargs */ + LDAPDefaults->ldap_filter = NULL; + } + + if (LDAPDefaults->ldap_attr[0] != NULL) + { + syserr("readcf: option LDAPDefaultSpec: Do not set the requested LDAP attributes"); + /* don't free, they aren't malloc'ed in parseargs */ + LDAPDefaults->ldap_attr[0] = NULL; + } +} +#endif /* LDAPMAP */ + /* +** PH map +*/ + +#ifdef PH_MAP + +/* +** Support for the CCSO Nameserver (ph/qi). +** This code is intended to replace the so-called "ph mailer". +** Contributed by Mark D. Roth . Contact him for support. +*/ + +# include +# include + +/* +** PH_MAP_PARSEARGS -- parse ph map definition args. +*/ + +bool +ph_map_parseargs(map, args) + MAP *map; + char *args; +{ + int i; + register int done; + PH_MAP_STRUCT *pmap = NULL; + register char *p = args; + + pmap = (PH_MAP_STRUCT *) xalloc(sizeof *pmap); + + /* defaults */ + pmap->ph_servers = NULL; + pmap->ph_field_list = NULL; + pmap->ph_to_server = NULL; + pmap->ph_from_server = NULL; + pmap->ph_sockfd = -1; + pmap->ph_timeout = 0; + + 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 't': + map->map_mflags |= MF_NODEFER; + break; + + case 'a': + map->map_app = ++p; + break; + + case 'T': + map->map_tapp = ++p; + break; + +#if _FFR_PHMAP_TIMEOUT + case 'l': + while (isascii(*++p) && isspace(*p)) + continue; + pmap->ph_timeout = atoi(p); + break; +#endif /* _FFR_PHMAP_TIMEOUT */ + + case 'S': + map->map_spacesub = *++p; + break; + + case 'D': + map->map_mflags |= MF_DEFER; + break; + + case 'h': /* PH server list */ + while (isascii(*++p) && isspace(*p)) + continue; + pmap->ph_servers = p; + break; + + case 'v': /* fields to search for */ + while (isascii(*++p) && isspace(*p)) + continue; + pmap->ph_field_list = p; + break; + + default: + syserr("ph_map_parseargs: unknown option -%c\n", *p); + } + + /* try to account for quoted strings */ + done = isascii(*p) && isspace(*p); + while (*p != '\0' && !done) + { + if (*p == '"') + { + while (*++p != '"' && *p != '\0') + continue; + if (*p != '\0') + p++; + } + else + p++; + done = isascii(*p) && isspace(*p); + } + + if (*p != '\0') + *p++ = '\0'; + } + + if (map->map_app != NULL) + map->map_app = newstr(ph_map_dequote(map->map_app)); + if (map->map_tapp != NULL) + map->map_tapp = newstr(ph_map_dequote(map->map_tapp)); + + if (pmap->ph_field_list != NULL) + pmap->ph_field_list = newstr(ph_map_dequote(pmap->ph_field_list)); + else + pmap->ph_field_list = DEFAULT_PH_MAP_FIELDS; + + if (pmap->ph_servers != NULL) + pmap->ph_servers = newstr(ph_map_dequote(pmap->ph_servers)); + else + { + syserr("ph_map_parseargs: -h flag is required"); + return FALSE; + } + + map->map_db1 = (ARBPTR_T) pmap; + return TRUE; +} + +#if _FFR_PHMAP_TIMEOUT +/* +** PH_MAP_CLOSE -- close the connection to the ph server +*/ + +static void +ph_map_safeclose(map) + MAP *map; +{ + int save_errno = errno; + PH_MAP_STRUCT *pmap; + + pmap = (PH_MAP_STRUCT *)map->map_db1; + + if (pmap->ph_sockfd != -1) + { + (void) close(pmap->ph_sockfd); + pmap->ph_sockfd = -1; + } + if (pmap->ph_from_server != NULL) + { + (void) fclose(pmap->ph_from_server); + pmap->ph_from_server = NULL; + } + if (pmap->ph_to_server != NULL) + { + (void) fclose(pmap->ph_to_server); + pmap->ph_to_server = NULL; + } + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + errno = save_errno; +} + +void +ph_map_close(map) + MAP *map; +{ + PH_MAP_STRUCT *pmap; + + pmap = (PH_MAP_STRUCT *)map->map_db1; + (void) fprintf(pmap->ph_to_server, "quit\n"); + (void) fflush(pmap->ph_to_server); + ph_map_safeclose(map); +} + +static jmp_buf PHTimeout; + +/* ARGSUSED */ +static void +ph_timeout_func(sig_no) + int sig_no; +{ + longjmp(PHTimeout, 1); +} +#else /* _FFR_PHMAP_TIMEOUT */ +/* +** PH_MAP_CLOSE -- close the connection to the ph server +*/ + +void +ph_map_close(map) + MAP *map; +{ + PH_MAP_STRUCT *pmap; + + pmap = (PH_MAP_STRUCT *)map->map_db1; + CloseQi(pmap->ph_to_server, pmap->ph_from_server); + pmap->ph_to_server = NULL; + pmap->ph_from_server = NULL; +} +#endif /* _FFR_PHMAP_TIMEOUT */ + + /* +** PH_MAP_OPEN -- sub for opening PH map +*/ +bool +ph_map_open(map, mode) + MAP *map; + int mode; +{ +#if !_FFR_PHMAP_TIMEOUT + int save_errno = 0; +#endif /* !_FFR_PHMAP_TIMEOUT */ + int j; + char *hostlist, *tmp; + QIR *server_data = NULL; + PH_MAP_STRUCT *pmap; +#if _FFR_PHMAP_TIMEOUT + register EVENT *ev = NULL; +#endif /* _FFR_PHMAP_TIMEOUT */ + + if (tTd(38, 2)) + dprintf("ph_map_open(%s)\n", map->map_mname); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + /* issue a pseudo-error message */ +# ifdef ENOSYS + errno = ENOSYS; +# else /* ENOSYS */ +# ifdef EFTYPE + errno = EFTYPE; +# else /* EFTYPE */ + errno = ENXIO; +# endif /* EFTYPE */ +# endif /* ENOSYS */ + return FALSE; + } + + pmap = (PH_MAP_STRUCT *)map->map_db1; + + hostlist = newstr(pmap->ph_servers); + tmp = strtok(hostlist, " "); + do { +#if _FFR_PHMAP_TIMEOUT + if (pmap->ph_timeout != 0) + { + if (setjmp(PHTimeout) != 0) + { + ev = NULL; + if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "timeout connecting to PH server %.100s", + tmp); +# ifdef ETIMEDOUT + errno = ETIMEDOUT; +# else /* ETIMEDOUT */ + errno = 0; +# endif /* ETIMEDOUT */ + goto ph_map_open_abort; + } + ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); + } + if (!OpenQiSock(tmp, &(pmap->ph_sockfd)) && + !Sock2FILEs(pmap->ph_sockfd, &(pmap->ph_to_server), + &(pmap->ph_from_server)) && + fprintf(pmap->ph_to_server, "id sendmail+phmap\n") >= 0 && + fflush(pmap->ph_to_server) == 0 && + (server_data = ReadQi(pmap->ph_from_server, &j)) != NULL && + server_data->code == 200) + { + if (ev != NULL) + clrevent(ev); + FreeQIR(server_data); +#else /* _FFR_PHMAP_TIMEOUT */ + if (OpenQi(tmp, &(pmap->ph_to_server), + &(pmap->ph_from_server)) >= 0) + { + if (fprintf(pmap->ph_to_server, + "id sendmail+phmap\n") < 0 || + fflush(pmap->ph_to_server) < 0 || + (server_data = ReadQi(pmap->ph_from_server, + &j)) == NULL || + server_data->code != 200) + { + save_errno = errno; + CloseQi(pmap->ph_to_server, + pmap->ph_from_server); + continue; + } + if (server_data != NULL) + FreeQIR(server_data); +#endif /* _FFR_PHMAP_TIMEOUT */ + free(hostlist); + return TRUE; + } +#if _FFR_PHMAP_TIMEOUT + ph_map_open_abort: + if (ev != NULL) + clrevent(ev); + ph_map_safeclose(map); + if (server_data != NULL) + { + FreeQIR(server_data); + server_data = NULL; + } +#else /* _FFR_PHMAP_TIMEOUT */ + save_errno = errno; +#endif /* _FFR_PHMAP_TIMEOUT */ + } while (tmp = strtok(NULL, " ")); + +#if !_FFR_PHMAP_TIMEOUT + errno = save_errno; +#endif /* !_FFR_PHMAP_TIMEOUT */ + if (!bitset(MF_OPTIONAL, map->map_mflags)) + { + if (errno == 0 && !bitset(MF_NODEFER,map->map_mflags)) + errno = EAGAIN; + syserr("ph_map_open: cannot connect to PH server"); + } + else if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "ph_map_open: cannot connect to PH server"); + free(hostlist); + return FALSE; +} + +/* +** PH_MAP_LOOKUP -- look up key from ph server +*/ + +#if _FFR_PHMAP_TIMEOUT +# define MAX_PH_FIELDS 20 +#endif /* _FFR_PHMAP_TIMEOUT */ + +char * +ph_map_lookup(map, key, args, pstat) + MAP *map; + char *key; + char **args; + int *pstat; +{ + int j; + size_t sz; + char *tmp, *tmp2; + char *message = NULL, *field = NULL, *fmtkey; + QIR *server_data = NULL; + QIR *qirp; + char keybuf[MAXKEY + 1], fieldbuf[101]; +#if _FFR_PHMAP_TIMEOUT + QIR *hold_data[MAX_PH_FIELDS]; + int hold_data_idx = 0; + register EVENT *ev = NULL; +#endif /* _FFR_PHMAP_TIMEOUT */ + PH_MAP_STRUCT *pmap; + + pmap = (PH_MAP_STRUCT *)map->map_db1; + + *pstat = EX_OK; + +#if _FFR_PHMAP_TIMEOUT + if (pmap->ph_timeout != 0) + { + if (setjmp(PHTimeout) != 0) + { + ev = NULL; + if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "timeout during PH lookup of %.100s", + key); +# ifdef ETIMEDOUT + errno = ETIMEDOUT; +# else /* ETIMEDOUT */ + errno = 0; +# endif /* ETIMEDOUT */ + *pstat = EX_TEMPFAIL; + goto ph_map_lookup_abort; + } + ev = setevent(pmap->ph_timeout, ph_timeout_func, 0); + } + +#endif /* _FFR_PHMAP_TIMEOUT */ + /* check all relevant fields */ + tmp = pmap->ph_field_list; + do { +#if _FFR_PHMAP_TIMEOUT + server_data = NULL; +#endif /* _FFR_PHMAP_TIMEOUT */ + while (isascii(*tmp) && isspace(*tmp)) + tmp++; + if (*tmp == '\0') + break; + sz = strcspn(tmp, " ") + 1; + if (sz > sizeof fieldbuf) + sz = sizeof fieldbuf; + (void) strlcpy(fieldbuf, tmp, sz); + field = fieldbuf; + tmp += sz; + + (void) strlcpy(keybuf, key, sizeof keybuf); + fmtkey = keybuf; + if (strcmp(field, "alias") == 0) + { + /* + ** for alias lookups, replace any punctuation + ** characters with '-' + */ + + for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) + { + if (isascii(*tmp2) && ispunct(*tmp2)) + *tmp2 = '-'; + } + tmp2 = field; + } + else if (strcmp(field,"spacedname") == 0) + { + /* + ** for "spaced" name lookups, replace any + ** punctuation characters with a space + */ + + for (tmp2 = fmtkey; *tmp2 != '\0'; tmp2++) + { + if (isascii(*tmp2) && ispunct(*tmp2) && + *tmp2 != '*') + *tmp2 = ' '; + } + tmp2 = &(field[6]); + } + else + tmp2 = field; + + if (LogLevel > 9) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "ph_map_lookup: query %s=\"%s\" return email", + tmp2, fmtkey); + if (tTd(38, 20)) + dprintf("ph_map_lookup: query %s=\"%s\" return email\n", + tmp2, fmtkey); + + j = 0; + + if (fprintf(pmap->ph_to_server, "query %s=%s return email\n", + tmp2, fmtkey) < 0) + message = "qi query command failed"; + else if (fflush(pmap->ph_to_server) < 0) + message = "qi fflush failed"; + else if ((server_data = ReadQi(pmap->ph_from_server, + &j)) == NULL) + message = "ReadQi() returned NULL"; + +#if _FFR_PHMAP_TIMEOUT + if ((hold_data[hold_data_idx] = server_data) != NULL) + { + /* save pointer for later free() */ + hold_data_idx++; + } +#endif /* _FFR_PHMAP_TIMEOUT */ + + if (server_data == NULL || + (server_data->code >= 400 && + server_data->code < 500)) + { + /* temporary failure */ + *pstat = EX_TEMPFAIL; +#if _FFR_PHMAP_TIMEOUT + break; +#else /* _FFR_PHMAP_TIMEOUT */ + if (server_data != NULL) + { + FreeQIR(server_data); + server_data = NULL; + } + return NULL; +#endif /* _FFR_PHMAP_TIMEOUT */ + } + + /* + ** if we found a single match, break out. + ** otherwise, try the next field. + */ + + if (j == 1) + break; + + /* + ** check for a single response which is an error: + ** ReadQi() doesn't set j on error responses, + ** but we should stop here instead of moving on if + ** it happens (e.g., alias found but email field empty) + */ + + for (qirp = server_data; + qirp != NULL && qirp->code < 0; + qirp++) + { + if (tTd(38, 20)) + dprintf("ph_map_lookup: QIR: %d:%d:%d:%s\n", + qirp->code, qirp->subcode, qirp->field, + (qirp->message ? qirp->message + : "[NULL]")); + if (qirp->code <= -500) + { + j = 0; + goto ph_map_lookup_abort; + } + } + +#if _FFR_PHMAP_TIMEOUT + } while (*tmp != '\0' && hold_data_idx < MAX_PH_FIELDS); +#else /* _FFR_PHMAP_TIMEOUT */ + } while (*tmp != '\0'); +#endif /* _FFR_PHMAP_TIMEOUT */ + + ph_map_lookup_abort: +#if _FFR_PHMAP_TIMEOUT + if (ev != NULL) + clrevent(ev); + + /* + ** Return EX_TEMPFAIL if the timer popped + ** or we got a temporary PH error + */ + + if (*pstat == EX_TEMPFAIL) + ph_map_safeclose(map); + + /* if we didn't find a single match, bail out */ + if (*pstat == EX_OK && j != 1) + *pstat = EX_UNAVAILABLE; + + if (*pstat == EX_OK) + { + /* + ** skip leading whitespace and chop at first address + */ + + for (tmp = server_data->message; + isascii(*tmp) && isspace(*tmp); + tmp++) + continue; + + for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) + { + if (isascii(*tmp2) && isspace(*tmp2)) + { + *tmp2 = '\0'; + break; + } + } + + if (tTd(38,20)) + dprintf("ph_map_lookup: %s => %s\n", key, tmp); + + if (bitset(MF_MATCHONLY, map->map_mflags)) + message = map_rewrite(map, key, strlen(key), NULL); + else + message = map_rewrite(map, tmp, strlen(tmp), args); + } + + /* + ** Deferred free() of returned server_data values + ** the deferral is to avoid the risk of a free() being + ** interrupted by the event timer. By now the timeout event + ** has been cleared and none of the data is still in use. + */ + + while (--hold_data_idx >= 0) + { + if (hold_data[hold_data_idx] != NULL) + FreeQIR(hold_data[hold_data_idx]); + } + + if (*pstat == EX_OK) + return message; + + return NULL; +#else /* _FFR_PHMAP_TIMEOUT */ + /* if we didn't find a single match, bail out */ + if (j != 1) + { + *pstat = EX_UNAVAILABLE; + if (server_data != NULL) + { + FreeQIR(server_data); + server_data = NULL; + } + return NULL; + } + + /* + ** skip leading whitespace and chop at first address + */ + + for (tmp = server_data->message; + isascii(*tmp) && isspace(*tmp); + tmp++) + continue; + + for (tmp2 = tmp; *tmp2 != '\0'; tmp2++) + { + if (isascii(*tmp2) && isspace(*tmp2)) + { + *tmp2 = '\0'; + break; + } + } + + if (tTd(38,20)) + dprintf("ph_map_lookup: %s => %s\n", key, tmp); + + if (bitset(MF_MATCHONLY, map->map_mflags)) + message = map_rewrite(map, key, strlen(key), NULL); + else + message = map_rewrite(map, tmp, strlen(tmp), args); + if (server_data != NULL) + { + FreeQIR(server_data); + server_data = NULL; + } + return message; +#endif /* _FFR_PHMAP_TIMEOUT */ +} +#endif /* PH_MAP */ + /* +** syslog map +*/ + +#define map_prio map_lockfd /* overload field */ + +/* +** SYSLOG_MAP_PARSEARGS -- check for priority level to syslog messages. +*/ + +bool +syslog_map_parseargs(map, args) + MAP *map; + char *args; +{ + char *p = args; + char *priority = NULL; + + /* there is no check whether there is really an argument */ + while (*p != '\0') + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p != '-') + break; + ++p; + if (*p == 'D') + { + map->map_mflags |= MF_DEFER; + ++p; + } + else if (*p == 'S') + { + map->map_spacesub = *++p; + if (*p != '\0') + p++; + } + else if (*p == 'L') + { + while (*++p != '\0' && isascii(*p) && isspace(*p)) + continue; + if (*p == '\0') + break; + priority = p; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + else + { + syserr("Illegal option %c map syslog", *p); + ++p; + } + } + + if (priority == NULL) + map->map_prio = LOG_INFO; + else + { + if (strncasecmp("LOG_", priority, 4) == 0) + priority += 4; + +#ifdef LOG_EMERG + if (strcasecmp("EMERG", priority) == 0) + map->map_prio = LOG_EMERG; + else +#endif /* LOG_EMERG */ +#ifdef LOG_ALERT + if (strcasecmp("ALERT", priority) == 0) + map->map_prio = LOG_ALERT; + else +#endif /* LOG_ALERT */ +#ifdef LOG_CRIT + if (strcasecmp("CRIT", priority) == 0) + map->map_prio = LOG_CRIT; + else +#endif /* LOG_CRIT */ +#ifdef LOG_ERR + if (strcasecmp("ERR", priority) == 0) + map->map_prio = LOG_ERR; + else +#endif /* LOG_ERR */ +#ifdef LOG_WARNING + if (strcasecmp("WARNING", priority) == 0) + map->map_prio = LOG_WARNING; + else +#endif /* LOG_WARNING */ +#ifdef LOG_NOTICE + if (strcasecmp("NOTICE", priority) == 0) + map->map_prio = LOG_NOTICE; + else +#endif /* LOG_NOTICE */ +#ifdef LOG_INFO + if (strcasecmp("INFO", priority) == 0) + map->map_prio = LOG_INFO; + else +#endif /* LOG_INFO */ +#ifdef LOG_DEBUG + if (strcasecmp("DEBUG", priority) == 0) + map->map_prio = LOG_DEBUG; + else +#endif /* LOG_DEBUG */ + { + syserr("syslog_map_parseargs: Unknown priority %s\n", + priority); + return FALSE; + } + } + return TRUE; +} + +/* +** SYSLOG_MAP_LOOKUP -- rewrite and syslog message. Always return empty string +*/ + +char * +syslog_map_lookup(map, string, args, statp) + MAP *map; + char *string; + char **args; + int *statp; +{ + char *ptr = map_rewrite(map, string, strlen(string), args); + + if (ptr != NULL) + { + if (tTd(38, 20)) + dprintf("syslog_map_lookup(%s (priority %d): %s\n", + map->map_mname, map->map_prio, ptr); + + sm_syslog(map->map_prio, CurEnv->e_id, "%s", ptr); + } + + *statp = EX_OK; + return ""; +} + + /* +** HESIOD Modules +*/ + +#ifdef HESIOD + +bool +hes_map_open(map, mode) + MAP *map; + int mode; +{ + if (tTd(38, 2)) + dprintf("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 /* ENOSYS */ +# ifdef EFTYPE + errno = EFTYPE; +# else /* EFTYPE */ + errno = ENXIO; +# endif /* EFTYPE */ +# endif /* ENOSYS */ + return FALSE; + } + +# ifdef HESIOD_INIT + if (HesiodContext != NULL || hesiod_init(&HesiodContext) == 0) + return TRUE; + + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("421 4.0.0 cannot initialize Hesiod map (%s)", + errstring(errno)); + return FALSE; +# else /* HESIOD_INIT */ + 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 4.0.0 cannot initialize Hesiod map (%d)", hes_error()); + + return FALSE; +# endif /* HESIOD_INIT */ +} + +char * +hes_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + char **hp; + + if (tTd(38, 20)) + dprintf("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] = '\\'; + (void) strlcpy(&np[1], name, (sizeof nbuf) - 1); +# ifdef HESIOD_INIT + hp = hesiod_resolve(HesiodContext, np, map->map_file); +# else /* HESIOD_INIT */ + hp = hes_resolve(np, map->map_file); +# endif /* HESIOD_INIT */ + if (np != nbuf) + free(np); + } + else + { +# ifdef HESIOD_INIT + hp = hesiod_resolve(HesiodContext, name, map->map_file); +# else /* HESIOD_INIT */ + hp = hes_resolve(name, map->map_file); +# endif /* HESIOD_INIT */ + } +# ifdef HESIOD_INIT + if (hp == NULL) + return NULL; + if (*hp == NULL) + { + hesiod_free_list(HesiodContext, hp); + switch (errno) + { + case ENOENT: + *statp = EX_NOTFOUND; + break; + case ECONNREFUSED: + case EMSGSIZE: + *statp = EX_TEMPFAIL; + break; + case ENOMEM: + default: + *statp = EX_UNAVAILABLE; + break; + } + return NULL; + } +# else /* HESIOD_INIT */ + 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; + } +# endif /* HESIOD_INIT */ + + 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 /* HESIOD */ + /* +** NeXT NETINFO Modules +*/ + +#if NETINFO + +# define NETINFO_DEFAULT_DIR "/aliases" +# define NETINFO_DEFAULT_PROPERTY "members" + +/* +** NI_MAP_OPEN -- open NetInfo Aliases +*/ + +bool +ni_map_open(map, mode) + MAP *map; + int mode; +{ + if (tTd(38, 2)) + dprintf("ni_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + mode &= O_ACCMODE; + + 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)) + dprintf("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; +} + + +static bool +ni_getcanonname(name, hbsize, statp) + char *name; + int hbsize; + int *statp; +{ + char *vptr; + char *ptr; + char nbuf[MAXNAME + 1]; + + if (tTd(38, 20)) + dprintf("ni_getcanonname(%s)\n", name); + + if (strlcpy(nbuf, name, sizeof nbuf) >= sizeof nbuf) + { + *statp = EX_UNAVAILABLE; + return FALSE; + } + 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", '\n'); + + if (vptr == NULL) + { + *statp = EX_NOHOST; + return FALSE; + } + + /* Only want the first machine name */ + if ((ptr = strchr(vptr, '\n')) != NULL) + *ptr = '\0'; + + if (hbsize >= strlen(vptr)) + { + (void) strlcpy(name, vptr, hbsize); + free(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 occurred +** 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 + +# 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, l; + 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; + (void) strlcpy(keybuf, keydir, sizeof keybuf); + (void) strlcat(keybuf, "/", sizeof keybuf); + if (keyprop != NULL) + { + (void) strlcat(keybuf, keyprop, sizeof keybuf); + (void) strlcat(keybuf, "=", sizeof keybuf); + } + (void) strlcat(keybuf, keyval, sizeof keybuf); + + if (tTd(38, 21)) + dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", + keydir, keyprop, keyval, valprop, sepchar, keybuf); + /* + ** 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 && propval == NULL; i++) + { + if (i == 0) + { + nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); + if (tTd(38, 20)) + dprintf("ni_open(LOCAL) = %d\n", nis); + } + else + { + if (lastni != NULL) + ni_free(lastni); + lastni = ni; + nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); + if (tTd(38, 20)) + dprintf("ni_open(PARENT) = %d\n", nis); + } + + /* + ** 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; + + if (tTd(38, 20)) + dprintf("ni_lookupprop: len=%d\n", + ninl.ni_namelist_len); + + /* + ** 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++) + { + (void) strlcpy(p, ninl.ni_namelist_val[j], alen); + l = strlen(p); + p += l; + *p++ = sepchar; + alen -= l + 1; + } + *--p = '\0'; + + ni_namelist_free(&ninl); + } + + /* + ** Clean up. + */ + + if (ni != NULL) + ni_free(ni); + if (lastni != NULL && ni != lastni) + ni_free(lastni); + if (tTd(38, 20)) + dprintf("ni_propval returns: '%s'\n", propval); + + return propval; +} + +#endif /* NETINFO */ + /* +** TEXT (unindexed text file) Modules +** +** This code donated by Sun Microsystems. +*/ + +#define map_sff map_lockfd /* overload field */ + + +/* +** TEXT_MAP_OPEN -- open text table +*/ + +bool +text_map_open(map, mode) + MAP *map; + int mode; +{ + long sff; + int i; + + if (tTd(38, 2)) + dprintf("text_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + errno = EPERM; + return FALSE; + } + + if (*map->map_file == '\0') + { + syserr("text map \"%s\": file name required", + map->map_mname); + return FALSE; + } + + if (map->map_file[0] != '/') + { + syserr("text map \"%s\": file name must be fully qualified", + map->map_mname); + return FALSE; + } + + sff = SFF_ROOTOK|SFF_REGONLY; + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + if ((i = safefile(map->map_file, RunAsUid, RunAsGid, RunAsUserName, + sff, S_IRUSR, NULL)) != 0) + { + int save_errno = errno; + + /* cannot open this map */ + if (tTd(38, 2)) + dprintf("\tunsafe map file: %d\n", i); + errno = save_errno; + if (!bitset(MF_OPTIONAL, map->map_mflags)) + syserr("text map \"%s\": unsafe map file %s", + map->map_mname, map->map_file); + return FALSE; + } + + if (map->map_keycolnm == NULL) + map->map_keycolno = 0; + else + { + if (!(isascii(*map->map_keycolnm) && isdigit(*map->map_keycolnm))) + { + syserr("text map \"%s\", file %s: -k should specify a number, not %s", + 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 (!(isascii(*map->map_valcolnm) && isdigit(*map->map_valcolnm))) + { + syserr("text map \"%s\", file %s: -v should specify a number, not %s", + map->map_mname, map->map_file, + map->map_valcolnm); + return FALSE; + } + map->map_valcolno = atoi(map->map_valcolnm); + } + + if (tTd(38, 2)) + { + dprintf("text_map_open(%s, %s): delimiter = ", + map->map_mname, map->map_file); + if (map->map_coldelim == '\0') + dprintf("(white space)\n"); + else + dprintf("%c\n", map->map_coldelim); + } + + map->map_sff = sff; + 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; + FILE *f; + char delim; + int key_idx; + bool found_it; + long sff = map->map_sff; + char search_key[MAXNAME + 1]; + char linebuf[MAXLINE]; + char buf[MAXNAME + 1]; + + found_it = FALSE; + if (tTd(38, 20)) + dprintf("text_map_lookup(%s, %s)\n", map->map_mname, name); + + buflen = strlen(name); + if (buflen > sizeof search_key - 1) + buflen = sizeof search_key - 1; + memmove(search_key, name, buflen); + search_key[buflen] = '\0'; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(search_key); + + f = safefopen(map->map_file, O_RDONLY, FileMode, sff); + 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, sizeof buf); + if (p != NULL && strcasecmp(search_key, p) == 0) + { + found_it = TRUE; + break; + } + } + (void) fclose(f); + if (!found_it) + { + *statp = EX_NOTFOUND; + return NULL; + } + vp = get_column(linebuf, map->map_valcolno, delim, buf, sizeof buf); + if (vp == NULL) + { + *statp = EX_NOTFOUND; + return NULL; + } + 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 +*/ + +static bool +text_getcanonname(name, hbsize, statp) + char *name; + int hbsize; + int *statp; +{ + bool found; + FILE *f; + char linebuf[MAXLINE]; + char cbuf[MAXNAME + 1]; + char nbuf[MAXNAME + 1]; + + if (tTd(38, 20)) + dprintf("text_getcanonname(%s)\n", name); + + if (strlen(name) >= (SIZE_T) sizeof nbuf) + { + *statp = EX_UNAVAILABLE; + return FALSE; + } + (void) strlcpy(nbuf, name, sizeof nbuf); + 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, sizeof cbuf); + } + (void) fclose(f); + if (!found) + { + *statp = EX_NOHOST; + return FALSE; + } + + if ((SIZE_T) hbsize >= strlen(cbuf)) + { + (void) strlcpy(name, cbuf, hbsize); + *statp = EX_OK; + return TRUE; + } + *statp = EX_UNAVAILABLE; + return FALSE; +} + /* +** STAB (Symbol Table) Modules +*/ + + +/* +** STAB_MAP_LOOKUP -- look up alias in symbol table +*/ + +/* ARGSUSED2 */ +char * +stab_map_lookup(map, name, av, pstat) + register MAP *map; + char *name; + char **av; + int *pstat; +{ + register STAB *s; + + if (tTd(38, 20)) + dprintf("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; + long sff; + struct stat st; + + if (tTd(38, 2)) + dprintf("stab_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + errno = EPERM; + return FALSE; + } + + sff = SFF_ROOTOK|SFF_REGONLY; + if (!bitnset(DBS_LINKEDMAPINWRITABLEDIR, DontBlameSendmail)) + sff |= SFF_NOWLINK; + if (!bitnset(DBS_MAPINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + af = safefopen(map->map_file, O_RDONLY, 0444, sff); + if (af == NULL) + return FALSE; + readaliases(map, af, FALSE, FALSE); + + if (fstat(fileno(af), &st) >= 0) + map->map_mtime = st.st_mtime; + (void) 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)) + dprintf("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 /* NEWDB */ +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + return ndbm_map_lookup(map, name, av, pstat); +#endif /* NDBM */ + 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)) + dprintf("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 /* NEWDB */ +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + ndbm_map_store(map, lhs, rhs); +#endif /* NDBM */ + 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)) + dprintf("impl_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; +#ifdef NEWDB + map->map_mflags |= MF_IMPL_HASH; + if (hash_map_open(map, mode)) + { +# ifdef NDBM_YP_COMPAT + if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL) +# endif /* NDBM_YP_COMPAT */ + return TRUE; + } + else + map->map_mflags &= ~MF_IMPL_HASH; +#endif /* NEWDB */ +#ifdef NDBM + map->map_mflags |= MF_IMPL_NDBM; + if (ndbm_map_open(map, mode)) + { + return TRUE; + } + else + map->map_mflags &= ~MF_IMPL_NDBM; +#endif /* NDBM */ + +#if defined(NEWDB) || defined(NDBM) + if (Verbose) + message("WARNING: cannot open alias database %s%s", + map->map_file, + mode == O_RDONLY ? "; reading text version" : ""); +#else /* defined(NEWDB) || defined(NDBM) */ + if (mode != O_RDONLY) + usrerr("Cannot rebuild aliases: no database format defined"); +#endif /* defined(NEWDB) || defined(NDBM) */ + + if (mode == O_RDONLY) + return stab_map_open(map, mode); + else + return FALSE; +} + + +/* +** IMPL_MAP_CLOSE -- close any open database(s) +*/ + +void +impl_map_close(map) + MAP *map; +{ + if (tTd(38, 9)) + dprintf("impl_map_close(%s, %s, %lx)\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 /* NEWDB */ + +#ifdef NDBM + if (bitset(MF_IMPL_NDBM, map->map_mflags)) + { + ndbm_map_close(map); + map->map_mflags &= ~MF_IMPL_NDBM; + } +#endif /* NDBM */ +} + /* +** 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)) + dprintf("user_map_open(%s, %d)\n", + map->map_mname, mode); + + mode &= O_ACCMODE; + if (mode != O_RDONLY) + { + /* issue a pseudo-error message */ +#ifdef ENOSYS + errno = ENOSYS; +#else /* ENOSYS */ +# ifdef EFTYPE + errno = EFTYPE; +# else /* EFTYPE */ + errno = ENXIO; +# endif /* EFTYPE */ +#endif /* ENOSYS */ + return FALSE; + } + if (map->map_valcolnm == NULL) + /* EMPTY */ + /* 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. +*/ + +/* ARGSUSED3 */ +char * +user_map_lookup(map, key, av, statp) + MAP *map; + char *key; + char **av; + int *statp; +{ + struct passwd *pw; + auto bool fuzzy; + + if (tTd(38, 20)) + dprintf("user_map_lookup(%s, %s)\n", + map->map_mname, key); + + pw = finduser(key, &fuzzy); + 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: + snprintf(buf, sizeof buf, "%d", (int) pw->pw_uid); + rwval = buf; + break; + + case 4: + snprintf(buf, sizeof buf, "%d", (int) 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; + int save_errno; + int fd; + int status; + auto pid_t pid; + register char *p; + char *rval; + char *argv[MAXPV + 1]; + char buf[MAXLINE]; + + if (tTd(38, 20)) + dprintf("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) + { + snprintf(buf, sizeof buf, "%s", 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)) + { + dprintf("prog_open:"); + for (i = 0; argv[i] != NULL; i++) + dprintf(" %s", argv[i]); + dprintf("\n"); + } + (void) blocksignal(SIGCHLD); + 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)) + dprintf("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) + { + if (tTd(38, 20)) + dprintf("prog_map_lookup(%s): empty answer\n", + map->map_mname); + rval = NULL; + } + else + { + 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 */ + (void) close(fd); + status = waitfor(pid); + save_errno = errno; + (void) releasesignal(SIGCHLD); + errno = save_errno; + + if (status == -1) + { + syserr("prog_map_lookup(%s): wait error %s\n", + map->map_mname, errstring(errno)); + *statp = EX_SOFTWARE; + rval = NULL; + } + else if (WIFEXITED(status)) + { + if ((*statp = WEXITSTATUS(status)) != EX_OK) + rval = NULL; + } + else + { + syserr("prog_map_lookup(%s): child died on signal %d", + map->map_mname, status); + *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)) + dprintf("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 == '_' || *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)) + dprintf("switch_map_open(%s, %s, %d)\n", + map->map_mname, map->map_file, mode); + + mode &= O_ACCMODE; + nmaps = switch_map_find(map->map_file, maptype, map->map_return); + if (tTd(38, 19)) + { + dprintf("\tswitch_map_find => %d\n", nmaps); + for (mapno = 0; mapno < nmaps; mapno++) + dprintf("\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) snprintf(nbuf, sizeof 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)) + dprintf("\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)) + dprintf("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)) + dprintf("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) && + !openmap(mm)) + { + 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)) + dprintf("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 +*/ + +/* ARGSUSED */ +bool +null_map_open(map, mode) + MAP *map; + int mode; +{ + return TRUE; +} + +/* ARGSUSED */ +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; +} + +/* ARGSUSED */ +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, +}; + /* +** MACRO modules +*/ + +char * +macro_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int mid; + + if (tTd(38, 20)) + dprintf("macro_map_lookup(%s, %s)\n", map->map_mname, + name == NULL ? "NULL" : name); + + if (name == NULL || + *name == '\0' || + (mid = macid(name, NULL)) == '\0') + { + *statp = EX_CONFIG; + return NULL; + } + + if (av[1] == NULL) + define(mid, NULL, CurEnv); + else + define(mid, newstr(av[1]), CurEnv); + + *statp = EX_OK; + return ""; +} + /* +** REGEX modules +*/ + +#ifdef MAP_REGEX + +# include + +# define DEFAULT_DELIM CONDELSE + +# define END_OF_FIELDS -1 + +# define ERRBUF_SIZE 80 +# define MAX_MATCH 32 + +# define xnalloc(s) memset(xalloc(s), '\0', s); + +struct regex_map +{ + regex_t regex_pattern_buf; /* xalloc it */ + int *regex_subfields; /* move to type MAP */ + char *regex_delim; /* move to type MAP */ +}; + +static int +parse_fields(s, ibuf, blen, nr_substrings) + char *s; + int *ibuf; /* array */ + int blen; /* number of elements in ibuf */ + int nr_substrings; /* number of substrings in the pattern */ +{ + register char *cp; + int i = 0; + bool lastone = FALSE; + + blen--; /* for terminating END_OF_FIELDS */ + cp = s; + do + { + for (;; cp++) + { + if (*cp == ',') + { + *cp = '\0'; + break; + } + if (*cp == '\0') + { + lastone = TRUE; + break; + } + } + if (i < blen) + { + int val = atoi(s); + + if (val < 0 || val >= nr_substrings) + { + syserr("field (%d) out of range, only %d substrings in pattern", + val, nr_substrings); + return -1; + } + ibuf[i++] = val; + } + else + { + syserr("too many fields, %d max\n", blen); + return -1; + } + s = ++cp; + } while (!lastone); + ibuf[i] = END_OF_FIELDS; + return i; +} + +bool +regex_map_init(map, ap) + MAP *map; + char *ap; +{ + int regerr; + struct regex_map *map_p; + register char *p; + char *sub_param = NULL; + int pflags; + static char defdstr[] = { (char)DEFAULT_DELIM, '\0' }; + + if (tTd(38, 2)) + dprintf("regex_map_init: mapname '%s', args '%s'\n", + map->map_mname, ap); + + pflags = REG_ICASE | REG_EXTENDED | REG_NOSUB; + + p = ap; + + map_p = (struct regex_map *) xnalloc(sizeof *map_p); + + for (;;) + { + while (isascii(*p) && isspace(*p)) + p++; + if (*p != '-') + break; + switch (*++p) + { + case 'n': /* not */ + map->map_mflags |= MF_REGEX_NOT; + break; + + case 'f': /* case sensitive */ + map->map_mflags |= MF_NOFOLDCASE; + pflags &= ~REG_ICASE; + break; + + case 'b': /* basic regular expressions */ + pflags &= ~REG_EXTENDED; + break; + + case 's': /* substring match () syntax */ + sub_param = ++p; + pflags &= ~REG_NOSUB; + break; + + case 'd': /* delimiter */ + map_p->regex_delim = ++p; + break; + + case 'a': /* map append */ + map->map_app = ++p; + break; + + case 'm': /* matchonly */ + map->map_mflags |= MF_MATCHONLY; + break; + + case 'S': + map->map_spacesub = *++p; + break; + + case 'D': + map->map_mflags |= MF_DEFER; + break; + + } + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p != '\0') + *p++ = '\0'; + } + if (tTd(38, 3)) + dprintf("regex_map_init: compile '%s' 0x%x\n", p, pflags); + + if ((regerr = regcomp(&(map_p->regex_pattern_buf), p, pflags)) != 0) + { + /* Errorhandling */ + char errbuf[ERRBUF_SIZE]; + + (void) regerror(regerr, &(map_p->regex_pattern_buf), + errbuf, ERRBUF_SIZE); + syserr("pattern-compile-error: %s\n", errbuf); + free(map_p); + return FALSE; + } + + if (map->map_app != NULL) + map->map_app = newstr(map->map_app); + if (map_p->regex_delim != NULL) + map_p->regex_delim = newstr(map_p->regex_delim); + else + map_p->regex_delim = defdstr; + + if (!bitset(REG_NOSUB, pflags)) + { + /* substring matching */ + int substrings; + int *fields = (int *) xalloc(sizeof(int) * (MAX_MATCH + 1)); + + substrings = map_p->regex_pattern_buf.re_nsub + 1; + + if (tTd(38, 3)) + dprintf("regex_map_init: nr of substrings %d\n", + substrings); + + if (substrings >= MAX_MATCH) + { + syserr("too many substrings, %d max\n", MAX_MATCH); + free(map_p); + return FALSE; + } + if (sub_param != NULL && sub_param[0] != '\0') + { + /* optional parameter -sfields */ + if (parse_fields(sub_param, fields, + MAX_MATCH + 1, substrings) == -1) + return FALSE; + } + else + { + /* set default fields */ + int i; + + for (i = 0; i < substrings; i++) + fields[i] = i; + fields[i] = END_OF_FIELDS; + } + map_p->regex_subfields = fields; + if (tTd(38, 3)) + { + int *ip; + + dprintf("regex_map_init: subfields"); + for (ip = fields; *ip != END_OF_FIELDS; ip++) + dprintf(" %d", *ip); + dprintf("\n"); + } + } + map->map_db1 = (ARBPTR_T)map_p; /* dirty hack */ + + return TRUE; +} + +static char * +regex_map_rewrite(map, s, slen, av) + MAP *map; + const char *s; + size_t slen; + char **av; +{ + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, av[0], strlen(av[0]), NULL); + else + return map_rewrite(map, s, slen, NULL); +} + +char * +regex_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int reg_res; + struct regex_map *map_p; + regmatch_t pmatch[MAX_MATCH]; + + if (tTd(38, 20)) + { + char **cpp; + + dprintf("regex_map_lookup: key '%s'\n", name); + for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) + dprintf("regex_map_lookup: arg '%s'\n", *cpp); + } + + map_p = (struct regex_map *)(map->map_db1); + reg_res = regexec(&(map_p->regex_pattern_buf), + name, MAX_MATCH, pmatch, 0); + + if (bitset(MF_REGEX_NOT, map->map_mflags)) + { + /* option -n */ + if (reg_res == REG_NOMATCH) + return regex_map_rewrite(map, "", (size_t)0, av); + else + return NULL; + } + if (reg_res == REG_NOMATCH) + return NULL; + + if (map_p->regex_subfields != NULL) + { + /* option -s */ + static char retbuf[MAXNAME]; + int fields[MAX_MATCH + 1]; + bool first = TRUE; + int anglecnt = 0, cmntcnt = 0, spacecnt = 0; + bool quotemode = FALSE, bslashmode = FALSE; + register char *dp, *sp; + char *endp, *ldp; + int *ip; + + dp = retbuf; + ldp = retbuf + sizeof(retbuf) - 1; + + if (av[1] != NULL) + { + if (parse_fields(av[1], fields, MAX_MATCH + 1, + (int) map_p->regex_pattern_buf.re_nsub + 1) == -1) + { + *statp = EX_CONFIG; + return NULL; + } + ip = fields; + } + else + ip = map_p->regex_subfields; + + for ( ; *ip != END_OF_FIELDS; ip++) + { + if (!first) + { + for (sp = map_p->regex_delim; *sp; sp++) + { + if (dp < ldp) + *dp++ = *sp; + } + } + else + first = FALSE; + + + if (pmatch[*ip].rm_so < 0 || pmatch[*ip].rm_eo < 0) + continue; + + sp = name + pmatch[*ip].rm_so; + endp = name + pmatch[*ip].rm_eo; + for (; endp > sp; sp++) + { + if (dp < ldp) + { + if (bslashmode) + { + *dp++ = *sp; + bslashmode = FALSE; + } + else if (quotemode && *sp != '"' && + *sp != '\\') + { + *dp++ = *sp; + } + else switch(*dp++ = *sp) + { + case '\\': + bslashmode = TRUE; + break; + + case '(': + cmntcnt++; + break; + + case ')': + cmntcnt--; + break; + + case '<': + anglecnt++; + break; + + case '>': + anglecnt--; + break; + + case ' ': + spacecnt++; + break; + + case '"': + quotemode = !quotemode; + break; + } + } + } + } + if (anglecnt != 0 || cmntcnt != 0 || quotemode || + bslashmode || spacecnt != 0) + { + sm_syslog(LOG_WARNING, NOQID, + "Warning: regex may cause prescan() failure map=%s lookup=%s", + map->map_mname, name); + return NULL; + } + + *dp = '\0'; + + return regex_map_rewrite(map, retbuf, strlen(retbuf), av); + } + return regex_map_rewrite(map, "", (size_t)0, av); +} +#endif /* MAP_REGEX */ + /* +** NSD modules +*/ +#ifdef MAP_NSD + +# include +# define _DATUM_DEFINED +# include + +typedef struct ns_map_list +{ + ns_map_t *map; + char *mapname; + struct ns_map_list *next; +} ns_map_list_t; + +static ns_map_t * +ns_map_t_find(mapname) + char *mapname; +{ + static ns_map_list_t *ns_maps = NULL; + ns_map_list_t *ns_map; + + /* walk the list of maps looking for the correctly named map */ + for (ns_map = ns_maps; ns_map != NULL; ns_map = ns_map->next) + { + if (strcmp(ns_map->mapname, mapname) == 0) + break; + } + + /* if we are looking at a NULL ns_map_list_t, then create a new one */ + if (ns_map == NULL) + { + ns_map = (ns_map_list_t *) xalloc(sizeof *ns_map); + ns_map->mapname = newstr(mapname); + ns_map->map = (ns_map_t *) xalloc(sizeof *ns_map->map); + ns_map->next = ns_maps; + ns_maps = ns_map; + } + return ns_map->map; +} + +char * +nsd_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int buflen; + char *p; + ns_map_t *ns_map; + char keybuf[MAXNAME + 1]; + char buf[MAXLINE]; + + if (tTd(38, 20)) + dprintf("nsd_map_lookup(%s, %s)\n", map->map_mname, name); + + buflen = strlen(name); + if (buflen > sizeof keybuf - 1) + buflen = sizeof keybuf - 1; + memmove(keybuf, name, buflen); + keybuf[buflen] = '\0'; + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) + makelower(keybuf); + + ns_map = ns_map_t_find(map->map_file); + if (ns_map == NULL) + { + if (tTd(38, 20)) + dprintf("nsd_map_t_find failed\n"); + return NULL; + } + + if (ns_lookup(ns_map, NULL, map->map_file, + keybuf, NULL, buf, MAXLINE) == NULL) + return NULL; + + /* Null out trailing \n */ + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + + return map_rewrite(map, buf, strlen(buf), av); +} +#endif /* MAP_NSD */ + +char * +arith_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + long r; + long v[2]; + bool res = FALSE; + bool boolres; + static char result[16]; + char **cpp; + + if (tTd(38, 2)) + { + dprintf("arith_map_lookup: key '%s'\n", name); + for (cpp = av; cpp != NULL && *cpp != NULL; cpp++) + dprintf("arith_map_lookup: arg '%s'\n", *cpp); + } + r = 0; + boolres = FALSE; + cpp = av; + *statp = EX_OK; + + /* + ** read arguments for arith map + ** - no check is made whether they are really numbers + ** - just ignores args after the second + */ + for (++cpp; cpp != NULL && *cpp != NULL && r < 2; cpp++) + v[r++] = strtol(*cpp, NULL, 0); + + /* operator and (at least) two operands given? */ + if (name != NULL && r == 2) + { + switch(*name) + { +#if _FFR_ARITH + case '|': + r = v[0] | v[1]; + break; + + case '&': + r = v[0] & v[1]; + break; + + case '%': + if (v[1] == 0) + return NULL; + r = v[0] % v[1]; + break; +#endif /* _FFR_ARITH */ + + case '+': + r = v[0] + v[1]; + break; + + case '-': + r = v[0] - v[1]; + break; + + case '*': + r = v[0] * v[1]; + break; + + case '/': + if (v[1] == 0) + return NULL; + r = v[0] / v[1]; + break; + + case 'l': + res = v[0] < v[1]; + boolres = TRUE; + break; + + case '=': + res = v[0] == v[1]; + boolres = TRUE; + break; + + default: + /* XXX */ + *statp = EX_CONFIG; + if (LogLevel > 10) + sm_syslog(LOG_WARNING, NOQID, + "arith_map: unknown operator %c", + isprint(*name) ? *name : '?'); + return NULL; + } + if (boolres) + snprintf(result, sizeof result, res ? "TRUE" : "FALSE"); + else + snprintf(result, sizeof result, "%ld", r); + return result; + } + *statp = EX_CONFIG; + return NULL; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/mci.c b/gnu/usr.sbin/sendmail/sendmail/mci.c new file mode 100644 index 00000000000..7e2da09ad4f --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/mci.c @@ -0,0 +1,1387 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: mci.c,v 8.133 2000/01/18 01:19:07 ca Exp $"; +#endif /* ! lint */ + +#include +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ +#include + +static int mci_generate_persistent_path __P((const char *, char *, + int, bool)); +static bool mci_load_persistent __P((MCI *)); +static void mci_uncache __P((MCI **, bool)); +static int mci_lock_host_statfile __P((MCI *)); +static int mci_read_persistent __P((FILE *, MCI *)); + +/* +** 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. +** +** The persistent MCI code is donated by Mark Lovell and Paul +** Vixie. It is based on the long term host status code in KJS +** written by Paul but has been adapted by Mark to fit into the +** MCI structure. +*/ + +static MCI **MciCache; /* the open connection cache */ + + /* +** 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; + + /* + ** 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 (mci->mci_host == NULL) + 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)) + dprintf("mci_cache: caching %lx (%s) in slot %d\n", + (u_long) mci, mci->mci_host, + (int)(mcislot - MciCache)); + if (tTd(91, 100)) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "mci_cache: caching %lx (%.100s) in slot %d", + (u_long) mci, mci->mci_host, mcislot - MciCache); + + *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); + memset((char *) MciCache, '\0', 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->mci_mailer != NULL && + mci->mci_mailer->m_maxdeliveries > 0 && + mci->mci_deliveries + 1 >= mci->mci_mailer->m_maxdeliveries))&& + mci != savemci) + { + /* connection idle too long or too many deliveries */ + bestmci = &MciCache[i]; + + /* close it */ + 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. +*/ + +static 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 (mci->mci_host == NULL) + return; + + mci_unlock_host(mci); + + if (tTd(42, 5)) + dprintf("mci_uncache: uncaching %lx (%s) from slot %d (%d)\n", + (u_long) mci, mci->mci_host, + (int)(mcislot - MciCache), doquit); + if (tTd(91, 100)) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "mci_uncache: uncaching %lx (%.100s) from slot %d (%d)", + (u_long) mci, mci->mci_host, + mcislot - MciCache, doquit); + + mci->mci_deliveries = 0; +#if 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 /* XLA */ + } + else +#endif /* SMTP */ + { + if (mci->mci_in != NULL) + (void) fclose(mci->mci_in); + if (mci->mci_out != NULL) + (void) fclose(mci->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; + +#if DAEMON + extern SOCKADDR CurHostAddr; + + /* clear CurHostAddr so we don't get a bogus address with this name */ + memset(&CurHostAddr, '\0', sizeof CurHostAddr); +#endif /* DAEMON */ + + /* 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; + + /* + ** We don't need to load the peristent data if we have data + ** already loaded in the cache. + */ + + if (mci->mci_host == NULL && + (mci->mci_host = s->s_name) != NULL && + !mci_load_persistent(mci)) + { + if (tTd(42, 2)) + dprintf("mci_get(%s %s): lock failed\n", + host, m->m_name); + mci->mci_exitstat = EX_TEMPFAIL; + mci->mci_state = MCIS_CLOSED; + mci->mci_statfile = NULL; + return mci; + } + + if (tTd(42, 2)) + { + dprintf("mci_get(%s %s): mci_state=%d, _flags=%lx, _exitstat=%d, _errno=%d\n", + host, m->m_name, mci->mci_state, mci->mci_flags, + mci->mci_exitstat, mci->mci_errno); + } + +#if SMTP + if (mci->mci_state == MCIS_OPEN) + { + /* poke the connection to see if it's still alive */ + (void) 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; + } +# if DAEMON + else + { + /* get peer host address for logging reasons only */ + /* (this should really be in the mci struct) */ + SOCKADDR_LEN_T socklen = sizeof CurHostAddr; + + (void) getpeername(fileno(mci->mci_in), + (struct sockaddr *) &CurHostAddr, &socklen); + } +# endif /* DAEMON */ + } +#endif /* SMTP */ + 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; + } + } + + return mci; +} + /* +** MCI_MATCH -- check connection cache for a particular host +*/ + +bool +mci_match(host, m) + char *host; + MAILER *m; +{ + register MCI *mci; + register STAB *s; + + if (m->m_mno < 0) + return FALSE; + s = stab(host, ST_MCI + m->m_mno, ST_FIND); + if (s == NULL) + return FALSE; + + mci = &s->s_mci; + if (mci->mci_state == MCIS_OPEN) + return TRUE; + return FALSE; +} + /* +** MCI_SETSTAT -- set status codes in MCI structure. +** +** Parameters: +** mci -- the MCI structure to set. +** xstat -- the exit status code. +** dstat -- the DSN status code. +** rstat -- the SMTP status code. +** +** Returns: +** none. +*/ + +void +mci_setstat(mci, xstat, dstat, rstat) + MCI *mci; + int xstat; + char *dstat; + char *rstat; +{ + /* protocol errors should never be interpreted as sticky */ + if (xstat != EX_NOTSTICKY && xstat != EX_PROTOCOL) + mci->mci_exitstat = xstat; + + mci->mci_status = dstat; + if (mci->mci_rstatus != NULL) + free(mci->mci_rstatus); + if (rstat != NULL) + rstat = newstr(rstat); + mci->mci_rstatus = rstat; +} + /* +** MCI_DUMP -- dump the contents of an MCI structure. +** +** Parameters: +** mci -- the MCI structure to dump. +** +** Returns: +** none. +** +** Side Effects: +** none. +*/ + +struct mcifbits +{ + int mcif_bit; /* flag bit */ + char *mcif_name; /* flag name */ +}; +static struct mcifbits MciFlags[] = +{ + { MCIF_VALID, "VALID" }, + { MCIF_TEMP, "TEMP" }, + { MCIF_CACHED, "CACHED" }, + { MCIF_ESMTP, "ESMTP" }, + { MCIF_EXPN, "EXPN" }, + { MCIF_SIZE, "SIZE" }, + { MCIF_8BITMIME, "8BITMIME" }, + { MCIF_7BIT, "7BIT" }, + { MCIF_MULTSTAT, "MULTSTAT" }, + { MCIF_INHEADER, "INHEADER" }, + { MCIF_CVT8TO7, "CVT8TO7" }, + { MCIF_DSN, "DSN" }, + { MCIF_8BITOK, "8BITOK" }, + { MCIF_CVT7TO8, "CVT7TO8" }, + { MCIF_INMIME, "INMIME" }, + { 0, NULL } +}; + + +void +mci_dump(mci, logit) + register MCI *mci; + bool logit; +{ + register char *p; + char *sep; + char buf[4000]; + + sep = logit ? " " : "\n\t"; + p = buf; + snprintf(p, SPACELEFT(buf, p), "MCI@%lx: ", (u_long) mci); + p += strlen(p); + if (mci == NULL) + { + snprintf(p, SPACELEFT(buf, p), "NULL"); + goto printit; + } + snprintf(p, SPACELEFT(buf, p), "flags=%lx", mci->mci_flags); + p += strlen(p); + if (mci->mci_flags != 0) + { + struct mcifbits *f; + + *p++ = '<'; + for (f = MciFlags; f->mcif_bit != 0; f++) + { + if (!bitset(f->mcif_bit, mci->mci_flags)) + continue; + snprintf(p, SPACELEFT(buf, p), "%s,", f->mcif_name); + p += strlen(p); + } + p[-1] = '>'; + } + snprintf(p, SPACELEFT(buf, p), + ",%serrno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s", + sep, mci->mci_errno, mci->mci_herrno, + mci->mci_exitstat, mci->mci_state, (int) mci->mci_pid, sep); + p += strlen(p); + snprintf(p, SPACELEFT(buf, 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); + snprintf(p, SPACELEFT(buf, p), + "status=%s, rstatus=%s,%s", + mci->mci_status == NULL ? "NULL" : mci->mci_status, + mci->mci_rstatus == NULL ? "NULL" : mci->mci_rstatus, + sep); + p += strlen(p); + snprintf(p, SPACELEFT(buf, p), + "host=%s, lastuse=%s", + mci->mci_host == NULL ? "NULL" : mci->mci_host, + ctime(&mci->mci_lastuse)); +printit: + if (logit) + sm_syslog(LOG_DEBUG, CurEnv->e_id, "%.1000s", buf); + else + 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); +} + /* +** MCI_LOCK_HOST -- Lock host while sending. +** +** If we are contacting a host, we'll need to +** update the status information in the host status +** file, and if we want to do that, we ought to have +** locked it. This has the (according to some) +** desirable effect of serializing connectivity with +** remote hosts -- i.e.: one connection to a give +** host at a time. +** +** Parameters: +** mci -- containing the host we want to lock. +** +** Returns: +** EX_OK -- got the lock. +** EX_TEMPFAIL -- didn't get the lock. +*/ + +int +mci_lock_host(mci) + MCI *mci; +{ + if (mci == NULL) + { + if (tTd(56, 1)) + dprintf("mci_lock_host: NULL mci\n"); + return EX_OK; + } + + if (!SingleThreadDelivery) + return EX_OK; + + return mci_lock_host_statfile(mci); +} + +static int +mci_lock_host_statfile(mci) + MCI *mci; +{ + int save_errno = errno; + int retVal = EX_OK; + char fname[MAXPATHLEN + 1]; + + if (HostStatDir == NULL || mci->mci_host == NULL) + return EX_OK; + + if (tTd(56, 2)) + dprintf("mci_lock_host: attempting to lock %s\n", + mci->mci_host); + + if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, TRUE) < 0) + { + /* of course this should never happen */ + if (tTd(56, 2)) + dprintf("mci_lock_host: Failed to generate host path for %s\n", + mci->mci_host); + + retVal = EX_TEMPFAIL; + goto cleanup; + } + + mci->mci_statfile = safefopen(fname, O_RDWR, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH|SFF_CREAT); + + if (mci->mci_statfile == NULL) + { + syserr("mci_lock_host: cannot create host lock file %s", + fname); + goto cleanup; + } + + if (!lockfile(fileno(mci->mci_statfile), fname, "", LOCK_EX|LOCK_NB)) + { + if (tTd(56, 2)) + dprintf("mci_lock_host: couldn't get lock on %s\n", + fname); + (void) fclose(mci->mci_statfile); + mci->mci_statfile = NULL; + retVal = EX_TEMPFAIL; + goto cleanup; + } + + if (tTd(56, 12) && mci->mci_statfile != NULL) + dprintf("mci_lock_host: Sanity check -- lock is good\n"); + +cleanup: + errno = save_errno; + return retVal; +} + /* +** MCI_UNLOCK_HOST -- unlock host +** +** Clean up the lock on a host, close the file, let +** someone else use it. +** +** Parameters: +** mci -- us. +** +** Returns: +** nothing. +*/ + +void +mci_unlock_host(mci) + MCI *mci; +{ + int save_errno = errno; + + if (mci == NULL) + { + if (tTd(56, 1)) + dprintf("mci_unlock_host: NULL mci\n"); + return; + } + + if (HostStatDir == NULL || mci->mci_host == NULL) + return; + + if (!SingleThreadDelivery && mci_lock_host_statfile(mci) == EX_TEMPFAIL) + { + if (tTd(56, 1)) + dprintf("mci_unlock_host: stat file already locked\n"); + } + else + { + if (tTd(56, 2)) + dprintf("mci_unlock_host: store prior to unlock\n"); + + mci_store_persistent(mci); + } + + if (mci->mci_statfile != NULL) + { + (void) fclose(mci->mci_statfile); + mci->mci_statfile = NULL; + } + + errno = save_errno; +} + /* +** MCI_LOAD_PERSISTENT -- load persistent host info +** +** Load information about host that is kept +** in common for all running sendmails. +** +** Parameters: +** mci -- the host/connection to load persistent info +** for. +** +** Returns: +** TRUE -- lock was successful +** FALSE -- lock failed +*/ + +static bool +mci_load_persistent(mci) + MCI *mci; +{ + int save_errno = errno; + bool locked = TRUE; + FILE *fp; + char fname[MAXPATHLEN + 1]; + + if (mci == NULL) + { + if (tTd(56, 1)) + dprintf("mci_load_persistent: NULL mci\n"); + return TRUE; + } + + if (IgnoreHostStatus || HostStatDir == NULL || mci->mci_host == NULL) + return TRUE; + + /* Already have the persistent information in memory */ + if (SingleThreadDelivery && mci->mci_statfile != NULL) + return TRUE; + + if (tTd(56, 1)) + dprintf("mci_load_persistent: Attempting to load persistent information for %s\n", + mci->mci_host); + + if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, FALSE) < 0) + { + /* Not much we can do if the file isn't there... */ + if (tTd(56, 1)) + dprintf("mci_load_persistent: Couldn't generate host path\n"); + goto cleanup; + } + + fp = safefopen(fname, O_RDONLY, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH); + if (fp == NULL) + { + /* I can't think of any reason this should ever happen */ + if (tTd(56, 1)) + dprintf("mci_load_persistent: open(%s): %s\n", + fname, errstring(errno)); + goto cleanup; + } + + FileName = fname; + locked = lockfile(fileno(fp), fname, "", LOCK_SH|LOCK_NB); + if (locked) + { + (void) mci_read_persistent(fp, mci); + (void) lockfile(fileno(fp), fname, "", LOCK_UN); + } + FileName = NULL; + (void) fclose(fp); + +cleanup: + errno = save_errno; + return locked; +} + /* +** MCI_READ_PERSISTENT -- read persistent host status file +** +** Parameters: +** fp -- the file pointer to read. +** mci -- the pointer to fill in. +** +** Returns: +** -1 -- if the file was corrupt. +** 0 -- otherwise. +** +** Warning: +** This code makes the assumption that this data +** will be read in an atomic fashion, and that the data +** was written in an atomic fashion. Any other functioning +** may lead to some form of insanity. This should be +** perfectly safe due to underlying stdio buffering. +*/ + +static int +mci_read_persistent(fp, mci) + FILE *fp; + register MCI *mci; +{ + int ver; + register char *p; + int saveLineNumber = LineNumber; + char buf[MAXLINE]; + + if (fp == NULL) + syserr("mci_read_persistent: NULL fp"); + if (mci == NULL) + syserr("mci_read_persistent: NULL mci"); + if (tTd(56, 93)) + { + dprintf("mci_read_persistent: fp=%lx, mci=", (u_long) fp); + mci_dump(mci, FALSE); + } + + mci->mci_status = NULL; + if (mci->mci_rstatus != NULL) + free(mci->mci_rstatus); + mci->mci_rstatus = NULL; + + rewind(fp); + ver = -1; + LineNumber = 0; + while (fgets(buf, sizeof buf, fp) != NULL) + { + LineNumber++; + p = strchr(buf, '\n'); + if (p != NULL) + *p = '\0'; + switch (buf[0]) + { + case 'V': /* version stamp */ + ver = atoi(&buf[1]); + if (ver < 0 || ver > 0) + syserr("Unknown host status version %d: %d max", + ver, 0); + break; + + case 'E': /* UNIX error number */ + mci->mci_errno = atoi(&buf[1]); + break; + + case 'H': /* DNS error number */ + mci->mci_herrno = atoi(&buf[1]); + break; + + case 'S': /* UNIX exit status */ + mci->mci_exitstat = atoi(&buf[1]); + break; + + case 'D': /* DSN status */ + mci->mci_status = newstr(&buf[1]); + break; + + case 'R': /* SMTP status */ + mci->mci_rstatus = newstr(&buf[1]); + break; + + case 'U': /* last usage time */ + mci->mci_lastuse = atol(&buf[1]); + break; + + case '.': /* end of file */ + return 0; + + default: + sm_syslog(LOG_CRIT, NOQID, + "%s: line %d: Unknown host status line \"%s\"", + FileName == NULL ? mci->mci_host : FileName, + LineNumber, buf); + LineNumber = saveLineNumber; + return -1; + } + } + LineNumber = saveLineNumber; + if (ver < 0) + return -1; + return 0; +} + /* +** MCI_STORE_PERSISTENT -- Store persistent MCI information +** +** Store information about host that is kept +** in common for all running sendmails. +** +** Parameters: +** mci -- the host/connection to store persistent info for. +** +** Returns: +** none. +*/ + +void +mci_store_persistent(mci) + MCI *mci; +{ + int save_errno = errno; + + if (mci == NULL) + { + if (tTd(56, 1)) + dprintf("mci_store_persistent: NULL mci\n"); + return; + } + + if (HostStatDir == NULL || mci->mci_host == NULL) + return; + + if (tTd(56, 1)) + dprintf("mci_store_persistent: Storing information for %s\n", + mci->mci_host); + + if (mci->mci_statfile == NULL) + { + if (tTd(56, 1)) + dprintf("mci_store_persistent: no statfile\n"); + return; + } + + rewind(mci->mci_statfile); +#if !NOFTRUNCATE + (void) ftruncate(fileno(mci->mci_statfile), (off_t) 0); +#endif /* !NOFTRUNCATE */ + + fprintf(mci->mci_statfile, "V0\n"); + fprintf(mci->mci_statfile, "E%d\n", mci->mci_errno); + fprintf(mci->mci_statfile, "H%d\n", mci->mci_herrno); + fprintf(mci->mci_statfile, "S%d\n", mci->mci_exitstat); + if (mci->mci_status != NULL) + fprintf(mci->mci_statfile, "D%.80s\n", + denlstring(mci->mci_status, TRUE, FALSE)); + if (mci->mci_rstatus != NULL) + fprintf(mci->mci_statfile, "R%.80s\n", + denlstring(mci->mci_rstatus, TRUE, FALSE)); + fprintf(mci->mci_statfile, "U%ld\n", (long)(mci->mci_lastuse)); + fprintf(mci->mci_statfile, ".\n"); + + (void) fflush(mci->mci_statfile); + + errno = save_errno; + return; +} + /* +** MCI_TRAVERSE_PERSISTENT -- walk persistent status tree +** +** Recursively find all the mci host files in `pathname'. Default to +** main host status directory if no path is provided. +** Call (*action)(pathname, host) for each file found. +** +** Note: all information is collected in a list before it is processed. +** This may not be the best way to do it, but it seems safest, since +** the file system would be touched while we are attempting to traverse +** the directory tree otherwise (during purges). +** +** Parameters: +** action -- function to call on each node. If returns < 0, +** return immediately. +** pathname -- root of tree. If null, use main host status +** directory. +** +** Returns: +** < 0 -- if any action routine returns a negative value, that +** value is returned. +** 0 -- if we successfully went to completion. +*/ + +int +mci_traverse_persistent(action, pathname) + int (*action)(); + char *pathname; +{ + struct stat statbuf; + DIR *d; + int ret; + + if (pathname == NULL) + pathname = HostStatDir; + if (pathname == NULL) + return -1; + + if (tTd(56, 1)) + dprintf("mci_traverse: pathname is %s\n", pathname); + + ret = stat(pathname, &statbuf); + if (ret < 0) + { + if (tTd(56, 2)) + dprintf("mci_traverse: Failed to stat %s: %s\n", + pathname, errstring(errno)); + return ret; + } + if (S_ISDIR(statbuf.st_mode)) + { + struct dirent *e; + char *newptr; + char newpath[MAXPATHLEN + 1]; + bool leftone, removedone; + + if ((d = opendir(pathname)) == NULL) + { + if (tTd(56, 2)) + dprintf("mci_traverse: opendir %s: %s\n", + pathname, errstring(errno)); + return -1; + } + + if (strlen(pathname) >= sizeof newpath - MAXNAMLEN - 3) + { + if (tTd(56, 2)) + dprintf("mci_traverse: path \"%s\" too long", + pathname); + return -1; + } + (void) strlcpy(newpath, pathname, sizeof newpath); + newptr = newpath + strlen(newpath); + *newptr++ = '/'; + + /* + ** repeat until no file has been removed + ** this may become ugly when several files "expire" + ** during these loops, but it's better than doing + ** a rewinddir() inside the inner loop + */ + do + { + leftone = removedone = FALSE; + while ((e = readdir(d)) != NULL) + { + if (e->d_name[0] == '.') + continue; + + (void) strlcpy(newptr, e->d_name, + sizeof newpath - + (newptr - newpath)); + + ret = mci_traverse_persistent(action, newpath); + if (ret < 0) + break; + if (ret == 1) + leftone = TRUE; + if (!removedone && ret == 0 && + action == mci_purge_persistent) + removedone = TRUE; + } + if (ret < 0) + break; + /* + ** The following appears to be + ** necessary during purges, since + ** we modify the directory structure + */ + if (removedone) + rewinddir(d); + if (tTd(56, 40)) + dprintf("mci_traverse: path %s: ret %d removed %d left %d\n", + pathname, ret, removedone, leftone); + } while (removedone); + + /* purge (or whatever) the directory proper */ + if (!leftone) + { + *--newptr = '\0'; + ret = (*action)(newpath, NULL); + } + (void) closedir(d); + } + else if (S_ISREG(statbuf.st_mode)) + { + char *end = pathname + strlen(pathname) - 1; + char *start; + char *scan; + char host[MAXHOSTNAMELEN]; + char *hostptr = host; + + /* + ** Reconstruct the host name from the path to the + ** persistent information. + */ + + do + { + if (hostptr != host) + *(hostptr++) = '.'; + start = end; + while (*(start - 1) != '/') + start--; + + if (*end == '.') + end--; + + for (scan = start; scan <= end; scan++) + *(hostptr++) = *scan; + + end = start - 2; + } while (*end == '.'); + + *hostptr = '\0'; + + /* + ** Do something with the file containing the persistent + ** information. + */ + ret = (*action)(pathname, host); + } + + return ret; +} + /* +** MCI_PRINT_PERSISTENT -- print persistent info +** +** Dump the persistent information in the file 'pathname' +** +** Parameters: +** pathname -- the pathname to the status file. +** hostname -- the corresponding host name. +** +** Returns: +** 0 +*/ + +int +mci_print_persistent(pathname, hostname) + char *pathname; + char *hostname; +{ + static int initflag = FALSE; + FILE *fp; + int width = Verbose ? 78 : 25; + bool locked; + MCI mcib; + + /* skip directories */ + if (hostname == NULL) + return 0; + + if (!initflag) + { + initflag = TRUE; + printf(" -------------- Hostname --------------- How long ago ---------Results---------\n"); + } + + fp = safefopen(pathname, O_RDWR, FileMode, + SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH); + + if (fp == NULL) + { + if (tTd(56, 1)) + dprintf("mci_print_persistent: cannot open %s: %s\n", + pathname, errstring(errno)); + return 0; + } + + FileName = pathname; + memset(&mcib, '\0', sizeof mcib); + if (mci_read_persistent(fp, &mcib) < 0) + { + syserr("%s: could not read status file", pathname); + (void) fclose(fp); + FileName = NULL; + return 0; + } + + locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB); + (void) fclose(fp); + FileName = NULL; + + printf("%c%-39s %12s ", + locked ? '*' : ' ', hostname, + pintvl(curtime() - mcib.mci_lastuse, TRUE)); + if (mcib.mci_rstatus != NULL) + printf("%.*s\n", width, mcib.mci_rstatus); + else if (mcib.mci_exitstat == EX_TEMPFAIL && mcib.mci_errno != 0) + printf("Deferred: %.*s\n", width - 10, errstring(mcib.mci_errno)); + else if (mcib.mci_exitstat != 0) + { + int i = mcib.mci_exitstat - EX__BASE; + extern int N_SysEx; + extern char *SysExMsg[]; + + if (i < 0 || i >= N_SysEx) + { + char buf[80]; + + snprintf(buf, sizeof buf, "Unknown mailer error %d", + mcib.mci_exitstat); + printf("%.*s\n", width, buf); + } + else + printf("%.*s\n", width, &(SysExMsg[i])[5]); + } + else if (mcib.mci_errno == 0) + printf("OK\n"); + else + printf("OK: %.*s\n", width - 4, errstring(mcib.mci_errno)); + + return 0; +} + /* +** MCI_PURGE_PERSISTENT -- Remove a persistence status file. +** +** Parameters: +** pathname -- path to the status file. +** hostname -- name of host corresponding to that file. +** NULL if this is a directory (domain). +** +** Returns: +** 0 -- ok +** 1 -- file too young to be deleted +** < 0 -- some error occurred +*/ + +int +mci_purge_persistent(pathname, hostname) + char *pathname; + char *hostname; +{ + struct stat statbuf; + char *end = pathname + strlen(pathname) - 1; + int ret; + + if (tTd(56, 1)) + dprintf("mci_purge_persistent: purging %s\n", pathname); + + ret = stat(pathname, &statbuf); + if (ret < 0) + { + if (tTd(56, 2)) + dprintf("mci_purge_persistent: Failed to stat %s: %s\n", + pathname, errstring(errno)); + return ret; + } + if (curtime() - statbuf.st_mtime < MciInfoTimeout) + return 1; + if (hostname != NULL) + { + /* remove the file */ + if (unlink(pathname) < 0) + { + if (tTd(56, 2)) + dprintf("mci_purge_persistent: failed to unlink %s: %s\n", + pathname, errstring(errno)); + } + } + else + { + /* remove the directory */ + if (*end != '.') + return 0; + + if (tTd(56, 1)) + dprintf("mci_purge_persistent: dpurge %s\n", pathname); + + if (rmdir(pathname) < 0) + { + if (tTd(56, 2)) + dprintf("mci_purge_persistent: rmdir %s: %s\n", + pathname, errstring(errno)); + } + + } + + return 0; +} + /* +** MCI_GENERATE_PERSISTENT_PATH -- generate path from hostname +** +** Given `host', convert from a.b.c to $QueueDir/.hoststat/c./b./a, +** putting the result into `path'. if `createflag' is set, intervening +** directories will be created as needed. +** +** Parameters: +** host -- host name to convert from. +** path -- place to store result. +** pathlen -- length of path buffer. +** createflag -- if set, create intervening directories as +** needed. +** +** Returns: +** 0 -- success +** -1 -- failure +*/ + +static int +mci_generate_persistent_path(host, path, pathlen, createflag) + const char *host; + char *path; + int pathlen; + bool createflag; +{ + char *elem, *p, *x, ch; + int ret = 0; + int len; + char t_host[MAXHOSTNAMELEN]; +#if NETINET6 + struct in6_addr in6_addr; +#endif /* NETINET6 */ + + /* + ** Rationality check the arguments. + */ + + if (host == NULL) + { + syserr("mci_generate_persistent_path: null host"); + return -1; + } + if (path == NULL) + { + syserr("mci_generate_persistent_path: null path"); + return -1; + } + + if (tTd(56, 80)) + dprintf("mci_generate_persistent_path(%s): ", host); + + if (*host == '\0' || *host == '.') + return -1; + + /* make certain this is not a bracketed host number */ + if (strlen(host) > sizeof t_host - 1) + return -1; + if (host[0] == '[') + (void) strlcpy(t_host, host + 1, sizeof t_host); + else + (void) strlcpy(t_host, host, sizeof t_host); + + /* + ** Delete any trailing dots from the hostname. + ** Leave 'elem' pointing at the \0. + */ + + elem = t_host + strlen(t_host); + while (elem > t_host && + (elem[-1] == '.' || (host[0] == '[' && elem[-1] == ']'))) + *--elem = '\0'; + +#if NETINET || NETINET6 + /* check for bogus bracketed address */ + if (host[0] == '[' && +# if NETINET6 + inet_pton(AF_INET6, t_host, &in6_addr) != 1 && +# endif /* NETINET6 */ +# if NETINET + inet_addr(t_host) == INADDR_NONE +# endif /* NETINET */ + ) + return -1; +#endif /* NETINET || NETINET6 */ + + /* check for what will be the final length of the path */ + len = strlen(HostStatDir) + 2; + for (p = (char *) t_host; *p != '\0'; p++) + { + if (*p == '.') + len++; + len++; + if (p[0] == '.' && p[1] == '.') + return -1; + } + if (len > pathlen || len < 1) + return -1; + + (void) strlcpy(path, HostStatDir, pathlen); + p = path + strlen(path); + + while (elem > t_host) + { + if (!path_is_dir(path, createflag)) + { + ret = -1; + break; + } + elem--; + while (elem >= t_host && *elem != '.') + elem--; + *p++ = '/'; + x = elem + 1; + while ((ch = *x++) != '\0' && ch != '.') + { + if (isascii(ch) && isupper(ch)) + ch = tolower(ch); + if (ch == '/') + ch = ':'; /* / -> : */ + *p++ = ch; + } + if (elem >= t_host) + *p++ = '.'; + *p = '\0'; + } + + if (tTd(56, 80)) + { + if (ret < 0) + dprintf("FAILURE %d\n", ret); + else + dprintf("SUCCESS %s\n", path); + } + + return ret; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/milter.c b/gnu/usr.sbin/sendmail/sendmail/milter.c new file mode 100644 index 00000000000..dc47fe1e682 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/milter.c @@ -0,0 +1,3017 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: milter.c,v 8.45 2000/02/26 07:20:48 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_MILTER + +# include +# include +# include + +# if NETINET || NETINET6 +# include +# endif /* NETINET || NETINET6 */ + +/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ +/* To do: */ +/* - Optimize body chunk sending in milter_body() */ +/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ + +static void milter_error __P((struct milter *)); + +static char *MilterConnectMacros[MAXFILTERMACROS + 1]; +static char *MilterHeloMacros[MAXFILTERMACROS + 1]; +static char *MilterEnvFromMacros[MAXFILTERMACROS + 1]; +static char *MilterEnvRcptMacros[MAXFILTERMACROS + 1]; + +#define MILTER_CHECK_DONE_MSG() \ + if (*state == SMFIR_REPLYCODE || \ + *state == SMFIR_REJECT || \ + *state == SMFIR_DISCARD || \ + *state == SMFIR_TEMPFAIL) \ + { \ + /* Abort the filters to let them know we are done with msg */ \ + milter_abort(e); \ + } + +#define MILTER_CHECK_ERROR() \ + if (bitnset(SMF_TEMPFAIL, m->mf_flags)) \ + *state = SMFIR_TEMPFAIL; \ + else if (bitnset(SMF_REJECT, m->mf_flags)) \ + *state = SMFIR_REJECT; \ + else \ + continue; + +#define MILTER_CHECK_REPLYCODE(default) \ + if (response == NULL || \ + strlen(response) + 1 != rlen || \ + rlen < 3 || \ + (response[0] != '4' && response[0] != '5') || \ + !isascii(response[1]) || !isdigit(response[1]) || \ + !isascii(response[2]) || !isdigit(response[2])) \ + { \ + if (response != NULL) \ + free(response); \ + response = newstr(default); \ + } \ + else \ + { \ + char *ptr = response; \ + \ + /* Check for unprotected %'s in the string */ \ + while (*ptr != '\0') \ + { \ + if (*ptr == '%' && *++ptr != '%') \ + { \ + free(response); \ + response = newstr(default); \ + break; \ + } \ + ptr++; \ + } \ + } + +/* +** MILTER_TIMEOUT -- make sure socket is ready in time +** +** Parameters: +** routine -- routine name for debug/logging +** secs -- number of seconds in timeout +** write -- waiting to read or write? +** +** Assumes 'm' is a milter structure for the current socket. +*/ + +#define MILTER_TIMEOUT(routine, secs, write) \ +{ \ + int ret; \ + int save_errno; \ + fd_set fds; \ + struct timeval tv; \ + \ + if (m->mf_sock >= FD_SETSIZE) \ + { \ + if (tTd(64, 5)) \ + dprintf("%s(%s): socket %d is larger than FD_SETSIZE %d\n", \ + routine, m->mf_name, m->mf_sock, FD_SETSIZE); \ + if (LogLevel > 0) \ + sm_syslog(LOG_ERR, e->e_id, \ + "%s(%s): socket %d is larger than FD_SETSIZE %d\n", \ + routine, m->mf_name, m->mf_sock, FD_SETSIZE); \ + milter_error(m); \ + return NULL; \ + } \ + \ + FD_ZERO(&fds); \ + FD_SET(m->mf_sock, &fds); \ + tv.tv_sec = secs; \ + tv.tv_usec = 0; \ + ret = select(m->mf_sock + 1, \ + write ? NULL : &fds, \ + write ? &fds : NULL, \ + NULL, &tv); \ + \ + switch (ret) \ + { \ + case 0: \ + if (tTd(64, 5)) \ + dprintf("%s(%s): timeout\n", routine, m->mf_name); \ + if (LogLevel > 0) \ + sm_syslog(LOG_ERR, e->e_id, "%s(%s): timeout\n", \ + routine, m->mf_name); \ + milter_error(m); \ + return NULL; \ + \ + case -1: \ + save_errno = errno; \ + if (tTd(64, 5)) \ + dprintf("%s(%s): select: %s\n", \ + routine, m->mf_name, strerror(save_errno)); \ + if (LogLevel > 0) \ + sm_syslog(LOG_ERR, e->e_id, \ + "%s(%s): select: %s\n", \ + routine, m->mf_name, strerror(save_errno)); \ + milter_error(m); \ + return NULL; \ + \ + default: \ + if (FD_ISSET(m->mf_sock, &fds)) \ + break; \ + if (tTd(64, 5)) \ + dprintf("%s(%s): socket not ready\n", \ + routine, m->mf_name); \ + if (LogLevel > 0) \ + sm_syslog(LOG_ERR, e->e_id, \ + "%s(%s): socket not ready\n", \ + m->mf_name, routine); \ + milter_error(m); \ + return NULL; \ + } \ +} + +/* +** Low level functions +*/ + + /* +** MILTER_READ -- read from a remote milter filter +** +** Parameters: +** m -- milter to read from. +** cmd -- return param for command read. +** rlen -- return length of response string. +** to -- timeout in seconds. +** e -- current envelope. +** +** Returns: +** response string (may be NULL) +*/ + +static char * +milter_read(m, cmd, rlen, to, e) + struct milter *m; + char *cmd; + ssize_t *rlen; + time_t to; + ENVELOPE *e; +{ + time_t readstart = (time_t) 0; + ssize_t len, expl; + mi_int32 i; + char *buf; + char data[MILTER_LEN_BYTES + 1]; + + *rlen = 0; + *cmd = '\0'; + + if (to > 0) + { + readstart = curtime(); + MILTER_TIMEOUT("milter_read", to, FALSE); + } + + len = read(m->mf_sock, data, sizeof data); + if (len <= 0) + { + int save_errno = errno; + + if (tTd(64, 5)) + dprintf("milter_read(%s): read returned %ld: %s\n", + m->mf_name, (long) len, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): read returned %ld: %s", + m->mf_name, (long) len, + strerror(save_errno)); + milter_error(m); + return NULL; + } + + if (len != sizeof data) + { + if (tTd(64, 5)) + dprintf("milter_read(%s): cmd read returned %ld, expecting %ld\n", + m->mf_name, (long) *rlen, (long) sizeof data); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): cmd read returned %ld, expecting %ld", + m->mf_name, (long) *rlen, + (long) sizeof data); + milter_error(m); + return NULL; + } + + *cmd = data[MILTER_LEN_BYTES]; + data[MILTER_LEN_BYTES] = '\0'; + (void) memcpy(&i, data, MILTER_LEN_BYTES); + expl = ntohl(i) - 1; + + if (tTd(64, 25)) + dprintf("milter_read(%s): expecting %ld bytes\n", + m->mf_name, (long) expl); + + if (expl < 0 || expl > MILTER_CHUNK_SIZE) + { + if (tTd(64, 5)) + dprintf("milter_read(%s): read size %ld out of range\n", + m->mf_name, (long) expl); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): read size %ld out of range", + m->mf_name, (long) expl); + milter_error(m); + return NULL; + } + + if (expl == 0) + return NULL; + + buf = (char *)xalloc(expl); + + if (to > 0) + { + time_t now; + + now = curtime(); + if (now - readstart >= to) + { + if (tTd(64, 5)) + dprintf("milter_read(%s): timeout before data read\n", + m->mf_name); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): timeout before data read\n", + m->mf_name); + milter_error(m); + return NULL; + } + else + { + to -= now - readstart; + MILTER_TIMEOUT("milter_read", to, FALSE); + } + } + + *rlen = read(m->mf_sock, buf, expl); + if (len <= 0) + { + int save_errno = errno; + + if (tTd(64, 5)) + dprintf("milter_read(%s): read returned %ld: %s\n", + m->mf_name, (long) len, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): read returned %ld: %s", + m->mf_name, (long) len, + strerror(save_errno)); + free(buf); + milter_error(m); + return NULL; + } + if (*rlen != expl) + { + if (tTd(64, 5)) + dprintf("milter_read(%s): read returned %ld, expecting %ld\n", + m->mf_name, (long) *rlen, (long) len); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_read(%s): read returned %ld, expecting %ld", + m->mf_name, (long) *rlen, (long) len); + free(buf); + milter_error(m); + return NULL; + } + if (tTd(64, 50)) + dprintf("milter_read(%s): Returning %*s\n", + m->mf_name, (int) *rlen, buf); + return buf; +} + /* +** MILTER_WRITE -- write to a remote milter filter +** +** Parameters: +** m -- milter to read from. +** cmd -- command to send. +** buf -- optional command data. +** len -- length of buf. +** to -- timeout in seconds. +** e -- current envelope. +** +** Returns: +** buf if successful, NULL otherwise +** Not actually used anywhere but function prototype +** must match milter_read() +*/ + +static char * +milter_write(m, cmd, buf, len, to, e) + struct milter *m; + char cmd; + char *buf; + ssize_t len; + time_t to; + ENVELOPE *e; +{ + time_t writestart = (time_t) 0; + ssize_t sl, i; + mi_int32 nl; + char data[MILTER_LEN_BYTES + 1]; + + if (len < 0 || len > MILTER_CHUNK_SIZE) + { + if (tTd(64, 5)) + dprintf("milter_write(%s): length %ld out of range\n", + m->mf_name, (long) len); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_write(%s): length %ld out of range", + m->mf_name, (long) len); + milter_error(m); + return NULL; + } + + if (tTd(64, 20)) + dprintf("milter_write(%s): cmd %c, len %ld\n", + m->mf_name, cmd, (long) len); + + nl = htonl(len + 1); /* add 1 for the cmd char */ + (void) memcpy(data, (char *) &nl, MILTER_LEN_BYTES); + data[MILTER_LEN_BYTES] = cmd; + sl = MILTER_LEN_BYTES + 1; + + if (to > 0) + { + writestart = curtime(); + MILTER_TIMEOUT("milter_write", to, TRUE); + } + + /* use writev() instead to send the whole stuff at once? */ + i = write(m->mf_sock, (void *) data, sl); + if (i != sl) + { + int save_errno = errno; + + if (tTd(64, 5)) + dprintf("milter_write(%s): write(%c) returned %ld, expected %ld: %s\n", + m->mf_name, cmd, (long) i, (long) sl, + strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_write(%s): write(%c) returned %ld, expected %ld: %s", + m->mf_name, cmd, (long) i, (long) sl, + strerror(save_errno)); + milter_error(m); + return buf; + } + + if (len <= 0 || buf == NULL) + return buf; + + if (tTd(64, 50)) + dprintf("milter_write(%s): Sending %*s\n", + m->mf_name, (int) len, buf); + + if (to > 0) + { + time_t now; + + now = curtime(); + if (now - writestart >= to) + { + if (tTd(64, 5)) + dprintf("milter_write(%s): timeout before data send\n", + m->mf_name); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_write(%s): timeout before data send\n", + m->mf_name); + milter_error(m); + return NULL; + } + else + { + to -= now - writestart; + MILTER_TIMEOUT("milter_write", to, TRUE); + } + } + + i = write(m->mf_sock, (void *) buf, len); + if (i != len) + { + int save_errno = errno; + + if (tTd(64, 5)) + dprintf("milter_write(%s): write(%c) returned %ld, expected %ld: %s\n", + m->mf_name, cmd, (long) i, (long) sl, + strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_write(%s): write(%c) returned %ld, expected %ld: %s", + m->mf_name, cmd, (long) i, (long) len, + strerror(save_errno)); + milter_error(m); + return NULL; + } + return buf; +} + +/* +** Utility functions +*/ + + /* +** MILTER_OPEN -- connect to remote milter filter +** +** Parameters: +** m -- milter to connect to. +** parseonly -- parse but don't connect. +** e -- current envelope. +** +** Returns: +** connected socket if sucessful && !parseonly, +** 0 upon parse success if parseonly, +** -1 otherwise. +*/ + +int +milter_open(m, parseonly, e) + struct milter *m; + bool parseonly; + ENVELOPE *e; +{ + int sock = 0; + SOCKADDR_LEN_T addrlen = 0; + int addrno = 0; + int save_errno; + char *p; + char *colon; + char *at; + struct hostent *hp = NULL; + SOCKADDR addr; + + if (m->mf_conn == NULL || m->mf_conn[0] == '\0') + { + if (tTd(64, 5)) + dprintf("X%s: empty or missing socket information\n", + m->mf_name); + if (parseonly) + syserr("X%s: empty or missing socket information", + m->mf_name); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: empty or missing socket information", + m->mf_name); + milter_error(m); + return -1; + } + + /* protocol:filename or protocol:port@host */ + p = m->mf_conn; + colon = strchr(p, ':'); + if (colon != NULL) + { + *colon = '\0'; + + if (*p == '\0') + { +# if NETUNIX + /* default to AF_UNIX */ + addr.sa.sa_family = AF_UNIX; +# else /* NETUNIX */ +# if NETINET + /* default to AF_INET */ + addr.sa.sa_family = AF_INET; +# else /* NETINET */ +# if NETINET6 + /* default to AF_INET6 */ + addr.sa.sa_family = AF_INET6; +# else /* NETINET6 */ + /* no protocols available */ + sm_syslog(LOG_ERR, e->e_id, + "X%s: no valid socket protocols available", + m->mf_name); + milter_error(m); + return -1; +# endif /* NETINET6 */ +# endif /* NETINET */ +# endif /* NETUNIX */ + } +# if NETUNIX + else if (strcasecmp(p, "unix") == 0 || + strcasecmp(p, "local") == 0) + addr.sa.sa_family = AF_UNIX; +# endif /* NETUNIX */ +# if NETINET + else if (strcasecmp(p, "inet") == 0) + addr.sa.sa_family = AF_INET; +# endif /* NETINET */ +# if NETINET6 + else if (strcasecmp(p, "inet6") == 0) + addr.sa.sa_family = AF_INET6; +# endif /* NETINET6 */ + else + { +# ifdef EPROTONOSUPPORT + errno = EPROTONOSUPPORT; +# else /* EPROTONOSUPPORT */ + errno = EINVAL; +# endif /* EPROTONOSUPPORT */ + if (tTd(64, 5)) + dprintf("X%s: unknown socket type %s\n", + m->mf_name, p); + if (parseonly) + syserr("X%s: unknown socket type %s", + m->mf_name, p); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: unknown socket type %s", + m->mf_name, p); + milter_error(m); + return -1; + } + *colon++ = ':'; + } + else + { + /* default to AF_UNIX */ + addr.sa.sa_family = AF_UNIX; + colon = p; + } + +# if NETUNIX + if (addr.sa.sa_family == AF_UNIX) + { + long sff = SFF_SAFEDIRPATH|SFF_OPENASROOT|SFF_NOLINK|SFF_CREAT|SFF_MUSTOWN|SFF_EXECOK; + + at = colon; + if (strlen(colon) >= sizeof addr.sunix.sun_path) + { + if (tTd(64, 5)) + dprintf("X%s: local socket name %s too long\n", + m->mf_name, colon); + errno = EINVAL; + if (parseonly) + syserr("X%s: local socket name %s too long", + m->mf_name, colon); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: local socket name %s too long", + m->mf_name, colon); + milter_error(m); + return -1; + } + errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, + S_IRUSR|S_IWUSR, NULL); + + /* if not safe, don't create */ + if (errno != 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("X%s: local socket name %s unsafe\n", + m->mf_name, colon); + errno = save_errno; + if (parseonly) + { + if (OpMode == MD_DAEMON || + OpMode == MD_FGDAEMON || + OpMode == MD_SMTP) + syserr("X%s: local socket name %s unsafe", + m->mf_name, colon); + } + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: local socket name %s unsafe", + m->mf_name, colon); + milter_error(m); + return -1; + } + + (void) strlcpy(addr.sunix.sun_path, colon, + sizeof addr.sunix.sun_path); + addrlen = sizeof (struct sockaddr_un); + } +# endif /* NETUNIX */ +# if NETINET || NETINET6 + else if (FALSE +# if NETINET + || addr.sa.sa_family == AF_INET +# endif /* NETINET */ +# if NETINET6 + || addr.sa.sa_family == AF_INET6 +# endif /* NETINET6 */ + ) + { + u_short port; + + /* Parse port@host */ + at = strchr(colon, '@'); + if (at == NULL) + { + if (tTd(64, 5)) + dprintf("X%s: bad address %s (expected port@host)\n", + m->mf_name, colon); + if (parseonly) + syserr("X%s: bad address %s (expected port@host)", + m->mf_name, colon); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: bad address %s (expected port@host)", + m->mf_name, colon); + milter_error(m); + return -1; + } + *at = '\0'; + if (isascii(*colon) && isdigit(*colon)) + port = htons(atoi(colon)); + else + { +# ifdef NO_GETSERVBYNAME + if (tTd(64, 5)) + dprintf("X%s: invalid port number %s\n", + m->mf_name, colon); + if (parseonly) + syserr("X%s: invalid port number %s", + m->mf_name, colon); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: invalid port number %s", + m->mf_name, colon); + milter_error(m); + return -1; +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(colon, "tcp"); + if (sp == NULL) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("X%s: unknown port name %s\n", + m->mf_name, colon); + errno = save_errno; + if (parseonly) + syserr("X%s: unknown port name %s", + m->mf_name, colon); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: unknown port name %s", + m->mf_name, colon); + milter_error(m); + return -1; + } + port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + *at++ = '@'; + if (*at == '[') + { + char *end; + + end = strchr(at, ']'); + if (end != NULL) + { + bool found = FALSE; +# if NETINET + unsigned long hid = INADDR_NONE; +# endif /* NETINET */ +# if NETINET6 + struct sockaddr_in6 hid6; +# endif /* NETINET6 */ + + *end = '\0'; +# if NETINET + if (addr.sa.sa_family == AF_INET && + (hid = inet_addr(&at[1])) != INADDR_NONE) + { + addr.sin.sin_addr.s_addr = hid; + addr.sin.sin_port = port; + found = TRUE; + } +# endif /* NETINET */ +# if NETINET6 + (void) memset(&hid6, '\0', sizeof hid6); + if (addr.sa.sa_family == AF_INET6 && + inet_pton(AF_INET6, &at[1], + &hid6.sin6_addr) == 1) + { + addr.sin6.sin6_addr = hid6.sin6_addr; + addr.sin6.sin6_port = port; + found = TRUE; + } +# endif /* NETINET6 */ + *end = ']'; + if (!found) + { + if (tTd(64, 5)) + dprintf("X%s: Invalid numeric domain spec \"%s\"\n", + m->mf_name, at); + if (parseonly) + syserr("X%s: Invalid numeric domain spec \"%s\"", + m->mf_name, at); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: Invalid numeric domain spec \"%s\"", + m->mf_name, at); + milter_error(m); + return -1; + } + } + else + { + if (tTd(64, 5)) + dprintf("X%s: Invalid numeric domain spec \"%s\"\n", + m->mf_name, at); + if (parseonly) + syserr("X%s: Invalid numeric domain spec \"%s\"", + m->mf_name, at); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: Invalid numeric domain spec \"%s\"", + m->mf_name, at); + milter_error(m); + return -1; + } + } + else + { + hp = sm_gethostbyname(at, addr.sa.sa_family); + if (hp == NULL) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("X%s: Unknown host name %s\n", + m->mf_name, at); + errno = save_errno; + if (parseonly) + syserr("X%s: Unknown host name %s", + m->mf_name, at); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: Unknown host name %s", + m->mf_name, at); + milter_error(m); + return -1; + } + addr.sa.sa_family = hp->h_addrtype; + switch (hp->h_addrtype) + { +# if NETINET + case AF_INET: + memmove(&addr.sin.sin_addr, + hp->h_addr, + INADDRSZ); + addr.sin.sin_port = port; + addrlen = sizeof (struct sockaddr_in); + addrno = 1; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + hp->h_addr, + IN6ADDRSZ); + addr.sin6.sin6_port = port; + addrlen = sizeof (struct sockaddr_in6); + addrno = 1; + break; +# endif /* NETINET6 */ + + default: + if (tTd(64, 5)) + dprintf("X%s: Unknown protocol for %s (%d)\n", + m->mf_name, at, + hp->h_addrtype); + if (parseonly) + syserr("X%s: Unknown protocol for %s (%d)", + m->mf_name, at, hp->h_addrtype); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: Unknown protocol for %s (%d)", + m->mf_name, at, + hp->h_addrtype); + milter_error(m); + return -1; + } + } + } +# endif /* NETINET || NETINET6 */ + else + { + if (tTd(64, 5)) + dprintf("X%s: unknown socket protocol\n", m->mf_name); + if (parseonly) + syserr("X%s: unknown socket protocol", m->mf_name); + else if (LogLevel > 10) + sm_syslog(LOG_ERR, e->e_id, + "X%s: unknown socket protocol", m->mf_name); + milter_error(m); + return -1; + } + + /* just parsing through? */ + if (parseonly) + { + m->mf_state = SMFS_READY; + return 0; + } + + /* sanity check */ + if (m->mf_state != SMFS_READY && + m->mf_state != SMFS_CLOSED) + { + /* shouldn't happen */ + if (tTd(64, 1)) + dprintf("milter_open(%s): Trying to open filter in state %c\n", + m->mf_name, (char) m->mf_state); + milter_error(m); + return -1; + } + + /* nope, actually connecting */ + for (;;) + { + sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); + if (sock < 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("X%s: error creating socket: %s\n", + m->mf_name, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "X%s: error creating socket: %s", + m->mf_name, strerror(save_errno)); + milter_error(m); + return -1; + } + + if (connect(sock, (struct sockaddr *) &addr, addrlen) >= 0) + break; + + /* couldn't connect.... try next address */ + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_open(%s): %s failed: %s\n", + m->mf_name, at, errstring(save_errno)); + if (LogLevel >= 14) + sm_syslog(LOG_INFO, e->e_id, + "milter_open(%s): %s failed: %s", + m->mf_name, at, errstring(save_errno)); + (void) close(sock); + + /* try next address */ + if (hp != NULL && hp->h_addr_list[addrno] != NULL) + { + switch (addr.sa.sa_family) + { +# if NETINET + case AF_INET: + memmove(&addr.sin.sin_addr, + hp->h_addr_list[addrno++], + INADDRSZ); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + memmove(&addr.sin6.sin6_addr, + hp->h_addr_list[addrno++], + IN6ADDRSZ); + break; +# endif /* NETINET6 */ + + default: + if (tTd(64, 5)) + dprintf("X%s: Unknown protocol for %s (%d)\n", + m->mf_name, at, + hp->h_addrtype); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "X%s: Unknown protocol for %s (%d)", + m->mf_name, at, + hp->h_addrtype); + milter_error(m); + return -1; + } + continue; + } + if (tTd(64, 5)) + dprintf("X%s: error connecting to filter\n", + m->mf_name); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "X%s: error connecting to filter", + m->mf_name); + milter_error(m); + return -1; + } + m->mf_state = SMFS_OPEN; + return sock; +} + /* +** MILTER_PARSE_LIST -- parse option list into an array +** +** Called when reading configuration file. +** +** Parameters: +** spec -- the filter list. +** list -- the array to fill in. +** max -- the maximum number of entries in list. +** +** Returns: +** none +*/ + +void +milter_parse_list(spec, list, max) + char *spec; + struct milter **list; + int max; +{ + int numitems = 0; + register char *p; + + /* leave one for the NULL signifying the end of the list */ + max--; + + for (p = spec; p != NULL; ) + { + STAB *s; + + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + spec = p; + + if (numitems >= max) + { + syserr("Too many filters defined, %d max", max); + if (max > 0) + list[0] = NULL; + return; + } + p = strpbrk(p, ","); + if (p != NULL) + *p++ = '\0'; + + s = stab(spec, ST_MILTER, ST_FIND); + if (s == NULL) + { + syserr("InputFilter %s not defined", spec); + ExitStat = EX_CONFIG; + return; + } + list[numitems++] = s->s_milter; + } + list[numitems] = NULL; +} + /* +** MILTER_PARSE_TIMEOUTS -- parse timeout list +** +** Called when reading configuration file. +** +** Parameters: +** spec -- the timeout list. +** m -- milter to set. +** +** Returns: +** none +*/ + +void +milter_parse_timeouts(spec, m) + char *spec; + struct milter *m; +{ + char fcode; + register char *p; + + p = spec; + + /* now scan through and assign info from the fields */ + while (*p != '\0') + { + char *delimptr; + + while (*p != '\0' && + (*p == ';' || (isascii(*p) && isspace(*p)))) + p++; + + /* p now points to field code */ + fcode = *p; + while (*p != '\0' && *p != ':') + p++; + if (*p++ != ':') + { + syserr("X%s, T=: `:' expected", m->mf_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 'S': + m->mf_timeout[SMFTO_WRITE] = convtime(p, 's'); + if (tTd(64, 5)) + printf("X%s: %c=%ld\n", + m->mf_name, fcode, + (u_long) m->mf_timeout[SMFTO_WRITE]); + break; + + case 'R': + m->mf_timeout[SMFTO_READ] = convtime(p, 's'); + if (tTd(64, 5)) + printf("X%s: %c=%ld\n", + m->mf_name, fcode, + (u_long) m->mf_timeout[SMFTO_READ]); + break; + + case 'E': + m->mf_timeout[SMFTO_EOM] = convtime(p, 's'); + if (tTd(64, 5)) + printf("X%s: %c=%ld\n", + m->mf_name, fcode, + (u_long) m->mf_timeout[SMFTO_EOM]); + break; + + default: + if (tTd(64, 5)) + printf("X%s: %c unknown\n", + m->mf_name, fcode); + syserr("X%s: unknown filter timeout %c", + m->mf_name, fcode); + break; + } + p = delimptr; + } +} + /* +** MILTER_SET_OPTION -- set an individual milter option +** +** Parameters: +** name -- the name of the option. +** val -- the value of the option. +** sticky -- if set, don't let other setoptions override +** this value. +** +** Returns: +** none. +*/ + +/* set if Milter sub-option is stuck */ +static BITMAP256 StickyMilterOpt; + +static struct milteropt +{ + char *mo_name; /* long name of milter option */ + u_char mo_code; /* code for option */ +} MilterOptTab[] = +{ +#define MO_MACROS_CONNECT 0x01 + { "macros.connect", MO_MACROS_CONNECT }, +#define MO_MACROS_HELO 0x02 + { "macros.helo", MO_MACROS_HELO }, +#define MO_MACROS_ENVFROM 0x03 + { "macros.envfrom", MO_MACROS_ENVFROM }, +#define MO_MACROS_ENVRCPT 0x04 + { "macros.envrcpt", MO_MACROS_ENVRCPT }, + { NULL, 0 }, +}; + +void +milter_set_option(name, val, sticky) + char *name; + char *val; + bool sticky; +{ + int nummac = 0; + register struct milteropt *mo; + char *p; + char **macros = NULL; + + if (tTd(37, 2) || tTd(64, 5)) + dprintf("milter_set_option(%s = %s)", name, val); + + for (mo = MilterOptTab; mo->mo_name != NULL; mo++) + { + if (strcasecmp(mo->mo_name, name) == 0) + break; + } + + if (mo->mo_name == NULL) + syserr("milter_set_option: invalid Milter option %s", name); + + /* + ** See if this option is preset for us. + */ + + if (!sticky && bitnset(mo->mo_code, StickyMilterOpt)) + { + if (tTd(37, 2) || tTd(64,5)) + dprintf(" (ignored)\n"); + return; + } + + if (tTd(37, 2) || tTd(64,5)) + dprintf("\n"); + + switch (mo->mo_code) + { + case MO_MACROS_CONNECT: + if (macros == NULL) + macros = MilterConnectMacros; + /* FALLTHROUGH */ + + case MO_MACROS_HELO: + if (macros == NULL) + macros = MilterHeloMacros; + /* FALLTHROUGH */ + + case MO_MACROS_ENVFROM: + if (macros == NULL) + macros = MilterEnvFromMacros; + /* FALLTHROUGH */ + + case MO_MACROS_ENVRCPT: + if (macros == NULL) + macros = MilterEnvRcptMacros; + + p = newstr(val); + while (*p != '\0') + { + char *macro; + + /* Skip leading commas, spaces */ + while (*p != '\0' && + (*p == ',' || (isascii(*p) && isspace(*p)))) + p++; + + if (*p == '\0') + break; + + /* Find end of macro */ + macro = p; + while (*p != '\0' && *p != ',' && + isascii(*p) && !isspace(*p)) + p++; + if (*p != '\0') + *p++ = '\0'; + + if (nummac >= MAXFILTERMACROS) + { + syserr("milter_set_option: too many macros in Milter.%s (max %d)", + name, MAXFILTERMACROS); + macros[nummac] = NULL; + break; + } + macros[nummac++] = macro; + } + macros[nummac] = NULL; + break; + + default: + syserr("milter_set_option: invalid Milter option %s", name); + break; + } + + if (sticky) + setbitn(mo->mo_code, StickyMilterOpt); +} + /* +** MILTER_CAN_DELRCPTS -- can any milter filters delete recipients? +** +** Parameters: +** none +** +** Returns: +** TRUE if any filter deletes recipients, FALSE otherwise +*/ + +bool +milter_can_delrcpts() +{ + int i; + + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + if (bitset(SMFIF_DELRCPT, m->mf_fflags)) + return TRUE; + } + return FALSE; +} + /* +** MILTER_QUIT_FILTER -- close down a single filter +** +** Parameters: +** m -- milter structure of filter to close down. +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_quit_filter(m, e) + struct milter *m; + ENVELOPE *e; +{ + if (tTd(64, 10)) + dprintf("milter_quit_filter(%s)\n", m->mf_name); + + /* Never replace error state */ + if (m->mf_state == SMFS_ERROR) + return; + + if (m->mf_sock < 0 || + m->mf_state == SMFS_CLOSED || + m->mf_state == SMFS_READY) + { + m->mf_sock = -1; + m->mf_state = SMFS_CLOSED; + return; + } + + (void) milter_write(m, SMFIC_QUIT, NULL, 0, + m->mf_timeout[SMFTO_WRITE], e); + (void) close(m->mf_sock); + m->mf_sock = -1; + if (m->mf_state != SMFS_ERROR) + m->mf_state = SMFS_CLOSED; +} + /* +** MILTER_ABORT_FILTER -- tell filter to abort current message +** +** Parameters: +** m -- milter structure of filter to abort. +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_abort_filter(m, e) + struct milter *m; + ENVELOPE *e; +{ + if (tTd(64, 10)) + dprintf("milter_abort_filter(%s)\n", m->mf_name); + + if (m->mf_sock < 0 || + m->mf_state != SMFS_INMSG) + return; + + (void) milter_write(m, SMFIC_ABORT, NULL, 0, + m->mf_timeout[SMFTO_WRITE], e); + if (m->mf_state != SMFS_ERROR) + m->mf_state = SMFS_DONE; +} + /* +** MILTER_SEND_MACROS -- provide macros to the filters +** +** Parameters: +** m -- milter to send macros to. +** macros -- macros to send for filter smfi_getsymval(). +** cmd -- which command the macros are associated with. +** e -- current envelope (for macro access). +** +** Returns: +** none +*/ + +static void +milter_send_macros(m, macros, cmd, e) + struct milter *m; + char **macros; + char cmd; + ENVELOPE *e; +{ + int i; + int mid; + char *v; + char *buf, *bp; + ssize_t s; + + /* sanity check */ + if (macros == NULL || macros[0] == NULL) + return; + + /* put together data */ + s = 1; /* for the command character */ + for (i = 0; macros[i] != NULL; i++) + { + mid = macid(macros[i], NULL); + if (mid == '\0') + continue; + v = macvalue(mid, e); + if (v == NULL) + continue; + s += strlen(macros[i]) + 1 + strlen(v) + 1; + } + + buf = (char *)xalloc(s); + bp = buf; + *bp++ = cmd; + for (i = 0; macros[i] != NULL; i++) + { + mid = macid(macros[i], NULL); + if (mid == '\0') + continue; + v = macvalue(mid, e); + if (v == NULL) + continue; + + if (tTd(64, 10)) + dprintf("milter_send_macros(%s, %c): %s=%s\n", + m->mf_name, cmd, macros[i], v); + + (void) strlcpy(bp, macros[i], s - (bp - buf)); + bp += strlen(bp) + 1; + (void) strlcpy(bp, v, s - (bp - buf)); + bp += strlen(bp) + 1; + } + (void) milter_write(m, SMFIC_MACRO, buf, s, + m->mf_timeout[SMFTO_WRITE], e); + free(buf); +} + /* +** MILTER_COMMAND -- send a command and return the response for each filter +** +** Parameters: +** command -- command to send. +** data -- optional command data. +** sz -- length of buf. +** macros -- macros to send for filter smfi_getsymval(). +** e -- current envelope (for macro access). +** state -- return state word. +** +** Returns: +** response string (may be NULL) +*/ + +static char * +milter_command(command, data, sz, macros, e, state) + char command; + void *data; + ssize_t sz; + char **macros; + ENVELOPE *e; + char *state; +{ + int i; + char rcmd; + u_long skipflag; + char *response = NULL; + char *defresponse; + ssize_t rlen; + + if (tTd(64, 10)) + dprintf("milter_command: cmd %c len %ld\n", + (char) command, (long) sz); + + /* find skip flag and default failure */ + switch (command) + { + case SMFIC_CONNECT: + skipflag = SMFIF_NOCONNECT; + defresponse = "554 Command rejected"; + break; + + case SMFIC_HELO: + skipflag = SMFIF_NOHELO; + defresponse = "550 Command rejected"; + break; + + case SMFIC_MAIL: + skipflag = SMFIF_NOMAIL; + defresponse = "550 5.7.1 Command rejected"; + break; + + case SMFIC_RCPT: + skipflag = SMFIF_NORCPT; + defresponse = "550 5.7.1 Command rejected"; + break; + + case SMFIC_HEADER: + case SMFIC_EOH: + skipflag = SMFIF_NOHDRS; + defresponse = "550 5.7.1 Command rejected"; + break; + + case SMFIC_BODY: + case SMFIC_BODYEOB: + case SMFIC_OPTNEG: + case SMFIC_MACRO: + case SMFIC_ABORT: + case SMFIC_QUIT: + /* NOTE: not handled by milter_command() */ + /* FALLTHROUGH */ + + default: + skipflag = 0; + defresponse = "550 5.7.1 Command rejected"; + break; + } + + *state = SMFIR_CONTINUE; + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + /* sanity check */ + if (m->mf_sock < 0 || + (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG)) + continue; + + /* send macros (regardless of whether we send command) */ + if (macros != NULL && macros[0] != NULL) + { + milter_send_macros(m, macros, command, e); + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + break; + } + } + + /* check if filter wants this command */ + if (skipflag != 0 && + bitset(skipflag, m->mf_fflags)) + continue; + + (void) milter_write(m, command, data, sz, + m->mf_timeout[SMFTO_WRITE], e); + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + break; + } + + response = milter_read(m, &rcmd, &rlen, + m->mf_timeout[SMFTO_READ], e); + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + break; + } + + if (tTd(64, 10)) + dprintf("milter_command(%s): returned %c%s%s\n", + m->mf_name, (char) rcmd, + response == NULL ? "" : ":", + response == NULL ? "" : response); + + switch (rcmd) + { + case SMFIR_REPLYCODE: + MILTER_CHECK_REPLYCODE(defresponse); + /* FALLTHROUGH */ + + case SMFIR_REJECT: + case SMFIR_DISCARD: + case SMFIR_TEMPFAIL: + *state = rcmd; + break; + + case SMFIR_ACCEPT: + /* this filter is done with message/connection */ + m->mf_state = SMFS_DONE; + break; + + case SMFIR_CONTINUE: + /* if MAIL command is ok, filter is in message state */ + if (command == SMFIC_MAIL) + m->mf_state = SMFS_INMSG; + break; + + default: + /* Invalid response to command */ + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_command(%s): returned bogus response %c", + m->mf_name, rcmd); + milter_error(m); + break; + } + + if (*state != SMFIR_REPLYCODE && + response != NULL) + { + free(response); + response = NULL; + } + + if (*state != SMFIR_CONTINUE) + break; + } + return response; +} + /* +** MILTER_NEGOTIATE -- get version and flags from filter +** +** Parameters: +** m -- milter filter structure. +** e -- current envelope. +** +** Returns: +** 0 on success, -1 otherwise +*/ + +static int +milter_negotiate(m, e) + struct milter *m; + ENVELOPE *e; +{ + char rcmd; + mi_int32 fvers; + mi_int32 flags; + char *response = NULL; + ssize_t rlen; + char data[MILTER_LEN_BYTES * 2]; + + /* sanity check */ + if (m->mf_sock < 0 || m->mf_state != SMFS_OPEN) + { + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_negotiate(%s): impossible state", + m->mf_name); + milter_error(m); + return -1; + } + + fvers = htonl(SMFI_VERSION); + flags = htonl(0); + (void) memcpy(data, (char *) &fvers, MILTER_LEN_BYTES); + (void) memcpy(data + MILTER_LEN_BYTES, + (char *) &flags, MILTER_LEN_BYTES); + (void) milter_write(m, SMFIC_OPTNEG, data, sizeof data, + m->mf_timeout[SMFTO_WRITE], e); + + if (m->mf_state == SMFS_ERROR) + return -1; + + response = milter_read(m, &rcmd, &rlen, m->mf_timeout[SMFTO_READ], e); + if (m->mf_state == SMFS_ERROR) + return -1; + + if (rcmd != SMFIC_OPTNEG) + { + if (tTd(64, 5)) + dprintf("milter_negotiate(%s): returned %c instead of %c\n", + m->mf_name, rcmd, SMFIC_OPTNEG); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_negotiate(%s): returned %c instead of %c", + m->mf_name, rcmd, SMFIC_OPTNEG); + if (response != NULL) + free(response); + milter_error(m); + return -1; + } + + if (response == NULL || rlen != MILTER_LEN_BYTES * 2) + { + if (tTd(64, 5)) + dprintf("milter_negotiate(%s): did not return valid info\n", + m->mf_name); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_negotiate(%s): did not return valid info", + m->mf_name); + if (response != NULL) + free(response); + milter_error(m); + return -1; + } + + /* extract information */ + (void) memcpy((char *) &fvers, response, MILTER_LEN_BYTES); + (void) memcpy((char *) &flags, response + MILTER_LEN_BYTES, + MILTER_LEN_BYTES); + free(response); + response = NULL; + + /* check for version mismatch */ + if (ntohl(fvers) != SMFI_VERSION) + { + if (tTd(64, 5)) + dprintf("milter_negotiate(%s): version %ld != MTA milter version %d\n", + m->mf_name, (u_long) ntohl(fvers), + SMFI_VERSION); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_negotiate(%s): version %ld != MTA milter version %d", + m->mf_name, (u_long) ntohl(fvers), + SMFI_VERSION); + milter_error(m); + return -1; + } + m->mf_fflags = ntohl(flags); + if (tTd(64, 5)) + dprintf("milter_negotiate(%s): version %d, flags %x\n", + m->mf_name, (u_long) ntohl(fvers), m->mf_fflags); + return 0; +} + /* +** MILTER_PER_CONNECTION_CHECK -- checks on per-connection commands +** +** Reduce code duplication by putting these checks in one place +** +** Parameters: +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_per_connection_check(e) + ENVELOPE *e; +{ + int i; + + /* see if we are done with any of the filters */ + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + if (m->mf_state == SMFS_DONE) + milter_quit_filter(m, e); + } +} + /* +** MILTER_ERROR -- Put a milter filter into error state +** +** Parameters: +** m -- the broken filter. +** +** Returns: +** none +*/ + +static void +milter_error(m) + struct milter *m; +{ + /* + ** We could send a quit here but + ** we may have gotten here due to + ** an I/O error so we don't want + ** to try to make things worse. + */ + + if (m->mf_sock >= 0) + { + (void) close(m->mf_sock); + m->mf_sock = -1; + } + m->mf_state = SMFS_ERROR; +} + +/* +** Actions +*/ + + /* +** MILTER_ADDHEAER -- Add the supplied header to the message +** +** Parameters: +** response -- encoded form of header/value. +** rlen -- length of response. +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_addheader(response, rlen, e) + char *response; + ssize_t rlen; + ENVELOPE *e; +{ + char *val; + + if (tTd(64, 10)) + dprintf("milter_addheader: "); + + /* sanity checks */ + if (response == NULL) + { + if (tTd(64, 10)) + dprintf("NULL response\n"); + return; + } + + if (rlen < 2 || strlen(response) + 1 >= rlen) + { + if (tTd(64, 10)) + dprintf("didn't follow protocol (total len)\n"); + return; + } + + /* Find separating NUL */ + val = response + strlen(response) + 1; + + /* another sanity check */ + if (strlen(response) + strlen(val) + 2 != rlen) + { + if (tTd(64, 10)) + dprintf("didn't follow protocol (part len)\n"); + return; + } + + /* add to e_msgsize */ + e->e_msgsize += strlen(response) + 2 + strlen(val); + + if (tTd(64, 10)) + dprintf("%s: %s\n", response, val); + + addheader(newstr(response), val, &e->e_header); +} + /* +** MILTER_ADDRCPT -- Add the supplied recipient to the message +** +** Parameters: +** response -- encoded form of recipient address. +** rlen -- length of response. +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_addrcpt(response, rlen, e) + char *response; + ssize_t rlen; + ENVELOPE *e; +{ + if (tTd(64, 10)) + dprintf("milter_addrcpt: "); + + /* sanity checks */ + if (response == NULL) + { + if (tTd(64, 10)) + dprintf("NULL response\n"); + return; + } + + if (*response == '\0' || + strlen(response) + 1 != rlen) + { + if (tTd(64, 10)) + dprintf("didn't follow protocol (total len)\n"); + return; + } + + if (tTd(64, 10)) + dprintf("%s\n", response); + (void) sendtolist(response, NULLADDR, &e->e_sendqueue, 0, e); + return; +} + /* +** MILTER_DELRCPT -- Delete the supplied recipient from the message +** +** Parameters: +** response -- encoded form of recipient address. +** rlen -- length of response. +** e -- current envelope. +** +** Returns: +** none +*/ + +static void +milter_delrcpt(response, rlen, e) + char *response; + ssize_t rlen; + ENVELOPE *e; +{ + if (tTd(64, 10)) + dprintf("milter_delrcpt: "); + + /* sanity checks */ + if (response == NULL) + { + if (tTd(64, 10)) + dprintf("NULL response\n"); + return; + } + + if (*response == '\0' || + strlen(response) + 1 != rlen) + { + if (tTd(64, 10)) + dprintf("didn't follow protocol (total len)\n"); + return; + } + + if (tTd(64, 10)) + dprintf("%s\n", response); + (void) removefromlist(response, &e->e_sendqueue, e); + return; +} + /* +** MILTER_REPLBODY -- Replace the current df file with new body +** +** Parameters: +** response -- encoded form of new body (first chunk). +** Used to return response buffer for return rcmd. +** rlen -- length of response. Also return length of final +** response. +** rcmd -- current command (used to return new command). +** m -- milter filter to read further chunks from. +** e -- current envelope. +** +** Returns: +** 0 upon success, -1 upon failure +*/ + +static int +milter_replbody(response, rlen, rcmd, m, e) + char **response; + ssize_t *rlen; + char *rcmd; + struct milter *m; + ENVELOPE *e; +{ + bool failure = FALSE; + char prevchar = '\0'; + int afd; + int i; + int save_errno; + off_t newsize = 0; + struct stat st; + char dfname[MAXPATHLEN]; + + if (tTd(64, 10)) + dprintf("milter_replbody(%s)\n", m->mf_name); + + /* save the df file name for later use */ + (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); + + /* Get the current df information */ + if (bitset(EF_HAS_DF, e->e_flags) && + e->e_dfp != NULL) + { + afd = fileno(e->e_dfp); + if (afd < 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): fstat %s: %s\n", + m->mf_name, dfname, + strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): fstat %s: %s", + m->mf_name, dfname, + strerror(save_errno)); + failure = TRUE; + } + else + { + /* fixup e->e_msgsize */ + if (fstat(afd, &st) == 0) + { + newsize = e->e_msgsize - st.st_size; + if (newsize < 0) + newsize = 0; + } + } + } + + /* + ** In SuperSafe mode, e->e_dfp is a read-only FP so + ** close and reopen writable (later close and reopen + ** read only again). + ** + ** In !SuperSafe mode, e->e_dfp still points at the + ** buffered file I/O descriptor, still open for writing + ** so there isn't as much work to do, just truncate it + ** and go. + */ + + if (SuperSafe) + { + /* close read-only df */ + if (bitset(EF_HAS_DF, e->e_flags) && + e->e_dfp != NULL) + (void) fclose(e->e_dfp); + + /* open writable */ + if ((e->e_dfp = fopen(dfname, "w")) == NULL) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): fopen %s: %s\n", + m->mf_name, dfname, + strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): fopen %s: %s", + m->mf_name, dfname, + strerror(save_errno)); + e->e_flags &= ~EF_HAS_DF; + failure = TRUE; + } + } + else if (e->e_dfp == NULL) + { + /* shouldn't happen */ + if (tTd(64, 5)) + dprintf("milter_replbody(%s): NULL e_dfp (%s)\n", + m->mf_name, dfname); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): NULL e_dfp (%s)\n", + m->mf_name, dfname); + failure = TRUE; + } + else if (bftruncate(e->e_dfp) < 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): bftruncate %s: %s\n", + m->mf_name, dfname, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): bftruncate %s: %s", + m->mf_name, dfname, strerror(save_errno)); + failure = TRUE; + } + + for (;;) + { + if (*response != NULL) + { + /* + ** Can't simply return on failure, have to + ** collect all data from remote filter to + ** prevent the protocol from getting out of sync. + ** Another way to fix this would be to have the + ** MTA ACK/NAK each body chunk it receives. + */ + + if (!failure) + { + for (i = 0; i < *rlen; i++) + { + /* Buffered char from last chunk */ + if (i == 0 && prevchar == '\r') + { + /* Not CRLF, output prevchar */ + if ((*response)[i] != '\n') + { + (void) putc(prevchar, + e->e_dfp); + if (newsize > 0) + newsize++; + } + prevchar = '\0'; + } + + /* Turn CRLF into LF */ + if ((*response)[i] == '\r') + { + /* check if at end of chunk */ + if (i + 1 < *rlen) + { + /* If LF, strip CR */ + if ((*response)[i + 1] == '\n') + i++; + } + else + { + /* check next chunk */ + prevchar = '\r'; + } + } + (void) putc((*response)[i], e->e_dfp); + if (newsize > 0) + newsize++; + } + } + free(*response); + *response = NULL; + } + + /* Get next command (might be another body chunk) */ + *response = milter_read(m, rcmd, rlen, + m->mf_timeout[SMFTO_READ], e); + + if (m->mf_state == SMFS_ERROR) + { + if (SuperSafe) + { + (void) fclose(e->e_dfp); + e->e_dfp = NULL; + e->e_flags &= ~EF_HAS_DF; + } + failure = TRUE; + break; + } + + /* If not another body chunk, save for returning */ + if (*rcmd != SMFIR_REPLBODY) + break; + + if (tTd(64, 10)) + dprintf("milter_replbody(%s): returned %c%s%s\n", + m->mf_name, (char) *rcmd, + *response == NULL ? "" : ":", + *response == NULL ? "" : *response); + } + + /* Now it's safe to return */ + if (failure) + return -1; + + if (fflush(e->e_dfp) != 0 || ferror(e->e_dfp)) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): error writing/flushing %s: %s\n", + m->mf_name, dfname, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): error writing/flushing %s: %s", + m->mf_name, dfname, strerror(save_errno)); + if (SuperSafe) + { + (void) fclose(e->e_dfp); + e->e_dfp = NULL; + e->e_flags &= ~EF_HAS_DF; + } + return -1; + } + else if (!SuperSafe) + { + /* skip next few clauses */ + /* EMPTY */ + } + else if ((afd = fileno(e->e_dfp)) >= 0 && fsync(afd) < 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): error sync'ing %s: %s\n", + m->mf_name, dfname, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): error sync'ing %s: %s", + m->mf_name, dfname, strerror(save_errno)); + (void) fclose(e->e_dfp); + e->e_dfp = NULL; + e->e_flags &= ~EF_HAS_DF; + return -1; + } + else if (fclose(e->e_dfp) < 0) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): error closing %s: %s\n", + m->mf_name, dfname, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): error closing %s: %s", + m->mf_name, dfname, strerror(save_errno)); + e->e_flags &= ~EF_HAS_DF; + return -1; + } + else if ((e->e_dfp = fopen(dfname, "r")) == NULL) + { + save_errno = errno; + if (tTd(64, 5)) + dprintf("milter_replbody(%s): error reopening %s: %s", + m->mf_name, dfname, strerror(save_errno)); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_replbody(%s): error reopening %s: %s", + m->mf_name, dfname, strerror(save_errno)); + e->e_flags &= ~EF_HAS_DF; + return -1; + } + else + e->e_flags |= EF_HAS_DF; + + /* Set the message size */ + if (newsize > 0) + e->e_msgsize = newsize; + return 0; +} + +/* +** MTA callouts +*/ + + /* +** MILTER_INIT -- open and negotiate with all of the filters +** +** Parameters: +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** none +*/ + +/* ARGSUSED */ +void +milter_init(e, state) + ENVELOPE *e; + char *state; +{ + int i; + + if (tTd(64, 10)) + dprintf("milter_init\n"); + + *state = SMFIR_CONTINUE; + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + m->mf_sock = milter_open(m, FALSE, e); + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + break; + } + + if (m->mf_sock < 0 || + milter_negotiate(m, e) < 0 || + m->mf_state == SMFS_ERROR) + { + if (tTd(64, 5)) + dprintf("milter_init(%s): failed to %s\n", + m->mf_name, + m->mf_sock < 0 ? "open" : "negotiate"); + + /* if negotation failure, close socket */ + if (m->mf_sock >= 0) + { + (void) close(m->mf_sock); + m->mf_sock = -1; + } + milter_error(m); + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + break; + } + } + } + + /* + ** If something temp/perm failed with one of the filters, + ** we won't be using any of them, so clear any existing + ** connections. + */ + + if (*state != SMFIR_CONTINUE) + milter_quit(e); +} + /* +** MILTER_CONNECT -- send connection info to milter filters +** +** Parameters: +** hostname -- hostname of remote machine. +** addr -- address of remote machine. +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_connect(hostname, addr, e, state) + char *hostname; + SOCKADDR addr; + ENVELOPE *e; + char *state; +{ + char family; + u_short port; + char *buf, *bp; + char *response; + char *sockinfo = NULL; + ssize_t s; +# if NETINET6 + char buf6[INET6_ADDRSTRLEN]; +# endif /* NETINET6 */ + + if (tTd(64, 10)) + dprintf("milter_connect(%s)\n", hostname); + + /* gather data */ + switch (addr.sa.sa_family) + { +# if NETUNIX + case AF_UNIX: + family = SMFIA_UNIX; + port = htons(0); + sockinfo = addr.sunix.sun_path; + break; +# endif /* NETUNIX */ + +# if NETINET + case AF_INET: + family = SMFIA_INET; + port = htons(addr.sin.sin_port); + sockinfo = (char *) inet_ntoa(addr.sin.sin_addr); + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + family = SMFIA_INET6; + port = htons(addr.sin6.sin6_port); + sockinfo = anynet_ntop(&addr.sin6.sin6_addr, buf6, + sizeof buf6); + if (sockinfo == NULL) + sockinfo = ""; + break; +# endif /* NETINET6 */ + + default: + family = SMFIA_UNKNOWN; + break; + } + + s = strlen(hostname) + 1 + sizeof(family); + if (family != SMFIA_UNKNOWN) + s += sizeof(port) + strlen(sockinfo); + + buf = (char *)xalloc(s); + bp = buf; + + /* put together data */ + (void) memcpy(bp, hostname, strlen(hostname)); + bp += strlen(hostname); + *bp++ = '\0'; + (void) memcpy(bp, &family, sizeof family); + bp += sizeof family; + if (family != SMFIA_UNKNOWN) + { + (void) memcpy(bp, &port, sizeof port); + bp += sizeof port; + (void) memcpy(bp, sockinfo, strlen(sockinfo)); + } + + response = milter_command(SMFIC_CONNECT, buf, s, + MilterConnectMacros, e, state); + free(buf); + + /* + ** If this message connection is done for, + ** close the filters. + */ + + if (*state != SMFIR_CONTINUE) + milter_quit(e); + else + milter_per_connection_check(e); + + /* + ** SMFIR_REPLYCODE can't work with connect due to + ** the requirements of SMTP. Therefore, ignore the + ** reply code text but keep the state it would reflect. + */ + + if (*state == SMFIR_REPLYCODE) + { + if (response != NULL && + *response == '4') + *state = SMFIR_TEMPFAIL; + else + *state = SMFIR_REJECT; + if (response != NULL) + { + free(response); + response = NULL; + } + } + return response; +} + /* +** MILTER_HELO -- send SMTP HELO/EHLO command info to milter filters +** +** Parameters: +** helo -- argument to SMTP HELO/EHLO command. +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_helo(helo, e, state) + char *helo; + ENVELOPE *e; + char *state; +{ + char *response; + + if (tTd(64, 10)) + dprintf("milter_helo(%s)\n", helo); + + response = milter_command(SMFIC_HELO, helo, strlen(helo) + 1, + MilterHeloMacros, e, state); + milter_per_connection_check(e); + return response; +} + /* +** MILTER_ENVFROM -- send SMTP MAIL command info to milter filters +** +** Parameters: +** args -- SMTP MAIL command args (args[0] == sender). +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_envfrom(args, e, state) + char **args; + ENVELOPE *e; + char *state; +{ + int i; + char *buf, *bp; + char *response; + ssize_t s; + + if (tTd(64, 10)) + { + dprintf("milter_envfrom:"); + for (i = 0; args[i] != NULL; i++) + dprintf(" %s", args[i]); + dprintf("\n"); + } + + /* sanity check */ + if (args[0] == NULL) + { + *state = SMFIR_REJECT; + return NULL; + } + + /* new message, so ... */ + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + switch (m->mf_state) + { + case SMFS_INMSG: + /* abort in message filters */ + milter_abort_filter(m, e); + /* FALLTHROUGH */ + + case SMFS_DONE: + /* reset done filters */ + m->mf_state = SMFS_OPEN; + break; + } + } + + /* put together data */ + s = 0; + for (i = 0; args[i] != NULL; i++) + s += strlen(args[i]) + 1; + buf = (char *)xalloc(s); + bp = buf; + for (i = 0; args[i] != NULL; i++) + { + (void) strlcpy(bp, args[i], s - (bp - buf)); + bp += strlen(bp) + 1; + } + + /* send it over */ + response = milter_command(SMFIC_MAIL, buf, s, + MilterEnvFromMacros, e, state); + free(buf); + + /* + ** If filter rejects/discards a per message command, + ** abort the other filters since we are done with the + ** current message. + */ + + MILTER_CHECK_DONE_MSG(); + return response; +} + /* +** MILTER_ENVRCPT -- send SMTP RCPT command info to milter filters +** +** Parameters: +** args -- SMTP MAIL command args (args[0] == recipient). +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_envrcpt(args, e, state) + char **args; + ENVELOPE *e; + char *state; +{ + int i; + char *buf, *bp; + char *response; + ssize_t s; + + if (tTd(64, 10)) + { + dprintf("milter_envrcpt:"); + for (i = 0; args[i] != NULL; i++) + dprintf(" %s", args[i]); + dprintf("\n"); + } + + /* sanity check */ + if (args[0] == NULL) + { + *state = SMFIR_REJECT; + return NULL; + } + + /* put together data */ + s = 0; + for (i = 0; args[i] != NULL; i++) + s += strlen(args[i]) + 1; + buf = (char *)xalloc(s); + bp = buf; + for (i = 0; args[i] != NULL; i++) + { + (void) strlcpy(bp, args[i], s - (bp - buf)); + bp += strlen(bp) + 1; + } + + /* send it over */ + response = milter_command(SMFIC_RCPT, buf, s, + MilterEnvRcptMacros, e, state); + free(buf); + return response; +} + /* +** MILTER_HEADER -- send single header to milter filters +** +** Parameters: +** name -- header field name. +** value -- header value (including continuation lines). +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_header(name, value, e, state) + char *name; + char *value; + ENVELOPE *e; + char *state; +{ + char *buf; + char *response; + ssize_t s; + + if (tTd(64, 10)) + dprintf("milter_header: %s: %s\n", name, value); + + s = strlen(name) + 1 + strlen(value) + 1; + buf = (char *) xalloc(s); + snprintf(buf, s, "%s%c%s", name, '\0', value); + + /* send it over */ + response = milter_command(SMFIC_HEADER, buf, s, NULL, e, state); + free(buf); + + /* + ** If filter rejects/discards a per message command, + ** abort the other filters since we are done with the + ** current message. + */ + + MILTER_CHECK_DONE_MSG(); + return response; +} + /* +** MILTER_EOH -- notify milter filters that the headers are done +** +** Parameters: +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +*/ + +char * +milter_eoh(e, state) + ENVELOPE *e; + char *state; +{ + char *response; + + if (tTd(64, 10)) + dprintf("milter_eoh\n"); + + response = milter_command(SMFIC_EOH, NULL, 0, NULL, e, state); + + /* + ** If filter rejects/discards a per message command, + ** abort the other filters since we are done with the + ** current message. + */ + + MILTER_CHECK_DONE_MSG(); + return response; +} + /* +** MILTER_BODY -- send message body and gather final message results +** +** Parameters: +** e -- current envelope. +** state -- return state from response. +** +** Returns: +** response string (may be NULL) +** +** Side effects: +** - Uses e->e_dfp for access to the body +** - Can call the various milter action routines to +** modify the envelope or message. +*/ + +char * +milter_body(e, state) + ENVELOPE *e; + char *state; +{ + bool replfailed = FALSE; + bool rewind = FALSE; + char rcmd; + char bufchar = '\0'; + char prevchar = '\0'; + int i; + int c; + int save_errno; + char *bp; + char *response = NULL; + time_t eomsent; + ssize_t rlen; + char buf[MILTER_CHUNK_SIZE]; + + if (tTd(64, 10)) + dprintf("milter_body\n"); + + *state = SMFIR_CONTINUE; + +/* +** XXX: Should actually send body chunks to each filter +** a chunk at a time instead of sending the whole body to +** each filter in turn +*/ + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + if (*state != SMFIR_CONTINUE && + *state != SMFIR_ACCEPT) + { + /* + ** A previous filter has dealt with the message, + ** safe to stop processing the filters. + */ + + break; + } + + /* Now reset state for later evaluation */ + *state = SMFIR_CONTINUE; + + /* sanity checks */ + if (m->mf_sock < 0 || + (m->mf_state != SMFS_OPEN && m->mf_state != SMFS_INMSG)) + continue; + + m->mf_state = SMFS_INMSG; + bp = buf; + + /* check if filter wants the body */ + if (bitset(SMFIF_NOBODY, m->mf_fflags)) + { + /* still need to send BODYEOB */ + goto eob; + } + + if (e->e_dfp == NULL) + { + /* shouldn't happen */ + goto eob; + } + + if (bfrewind(e->e_dfp) < 0) + { + ExitStat = EX_IOERR; + *state = SMFIR_TEMPFAIL; + syserr("milter_body: %s/df%s: read error", + qid_printqueue(e->e_queuedir), e->e_id); + break; + } + + rewind = TRUE; + while ((c = getc(e->e_dfp)) != EOF) + { + /* Change LF to CRLF */ + if (c == '\n') + { + /* Not a CRLF already? */ + if (prevchar != '\r') + { + /* Room for CR now? */ + if (bp + 2 >= &buf[sizeof buf]) + { + /* No room, buffer LF */ + bufchar = c; + + /* and send CR now */ + c = '\r'; + } + else + { + /* Room to do it all now */ + *bp++ = '\r'; + prevchar = '\r'; + } + } + } + *bp++ = (char) c; + prevchar = c; + if (bp >= &buf[sizeof buf]) + { + /* send chunk */ + (void) milter_write(m, SMFIC_BODY, buf, + buf - bp, + m->mf_timeout[SMFTO_WRITE], + e); + if (m->mf_state == SMFS_ERROR) + break; + bp = buf; + if (bufchar != '\0') + { + *bp++ = bufchar; + bufchar = '\0'; + prevchar = bufchar; + } + + /* get reply */ + response = milter_read(m, &rcmd, &rlen, + m->mf_timeout[SMFTO_READ], + e); + if (m->mf_state == SMFS_ERROR) + break; + switch (rcmd) + { + case SMFIR_REPLYCODE: + MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected"); + /* FALLTHROUGH */ + + case SMFIR_REJECT: + case SMFIR_DISCARD: + case SMFIR_TEMPFAIL: + case SMFIR_ACCEPT: + case SMFIR_CONTINUE: + *state = rcmd; + if (*state != SMFIR_CONTINUE) + m->mf_state = SMFS_DONE; + break; + + default: + /* Invalid response to command */ + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_body(%s): returned bogus response %c", + m->mf_name, rcmd); + milter_error(m); + break; + } + if (rcmd != SMFIR_REPLYCODE && + response != NULL) + { + free(response); + response = NULL; + } + } + if (*state == SMFIR_ACCEPT) + break; + + if (*state != SMFIR_CONTINUE) + goto finishup; + } + + /* check for read errors */ + if (ferror(e->e_dfp)) + goto death; + + /* if filter accepted the message, move on to the next one */ + if (*state == SMFIR_ACCEPT) + continue; + +eob: + /* Make sure there wasn't an error above before proceeding */ + if (m->mf_state != SMFS_ERROR) + { + /* send the final body chunk */ + (void) milter_write(m, SMFIC_BODYEOB, buf, bp - buf, + m->mf_timeout[SMFTO_WRITE], e); + } + else + { + MILTER_CHECK_ERROR(); + goto finishup; + } + + /* Get time EOM sent for timeout */ + eomsent = curtime(); + + /* deal with the possibility of multiple responses */ + while (*state == SMFIR_CONTINUE) + { + /* From a prevous state */ + if (m->mf_state == SMFS_ERROR) + break; + + /* Check total timeout from EOM to final ACK/NAK */ + if (m->mf_timeout[SMFTO_EOM] > 0 && + curtime() - eomsent >= m->mf_timeout[SMFTO_EOM]) + { + if (tTd(64, 5)) + dprintf("milter_body(%s): EOM ACK/NAK timeout\n", + m->mf_name); + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_body(%s): EOM ACK/NAK timeout\n", + m->mf_name); + milter_error(m); + MILTER_CHECK_ERROR(); + break; + } + + response = milter_read(m, &rcmd, &rlen, + m->mf_timeout[SMFTO_READ], e); + if (m->mf_state == SMFS_ERROR) + break; + +newstate: + if (tTd(64, 10)) + dprintf("milter_body(%s): state %c%s%s\n", + m->mf_name, (char) rcmd, + response == NULL ? "" : ":", + response == NULL ? "" : response); + + switch (rcmd) + { + case SMFIR_REPLYCODE: + MILTER_CHECK_REPLYCODE("554 5.7.1 Command rejected"); + *state = rcmd; + m->mf_state = SMFS_DONE; + break; + + case SMFIR_REJECT: + case SMFIR_DISCARD: + case SMFIR_TEMPFAIL: + *state = rcmd; + m->mf_state = SMFS_DONE; + break; + + case SMFIR_CONTINUE: + case SMFIR_ACCEPT: + /* this filter is done with message */ + if (replfailed) + *state = SMFIR_TEMPFAIL; + else + *state = SMFIR_ACCEPT; + m->mf_state = SMFS_DONE; + break; + + case SMFIR_PROGRESS: + break; + + case SMFIR_ADDHEADER: + if (!bitset(SMFIF_MODHDRS, m->mf_fflags)) + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "milter_body(%s): lied about adding headers, honoring request anyway", + m->mf_name); + } + milter_addheader(response, rlen, e); + break; + + case SMFIR_ADDRCPT: + if (!bitset(SMFIF_ADDRCPT, m->mf_fflags)) + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "milter_body(%s) lied about adding recipients, honoring request anyway", + m->mf_name); + } + milter_addrcpt(response, rlen, e); + break; + + case SMFIR_DELRCPT: + if (!bitset(SMFIF_DELRCPT, m->mf_fflags)) + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "milter_body(%s): lied about removing recipients, honoring request anyway", + m->mf_name); + } + milter_delrcpt(response, rlen, e); + break; + + case SMFIR_REPLBODY: + if (!bitset(SMFIF_MODBODY, m->mf_fflags)) + { + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_body(%s): lied about replacing body, rejecting request and tempfailing message", + m->mf_name); + replfailed = TRUE; + goto newstate; + } + rewind = TRUE; + + /* protect &response in next command */ + if (response == NULL) + { + response = newstr(""); + rlen = 0; + } + + if (milter_replbody(&response, &rlen, + &rcmd, m, e) < 0) + { + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_body(%s): Failed to replace body, tempfailing message", + m->mf_name); + replfailed = TRUE; + rewind = FALSE; + } + goto newstate; + + default: + /* Invalid response to command */ + if (LogLevel > 0) + sm_syslog(LOG_ERR, e->e_id, + "milter_body(%s): returned bogus response %c", + m->mf_name, rcmd); + milter_error(m); + break; + } + if (rcmd != SMFIR_REPLYCODE && + response != NULL) + { + free(response); + response = NULL; + } + } + if (m->mf_state == SMFS_ERROR) + { + MILTER_CHECK_ERROR(); + goto finishup; + } + } + +finishup: + /* leave things in the expected state if we touched it */ + if (rewind && bfrewind(e->e_dfp) < 0) + { +death: + save_errno = errno; + ExitStat = EX_IOERR; + + /* + ** If filter told us to keep message but we had + ** an error, we can't really keep it, tempfail it. + */ + + if (*state == SMFIR_CONTINUE || + *state == SMFIR_ACCEPT) + *state = SMFIR_TEMPFAIL; + + errno = save_errno; + syserr("milter_body: %s/df%s: read error", + qid_printqueue(e->e_queuedir), e->e_id); + } + return response; +} + /* +** MILTER_QUIT -- informs the filter(s) we are done and closes connection(s) +** +** Parameters: +** e -- current envelope. +** +** Returns: +** none +*/ + +void +milter_quit(e) + ENVELOPE *e; +{ + int i; + + if (tTd(64, 10)) + dprintf("milter_quit\n"); + + for (i = 0; InputFilters[i] != NULL; i++) + milter_quit_filter(InputFilters[i], e); +} + /* +** MILTER_ABORT -- informs the filter(s) that we are aborting current message +** +** Parameters: +** e -- current envelope. +** +** Returns: +** none +*/ + +void +milter_abort(e) + ENVELOPE *e; +{ + int i; + + if (tTd(64, 10)) + dprintf("milter_abort\n"); + + for (i = 0; InputFilters[i] != NULL; i++) + { + struct milter *m = InputFilters[i]; + + /* sanity checks */ + if (m->mf_sock < 0 || m->mf_state != SMFS_INMSG) + continue; + + milter_abort_filter(m, e); + } +} +#endif /* _FFR_MILTER */ diff --git a/gnu/usr.sbin/sendmail/sendmail/mime.c b/gnu/usr.sbin/sendmail/sendmail/mime.c new file mode 100644 index 00000000000..32d014cdd37 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/mime.c @@ -0,0 +1,1195 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1994, 1996-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1994 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: mime.c,v 8.94 1999/10/17 17:35:58 ca Exp $"; +#endif /* ! lint */ + +static int isboundary __P((char *, char **)); +static int mimeboundary __P((char *, char **)); +static int mime_fromqp __P((u_char *, u_char **, int, int)); +static int mime_getchar __P((FILE *, char **, int *)); +static int mime_getchar_crlf __P((FILE *, char **, int *)); + +/* +** 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 */ +static char Base16Code[] = "0123456789ABCDEF"; +static 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" +}; + +static bool MapNLtoCRLF; + + /* +** 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 *a_field; /* name of field */ + char *a_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; + bool use_qp = FALSE; + struct args argv[MAXMIMEARGS]; + char bbuf[128]; + char buf[MAXLINE]; + char pvpbuf[MAXLINE]; + extern u_char MimeTokenTab[256]; + + if (tTd(43, 1)) + { + dprintf("mime8to7: flags = %x, boundaries =", flags); + if (boundaries[0] == NULL) + dprintf(" "); + else + { + for (i = 0; boundaries[i] != NULL; i++) + dprintf(" %s", boundaries[i]); + } + dprintf("\n"); + } + MapNLtoCRLF = TRUE; + 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++) + dprintf("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; + + /* complain about empty values */ + if (strcmp(*pvp, ";") == 0) + { + usrerr("mime8to7: Empty parameter in Content-Type header"); + + /* avoid bounce loops */ + e->e_flags |= EF_DONT_MIME; + continue; + } + + /* extract field name */ + argv[argc].a_field = *pvp++; + + /* see if there is a value */ + if (*pvp != NULL && strcmp(*pvp, "=") == 0 && + (*++pvp == NULL || strcmp(*pvp, ";") != 0)) + { + argv[argc].a_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. + */ + + snprintf(buf, sizeof buf, "%.100s/%.100s", type, subtype); + if (wordinclass(buf, 'n') || (cte != NULL && !wordinclass(cte, 'e'))) + flags |= M87F_NO8BIT; + +# ifdef USE_B_CLASS + if (wordinclass(buf, 'b') || wordinclass(type, 'b')) + MapNLtoCRLF = FALSE; +# endif /* USE_B_CLASS */ + if (wordinclass(buf, 'q') || wordinclass(type, 'q')) + use_qp = TRUE; + + /* + ** Multipart requires special processing. + ** + ** Do a recursive descent into the message. + */ + + if (strcasecmp(type, "multipart") == 0 && + (!bitset(M87F_NO8BIT, flags) || bitset(M87F_NO8TO7, flags))) + { + + if (strcasecmp(subtype, "digest") == 0) + flags |= M87F_DIGEST; + + for (i = 0; i < argc; i++) + { + if (strcasecmp(argv[i].a_field, "boundary") == 0) + break; + } + if (i >= argc || argv[i].a_value == NULL) + { + usrerr("mime8to7: Content-Type: \"%s\": %s boundary", + i >= argc ? "missing" : "bogus", p); + p = "---"; + + /* avoid bounce loops */ + e->e_flags |= EF_DONT_MIME; + } + else + { + p = argv[i].a_value; + stripquotes(p); + } + if (strlcpy(bbuf, p, sizeof bbuf) >= sizeof bbuf) + { + usrerr("mime8to7: multipart boundary \"%s\" too long", + p); + + /* avoid bounce loops */ + e->e_flags |= EF_DONT_MIME; + } + + if (tTd(43, 1)) + dprintf("mime8to7: multipart boundary \"%s\"\n", bbuf); + for (i = 0; i < MAXMIMENESTING; i++) + if (boundaries[i] == NULL) + break; + if (i >= MAXMIMENESTING) + { + usrerr("mime8to7: multipart nesting boundary too deep"); + + /* avoid bounce loops */ + e->e_flags |= EF_DONT_MIME; + } + else + { + boundaries[i] = bbuf; + boundaries[i + 1] = NULL; + } + mci->mci_flags |= MCIF_INMIME; + + /* skip the early "comment" prologue */ + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + bt = MBT_FINAL; + while (fgets(buf, sizeof buf, e->e_dfp) != NULL) + { + bt = mimeboundary(buf, boundaries); + if (bt != MBT_NOTSEP) + break; + putxline(buf, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT); + if (tTd(43, 99)) + dprintf(" ...%s", buf); + } + if (feof(e->e_dfp)) + bt = MBT_FINAL; + while (bt != MBT_FINAL) + { + auto HDR *hdr = NULL; + + snprintf(buf, sizeof buf, "--%s", bbuf); + putline(buf, mci); + if (tTd(43, 35)) + dprintf(" ...%s\n", buf); + collect(e->e_dfp, FALSE, &hdr, e); + if (tTd(43, 101)) + putline("+++after collect", mci); + putheader(mci, hdr, e, flags); + if (tTd(43, 101)) + putline("+++after putheader", mci); + bt = mime8to7(mci, hdr, e, boundaries, flags); + } + snprintf(buf, sizeof buf, "--%s--", bbuf); + putline(buf, mci); + if (tTd(43, 35)) + dprintf(" ...%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, strlen(buf), mci, PXLF_MAPFROM|PXLF_STRIP8BIT); + if (tTd(43, 99)) + dprintf(" ...%s", buf); + } + if (feof(e->e_dfp)) + bt = MBT_FINAL; + if (tTd(43, 3)) + dprintf("\t\t\tmime8to7=>%s (multipart)\n", + MimeBoundaryNames[bt]); + return bt; + } + + /* + ** Message/xxx 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, &hdr, e); + if (tTd(43, 101)) + putline("+++after collect", mci); + putheader(mci, hdr, e, flags); + 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|M87F_NO8TO7, 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)) + { + dprintf("mime8to7: %ld high bit(s) in %ld byte(s), cte=%s, type=%s/%s\n", + (long) sectionhighbits, (long) sectionsize, + cte == NULL ? "[none]" : cte, + type == NULL ? "[none]" : type, + subtype == NULL ? "[none]" : subtype); + } + if (cte != NULL && strcasecmp(cte, "binary") == 0) + sectionsize = sectionhighbits; + linelen = 0; + bp = buf; + if (sectionhighbits == 0) + { + /* no encoding necessary */ + if (cte != NULL && + bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, + mci->mci_flags) && + !bitset(M87F_NO8TO7, flags)) + { + /* + ** Skip _unless_ in MIME mode and potentially + ** converting from 8 bit to 7 bit MIME. See + ** putheader() for the counterpart where the + ** CTE header is skipped in the opposite + ** situation. + */ + + snprintf(buf, sizeof buf, + "Content-Transfer-Encoding: %.200s", cte); + putline(buf, mci); + if (tTd(43, 36)) + dprintf(" ...%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 (!MapNLtoCRLF || + (sectionsize / 8 < sectionhighbits && !use_qp)) + { + /* use base64 encoding */ + int c1, c2; + + if (tTd(43, 36)) + dprintf(" ...Content-Transfer-Encoding: base64\n"); + putline("Content-Transfer-Encoding: base64", mci); + snprintf(buf, sizeof buf, + "X-MIME-Autoconverted: from 8bit to base64 by %s id %s", + MyHostName, e->e_id); + putline(buf, mci); + 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; + BITMAP256 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); + + if (tTd(43, 36)) + dprintf(" ...Content-Transfer-Encoding: quoted-printable\n"); + putline("Content-Transfer-Encoding: quoted-printable", mci); + snprintf(buf, sizeof buf, + "X-MIME-Autoconverted: from 8bit to quoted-printable by %s id %s", + MyHostName, e->e_id); + putline(buf, mci); + 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)) + dprintf("\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. +*/ + +static 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 */ + int start = 0; /* indicates position of - in buffer */ + + if (buflen == 1 && *bp == '\n') + { + /* last \n in buffer may be part of next MIME boundary */ + c = *bp; + } + else if (buflen > 0) + { + buflen--; + return *bp++; + } + else + c = getc(fp); + bp = buf; + buflen = 0; + if (c == '\n') + { + /* might be part of a MIME boundary */ + *bp++ = c; + atbol = TRUE; + c = getc(fp); + if (c == '\n') + { + (void) ungetc(c, fp); + return c; + } + start = 1; + } + 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((char *) &buf[start], 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. +*/ + +static 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' && MapNLtoCRLF) + { + 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. +*/ + +static 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)) + dprintf("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)) + dprintf("%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. +** +*/ + +static 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 /* MIME8TO7 */ + +#if MIME7TO8 + +/* +** MIME7TO8 -- output 7 bit encoded MIME body in 8 bit format +** +** This is a hack. Supports translating the two 7-bit body-encodings +** (quoted-printable and base64) to 8-bit coded bodies. +** +** There is not much point in supporting multipart here, as the UA +** will be able to deal with encoded MIME bodies if it can parse MIME +** multipart messages. +** +** Note also that we wont be called unless it is a text/plain MIME +** message, encoded base64 or QP and mailer flag '9' has been defined +** on mailer. +** +** Contributed by Marius Olaffson . +** +** Parameters: +** mci -- mailer connection information. +** header -- the header for this body part. +** e -- envelope. +** +** Returns: +** none. +*/ + +static char index_64[128] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +}; + +# define CHAR64(c) (((c) < 0 || (c) > 127) ? -1 : index_64[(c)]) + +void +mime7to8(mci, header, e) + register MCI *mci; + HDR *header; + register ENVELOPE *e; +{ + register char *p; + char *cte; + char **pvp; + u_char *fbufp; + char buf[MAXLINE]; + u_char fbuf[MAXLINE + 1]; + char pvpbuf[MAXLINE]; + extern u_char MimeTokenTab[256]; + + p = hvalue("Content-Transfer-Encoding", header); + if (p == NULL || + (pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL, + MimeTokenTab)) == NULL || + pvp[0] == NULL) + { + /* "can't happen" -- upper level should have caught this */ + syserr("mime7to8: unparsable CTE %s", p == NULL ? "" : p); + + /* avoid bounce loops */ + e->e_flags |= EF_DONT_MIME; + + /* cheap failsafe algorithm -- should work on text/plain */ + if (p != NULL) + { + snprintf(buf, sizeof buf, + "Content-Transfer-Encoding: %s", p); + putline(buf, mci); + } + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + while (fgets(buf, sizeof buf, e->e_dfp) != NULL) + putline(buf, mci); + return; + } + cataddr(pvp, NULL, buf, sizeof buf, '\0'); + cte = newstr(buf); + + mci->mci_flags |= MCIF_INHEADER; + putline("Content-Transfer-Encoding: 8bit", mci); + snprintf(buf, sizeof buf, + "X-MIME-Autoconverted: from %.200s to 8bit by %s id %s", + cte, MyHostName, e->e_id); + putline(buf, mci); + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + + /* + ** Translate body encoding to 8-bit. Supports two types of + ** encodings; "base64" and "quoted-printable". Assume qp if + ** it is not base64. + */ + + if (strcasecmp(cte, "base64") == 0) + { + int c1, c2, c3, c4; + + fbufp = fbuf; + while ((c1 = fgetc(e->e_dfp)) != EOF) + { + if (isascii(c1) && isspace(c1)) + continue; + + do + { + c2 = fgetc(e->e_dfp); + } while (isascii(c2) && isspace(c2)); + if (c2 == EOF) + break; + + do + { + c3 = fgetc(e->e_dfp); + } while (isascii(c3) && isspace(c3)); + if (c3 == EOF) + break; + + do + { + c4 = fgetc(e->e_dfp); + } while (isascii(c4) && isspace(c4)); + if (c4 == EOF) + break; + + if (c1 == '=' || c2 == '=') + continue; + c1 = CHAR64(c1); + c2 = CHAR64(c2); + + *fbufp = (c1 << 2) | ((c2 & 0x30) >> 4); + if (*fbufp++ == '\n' || fbufp >= &fbuf[MAXLINE]) + { + if (*--fbufp != '\n' || + (fbufp > fbuf && *--fbufp != '\r')) + fbufp++; + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); + fbufp = fbuf; + } + if (c3 == '=') + continue; + c3 = CHAR64(c3); + *fbufp = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2); + if (*fbufp++ == '\n' || fbufp >= &fbuf[MAXLINE]) + { + if (*--fbufp != '\n' || + (fbufp > fbuf && *--fbufp != '\r')) + fbufp++; + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); + fbufp = fbuf; + } + if (c4 == '=') + continue; + c4 = CHAR64(c4); + *fbufp = ((c3 & 0x03) << 6) | c4; + if (*fbufp++ == '\n' || fbufp >= &fbuf[MAXLINE]) + { + if (*--fbufp != '\n' || + (fbufp > fbuf && *--fbufp != '\r')) + fbufp++; + putxline((char *) fbuf, fbufp - fbuf, + mci, PXLF_MAPFROM); + fbufp = fbuf; + } + } + } + else + { + /* quoted-printable */ + fbufp = fbuf; + while (fgets(buf, sizeof buf, e->e_dfp) != NULL) + { + if (mime_fromqp((u_char *) buf, &fbufp, 0, + &fbuf[MAXLINE] - fbufp) == 0) + continue; + + if (fbufp - fbuf > 0) + putxline((char *) fbuf, fbufp - fbuf - 1, mci, + PXLF_MAPFROM); + fbufp = fbuf; + } + } + + /* force out partial last line */ + if (fbufp > fbuf) + { + *fbufp = '\0'; + putxline((char *) fbuf, fbufp - fbuf, mci, PXLF_MAPFROM); + } + if (tTd(43, 3)) + dprintf("\t\t\tmime7to8 => %s to 8bit done\n", cte); +} + /* +** The following is based on Borenstein's "codes.c" module, with simplifying +** changes as we do not deal with multipart, and to do the translation in-core, +** with an attempt to prevent overrun of output buffers. +** +** What is needed here are changes to defned this code better against +** bad encodings. Questionable to always return 0xFF for bad mappings. +*/ + +static char index_hex[128] = +{ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1 +}; + +# define HEXCHAR(c) (((c) < 0 || (c) > 127) ? -1 : index_hex[(c)]) + +static int +mime_fromqp(infile, outfile, state, maxlen) + u_char *infile; + u_char **outfile; + int state; /* Decoding body (0) or header (1) */ + int maxlen; /* Max # of chars allowed in outfile */ +{ + int c1, c2; + int nchar = 0; + + while ((c1 = *infile++) != '\0') + { + if (c1 == '=') + { + if ((c1 = *infile++) == 0) + break; + + if (c1 == '\n' || (c1 = HEXCHAR(c1)) == -1) + { + /* ignore it */ + if (state == 0) + return 0; + } + else + { + do + { + if ((c2 = *infile++) == '\0') + { + c2 = -1; + break; + } + } while ((c2 = HEXCHAR(c2)) == -1); + + if (c2 == -1 || ++nchar > maxlen) + break; + + *(*outfile)++ = c1 << 4 | c2; + } + } + else + { + if (state == 1 && c1 == '_') + c1 = ' '; + + if (++nchar > maxlen) + break; + + *(*outfile)++ = c1; + + if (c1 == '\n') + break; + } + } + *(*outfile)++ = '\0'; + return 1; +} +#endif /* MIME7TO8 */ diff --git a/gnu/usr.sbin/sendmail/sendmail/newaliases.0 b/gnu/usr.sbin/sendmail/sendmail/newaliases.0 new file mode 100644 index 00000000000..b8c6e40b5d8 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/newaliases.0 @@ -0,0 +1,66 @@ + + + +NEWALIASES(1) NEWALIASES(1) + + +NNAAMMEE + nneewwaalliiaasseess - rebuild the data base for the mail aliases + file + +SSYYNNOOPPSSIISS + nneewwaalliiaasseess + +DDEESSCCRRIIPPTTIIOONN + NNeewwaalliiaasseess rebuilds the random access data base for the + mail aliases file /etc/mail/aliases. It must be run each + time this file is changed in order for the change to take + effect. + + NNeewwaalliiaasseess is identical to ``sendmail -bi''. + + The nneewwaalliiaasseess utility exits 0 on success, and >0 if an + error occurs. + +FFIILLEESS + /etc/mail/aliases The mail aliases file + +SSEEEE AALLSSOO + aliases(5), sendmail(8) + +HHIISSTTOORRYY + The nneewwaalliiaasseess command appeared in 4.0BSD. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:46 $ 1 + + diff --git a/gnu/usr.sbin/sendmail/sendmail/newaliases.1 b/gnu/usr.sbin/sendmail/sendmail/newaliases.1 new file mode 100644 index 00000000000..f56ba8c6295 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/newaliases.1 @@ -0,0 +1,41 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1985, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: newaliases.1,v 8.15 1999/06/22 20:41:34 tony Exp $ +.\" +.TH NEWALIASES 1 "$Date: 2000/04/02 19:05:46 $" +.SH NAME +.B newaliases +\- rebuild the data base for the mail aliases file +.SH SYNOPSIS +.B newaliases +.SH DESCRIPTION +.B Newaliases +rebuilds the random access data base for the mail aliases file +/etc/mail/aliases. It must be run each time this file is changed +in order for the change to take effect. +.PP +.B Newaliases +is identical to ``sendmail -bi''. +.PP +The +.B newaliases +utility exits 0 on success, and >0 if an error occurs. +.SH FILES +.TP 2i +/etc/mail/aliases +The mail aliases file +.SH SEE ALSO +aliases(5), sendmail(8) +.SH HISTORY +The +.B newaliases +command appeared in 4.0BSD. diff --git a/gnu/usr.sbin/sendmail/sendmail/parseaddr.c b/gnu/usr.sbin/sendmail/sendmail/parseaddr.c new file mode 100644 index 00000000000..9ff47e4fd6b --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/parseaddr.c @@ -0,0 +1,2795 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: parseaddr.c,v 8.231 1999/12/06 21:48:51 ca Exp $"; +#endif /* ! lint */ + +#include + +static void allocaddr __P((ADDRESS *, int, char *)); +static int callsubr __P((char**, int, ENVELOPE *)); +static char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *)); +static ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *)); + +/* +** 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 qup; + char pvpbuf[PSBUFSIZE]; + + /* + ** Initialize and prescan address. + */ + + e->e_to = addr; + if (tTd(20, 1)) + dprintf("\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)) + dprintf("parseaddr-->NULL\n"); + return NULL; + } + + if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr)) + { + if (tTd(20, 1)) + dprintf("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. + */ + + qup = FALSE; + if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL) + qup = TRUE; + if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL) + qup = 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 (QS_IS_BADADDR(a->q_state)) + return a; + + /* + ** If there was a parsing failure, mark it for queueing. + */ + + if (qup && OpMode != MD_INITALIAS) + { + 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)) + dprintf("parseaddr: queuing message\n"); + message(msg); + if (e->e_message == NULL && e->e_sendmode != SM_DEFER) + e->e_message = newstr(msg); + a->q_state = QS_QUEUEUP; + a->q_status = "4.4.3"; + } + + /* + ** Compute return value. + */ + + if (tTd(20, 1)) + { + dprintf("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 (strlen(addr) > MAXNAME - 1) + { + usrerr("553 5.1.1 Address too long (%d bytes max)", + MAXNAME - 1); + goto failure; + } + 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 5.1.1 Address contained invalid control characters"); +failure: + 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. +*/ + +static void +allocaddr(a, flags, paddr) + register ADDRESS *a; + int flags; + char *paddr; +{ + if (tTd(24, 4)) + dprintf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr); + + a->q_paddr = paddr; + + if (a->q_user == NULL) + a->q_user = newstr(""); + if (a->q_host == NULL) + a->q_host = newstr(""); + + 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 = newstr(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) (if the token type +** for left paren is SPC). +** +** 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, SPC,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, SPC,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, +}; + +/* token type table: don't strip comments */ +u_char TokTypeNoC[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, OPR,OPR,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, +}; + + +#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; + bool route_syntax; + 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); + (void) strlcat(obuf, DELIMCHARS, sizeof obuf); + for (p = obuf; *p != '\0'; p++) + { + if (TokTypeTab[*p & 0xff] == ATM) + TokTypeTab[*p & 0xff] = OPR; + if (TokTypeNoC[*p & 0xff] == ATM) + TokTypeNoC[*p & 0xff] = OPR; + } + } + if (toktab == NULL) + toktab = TokTypeTab; + + /* make sure error messages don't have garbage on them */ + errno = 0; + + q = pvpbuf; + bslashmode = FALSE; + route_syntax = FALSE; + cmntcnt = 0; + anglecnt = 0; + avp = av; + state = ATM; + c = NOCHAR; + p = addr; + CurEnv->e_to = p; + if (tTd(22, 11)) + { + dprintf("prescan: "); + xputs(p); + dprintf("\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 5.1.1 Address too long"); + if (strlen(addr) > (SIZE_T) 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 && cmntcnt <= 0 && state != QST) + { + if (anglecnt <= 0) + break; + + /* special case for better error management */ + if (delim == ',' && !route_syntax) + { + usrerr("653 Unbalanced '<'"); + c = '>'; + p--; + } + } + + if (tTd(22, 101)) + dprintf("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) + { + /* EMPTY */ + /* do nothing, just avoid next clauses */ + } + else if (c == '(' && toktab['('] == SPC) + { + cmntcnt++; + c = NOCHAR; + } + else if (c == ')' && toktab['('] == SPC) + { + if (cmntcnt <= 0) + { + usrerr("653 Unbalanced ')'"); + c = NOCHAR; + } + else + cmntcnt--; + } + else if (cmntcnt > 0) + { + c = NOCHAR; + } + else if (c == '<') + { + char *ptr = p; + + anglecnt++; + while (isascii(*ptr) && isspace(*ptr)) + ptr++; + if (*ptr == '@') + route_syntax = TRUE; + } + else if (c == '>') + { + if (anglecnt <= 0) + { + usrerr("653 Unbalanced '>'"); + c = NOCHAR; + } + else + anglecnt--; + route_syntax = FALSE; + } + 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)) + dprintf("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)) + { + dprintf("tok="); + xputs(tok); + dprintf("\n"); + } + if (avp >= &av[MAXATOM]) + { + usrerr("553 5.1.0 prescan: too many tokens"); + goto returnnull; + } + if (q - tok > MAXNAME) + { + usrerr("553 5.1.0 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)) + { + dprintf("prescan==>"); + printav(av); + } + CurEnv->e_to = saveto; + if (av[0] == NULL) + { + if (tTd(22, 1)) + dprintf("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 **match_first; /* first token matched */ + char **match_last; /* last token matched */ + char **match_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 *rulename; /* ruleset name */ + register char *prefix; + 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 */ + char buf[MAXLINE]; + char name[6]; + + if (ruleset < 0 || ruleset >= MAXRWSETS) + { + syserr("554 5.3.5 rewrite: illegal ruleset number %d", ruleset); + return EX_CONFIG; + } + rulename = RuleSetNames[ruleset]; + if (rulename == NULL) + { + snprintf(name, sizeof name, "%d", ruleset); + rulename = name; + } + if (OpMode == MD_TEST) + prefix = ""; + else + prefix = "rewrite: ruleset "; + if (OpMode == MD_TEST) + { + printf("%s%-16.16s input:", prefix, rulename); + printav(pvp); + } + else if (tTd(21, 1)) + { + dprintf("%s%-16.16s input:", prefix, rulename); + printav(pvp); + } + if (reclevel++ > MaxRuleRecursion) + { + syserr("rewrite: excessive recursion (max %d), ruleset %s", + MaxRuleRecursion, rulename); + 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; ) + { + int status; + + /* if already canonical, quit now */ + if (pvp[0] != NULL && (pvp[0][0] & 0377) == CANONNET) + break; + + if (tTd(21, 12)) + { + if (tTd(21, 15)) + dprintf("-----trying rule (line %d):", + rwr->r_line); + else + dprintf("-----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 5.3.5 Infinite loop in ruleset %s, rule %d", + rulename, ruleno); + if (tTd(21, 1)) + { + dprintf("workspace: "); + printav(pvp); + } + break; + } + + while ((ap = *avp) != NULL || *rvp != NULL) + { + rp = *rvp; + if (tTd(21, 35)) + { + dprintf("ADVANCE rp="); + xputs(rp); + dprintf(", ap="); + xputs(ap); + dprintf("\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) + { + case MATCHCLASS: + /* match any phrase in a class */ + mlp->match_pattern = rvp; + mlp->match_first = avp; + extendclass: + ap = *avp; + if (ap == NULL) + goto backup; + mlp->match_last = avp++; + cataddr(mlp->match_first, mlp->match_last, + buf, sizeof buf, '\0'); + if (!wordinclass(buf, rp[1])) + { + if (tTd(21, 36)) + { + dprintf("EXTEND rp="); + xputs(rp); + dprintf(", ap="); + xputs(ap); + dprintf("\n"); + } + goto extendclass; + } + if (tTd(21, 36)) + dprintf("CLMATCH\n"); + mlp++; + break; + + case MATCHNCLASS: + /* match any token not in a class */ + if (wordinclass(ap, rp[1])) + goto backup; + + /* FALLTHROUGH */ + + case MATCHONE: + case MATCHANY: + /* match exactly one token */ + mlp->match_pattern = rvp; + mlp->match_first = avp; + mlp->match_last = avp++; + mlp++; + break; + + case MATCHZANY: + /* match zero or more tokens */ + mlp->match_pattern = rvp; + mlp->match_first = avp; + mlp->match_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->match_first = avp; + if (tTd(21, 2)) + dprintf("rewrite: LHS $&%s => \"%s\"\n", + macname(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->match_first; + goto backup; + } + ap += strlen(*avp++); + } + + /* match */ + break; + + default: + /* must have exact match */ + if (sm_strcasecmp(rp, ap)) + goto backup; + avp++; + break; + } + + /* successful match on this token */ + rvp++; + continue; + + backup: + /* match failed -- back up */ + while (--mlp >= mlist) + { + rvp = mlp->match_pattern; + rp = *rvp; + avp = mlp->match_last + 1; + ap = *avp; + + if (tTd(21, 36)) + { + dprintf("BACKUP rp="); + xputs(rp); + dprintf(", ap="); + xputs(ap); + dprintf("\n"); + } + + if (ap == NULL) + { + /* run off the end -- back up again */ + continue; + } + if ((*rp & 0377) == MATCHANY || + (*rp & 0377) == MATCHZANY) + { + /* extend binding and continue */ + mlp->match_last = avp++; + rvp++; + mlp++; + break; + } + if ((*rp & 0377) == MATCHCLASS) + { + /* extend binding and try again */ + mlp->match_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)) + dprintf("----- rule fails\n"); + rwr = rwr->r_next; + ruleno++; + loopcount = 0; + continue; + } + + rvp = rwr->r_rhs; + if (tTd(21, 12)) + { + dprintf("-----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; + } + + /* 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 5.3.5 rewrite: ruleset %s: replacement $%c out of bounds", + rulename, rp[1]); + return EX_CONFIG; + } + if (tTd(21, 15)) + { + dprintf("$%c:", rp[1]); + pp = m->match_first; + while (pp <= m->match_last) + { + dprintf(" %lx=\"", + (u_long) *pp); + (void) dflush(); + dprintf("%s\"", *pp++); + } + dprintf("\n"); + } + pp = m->match_first; + while (pp <= m->match_last) + { + if (avp >= &npvp[MAXATOM]) + { + syserr("554 5.3.0 rewrite: expansion too long"); + return EX_DATAERR; + } + *avp++ = *pp++; + } + } + else + { + /* some sort of replacement */ + if (avp >= &npvp[MAXATOM]) + { + toolong: + syserr("554 5.3.0 rewrite: expansion too long"); + return EX_DATAERR; + } + if ((*rp & 0377) != MACRODEXPAND) + { + /* vanilla replacement */ + *avp++ = rp; + } + else + { + /* $&x replacement */ + char *mval = macvalue(rp[1], e); + char **xpvp; + int trsize = 0; + static size_t pvpb1_size = 0; + static char **pvpb1 = NULL; + char pvpbuf[PSBUFSIZE]; + + if (tTd(21, 2)) + dprintf("rewrite: RHS $&%s => \"%s\"\n", + macname(rp[1]), + mval == NULL ? "(NULL)" : mval); + if (mval == NULL || *mval == '\0') + continue; + + /* save the remainder of the input */ + for (xpvp = pvp; *xpvp != NULL; xpvp++) + trsize += sizeof *xpvp; + if (trsize > pvpb1_size) + { + if (pvpb1 != NULL) + free(pvpb1); + pvpb1 = (char **)xalloc(trsize); + pvpb1_size = trsize; + } + + memmove((char *) pvpb1, + (char *) pvp, + trsize); + + /* scan the new replacement */ + xpvp = prescan(mval, '\0', pvpbuf, + sizeof pvpbuf, NULL, + NULL); + if (xpvp == NULL) + { + /* prescan pre-printed error */ + return EX_DATAERR; + } + + /* insert it into the output stream */ + while (*xpvp != NULL) + { + if (tTd(21, 19)) + dprintf(" ... %s\n", + *xpvp); + *avp++ = newstr(*xpvp); + if (avp >= &npvp[MAXATOM]) + goto toolong; + xpvp++; + } + if (tTd(21, 19)) + dprintf(" ... DONE\n"); + + /* restore the old trailing input */ + memmove((char *) pvp, + (char *) pvpb1, + trsize); + } + } + } + *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 cbuf[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 5.3.0 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; + memmove((char *) pvpb1, (char *) rvp, trsize); + + /* look it up */ + cataddr(key_rvp, NULL, cbuf, sizeof cbuf, + map == NULL ? '\0' : map->s_map.map_spacesub); + argvect[0] = cbuf; + replac = map_lookup(map, cbuf, argvect, &rstat, e); + + /* if no replacement, use default */ + if (replac == NULL && default_rvp != NULL) + { + /* create the default */ + cataddr(default_rvp, NULL, cbuf, sizeof cbuf, '\0'); + replac = cbuf; + } + + 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 */ + rvp = avp - 1; + for (xpvp = pvpb1; (*avp++ = *xpvp++) != NULL; ) + if (avp >= &npvp[MAXATOM]) + goto toolong; + } + + /* + ** Check for subroutine calls. + */ + + status = callsubr(npvp, reclevel, e); + if (rstat == EX_OK || status == EX_TEMPFAIL) + rstat = status; + + /* copy vector back into original space. */ + for (avp = npvp; *avp++ != NULL;) + continue; + memmove((char *) pvp, (char *) npvp, + (int) (avp - npvp) * sizeof *avp); + + if (tTd(21, 4)) + { + dprintf("rewritten as:"); + printav(pvp); + } + } + + if (OpMode == MD_TEST) + { + printf("%s%-16.16s returns:", prefix, rulename); + printav(pvp); + } + else if (tTd(21, 1)) + { + dprintf("%s%-16.16s returns:", prefix, rulename); + printav(pvp); + } + return rstat; +} + /* +** CALLSUBR -- call subroutines in rewrite vector +** +** Parameters: +** pvp -- pointer to token vector. +** reclevel -- the current recursion level. +** e -- the current envelope. +** +** Returns: +** The status from the subroutine call. +** +** Side Effects: +** pvp is modified. +*/ + +static int +callsubr(pvp, reclevel, e) + char **pvp; + int reclevel; + ENVELOPE *e; +{ + char **avp; + char **rvp; + register int i; + int subr; + int status; + int rstat = EX_OK; + char *tpvp[MAXATOM + 1]; + + for (avp = pvp; *avp != NULL; avp++) + { + if ((**avp & 0377) == CALLSUBR && avp[1] != NULL) + { + stripquotes(avp[1]); + subr = strtorwset(avp[1], NULL, ST_FIND); + if (subr < 0) + { + syserr("Unknown ruleset %s", avp[1]); + return EX_CONFIG; + } + + if (tTd(21, 3)) + dprintf("-----callsubr %s (%d)\n", + avp[1], subr); + + /* + ** Take care of possible inner calls first. + ** use a full size temporary buffer to avoid + ** overflows in rewrite, but strip off the + ** subroutine call. + */ + + for (i = 2; avp[i] != NULL; i++) + tpvp[i - 2] = avp[i]; + tpvp[i - 2] = NULL; + + status = callsubr(tpvp, reclevel, e); + if (rstat == EX_OK || status == EX_TEMPFAIL) + rstat = status; + + /* + ** Now we need to call the ruleset specified for + ** the subroutine. we can do this with the + ** temporary buffer that we set up earlier, + ** since it has all the data we want to rewrite. + */ + + status = rewrite(tpvp, subr, reclevel, e); + if (rstat == EX_OK || status == EX_TEMPFAIL) + rstat = status; + + /* + ** Find length of tpvp and current offset into + ** pvp, if the total is greater than MAXATOM, + ** then it would overflow the buffer if we copied + ** it back in to pvp, in which case we throw a + ** fit. + */ + + for (rvp = tpvp; *rvp != NULL; rvp++) + continue; + if (((rvp - tpvp) + (avp - pvp)) > MAXATOM) + { + syserr("554 5.3.0 callsubr: expansion too long"); + return EX_DATAERR; + } + + /* + ** Now we can copy the rewritten code over + ** the initial subroutine call in the buffer. + */ + + for (i = 0; tpvp[i] != NULL; i++) + avp[i] = tpvp[i]; + avp[i] = NULL; + + /* + ** If we got this far, we've processed the left + ** most subroutine, and recursively called ourselves + ** to handle any other subroutines. We're done. + */ + + break; + } + } + return rstat; +} + /* +** MAP_LOOKUP -- do lookup in map +** +** Parameters: +** map -- the map to use for the lookup. +** key -- the key to look up. +** argvect -- arguments to pass to the map lookup. +** pstat -- a pointer to an integer in which to store the +** status from the lookup. +** e -- the current envelope. +** +** Returns: +** The result of the lookup. +** NULL -- if there was no data for the given key. +*/ + +static char * +map_lookup(smap, key, argvect, pstat, e) + STAB *smap; + char key[]; + char **argvect; + int *pstat; + ENVELOPE *e; +{ + auto int status = EX_OK; + MAP *map; + char *replac; + + if (smap == NULL) + return NULL; + + map = &smap->s_map; + DYNOPENMAP(map); + + if (e->e_sendmode == SM_DEFER && + bitset(MF_DEFER, map->map_mflags)) + { + /* don't do any map lookups */ + if (tTd(60, 1)) + dprintf("map_lookup(%s, %s) => DEFERRED\n", + smap->s_name, key); + *pstat = EX_TEMPFAIL; + return NULL; + } + + if (!bitset(MF_KEEPQUOTES, map->map_mflags)) + stripquotes(key); + + if (tTd(60, 1)) + { + dprintf("map_lookup(%s, %s", smap->s_name, key); + if (tTd(60, 5)) + { + int i; + + for (i = 0; argvect[i] != NULL; i++) + dprintf(", %%%d=%s", i, argvect[i]); + } + dprintf(") => "); + } + replac = (*map->map_class->map_lookup)(map, key, argvect, &status); + if (tTd(60, 1)) + dprintf("%s (%d)\n", + replac != NULL ? replac : "NOT FOUND", + status); + + /* should recover if status == EX_TEMPFAIL */ + if (status == EX_TEMPFAIL && !bitset(MF_NODEFER, map->map_mflags)) + { + *pstat = EX_TEMPFAIL; + if (tTd(60, 1)) + dprintf("map_lookup(%s, %s) tempfail: errno=%d\n", + smap->s_name, key, errno); + if (e->e_message == NULL) + { + char mbuf[320]; + + snprintf(mbuf, sizeof mbuf, + "%.80s map: lookup (%s): deferred", + smap->s_name, + shortenstring(key, MAXSHORTSTR)); + e->e_message = newstr(mbuf); + } + } + if (status == EX_TEMPFAIL && map->map_tapp != NULL) + { + size_t i = strlen(key) + strlen(map->map_tapp) + 1; + static char *rwbuf = NULL; + static size_t rwbuflen = 0; + + if (i > rwbuflen) + { + if (rwbuf != NULL) + free(rwbuf); + rwbuflen = i; + rwbuf = (char *) xalloc(rwbuflen); + } + snprintf(rwbuf, rwbuflen, "%s%s", key, map->map_tapp); + if (tTd(60, 4)) + dprintf("map_lookup tempfail: returning \"%s\"\n", + rwbuf); + return rwbuf; + } + return replac; +} + /* +** INITERRMAILERS -- initialize error and discard mailers +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** initializes error and discard mailers. +*/ + +static MAILER discardmailer; +static MAILER errormailer; +static char *discardargv[] = { "DISCARD", NULL }; +static char *errorargv[] = { "ERROR", NULL }; + +void +initerrmailers() +{ + if (discardmailer.m_name == NULL) + { + /* initialize the discard mailer */ + discardmailer.m_name = "*discard*"; + discardmailer.m_mailer = "DISCARD"; + discardmailer.m_argv = discardargv; + } + if (errormailer.m_name == NULL) + { + /* initialize the bogus mailer */ + errormailer.m_name = "*error*"; + errormailer.m_mailer = "ERROR"; + errormailer.m_argv = errorargv; + } +} + /* +** 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' +*/ + +static 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 /* EX_CONFIG */ + { NULL, EX_UNAVAILABLE } +}; + + +static 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 char ubuf[MAXNAME + 2]; + + if (tTd(24, 5)) + { + dprintf("buildaddr, flags=%x, tv=", flags); + printav(tv); + } + + if (a == NULL) + a = (ADDRESS *) xalloc(sizeof *a); + memset((char *) a, '\0', sizeof *a); + hbuf[0] = '\0'; + + /* set up default error return flags */ + a->q_flags |= DefaultNotify; + + /* figure out what net/mailer to use */ + if (*tv == NULL || (**tv & 0377) != CANONNET) + { + syserr("554 5.3.5 buildaddr: no mailer in parsed address"); +badaddr: + if (ExitStat == EX_TEMPFAIL) + a->q_state = QS_QUEUEUP; + else + { + a->q_state = QS_BADADDR; + a->q_mailer = &errormailer; + } + return a; + } + mname = *++tv; + + /* extract host and user portions */ + if (*++tv != NULL && (**tv & 0377) == CANONHOST) + hostp = ++tv; + else + hostp = NULL; + while (*tv != NULL && (**tv & 0377) != CANONUSER) + tv++; + if (*tv == NULL) + { + syserr("554 5.3.5 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) + { + /* Set up triplet for use by -bv */ + a->q_mailer = &errormailer; + a->q_user = newstr(ubuf); + + if (hostp != NULL) + { + register struct errcodes *ep; + + a->q_host = newstr(hbuf); + 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 + { + a->q_host = NULL; + setstat(EX_UNAVAILABLE); + } + stripquotes(ubuf); + if (ISSMTPCODE(ubuf) && ubuf[3] == ' ') + { + char fmt[16]; + int off; + + if ((off = isenhsc(ubuf + 4, ' ')) > 0) + { + ubuf[off + 4] = '\0'; + off += 5; + } + else + { + off = 4; + ubuf[3] = '\0'; + } + (void) snprintf(fmt, sizeof fmt, "%s %%s", ubuf); + if (off > 4) + usrerr(fmt, ubuf + off); + else if (isenhsc(hbuf, '\0') > 0) + usrerrenh(hbuf, fmt, ubuf + off); + else + usrerr(fmt, ubuf + off); + /* XXX ubuf[off - 1] = ' '; */ + } + else + { + usrerr("553 5.3.0 %s", ubuf); + } + goto badaddr; + } + + for (mp = Mailer; (m = *mp++) != NULL; ) + { + if (strcasecmp(m->m_name, mname) == 0) + break; + } + if (m == NULL) + { + syserr("554 5.3.5 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 5.3.5 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 _FFR_ADDR_TYPE + /* + ** Note, change the 9 to a 10 before removing #if FFR check + ** in a future version. + */ + + if (ConfigLevel >= 9 || + !bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) +#else /* _FFR_ADDR_TYPE */ + if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) +#endif /* _FFR_ADDR_TYPE */ + { + /* 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 = newstr(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)) + { + dprintf("buildaddr => "); + printaddr(a, FALSE); + } + return a; +} + /* +** CATADDR -- concatenate pieces of addresses (putting in 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 (sz <= 0) + return; + + if (spacesub == '\0') + spacesub = SpaceSub; + + if (pvp == NULL) + { + *buf = '\0'; + return; + } + p = buf; + sz -= 2; + while (*pvp != NULL && (i = strlen(*pvp)) < sz - 1) + { + natomtok = (TokTypeTab[**pvp & 0xff] == ATM); + if (oatomtok && natomtok) + { + *p++ = spacesub; + --sz; + } + (void) strlcpy(p, *pvp, sz); + oatomtok = natomtok; + p += i; + sz -= i; + 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; +}; + +static struct qflags AddressFlags[] = +{ + { "QGOODUID", QGOODUID }, + { "QPRIMARY", QPRIMARY }, + { "QNOTREMOTE", QNOTREMOTE }, + { "QSELFREF", QSELFREF }, + { "QBOGUSSHELL", QBOGUSSHELL }, + { "QUNSAFEADDR", QUNSAFEADDR }, + { "QPINGONSUCCESS", QPINGONSUCCESS }, + { "QPINGONFAILURE", QPINGONFAILURE }, + { "QPINGONDELAY", QPINGONDELAY }, + { "QHASNOTIFY", QHASNOTIFY }, + { "QRELAYED", QRELAYED }, + { "QEXPANDED", QEXPANDED }, + { "QDELIVERED", QDELIVERED }, + { "QDELAYED", QDELAYED }, + { "QTHISPASS", QTHISPASS }, + { "QRCPTOK", QRCPTOK }, + { 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("%lx=", (u_long) 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 ? "" : a->q_paddr, + m->m_mno, m->m_name, + a->q_host == NULL ? "" : a->q_host); + printf("\tuser `%s', ruser `%s'\n", + a->q_user, + a->q_ruser == NULL ? "" : a->q_ruser); + printf("\tstate="); + switch (a->q_state) + { + case QS_OK: + printf("OK"); + break; + + case QS_DONTSEND: + printf("DONTSEND"); + break; + + case QS_BADADDR: + printf("BADADDR"); + break; + + case QS_QUEUEUP: + printf("QUEUEUP"); + break; + + case QS_SENT: + printf("SENT"); + break; + + case QS_VERIFIED: + printf("VERIFIED"); + break; + + case QS_EXPANDED: + printf("EXPANDED"); + break; + + case QS_SENDER: + printf("SENDER"); + break; + + case QS_CLONED: + printf("CLONED"); + break; + + case QS_DISCARDED: + printf("DISCARDED"); + break; + + case QS_REPLACED: + printf("REPLACED"); + break; + + case QS_REMOVED: + printf("REMOVED"); + break; + + case QS_DUPLICATE: + printf("DUPLICATE"); + break; + + case QS_INCLUDED: + printf("INCLUDED"); + break; + + default: + printf("%d", a->q_state); + break; + } + printf(", next=%lx, alias %lx, uid %d, gid %d\n", + (u_long) a->q_next, (u_long) a->q_alias, + (int) a->q_uid, (int) 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, status=%s\n", + a->q_orcpt == NULL ? "(none)" : a->q_orcpt, + a->q_statmta == NULL ? "(none)" : a->q_statmta, + a->q_status == NULL ? "(none)" : a->q_status); + printf("\trstatus=\"%s\"\n", + a->q_rstatus == NULL ? "(none)" : a->q_rstatus); + printf("\tspecificity=%d, statdate=%s\n", + a->q_specificity, + a->q_statdate == 0 ? "(none)" : ctime(&a->q_statdate)); + + 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]; +#if _FFR_ADDR_TYPE + char addrtype[4]; +#endif /* _FFR_ADDR_TYPE */ + + if (tTd(12, 1)) + dprintf("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; +#if _FFR_ADDR_TYPE + addrtype[2] = 's'; +#endif /* _FFR_ADDR_TYPE */ + } + else + { + rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset + : m->m_re_rwset; +#if _FFR_ADDR_TYPE + addrtype[2] = 'r'; +#endif /* _FFR_ADDR_TYPE */ + } + if (rwset < 0) + return name; +#if _FFR_ADDR_TYPE + addrtype[1] = ' '; + addrtype[3] = '\0'; + addrtype[0] = bitset(RF_HEADERADDR, flags) ? 'h' : 'e'; + define(macid("{addr_type}", NULL), addrtype, e); +#endif /* _FFR_ADDR_TYPE */ + + /* + ** 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; + int l = MAXATOM; /* size of buffer for pvp */ + + /* see if there is an "@domain" in the current name */ + while (*pxp != NULL && strcmp(*pxp, "@") != 0) + { + pxp++; + --l; + } + if (*pxp == NULL) + { + /* no.... append the "@domain" from the sender */ + register char **qxq = e->e_fromdomain; + + while ((*pxp++ = *qxq++) != NULL) + { + if (--l <= 0) + { + *--pxp = NULL; + usrerr("553 5.1.0 remotename: too many tokens"); + *pstat = EX_UNAVAILABLE; + break; + } + } + 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 */ + 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)) + dprintf("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. +*/ + +#define Q_COPYFLAGS (QPRIMARY|QBOGUSSHELL|QUNSAFEADDR|\ + Q_PINGFLAGS|QHASNOTIFY|\ + QRELAYED|QEXPANDED|QDELIVERED|QDELAYED) + +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)) + { + dprintf("maplocaluser: "); + printaddr(a, FALSE); + } + pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL); + if (pvp == NULL) + { + if (tTd(29, 9)) + dprintf("maplocaluser: cannot prescan %s\n", + a->q_user); + return; + } + + define('h', a->q_host, e); + define('u', a->q_user, e); + define('z', a->q_home, e); + +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e r", e); +#endif /* _FFR_ADDR_TYPE */ + if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL) + { + if (tTd(29, 9)) + dprintf("maplocaluser: rewrite tempfail\n"); + a->q_state = QS_QUEUEUP; + a->q_status = "4.4.3"; + return; + } + if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET) + { + if (tTd(29, 9)) + dprintf("maplocaluser: doesn't resolve\n"); + return; + } + + /* if non-null, mailer destination specified -- has it changed? */ + a1 = buildaddr(pvp, NULL, 0, e); + if (a1 == NULL || sameaddr(a, a1)) + { + if (tTd(29, 9)) + dprintf("maplocaluser: address unchanged\n"); + if (a1 != NULL) + free(a1); + return; + } + + /* make new address take on flags and print attributes of old */ + a1->q_flags &= ~Q_COPYFLAGS; + a1->q_flags |= a->q_flags & Q_COPYFLAGS; + a1->q_paddr = newstr(a->q_paddr); + a1->q_orcpt = a->q_orcpt; + + /* mark old address as dead; insert new address */ + a->q_state = QS_REPLACED; + if (tTd(29, 5)) + { + dprintf("maplocaluser: QS_REPLACED "); + printaddr(a, FALSE); + } + a1->q_alias = a; + allocaddr(a1, RF_COPYALL, newstr(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; + + /* there is no check whether there is really an argument */ + 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 'D': + map->map_mflags |= MF_DEFER; + break; + + case 'S': + case 's': + map->map_spacesub = *++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. +*/ + +/* ARGSUSED2 */ +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_spacesub; + + 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 ' ': + case '\t': + 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 map_rewrite(map, name, strlen(name), NULL); +} + /* +** RSCHECK -- check string(s) for validity using rewriting sets +** +** Parameters: +** rwset -- the rewriting set to use. +** p1 -- the first string to check. +** p2 -- the second string to check -- may be null. +** e -- the current envelope. +** rmcomm -- remove comments? +** cnt -- count rejections (statistics)? +** +** Returns: +** EX_OK -- if the rwset doesn't resolve to $#error +** else -- the failure status (message printed) +*/ + +int +rscheck(rwset, p1, p2, e, rmcomm, cnt) + char *rwset; + char *p1; + char *p2; + ENVELOPE *e; + bool rmcomm, cnt; +{ + char *buf; + int bufsize; + int saveexitstat; + int rstat = EX_OK; + char **pvp; + int rsno; + bool discard = FALSE; + auto ADDRESS a1; + bool saveQuickAbort = QuickAbort; + bool saveSuprErrs = SuprErrs; + char buf0[MAXLINE]; + char pvpbuf[PSBUFSIZE]; + extern char MsgBuf[]; + + if (tTd(48, 2)) + dprintf("rscheck(%s, %s, %s)\n", rwset, p1, + p2 == NULL ? "(NULL)" : p2); + + rsno = strtorwset(rwset, NULL, ST_FIND); + if (rsno < 0) + return EX_OK; + + if (p2 != NULL) + { + bufsize = strlen(p1) + strlen(p2) + 2; + if (bufsize > sizeof buf0) + buf = xalloc(bufsize); + else + { + buf = buf0; + bufsize = sizeof buf0; + } + (void) snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2); + } + else + { + bufsize = strlen(p1) + 1; + if (bufsize > sizeof buf0) + buf = xalloc(bufsize); + else + { + buf = buf0; + bufsize = sizeof buf0; + } + (void) snprintf(buf, bufsize, "%s", p1); + } + SuprErrs = TRUE; + QuickAbort = FALSE; + pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL, + rmcomm ? NULL : TokTypeNoC); + SuprErrs = saveSuprErrs; + if (pvp == NULL) + { + if (tTd(48, 2)) + dprintf("rscheck: cannot prescan input\n"); +/* + syserr("rscheck: cannot prescan input: \"%s\"", + shortenstring(buf, MAXSHORTSTR)); + rstat = EX_DATAERR; +*/ + goto finis; + } + (void) rewrite(pvp, rsno, 0, e); + if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET || + pvp[1] == NULL || (strcmp(pvp[1], "error") != 0 && + strcmp(pvp[1], "discard") != 0)) + { + goto finis; + } + + if (strcmp(pvp[1], "discard") == 0) + { + if (tTd(48, 2)) + dprintf("rscheck: discard mailer selected\n"); + e->e_flags |= EF_DISCARD; + discard = TRUE; + } + else + { + int savelogusrerrs = LogUsrErrs; + static bool logged = FALSE; + + /* got an error -- process it */ + saveexitstat = ExitStat; + LogUsrErrs = FALSE; + (void) buildaddr(pvp, &a1, 0, e); + LogUsrErrs = savelogusrerrs; + rstat = ExitStat; + ExitStat = saveexitstat; + if (!logged) + { + if (cnt) + markstats(e, &a1, TRUE); + logged = TRUE; + } + } + + if (LogLevel >= 4) + { + char *relay; + char *p; + char lbuf[MAXLINE]; + + p = lbuf; + if (p2 != NULL) + { + snprintf(p, SPACELEFT(lbuf, p), + ", arg2=%s", + p2); + p += strlen(p); + } + if ((relay = macvalue('_', e)) != NULL) + { + snprintf(p, SPACELEFT(lbuf, p), + ", relay=%s", relay); + p += strlen(p); + } + *p = '\0'; + if (discard) + sm_syslog(LOG_NOTICE, e->e_id, + "ruleset=%s, arg1=%s%s, discard", + rwset, p1, lbuf); + else + sm_syslog(LOG_NOTICE, e->e_id, + "ruleset=%s, arg1=%s%s, reject=%s", + rwset, p1, lbuf, MsgBuf); + } + + finis: + /* clean up */ + QuickAbort = saveQuickAbort; + setstat(rstat); + if (buf != buf0) + free(buf); + + if (rstat != EX_OK && QuickAbort) + longjmp(TopFrame, 2); + return rstat; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/queue.c b/gnu/usr.sbin/sendmail/sendmail/queue.c new file mode 100644 index 00000000000..7581ec938b7 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/queue.c @@ -0,0 +1,3320 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# if QUEUE +static char id[] = "@(#)$Sendmail: queue.c,v 8.342 2000/02/27 01:27:44 gshapiro Exp $ (with queueing)"; +# else /* QUEUE */ +static char id[] = "@(#)$Sendmail: queue.c,v 8.342 2000/02/27 01:27:44 gshapiro Exp $ (without queueing)"; +# endif /* QUEUE */ +#endif /* ! lint */ + +#include + +#if QUEUE + +# if _FFR_QUEUEDELAY +# define QF_VERSION 5 /* version number of this queue format */ +static time_t queuedelay __P((ENVELOPE *)); +# else /* _FFR_QUEUEDELAY */ +# define QF_VERSION 4 /* version number of this queue format */ +# define queuedelay(e) MinQueueAge +# endif /* _FFR_QUEUEDELAY */ + +/* +** 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; + +static WORK *WorkQ; /* queue of things to be done */ + +static void grow_wlist __P((int)); +static int orderq __P((int, bool)); +static void printctladdr __P((ADDRESS *, FILE *)); +static int print_single_queue __P((int)); +static bool readqf __P((ENVELOPE *)); +static void runqueueevent __P((void)); +static int run_single_queue __P((int, bool, bool)); +static char *strrev __P((char *)); +static ADDRESS *setctluser __P((char *, int)); +static int workcmpf0(); +static int workcmpf1(); +static int workcmpf2(); +static int workcmpf3(); +static int workcmpf4(); + + /* +** 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 tfd = -1; + int i; + bool newid; + register char *p; + MAILER nullmailer; + MCI mcibuf; + char tf[MAXPATHLEN]; + char buf[MAXLINE]; + + /* + ** 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 */ + (void) strlcpy(tf, queuename(e, 't'), sizeof tf); + 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++) + { +#if _FFR_QUEUE_FILE_MODE + { + MODE_T oldumask; + + if (bitset(S_IWGRP, QueueFileMode)) + oldumask = umask(002); + tfd = open(tf, O_CREAT|O_WRONLY|O_EXCL, + QueueFileMode); + if (bitset(S_IWGRP, QueueFileMode)) + (void) umask(oldumask); + } +#else /* _FFR_QUEUE_FILE_MODE */ + tfd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode); +#endif /* _FFR_QUEUE_FILE_MODE */ + + if (tfd < 0) + { + if (errno != EEXIST) + break; + if (LogLevel > 0 && (i % 32) == 0) + sm_syslog(LOG_ALERT, e->e_id, + "queueup: cannot create %s, uid=%d: %s", + tf, geteuid(), errstring(errno)); + } + else + { + if (lockfile(tfd, tf, NULL, LOCK_EX|LOCK_NB)) + break; + else if (LogLevel > 0 && (i % 32) == 0) + sm_syslog(LOG_ALERT, e->e_id, + "queueup: cannot lock %s: %s", + tf, errstring(errno)); + (void) close(tfd); + } + + if ((i % 32) == 31) + { + /* save the old temp file away */ + (void) rename(tf, queuename(e, 'T')); + } + else + (void) sleep(i % 32); + } + if (tfd < 0 || (tfp = fdopen(tfd, "w")) == NULL) + { + int save_errno = errno; + + printopenfds(TRUE); + errno = save_errno; + syserr("!queueup: cannot create queue temp file %s, uid=%d", + tf, geteuid()); + } + } + + if (tTd(40, 1)) + dprintf("\n>>>>> queueing %s/qf%s%s >>>>>\n", + qid_printqueue(e->e_queuedir), e->e_id, + newid ? " (new id)" : ""); + if (tTd(40, 3)) + { + dprintf(" e_flags="); + printenvflags(e); + } + if (tTd(40, 32)) + { + dprintf(" sendq="); + printaddr(e->e_sendqueue, TRUE); + } + if (tTd(40, 9)) + { + dprintf(" tfp="); + dumpfd(fileno(tfp), TRUE, FALSE); + dprintf(" lockfp="); + if (e->e_lockfp == NULL) + dprintf("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)) + { + if (e->e_dfp != NULL && bfcommit(e->e_dfp) < 0) + syserr("!queueup: cannot commit data file %s, uid=%d", + queuename(e, 'd'), geteuid()); + } + else + { + int dfd; + register FILE *dfp = NULL; + char dfname[MAXPATHLEN]; + struct stat stbuf; + + if (e->e_dfp != NULL && bftest(e->e_dfp)) + syserr("committing over bf file"); + + (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); +#if _FFR_QUEUE_FILE_MODE + { + MODE_T oldumask; + + if (bitset(S_IWGRP, QueueFileMode)) + oldumask = umask(002); + dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, + QueueFileMode); + if (bitset(S_IWGRP, QueueFileMode)) + (void) umask(oldumask); + } +#else /* _FFR_QUEUE_FILE_MODE */ + dfd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode); +#endif /* _FFR_QUEUE_FILE_MODE */ + if (dfd < 0 || (dfp = fdopen(dfd, "w")) == NULL) + syserr("!queueup: cannot create data temp file %s, uid=%d", + dfname, geteuid()); + if (fstat(dfd, &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; + memset(&mcibuf, '\0', sizeof mcibuf); + mcibuf.mci_out = dfp; + mcibuf.mci_mailer = FileMailer; + (*e->e_putbody)(&mcibuf, e, NULL); + if (fclose(dfp) < 0) + syserr("!queueup: cannot save data temp file %s, uid=%d", + dfname, geteuid()); + 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", (long) e->e_ctime); + + /* output last delivery time */ +# if _FFR_QUEUEDELAY + fprintf(tfp, "K%ld\n", (long) e->e_dtime); + fprintf(tfp, "G%d\n", e->e_queuealg); + fprintf(tfp, "Y%ld\n", (long) e->e_queuedelay); + if (tTd(40, 64)) + sm_syslog(LOG_INFO, e->e_id, + "queue alg: %d delay %ld next: %ld (now: %ld)\n", + e->e_queuealg, e->e_queuedelay, e->e_dtime, curtime()); +# else /* _FFR_QUEUEDELAY */ + fprintf(tfp, "K%ld\n", (long) e->e_dtime); +# endif /* _FFR_QUEUEDELAY */ + + /* 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) + { + /*CONSTCOND*/ + if (sizeof e->e_dfino > sizeof(long)) + fprintf(tfp, "I%ld/%ld/%s\n", + (long) major(e->e_dfdev), + (long) minor(e->e_dfdev), + quad_to_string(e->e_dfino)); + else + fprintf(tfp, "I%ld/%ld/%lu\n", + (long) major(e->e_dfdev), + (long) minor(e->e_dfdev), + (unsigned long) e->e_dfino); + } + + /* output body type */ + if (e->e_bodytype != NULL) + fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE)); + +# if _FFR_SAVE_CHARSET + if (e->e_charset != NULL) + fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE)); +# endif /* _FFR_SAVE_CHARSET */ + + /* 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'; + if (bitset(EF_DELETE_BCC, e->e_flags)) + *p++ = 'b'; + if (bitset(EF_RET_PARAM, e->e_flags)) + *p++ = 'd'; + if (bitset(EF_NO_BODY_RETN, e->e_flags)) + *p++ = 'n'; + *p++ = '\0'; + if (buf[0] != '\0') + fprintf(tfp, "F%s\n", buf); + + /* save $={persistentMacros} macro values */ + queueup_macros(macid("{persistentMacros}", NULL), tfp, e); + + /* 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 AUTH= parameter */ + if (e->e_auth_param != NULL) + fprintf(tfp, "A%s\n", denlstring(e->e_auth_param, + TRUE, FALSE)); + + /* output list of recipient addresses */ + printctladdr(NULL, NULL); + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (!QS_IS_UNDELIVERED(q->q_state)) + continue; + + printctladdr(q, tfp); + if (q->q_orcpt != NULL) + fprintf(tfp, "Q%s\n", + denlstring(q->q_orcpt, TRUE, FALSE)); + (void) putc('R', tfp); + if (bitset(QPRIMARY, q->q_flags)) + (void) putc('P', tfp); + if (bitset(QHASNOTIFY, q->q_flags)) + (void) putc('N', tfp); + if (bitset(QPINGONSUCCESS, q->q_flags)) + (void) putc('S', tfp); + if (bitset(QPINGONFAILURE, q->q_flags)) + (void) putc('F', tfp); + if (bitset(QPINGONDELAY, q->q_flags)) + (void) putc('D', tfp); + (void) putc(':', tfp); + (void) 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, q->q_status, + "queued", NULL, (time_t) 0, e); + e->e_to = NULL; + } + if (tTd(40, 1)) + { + dprintf("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. + */ + + memset((char *) &nullmailer, '\0', sizeof nullmailer); + nullmailer.m_re_rwset = nullmailer.m_rh_rwset = + nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1; + nullmailer.m_eol = "\n"; + memset(&mcibuf, '\0', 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) + { + if (h->h_value == NULL) + 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?"); + + /* output conditional macro if present */ + if (h->h_macro != '\0') + { + if (bitset(0200, h->h_macro)) + fprintf(tfp, "${%s}", + macname(h->h_macro & 0377)); + else + fprintf(tfp, "$%c", h->h_macro); + } + else if (!bitzerop(h->h_mflags) && + bitset(H_CHECK|H_ACHECK, h->h_flags)) + { + int j; + + /* if conditional, output the set of conditions */ + 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) && + !bitset(H_BINDLATE, h->h_flags)) + { + fprintf(tfp, "%s: %s\n", + h->h_field, + denlstring(buf, FALSE, TRUE)); + } + else if (bitset(H_FROM|H_RCPT, h->h_flags) && + !bitset(H_BINDLATE, 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, + denlstring(h->h_value, FALSE, TRUE)); + } + } + + /* + ** Clean up. + ** + ** Write a terminator record -- this is to prevent + ** scurrilous crackers from appending any data. + */ + + fprintf(tfp, ".\n"); + + if (fflush(tfp) < 0 || + (SuperSafe && 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()); + + /* + ** fsync() after renaming to make sure + ** metadata is written to disk on + ** filesystems in which renames are + ** not guaranteed such as softupdates. + */ + + if (tfd >= 0 && SuperSafe && fsync(tfd) < 0) + syserr("!queueup: cannot fsync queue temp file %s", + tf); + + /* close and unlock old (locked) qf */ + if (e->e_lockfp != NULL) + (void) fclose(e->e_lockfp); + e->e_lockfp = tfp; + } + else + qf = tf; + errno = 0; + e->e_flags |= EF_INQUEUE; + + /* save log info */ + if (LogLevel > 79) + sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf); + + if (tTd(40, 1)) + dprintf("<<<<< done queueing %s <<<<<\n\n", e->e_id); + return; +} + +static void +printctladdr(a, tfp) + register ADDRESS *a; + FILE *tfp; +{ + char *user; + register ADDRESS *q; + uid_t uid; + gid_t gid; + static ADDRESS *lastctladdr = NULL; + 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) + { + user = NULL; + uid = 0; + gid = 0; + } + else + { + user = q->q_ruser != NULL ? q->q_ruser : q->q_user; + uid = q->q_uid; + gid = q->q_gid; + } + 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 || user == NULL || user[0] == '\0') + fprintf(tfp, "C"); + else + fprintf(tfp, "C%s:%ld:%ld", + denlstring(user, TRUE, FALSE), (long) uid, (long) gid); + fprintf(tfp, ":%s\n", 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. +** FALSE can be ignored if we have multiple queues. +** verbose -- if TRUE, print out status information. +** +** Returns: +** TRUE if the queue run successfully began. +** +** Side Effects: +** runs things in the mail queue. +*/ + +static ENVELOPE QueueEnvelope; /* the queue run envelope */ +int NumQueues = 0; /* number of queues */ +static time_t LastQueueTime = 0; /* last time a queue ID assigned */ +static pid_t LastQueuePid = -1; /* last PID which had a queue ID */ + +struct qpaths_s +{ + char *qp_name; /* name of queue dir */ + short qp_subdirs; /* use subdirs? */ +}; + +typedef struct qpaths_s QPATHS; + +/* values for qp_supdirs */ +#define QP_NOSUB 0x0000 /* No subdirectories */ +#define QP_SUBDF 0x0001 /* "df" subdirectory */ +#define QP_SUBQF 0x0002 /* "qf" subdirectory */ +#define QP_SUBXF 0x0004 /* "xf" subdirectory */ + +static QPATHS *QPaths = NULL; /* list of queue directories */ + +bool +runqueue(forkflag, verbose) + bool forkflag; + bool verbose; +{ + int i; + bool ret = TRUE; + static int curnum = 0; + + if (!forkflag && NumQueues > 1 && !verbose) + forkflag = TRUE; + + for (i = 0; i < NumQueues; i++) + { + /* + ** Pick up where we left off, in case we + ** used up all the children last time + ** without finishing. + */ + + ret = run_single_queue(curnum, forkflag, verbose); + + /* + ** Failure means a message was printed for ETRN + ** and subsequent queues are likely to fail as well. + */ + + if (!ret) + break; + + if (++curnum >= NumQueues) + curnum = 0; + } + if (QueueIntvl != 0) + (void) setevent(QueueIntvl, runqueueevent, 0); + return ret; +} + /* +** RUN_SINGLE_QUEUE -- run the jobs in a single queue. +** +** Gets the stuff out of the queue in some presumably logical +** order and processes them. +** +** Parameters: +** queuedir -- queue to process +** 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. +** verbose -- if TRUE, print out status information. +** +** Returns: +** TRUE if the queue run successfully began. +** +** Side Effects: +** runs things in the mail queue. +*/ + +static bool +run_single_queue(queuedir, forkflag, verbose) + int queuedir; + bool forkflag; + bool verbose; +{ + register ENVELOPE *e; + int njobs; + int sequenceno = 0; + time_t current_la_time; + extern ENVELOPE BlankEnvelope; + + DoQueueRun = FALSE; + + /* + ** If no work will ever be selected, don't even bother reading + ** the queue. + */ + + CurrentLA = sm_getla(NULL); /* get load average */ + current_la_time = curtime(); + + if (shouldqueue(WkRecipFact, current_la_time)) + { + char *msg = "Skipping queue run -- load average too high"; + + if (verbose) + message("458 %s\n", msg); + if (LogLevel > 8) + sm_syslog(LOG_INFO, NOQID, + "runqueue: %s", + msg); + return FALSE; + } + + /* + ** See if we already have too many children. + */ + + if (forkflag && QueueIntvl != 0 && + MaxChildren > 0 && CurChildren >= MaxChildren) + { + char *msg = "Skipping queue run -- too many children"; + + if (verbose) + message("458 %s (%d)\n", msg, CurChildren); + if (LogLevel > 8) + sm_syslog(LOG_INFO, NOQID, + "runqueue: %s (%d)", + msg, CurChildren); + return FALSE; + } + + /* + ** See if we want to go off and do other useful work. + */ + + if (forkflag) + { + pid_t pid; + + (void) blocksignal(SIGCHLD); + (void) setsignal(SIGCHLD, reapchild); + + pid = dofork(); + if (pid == -1) + { + const char *msg = "Skipping queue run -- fork() failed"; + const char *err = errstring(errno); + + if (verbose) + message("458 %s: %s\n", msg, err); + if (LogLevel > 8) + sm_syslog(LOG_INFO, NOQID, + "runqueue: %s: %s", + msg, err); + (void) releasesignal(SIGCHLD); + return FALSE; + } + if (pid != 0) + { + /* parent -- pick up intermediate zombie */ + (void) blocksignal(SIGALRM); + proc_list_add(pid, "Queue runner", PROC_QUEUE); + (void) releasesignal(SIGALRM); + (void) releasesignal(SIGCHLD); + return TRUE; + } + /* child -- clean up signals */ + clrcontrol(); + proc_list_clear(); + + /* Add parent process as first child item */ + proc_list_add(getpid(), "Queue runner child process", + PROC_QUEUE_CHILD); + (void) releasesignal(SIGCHLD); + (void) setsignal(SIGCHLD, SIG_DFL); + (void) setsignal(SIGHUP, intsig); + } + + sm_setproctitle(TRUE, CurEnv, "running queue: %s", + qid_printqueue(queuedir)); + + if (LogLevel > 69 || tTd(63, 99)) + sm_syslog(LOG_DEBUG, NOQID, + "runqueue %s, pid=%d, forkflag=%d", + qid_printqueue(queuedir), getpid(), forkflag); + + /* + ** Release any resources used by the daemon code. + */ + +# if DAEMON + clrdaemon(); +# endif /* DAEMON */ + + /* force it to run expensive jobs */ + NoConnect = FALSE; + + /* drop privileges */ + if (geteuid() == (uid_t) 0) + (void) drop_privileges(FALSE); + + /* + ** Create ourselves an envelope + */ + + CurEnv = &QueueEnvelope; + e = newenvelope(&QueueEnvelope, CurEnv); + e->e_flags = BlankEnvelope.e_flags; + + /* make sure we have disconnected from parent */ + if (forkflag) + { + disconnect(1, e); + QuickAbort = FALSE; + } + + /* + ** If we are running part of the queue, always ignore stored + ** host status. + */ + + if (QueueLimitId != NULL || QueueLimitSender != NULL || + QueueLimitRecipient != NULL) + { + IgnoreHostStatus = TRUE; + MinQueueAge = 0; + } + + /* + ** 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(queuedir, FALSE); + + /* process them once at a time */ + while (WorkQ != NULL) + { + WORK *w = WorkQ; + + WorkQ = WorkQ->w_next; + e->e_to = NULL; + + /* + ** Ignore jobs that are too expensive for the moment. + ** + ** Get new load average every 30 seconds. + */ + + if (current_la_time < curtime() - 30) + { + CurrentLA = sm_getla(e); + current_la_time = curtime(); + } + if (shouldqueue(WkRecipFact, current_la_time)) + { + char *msg = "Aborting queue run: load average too high"; + + if (Verbose) + message("%s", msg); + if (LogLevel > 8) + sm_syslog(LOG_INFO, NOQID, + "runqueue: %s", + msg); + break; + } + sequenceno++; + if (shouldqueue(w->w_pri, w->w_ctime)) + { + if (Verbose) + message(""); + if (QueueSortOrder == QSO_BYPRIORITY) + { + if (Verbose) + message("Skipping %s/%s (sequence %d of %d) and flushing rest of queue", + qid_printqueue(queuedir), + w->w_name + 2, + sequenceno, + njobs); + if (LogLevel > 8) + sm_syslog(LOG_INFO, NOQID, + "runqueue: Flushing queue from %s/%s (pri %ld, LA %d, %d of %d)", + qid_printqueue(queuedir), + w->w_name + 2, + w->w_pri, + CurrentLA, + sequenceno, + njobs); + break; + } + else if (Verbose) + message("Skipping %s/%s (sequence %d of %d)", + qid_printqueue(queuedir), + w->w_name + 2, + sequenceno, njobs); + } + else + { + pid_t pid; + + if (Verbose) + { + message(""); + message("Running %s/%s (sequence %d of %d)", + qid_printqueue(queuedir), + w->w_name + 2, + sequenceno, njobs); + } + if (tTd(63, 100)) + sm_syslog(LOG_DEBUG, NOQID, + "runqueue %s dowork(%s)", + qid_printqueue(queuedir), + w->w_name + 2); + + pid = dowork(queuedir, 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; + if (forkflag) + finis(TRUE, ExitStat); + /* NOTREACHED */ + return TRUE; +} + +/* +** RUNQUEUEEVENT -- stub for use in setevent +*/ + +static void +runqueueevent() +{ + DoQueueRun = TRUE; +} + /* +** ORDERQ -- order the work queue. +** +** Parameters: +** queuedir -- the index of the queue directory. +** 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; + +static int +orderq(queuedir, doall) + int queuedir; + bool doall; +{ + register struct dirent *d; + register WORK *w; + register char *p; + DIR *f; + register int i; + int wn = -1; + int wc; + QUEUE_CHAR *check; + char qd[MAXPATHLEN]; + char qf[MAXPATHLEN]; + + if (queuedir == NOQDIR) + (void) strlcpy(qd, ".", sizeof qd); + else + (void) snprintf(qd, sizeof qd, "%s%s", + QPaths[queuedir].qp_name, + (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); + + if (tTd(41, 1)) + { + dprintf("orderq:\n"); + + check = QueueLimitId; + while (check != NULL) + { + dprintf("\tQueueLimitId = %s\n", + check->queue_match); + check = check->queue_next; + } + + check = QueueLimitSender; + while (check != NULL) + { + dprintf("\tQueueLimitSender = %s\n", + check->queue_match); + check = check->queue_next; + } + + check = QueueLimitRecipient; + while (check != NULL) + { + dprintf("\tQueueLimitRecipient = %s\n", + check->queue_match); + check = check->queue_next; + } + } + + /* 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(qd); + if (f == NULL) + { + syserr("orderq: cannot open \"%s\"", qid_printqueue(queuedir)); + return 0; + } + + /* + ** Read the work directory. + */ + + while ((d = readdir(f)) != NULL) + { + FILE *cf; + int qfver = 0; + char lbuf[MAXNAME + 1]; + struct stat sbuf; + + if (tTd(41, 50)) + dprintf("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 (strlen(d->d_name) >= MAXQFNAME) + { + if (Verbose) + printf("orderq: %s too long, %d max characters\n", + d->d_name, MAXQFNAME); + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "orderq: %s too long, %d max characters", + d->d_name, MAXQFNAME); + continue; + } + + check = QueueLimitId; + while (check != NULL) + { + if (strcontainedin(check->queue_match, d->d_name)) + break; + else + check = check->queue_next; + } + if (QueueLimitId != NULL && check == NULL) + continue; + + /* grow work list if necessary */ + if (++wn >= MaxQueueRun && MaxQueueRun > 0) + { + if (wn == MaxQueueRun && LogLevel > 0) + sm_syslog(LOG_WARNING, NOQID, + "WorkList for %s maxed out at %d", + qid_printqueue(queuedir), + MaxQueueRun); + continue; + } + if (wn >= WorkListSize) + { + grow_wlist(queuedir); + if (wn >= WorkListSize) + continue; + } + w = &WorkList[wn]; + + (void) snprintf(qf, sizeof qf, "%s/%s", qd, d->d_name); + if (stat(qf, &sbuf) < 0) + { + if (errno != ENOENT) + sm_syslog(LOG_INFO, NOQID, + "orderq: can't stat %s/%s", + qid_printqueue(queuedir), d->d_name); + wn--; + continue; + } + if (!bitset(S_IFREG, sbuf.st_mode)) + { + /* Yikes! Skip it or we will hang on open! */ + syserr("orderq: %s/%s is not a regular file", + qid_printqueue(queuedir), d->d_name); + wn--; + continue; + } + + /* avoid work if possible */ + if (QueueSortOrder == QSO_BYFILENAME) + { + w->w_name = newstr(d->d_name); + w->w_host = NULL; + w->w_lock = w->w_tooyoung = FALSE; + w->w_pri = 0; + w->w_ctime = 0; + continue; + } + + /* open control file */ + cf = fopen(qf, "r"); + if (cf == NULL) + { + /* this may be some random person sending hir msgs */ + /* syserr("orderq: cannot open %s", cbuf); */ + if (tTd(41, 2)) + dprintf("orderq: cannot open %s: %s\n", + d->d_name, errstring(errno)); + errno = 0; + wn--; + continue; + } + 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 == QSO_BYHOST || QueueLimitRecipient != NULL) + i |= NEED_R; + while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL) + { + int c; + time_t age; + + p = strchr(lbuf, '\n'); + if (p != NULL) + *p = '\0'; + else + { + /* flush rest of overly long line */ + while ((c = getc(cf)) != EOF && c != '\n') + continue; + } + + switch (lbuf[0]) + { + case 'V': + qfver = atoi(&lbuf[1]); + break; + + 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 = strrev(&p[1]); + makelower(w->w_host); + } + if (QueueLimitRecipient == NULL) + { + i &= ~NEED_R; + break; + } + if (qfver > 0) + { + p = strchr(&lbuf[1], ':'); + if (p == NULL) + p = &lbuf[1]; + } + else + p = &lbuf[1]; + check = QueueLimitRecipient; + while (check != NULL) + { + if (strcontainedin(check->queue_match, + p)) + break; + else + check = check->queue_next; + } + if (check != NULL) + i &= ~NEED_R; + break; + + case 'S': + check = QueueLimitSender; + while (check != NULL) + { + if (strcontainedin(check->queue_match, + &lbuf[1])) + break; + else + check = check->queue_next; + } + if (check != NULL) + i &= ~NEED_S; + break; + + case 'K': + age = curtime() - (time_t) atol(&lbuf[1]); + if (age >= 0 && MinQueueAge > 0 && + age < MinQueueAge) + w->w_tooyoung = TRUE; + break; + + case 'N': + if (atol(&lbuf[1]) == 0) + w->w_tooyoung = FALSE; + break; + +# if _FFR_QUEUEDELAY +/* + case 'G': + queuealg = atoi(lbuf[1]); + break; + case 'Y': + queuedelay = (time_t) atol(&lbuf[1]); + break; +*/ +# endif /* _FFR_QUEUEDELAY */ + } + } + (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)) + dprintf("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++; + + WorkQ = NULL; + if (WorkList == NULL) + return 0; + wc = min(wn, WorkListSize); + if (wc > MaxQueueRun && MaxQueueRun > 0) + wc = MaxQueueRun; + + if (QueueSortOrder == QSO_BYHOST) + { + /* + ** 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 && + sm_strcasecmp(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 if (QueueSortOrder == QSO_BYTIME) + { + /* + ** Simple sort based on submission time only. + */ + + qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3); + } + else if (QueueSortOrder == QSO_BYFILENAME) + { + /* + ** Sort based on qf filename. + */ + + qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf4); + } + else + { + /* + ** 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. + */ + + 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; + WorkListSize = 0; + + if (tTd(40, 1)) + { + for (w = WorkQ; w != NULL; w = w->w_next) + { + if (w->w_host != NULL) + dprintf("%22s: pri=%ld %s\n", + w->w_name, w->w_pri, w->w_host); + else + dprintf("%32s: pri=%ld\n", + w->w_name, w->w_pri); + } + } + + return wn; +} + /* +** GROW_WLIST -- make the work list larger +** +** Parameters: +** queuedir -- the index for the queue directory. +** +** 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. +*/ + +static void +grow_wlist(queuedir) + int queuedir; +{ + if (tTd(41, 1)) + dprintf("grow_wlist: WorkListSize=%d\n", WorkListSize); + if (WorkList == NULL) + { + WorkList = (WORK *) xalloc((sizeof *WorkList) * + (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; + if (LogLevel > 1) + { + sm_syslog(LOG_INFO, NOQID, + "grew WorkList for %s to %d", + qid_printqueue(queuedir), + WorkListSize); + } + } + else if (LogLevel > 0) + { + sm_syslog(LOG_ALERT, NOQID, + "FAILED to grow WorkList for %s to %d", + qid_printqueue(queuedir), newsize); + } + } + if (tTd(41, 1)) + dprintf("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. +*/ + +static 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. +*/ + +static 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 = sm_strcasecmp(a->w_host, b->w_host)) != 0) + 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. +*/ + +static 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 = sm_strcasecmp(a->w_host, b->w_host)) != 0) + return i; + + /* job priority */ + return a->w_pri - b->w_pri; +} + /* +** WORKCMPF3 -- simple submission-time-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. +*/ + +static int +workcmpf3(a, b) + register WORK *a; + register WORK *b; +{ + if (a->w_ctime > b->w_ctime) + return 1; + else if (a->w_ctime < b->w_ctime) + return -1; + else + return 0; +} + /* +** WORKCMPF4 -- compare based on file name +** +** 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. +*/ + +static int +workcmpf4(a, b) + register WORK *a; + register WORK *b; +{ + return strcmp(a->w_name, b->w_name); +} + /* +** STRREV -- reverse string +** +** Returns a pointer to a new string that is the reverse of +** the string pointed to by fwd. The space for the new +** string is obtained using xalloc(). +** +** Parameters: +** fwd -- the string to reverse. +** +** Returns: +** the reversed string. +*/ + +static char * +strrev(fwd) + char *fwd; +{ + char *rev = NULL; + int len, cnt; + + len = strlen(fwd); + rev = xalloc(len + 1); + for (cnt = 0; cnt < len; ++cnt) + rev[cnt] = fwd[len - cnt - 1]; + rev[len] = '\0'; + return rev; +} + /* +** DOWORK -- do a work request. +** +** Parameters: +** queuedir -- the index of the queue directory for the job. +** 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(queuedir, id, forkflag, requeueflag, e) + int queuedir; + char *id; + bool forkflag; + bool requeueflag; + register ENVELOPE *e; +{ + register pid_t pid; + + if (tTd(40, 1)) + dprintf("dowork(%s/%s)\n", qid_printqueue(queuedir), id); + + /* + ** Fork for work. + */ + + if (forkflag) + { + /* + ** Since the delivery may happen in a child and the + ** parent does not wait, the parent may close the + ** maps thereby removing any shared memory used by + ** the map. Therefore, close the maps now so the + ** child will dynamically open them if necessary. + */ + + closemaps(); + + 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 + { + /* child -- error messages to the transcript */ + QuickAbort = OnlyOneError = FALSE; + } + } + 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); + clearstats(); + clearenvelope(e, FALSE); + e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS; + set_delivery_mode(SM_DELIVER, e); + e->e_errormode = EM_MAIL; + e->e_id = id; + e->e_queuedir = queuedir; + GrabTo = UseErrorsTo = FALSE; + ExitStat = EX_OK; + if (forkflag) + { + disconnect(1, e); + OpMode = MD_QUEUERUN; + } + sm_setproctitle(TRUE, e, "%s: from queue", qid_printname(e)); + if (LogLevel > 76) + sm_syslog(LOG_DEBUG, e->e_id, + "dowork, pid=%d", + getpid()); + + /* 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) && e->e_id != NULL) + dprintf("readqf(%s) failed\n", + qid_printname(e)); + e->e_id = NULL; + if (forkflag) + finis(FALSE, 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(TRUE, ExitStat); + else + dropenvelope(e, TRUE); + } + 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. +*/ + +static bool +readqf(e) + register ENVELOPE *e; +{ + register FILE *qfp; + ADDRESS *ctladdr; + struct stat st; + char *bp; + int qfver = 0; + int chompflags; + long hdrsize = 0; + register char *p; + char *orcpt = NULL; + bool nomore = FALSE; + char qf[MAXPATHLEN]; + char buf[MAXLINE]; + + /* + ** Read and process the file. + */ + + (void) strlcpy(qf, queuename(e, 'q'), sizeof qf); + qfp = fopen(qf, "r+"); + if (qfp == NULL) + { + int save_errno = errno; + + if (tTd(40, 8)) + dprintf("readqf(%s): fopen failure (%s)\n", + qf, errstring(errno)); + errno = save_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) + printf("%s: locked\n", e->e_id); + if (tTd(40, 8)) + dprintf("%s: locked\n", e->e_id); + if (LogLevel > 19) + sm_syslog(LOG_DEBUG, e->e_id, "locked"); + (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)) + dprintf("readqf(%s): fstat failure (%s)\n", + qf, errstring(errno)); + (void) fclose(qfp); + return FALSE; + } + + if ((st.st_uid != geteuid() && geteuid() != RealUid) || + bitset(S_IWOTH|S_IWGRP, st.st_mode)) + { + if (LogLevel > 0) + { + sm_syslog(LOG_ALERT, e->e_id, + "bogus queue file, uid=%d, mode=%o", + st.st_uid, st.st_mode); + } + if (tTd(40, 8)) + dprintf("readqf(%s): bogus file\n", qf); + loseqfile(e, "bogus file uid in mqueue"); + (void) fclose(qfp); + return FALSE; + } + + if (st.st_size == 0) + { + /* must be a bogus file -- if also old, just remove it */ + if (st.st_ctime + 10 * 60 < curtime()) + { + (void) xunlink(queuename(e, 'd')); + (void) xunlink(queuename(e, 'q')); + } + (void) 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. + */ + + (void) 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_QUEUERUN; + ctladdr = NULL; + e->e_dfino = -1; + e->e_msgsize = -1; +# if _FFR_QUEUEDELAY + e->e_queuealg = QD_LINEAR; + e->e_queuedelay = (time_t) 0; +# endif /* _FFR_QUEUEDELAY */ + while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL) + { + u_long qflags; + ADDRESS *q; + int mid; + auto char *ep; + + if (tTd(40, 4)) + dprintf("+++++ %s\n", bp); + if (nomore) + { + /* hack attack */ + syserr("SECURITY ALERT: extra data in qf: %s", bp); + (void) 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) + break; + syserr("Version number in qf (%d) greater than max (%d)", + qfver, QF_VERSION); + (void) fclose(qfp); + loseqfile(e, "unsupported qf file version"); + return FALSE; + + case 'C': /* specify controlling user */ + ctladdr = setctluser(&bp[1], qfver); + 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 'N': + qflags |= QHASNOTIFY; + break; + + 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; + if (qfver >= 1) + q->q_flags &= ~Q_PINGFLAGS; + 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 */ + chompflags = 0; + (void) chompheader(&bp[1], &chompflags, NULL, e); + hdrsize += strlen(&bp[1]); + break; + + case 'L': /* Solaris Content-Length: */ + case 'M': /* message */ + /* ignore this; we want a new message next time */ + break; + + case 'S': /* sender */ + setsender(newstr(&bp[1]), e, NULL, '\0', TRUE); + break; + + case 'B': /* body type */ + e->e_bodytype = newstr(&bp[1]); + break; + +# if _FFR_SAVE_CHARSET + case 'X': /* character set */ + e->e_charset = newstr(&bp[1]); + break; +# endif /* _FFR_SAVE_CHARSET */ + + 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 */ + /* regenerated below */ + break; + + case 'K': /* time of last delivery attempt */ + e->e_dtime = atol(&buf[1]); + break; + +# if _FFR_QUEUEDELAY + case 'G': /* queue delay algorithm */ + e->e_queuealg = atoi(&buf[1]); + break; + case 'Y': /* current delay */ + e->e_queuedelay = (time_t) atol(&buf[1]); + break; +# endif /* _FFR_QUEUEDELAY */ + + case 'N': /* number of delivery attempts */ + e->e_ntries = atoi(&buf[1]); + + /* if this has been tried recently, let it be */ + if (e->e_ntries > 0 && e->e_dtime <= curtime() && + curtime() < e->e_dtime + queuedelay(e)) + { + char *howlong; + + howlong = pintvl(curtime() - e->e_dtime, TRUE); + if (Verbose) + printf("%s: too young (%s)\n", + e->e_id, howlong); + if (tTd(40, 8)) + dprintf("%s: too young (%s)\n", + e->e_id, howlong); + if (LogLevel > 19) + sm_syslog(LOG_DEBUG, e->e_id, + "too young (%s)", + howlong); + e->e_id = NULL; + unlockqueue(e); + return FALSE; + } + define(macid("{ntries}", NULL), newstr(&buf[1]), e); + +# if NAMED_BIND + /* adjust BIND parameters immediately */ + if (e->e_ntries == 0) + { + _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; + _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; + } + else + { + _res.retry = TimeOuts.res_retry[RES_TO_NORMAL]; + _res.retrans = TimeOuts.res_retrans[RES_TO_NORMAL]; + } +# endif /* NAMED_BIND */ + 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); + (void) 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; + + case 'b': /* delete Bcc: header */ + e->e_flags |= EF_DELETE_BCC; + break; + + case 'd': /* envelope has DSN RET= */ + e->e_flags |= EF_RET_PARAM; + break; + + case 'n': /* don't return body */ + e->e_flags |= EF_NO_BODY_RETN; + break; + } + } + break; + + case 'Z': /* original envelope id from ESMTP */ + e->e_envid = newstr(&bp[1]); + define(macid("{dsn_envid}", NULL), newstr(&bp[1]), e); + break; + + case 'A': /* AUTH= parameter */ + e->e_auth_param = newstr(&bp[1]); + break; + + case '$': /* define macro */ + mid = macid(&bp[1], &ep); + define(mid, newstr(ep), e); + break; + + case '.': /* terminate file */ + nomore = TRUE; + break; + + default: + syserr("readqf: %s: line %d: bad line \"%s\"", + qf, LineNumber, shortenstring(bp, MAXSHORTSTR)); + (void) 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; + } + + /* possibly set ${dsn_ret} macro */ + if (bitset(EF_RET_PARAM, e->e_flags)) + { + if (bitset(EF_NO_BODY_RETN, e->e_flags)) + define(macid("{dsn_ret}", NULL), "hdrs", e); + else + define(macid("{dsn_ret}", NULL), "full", e); + } + + /* + ** 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 + hdrsize; + e->e_dfdev = st.st_dev; + e->e_dfino = st.st_ino; + } + } + + return TRUE; +} + /* +** PRTSTR -- print a string, "unprintable" characters are shown as \oct +** +** Parameters: +** s -- string to print +** ml -- maximum length of output +** +** Returns: +** none. +** +** Side Effects: +** Prints a string on stdout. +*/ + +static void +prtstr(s, ml) + char *s; + int ml; +{ + char c; + + if (s == NULL) + return; + while (ml-- > 0 && ((c = *s++) != '\0')) + { + if (c == '\\') + { + if (ml-- > 0) + { + putchar(c); + putchar(c); + } + } + else if (isascii(c) && isprint(c)) + putchar(c); + else + { + if ((ml -= 3) > 0) + printf("\\%03o", c); + } + } +} + /* +** 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() +{ + int i, nrequests = 0; + + for (i = 0; i < NumQueues; i++) + nrequests += print_single_queue(i); + if (NumQueues > 1) + printf("\t\tTotal Requests: %d\n", nrequests); +} + /* +** PRINT_SINGLE_QUEUE -- print out a representation of a single mail queue +** +** Parameters: +** queuedir -- queue directory +** +** Returns: +** none. +** +** Side Effects: +** Prints a listing of the mail queue on the standard output. +*/ + +static int +print_single_queue(queuedir) + int queuedir; +{ + register WORK *w; + FILE *f; + int nrequests; + char qd[MAXPATHLEN]; + char qddf[MAXPATHLEN]; + char buf[MAXLINE]; + + if (queuedir == NOQDIR) + { + (void) strlcpy(qd, ".", sizeof qd); + (void) strlcpy(qddf, ".", sizeof qddf); + } + else + { + (void) snprintf(qd, sizeof qd, "%s%s", + QPaths[queuedir].qp_name, + (bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : "")); + (void) snprintf(qddf, sizeof qddf, "%s%s", + QPaths[queuedir].qp_name, + (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); + } + + /* + ** Check for permission to print the queue + */ + + if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0) + { + struct stat st; +# ifdef NGROUPS_MAX + int n; + extern GIDSET_T InitialGidSet[NGROUPS_MAX]; +# endif /* NGROUPS_MAX */ + + if (stat(qd, &st) < 0) + { + syserr("Cannot stat %s", qid_printqueue(queuedir)); + return 0; + } +# ifdef NGROUPS_MAX + n = NGROUPS_MAX; + while (--n >= 0) + { + if (InitialGidSet[n] == st.st_gid) + break; + } + if (n < 0 && RealGid != st.st_gid) +# else /* NGROUPS_MAX */ + if (RealGid != st.st_gid) +# endif /* NGROUPS_MAX */ + { + usrerr("510 You are not permitted to see the queue"); + setstat(EX_NOPERM); + return 0; + } + } + + /* + ** Read and order the queue. + */ + + nrequests = orderq(queuedir, TRUE); + + /* + ** Print the work list that we have read. + */ + + /* first see if there is anything */ + if (nrequests <= 0) + { + printf("%s is empty\n", qid_printqueue(queuedir)); + return 0; + } + + CurrentLA = sm_getla(NULL); /* get load average */ + + printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests, + nrequests == 1 ? "" : "s"); + if (MaxQueueRun > 0 && nrequests > MaxQueueRun) + printf(", only %d printed", MaxQueueRun); + 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]; + char qf[MAXPATHLEN]; + + printf("%12s", w->w_name + 2); + (void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name); + f = fopen(qf, "r"); + if (f == NULL) + { + printf(" (job completed)\n"); + errno = 0; + continue; + } + w->w_name[0] = 'd'; + (void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name); + if (stat(qf, &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; + memmove(statmsg, &buf[1], i); + statmsg[i] = '\0'; + break; + + case 'B': /* body type */ + if ((i = strlen(&buf[1])) >= sizeof bodytype) + i = sizeof bodytype - 1; + memmove(bodytype, &buf[1], i); + bodytype[i] = '\0'; + break; + + case 'S': /* sender name */ + if (Verbose) + { + printf("%8ld %10ld%c%.12s ", + dfsize, + w->w_pri, + bitset(EF_WARNING, flags) ? '+' : ' ', + ctime(&submittime) + 4); + prtstr(&buf[1], 78); + } + else + { + printf("%8ld %.16s ", dfsize, + ctime(&submittime)); + prtstr(&buf[1], 40); + } + if (statmsg[0] != '\0' || bodytype[0] != '\0') + { + printf("\n %10.10s", bodytype); + if (statmsg[0] != '\0') + printf(" (%.*s)", + Verbose ? 100 : 60, + statmsg); + } + break; + + case 'C': /* controlling user */ + if (Verbose) + printf("\n\t\t\t\t (---%.74s---)", + &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 "); + prtstr(p, 73); + } + else + { + printf("\n\t\t\t\t "); + prtstr(p, 40); + } + 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); + } + return nrequests; +} + /* +** QUEUENAME -- build a file name in the queue directory for this envelope. +** +** 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 queue name (in a static buffer). +** +** Side Effects: +** If no id code is already assigned, queuename() will +** assign an id code with assign_queueid(). If no queue +** directory is assigned, one will be set with setnewqueue(). +*/ + +char * +queuename(e, type) + register ENVELOPE *e; + int type; +{ + char *sub = ""; + static char buf[MAXPATHLEN]; + + /* Assign an ID if needed */ + if (e->e_id == NULL) + assign_queueid(e); + + /* Assign a queue directory if needed */ + if (e->e_queuedir == NOQDIR) + setnewqueue(e); + + if (e->e_queuedir == NOQDIR) + (void) snprintf(buf, sizeof buf, "%cf%s", + type, e->e_id); + else + { + switch (type) + { + case 'd': + if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs)) + sub = "/df"; + break; + + case 'T': + case 't': + case 'Q': + case 'q': + if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs)) + sub = "/qf"; + break; + + case 'x': + if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs)) + sub = "/xf"; + break; + } + + (void) snprintf(buf, sizeof buf, "%s%s/%cf%s", + QPaths[e->e_queuedir].qp_name, + sub, type, e->e_id); + } + + if (tTd(7, 2)) + dprintf("queuename: %s\n", buf); + return buf; +} + /* +** ASSIGN_QUEUEID -- assign a queue ID for this envelope. +** +** Assigns an id code if one does not already exist. +** This code assumes that nothing will remain in the queue for +** longer than 60 years. It is critical that files with the given +** name not already exist in the queue. +** Also initializes e_queuedir to NOQDIR. +** +** Parameters: +** e -- envelope to set it in. +** +** Returns: +** none. +*/ + +static char Base60Code[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx"; + +void +assign_queueid(e) + register ENVELOPE *e; +{ + pid_t pid = getpid(); + static char cX = 0; + static long random_offset; + struct tm *tm; + char idbuf[MAXQFNAME - 2]; + + if (e->e_id != NULL) + return; + + /* see if we need to get a new base time/pid */ + if (cX >= 60 || LastQueueTime == 0 || LastQueuePid != pid) + { + time_t then = LastQueueTime; + + /* if the first time through, pick a random offset */ + if (LastQueueTime == 0) + random_offset = get_random(); + + while ((LastQueueTime = curtime()) == then && + LastQueuePid == pid) + { + (void) sleep(1); + } + LastQueuePid = getpid(); + cX = 0; + } + if (tTd(7, 50)) + dprintf("assign_queueid: random_offset = %ld (%d)\n", + random_offset, (int)(cX + random_offset) % 60); + + tm = gmtime(&LastQueueTime); + idbuf[0] = Base60Code[tm->tm_year % 60]; + idbuf[1] = Base60Code[tm->tm_mon]; + idbuf[2] = Base60Code[tm->tm_mday]; + idbuf[3] = Base60Code[tm->tm_hour]; + idbuf[4] = Base60Code[tm->tm_min]; + idbuf[5] = Base60Code[tm->tm_sec]; + idbuf[6] = Base60Code[((int)cX++ + random_offset) % 60]; + (void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d", + (int) LastQueuePid); + e->e_id = newstr(idbuf); + define('i', e->e_id, e); + e->e_queuedir = NOQDIR; + if (tTd(7, 1)) + dprintf("assign_queueid: assigned id %s, e=%lx\n", + e->e_id, (u_long) e); + if (LogLevel > 93) + sm_syslog(LOG_DEBUG, e->e_id, "assigned id"); +} + /* +** SYNC_QUEUE_TIME -- Assure exclusive PID in any given second +** +** Make sure one PID can't be used by two processes in any one second. +** +** If the system rotates PIDs fast enough, may get the +** same pid in the same second for two distinct processes. +** This will interfere with the queue file naming system. +** +** Parameters: +** none +** +** Returns: +** none +*/ +void +sync_queue_time() +{ +# if FAST_PID_RECYCLE + if (OpMode != MD_TEST && + OpMode != MD_VERIFY && + LastQueueTime > 0 && + LastQueuePid == getpid() && + curtime() == LastQueueTime) + (void) sleep(1); +# endif /* FAST_PID_RECYCLE */ +} + /* +** 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)) + dprintf("unlockqueue(%s)\n", + e->e_id == NULL ? "NOQUEUE" : e->e_id); + + /* if there is a lock file in the envelope, close it */ + if (e->e_lockfp != NULL) + (void) fclose(e->e_lockfp); + 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 */ + if (LogLevel > 87) + sm_syslog(LOG_DEBUG, e->e_id, "unlock"); + 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. +** qfver -- the version stamp of this qf file. +** +** Returns: +** An address descriptor for the controlling user. +** +** Side Effects: +** none. +*/ + +static ADDRESS * +setctluser(user, qfver) + char *user; + int qfver; +{ + 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); + memset((char *) a, '\0', sizeof *a); + + if (*user == '\0') + { + p = NULL; + a->q_user = newstr(DefUser); + } + else if (*user == ':') + { + p = &user[1]; + a->q_user = newstr(p); + } + else + { + p = strtok(user, ":"); + a->q_user = newstr(user); + if (qfver >= 2) + { + if ((p = strtok(NULL, ":")) != NULL) + a->q_uid = atoi(p); + if ((p = strtok(NULL, ":")) != NULL) + a->q_gid = atoi(p); + if ((p = strtok(NULL, ":")) != NULL) + a->q_flags |= QGOODUID; + } + else if ((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; + } + } + + a->q_flags |= QPRIMARY; /* flag as a "ctladdr" */ + a->q_mailer = LocalMailer; + if (p == NULL) + a->q_paddr = newstr(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[MAXPATHLEN]; + + if (e == NULL || e->e_id == NULL) + return; + p = queuename(e, 'q'); + if (strlen(p) >= (SIZE_T) sizeof buf) + return; + (void) strlcpy(buf, p, sizeof buf); + p = queuename(e, 'Q'); + if (rename(buf, p) < 0) + syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid()); + else if (LogLevel > 0) + sm_syslog(LOG_ALERT, e->e_id, + "Losing %s: %s", buf, why); +} + /* +** QID_PRINTNAME -- create externally printable version of queue id +** +** Parameters: +** e -- the envelope. +** +** Returns: +** a printable version +*/ + +char * +qid_printname(e) + ENVELOPE *e; +{ + char *id; + static char idbuf[MAXQFNAME + 34]; + + if (e == NULL) + return ""; + + if (e->e_id == NULL) + id = ""; + else + id = e->e_id; + + if (e->e_queuedir == NOQDIR) + return id; + + (void) snprintf(idbuf, sizeof idbuf, "%.32s/%s", + QPaths[e->e_queuedir].qp_name, id); + return idbuf; +} + /* +** QID_PRINTQUEUE -- create full version of queue directory for df files +** +** Parameters: +** queuedir -- the short version of the queue directory +** +** Returns: +** the full pathname to the queue (static) +*/ + +char * +qid_printqueue(queuedir) + int queuedir; +{ + char *subdir; + static char dir[MAXPATHLEN]; + + if (queuedir == NOQDIR) + return QueueDir; + + if (strcmp(QPaths[queuedir].qp_name, ".") == 0) + subdir = NULL; + else + subdir = QPaths[queuedir].qp_name; + + (void) snprintf(dir, sizeof dir, "%s%s%s%s", QueueDir, + subdir == NULL ? "" : "/", + subdir == NULL ? "" : subdir, + (bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : "")); + return dir; +} + /* +** SETNEWQUEUE -- Sets a new queue directory +** +** Assign a queue directory to an envelope and store the directory +** in e->e_queuedir. The queue is chosen at random. +** +** This routine may be improved in the future to allow for more +** elaborate queueing schemes. Suggestions and code contributions +** are welcome. +** +** Parameters: +** e -- envelope to assign a queue for. +** +** Returns: +** none. +*/ + +void +setnewqueue(e) + ENVELOPE *e; +{ + int idx; + + if (tTd(41, 20)) + dprintf("setnewqueue: called\n"); + + if (e->e_queuedir != NOQDIR) + { + if (tTd(41, 20)) + dprintf("setnewqueue: e_queuedir already assigned (%s)\n", + qid_printqueue(e->e_queuedir)); + return; + } + + if (NumQueues == 1) + idx = 0; + else + { +#if RANDOMSHIFT + /* lower bits are not random "enough", select others */ + idx = (get_random() >> RANDOMSHIFT) % NumQueues; +#else /* RANDOMSHIFT */ + idx = get_random() % NumQueues; +#endif /* RANDOMSHIFT */ + if (tTd(41, 15)) + dprintf("setnewqueue: get_random() %% %d = %d\n", + NumQueues, idx); + } + + e->e_queuedir = idx; + if (tTd(41, 3)) + dprintf("setnewqueue: Assigned queue directory %s\n", + qid_printqueue(e->e_queuedir)); +} + + /* +** CHKQDIR -- check a queue directory +** +** Parameters: +** name -- name of queue directory +** sff -- flags for safefile() +** +** Returns: +** is it a queue directory? +*/ + +static bool +chkqdir(name, sff) + char *name; + long sff; +{ + struct stat statb; + int i; + +# if HASLSTAT + if (lstat(name, &statb) < 0) +# else /* HASLSTAT */ + if (stat(name, &statb) < 0) +# endif /* HASLSTAT */ + { + if (tTd(41, 2)) + dprintf("multiqueue_cache: stat(\"%s\"): %s\n", + name, errstring(errno)); + return FALSE; + } +# if HASLSTAT + if (S_ISLNK(statb.st_mode)) + { + /* + ** For a symlink we need to make sure the + ** target is a directory + */ + if (stat(name, &statb) < 0) + { + if (tTd(41, 2)) + dprintf("multiqueue_cache: stat(\"%s\"): %s\n", + name, errstring(errno)); + return FALSE; + } + } +# endif /* HASLSTAT */ + + if (!S_ISDIR(statb.st_mode)) + { + if (tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": Not a directory\n", + name); + return FALSE; + } + + /* Print a warning if unsafe (but still use it) */ + i = safedirpath(name, RunAsUid, RunAsGid, NULL, sff, 0, 0); + if (i != 0 && tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", + name, errstring(i)); + return TRUE; +} + + /* +** MULTIQUEUE_CACHE -- cache a list of paths to queues. +** +** Each potential queue is checked as the cache is built. +** Thereafter, each is blindly trusted. +** Note that we can be called again after a timeout to rebuild +** (although code for that is not ready yet). +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +multiqueue_cache() +{ + register DIR *dp; + register struct dirent *d; + char *cp; + int i, len; + int slotsleft = 0; + long sff = SFF_ANYFILE; + char qpath[MAXPATHLEN]; + char subdir[MAXPATHLEN]; + + if (tTd(41, 20)) + dprintf("multiqueue_cache: called\n"); + + if (NumQueues != 0 && QPaths != NULL) + { + for (i = 0; i < NumQueues; i++) + { + if (QPaths[i].qp_name != NULL) + (void) free(QPaths[i].qp_name); + } + (void) free((char *)QPaths); + QPaths = NULL; + NumQueues = 0; + } + + /* If running as root, allow safedirpath() checks to use privs */ + if (RunAsUid == 0) + sff |= SFF_ROOTOK; + + (void) snprintf(qpath, sizeof qpath, "%s", QueueDir); + len = strlen(qpath) - 1; + cp = &qpath[len]; + if (*cp == '*') + { + *cp = '\0'; + if ((cp = strrchr(qpath, '/')) == NULL) + { + syserr("QueueDirectory: can not wildcard relative path"); + if (tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": Can not wildcard relative path.\n", + QueueDir); + ExitStat = EX_CONFIG; + return; + } + if (cp == qpath) + { + /* + ** Special case of top level wildcard, like /foo* + */ + + (void) snprintf(qpath + 1, sizeof qpath - 1, + "%s", qpath); + ++cp; + } + *(cp++) = '\0'; + len = strlen(cp); + + if (tTd(41, 2)) + dprintf("multiqueue_cache: prefix=\"%s\"\n", cp); + + QueueDir = newstr(qpath); + + /* + ** XXX Should probably wrap this whole loop in a timeout + ** in case some wag decides to NFS mount the queues. + */ + + /* test path to get warning messages */ + i= safedirpath(QueueDir, RunAsUid, RunAsGid, NULL, sff, 0, 0); + if (i != 0 && tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": Not safe: %s\n", + QueueDir, errstring(i)); + + if (chdir(QueueDir) < 0) + { + syserr("can not chdir(%s)", QueueDir); + if (tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": %s\n", + qpath, errstring(errno)); + ExitStat = EX_CONFIG; + return; + } + + if ((dp = opendir(".")) == NULL) + { + syserr("can not opendir(%s)", QueueDir); + if (tTd(41, 2)) + dprintf("multiqueue_cache: opendir(\"%s\"): %s\n", + QueueDir, errstring(errno)); + ExitStat = EX_CONFIG; + return; + } + while ((d = readdir(dp)) != NULL) + { + if (strncmp(d->d_name, cp, len) != 0) + { + if (tTd(41, 5)) + dprintf("multiqueue_cache: \"%s\", skipped\n", + d->d_name); + continue; + } + if (!chkqdir(d->d_name, sff)) + continue; + + if (QPaths == NULL) + { + slotsleft = 20; + QPaths = (QPATHS *)xalloc((sizeof *QPaths) * + slotsleft); + NumQueues = 0; + } + else if (slotsleft < 1) + { + QPaths = (QPATHS *)realloc((char *)QPaths, + (sizeof *QPaths) * + (NumQueues + 10)); + if (QPaths == NULL) + { + (void) closedir(dp); + return; + } + slotsleft += 10; + } + + /* check subdirs */ + QPaths[NumQueues].qp_subdirs = QP_NOSUB; + (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", + qpath, d->d_name, "qf"); + if (chkqdir(subdir, sff)) + QPaths[NumQueues].qp_subdirs |= QP_SUBQF; + + (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", + qpath, d->d_name, "df"); + if (chkqdir(subdir, sff)) + QPaths[NumQueues].qp_subdirs |= QP_SUBDF; + + (void) snprintf(subdir, sizeof subdir, "%s/%s/%s", + qpath, d->d_name, "xf"); + if (chkqdir(subdir, sff)) + QPaths[NumQueues].qp_subdirs |= QP_SUBXF; + + /* assert(strlen(d->d_name) < MAXPATHLEN - 14) */ + /* maybe even - 17 (subdirs) */ + QPaths[NumQueues].qp_name = newstr(d->d_name); + if (tTd(41, 2)) + dprintf("multiqueue_cache: %d: \"%s\" cached (%x).\n", + NumQueues, d->d_name, + QPaths[NumQueues].qp_subdirs); + NumQueues++; + slotsleft--; + } + (void) closedir(dp); + } + if (NumQueues == 0) + { + if (*cp != '*' && tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": No wildcard suffix character\n", + QueueDir); + QPaths = (QPATHS *)xalloc(sizeof *QPaths); + QPaths[0].qp_name = newstr("."); + QPaths[0].qp_subdirs = QP_NOSUB; + NumQueues = 1; + + /* test path to get warning messages */ + (void) safedirpath(QueueDir, RunAsUid, RunAsGid, + NULL, sff, 0, 0); + if (chdir(QueueDir) < 0) + { + syserr("can not chdir(%s)", QueueDir); + if (tTd(41, 2)) + dprintf("multiqueue_cache: \"%s\": %s\n", + QueueDir, errstring(errno)); + ExitStat = EX_CONFIG; + } + + /* check subdirs */ + (void) snprintf(subdir, sizeof subdir, "%s/qf", QueueDir); + if (chkqdir(subdir, sff)) + QPaths[0].qp_subdirs |= QP_SUBQF; + + (void) snprintf(subdir, sizeof subdir, "%s/df", QueueDir); + if (chkqdir(subdir, sff)) + QPaths[0].qp_subdirs |= QP_SUBDF; + + (void) snprintf(subdir, sizeof subdir, "%s/xf", QueueDir); + if (chkqdir(subdir, sff)) + QPaths[0].qp_subdirs |= QP_SUBXF; + } +} + +# if 0 + /* +** HASHFQN -- calculate a hash value for a fully qualified host name +** +** Arguments: +** fqn -- an all lower-case host.domain string +** buckets -- the number of buckets (queue directories) +** +** Returns: +** a bucket number (signed integer) +** -1 on error +** +** Contributed by Exactis.com, Inc. +*/ + +int +hashfqn(fqn, buckets) + register char *fqn; + int buckets; +{ + register char *p; + register int h = 0, hash, cnt; +# define WATERINC (1000) + + if (fqn == NULL) + return -1; + + /* + ** A variation on the gdb hash + ** This is the best as of Feb 19, 1996 --bcx + */ + + p = fqn; + h = 0x238F13AF * strlen(p); + for (cnt = 0; *p != 0; ++p, cnt++) + { + h = (h + (*p << (cnt * 5 % 24))) & 0x7FFFFFFF; + } + h = (1103515243 * h + 12345) & 0x7FFFFFFF; + if (buckets < 2) + hash = 0; + else + hash = (h % buckets); + + return hash; +} +# endif /* 0 */ + +# if _FFR_QUEUEDELAY + /* +** QUEUEDELAY -- compute queue delay time +** +** Parameters: +** e -- the envelope to queue up. +** +** Returns: +** queue delay time +** +** Side Effects: +** may change e_queuedelay +*/ + +static time_t +queuedelay(e) + ENVELOPE *e; +{ + time_t qd; + + if (e->e_queuealg == QD_EXP) + { + if (e->e_queuedelay == 0) + e->e_queuedelay = QueueInitDelay; + else + { + e->e_queuedelay *= 2; + if (e->e_queuedelay > QueueMaxDelay) + e->e_queuedelay = QueueMaxDelay; + } + qd = e->e_queuedelay; + } + else + qd = MinQueueAge; + return qd; +} +# endif /* _FFR_QUEUEDELAY */ +#endif /* QUEUE */ diff --git a/gnu/usr.sbin/sendmail/sendmail/readcf.c b/gnu/usr.sbin/sendmail/sendmail/readcf.c new file mode 100644 index 00000000000..7d3e2b4f783 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/readcf.c @@ -0,0 +1,3569 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: readcf.c,v 8.380 2000/02/16 00:44:17 ca Exp $"; +#endif /* ! lint */ + +#include +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + +#define SECONDS +#define MINUTES * 60 +#define HOUR * 3600 +#define HOURS HOUR + +static void fileclass __P((int, char *, char *, bool, bool)); +static char **makeargv __P((char *)); +static void settimeout __P((char *, char *, bool)); +static void toomany __P((int, int)); +#if _FFR_MILTER +static void milter_setup __P((char *)); +#endif /* _FFR_MILTER */ + +/* +** READCF -- read configuration file. +** +** This routine reads the configuration 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 -- configuration 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 = -1; + char *q; + struct rewrite *rwp = NULL; + char *bp; + auto char *ep; + int nfuzzy; + char *file; + bool optional; + int mid; + int chompflags; + register char *p; + long sff = SFF_OPENASROOT; + struct stat statb; + char buf[MAXLINE]; + char exbuf[MAXLINE]; + char pvpbuf[MAXLINE + MAXATOM]; + static char *null_list[1] = { NULL }; + extern u_char TokTypeNoC[]; + + FileName = cfname; + LineNumber = 0; + + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + cf = safefopen(cfname, O_RDONLY, 0444, sff); + if (cf == NULL) + { + syserr("cannot open"); + finis(FALSE, EX_OSFILE); + } + + if (fstat(fileno(cf), &statb) < 0) + { + syserr("cannot fstat"); + finis(FALSE, EX_OSFILE); + } + + if (!S_ISREG(statb.st_mode)) + { + syserr("not a plain file"); + finis(FALSE, 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); + if (LogLevel > 0) + sm_syslog(LOG_CRIT, NOQID, + "%s: WARNING: dangerous write permissions", + FileName); + } + +#ifdef XLA + xla_zero(); +#endif /* XLA */ + + 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 */ + if (ruleset < 0) + { + syserr("missing valid ruleset for \"%s\"", bp); + break; + } + 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, + ConfigLevel >= 9 ? TokTypeNoC : 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 CANONUSER: + botch = "$:"; + break; + + case CALLSUBR: + botch = "$>"; + break; + + case CONDIF: + 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); + } + rwp->r_line = LineNumber; + } + 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, + ConfigLevel >= 9 ? TokTypeNoC : 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) + { + if (OpMode == MD_TEST) + printf("WARNING: Ruleset %s has multiple definitions\n", + &bp[1]); + if (tTd(37, 1)) + dprintf("WARNING: Ruleset %s has multiple definitions\n", + &bp[1]); + while (rwp->r_next != NULL) + rwp = rwp->r_next; + } + break; + + case 'D': /* macro definition */ + mid = macid(&bp[1], &ep); + p = munchstring(ep, NULL, '\0'); + define(mid, newstr(p), e); + break; + + case 'H': /* required header line */ + chompflags = CHHDR_DEF; + (void) chompheader(&bp[1], &chompflags, 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 /* XLA */ + +#if defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) + case 'L': /* lookup macro */ + case 'G': /* lookup class */ + /* reserved for Sun -- NIS+ database lookup */ + if (VendorCode != VENDOR_SUN) + goto badline; + sun_lg_config_line(bp, e); + break; +#endif /* defined(SUN_EXTENSIONS) && defined(SUN_LOOKUP_MACRO) */ + + 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; + +#if _FFR_MILTER + case 'X': /* mail filter */ + milter_setup(&bp[1]); + break; +#endif /* _FFR_MILTER */ + + default: + badline: + syserr("unknown configuration line \"%s\"", bp); + } + if (bp != buf) + free(bp); + } + if (ferror(cf)) + { + syserr("I/O read error"); + finis(FALSE, EX_OSFILE); + } + (void) fclose(cf); + FileName = NULL; + + /* initialize host maps from local service tables */ + inithostmaps(); + + /* initialize daemon (if not defined yet) */ + initdaemon(); + + /* 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 /* HESIOD */ + } +} + /* +** 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) strlcpy(p, p + 1, strlen(p)); + break; + + default: + /* delete leading white space */ + while (isascii(*p) && isspace(*p) && + *p != '\n' && p > bp) + p--; + if ((e = strchr(++p, '\n')) != NULL) + (void) strlcpy(p, e, strlen(p)); + else + *p-- = '\0'; + break; + } + continue; + } + + if (*p != '$' || p[1] == '\0') + continue; + + if (p[1] == '$') + { + /* actual dollar sign.... */ + (void) strlcpy(p, p + 1, strlen(p)); + 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 + 1) + (void) strlcpy(p + 1, ep, strlen(p + 1)); + } + + /* 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. +*/ + +static 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. +*/ + +static void +fileclass(class, filename, fmt, safe, optional) + int class; + char *filename; + char *fmt; + bool safe; + bool optional; +{ + FILE *f; + long sff; + pid_t pid; + register char *p; + char buf[MAXLINE]; + + if (tTd(37, 2)) + dprintf("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 (!bitnset(DBS_CLASSFILEINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + if (!bitnset(DBS_LINKEDCLASSFILEINWRITABLEDIR, + DontBlameSendmail)) + sff |= SFF_NOWLINK; + if (safe) + sff |= SFF_OPENASROOT; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + 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) + { +#if SCANF + char wordbuf[MAXLINE + 1]; +#endif /* SCANF */ + + 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); +} +#if _FFR_MILTER + /* +** MILTER_SETUP -- setup structure for a mail filter +** +** Parameters: +** line -- the options line. +** +** Returns: +** none +*/ + +static void +milter_setup(line) + char *line; +{ + char fcode; + register char *p; + register struct milter *m; + STAB *s; + + /* 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 mail filter"); + return; + } + m = (struct milter *)xalloc(sizeof *m); + memset((char *) m, '\0', sizeof *m); + m->mf_name = newstr(line); + m->mf_state = SMFS_READY; + m->mf_sock = -1; + m->mf_timeout[SMFTO_WRITE] = (time_t) 10; + m->mf_timeout[SMFTO_READ] = (time_t) 10; + m->mf_timeout[SMFTO_EOM] = (time_t) 5 MINUTES; + + /* now scan through and assign info from the fields */ + while (*p != '\0') + { + 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("X%s: `=' expected", m->mf_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 'S': /* socket */ + if (p == NULL) + m->mf_conn = NULL; + else + m->mf_conn = newstr(p); + + /* early check for errors */ + (void) milter_open(m, TRUE, CurEnv); + break; + + case 'F': /* Milter flags configured on MTA */ + for (; *p != '\0'; p++) + { + if (!(isascii(*p) && isspace(*p))) + setbitn(*p, m->mf_flags); + } + break; + + case 'T': /* timeouts */ + milter_parse_timeouts(p, m); + break; + + default: + syserr("X%s: unknown filter equate %c=", + m->mf_name, fcode); + break; + } + p = delimptr; + } + + /* enter the mailer into the symbol table */ + s = stab(m->mf_name, ST_MILTER, ST_ENTER); + if (s->s_milter != NULL) + syserr("X%s: duplicate filter definition", m->mf_name); + else + s->s_milter = m; +} +#endif /* _FFR_MILTER */ + /* +** 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 +** W -- the time to wait at the end +** 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; + + /* allocate a mailer and set up defaults */ + m = (struct mailer *) xalloc(sizeof *m); + memset((char *) m, '\0', sizeof *m); + + /* 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 'm': /* maximum messages per connection */ + m->m_maxdeliveries = atoi(p); + break; + + case 'L': /* maximum line length */ + m->m_linelimit = atoi(p); + if (m->m_linelimit < 0) + m->m_linelimit = 0; + 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') + p++; + } + 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; + + case 'W': /* wait timeout */ + m->m_wait = convtime(p, 's'); + break; + + case '/': /* new root directory */ + if (*p == '\0') + syserr("mailer %s: null root directory", + m->m_name); + else + m->m_rootdir = newstr(p); + break; + + default: + syserr("M%s: unknown mailer equate %c=", + m->m_name, fcode); + 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, "[TCP]") == 0) + { +#if _FFR_REMOVE_TCP_PATH + syserr("M%s: P=[TCP] is deprecated, use P=[IPC] instead\n", + m->m_name); +#else /* _FFR_REMOVE_TCP_PATH */ + printf("M%s: Warning: P=[TCP] is deprecated, use P=[IPC] instead\n", + m->m_name); +#endif /* _FFR_REMOVE_TCP_PATH */ + } + + if (strcmp(m->m_mailer, "[IPC]") == 0 || +#if !_FFR_REMOVE_TCP_MAILER_PATH + strcmp(m->m_mailer, "[TCP]") == 0 +#endif /* !_FFR_REMOVE_TCP_MAILER_PATH */ + ) + { + /* Use the second argument for host or path to socket */ + if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || + m->m_argv[1][0] == '\0') + { + syserr("M%s: too few parameters for %s mailer", + m->m_name, m->m_mailer); + } + if (strcmp(m->m_argv[0], "TCP") != 0 && +#if NETUNIX + strcmp(m->m_argv[0], "FILE") != 0 && +#endif /* NETUNIX */ +#if !_FFR_DEPRECATE_IPC_MAILER_ARG + strcmp(m->m_argv[0], "IPC") != 0 +#endif /* !_FFR_DEPRECATE_IPC_MAILER_ARG */ + ) + { + printf("M%s: Warning: first argument in %s mailer must be %s\n", + m->m_name, m->m_mailer, +#if NETUNIX + "TCP or FILE" +#else /* NETUNIX */ + "TCP" +#endif /* NETUNIX */ + ); + } + + } + else if (strcmp(m->m_mailer, "[FILE]") == 0) + { + /* Use the second argument for filename */ + if (m->m_argv[0] == NULL || m->m_argv[1] == NULL || + m->m_argv[2] != NULL) + { + syserr("M%s: too %s parameters for [FILE] mailer", + m->m_name, + (m->m_argv[0] == NULL || + m->m_argv[1] == NULL) ? "few" : "many"); + } + else if (strcmp(m->m_argv[0], "FILE") != 0) + { + syserr("M%s: first argument in [FILE] mailer must be FILE", + m->m_name); + } + } + + 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) + { + if (m->m_argv[0] != NULL && + strcmp(m->m_argv[0], "FILE") == 0) + m->m_diagtype = "x-unix"; + else + m->m_diagtype = "smtp"; + } + } + + if (m->m_eol == NULL) + { + char **pp; + + /* default for SMTP is \r\n; use \n for local delivery */ + for (pp = m->m_argv; *pp != NULL; pp++) + { + for (p = *pp; *p != '\0'; ) + { + if ((*p++ & 0377) == MACROEXPAND && *p == 'u') + break; + } + if (*p != '\0') + break; + } + if (*pp == NULL) + m->m_eol = "\r\n"; + else + m->m_eol = "\n"; + } + + /* 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. +** delim -- the delimiter for the field. +** +** Returns: +** the munched string. +*/ + +char * +munchstring(p, delimptr, delim) + register char *p; + char **delimptr; + int delim; +{ + 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 != delim) + *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. +*/ + +static 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); + memmove((char *) avp, (char *) argv, 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=", m->m_mno, m->m_name, m->m_mailer); + if (RuleSetNames[m->m_se_rwset] == NULL) + printf("%d/", m->m_se_rwset); + else + printf("%s/", RuleSetNames[m->m_se_rwset]); + if (RuleSetNames[m->m_sh_rwset] == NULL) + printf("%d R=", m->m_sh_rwset); + else + printf("%s R=", RuleSetNames[m->m_sh_rwset]); + if (RuleSetNames[m->m_re_rwset] == NULL) + printf("%d/", m->m_re_rwset); + else + printf("%s/", RuleSetNames[m->m_re_rwset]); + if (RuleSetNames[m->m_rh_rwset] == NULL) + printf("%d ", m->m_rh_rwset); + else + printf("%s ", RuleSetNames[m->m_rh_rwset]); + printf("M=%ld U=%d:%d F=", m->m_maxsize, + (int) m->m_uid, (int) 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 ? "" : m->m_mtatype, + m->m_addrtype == NULL ? "" : m->m_addrtype, + m->m_diagtype == NULL ? "" : 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 BITMAP256 StickyOpt; /* set if option is stuck */ + +#if NAMED_BIND + +static 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 }, /* avoid error on old syntax */ + { NULL, 0 } +}; + +#endif /* NAMED_BIND */ + +#define OI_NONE 0 /* no special treatment */ +#define OI_SAFE 0x0001 /* safe for random people to use */ +#define OI_SUBOPT 0x0002 /* option has suboptions */ + +static struct optioninfo +{ + char *o_name; /* long name of option */ + u_char o_code; /* short name of option */ + u_short o_flags; /* option flags */ +} OptionTab[] = +{ +#if defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) + { "RemoteMode", '>', OI_NONE }, +#endif /* defined(SUN_EXTENSIONS) && defined(REMOTE_MODE) */ + { "SevenBitInput", '7', OI_SAFE }, +#if MIME8TO7 + { "EightBitMode", '8', OI_SAFE }, +#endif /* MIME8TO7 */ + { "AliasFile", 'A', OI_NONE }, + { "AliasWait", 'a', OI_NONE }, + { "BlankSub", 'B', OI_NONE }, + { "MinFreeBlocks", 'b', OI_SAFE }, + { "CheckpointInterval", 'C', OI_SAFE }, + { "HoldExpensive", 'c', OI_NONE }, +#if !_FFR_REMOVE_AUTOREBUILD + { "AutoRebuildAliases", 'D', OI_NONE }, +#endif /* !_FFR_REMOVE_AUTOREBUILD */ + { "DeliveryMode", 'd', OI_SAFE }, + { "ErrorHeader", 'E', OI_NONE }, + { "ErrorMode", 'e', OI_SAFE }, + { "TempFileMode", 'F', OI_NONE }, + { "SaveFromLine", 'f', OI_NONE }, + { "MatchGECOS", 'G', OI_NONE }, + { "HelpFile", 'H', OI_NONE }, + { "MaxHopCount", 'h', OI_NONE }, + { "ResolverOptions", 'I', OI_NONE }, + { "IgnoreDots", 'i', OI_SAFE }, + { "ForwardPath", 'J', OI_NONE }, + { "SendMimeErrors", 'j', OI_SAFE }, + { "ConnectionCacheSize", 'k', OI_NONE }, + { "ConnectionCacheTimeout", 'K', OI_NONE }, + { "UseErrorsTo", 'l', OI_NONE }, + { "LogLevel", 'L', OI_SAFE }, + { "MeToo", 'm', OI_SAFE }, + { "CheckAliases", 'n', OI_NONE }, + { "OldStyleHeaders", 'o', OI_SAFE }, + { "DaemonPortOptions", 'O', OI_NONE }, + { "PrivacyOptions", 'p', OI_SAFE }, + { "PostmasterCopy", 'P', OI_NONE }, + { "QueueFactor", 'q', OI_NONE }, + { "QueueDirectory", 'Q', OI_NONE }, + { "DontPruneRoutes", 'R', OI_NONE }, + { "Timeout", 'r', OI_SUBOPT }, + { "StatusFile", 'S', OI_NONE }, + { "SuperSafe", 's', OI_SAFE }, + { "QueueTimeout", 'T', OI_NONE }, + { "TimeZoneSpec", 't', OI_NONE }, + { "UserDatabaseSpec", 'U', OI_NONE }, + { "DefaultUser", 'u', OI_NONE }, + { "FallbackMXhost", 'V', OI_NONE }, + { "Verbose", 'v', OI_SAFE }, + { "TryNullMXList", 'w', OI_NONE }, + { "QueueLA", 'x', OI_NONE }, + { "RefuseLA", 'X', OI_NONE }, + { "RecipientFactor", 'y', OI_NONE }, + { "ForkEachJob", 'Y', OI_NONE }, + { "ClassFactor", 'z', OI_NONE }, + { "RetryFactor", 'Z', OI_NONE }, +#define O_QUEUESORTORD 0x81 + { "QueueSortOrder", O_QUEUESORTORD, OI_SAFE }, +#define O_HOSTSFILE 0x82 + { "HostsFile", O_HOSTSFILE, OI_NONE }, +#define O_MQA 0x83 + { "MinQueueAge", O_MQA, OI_SAFE }, +#define O_DEFCHARSET 0x85 + { "DefaultCharSet", O_DEFCHARSET, OI_SAFE }, +#define O_SSFILE 0x86 + { "ServiceSwitchFile", O_SSFILE, OI_NONE }, +#define O_DIALDELAY 0x87 + { "DialDelay", O_DIALDELAY, OI_SAFE }, +#define O_NORCPTACTION 0x88 + { "NoRecipientAction", O_NORCPTACTION, OI_SAFE }, +#define O_SAFEFILEENV 0x89 + { "SafeFileEnvironment", O_SAFEFILEENV, OI_NONE }, +#define O_MAXMSGSIZE 0x8a + { "MaxMessageSize", O_MAXMSGSIZE, OI_NONE }, +#define O_COLONOKINADDR 0x8b + { "ColonOkInAddr", O_COLONOKINADDR, OI_SAFE }, +#define O_MAXQUEUERUN 0x8c + { "MaxQueueRunSize", O_MAXQUEUERUN, OI_SAFE }, +#define O_MAXCHILDREN 0x8d + { "MaxDaemonChildren", O_MAXCHILDREN, OI_NONE }, +#define O_KEEPCNAMES 0x8e + { "DontExpandCnames", O_KEEPCNAMES, OI_NONE }, +#define O_MUSTQUOTE 0x8f + { "MustQuoteChars", O_MUSTQUOTE, OI_NONE }, +#define O_SMTPGREETING 0x90 + { "SmtpGreetingMessage", O_SMTPGREETING, OI_NONE }, +#define O_UNIXFROM 0x91 + { "UnixFromLine", O_UNIXFROM, OI_NONE }, +#define O_OPCHARS 0x92 + { "OperatorChars", O_OPCHARS, OI_NONE }, +#define O_DONTINITGRPS 0x93 + { "DontInitGroups", O_DONTINITGRPS, OI_NONE }, +#define O_SLFH 0x94 + { "SingleLineFromHeader", O_SLFH, OI_SAFE }, +#define O_ABH 0x95 + { "AllowBogusHELO", O_ABH, OI_SAFE }, +#define O_CONNTHROT 0x97 + { "ConnectionRateThrottle", O_CONNTHROT, OI_NONE }, +#define O_UGW 0x99 + { "UnsafeGroupWrites", O_UGW, OI_NONE }, +#define O_DBLBOUNCE 0x9a + { "DoubleBounceAddress", O_DBLBOUNCE, OI_NONE }, +#define O_HSDIR 0x9b + { "HostStatusDirectory", O_HSDIR, OI_NONE }, +#define O_SINGTHREAD 0x9c + { "SingleThreadDelivery", O_SINGTHREAD, OI_NONE }, +#define O_RUNASUSER 0x9d + { "RunAsUser", O_RUNASUSER, OI_NONE }, +#define O_DSN_RRT 0x9e + { "RrtImpliesDsn", O_DSN_RRT, OI_NONE }, +#define O_PIDFILE 0x9f + { "PidFile", O_PIDFILE, OI_NONE }, +#define O_DONTBLAMESENDMAIL 0xa0 + { "DontBlameSendmail", O_DONTBLAMESENDMAIL, OI_NONE }, +#define O_DPI 0xa1 + { "DontProbeInterfaces", O_DPI, OI_NONE }, +#define O_MAXRCPT 0xa2 + { "MaxRecipientsPerMessage", O_MAXRCPT, OI_SAFE }, +#define O_DEADLETTER 0xa3 + { "DeadLetterDrop", O_DEADLETTER, OI_NONE }, +#if _FFR_DONTLOCKFILESFORREAD_OPTION +# define O_DONTLOCK 0xa4 + { "DontLockFilesForRead", O_DONTLOCK, OI_NONE }, +#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ +#define O_MAXALIASRCSN 0xa5 + { "MaxAliasRecursion", O_MAXALIASRCSN, OI_NONE }, +#define O_CNCTONLYTO 0xa6 + { "ConnectOnlyTo", O_CNCTONLYTO, OI_NONE }, +#define O_TRUSTUSER 0xa7 + { "TrustedUser", O_TRUSTUSER, OI_NONE }, +#define O_MAXMIMEHDRLEN 0xa8 + { "MaxMimeHeaderLength", O_MAXMIMEHDRLEN, OI_NONE }, +#define O_CONTROLSOCKET 0xa9 + { "ControlSocketName", O_CONTROLSOCKET, OI_NONE }, +#define O_MAXHDRSLEN 0xaa + { "MaxHeadersLength", O_MAXHDRSLEN, OI_NONE }, +#if _FFR_MAX_FORWARD_ENTRIES +# define O_MAXFORWARD 0xab + { "MaxForwardEntries", O_MAXFORWARD, OI_NONE }, +#endif /* _FFR_MAX_FORWARD_ENTRIES */ +#define O_PROCTITLEPREFIX 0xac + { "ProcessTitlePrefix", O_PROCTITLEPREFIX, OI_NONE }, +#define O_SASLINFO 0xad +#if _FFR_ALLOW_SASLINFO + { "DefaultAuthInfo", O_SASLINFO, OI_SAFE }, +#else /* _FFR_ALLOW_SASLINFO */ + { "DefaultAuthInfo", O_SASLINFO, OI_NONE }, +#endif /* _FFR_ALLOW_SASLINFO */ +#define O_SASLMECH 0xae + { "AuthMechanisms", O_SASLMECH, OI_NONE }, +#define O_CLIENTPORT 0xaf + { "ClientPortOptions", O_CLIENTPORT, OI_NONE }, +#define O_DF_BUFSIZE 0xb0 + { "DataFileBufferSize", O_DF_BUFSIZE, OI_NONE }, +#define O_XF_BUFSIZE 0xb1 + { "XscriptFileBufferSize", O_XF_BUFSIZE, OI_NONE }, +# define O_LDAPDEFAULTSPEC 0xb2 + { "LDAPDefaultSpec", O_LDAPDEFAULTSPEC, OI_NONE }, +#if _FFR_QUEUEDELAY +#define O_QUEUEDELAY 0xb3 + { "QueueDelay", O_QUEUEDELAY, OI_NONE }, +#endif /* _FFR_QUEUEDELAY */ +#if _FFR_MILTER +#define O_INPUTMILTER 0xbb + { "InputMailFilters", O_INPUTMILTER, OI_NONE }, +#define O_MILTER 0xbc + { "Milter", O_MILTER, OI_SUBOPT }, +#endif /* _FFR_MILTER */ +#define O_SASLOPTS 0xbd + { "AuthOptions", O_SASLOPTS, OI_NONE }, +#if _FFR_QUEUE_FILE_MODE +#define O_QUEUE_FILE_MODE 0xbe + { "QueueFileMode", O_QUEUE_FILE_MODE, OI_NONE }, +#endif /* _FFR_QUEUE_FILE_MODE */ + { NULL, '\0', OI_NONE } +}; + +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; + int mid; + bool can_setuid = RunAsUid == 0; + auto char *ep; + char buf[50]; + extern bool Warn_Q_option; +#if _FFR_ALLOW_SASLINFO + extern int SubmitMode; +#endif /* _FFR_ALLOW_SASLINFO */ + + 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)) + { + int oldVerbose = Verbose; + + Verbose = 1; + 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 (subopt != NULL && !bitset(OI_SUBOPT, o->o_flags)) + { + if (tTd(37, 1)) + dprintf("setoption: %s does not support suboptions, ignoring .%s\n", + o->o_name == NULL ? "" : o->o_name, + subopt); + subopt = NULL; + } + + if (tTd(37, 1)) + { + dprintf(isascii(opt) && isprint(opt) ? + "setoption %s (%c)%s%s=" : + "setoption %s (0x%x)%s%s=", + o->o_name == NULL ? "" : o->o_name, + opt, + subopt == NULL ? "" : ".", + subopt == NULL ? "" : subopt); + xputs(val); + } + + /* + ** See if this option is preset for us. + */ + + if (!sticky && bitnset(opt, StickyOpt)) + { + if (tTd(37, 1)) + dprintf(" (ignored)\n"); + return; + } + + /* + ** Check to see if this option can be specified by this user. + */ + + if (!safe && RealUid == 0) + safe = TRUE; + if (!safe && !bitset(OI_SAFE, o->o_flags)) + { + if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) + { + if (tTd(37, 1)) + dprintf(" (unsafe)"); + (void) drop_privileges(TRUE); + } + } + if (tTd(37, 1)) + dprintf("\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 /* 0 */ + + default: + syserr("Unknown 8-bit mode %c", *val); + finis(FALSE, EX_USAGE); + } + break; +#endif /* MIME8TO7 */ + + 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': + set_delivery_mode(SM_DELIVER, e); + break; + + case SM_QUEUE: /* queue only */ + case SM_DEFER: /* queue only and defer map lookups */ +#if !QUEUE + syserr("need QUEUE to set -odqueue or -oddefer"); +#endif /* !QUEUE */ + /* FALLTHROUGH */ + + case SM_DELIVER: /* do everything */ + case SM_FORK: /* fork after verification */ + set_delivery_mode(*val, e); + break; + + default: + syserr("Unknown delivery mode %c", *val); + finis(FALSE, EX_USAGE); + } + break; + +#if !_FFR_REMOVE_AUTOREBUILD + case 'D': /* rebuild alias database as needed */ + AutoRebuild = atobool(val); + break; +#endif /* !_FFR_REMOVE_AUTOREBUILD */ + + 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 = "helpfile"; + 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)) + dprintf("_res.options = %x, HasWildcardMX = %d\n", + (u_int) _res.options, HasWildcardMX); +#else /* NAMED_BIND */ + usrerr("name server (I option) specified but BIND not compiled in"); +#endif /* NAMED_BIND */ + 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 */ + mid = macid(val, &ep); + p = newstr(ep); + if (!safe) + cleanstrcpy(p, p, MAXNAME); + define(mid, 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 */ +#if DAEMON + if (!setdaemonoptions(val)) + { + syserr("too many daemons defined (%d max)", MAXDAEMONS); + } +#else /* DAEMON */ + syserr("DaemonPortOptions (O option) set but DAEMON not compiled in"); +#endif /* DAEMON */ + 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, sticky); + else + settimeout(subopt, val, sticky); + break; + + case 'S': /* status file */ + if (val[0] == '\0') + StatFile = "statistics"; + 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, sticky); + } + settimeout("queuereturn", val, sticky); + 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); + setdefuser(); + } + 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; + DefUser = newstr(pw->pw_name); + } + } + +#ifdef UID_MAX + if (DefUid > UID_MAX) + { + syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored", + DefUid, UID_MAX); + } +#endif /* UID_MAX */ + + /* handle the group if it is there */ + if (*p == '\0') + break; + val = p; + goto g_opt; + + case 'V': /* fallback MX host */ + if (val[0] != '\0') + FallBackMX = newstr(val); + break; + + case 'v': /* run in verbose mode */ + Verbose = atobool(val) ? 1 : 0; + 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 = QSO_BYHOST; + break; + + case 'p': /* Priority order */ + case 'P': + QueueSortOrder = QSO_BYPRIORITY; + break; + + case 't': /* Submission time */ + case 'T': + QueueSortOrder = QSO_BYTIME; + break; + + case 'f': /* File Name */ + case 'F': + QueueSortOrder = QSO_BYFILENAME; + break; + + default: + syserr("Invalid queue sort order \"%s\"", val); + } + break; + +#if _FFR_QUEUEDELAY + case O_QUEUEDELAY: /* queue delay algorithm */ + switch (*val) + { + case 'e': /* exponential */ + case 'E': + QueueAlg = QD_EXP; + QueueInitDelay = 10 MINUTES; + QueueMaxDelay = 2 HOURS; + p = strchr(val, '/'); + if (p != NULL) + { + char *q; + + *p++ = '\0'; + q = strchr(p, '/'); + if (q != NULL) + *q++ = '\0'; + QueueInitDelay = convtime(p, 's'); + if (q != NULL) + { + QueueMaxDelay = convtime(q, 's'); + } + } + break; + + case 'l': /* linear */ + case 'L': + QueueAlg = QD_LINEAR; + break; + + default: + syserr("Invalid queue delay algorithm \"%s\"", val); + } + break; +#endif /* _FFR_QUEUEDELAY */ + + 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_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; + +#if _FFR_MAX_FORWARD_ENTRIES + case O_MAXFORWARD: /* max # of forward entries */ + MaxForwardEntries = atoi(val); + break; +#endif /* _FFR_MAX_FORWARD_ENTRIES */ + + case O_KEEPCNAMES: /* don't expand CNAME records */ + DontExpandCnames = atobool(val); + break; + + case O_MUSTQUOTE: /* must quote these characters in phrases */ + (void) strlcpy(buf, "@,;:\\()[]", sizeof buf); + if (strlen(val) < (SIZE_T) sizeof buf - 10) + (void) strlcat(buf, val, sizeof buf); + else + printf("Warning: MustQuoteChars too long, ignored.\n"); + MustQuoteChars = newstr(buf); + break; + + case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ + SmtpGreeting = newstr(munchstring(val, NULL, '\0')); + break; + + case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ + UnixFromLine = newstr(munchstring(val, NULL, '\0')); + break; + + case O_OPCHARS: /* operator characters (old $o macro) */ + if (OperatorChars != NULL) + printf("Warning: OperatorChars is being redefined.\n It should only be set before ruleset definitions.\n"); + OperatorChars = newstr(munchstring(val, NULL, '\0')); + 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; + + case O_ABH: /* allow HELO commands with syntax errors */ + AllowBogusHELO = atobool(val); + break; + + case O_CONNTHROT: /* connection rate throttle */ + ConnRateThrottle = atoi(val); + break; + + case O_UGW: /* group writable files are unsafe */ + if (!atobool(val)) + { + setbitn(DBS_GROUPWRITABLEFORWARDFILESAFE, + DontBlameSendmail); + setbitn(DBS_GROUPWRITABLEINCLUDEFILESAFE, + DontBlameSendmail); + } + break; + + case O_DBLBOUNCE: /* address to which to send double bounces */ + if (val[0] != '\0') + DoubleBounceAddr = newstr(val); + else + syserr("readcf: option DoubleBounceAddress: value required"); + break; + + case O_HSDIR: /* persistent host status directory */ + if (val[0] != '\0') + HostStatDir = newstr(val); + break; + + case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */ + SingleThreadDelivery = atobool(val); + break; + + case O_RUNASUSER: /* run bulk of code as this user */ + for (p = val; *p != '\0'; p++) + { + if (*p == '.' || *p == '/' || *p == ':') + { + *p++ = '\0'; + break; + } + } + if (isascii(*val) && isdigit(*val)) + { + if (can_setuid) + RunAsUid = atoi(val); + } + else + { + register struct passwd *pw; + + pw = sm_getpwnam(val); + if (pw == NULL) + syserr("readcf: option RunAsUser: unknown user %s", val); + else if (can_setuid) + { + if (*p == '\0') + RunAsUserName = newstr(val); + RunAsUid = pw->pw_uid; + RunAsGid = pw->pw_gid; + } + } +#ifdef UID_MAX + if (RunAsUid > UID_MAX) + { + syserr("readcf: option RunAsUser: uid value (%ld) > UID_MAX (%ld); ignored", + RunAsUid, UID_MAX); + } +#endif /* UID_MAX */ + if (*p != '\0') + { + if (isascii(*p) && isdigit(*p)) + { + if (can_setuid) + RunAsGid = atoi(p); + } + else + { + register struct group *gr; + + gr = getgrnam(p); + if (gr == NULL) + syserr("readcf: option RunAsUser: unknown group %s", + p); + else if (can_setuid) + RunAsGid = gr->gr_gid; + } + } + if (tTd(47, 5)) + dprintf("readcf: RunAsUser = %d:%d\n", + (int)RunAsUid, (int)RunAsGid); + break; + + case O_DSN_RRT: + RrtImpliesDsn = atobool(val); + break; + + case O_PIDFILE: + if (PidFile != NULL) + free(PidFile); + PidFile = newstr(val); + break; + + case O_DONTBLAMESENDMAIL: + p = val; + for (;;) + { + register struct dbsval *dbs; + extern struct dbsval DontBlameSendmailValues[]; + + 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 (dbs = DontBlameSendmailValues; + dbs->dbs_name != NULL; dbs++) + { + if (strcasecmp(val, dbs->dbs_name) == 0) + break; + } + if (dbs->dbs_name == NULL) + syserr("readcf: DontBlameSendmail option: %s unrecognized", val); + else if (dbs->dbs_flag == DBS_SAFE) + clrbitmap(DontBlameSendmail); + else + setbitn(dbs->dbs_flag, DontBlameSendmail); + } + sticky = FALSE; + break; + + case O_DPI: + DontProbeInterfaces = atobool(val); + break; + + case O_MAXRCPT: + MaxRcptPerMsg = atoi(val); + break; + + case O_DEADLETTER: + if (DeadLetterDrop != NULL) + free(DeadLetterDrop); + DeadLetterDrop = newstr(val); + break; + +#if _FFR_DONTLOCKFILESFORREAD_OPTION + case O_DONTLOCK: + DontLockReadFiles = atobool(val); + break; +#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ + + case O_MAXALIASRCSN: + MaxAliasRecursion = atoi(val); + break; + + case O_CNCTONLYTO: + /* XXX should probably use gethostbyname */ +#if NETINET || NETINET6 +# if NETINET6 + if (inet_addr(val) == INADDR_NONE) + { + ConnectOnlyTo.sa.sa_family = AF_INET6; + if (inet_pton(AF_INET6, val, + &ConnectOnlyTo.sin6.sin6_addr) != 1) + syserr("readcf: option ConnectOnlyTo: invalid IP address %s", + val); + } + else +# endif /* NETINET6 */ + { + ConnectOnlyTo.sa.sa_family = AF_INET; + ConnectOnlyTo.sin.sin_addr.s_addr = inet_addr(val); + } +#endif /* NETINET || NETINET6 */ + break; + + case O_TRUSTUSER: +#if HASFCHOWN + if (isascii(*val) && isdigit(*val)) + TrustedUid = atoi(val); + else + { + register struct passwd *pw; + + TrustedUid = 0; + pw = sm_getpwnam(val); + if (pw == NULL) + syserr("readcf: option TrustedUser: unknown user %s", val); + else + TrustedUid = pw->pw_uid; + } + +# ifdef UID_MAX + if (TrustedUid > UID_MAX) + { + syserr("readcf: option TrustedUser: uid value (%ld) > UID_MAX (%ld)", + TrustedUid, UID_MAX); + TrustedUid = 0; + } +# endif /* UID_MAX */ +#else /* HASFCHOWN */ + syserr("readcf: option TrustedUser: can not be used on systems which do not support fchown()"); +#endif /* HASFCHOWN */ + break; + + case O_MAXMIMEHDRLEN: + p = strchr(val, '/'); + if (p != NULL) + *p++ = '\0'; + MaxMimeHeaderLength = atoi(val); + if (p != NULL && *p != '\0') + MaxMimeFieldLength = atoi(p); + else + MaxMimeFieldLength = MaxMimeHeaderLength / 2; + + if (MaxMimeHeaderLength < 0) + MaxMimeHeaderLength = 0; + else if (MaxMimeHeaderLength < 128) + printf("Warning: MaxMimeHeaderLength: header length limit set lower than 128\n"); + + if (MaxMimeFieldLength < 0) + MaxMimeFieldLength = 0; + else if (MaxMimeFieldLength < 40) + printf("Warning: MaxMimeHeaderLength: field length limit set lower than 40\n"); + break; + + case O_CONTROLSOCKET: + if (ControlSocketName != NULL) + free(ControlSocketName); + ControlSocketName = newstr(val); + break; + + case O_MAXHDRSLEN: + MaxHeadersLength = atoi(val); + + if (MaxHeadersLength > 0 && + MaxHeadersLength < (MAXHDRSLEN / 2)) + printf("Warning: MaxHeadersLength: headers length limit set lower than %d\n", (MAXHDRSLEN / 2)); + break; + + case O_PROCTITLEPREFIX: + if (ProcTitlePrefix != NULL) + free(ProcTitlePrefix); + ProcTitlePrefix = newstr(val); + break; + +#if SASL + case O_SASLINFO: +#if _FFR_ALLOW_SASLINFO + /* + ** Allow users to select their own authinfo file. + ** However, this is not a "perfect" solution. + ** If mail is queued, the authentication info + ** will not be used in subsequent delivery attempts. + ** If we really want to support this, then it has + ** to be stored in the queue file. + */ + if (!bitset(SUBMIT_MSA, SubmitMode) && RealUid != 0 && + RunAsUid != RealUid) + { + errno = 0; + syserr("Error: %s only allowed with -U\n", + o->o_name == NULL ? "" : o->o_name); + ExitStat = EX_USAGE; + break; + } +#endif /* _FFR_ALLOW_SASLINFO */ + if (SASLInfo != NULL) + free(SASLInfo); + SASLInfo = newstr(val); + break; + + case O_SASLMECH: + if (AuthMechanisms != NULL) + free(AuthMechanisms); + if (*val != '\0') + AuthMechanisms = newstr(val); + else + AuthMechanisms = NULL; + break; + + case O_SASLOPTS: + if (*val == '\0') + { + printf("Warning: Option: %s requires parameter(s)\n", + o->o_name == NULL ? "" : o->o_name); + break; + } + if (*val == 'A' || *val == 'a') + SASLTryAuth = SASL_AUTH_AUTH; + else + printf("Warning: Option: %s unknown parameter '%c'\n", + o->o_name == NULL ? "" : o->o_name, + (isascii(*val) && isprint(*val)) ? *val : '?'); + break; + +#else /* SASL */ + case O_SASLINFO: + case O_SASLMECH: + case O_SASLOPTS: + printf("Warning: Option: %s requires SASL support (-DSASL)\n", + o->o_name == NULL ? "" : o->o_name); + break; +#endif /* SASL */ + + + case O_CLIENTPORT: +#if DAEMON + setclientoptions(val); +#else /* DAEMON */ + syserr("ClientPortOptions (O option) set but DAEMON not compiled in"); +#endif /* DAEMON */ + break; + + case O_DF_BUFSIZE: + DataFileBufferSize = atoi(val); + break; + + case O_XF_BUFSIZE: + XscriptFileBufferSize = atoi(val); + break; + + case O_LDAPDEFAULTSPEC: +#ifdef LDAPMAP + ldapmap_set_defaults(val); +#else /* LDAPMAP */ + printf("Warning: Option: %s requires LDAP support (-DLDAPMAP)\n", + o->o_name == NULL ? "" : o->o_name); +#endif /* LDAPMAP */ + break; + +#if _FFR_MILTER + case O_INPUTMILTER: + InputFilterList = newstr(val); + break; + + case O_MILTER: + milter_set_option(subopt, val, sticky); + break; +#endif /* _FFR_MILTER */ + +#if _FFR_QUEUE_FILE_MODE + case O_QUEUE_FILE_MODE: /* queue file mode */ + QueueFileMode = atooct(val) & 0777; + break; +#endif /* _FFR_QUEUE_FILE_MODE */ + + default: + if (tTd(37, 1)) + { + if (isascii(opt) && isprint(opt)) + dprintf("Warning: option %c unknown\n", opt); + else + dprintf("Warning: option 0x%x unknown\n", opt); + } + break; + } + + /* + ** Options with suboptions are responsible for taking care + ** of sticky-ness (e.g., that a command line setting is kept + ** when reading in the sendmail.cf file). This has to be done + ** when the suboptions are parsed since each suboption must be + ** sticky, not the root option. + */ + + if (sticky && !bitset(OI_SUBOPT, o->o_flags)) + 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 ((*str & 0377) == MATCHCLASS) + { + int mid; + + str++; + mid = macid(str, NULL); + if (mid == '\0') + return; + + if (tTd(37, 8)) + dprintf("setclass(%s, $=%s)\n", + macname(class), macname(mid)); + copy_class(mid, class); + } + else + { + if (tTd(37, 8)) + dprintf("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)) + { + dprintf("map %s, class %s, flags %lx, 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); + dprintf("\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 = NULL; + + q = p; + while (*p != '\0' && isascii(*p) && + (isalnum(*p) || *p == '_')) + p++; + if (q == p || !(isascii(*q) && 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) + return -1; + + if (stabmode == ST_ENTER && delim == '=') + { + while (isascii(*++p) && isspace(*p)) + continue; + if (!(isascii(*p) && 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, s->s_ruleset, ruleset); + ruleset = s->s_ruleset; + } + else if (ruleset >= 0) + { + s->s_ruleset = ruleset; + } + if (stabmode == ST_ENTER) + { + char *h = NULL; + + if (RuleSetNames[ruleset] != NULL) + free(RuleSetNames[ruleset]); + if (delim != '\0' && (h = strchr(q, delim)) != NULL) + *h = '\0'; + RuleSetNames[ruleset] = newstr(q); + if (delim == '/' && h != NULL) + *h = delim; /* put back delim */ + } + } + return ruleset; +} + /* +** SETTIMEOUT -- set an individual timeout +** +** Parameters: +** name -- the name of the timeout. +** val -- the value of the timeout. +** sticky -- if set, don't let other setoptions override +** this value. +** +** Returns: +** none. +*/ + +/* set if Timeout sub-option is stuck */ +static BITMAP256 StickyTimeoutOpt; + +static struct timeoutinfo +{ + char *to_name; /* long name of timeout */ + u_char to_code; /* code for option */ +} TimeOutTab[] = +{ +#define TO_INITIAL 0x01 + { "initial", TO_INITIAL }, +#define TO_MAIL 0x02 + { "mail", TO_MAIL }, +#define TO_RCPT 0x03 + { "rcpt", TO_RCPT }, +#define TO_DATAINIT 0x04 + { "datainit", TO_DATAINIT }, +#define TO_DATABLOCK 0x05 + { "datablock", TO_DATABLOCK }, +#define TO_DATAFINAL 0x06 + { "datafinal", TO_DATAFINAL }, +#define TO_COMMAND 0x07 + { "command", TO_COMMAND }, +#define TO_RSET 0x08 + { "rset", TO_RSET }, +#define TO_HELO 0x09 + { "helo", TO_HELO }, +#define TO_QUIT 0x0A + { "quit", TO_QUIT }, +#define TO_MISC 0x0B + { "misc", TO_MISC }, +#define TO_IDENT 0x0C + { "ident", TO_IDENT }, +#define TO_FILEOPEN 0x0D + { "fileopen", TO_FILEOPEN }, +#define TO_CONNECT 0x0E + { "connect", TO_CONNECT }, +#define TO_ICONNECT 0x0F + { "iconnect", TO_ICONNECT }, +#define TO_QUEUEWARN 0x10 + { "queuewarn", TO_QUEUEWARN }, + { "queuewarn.*", TO_QUEUEWARN }, +#define TO_QUEUEWARN_NORMAL 0x11 + { "queuewarn.normal", TO_QUEUEWARN_NORMAL }, +#define TO_QUEUEWARN_URGENT 0x12 + { "queuewarn.urgent", TO_QUEUEWARN_URGENT }, +#define TO_QUEUEWARN_NON_URGENT 0x13 + { "queuewarn.non-urgent", TO_QUEUEWARN_NON_URGENT }, +#define TO_QUEUERETURN 0x14 + { "queuereturn", TO_QUEUERETURN }, + { "queuereturn.*", TO_QUEUERETURN }, +#define TO_QUEUERETURN_NORMAL 0x15 + { "queuereturn.normal", TO_QUEUERETURN_NORMAL }, +#define TO_QUEUERETURN_URGENT 0x16 + { "queuereturn.urgent", TO_QUEUERETURN_URGENT }, +#define TO_QUEUERETURN_NON_URGENT 0x17 + { "queuereturn.non-urgent", TO_QUEUERETURN_NON_URGENT }, +#define TO_HOSTSTATUS 0x18 + { "hoststatus", TO_HOSTSTATUS }, +#define TO_RESOLVER_RETRANS 0x19 + { "resolver.retrans", TO_RESOLVER_RETRANS }, +#define TO_RESOLVER_RETRANS_NORMAL 0x1A + { "resolver.retrans.normal", TO_RESOLVER_RETRANS_NORMAL }, +#define TO_RESOLVER_RETRANS_FIRST 0x1B + { "resolver.retrans.first", TO_RESOLVER_RETRANS_FIRST }, +#define TO_RESOLVER_RETRY 0x1C + { "resolver.retry", TO_RESOLVER_RETRY }, +#define TO_RESOLVER_RETRY_NORMAL 0x1D + { "resolver.retry.normal", TO_RESOLVER_RETRY_NORMAL }, +#define TO_RESOLVER_RETRY_FIRST 0x1E + { "resolver.retry.first", TO_RESOLVER_RETRY_FIRST }, +#define TO_CONTROL 0x1F + { "control", TO_CONTROL }, + { NULL, 0 }, +}; + + +static void +settimeout(name, val, sticky) + char *name; + char *val; + bool sticky; +{ + register struct timeoutinfo *to; + int i; + time_t toval; + + if (tTd(37, 2)) + dprintf("settimeout(%s = %s)", name, val); + + for (to = TimeOutTab; to->to_name != NULL; to++) + { + if (strcasecmp(to->to_name, name) == 0) + break; + } + + if (to->to_name == NULL) + syserr("settimeout: invalid timeout %s", name); + + /* + ** See if this option is preset for us. + */ + + if (!sticky && bitnset(to->to_code, StickyTimeoutOpt)) + { + if (tTd(37, 2)) + dprintf(" (ignored)\n"); + return; + } + + if (tTd(37, 2)) + dprintf("\n"); + + toval = convtime(val, 'm'); + + switch (to->to_code) + { + case TO_INITIAL: + TimeOuts.to_initial = toval; + break; + + case TO_MAIL: + TimeOuts.to_mail = toval; + break; + + case TO_RCPT: + TimeOuts.to_rcpt = toval; + break; + + case TO_DATAINIT: + TimeOuts.to_datainit = toval; + break; + + case TO_DATABLOCK: + TimeOuts.to_datablock = toval; + break; + + case TO_DATAFINAL: + TimeOuts.to_datafinal = toval; + break; + + case TO_COMMAND: + TimeOuts.to_nextcommand = toval; + break; + + case TO_RSET: + TimeOuts.to_rset = toval; + break; + + case TO_HELO: + TimeOuts.to_helo = toval; + break; + + case TO_QUIT: + TimeOuts.to_quit = toval; + break; + + case TO_MISC: + TimeOuts.to_miscshort = toval; + break; + + case TO_IDENT: + TimeOuts.to_ident = toval; + break; + + case TO_FILEOPEN: + TimeOuts.to_fileopen = toval; + break; + + case TO_CONNECT: + TimeOuts.to_connect = toval; + break; + + case TO_ICONNECT: + TimeOuts.to_iconnect = toval; + break; + + case TO_QUEUEWARN: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NORMAL] = toval; + TimeOuts.to_q_warning[TOC_URGENT] = toval; + TimeOuts.to_q_warning[TOC_NONURGENT] = toval; + break; + + case TO_QUEUEWARN_NORMAL: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NORMAL] = toval; + break; + + case TO_QUEUEWARN_URGENT: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_URGENT] = toval; + break; + + case TO_QUEUEWARN_NON_URGENT: + toval = convtime(val, 'h'); + TimeOuts.to_q_warning[TOC_NONURGENT] = toval; + break; + + case TO_QUEUERETURN: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NORMAL] = toval; + TimeOuts.to_q_return[TOC_URGENT] = toval; + TimeOuts.to_q_return[TOC_NONURGENT] = toval; + break; + + case TO_QUEUERETURN_NORMAL: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NORMAL] = toval; + break; + + case TO_QUEUERETURN_URGENT: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_URGENT] = toval; + break; + + case TO_QUEUERETURN_NON_URGENT: + toval = convtime(val, 'd'); + TimeOuts.to_q_return[TOC_NONURGENT] = toval; + break; + + + case TO_HOSTSTATUS: + MciInfoTimeout = toval; + break; + + case TO_RESOLVER_RETRANS: + toval = convtime(val, 's'); + TimeOuts.res_retrans[RES_TO_DEFAULT] = toval; + TimeOuts.res_retrans[RES_TO_FIRST] = toval; + TimeOuts.res_retrans[RES_TO_NORMAL] = toval; + break; + + case TO_RESOLVER_RETRY: + i = atoi(val); + TimeOuts.res_retry[RES_TO_DEFAULT] = i; + TimeOuts.res_retry[RES_TO_FIRST] = i; + TimeOuts.res_retry[RES_TO_NORMAL] = i; + break; + + case TO_RESOLVER_RETRANS_NORMAL: + TimeOuts.res_retrans[RES_TO_NORMAL] = convtime(val, 's'); + break; + + case TO_RESOLVER_RETRY_NORMAL: + TimeOuts.res_retry[RES_TO_NORMAL] = atoi(val); + break; + + case TO_RESOLVER_RETRANS_FIRST: + TimeOuts.res_retrans[RES_TO_FIRST] = convtime(val, 's'); + break; + + case TO_RESOLVER_RETRY_FIRST: + TimeOuts.res_retry[RES_TO_FIRST] = atoi(val); + break; + + case TO_CONTROL: + TimeOuts.to_control = toval; + break; + + default: + syserr("settimeout: invalid timeout %s", name); + break; + } + + if (sticky) + setbitn(to->to_code, StickyTimeoutOpt); +} + /* +** INITTIMEOUTS -- parse and set timeout values +** +** Parameters: +** val -- a pointer to the values. If NULL, do initial +** settings. +** sticky -- if set, don't let other setoptions override +** this suboption value. +** +** Returns: +** none. +** +** Side Effects: +** Initializes the TimeOuts structure +*/ + +void +inittimeouts(val, sticky) + register char *val; + bool sticky; +{ + register char *p; + + if (tTd(37, 2)) + dprintf("inittimeouts(%s)\n", val == NULL ? "" : val); + 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) 5 SECONDS; +#else /* IDENTPROTO */ + TimeOuts.to_ident = (time_t) 0 SECONDS; +#endif /* IDENTPROTO */ + TimeOuts.to_fileopen = (time_t) 60 SECONDS; + TimeOuts.to_control = (time_t) 2 MINUTES; + if (tTd(37, 5)) + { + dprintf("Timeouts:\n"); + dprintf(" connect = %ld\n", (long)TimeOuts.to_connect); + dprintf(" initial = %ld\n", (long)TimeOuts.to_initial); + dprintf(" helo = %ld\n", (long)TimeOuts.to_helo); + dprintf(" mail = %ld\n", (long)TimeOuts.to_mail); + dprintf(" rcpt = %ld\n", (long)TimeOuts.to_rcpt); + dprintf(" datainit = %ld\n", (long)TimeOuts.to_datainit); + dprintf(" datablock = %ld\n", (long)TimeOuts.to_datablock); + dprintf(" datafinal = %ld\n", (long)TimeOuts.to_datafinal); + dprintf(" rset = %ld\n", (long)TimeOuts.to_rset); + dprintf(" quit = %ld\n", (long)TimeOuts.to_quit); + dprintf(" nextcommand = %ld\n", (long)TimeOuts.to_nextcommand); + dprintf(" miscshort = %ld\n", (long)TimeOuts.to_miscshort); + dprintf(" ident = %ld\n", (long)TimeOuts.to_ident); + dprintf(" fileopen = %ld\n", (long)TimeOuts.to_fileopen); + dprintf(" control = %ld\n", (long)TimeOuts.to_control); + } + 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; + if (sticky) + { + setbitn(TO_MAIL, StickyTimeoutOpt); + setbitn(TO_RCPT, StickyTimeoutOpt); + setbitn(TO_DATAINIT, StickyTimeoutOpt); + setbitn(TO_DATABLOCK, StickyTimeoutOpt); + setbitn(TO_DATAFINAL, StickyTimeoutOpt); + setbitn(TO_COMMAND, StickyTimeoutOpt); + } + continue; + } + else + { + register char *q = strchr(val, ':'); + + if (q == NULL && (q = strchr(val, '=')) == NULL) + { + /* syntax error */ + continue; + } + *q++ = '\0'; + settimeout(val, q, sticky); + } + } +} diff --git a/gnu/usr.sbin/sendmail/sendmail/recipient.c b/gnu/usr.sbin/sendmail/sendmail/recipient.c new file mode 100644 index 00000000000..3b76511a973 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/recipient.c @@ -0,0 +1,1673 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: recipient.c,v 8.231 2000/01/05 01:40:53 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +static void includetimeout __P((void)); +static ADDRESS *self_reference __P((ADDRESS *)); + +/* +** 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 */ + 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)) + { + dprintf("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 = ','; + + al = NULL; + naddrs = 0; + + /* make sure we have enough space to copy the string */ + i = strlen(list) + 1; + if (i <= sizeof buf) + { + bufp = buf; + i = sizeof buf; + } + else + bufp = xalloc(i); + (void) strlcpy(bufp, denlstring(list, FALSE, TRUE), i); + +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e r", e); +#endif /* _FFR_ADDR_TYPE */ + 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; + + /* self reference test */ + if (sameaddr(ctladdr, a)) + { + if (tTd(27, 5)) + { + dprintf("sendtolist: QSELFREF "); + printaddr(ctladdr, FALSE); + } + ctladdr->q_flags |= QSELFREF; + } + + /* check for address loops */ + b = self_reference(a); + if (b != NULL) + { + b->q_flags |= QSELFREF; + if (tTd(27, 5)) + { + dprintf("sendtolist: QSELFREF "); + printaddr(b, FALSE); + } + if (a != b) + { + if (tTd(27, 5)) + { + dprintf("sendtolist: QS_DONTSEND "); + printaddr(a, FALSE); + } + a->q_state = QS_DONTSEND; + 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; + } + + /* 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); +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), NULL, e); +#endif /* _FFR_ADDR_TYPE */ + return naddrs; +} + /* +** REMOVEFROMLIST -- Remove addresses from a send list. +** +** The parameter is a comma-separated list of recipients to remove. +** Note that it only deletes matching addresses. If those addresses +** have been expended already in the sendq, it won't mark the +** expanded recipients as QS_REMOVED. +** +** Parameters: +** list -- the list to remove. +** sendq -- a pointer to the head of a queue to remove +** these addresses from. +** e -- the envelope in which to remove these recipients. +** +** Returns: +** The number of addresses removed from the list. +** +*/ + +int +removefromlist(list, sendq, e) + char *list; + ADDRESS **sendq; + ENVELOPE *e; +{ + char delimiter; /* the address delimiter */ + int naddrs; + int i; + char *p; + char *oldto = e->e_to; + char *bufp; + char buf[MAXNAME + 1]; + + if (list == NULL) + { + syserr("removefromlist: null list"); + return 0; + } + + if (tTd(25, 1)) + dprintf("removefromlist: %s\n", list); + + /* heuristic to determine old versus new style addresses */ + if (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)) + delimiter = ','; + + naddrs = 0; + + /* make sure we have enough space to copy the string */ + i = strlen(list) + 1; + if (i <= sizeof buf) + { + bufp = buf; + i = sizeof buf; + } + else + bufp = xalloc(i); + (void) strlcpy(bufp, denlstring(list, FALSE, TRUE), i); + +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e r", e); +#endif /* _FFR_ADDR_TYPE */ + for (p = bufp; *p != '\0'; ) + { + ADDRESS a; /* parsed address to be removed */ + ADDRESS *q; + ADDRESS **pq; + char *delimptr; + + /* parse the address */ + while ((isascii(*p) && isspace(*p)) || *p == ',') + p++; + if (parseaddr(p, &a, RF_COPYALL, + delimiter, &delimptr, e) == NULL) + { + p = delimptr; + continue; + } + p = delimptr; + for (pq = sendq; (q = *pq) != NULL; pq = &q->q_next) + { + if (!QS_IS_DEAD(q->q_state) && + sameaddr(q, &a)) + { + if (tTd(25, 5)) + { + dprintf("removefromlist: QS_REMOVED "); + printaddr(&a, FALSE); + } + q->q_state = QS_REMOVED; + naddrs++; + break; + } + } + } + + e->e_to = oldto; + if (bufp != buf) + free(bufp); +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), NULL, e); +#endif /* _FFR_ADDR_TYPE */ + 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 suppression 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 = NULL; + bool quoted = FALSE; /* set if the addr has a quote bit */ + int findusercount = 0; + bool initialdontsend = QS_IS_DEAD(a->q_state); + int i, buflen; + char *buf; + char buf0[MAXNAME + 1]; /* unquoted image of the user name */ + + e->e_to = a->q_paddr; + m = a->q_mailer; + errno = 0; + if (aliaslevel == 0) + a->q_flags |= QPRIMARY; + if (tTd(26, 1)) + { + dprintf("\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 = ""; + } + +#if _FFR_GEN_ORCPT + /* set ORCPT DSN arg if not already set */ + if (a->q_orcpt == NULL) + { + for (q = a; q->q_alias != NULL; q = q->q_alias) + continue; + + /* check for an existing ORCPT */ + if (q->q_orcpt != NULL) + a->q_orcpt = q->q_orcpt; + else + { + /* make our own */ + bool b = FALSE; + char *qp; + char obuf[MAXLINE]; + + if (e->e_from.q_mailer != NULL) + p = e->e_from.q_mailer->m_addrtype; + if (p == NULL) + p = "rfc822"; + (void) strlcpy(obuf, p, sizeof obuf); + (void) strlcat(obuf, ";", sizeof obuf); + + qp = q->q_paddr; + + /* FFR: Needs to strip comments from stdin addrs */ + + /* strip brackets from address */ + if (*qp == '<') + { + b = qp[strlen(qp) - 1] == '>'; + if (b) + qp[strlen(qp) - 1] = '\0'; + qp++; + } + + p = xtextify(denlstring(qp, TRUE, FALSE), NULL); + + if (strlcat(obuf, p, sizeof obuf) >= sizeof obuf) + { + /* if too big, don't use it */ + obuf[0] = '\0'; + } + + /* undo damage */ + if (b) + qp[strlen(qp)] = '>'; + + if (obuf[0] != '\0') + a->q_orcpt = newstr(obuf); + } + } +#endif /* _FFR_GEN_ORCPT */ + + /* break aliasing loops */ + if (aliaslevel > MaxAliasRecursion) + { + a->q_state = QS_BADADDR; + a->q_status = "5.4.6"; + usrerrenh(a->q_status, + "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) + { + buflen = i + 1; + buf = xalloc(buflen); + } + else + { + buf = buf0; + buflen = sizeof buf0; + } + (void) strlcpy(buf, a->q_user, buflen); + 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_state = QS_BADADDR; + a->q_status = "5.7.1"; + usrerrenh(a->q_status, + "550 Cannot mail directly to programs"); + } + else if (bitset(QBOGUSSHELL, a->q_alias->q_flags)) + { + a->q_state = QS_BADADDR; + a->q_status = "5.7.1"; + if (a->q_alias->q_ruser == NULL) + usrerrenh(a->q_status, + "550 UID %d is an unknown user: cannot mail to programs", + a->q_alias->q_uid); + else + usrerrenh(a->q_status, + "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_state = QS_BADADDR; + a->q_status = "5.7.1"; + a->q_rstatus = newstr("550 Unsafe for mailing to programs"); + usrerrenh(a->q_status, + "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 QS_DUPLICATE state 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) && + (bitset(QRCPTOK, q->q_flags) || + !bitset(QPRIMARY, q->q_flags))) + { + if (tTd(26, 1)) + { + dprintf("%s in sendq: ", a->q_paddr); + printaddr(q, FALSE); + } + if (!bitset(QPRIMARY, q->q_flags)) + { + if (!QS_IS_DEAD(a->q_state)) + message("duplicate suppressed"); + else + q->q_state = QS_DUPLICATE; + q->q_flags |= a->q_flags; + } + else if (bitset(QSELFREF, q->q_flags)) + { + q->q_state = a->q_state; + q->q_flags |= a->q_flags; + } + a = q; + goto done; + } + } + + /* add address on list */ + if (pq != NULL) + { + *pq = a; + a->q_next = NULL; + } + + /* + ** Alias the name and handle special mailer types. + */ + + trylocaluser: + if (tTd(29, 7)) + { + dprintf("at trylocaluser: "); + printaddr(a, FALSE); + } + + if (!QS_IS_OK(a->q_state)) + goto testselfdestruct; + + if (m == InclMailer) + { + a->q_state = QS_INCLUDED; + if (a->q_alias == NULL) + { + a->q_state = QS_BADADDR; + a->q_status = "5.7.1"; + usrerrenh(a->q_status, + "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)) + { + if (LogLevel > 2) + sm_syslog(LOG_ERR, e->e_id, + "include %s: transient error: %s", + shortenstring(a->q_user, MAXSHORTSTR), + errstring(ret)); + a->q_state = QS_QUEUEUP; + usrerr("451 4.2.4 Cannot open %s: %s", + shortenstring(a->q_user, MAXSHORTSTR), + errstring(ret)); + } + else if (ret != 0) + { + a->q_state = QS_BADADDR; + a->q_status = "5.2.4"; + usrerrenh(a->q_status, + "550 Cannot open %s: %s", + shortenstring(a->q_user, MAXSHORTSTR), + errstring(ret)); + } + } + } + else if (m == FileMailer) + { + /* check if writable or creatable */ + if (a->q_alias == NULL) + { + a->q_state = QS_BADADDR; + a->q_status = "5.7.1"; + usrerrenh(a->q_status, + "550 Cannot mail directly to files"); + } + else if (bitset(QBOGUSSHELL, a->q_alias->q_flags)) + { + a->q_state = QS_BADADDR; + a->q_status = "5.7.1"; + if (a->q_alias->q_ruser == NULL) + usrerrenh(a->q_status, + "550 UID %d is an unknown user: cannot mail to files", + a->q_alias->q_uid); + else + usrerrenh(a->q_status, + "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_state = QS_BADADDR; + a->q_status = "5.7.1"; + a->q_rstatus = newstr("550 Unsafe for mailing to files"); + usrerrenh(a->q_status, + "550 Address %s is unsafe for mailing to files", + a->q_alias->q_paddr); + } + } + + /* try aliasing */ + if (!quoted && QS_IS_OK(a->q_state) && + 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(QNOTREMOTE, a->q_flags) && + QS_IS_SENDABLE(a->q_state) && + bitnset(M_CHECKUDB, m->m_flags)) + { + if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL) + { + a->q_state = QS_QUEUEUP; + if (e->e_message == NULL) + e->e_message = newstr("Deferred: user database error"); + if (LogLevel > 8) + sm_syslog(LOG_INFO, e->e_id, + "deferred: udbexpand: %s", + errstring(errno)); + message("queued (user database error): %s", + errstring(errno)); + e->e_nrcpts++; + goto testselfdestruct; + } + } +#endif /* USERDB */ + + /* + ** 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)) + { + dprintf("recipient: testing local? cl=%d, rr5=%lx\n\t", + ConfigLevel, (u_long) RewriteRules[5]); + printaddr(a, FALSE); + } + if (ConfigLevel >= 2 && RewriteRules[5] != NULL && + bitnset(M_TRYRULESET5, m->m_flags) && + !bitset(QNOTREMOTE, a->q_flags) && + QS_IS_OK(a->q_state)) + { + maplocaluser(a, sendq, aliaslevel + 1, e); + } + + /* + ** If it didn't get rewritten to another mailer, go ahead + ** and deliver it. + */ + + if (QS_IS_OK(a->q_state) && + bitnset(M_HASPWENT, m->m_flags)) + { + auto bool fuzzy; + register struct passwd *pw; + + /* warning -- finduser may trash buf */ + pw = finduser(buf, &fuzzy); + if (pw == NULL || strlen(pw->pw_name) > MAXNAME) + { + a->q_state = QS_BADADDR; + a->q_status = "5.1.1"; + a->q_rstatus = newstr("550 5.1.1 User unknown"); + giveresponse(EX_NOUSER, a->q_status, 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_state = QS_BADADDR; + a->q_status = "5.4.6"; + usrerrenh(a->q_status, + "554 aliasing/forwarding loop for %s broken", + pw->pw_name); + goto done; + } + + /* see if it aliases */ + (void) strlcpy(buf, pw->pw_name, buflen); + 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, sizeof 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_state = QS_VERIFIED; + } + else if (!quoted) + forward(a, sendq, aliaslevel, e); + } + } + if (!QS_IS_DEAD(a->q_state)) + e->e_nrcpts++; + + testselfdestruct: + a->q_flags |= QTHISPASS; + if (tTd(26, 8)) + { + dprintf("testselfdestruct: "); + printaddr(a, FALSE); + if (tTd(26, 10)) + { + dprintf("SENDQ:\n"); + printaddr(*sendq, TRUE); + dprintf("----\n"); + } + } + if (a->q_alias == NULL && a != &e->e_from && + QS_IS_DEAD(a->q_state)) + { + for (q = *sendq; q != NULL; q = q->q_next) + { + if (!QS_IS_DEAD(q->q_state)) + break; + } + if (q == NULL) + { + a->q_state = QS_BADADDR; + a->q_status = "5.4.6"; + usrerrenh(a->q_status, + "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 = NULL; + + for (q = *sendq; q != NULL; q = q->q_next) + { + if (bitset(QTHISPASS, q->q_flags) && + QS_IS_SENDABLE(q->q_state)) + { + 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); + } + } + a->q_flags |= QRCPTOK; + 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)) + dprintf("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)) + dprintf("failed (numeric input)\n"); + return NULL; + } +#endif /* HESIOD */ + + /* look up this login name using fast path */ + if ((pw = sm_getpwnam(name)) != NULL) + { + if (tTd(29, 4)) + dprintf("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)) + dprintf("found (lower case)\n"); + *fuzzyp = TRUE; + return pw; + } + +#if MATCHGECOS + /* see if fuzzy matching allowed */ + if (!MatchGecos) + { + if (tTd(29, 4)) + dprintf("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)) + dprintf("found (case wrapped)\n"); + break; + } +# endif /* 0 */ + + buildfname(pw->pw_gecos, pw->pw_name, buf, sizeof buf); + if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name)) + { + if (tTd(29, 4)) + dprintf("fuzzy matches %s\n", pw->pw_name); + message("sending to login name %s", pw->pw_name); + break; + } + } + if (pw != NULL) + *fuzzyp = TRUE; + else if (tTd(29, 4)) + dprintf("no fuzzy match found\n"); +# if DEC_OSF_BROKEN_GETPWENT /* DEC OSF/1 3.2 or earlier */ + endpwent(); +# endif /* DEC_OSF_BROKEN_GETPWENT */ + return pw; +#else /* MATCHGECOS */ + if (tTd(29, 4)) + dprintf("not found (fuzzy disabled)\n"); + return NULL; +#endif /* MATCHGECOS */ +} + /* +** 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; + long flags; +{ + uid_t euid; + gid_t egid; + char *user; + + if (tTd(44, 5)) + dprintf("writable(%s, 0x%lx)\n", filename, flags); + + /* + ** File does exist -- check that it is writable. + */ + + if (geteuid() != 0) + { + euid = geteuid(); + egid = getegid(); + user = NULL; + } + else if (ctladdr != NULL) + { + euid = ctladdr->q_uid; + egid = ctladdr->q_gid; + user = ctladdr->q_user; + } + else if (bitset(SFF_RUNASREALUID, flags)) + { + euid = RealUid; + egid = RealGid; + user = RealUserName; + } + else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags)) + { + euid = FileMailer->m_uid; + egid = FileMailer->m_gid; + user = NULL; + } + else + { + euid = egid = 0; + user = NULL; + } + if (!bitset(SFF_ROOTOK, flags)) + { + if (euid == 0) + { + euid = DefUid; + user = DefUser; + } + if (egid == 0) + egid = DefGid; + } + if (geteuid() == 0 && + (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags))) + flags |= SFF_SETUIDOK; + + if (!bitnset(DBS_FILEDELIVERYTOSYMLINK, DontBlameSendmail)) + flags |= SFF_NOSLINK; + if (!bitnset(DBS_FILEDELIVERYTOHARDLINK, DontBlameSendmail)) + flags |= SFF_NOHLINK; + + errno = safefile(filename, euid, egid, user, 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; + +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; + int mode; + volatile bool maxreached = FALSE; + register ADDRESS *ca; + volatile uid_t saveduid, uid; + volatile gid_t savedgid, gid; + char *volatile user; + int rval = 0; + volatile long sfflags = SFF_REGONLY; + register char *p; + bool safechown = FALSE; + volatile bool safedir = FALSE; + struct stat st; + char buf[MAXLINE]; + + if (tTd(27, 2)) + dprintf("include(%s)\n", fname); + if (tTd(27, 4)) + dprintf(" ruid=%d euid=%d\n", + (int) getuid(), (int) geteuid()); + if (tTd(27, 14)) + { + dprintf("ctladdr "); + printaddr(ctladdr, FALSE); + } + + if (tTd(27, 9)) + dprintf("include: old uid = %d/%d\n", + (int) getuid(), (int) geteuid()); + + if (forwarding) + sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOWLINK; + + /* + ** If RunAsUser set, won't be able to run programs as user + ** so mark them as unsafe unless the administrator knows better. + */ + + if ((geteuid() != 0 || RunAsUid != 0) && + !bitnset(DBS_NONROOTSAFEADDR, DontBlameSendmail)) + { + if (tTd(27, 4)) + dprintf("include: not safe (euid=%d, RunAsUid=%d)\n", + (int) geteuid(), (int) RunAsUid); + ctladdr->q_flags |= QUNSAFEADDR; + } + + ca = getctladdr(ctladdr); + if (ca == NULL || + (ca->q_uid == DefUid && ca->q_gid == 0)) + { + uid = DefUid; + gid = DefGid; + user = DefUser; + } + else + { + uid = ca->q_uid; + gid = ca->q_gid; + user = ca->q_user; + } +#if MAILER_SETUID_METHOD != USE_SETUID + saveduid = geteuid(); + savedgid = getegid(); + if (saveduid == 0) + { + if (!DontInitGroups) + { + if (initgroups(user, gid) == -1) + syserr("include: initgroups(%s, %d) failed", + user, gid); + } + else + { + GIDSET_T gidset[1]; + + gidset[0] = gid; + if (setgroups(1, gidset) == -1) + syserr("include: setgroups() failed"); + } + + if (gid != 0 && setgid(gid) < -1) + syserr("setgid(%d) failure", gid); + if (uid != 0) + { +# if MAILER_SETUID_METHOD == USE_SETEUID + if (seteuid(uid) < 0) + syserr("seteuid(%d) failure (real=%d, eff=%d)", + uid, getuid(), geteuid()); +# endif /* MAILER_SETUID_METHOD == USE_SETEUID */ +# if MAILER_SETUID_METHOD == USE_SETREUID + if (setreuid(0, uid) < 0) + syserr("setreuid(0, %d) failure (real=%d, eff=%d)", + uid, getuid(), geteuid()); +# endif /* MAILER_SETUID_METHOD == USE_SETREUID */ + } + } +#endif /* MAILER_SETUID_METHOD != USE_SETUID */ + + if (tTd(27, 9)) + dprintf("include: new uid = %d/%d\n", + (int) getuid(), (int) 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_state = QS_QUEUEUP; + errno = 0; + + /* return pseudo-error code */ + rval = E_SM_OPENTIMEOUT; + goto resetuid; + } + if (TimeOuts.to_fileopen > 0) + ev = setevent(TimeOuts.to_fileopen, includetimeout, 0); + else + ev = NULL; + + /* check for writable parent directory */ + p = strrchr(fname, '/'); + if (p != NULL) + { + int ret; + + *p = '\0'; + ret = safedirpath(fname, uid, gid, user, + sfflags|SFF_SAFEDIRPATH, 0, 0); + if (ret == 0) + { + /* in safe directory: relax chown & link rules */ + safedir = TRUE; + sfflags |= SFF_NOPATHCHECK; + } + else + { + if (bitnset((forwarding ? + DBS_FORWARDFILEINUNSAFEDIRPATH : + DBS_INCLUDEFILEINUNSAFEDIRPATH), + DontBlameSendmail)) + sfflags |= SFF_NOPATHCHECK; + else if (bitnset((forwarding ? + DBS_FORWARDFILEINGROUPWRITABLEDIRPATH : + DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH), + DontBlameSendmail) && + ret == E_SM_GWDIR) + { + setbitn(DBS_GROUPWRITABLEDIRPATHSAFE, + DontBlameSendmail); + ret = safedirpath(fname, uid, gid, user, + sfflags|SFF_SAFEDIRPATH, + 0, 0); + clrbitn(DBS_GROUPWRITABLEDIRPATHSAFE, + DontBlameSendmail); + if (ret == 0) + sfflags |= SFF_NOPATHCHECK; + else + sfflags |= SFF_SAFEDIRPATH; + } + else + sfflags |= SFF_SAFEDIRPATH; + if (ret > E_PSEUDOBASE && + !bitnset((forwarding ? + DBS_FORWARDFILEINUNSAFEDIRPATHSAFE : + DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE), + DontBlameSendmail)) + { + if (LogLevel >= 12) + sm_syslog(LOG_INFO, e->e_id, + "%s: unsafe directory path, marked unsafe", + shortenstring(fname, MAXSHORTSTR)); + ctladdr->q_flags |= QUNSAFEADDR; + } + } + *p = '/'; + } + + /* allow links only in unwritable directories */ + if (!safedir && + !bitnset((forwarding ? + DBS_LINKEDFORWARDFILEINWRITABLEDIR : + DBS_LINKEDINCLUDEFILEINWRITABLEDIR), + DontBlameSendmail)) + sfflags |= SFF_NOLINK; + + rval = safefile(fname, uid, gid, user, sfflags, S_IREAD, &st); + if (rval != 0) + { + /* don't use this :include: file */ + if (tTd(27, 4)) + dprintf("include: not safe (uid=%d): %s\n", + (int) uid, errstring(rval)); + } + else if ((fp = fopen(fname, "r")) == NULL) + { + rval = errno; + if (tTd(27, 4)) + dprintf("include: open: %s\n", errstring(rval)); + } + else if (filechanged(fname, fileno(fp), &st)) + { + rval = E_SM_FILECHANGE; + if (tTd(27, 4)) + dprintf("include: file changed after open\n"); + } + 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 /* USESETEUID */ + 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 /* USESETEUID */ + } + (void) setgid(savedgid); + } +#endif /* HASSETREUID || USESETEUID */ + + if (tTd(27, 9)) + dprintf("include: reset uid = %d/%d\n", + (int) getuid(), (int) geteuid()); + + if (rval == E_SM_OPENTIMEOUT) + usrerr("451 4.4.1 open timeout on %s", fname); + + if (fp == NULL) + return rval; + + if (fstat(fileno(fp), &st) < 0) + { + rval = errno; + syserr("Cannot fstat %s!", fname); + (void) fclose(fp); + return rval; + } + + /* if path was writable, check to avoid file giveaway tricks */ + safechown = chownsafe(fileno(fp), safedir); + if (tTd(27, 6)) + dprintf("include: parent of %s is %s, chown is %ssafe\n", + fname, + safedir ? "safe" : "dangerous", + safechown ? "" : "un"); + + /* if no controlling user or coming from an alias delivery */ + if (safechown && + (ca == NULL || + (ca->q_uid == DefUid && ca->q_gid == 0))) + { + 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 if (!forwarding) + { + register struct passwd *pw; + + pw = sm_getpwuid(st.st_uid); + if (pw == NULL) + { + ctladdr->q_uid = st.st_uid; + 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)) + { + if (LogLevel >= 12) + sm_syslog(LOG_INFO, e->e_id, + "%s: user %s has bad shell %s, marked %s", + shortenstring(fname, MAXSHORTSTR), + pw->pw_name, sh, + safechown ? "bogus" : "unsafe"); + 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_state = QS_VERIFIED; + e->e_nrcpts++; + (void) fclose(fp); + return rval; + } + + /* + ** Check to see if some bad guy can write this file + ** + ** Group write checking could be more clever, e.g., + ** guessing as to which groups are actually safe ("sys" + ** may be; "user" probably is not). + */ + + mode = S_IWOTH; + if (!bitnset((forwarding ? + DBS_GROUPWRITABLEFORWARDFILESAFE : + DBS_GROUPWRITABLEINCLUDEFILESAFE), + DontBlameSendmail)) + mode |= S_IWGRP; + + if (bitset(mode, st.st_mode)) + { + if (tTd(27, 6)) + dprintf("include: %s is %s writable, marked unsafe\n", + shortenstring(fname, MAXSHORTSTR), + bitset(S_IWOTH, st.st_mode) ? "world" : "group"); + if (LogLevel >= 12) + sm_syslog(LOG_INFO, e->e_id, + "%s: %s writable %s file, marked unsafe", + shortenstring(fname, MAXSHORTSTR), + bitset(S_IWOTH, st.st_mode) ? "world" : "group", + forwarding ? "forward" : ":include:"); + 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 && !maxreached) + { + fixcrlf(buf, TRUE); + LineNumber++; + if (buf[0] == '#' || buf[0] == '\0') + continue; + + /* #@# 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); + if (forwarding && LogLevel > 10) + sm_syslog(LOG_INFO, e->e_id, + "forward %.200s => %s", + oldto, shortenstring(buf, MAXSHORTSTR)); + + nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e); + + if (forwarding && + MaxForwardEntries > 0 && + nincludes >= MaxForwardEntries) + { + /* just stop reading and processing further entries */ + /* additional: (?) + ctladdr->q_state = QS_DONTSEND; + **/ + syserr("Attempt to forward to more then %d addresses (in %s)!", + MaxForwardEntries,fname); + maxreached = TRUE; + } + } + + if (ferror(fp) && tTd(27, 3)) + dprintf("include: read error: %s\n", errstring(errno)); + if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags)) + { + if (tTd(27, 5)) + { + dprintf("include: QS_DONTSEND "); + printaddr(ctladdr, FALSE); + } + ctladdr->q_state = QS_DONTSEND; + } + + (void) fclose(fp); + 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. +** +** Returns: +** The address that should be retained. +*/ + +static ADDRESS * +self_reference(a) + ADDRESS *a; +{ + ADDRESS *b; /* top entry in self ref loop */ + ADDRESS *c; /* entry that point to a real mail box */ + + if (tTd(27, 1)) + dprintf("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)) + dprintf("\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 as QS_IS_DEAD(), 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 QS_EXPANDED, 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 (tTd(27, 10)) + dprintf(" %s", c->q_user); + if (bitnset(M_HASPWENT, c->q_mailer->m_flags)) + { + if (tTd(27, 2)) + dprintf("\t... getpwnam(%s)... ", c->q_user); + if (sm_getpwnam(c->q_user) != NULL) + { + if (tTd(27, 2)) + dprintf("found\n"); + + /* ought to cache results here */ + if (sameaddr(b, c)) + return b; + else + return c; + } + if (tTd(27, 2)) + dprintf("failed\n"); + } + else + { + /* if local delivery, compare usernames */ + if (bitnset(M_LOCALMAILER, c->q_mailer->m_flags) && + b->q_mailer == c->q_mailer) + { + if (tTd(27, 2)) + dprintf("\t... local match (%s)\n", + c->q_user); + if (sameaddr(b, c)) + return b; + else + return c; + } + } + if (tTd(27, 10)) + dprintf("\n"); + c = c->q_alias; + } + + if (tTd(27, 1)) + dprintf("\t... cannot break loop for \"%s\"\n", a->q_paddr); + + return NULL; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/savemail.c b/gnu/usr.sbin/sendmail/sendmail/savemail.c new file mode 100644 index 00000000000..fb88a961a43 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/savemail.c @@ -0,0 +1,1589 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: savemail.c,v 8.211 2000/02/01 05:49:56 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +static void errbody __P((MCI *, ENVELOPE *, char *)); +static bool pruneroute __P((char *)); + +/* +** 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 /* mail has already been returned */ +#define ESM_DEADLETTER 3 /* save in ~/dead.letter */ +#define ESM_POSTMASTER 4 /* return to postmaster */ +#define ESM_DEADLETTERDROP 5 /* save in DeadLetterDrop */ +#define ESM_PANIC 6 /* call loseqfile() */ +#define ESM_DONE 7 /* message is successfully delivered */ + + +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 flags; + long sff; + char buf[MAXLINE + 1]; + + if (tTd(6, 1)) + { + dprintf("\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 5.3.5 Cannot parse Postmaster!"); + finis(TRUE, EX_SOFTWARE); + } + } + 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_DEADLETTERDROP + ** If DeadLetterDrop set, save it there. + ** 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 5.3.0 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)) + dprintf(" 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) bfrewind(e->e_xfp); + printf("Transcript follows:\r\n"); + while (fgets(buf, sizeof buf, e->e_xfp) != NULL && + !ferror(stdout)) + (void) fputs(buf, stdout); + } + else + { + syserr("Cannot open %s", queuename(e, 'x')); + printf("Transcript of session is unavailable.\r\n"); + } + 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)) + { + char from[TOBUFSIZE]; + + if (strlen(e->e_from.q_paddr) >= sizeof from) + { + state = ESM_POSTMASTER; + break; + } + (void) strlcpy(from, e->e_from.q_paddr, + sizeof from); + + if (!DontPruneRoutes && pruneroute(from)) + { + ADDRESS *a; + + for (a = e->e_errorqueue; a != NULL; + a = a->q_next) + { + if (sameaddr(a, &e->e_from)) + a->q_state = QS_DUPLICATE; + } + } + (void) sendtolist(from, 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 (QS_IS_SENDABLE(q->q_state)) + break; + } + if (q == NULL) + { + /* this is an error-error */ + state = ESM_POSTMASTER; + break; + } + if (returntosender(e->e_message, e->e_errorqueue, + sendbody ? RTSF_SEND_BODY + : RTSF_NO_BODY, + 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; + expand(DoubleBounceAddr, buf, sizeof buf, e); + if (sendtolist(buf, NULLADDR, &q, 0, e) <= 0) + { + syserr("553 5.3.0 cannot parse %s!", buf); + ExitStat = EX_SOFTWARE; + state = ESM_DEADLETTERDROP; + break; + } + flags = RTSF_PM_BOUNCE; + if (sendbody) + flags |= RTSF_SEND_BODY; + if (returntosender(e->e_message, q, flags, e) == 0) + { + state = ESM_DONE; + break; + } + + /* didn't work -- last resort */ + state = ESM_DEADLETTERDROP; + 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); + + /* get the sender for the UnixFromLine */ + p = macvalue('g', e); + define('g', e->e_sender, e); + + expand("\201z/dead.letter", buf, sizeof buf, e); + sff = SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; + if (RealUid == 0) + sff |= SFF_ROOTOK; + e->e_to = buf; + if (writable(buf, NULL, sff) && + mailfile(buf, FileMailer, NULL, sff, e) == EX_OK) + { + int oldverb = Verbose; + + if (OpMode != MD_DAEMON && OpMode != MD_SMTP) + Verbose = 1; + if (Verbose > 0) + message("Saved message in %s", buf); + Verbose = oldverb; + define('g', p, e); + state = ESM_DONE; + break; + } + define('g', p, e); + state = ESM_MAIL; + break; + + case ESM_DEADLETTERDROP: + /* + ** Log the mail in DeadLetterDrop file. + */ + + if (e->e_class < 0) + { + state = ESM_DONE; + break; + } + + if ((SafeFileEnv != NULL && SafeFileEnv[0] != '\0') || + DeadLetterDrop == NULL || + DeadLetterDrop[0] == '\0') + { + state = ESM_PANIC; + break; + } + + sff = SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT|SFF_MUSTOWN; + if (!writable(DeadLetterDrop, NULL, sff) || + (fp = safefopen(DeadLetterDrop, O_WRONLY|O_APPEND, + FileMode, sff)) == NULL) + { + state = ESM_PANIC; + break; + } + + memset(&mcibuf, '\0', sizeof mcibuf); + mcibuf.mci_out = fp; + mcibuf.mci_mailer = FileMailer; + if (bitnset(M_7BITS, FileMailer->m_flags)) + mcibuf.mci_flags |= MCIF_7BIT; + + /* get the sender for the UnixFromLine */ + p = macvalue('g', e); + define('g', e->e_sender, e); + + putfromline(&mcibuf, e); + (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER); + (*e->e_putbody)(&mcibuf, e, NULL); + putline("\n", &mcibuf); + (void) fflush(fp); + if (ferror(fp) || + fclose(fp) < 0) + state = ESM_PANIC; + else + { + int oldverb = Verbose; + + if (OpMode != MD_DAEMON && OpMode != MD_SMTP) + Verbose = 1; + if (Verbose > 0) + message("Saved message in %s", + DeadLetterDrop); + Verbose = oldverb; + if (LogLevel > 3) + sm_syslog(LOG_NOTICE, e->e_id, + "Saved message in %s", + DeadLetterDrop); + state = ESM_DONE; + } + define('g', p, e); + break; + + default: + syserr("554 5.3.5 savemail: unknown state %d", state); + + /* FALLTHROUGH */ + + 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. +** flags -- flags tweaking the operation: +** RTSF_SENDBODY -- include body of message (otherwise +** just send the header). +** RTSF_PMBOUNCE -- this is a postmaster bounce. +** 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, flags, e) + char *msg; + ADDRESS *returnq; + int flags; + register ENVELOPE *e; +{ + register ENVELOPE *ee; + ENVELOPE *oldcur = CurEnv; + ENVELOPE errenvelope; + static int returndepth = 0; + register ADDRESS *q; + char *p; + char buf[MAXNAME + 1]; + + if (returnq == NULL) + return -1; + + if (msg == NULL) + msg = "Unable to deliver mail"; + + if (tTd(6, 1)) + { + dprintf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%lx, returnq=", + msg, returndepth, (u_long) e); + printaddr(returnq, TRUE); + if (tTd(6, 20)) + { + dprintf("Sendq="); + printaddr(e->e_sendqueue, TRUE); + } + } + + if (++returndepth >= MAXRETURNS) + { + if (returndepth != MAXRETURNS) + syserr("554 5.3.0 returntosender: infinite recursion on %s", + returnq->q_paddr); + /* don't "unrecurse" and fake a clean exit */ + /* returndepth--; */ + return 0; + } + + define('g', e->e_sender, e); + define('u', NULL, e); + + /* initialize error envelope */ + ee = newenvelope(&errenvelope, e); + define('a', "\201b", ee); + define('r', "", 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; + if (bitset(EF_DONT_MIME, e->e_flags)) + { + ee->e_flags |= EF_DONT_MIME; + + /* + ** If we can't convert to MIME and we don't pass + ** 8-bit, we can't send the body. + */ + + if (bitset(EF_HAS8BIT, e->e_flags) && + !bitset(MM_PASS8BIT, MimeMode)) + flags &= ~RTSF_SEND_BODY; + } + + ee->e_sendqueue = returnq; + ee->e_msgsize = ERRORFUDGE; + if (bitset(RTSF_SEND_BODY, flags) && + !bitset(PRIV_NOBODYRETN, PrivacyFlags)) + ee->e_msgsize += e->e_msgsize; + else + ee->e_flags |= EF_NO_BODY_RETN; + initsys(ee); + +#if NAMED_BIND + _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; + _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; +#endif /* NAMED_BIND */ + for (q = returnq; q != NULL; q = q->q_next) + { + if (QS_IS_BADADDR(q->q_state)) + continue; + + q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); + q->q_flags |= QPINGONFAILURE; + + if (!QS_IS_DEAD(q->q_state)) + ee->e_nrcpts++; + + if (q->q_alias == NULL) + addheader("To", q->q_paddr, &ee->e_header); + } + + if (LogLevel > 5) + { + if (bitset(EF_RESPONSE, e->e_flags)) + p = "return to sender"; + else if (bitset(EF_WARNING, e->e_flags)) + p = "sender notify"; + else if (bitset(RTSF_PM_BOUNCE, flags)) + p = "postmaster notify"; + else + p = "DSN"; + sm_syslog(LOG_INFO, e->e_id, + "%s: %s: %s", + ee->e_id, p, shortenstring(msg, MAXSHORTSTR)); + } + + if (SendMIMEErrors) + { + addheader("MIME-Version", "1.0", &ee->e_header); + + (void) snprintf(buf, sizeof buf, "%s.%ld/%.100s", + ee->e_id, curtime(), MyHostName); + ee->e_msgboundary = newstr(buf); + (void) snprintf(buf, sizeof buf, +#if DSN + "multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"", +#else /* DSN */ + "multipart/mixed; boundary=\"%s\"", +#endif /* DSN */ + 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 if (bitset(RTSF_PM_BOUNCE, flags)) + { + snprintf(buf, sizeof buf, + "Postmaster notify: see transcript for details"); + addheader("Subject", buf, &ee->e_header); + p = "postmaster-notification"; + } + else + { + snprintf(buf, sizeof buf, + "Returned mail: see transcript for details"); + addheader("Subject", buf, &ee->e_header); + p = "failure"; + } + (void) snprintf(buf, sizeof 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 5.3.5 Can't parse myself!"); + ExitStat = EX_SOFTWARE; + returndepth--; + return -1; + } + ee->e_from.q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS); + ee->e_from.q_flags |= QPINGONFAILURE; + 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, FALSE); + + /* actually deliver the error message */ + sendall(ee, SM_DELIVER); + + /* restore state */ + dropenvelope(ee, TRUE); + 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 (QS_IS_ATTEMPTED(q->q_state)) + 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. +** +** Returns: +** none +** +** Side Effects: +** Outputs the body of an error message. +*/ + +/* ARGSUSED2 */ +static void +errbody(mci, e, separator) + register MCI *mci; + register ENVELOPE *e; + char *separator; +{ + bool printheader; + bool sendbody; + bool pm_notify; + int save_errno; + register FILE *xfile; + char *p; + register ADDRESS *q = NULL; + char buf[MAXLINE]; + + 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) snprintf(buf, sizeof buf, "--%s", e->e_msgboundary); + putline(buf, mci); + putline("", mci); + } + + /* + ** Output introductory information. + */ + + pm_notify = FALSE; + p = hvalue("subject", e->e_header); + if (p != NULL && strncmp(p, "Postmaster ", 11) == 0) + pm_notify = TRUE; + else + { + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_BADADDR(q->q_state)) + break; + } + } + if (!pm_notify && 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); + } + snprintf(buf, sizeof 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); + + /* include id in postmaster copies */ + if (pm_notify && e->e_parent->e_id != NULL) + { + snprintf(buf, sizeof buf, "with id %s", e->e_parent->e_id); + 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 == '/') + { + long sff = SFF_ROOTOK|SFF_REGONLY; + + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + if (!bitnset(DBS_ERRORHEADERINUNSAFEDIRPATH, + DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + xfile = safefopen(ErrMsgFile, O_RDONLY, 0444, sff); + if (xfile != NULL) + { + while (fgets(buf, sizeof buf, xfile) != NULL) + { + translate_dollars(buf); + 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 (!QS_IS_BADADDR(q->q_state) || + !bitset(QPINGONFAILURE, q->q_flags)) + continue; + + if (printheader) + { + putline(" ----- The following addresses had permanent fatal errors -----", + mci); + printheader = FALSE; + } + + snprintf(buf, sizeof buf, "%s", + shortenstring(q->q_paddr, MAXSHORTSTR)); + putline(buf, mci); + if (q->q_rstatus != NULL) + { + snprintf(buf, sizeof buf, " (reason: %s)", + shortenstring(exitstat(q->q_rstatus), + MAXSHORTSTR)); + putline(buf, mci); + } + if (q->q_alias != NULL) + { + snprintf(buf, sizeof buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); + putline(buf, mci); + } + } + if (!printheader) + putline("", mci); + + printheader = TRUE; + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_BADADDR(q->q_state) || + !bitset(QPRIMARY, q->q_flags) || + !bitset(QDELAYED, q->q_flags)) + continue; + + if (printheader) + { + putline(" ----- The following addresses had transient non-fatal errors -----", + mci); + printheader = FALSE; + } + + snprintf(buf, sizeof buf, "%s", + shortenstring(q->q_paddr, MAXSHORTSTR)); + putline(buf, mci); + if (q->q_alias != NULL) + { + snprintf(buf, sizeof buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); + putline(buf, mci); + } + } + if (!printheader) + putline("", mci); + + printheader = TRUE; + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + if (QS_IS_BADADDR(q->q_state) || + !bitset(QPRIMARY, q->q_flags) || + bitset(QDELAYED, q->q_flags)) + continue; + 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 had successful delivery notifications -----", + mci); + printheader = FALSE; + } + + snprintf(buf, sizeof buf, "%s (%s)", + shortenstring(q->q_paddr, MAXSHORTSTR), p); + putline(buf, mci); + if (q->q_alias != NULL) + { + snprintf(buf, sizeof buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, + MAXSHORTSTR)); + putline(buf, mci); + } + } + if (!printheader) + putline("", mci); + + /* + ** Output transcript of errors + */ + + (void) fflush(stdout); + if (e->e_parent->e_xfp == NULL) + { + putline(" ----- Transcript of session is unavailable -----\n", + mci); + } + else + { + printheader = TRUE; + (void) bfrewind(e->e_parent->e_xfp); + if (e->e_xfp != NULL) + (void) fflush(e->e_xfp); + while (fgets(buf, sizeof buf, e->e_parent->e_xfp) != NULL) + { + if (printheader) + putline(" ----- Transcript of session follows -----\n", + mci); + printheader = FALSE; + putline(buf, mci); + } + } + errno = 0; + +#if DSN + /* + ** Output machine-readable version. + */ + + if (e->e_msgboundary != NULL) + { + putline("", mci); + (void) snprintf(buf, sizeof 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) snprintf(buf, sizeof buf, + "Original-Envelope-Id: %.800s", + xuntextify(e->e_parent->e_envid)); + putline(buf, mci); + } + + /* Reporting-MTA: is us (required) */ + (void) snprintf(buf, sizeof 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) snprintf(buf, sizeof buf, + "Received-From-MTA: %s; %.800s", + p, RealHostName); + putline(buf, mci); + } + + /* Arrival-Date: -- when it arrived here */ + (void) snprintf(buf, sizeof 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 (QS_IS_BADADDR(q->q_state)) + 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) snprintf(buf, sizeof 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 (strcasecmp(p, "rfc822") != 0) + { + (void) snprintf(buf, sizeof buf, + "Final-Recipient: %s; %.800s", + r->q_mailer->m_addrtype, + r->q_user); + } + else if (strchr(r->q_user, '@') != NULL) + { + (void) snprintf(buf, sizeof buf, + "Final-Recipient: %s; %.800s", + p, r->q_user); + } + else if (strchr(r->q_paddr, '@') != NULL) + { + char *qp; + bool b; + + qp = r->q_paddr; + /* strip brackets from address */ + b = FALSE; + if (*qp == '<') + { + b = qp[strlen(qp) - 1] == '>'; + if (b) + qp[strlen(qp) - 1] = '\0'; + qp++; + } + (void) snprintf(buf, sizeof buf, + "Final-Recipient: %s; %.800s", + p, qp); + /* undo damage */ + if (b) + qp[strlen(qp)] = '>'; + } + else + { + (void) snprintf(buf, sizeof buf, + "Final-Recipient: %s; %.700s@%.100s", + p, r->q_user, MyHostName); + } + putline(buf, mci); + + /* X-Actual-Recipient: -- the real problem address */ + if (r != q && q->q_user[0] != '\0') + { + if (q->q_mailer != NULL && + q->q_mailer->m_addrtype != NULL) + p = q->q_mailer->m_addrtype; + else + p = "rfc822"; + + if (strcasecmp(p, "rfc822") == 0 && + strchr(q->q_user, '@') == NULL) + { + (void) snprintf(buf, sizeof buf, + "X-Actual-Recipient: %s; %.700s@%.100s", + p, q->q_user, + MyHostName); + } + else + { + (void) snprintf(buf, sizeof buf, + "X-Actual-Recipient: %s; %.800s", + p, q->q_user); + } + putline(buf, mci); + } + + /* Action: -- what happened? */ + snprintf(buf, sizeof buf, "Action: %s", action); + putline(buf, mci); + + /* Status: -- what _really_ happened? */ + if (q->q_status != NULL) + p = q->q_status; + else if (QS_IS_BADADDR(q->q_state)) + p = "5.0.0"; + else if (QS_IS_QUEUEUP(q->q_state)) + p = "4.0.0"; + else + p = "2.0.0"; + snprintf(buf, sizeof buf, "Status: %s", p); + 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) snprintf(buf, sizeof 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) snprintf(buf, sizeof 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) snprintf(buf, sizeof buf, + "Last-Attempt-Date: %s", + arpadate(ctime(&q->q_statdate))); + putline(buf, mci); + + /* Will-Retry-Until: -- for delayed messages only */ + if (QS_IS_QUEUEUP(q->q_state)) + { + time_t xdate; + + xdate = e->e_parent->e_ctime + + TimeOuts.to_q_return[e->e_parent->e_timeoutclass]; + snprintf(buf, sizeof buf, + "Will-Retry-Until: %s", + arpadate(ctime(&xdate))); + putline(buf, mci); + } + } + } +#endif /* DSN */ + + /* + ** 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); + } + else + { + (void) snprintf(buf, sizeof buf, "--%s", + e->e_msgboundary); + + putline(buf, mci); + (void) snprintf(buf, sizeof 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) snprintf(buf, sizeof buf, + "Content-Transfer-Encoding: %s", + p); + putline(buf, mci); + } + } + putline("", mci); + save_errno = errno; + putheader(mci, e->e_parent->e_header, e->e_parent, M87F_OUTER); + errno = save_errno; + 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) snprintf(buf, sizeof buf, "--%s--", e->e_msgboundary); + putline(buf, mci); + } + putline("", mci); + (void) fflush(mci->mci_out); + + /* + ** 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.0"; + + 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. +** taboo -- additional characters that must be encoded. +** +** Returns: +** The xtext-ified version of the same string. +*/ + +char * +xtextify(t, taboo) + register char *t; + char *taboo; +{ + register char *p; + int l; + int nbogus; + static char *bp = NULL; + static int bplen = 0; + + if (taboo == NULL) + taboo = ""; + + /* 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 == '(' || + strchr(taboo, c) != NULL) + 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 == '(' || + strchr(taboo, c) != NULL) + { + *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; + } + *p = '\0'; + return bp; +} + /* +** XTEXTOK -- check if a string is legal xtext +** +** Xtext is used in Delivery Status Notifications. The spec was +** taken from RFC 1891, ``SMTP Service Extension for Delivery +** Status Notifications''. +** +** 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 +*/ + +static bool +pruneroute(addr) + char *addr; +{ +#if NAMED_BIND + char *start, *at, *comma; + char c; + int rcode; + int i; + 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 */ + i = strlen(at + 1); + if (i >= (SIZE_T) sizeof hostbuf) + return FALSE; + (void) strlcpy(hostbuf, at + 1, sizeof hostbuf); + hostbuf[i - 1] = '\0'; + + while (start) + { + if (getmxrr(hostbuf, mxhosts, NULL, FALSE, &rcode) > 0) + { + (void) strlcpy(addr + 1, start + 1, strlen(addr) - 1); + return TRUE; + } + c = *start; + *start = '\0'; + comma = strrchr(addr, ','); + if (comma != NULL && comma[1] == '@' && + strlen(comma + 2) < (SIZE_T) sizeof hostbuf) + (void) strlcpy(hostbuf, comma + 2, sizeof hostbuf); + else + comma = NULL; + *start = c; + start = comma; + } +#endif /* NAMED_BIND */ + return FALSE; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/sendmail.0 b/gnu/usr.sbin/sendmail/sendmail/sendmail.0 new file mode 100644 index 00000000000..387ae282948 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sendmail.0 @@ -0,0 +1,594 @@ + + + +SENDMAIL(8) SENDMAIL(8) + + +NNAAMMEE + sseennddmmaaiill - an electronic mail transport agent + +SSYYNNOOPPSSIISS + sseennddmmaaiill [_f_l_a_g_s] [_a_d_d_r_e_s_s _._._.] + nneewwaalliiaasseess + mmaaiillqq [--vv] + hhoossttssttaatt + ppuurrggeessttaatt + ssmmttppdd + +DDEESSCCRRIIPPTTIIOONN + SSeennddmmaaiill sends a message to one or more _r_e_c_i_p_i_e_n_t_s_, rout- + ing the message over whatever networks are necessary. + SSeennddmmaaiill does internetwork forwarding as necessary to + deliver the message to the correct place. + + SSeennddmmaaiill is not intended as a user interface routine; + other programs provide user-friendly front ends; sseennddmmaaiill + is used only to deliver pre-formatted messages. + + With no flags, sseennddmmaaiill 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. + + Local addresses are looked up in a file and aliased appro- + priately. Aliasing can be prevented by preceding the + address with a backslash. Beginning with 8.10, the sender + is included in any alias expansions, e.g., if `john' sends + to `group', and `group' includes `john' in the expansion, + then the letter will also be delivered to `john'. + + PPaarraammeetteerrss + --BB_t_y_p_e Set the body type to _t_y_p_e. Current legal values + are 7BIT or 8BITMIME. + + --bbaa Go into 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. + + --bbdd Run as a daemon. This requires Berkeley IPC. + SSeennddmmaaiill will fork and run in background listening + on socket 25 for incoming SMTP connections. This + is normally run from /etc/rc. + + --bbDD Same as --bbdd except runs in foreground. + + --bbhh Print the persistent host status database. + + --bbHH Purge expired entries from the persistent host + + + + $Date: 2000/04/02 19:05:47 $ 1 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + status database. + + --bbii Initialize the alias database. + + --bbmm Deliver mail in the usual way (default). + + --bbpp Print a listing of the queue. + + --bbss Use the SMTP protocol as described in RFC821 on + standard input and output. This flag implies all + the operations of the --bbaa flag that are compatible + with SMTP. + + --bbtt Run in address test mode. This mode reads + addresses and shows the steps in parsing; it is + used for debugging configuration tables. + + --bbvv Verify names only - do not try to collect or + deliver a message. Verify mode is normally used + for validating users or mailing lists. + + --CC_f_i_l_e Use alternate configuration file. SSeennddmmaaiill refuses + to run as root if an alternate configuration file + is specified. + + --dd_X Set debugging value to _X. + + --FF_f_u_l_l_n_a_m_e + Set the full name of the sender. + + --ff_n_a_m_e Sets the name of the ``from'' person (i.e., the + envelope sender of the mail). This address may + also be used in the From: header if that header is + missing during initial submission. The envelope + sender address is used as the recipient for deliv- + ery status notifications and may also appear in a + Return-Path: header. --ff should only be used by + ``trusted'' users (normally _r_o_o_t, _d_a_e_m_o_n, and _n_e_t_- + _w_o_r_k) or if the person you are trying to become is + the same as the person you are. Otherwise, an X- + Authentication-Warning header will be added to the + message. + + --hh_N Set the hop count to _N. The hop count is incre- + mented 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. + + --ii Ignore dots alone on lines by themselves in incom- + ing messages. This should be set if you are read- + ing data from a file. + + + + + $Date: 2000/04/02 19:05:47 $ 2 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + --LL _t_a_g Set the identifier used in syslog messages to the + supplied _t_a_g. + + --NN _d_s_n Set delivery status notification conditions to _d_s_n, + which can be `never' for no notifications or a + comma separated list of the values `failure' to be + notified if delivery failed, `delay' to be notified + if delivery is delayed, and `success' to be noti- + fied when the message is successfully delivered. + + --nn Don't do aliasing. + + --OO _o_p_t_i_o_n=_v_a_l_u_e + Set option _o_p_t_i_o_n to the specified _v_a_l_u_e. This + form uses long names. See below for more details. + + --oo_x _v_a_l_u_e + Set option _x to the specified _v_a_l_u_e. This form + uses single character names only. The short names + are not described in this manual page; see the + _S_e_n_d_m_a_i_l _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n _G_u_i_d_e for + details. + + --pp_p_r_o_t_o_c_o_l + 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''. + + --qq[_t_i_m_e] + Processed saved messages in the queue at given + intervals. If _t_i_m_e is omitted, process the queue + once. _T_i_m_e is given as a tagged number, with `s' + being seconds, `m' being minutes, `h' being hours, + `d' being days, and `w' being weeks. For example, + `-q1h30m' or `-q90m' would both set the timeout to + one hour thirty minutes. If _t_i_m_e is specified, + sseennddmmaaiill will run in the background. This option + can be used safely with --bbdd. + + --qqII_s_u_b_s_t_r + Limit processed jobs to those containing _s_u_b_s_t_r as + a substring of the queue id. + + --qqRR_s_u_b_s_t_r + Limit processed jobs to those containing _s_u_b_s_t_r as + a substring of one of the recipients. + + --qqSS_s_u_b_s_t_r + Limit processed jobs to those containing _s_u_b_s_t_r as + a substring of the sender. + + --RR _r_e_t_u_r_n + Set the amount of the message to be returned if the + + + + $Date: 2000/04/02 19:05:47 $ 3 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + message bounces. The _r_e_t_u_r_n parameter can be + `full' to return the entire message or `hdrs' to + return only the headers. In the latter case also + local bounces return only the headers. + + --rr_n_a_m_e An alternate and obsolete form of the --ff flag. + + --tt Read message for recipients. To:, Cc:, and Bcc: + lines will be scanned for recipient addresses. The + Bcc: line will be deleted before transmission. + + --UU Initial (user) submission. This should _a_l_w_a_y_s be + set when called from a user agent such as MMaaiill or + eexxmmhh and _n_e_v_e_r be set when called by a network + delivery agent such as rrmmaaiill. + + --VV _e_n_v_i_d + Set the original envelope id. This is propagated + across SMTP to servers that support DSNs and is + returned in DSN-compliant error messages. + + --vv Go into verbose mode. Alias expansions will be + announced, etc. + + --XX _l_o_g_f_i_l_e + Log all traffic in and out of mailers in the indi- + cated log file. This should only be used as a last + resort for debugging mailer bugs. It will log a + lot of data very quickly. + + ---- Stop processing command flags and use the rest of + the arguments as addresses. + + OOppttiioonnss + There are also a number of processing options that may be + set. Normally these will only be used by a system admin- + istrator. Options may be set either on the command line + using the --oo flag (for short names), the --OO flag (for long + names), or in the configuration file. This is a partial + list limited to those options that are likely to be useful + on the command line and only shows the long names; for a + complete list (and details), consult the _S_e_n_d_m_a_i_l _I_n_s_t_a_l_- + _l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n _G_u_i_d_e. The options are: + + AliasFile=_f_i_l_e + Use alternate alias file. + + HoldExpensive + On mailers that are considered ``expensive'' to + connect to, don't initiate immediate connection. + This requires queueing. + + CheckpointInterval=_N + Checkpoint the queue file after every _N successful + + + + $Date: 2000/04/02 19:05:47 $ 4 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + deliveries (default 10). This avoids excessive + duplicate deliveries when sending to long mailing + lists interrupted by system crashes. + + DeliveryMode=_x + Set the delivery mode to _x. Delivery modes are `i' + for interactive (synchronous) delivery, `b' for + background (asynchronous) delivery, `q' for queue + only - i.e., actual delivery is done the next time + the queue is run, and `d' for deferred - the same + as `q' except that database lookups for maps which + have set the -D option (default for the host map) + are avoided. + + ErrorMode=_x + Set error processing to mode _x. Valid modes are + `m' to mail back the error message, `w' to + ``write'' back the error message (or mail it back + if the sender is not logged in), `p' to print the + errors on the terminal (default), `q' to throw away + error messages (only exit status is returned), and + `e' to do special processing for the BerkNet. If + the text of the message is not mailed back by modes + `m' or `w' and if the sender is local to this + machine, a copy of the message is appended to the + file _d_e_a_d_._l_e_t_t_e_r in the sender's home directory. + + SaveFromLine + Save UNIX-style From lines at the front of mes- + sages. + + MaxHopCount=_N + The maximum number of times a message is allowed to + ``hop'' before we decide it is in a loop. + + IgnoreDots + Do not take dots on a line by themselves as a mes- + sage terminator. + + SendMimeErrors + Send error messages in MIME format. If not set, + the DSN (Delivery Status Notification) SMTP exten- + sion is disabled. + + ConnectionCacheTimeout=_t_i_m_e_o_u_t + Set connection cache timeout. + + ConnectionCacheSize=_N + Set connection cache size. + + LogLevel=_n + The log level. + + + + + + $Date: 2000/04/02 19:05:47 $ 5 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + MeToo=_F_a_l_s_e + Don't send to ``me'' (the sender) if I am in an + alias expansion. + + CheckAliases + Validate the right hand side of aliases during a + newaliases(1) command. + + OldStyleHeaders + 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. + + QueueDirectory=_q_u_e_u_e_d_i_r + Select the directory in which to queue messages. + + StatusFile=_f_i_l_e + Save statistics in the named file. + + Timeout.queuereturn=_t_i_m_e + 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 five days. + + UserDatabaseSpec=_u_s_e_r_d_a_t_a_b_a_s_e + If set, a user database is consulted to get for- + warding 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 avail- + able if your sendmail does not have the USERDB + option compiled in. + + ForkEachJob + Fork each job during queue runs. May be convenient + on memory-poor machines. + + SevenBitInput + Strip incoming messages to seven bits. + + EightBitMode=_m_o_d_e + Set the handling of eight bit input to seven bit + destinations to _m_o_d_e: m (mimefy) will convert to + seven-bit MIME format, p (pass) will pass it as + eight bits (but violates protocols), and s (strict) + will bounce the message. + + MinQueueAge=_t_i_m_e_o_u_t + Sets how long a job must ferment in the queue + + + + $Date: 2000/04/02 19:05:47 $ 6 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + between attempts to send it. + + DefaultCharSet=_c_h_a_r_s_e_t + Sets the default character set used to label 8-bit + data that is not otherwise labelled. + + DialDelay=_s_l_e_e_p_t_i_m_e + If opening a connection fails, sleep for _s_l_e_e_p_t_i_m_e + seconds and try again. Useful on dial-on-demand + sites. + + NoRecipientAction=_a_c_t_i_o_n + Set the behaviour when there are no recipient head- + ers (To:, Cc: or Bcc:) in the message to _a_c_t_i_o_n: + none leaves the message unchanged, add-to adds a + To: header with the envelope recipients, add-appar- + ently-to adds an Apparently-To: header with the + envelope recipients, add-bcc adds an empty Bcc: + header, and add-to-undisclosed adds a header read- + ing `To: undisclosed-recipients:;'. + + MaxDaemonChildren=_N + Sets the maximum number of children that an incom- + ing SMTP daemon will allow to spawn at any time to + _N. + + ConnectionRateThrottle=_N + Sets the maximum number of connections per second + to the SMTP port to _N. + + In aliases, the first character of a name may be a verti- + cal 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 sseennddmmaaiill from suppressing the + blanks from between arguments. For example, a common + alias is: + + msgs: "|/usr/bin/msgs -s" + + Aliases may also have the syntax ``:include:_f_i_l_e_n_a_m_e'' to + ask sseennddmmaaiill to read the named file for a list of recipi- + ents. For example, an alias such as: + + poets: ":include:/usr/local/lib/poets.list" + + would read _/_u_s_r_/_l_o_c_a_l_/_l_i_b_/_p_o_e_t_s_._l_i_s_t for the list of + addresses making up the group. + + SSeennddmmaaiill returns an exit status describing what it did. + The codes are defined in <_s_y_s_e_x_i_t_s_._h>: + + EX_OK Successful completion on all addresses. + + + + + + $Date: 2000/04/02 19:05:47 $ 7 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + EX_NOUSER + User name not recognized. + + EX_UNAVAILABLE + Catchall meaning necessary resources were not + available. + + EX_SYNTAX + Syntax error in address. + + EX_SOFTWARE + Internal software error, including bad arguments. + + EX_OSERR + Temporary operating system error, such as ``cannot + fork''. + + EX_NOHOST + Host name not recognized. + + EX_TEMPFAIL + Message could not be sent immediately, but was + queued. + + If invoked as nneewwaalliiaasseess, sseennddmmaaiill will rebuild the alias + database. If invoked as mmaaiillqq, sseennddmmaaiill will print the + contents of the mail queue. If invoked as hhoossttssttaatt, sseenndd-- + mmaaiill will print the persistent host status database. If + invoked as ppuurrggeessttaatt, sseennddmmaaiill will purge expired entries + from the persistent host status database. If invoked as + ssmmttppdd, sseennddmmaaiill will act as a daemon, as if the --bbdd option + were specified. + +NNOOTTEESS + sseennddmmaaiill often gets blamed for many problems that are + actually the result of other problems, such as overly per- + missive modes on directories. For this reason, sseennddmmaaiill + checks the modes on system directories and files to deter- + mine if they can be trusted. Although these checks can be + turned off and your system security reduced by setting the + DDoonnttBBllaammeeSSeennddmmaaiill option, the permission problems should + be fixed. For more information, see: + + _h_t_t_p_:_/_/_w_w_w_._s_e_n_d_m_a_i_l_._o_r_g_/_t_i_p_s_/_D_o_n_t_B_l_a_m_e_S_e_n_d_m_a_i_l_._h_t_m_l + +FFIILLEESS + Except for the file _/_e_t_c_/_m_a_i_l_/_s_e_n_d_m_a_i_l_._c_f itself the fol- + lowing pathnames are all specified in _/_e_t_c_/_m_a_i_l_/_s_e_n_d_- + _m_a_i_l_._c_f. Thus, these values are only approximations. + + + /etc/mail/aliases + raw data for alias names + + + + + $Date: 2000/04/02 19:05:47 $ 8 + + + + + +SENDMAIL(8) SENDMAIL(8) + + + /etc/mail/aliases.db + data base of alias names + + /etc/mail/sendmail.cf + configuration file + + /etc/mail/helpfile + help file + + /etc/mail/statistics + collected statistics + + /var/spool/mqueue/* + temp files + +SSEEEE AALLSSOO + binmail(1), mail(1), rmail(1), syslog(3), aliases(5), + mailaddr(7), rc(8) + + DARPA Internet Request For Comments _R_F_C_8_1_9, _R_F_C_8_2_1, + _R_F_C_8_2_2. _S_e_n_d_m_a_i_l _- _A_n _I_n_t_e_r_n_e_t_w_o_r_k _M_a_i_l _R_o_u_t_e_r, No. 9, + SMM. _S_e_n_d_m_a_i_l _I_n_s_t_a_l_l_a_t_i_o_n _a_n_d _O_p_e_r_a_t_i_o_n _G_u_i_d_e, No. 8, + SMM. + + http://www.sendmail.org/ + +HHIISSTTOORRYY + The sseennddmmaaiill command appeared in 4.2BSD. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $Date: 2000/04/02 19:05:47 $ 9 + + diff --git a/gnu/usr.sbin/sendmail/sendmail/sendmail.8 b/gnu/usr.sbin/sendmail/sendmail/sendmail.8 new file mode 100644 index 00000000000..c184af4d08a --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sendmail.8 @@ -0,0 +1,685 @@ +.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1983, 1997 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: sendmail.8,v 8.36 2000/02/01 05:49:57 gshapiro Exp $ +.\" +.TH SENDMAIL 8 "$Date: 2000/04/02 19:05:47 $" +.SH NAME +.B sendmail +\- an electronic mail transport agent +.SH SYNOPSIS +.B sendmail +.RI [ flags "] [" "address ..." ] +.br +.B newaliases +.br +.B mailq +.RB [ \-v ] +.br +.B hoststat +.br +.B purgestat +.br +.B smtpd +.SH DESCRIPTION +.B Sendmail +sends a message to one or more +.I recipients, +routing the message over whatever networks +are necessary. +.B Sendmail +does internetwork forwarding as necessary +to deliver the message to the correct place. +.PP +.B Sendmail +is not intended as a user interface routine; +other programs provide user-friendly +front ends; +.B sendmail +is used only to deliver pre-formatted messages. +.PP +With no flags, +.B 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. +Beginning with 8.10, the sender is included in any alias +expansions, e.g., +if `john' sends to `group', +and `group' includes `john' in the expansion, +then the letter will also be delivered to `john'. +.SS Parameters +.TP +.BI \-B type +Set the body type to +.IR type . +Current legal values are +7BIT +or +8BITMIME. +.TP +.B \-ba +Go into +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. +.TP +.B \-bd +Run as a daemon. This requires Berkeley +IPC. +.B Sendmail +will fork and run in background +listening on socket 25 for incoming +SMTP +connections. +This is normally run from +/etc/rc. +.TP +.B \-bD +Same as +.B \-bd +except runs in foreground. +.TP +.B \-bh +Print the persistent host status database. +.TP +.B \-bH +Purge expired entries from the persistent host status database. +.TP +.B \-bi +Initialize the alias database. +.TP +.B \-bm +Deliver mail in the usual way (default). +.TP +.B \-bp +Print a listing of the queue. +.TP +.B \-bs +Use the +SMTP +protocol as described in +RFC821 +on standard input and output. +This flag implies all the operations of the +.B \-ba +flag that are compatible with +SMTP. +.TP +.B \-bt +Run in address test mode. +This mode reads addresses and shows the steps in parsing; +it is used for debugging configuration tables. +.TP +.B \-bv +Verify names only \- do not try to collect or deliver a message. +Verify mode is normally used for validating +users or mailing lists. +.TP +.BI \-C file +Use alternate configuration file. +.B Sendmail +refuses to run as root if an alternate configuration file is specified. +.TP +.BI \-d X +Set debugging value to +.IR X . +.ne 1i +.TP +.BI \-F fullname +Set the full name of the sender. +.TP +.BI \-f name +Sets the name of the ``from'' person +(i.e., the envelope sender of the mail). +This address may also be used in the From: header +if that header is missing during initial submission. +The envelope sender address is used as the recipient +for delivery status notifications +and may also appear in a Return-Path: header. +.B \-f +should only be used +by ``trusted'' users +(normally +.IR root ", " daemon , +and +.IR network ) +or if the person you are trying to become +is the same as the person you are. +Otherwise, +an X-Authentication-Warning header +will be added to the message. +.TP +.BI \-h N +Set the hop count to +.IR 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. +.TP +.B \-i +Ignore dots alone on lines by themselves in incoming messages. +This should be set if you are reading data from a file. +.TP +.BI "\-L " tag +Set the identifier used in syslog messages to the supplied +.IR tag . +.TP +.BI "\-N " dsn +Set delivery status notification conditions to +.IR dsn , +which can be +`never' +for no notifications +or a comma separated list of the values +`failure' +to be notified if delivery failed, +`delay' +to be notified if delivery is delayed, and +`success' +to be notified when the message is successfully delivered. +.TP +.B \-n +Don't do aliasing. +.TP +\fB\-O\fP \fIoption\fR=\fIvalue\fR +Set option +.I option +to the specified +.IR value . +This form uses long names. See below for more details. +.TP +.BI \-o "x value" +Set option +.I x +to the specified +.IR value . +This form uses single character names only. +The short names are not described in this manual page; +see the +.I "Sendmail Installation and Operation Guide" +for details. +.TP +.BI \-p 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''. +.TP +\fB\-q\fR[\fItime\fR] +Processed saved messages in the queue at given intervals. +If +.I time +is omitted, process the queue once. +.I Time +is given as a tagged number, +with +`s' +being seconds, +`m' +being minutes, +`h' +being hours, +`d' +being days, +and +`w' +being weeks. +For example, +`\-q1h30m' +or +`\-q90m' +would both set the timeout to one hour thirty minutes. +If +.I time +is specified, +.B sendmail +will run in the background. +This option can be used safely with +.BR \-bd . +.TP +.BI \-qI substr +Limit processed jobs to those containing +.I substr +as a substring of the queue id. +.TP +.BI \-qR substr +Limit processed jobs to those containing +.I substr +as a substring of one of the recipients. +.TP +.BI \-qS substr +Limit processed jobs to those containing +.I substr +as a substring of the sender. +.TP +.BI "\-R " return +Set the amount of the message to be returned +if the message bounces. +The +.I return +parameter can be +`full' +to return the entire message or +`hdrs' +to return only the headers. +In the latter case also local bounces return only the headers. +.TP +.BI \-r name +An alternate and obsolete form of the +.B \-f +flag. +.TP +.B \-t +Read message for recipients. +To:, Cc:, and Bcc: lines will be scanned for recipient addresses. +The Bcc: line will be deleted before transmission. +.TP +.B \-U +Initial (user) submission. This should +.I always +be set when called from a user agent such as +.B Mail +or +.B exmh +and +.I never +be set when called by a network delivery agent such as +.BR rmail . +.TP +.BI "\-V " envid +Set the original envelope id. +This is propagated across SMTP to servers that support DSNs +and is returned in DSN-compliant error messages. +.TP +.B \-v +Go into verbose mode. +Alias expansions will be announced, etc. +.TP +.BI "\-X " 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. +.TP +.B \-\- +Stop processing command flags and use the rest of the arguments as +addresses. +.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 +.B \-o +flag (for short names), the +.B \-O +flag (for long names), +or in the configuration file. +This is a partial list limited to those options that are likely to be useful +on the command line +and only shows the long names; +for a complete list (and details), consult the +.IR "Sendmail Installation and Operation Guide" . +The options are: +.TP +.RI AliasFile= file +Use alternate alias file. +.TP +HoldExpensive +On mailers that are considered ``expensive'' to connect to, +don't initiate immediate connection. +This requires queueing. +.TP +.RI CheckpointInterval= N +Checkpoint the queue file after every +.I N +successful deliveries (default 10). +This avoids excessive duplicate deliveries +when sending to long mailing lists +interrupted by system crashes. +.ne 1i +.TP +.RI DeliveryMode= x +Set the delivery mode to +.IR x . +Delivery modes are +`i' +for interactive (synchronous) delivery, +`b' +for background (asynchronous) delivery, +`q' +for queue only \- i.e., +actual delivery is done the next time the queue is run, and +`d' +for deferred \- the same as +`q' +except that database lookups for maps which have set the \-D option +(default for the host map) are avoided. +.TP +.RI ErrorMode= x +Set error processing to mode +.IR x . +Valid modes are +`m' +to mail back the error message, +`w' +to ``write'' +back the error message +(or mail it back if the sender is not logged in), +`p' +to print the errors on the terminal +(default), +`q' +to throw away error messages +(only exit status is returned), +and +`e' +to do special processing for the BerkNet. +If the text of the message is not mailed back +by +modes +`m' +or +`w' +and if the sender is local to this machine, +a copy of the message is appended to the file +.I dead.letter +in the sender's home directory. +.TP +SaveFromLine +Save +UNIX-style +From lines at the front of messages. +.TP +.RI MaxHopCount= N +The maximum number of times a message is allowed to ``hop'' +before we decide it is in a loop. +.TP +IgnoreDots +Do not take dots on a line by themselves +as a message terminator. +.TP +SendMimeErrors +Send error messages in MIME format. +If not set, the DSN (Delivery Status Notification) SMTP extension +is disabled. +.TP +.RI ConnectionCacheTimeout= timeout +Set connection cache timeout. +.TP +.RI ConnectionCacheSize= N +Set connection cache size. +.TP +.RI LogLevel= n +The log level. +.TP +.RI MeToo= False +Don't send to ``me'' (the sender) if I am in an alias expansion. +.TP +CheckAliases +Validate the right hand side of aliases during a +newaliases(1) +command. +.TP +OldStyleHeaders +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. +.TP +.RI QueueDirectory= queuedir +Select the directory in which to queue messages. +.TP +.RI StatusFile= file +Save statistics in the named file. +.TP +.RI Timeout.queuereturn= 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 five days. +.TP +.RI UserDatabaseSpec= 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 +USERDB +option compiled in. +.TP +ForkEachJob +Fork each job during queue runs. +May be convenient on memory-poor machines. +.TP +SevenBitInput +Strip incoming messages to seven bits. +.TP +.RI EightBitMode= mode +Set the handling of eight bit input to seven bit destinations to +.IR mode : +m +(mimefy) will convert to seven-bit MIME format, +p +(pass) will pass it as eight bits (but violates protocols), +and +s +(strict) will bounce the message. +.TP +.RI MinQueueAge= timeout +Sets how long a job must ferment in the queue between attempts to send it. +.TP +.RI DefaultCharSet= charset +Sets the default character set used to label 8-bit data +that is not otherwise labelled. +.TP +.RI DialDelay= sleeptime +If opening a connection fails, +sleep for +.I sleeptime +seconds and try again. +Useful on dial-on-demand sites. +.TP +.RI NoRecipientAction= action +Set the behaviour when there are no recipient headers (To:, Cc: or +Bcc:) in the message to +.IR action : +none +leaves the message unchanged, +add-to +adds a To: header with the envelope recipients, +add-apparently-to +adds an Apparently-To: header with the envelope recipients, +add-bcc +adds an empty Bcc: header, and +add-to-undisclosed +adds a header reading +`To: undisclosed-recipients:;'. +.TP +.RI MaxDaemonChildren= N +Sets the maximum number of children that an incoming SMTP daemon +will allow to spawn at any time to +.IR N . +.TP +.RI ConnectionRateThrottle= N +Sets the maximum number of connections per second to the SMTP port to +.IR N . +.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 +.B sendmail +from suppressing the blanks from between arguments. +For example, a common alias is: +.IP +msgs: "|/usr/bin/msgs -s" +.PP +Aliases may also have the syntax +.RI ``:include: filename '' +to ask +.B sendmail +to read the named file for a list of recipients. +For example, an alias such as: +.IP +poets: ":include:/usr/local/lib/poets.list" +.PP +would read +.I /usr/local/lib/poets.list +for the list of addresses making up the group. +.PP +.B Sendmail +returns an exit status +describing what it did. +The codes are defined in +.RI < sysexits.h >: +.TP +EX_OK +Successful completion on all addresses. +.TP +EX_NOUSER +User name not recognized. +.TP +EX_UNAVAILABLE +Catchall meaning necessary resources +were not available. +.TP +EX_SYNTAX +Syntax error in address. +.TP +EX_SOFTWARE +Internal software error, +including bad arguments. +.TP +EX_OSERR +Temporary operating system error, +such as +``cannot fork''. +.TP +EX_NOHOST +Host name not recognized. +.TP +EX_TEMPFAIL +Message could not be sent immediately, +but was queued. +.PP +If invoked as +.BR newaliases , +.B sendmail +will rebuild the alias database. If invoked as +.BR mailq , +.B sendmail +will print the contents of the mail queue. +If invoked as +.BR hoststat , +.B sendmail +will print the persistent host status database. +If invoked as +.BR purgestat , +.B sendmail +will purge expired entries from the persistent host status database. +If invoked as +.BR smtpd , +.B sendmail +will act as a daemon, as if the +.B \-bd +option were specified. +.SH NOTES +.B sendmail +often gets blamed for many problems +that are actually the result of other problems, +such as overly permissive modes on directories. +For this reason, +.B sendmail +checks the modes on system directories and files +to determine if they can be trusted. +Although these checks can be turned off +and your system security reduced by setting the +.BR DontBlameSendmail +option, +the permission problems should be fixed. +For more information, see: + +.I http://www.sendmail.org/tips/DontBlameSendmail.html +.SH FILES +Except for the file +.I /etc/mail/sendmail.cf +itself the following pathnames are all specified in +.IR /etc/mail/sendmail.cf . +Thus, +these values are only approximations. +.PP +.TP + /etc/mail/aliases +raw data for alias names +.TP + /etc/mail/aliases.db +data base of alias names +.TP + /etc/mail/sendmail.cf +configuration file +.TP + /etc/mail/helpfile +help file +.TP + /etc/mail/statistics +collected statistics +.TP + /var/spool/mqueue/* +temp files +.SH SEE ALSO +binmail(1), +mail(1), +rmail(1), +syslog(3), +aliases(5), +mailaddr(7), +rc(8) +.PP +DARPA +Internet Request For Comments +.IR RFC819 , +.IR RFC821 , +.IR RFC822 . +.IR "Sendmail \- An Internetwork Mail Router" , +No. 9, SMM. +.IR "Sendmail Installation and Operation Guide" , +No. 8, SMM. +.PP +http://www.sendmail.org/ +.SH HISTORY +The +.B sendmail +command appeared in +4.2BSD. diff --git a/gnu/usr.sbin/sendmail/sendmail/sendmail.h b/gnu/usr.sbin/sendmail/sendmail/sendmail.h new file mode 100644 index 00000000000..84d083170e4 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sendmail.h @@ -0,0 +1,1962 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +/* +** SENDMAIL.H -- MTA-specific definitions for sendmail. +*/ + +#ifndef _SENDMAIL_H +#define _SENDMAIL_H 1 + +#ifdef _DEFINE +# define EXTERN +# ifndef lint +static char SmailId[] = "@(#)$Sendmail: sendmail.h,v 8.513 2000/02/26 07:30:06 gshapiro Exp $"; +# endif /* ! lint */ +#else /* _DEFINE */ +# define EXTERN extern +#endif /* _DEFINE */ + + +#include +#include +#include +# include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* for SVr4.2 SMP */ +#endif /* EX_OK */ +#include + +#include "sendmail/sendmail.h" +#include "bf.h" +#include "timers.h" + +#ifdef LOG +# include +#endif /* LOG */ + +#if NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 +# include +#endif /* NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 */ +#if NETUNIX +# include +#endif /* NETUNIX */ +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ +#if NETINET6 +/* +** There is no standard yet for IPv6 includes. +** Specify OS specific implementation in conf.h +*/ +#endif /* NETINET6 */ +#if NETISO +# include +#endif /* NETISO */ +#if NETNS +# include +#endif /* NETNS */ +#if NETX25 +# include +#endif /* NETX25 */ + +#if NAMED_BIND +# include +# ifdef NOERROR +# undef NOERROR /* avoid conflict */ +# endif /* NOERROR */ +# include +#endif /* NAMED_BIND */ + +#ifdef HESIOD +# include +# if !defined(HES_ER_OK) || defined(HESIOD_INTERFACES) +# define HESIOD_INIT /* support for the new interface */ +# endif /* !defined(HES_ER_OK) || defined(HESIOD_INTERFACES) */ +#endif /* HESIOD */ + + +#if SASL /* include the sasl include files if we have them */ +# include +# if defined(SASL_VERSION_MAJOR) && defined(SASL_VERSION_MINOR) && defined(SASL_VERSION_STEP) +# define SASL_VERSION (SASL_VERSION_MAJOR * 10000) + (SASL_VERSION_MINOR * 100) + SASL_VERSION_STEP +# if SASL == 1 +# undef SASL +# define SASL SASL_VERSION +# else /* SASL == 1 */ +# if SASL != SASL_VERSION + ERROR README: -DSASL (SASL) does not agree with the version of the CYRUS_SASL library (SASL_VERSION) + ERROR README: see README! +# endif /* SASL != SASL_VERSION */ +# endif /* SASL == 1 */ +# else /* defined(SASL_VERSION_MAJOR) && defined(SASL_VERSION_MINOR) && defined(SASL_VERSION_STEP) */ +# if SASL == 1 + ERROR README: please set -DSASL to the version of the CYRUS_SASL library + ERROR README: see README! +# endif /* SASL == 1 */ +# endif /* defined(SASL_VERSION_MAJOR) && defined(SASL_VERSION_MINOR) && defined(SASL_VERSION_STEP) */ +#endif /* SASL */ + +/* +** Following are "sort of" configuration constants, but they should +** be pretty solid on most architectures today. They have to be +** defined after because some versions of that +** file also define them. In all cases, we can't use sizeof because +** some systems (e.g., Crays) always treat everything as being at +** least 64 bits. +*/ + +#ifndef INADDRSZ +# define INADDRSZ 4 /* size of an IPv4 address in bytes */ +#endif /* ! INADDRSZ */ +#ifndef IN6ADDRSZ +# define IN6ADDRSZ 16 /* size of an IPv6 address in bytes */ +#endif /* ! IN6ADDRSZ */ +#ifndef INT16SZ +# define INT16SZ 2 /* size of a 16 bit integer in bytes */ +#endif /* ! INT16SZ */ +#ifndef INT32SZ +# define INT32SZ 4 /* size of a 32 bit integer in bytes */ +#endif /* ! INT32SZ */ + +/* +** Error return from inet_addr(3), in case not defined in /usr/include. +*/ + +#ifndef INADDR_NONE +# define INADDR_NONE 0xffffffff +#endif /* ! INADDR_NONE */ + + +/* forward references for prototypes */ +typedef struct envelope ENVELOPE; +typedef struct mailer MAILER; + + /* +** 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_state; /* address state, see below */ + short q_specificity; /* how "specific" this address is */ +}; + +typedef struct address ADDRESS; + +/* bit values for q_flags */ +#define QGOODUID 0x00000001 /* the q_uid q_gid fields are good */ +#define QPRIMARY 0x00000002 /* set from RCPT or argv */ +#define QNOTREMOTE 0x00000004 /* address not for remote forwarding */ +#define QSELFREF 0x00000008 /* this address references itself */ +#define QBOGUSSHELL 0x00000010 /* user has no valid shell listed */ +#define QUNSAFEADDR 0x00000020 /* address acquired via unsafe path */ +#define QPINGONSUCCESS 0x00000040 /* give return on successful delivery */ +#define QPINGONFAILURE 0x00000080 /* give return on failure */ +#define QPINGONDELAY 0x00000100 /* give return on message delay */ +#define QHASNOTIFY 0x00000200 /* propogate notify parameter */ +#define QRELAYED 0x00000400 /* DSN: relayed to non-DSN aware sys */ +#define QEXPANDED 0x00000800 /* DSN: undergone list expansion */ +#define QDELIVERED 0x00001000 /* DSN: successful final delivery */ +#define QDELAYED 0x00002000 /* DSN: message delayed */ +#define QALIAS 0x00004000 /* expanded alias */ +#define QTHISPASS 0x40000000 /* temp: address set this pass */ +#define QRCPTOK 0x80000000 /* recipient() processed address */ + +#define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY) + +/* values for q_state */ +#define QS_OK 0 /* address ok (for now)/not yet tried */ +#define QS_SENT 1 /* good address, delivery complete */ +#define QS_BADADDR 2 /* illegal address */ +#define QS_QUEUEUP 3 /* save address in queue */ +#define QS_VERIFIED 4 /* verified, but not expanded */ +#define QS_DONTSEND 5 /* don't send to this address */ +#define QS_EXPANDED 6 /* expanded */ +#define QS_SENDER 7 /* message sender (MeToo) */ +#define QS_CLONED 8 /* addr cloned to a split envelope */ +#define QS_DISCARDED 9 /* recipient discarded (EF_DISCARD) */ +#define QS_REPLACED 10 /* maplocaluser()/UserDB replaced */ +#define QS_REMOVED 11 /* removed (removefromlist()) */ +#define QS_DUPLICATE 12 /* duplicate suppressed */ +#define QS_INCLUDED 13 /* :include: delivery */ + +/* address state testing primitives */ +#define QS_IS_OK(s) ((s) == QS_OK) +#define QS_IS_SENT(s) ((s) == QS_SENT) +#define QS_IS_BADADDR(s) ((s) == QS_BADADDR) +#define QS_IS_QUEUEUP(s) ((s) == QS_QUEUEUP) +#define QS_IS_VERIFIED(s) ((s) == QS_VERIFIED) +#define QS_IS_EXPANDED(s) ((s) == QS_EXPANDED) +#define QS_IS_UNDELIVERED(s) ((s) == QS_OK || \ + (s) == QS_QUEUEUP || \ + (s) == QS_VERIFIED) +#define QS_IS_SENDABLE(s) ((s) == QS_OK || \ + (s) == QS_QUEUEUP) +#define QS_IS_ATTEMPTED(s) ((s) == QS_QUEUEUP || \ + (s) == QS_SENT) +#define QS_IS_DEAD(s) ((s) == QS_DONTSEND || \ + (s) == QS_CLONED || \ + (s) == QS_SENDER || \ + (s) == QS_DISCARDED || \ + (s) == QS_REPLACED || \ + (s) == QS_REMOVED || \ + (s) == QS_DUPLICATE || \ + (s) == QS_INCLUDED || \ + (s) == QS_EXPANDED) + + +#define NULLADDR ((ADDRESS *) NULL) + +extern ADDRESS NullAddress; /* a null (template) address [main.c] */ + +/* functions */ +extern void cataddr __P((char **, char **, char *, int, int)); +extern char *crackaddr __P((char *)); +extern bool emptyaddr __P((ADDRESS *)); +extern ADDRESS *getctladdr __P((ADDRESS *)); +extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern bool invalidaddr __P((char *, char *)); +extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *)); +extern char **prescan __P((char *, int, char[], int, char **, u_char *)); +extern void printaddr __P((ADDRESS *, bool)); +extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *)); +extern int rewrite __P((char **, int, int, ENVELOPE *)); +extern bool sameaddr __P((ADDRESS *, ADDRESS *)); +extern int sendtolist __P((char *, ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern int removefromlist __P((char *, ADDRESS **, ENVELOPE *)); +extern void setsender __P((char *, ENVELOPE *, char **, int, bool)); + + /* +** 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 */ + BITMAP256 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 */ + int m_maxdeliveries; /* max deliveries per mailer connection */ + char *m_execdir; /* directory to chdir to before execv */ + char *m_rootdir; /* directory to chroot 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 */ + time_t m_wait; /* timeout to wait for end */ +}; + +/* 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_CHUNKING 'K' /* CHUNKING: reserved for future use */ +#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_VRFY250 'q' /* VRFY command returns 250 instead of 252 */ +#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_LMTP 'z' /* run Local Mail Transport Protocol */ +#define M_NOMX '0' /* turn off MX lookups */ +#define M_NONULLS '1' /* don't send null bytes */ +#define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */ +#define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */ +#define M_7BITHDRS '6' /* strip headers to 7 bits even in 8 bit path */ +#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 */ +#define M_CHECKHDIR '~' /* SGI: check for valid home directory */ +#define M_HOLD '%' /* Hold delivery until ETRN/-qI/-qR/-qS */ +#define M_PLUS '+' /* Reserved: Used in mc for adding new flags */ +#define M_MINUS '-' /* Reserved: Used in mc for removing flags */ + +/* functions */ +extern void initerrmailers __P((void)); +extern void makemailer __P((char *)); + + /* +** Information about currently open connections to mailers, or to +** hosts that we have looked up recently. +*/ + +#define MCI struct mailer_con_info + +MCI +{ + u_long 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 */ + int mci_deliveries; /* delivery attempts for connection */ + long mci_maxsize; /* max size this server will accept */ + FILE *mci_in; /* input side of connection */ + FILE *mci_out; /* output side of connection */ + pid_t 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 */ + char *mci_rstatus; /* SMTP status to be copied to addrs */ + time_t mci_lastuse; /* last usage time */ + FILE *mci_statfile; /* long term status file */ + char *mci_heloname; /* name to use as HELO arg */ +#if SASL + bool mci_sasl_auth; /* authenticated? */ + int mci_sasl_string_len; + char *mci_sasl_string; /* sasl reply string */ + char *mci_saslcap; /* SASL list of mechanisms */ + sasl_conn_t *mci_conn; /* SASL connection */ +#endif /* SASL */ +}; + + +/* flag bits */ +#define MCIF_VALID 0x00000001 /* this entry is valid */ +#define MCIF_TEMP 0x00000002 /* don't cache this connection */ +#define MCIF_CACHED 0x00000004 /* currently in open cache */ +#define MCIF_ESMTP 0x00000008 /* this host speaks ESMTP */ +#define MCIF_EXPN 0x00000010 /* EXPN command supported */ +#define MCIF_SIZE 0x00000020 /* SIZE option supported */ +#define MCIF_8BITMIME 0x00000040 /* BODY=8BITMIME supported */ +#define MCIF_7BIT 0x00000080 /* strip this message to 7 bits */ +#define MCIF_MULTSTAT 0x00000100 /* MAIL11V3: handles MULT status */ +#define MCIF_INHEADER 0x00000200 /* currently outputing header */ +#define MCIF_CVT8TO7 0x00000400 /* convert from 8 to 7 bits */ +#define MCIF_DSN 0x00000800 /* DSN extension supported */ +#define MCIF_8BITOK 0x00001000 /* OK to send 8 bit characters */ +#define MCIF_CVT7TO8 0x00002000 /* convert from 7 to 8 bits */ +#define MCIF_INMIME 0x00004000 /* currently reading MIME header */ +#define MCIF_AUTH 0x00008000 /* AUTH= supported */ +#define MCIF_AUTHACT 0x00010000 /* SASL (AUTH) active */ +#define MCIF_ENHSTAT 0x00020000 /* ENHANCEDSTATUSCODES supported */ +#define MCIF_EXTENS (MCIF_EXPN | MCIF_SIZE | MCIF_8BITMIME | MCIF_DSN | MCIF_8BITOK | MCIF_AUTH | MCIF_ENHSTAT) + +/* 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 void mci_cache __P((MCI *)); +extern void mci_dump __P((MCI *, bool)); +extern void mci_dump_all __P((bool)); +extern void mci_flush __P((bool, MCI *)); +extern MCI *mci_get __P((char *, MAILER *)); +extern int mci_lock_host __P((MCI *)); +extern bool mci_match __P((char *, MAILER *)); +extern int mci_print_persistent __P((char *, char *)); +extern int mci_purge_persistent __P((char *, char *)); +extern MCI **mci_scan __P((MCI *)); +extern void mci_setstat __P((MCI *, int, char *, char *)); +extern void mci_store_persistent __P((MCI *)); +extern int mci_traverse_persistent __P((int (*)(), char *)); +extern void mci_unlock_host __P((MCI *)); + + /* +** 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_char h_macro; /* include header if macro defined */ + u_long h_flags; /* status bits, see below */ + BITMAP256 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_long hi_flags; /* status bits, see below */ + char *hi_ruleset; /* validity check ruleset */ +}; + +extern struct hdrinfo HdrInfo[]; + +/* bits for h_flags and hi_flags */ +#define H_EOH 0x00000001 /* field terminates header */ +#define H_RCPT 0x00000002 /* contains recipient addresses */ +#define H_DEFAULT 0x00000004 /* if another value is found, drop this */ +#define H_RESENT 0x00000008 /* this address is a "Resent-..." address */ +#define H_CHECK 0x00000010 /* check h_mflags against m_flags */ +#define H_ACHECK 0x00000020 /* ditto, but always (not just default) */ +#define H_FORCE 0x00000040 /* force this field, even if default */ +#define H_TRACE 0x00000080 /* this field contains trace information */ +#define H_FROM 0x00000100 /* this is a from-type field */ +#define H_VALID 0x00000200 /* this field has a validated value */ +#define H_RECEIPTTO 0x00000400 /* field has return receipt info */ +#define H_ERRORSTO 0x00000800 /* field has error address info */ +#define H_CTE 0x00001000 /* field is a content-transfer-encoding */ +#define H_CTYPE 0x00002000 /* this is a content-type field */ +#define H_BCC 0x00004000 /* Bcc: header: strip value or delete */ +#define H_ENCODABLE 0x00008000 /* field can be RFC 1522 encoded */ +#define H_STRIPCOMM 0x00010000 /* header check: strip comments */ +#define H_BINDLATE 0x00020000 /* only expand macros at deliver */ + +/* bits for chompheader() */ +#define CHHDR_DEF 0x0001 /* default header */ +#define CHHDR_CHECK 0x0002 /* call ruleset for header */ +#define CHHDR_USER 0x0004 /* header from user */ +#if _FFR_MILTER +# define CHHDR_MILTER 0x0008 /* call milter filter for header */ +#endif /* _FFR_MILTER */ + +/* functions */ +extern void addheader __P((char *, char *, HDR **)); +extern u_long chompheader __P((char *, int *, HDR **, ENVELOPE *)); +extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *)); +extern HDR *copyheader __P((HDR *)); +extern void eatheader __P((ENVELOPE *, bool)); +extern char *hvalue __P((char *, HDR *)); +extern bool isheader __P((char *)); +extern void putfromline __P((MCI *, ENVELOPE *)); +extern void setupheaders __P((void)); + + /* +** Performance monitoring +*/ + +#define TIMERS struct sm_timers + +TIMERS +{ + TIMER ti_overall; /* the whole process */ +}; + + +#define PUSHTIMER(l, t) { if (tTd(98, l)) pushtimer(&t); } +#define POPTIMER(l, t) { if (tTd(98, l)) poptimer(&t); } + + /* +** 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 */ + 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 *, int)); + /* function to put header of message */ + void (*e_putbody)__P((MCI *, ENVELOPE *, char *)); + /* function to put body of message */ + ENVELOPE *e_parent; /* the message this one encloses */ + ENVELOPE *e_sibling; /* the next envelope of interest */ + char *e_bodytype; /* type of message body */ + FILE *e_dfp; /* data file */ + char *e_id; /* code for this entry in queue */ + int e_queuedir; /* index into queue directories */ + 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 */ + char *e_auth_param; + TIMERS e_timers; /* per job timers */ +#if _FFR_QUEUEDELAY + int e_queuealg; /* algorithm for queue delay */ + time_t e_queuedelay; /* current delay */ +#endif /* _FFR_QUEUEDELAY */ +}; + +/* values for e_flags */ +#define EF_OLDSTYLE 0x0000001L /* use spaces (not commas) in hdrs */ +#define EF_INQUEUE 0x0000002L /* this message is fully queued */ +#define EF_NO_BODY_RETN 0x0000004L /* omit message body on error */ +#define EF_CLRQUEUE 0x0000008L /* disk copy is no longer needed */ +#define EF_SENDRECEIPT 0x0000010L /* send a return receipt */ +#define EF_FATALERRS 0x0000020L /* fatal errors occurred */ +#define EF_DELETE_BCC 0x0000040L /* delete Bcc: headers entirely */ +#define EF_RESPONSE 0x0000080L /* this is an error or return receipt */ +#define EF_RESENT 0x0000100L /* this message is being forwarded */ +#define EF_VRFYONLY 0x0000200L /* verify only (don't expand aliases) */ +#define EF_WARNING 0x0000400L /* warning message has been sent */ +#define EF_QUEUERUN 0x0000800L /* this envelope is from queue */ +#define EF_GLOBALERRS 0x0001000L /* treat errors as global */ +#define EF_PM_NOTIFY 0x0002000L /* send return mail to postmaster */ +#define EF_METOO 0x0004000L /* send to me too */ +#define EF_LOGSENDER 0x0008000L /* need to log the sender */ +#define EF_NORECEIPT 0x0010000L /* suppress all return-receipts */ +#define EF_HAS8BIT 0x0020000L /* at least one 8-bit char in body */ +#define EF_NL_NOT_EOL 0x0040000L /* don't accept raw NL as EOLine */ +#define EF_CRLF_NOT_EOL 0x0080000L /* don't accept CR-LF as EOLine */ +#define EF_RET_PARAM 0x0100000L /* RCPT command had RET argument */ +#define EF_HAS_DF 0x0200000L /* set when df file is instantiated */ +#define EF_IS_MIME 0x0400000L /* really is a MIME message */ +#define EF_DONT_MIME 0x0800000L /* never MIME this message */ +#define EF_DISCARD 0x1000000L /* discard the message */ + +/* functions */ +extern void clearenvelope __P((ENVELOPE *, bool)); +extern void dropenvelope __P((ENVELOPE *, bool)); +extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *)); +extern void printenvflags __P((ENVELOPE *)); +extern void putbody __P((MCI *, ENVELOPE *, char *)); +extern void putheader __P((MCI *, HDR *, ENVELOPE *, int)); + + /* +** 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 */ +}; + + /* +** Rewrite rules. +*/ + +struct rewrite +{ + char **r_lhs; /* pattern match */ + char **r_rhs; /* substitution value */ + struct rewrite *r_next;/* next in chain */ + int r_line; /* rule line in sendmail.cf */ +}; + +/* +** 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 define __P((int, char *, ENVELOPE *)); +extern void expand __P((char *, char *, size_t, ENVELOPE *)); +extern int macid __P((char *, char **)); +extern char *macname __P((int)); +extern char *macvalue __P((int, ENVELOPE *)); +extern int rscheck __P((char *, char *, char *, ENVELOPE *, bool, bool)); +extern void setclass __P((int, char *)); +extern int strtorwset __P((char *, char **, int)); +extern void translate_dollars __P((char *)); +extern bool wordinclass __P((char *, int)); + + /* +** 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 */ + +/* functions */ +extern bool getcanonname __P((char *, int, bool)); +extern int getmxrr __P((char *, char **, u_short *, bool, int *)); + + /* +** 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 5 /* 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_spacesub; /* spacesub */ + char *map_app; /* to append to successful matches */ + char *map_tapp; /* to append to "tempfail" 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 */ + pid_t map_pid; /* PID of process which opened map */ + int map_lockfd; /* auxiliary lock file descriptor */ + short map_specificity; /* specificity of aliases */ + 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 rebuild */ +#define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */ +#define MF_NODEFER 0x00020000 /* don't defer if map lookup fails */ +#define MF_REGEX_NOT 0x00040000 /* regular expression negation */ +#define MF_DEFER 0x00080000 /* don't lookup map in defer mode */ +#define MF_SINGLEMATCH 0x00100000 /* successful only if match one key */ +#define MF_NOREWRITE 0x00200000 /* don't rewrite result, return as-is */ + +#define DYNOPENMAP(map) if (!bitset(MF_OPEN, (map)->map_mflags)) \ + { \ + if (!openmap(map)) \ + return NULL; \ + } + + +/* 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 void closemaps __P((void)); +extern bool impl_map_open __P((MAP *, int)); +extern void initmaps __P((void)); +extern MAP *makemapentry __P((char *)); +extern void maplocaluser __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern char *map_rewrite __P((MAP *, const char *, size_t, char **)); +#if NETINFO +extern char *ni_propval __P((char *, char *, char *, char *, int)); +#endif /* NETINFO */ +extern bool openmap __P((MAP *)); +#if USERDB +extern void _udbx_close __P((void)); +extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern char *udbsender __P((char *)); +#endif /* USERDB */ + /* +** LDAP related items +*/ +#ifdef LDAPMAP +struct ldapmap_struct +{ + /* needed for ldap_open or ldap_init */ + char *ldap_host; + int ldap_port; + + /* options set in ld struct before ldap_bind_s */ + int ldap_deref; + time_t ldap_timelimit; + int ldap_sizelimit; + int ldap_options; + + /* args for ldap_bind_s */ + LDAP *ldap_ld; + char *ldap_binddn; + char *ldap_secret; + int ldap_method; + + /* args for ldap_search */ + char *ldap_base; + int ldap_scope; + char *ldap_filter; + char *ldap_attr[LDAPMAP_MAX_ATTR + 1]; + bool ldap_attrsonly; + + /* args for ldap_result */ + struct timeval ldap_timeout; + LDAPMessage *ldap_res; +}; + +typedef struct ldapmap_struct LDAPMAP_STRUCT; + +/* struct defining LDAP Auth Methods */ +struct lamvalues +{ + char *lam_name; /* name of LDAP auth method */ + int lam_code; /* numeric code */ +}; + +/* struct defining LDAP Alias Dereferencing */ +struct ladvalues +{ + char *lad_name; /* name of LDAP alias dereferencing method */ + int lad_code; /* numeric code */ +}; + +/* struct defining LDAP Search Scope */ +struct lssvalues +{ + char *lss_name; /* name of LDAP search scope */ + int lss_code; /* numeric code */ +}; + +/* functions */ +extern bool ldapmap_parseargs __P((MAP *, char *)); +extern void ldapmap_set_defaults __P((char *)); +#endif /* LDAPMAP */ + + /* +** PH related items +*/ + +#ifdef PH_MAP +struct ph_map_struct +{ + char *ph_servers; /* list of ph servers */ + char *ph_field_list; /* list of fields to search for match */ + FILE *ph_to_server; + FILE *ph_from_server; + int ph_sockfd; + time_t ph_timeout; +}; +typedef struct ph_map_struct PH_MAP_STRUCT; + +# define DEFAULT_PH_MAP_FIELDS "alias callsign name spacedname" +#endif /* PH_MAP */ + /* +** Process List (proclist) +*/ + +struct procs +{ + pid_t proc_pid; + char *proc_task; + int proc_type; +}; + +#define NO_PID ((pid_t) 0) +#ifndef PROC_LIST_SEG +# define PROC_LIST_SEG 32 /* number of pids to alloc at a time */ +#endif /* ! PROC_LIST_SEG */ + +/* process types */ +#define PROC_NONE 0 +#define PROC_DAEMON 1 +#define PROC_DAEMON_CHILD 2 +#define PROC_QUEUE 3 +#define PROC_QUEUE_CHILD 3 +#define PROC_CONTROL 4 +#define PROC_CONTROL_CHILD 5 + +/* functions */ +extern void proc_list_add __P((pid_t, char *, int)); +extern void proc_list_clear __P((void)); +extern void proc_list_display __P((FILE *)); +extern int proc_list_drop __P((pid_t)); +extern void proc_list_probe __P((void)); +extern void proc_list_set __P((pid_t, char *)); + +#if _FFR_MILTER + /* +** Mail Filters (milter) +*/ + +#include + +#define SMFTO_WRITE 0 /* Timeout for sending information */ +#define SMFTO_READ 1 /* Timeout waiting for a response */ +#define SMFTO_EOM 2 /* Timeout for ACK/NAK to EOM */ + +#define SMFTO_NUM_TO 3 /* Total number of timeouts */ + +struct milter +{ + char *mf_name; /* filter name */ + BITMAP256 mf_flags; /* MTA flags */ + u_long mf_fflags; /* filter flags */ + char *mf_conn; /* connection info */ + int mf_sock; /* connected socket */ + char mf_state; /* state of filter */ + time_t mf_timeout[SMFTO_NUM_TO]; /* timeouts */ +}; + +/* MTA flags */ +# define SMF_REJECT 'R' /* Reject connection on filter fail */ +# define SMF_TEMPFAIL 'T' /* tempfail connection on failure */ + +/* states */ +# define SMFS_CLOSED 'C' /* closed for all further actions */ +# define SMFS_OPEN 'O' /* connected to remote milter filter */ +# define SMFS_INMSG 'M' /* currently servicing a message */ +# define SMFS_DONE 'D' /* done with current message */ +# define SMFS_ERROR 'E' /* error state */ +# define SMFS_READY 'R' /* ready for action */ + +/* 32-bit type used by milter */ +typedef SM_INT32 mi_int32; + +EXTERN struct milter *InputFilters[MAXFILTERS]; +EXTERN char *InputFilterList; +#endif /* _FFR_MILTER */ + /* +** Symbol table definitions +*/ + +struct symtab +{ + char *s_name; /* name to be entered */ + short s_type; /* general type (see below) */ + short s_len; /* length of this entry */ + struct symtab *s_next; /* pointer to next in chain */ + union + { + BITMAP256 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 */ + struct hdrinfo sv_header; /* header metainfo */ + char *sv_service[MAXMAPSTACK]; /* service switch */ +#ifdef LDAPMAP + LDAP *sv_ldap; /* LDAP connection */ +#endif /* LDAPMAP */ +#if _FFR_MILTER + struct milter *sv_milter; /* milter filter name */ +#endif /* _FFR_MILTER */ + } 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_SERVICE 11 /* service switch entry */ +#define ST_HEADER 12 /* special header flags */ +#ifdef LDAPMAP +# define ST_LDAP 13 /* LDAP connection */ +#endif /* LDAPMAP */ +#if _FFR_MILTER +# define ST_MILTER 14 /* milter filter */ +#endif /* _FFR_MILTER */ +#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 +#define s_service s_value.sv_service +#define s_header s_value.sv_header +#ifdef LDAPMAP +# define s_ldap s_value.sv_ldap +#endif /* LDAPMAP */ +#if _FFR_MILTER +# define s_milter s_value.sv_milter +#endif /* _FFR_MILTER */ + +/* opcodes to stab */ +#define ST_FIND 0 /* find entry */ +#define ST_ENTER 1 /* enter if not there */ + +/* functions */ +extern STAB *stab __P((char *, int, int)); +extern void stabapply __P((void (*)(STAB *, int), int)); + + /* +** 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; + +/* functions */ +extern void clrevent __P((EVENT *)); +extern void clear_events __P((void)); +extern EVENT *setevent __P((time_t, void(*)(), int)); + + /* +** 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. +*/ + +#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_FGDAEMON 'D' /* run daemon in foreground */ +#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 */ +#define MD_HOSTSTAT 'h' /* print persistent host stat info */ +#define MD_PURGESTAT 'H' /* purge persistent host stat info */ +#define MD_QUEUERUN 'q' /* queue run */ + +/* 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 */ + +/* functions */ +extern void set_delivery_mode __P((int, ENVELOPE *)); + +/* 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) */ + + +/* 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 */ + + +/* how to handle messages without any recipient addresses */ +#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 */ +#define PXLF_HEADER 0x0004 /* map newlines in headers */ + +/* +** 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_NOVERB 0x0100 /* disallow VERB command entirely */ +#define PRIV_RESTRICTMAILQ 0x1000 /* restrict mailq command */ +#define PRIV_RESTRICTQRUN 0x2000 /* restrict queue run */ +#define PRIV_NOETRN 0x4000 /* disallow ETRN command entirely */ +#define PRIV_NOBODYRETN 0x8000 /* do not return bodies on bounces */ + +/* don't give no info, anyway, anyhow */ +#define PRIV_GOAWAY (0x0fff & ~PRIV_NORECEIPTS) + +/* struct defining such things */ +struct prival +{ + char *pv_name; /* name of privacy flag */ + u_short 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 mime8to7 and putheader. +*/ + +#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 */ +#define M87F_NO8TO7 0x0004 /* don't do 8->7 bit conversions */ + +/* functions */ +extern void mime7to8 __P((MCI *, HDR *, ENVELOPE *)); +extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int)); + +/* +** Flags passed to returntosender. +*/ + +#define RTSF_NO_BODY 0 /* send headers only */ +#define RTSF_SEND_BODY 0x0001 /* include body of message in return */ +#define RTSF_PM_BOUNCE 0x0002 /* this is a postmaster bounce */ + +/* functions */ +extern int returntosender __P((char *, ADDRESS *, int, ENVELOPE *)); + +/* +** Regular UNIX sockaddrs are too small to handle ISO addresses, so +** we are forced to declare a supertype here. +*/ + +#if NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 +union bigsockaddr +{ + struct sockaddr sa; /* general version */ +# if NETUNIX + struct sockaddr_un sunix; /* UNIX family */ +# endif /* NETUNIX */ +# if NETINET + struct sockaddr_in sin; /* INET family */ +# endif /* NETINET */ +# if NETINET6 + struct sockaddr_in6 sin6; /* INET/IPv6 */ +# endif /* NETINET6 */ +# if NETISO + struct sockaddr_iso siso; /* ISO family */ +# endif /* NETISO */ +# if NETNS + struct sockaddr_ns sns; /* XNS family */ +# endif /* NETNS */ +# if NETX25 + struct sockaddr_x25 sx25; /* X.25 family */ +# endif /* NETX25 */ +}; + +# define SOCKADDR union bigsockaddr + +/* functions */ +extern char *anynet_ntoa __P((SOCKADDR *)); +# if NETINET6 +extern char *anynet_ntop __P((struct in6_addr *, char *, size_t)); +# endif /* NETINET6 */ +extern char *hostnamebyanyaddr __P((SOCKADDR *)); +# if DAEMON +extern char *validate_connection __P((SOCKADDR *, char *, ENVELOPE *)); +# endif /* DAEMON */ + +#endif /* NETINET || NETINET6 || NETUNIX || NETISO || NETNS || NETX25 */ + + +/* +** 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@sendmail.org 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 */ +#define VENDOR_SENDMAIL 5 /* Sendmail, Inc. specific config syntax */ + +/* prototypes for vendor-specific hook routines */ +extern void vendor_daemon_setup __P((ENVELOPE *)); +extern void vendor_set_uid __P((UID_T)); + + +/* +** Terminal escape codes. +** +** To make debugging output clearer. +*/ + +struct termescape +{ + char *te_rv_on; /* turn reverse-video on */ + char *te_rv_off; /* turn reverse-video off */ +}; + + /* +** Additional definitions +*/ + +/* d_flags, see daemon.c */ +/* generic rule: lower case: required, upper case: No */ +#define D_AUTHREQ 'a' /* authentication required */ +#define D_BINDIF 'b' /* use if_addr for outgoing connection */ +#define D_CANONREQ 'c' /* canonification required (cf) */ +#define D_IFNHELO 'h' /* use if name for HELO */ +#define D_FQMAIL 'f' /* fq sender address required (cf) */ +#define D_FQRCPT 'r' /* fq recipient address required (cf) */ +#define D_UNQUALOK 'u' /* unqualified address is ok (cf) */ +#define D_NOCANON 'C' /* no canonification (cf) */ +#define D_NOETRN 'E' /* no ETRN (MSA) */ +#define D_ETRNONLY ((char)0x01) /* allow only ETRN (disk low) */ + +/* Flags for submitmode */ +#define SUBMIT_UNKNOWN 0x0000 /* unknown agent type */ +#define SUBMIT_MTA 0x0001 /* act like a message transfer agent */ +#define SUBMIT_MSA 0x0002 /* act like a message submission agent */ + +#if SASL + /* +** SASL +*/ + +/* authenticated? */ +# define SASL_NOT_AUTH 0 /* not authenticated */ +# define SASL_PROC_AUTH 1 /* in process of authenticating */ +# define SASL_IS_AUTH 2 /* authenticated */ + +/* use AUTH= ? */ +# define SASL_AUTH_AUTH 1 /* use auth= only if authenticated */ + +# define MAXOUTLEN 1024 /* length of output buffer */ +#endif /* SASL */ + + + + /* +** Queue related items +*/ + +/* queue sort order */ +#define QSO_BYPRIORITY 0 /* sort by message priority */ +#define QSO_BYHOST 1 /* sort by first host name */ +#define QSO_BYTIME 2 /* sort by submission time */ +#define QSO_BYFILENAME 3 /* sort by file name only */ + +#if _FFR_QUEUEDELAY +#define QD_LINEAR 0 /* linear (old) delay alg */ +#define QD_EXP 1 /* exponential delay alg */ +#endif /* _FFR_QUEUEDELAY */ + +#define NOQDIR (-1) /* no queue directory (yet) */ + +#define NOW ((time_t) (-1)) /* queue return: now */ + +/* Queue Run Limitations */ +struct queue_char +{ + char *queue_match; /* string to match */ + struct queue_char *queue_next; +}; + +typedef struct queue_char QUEUE_CHAR; + +/* functions */ +extern void assign_queueid __P((ENVELOPE *)); +extern ADDRESS *copyqueue __P((ADDRESS *)); +extern void initsys __P((ENVELOPE *)); +extern void loseqfile __P((ENVELOPE *, char *)); +extern void multiqueue_cache __P((void)); +extern char *qid_printname __P((ENVELOPE *)); +extern char *qid_printqueue __P((int)); +extern char *queuename __P((ENVELOPE *, int)); +extern void queueup __P((ENVELOPE *, bool)); +extern bool runqueue __P((bool, bool)); +extern void setnewqueue __P((ENVELOPE *)); +extern bool shouldqueue __P((long, time_t)); +extern void sync_queue_time __P((void)); + +/* +** 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_iconnect; /* initial connection timeout (first try) */ + time_t to_connect; /* initial connection timeout (later tries) */ + 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 */ + time_t to_control; /* process a control socket command */ + /* following are per message */ + time_t to_q_return[MAXTOCLASS]; /* queue return timeouts */ + time_t to_q_warning[MAXTOCLASS]; /* queue warning timeouts */ + time_t res_retrans[MAXRESTOTYPES]; /* resolver retransmit */ + int res_retry[MAXRESTOTYPES]; /* resolver retry */ +} 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 */ + +/* resolver timeout specifiers */ +#define RES_TO_FIRST 0 /* first attempt */ +#define RES_TO_NORMAL 1 /* subsequent attempts */ +#define RES_TO_DEFAULT 2 /* default value */ + +/* functions */ +extern void inittimeouts __P((char *, bool)); + +/* +** Trace information +*/ + +/* macros for debugging flags */ +#define tTd(flag, level) (tTdvect[flag] >= (u_char)level) +#define tTdlevel(flag) (tTdvect[flag]) + +/* variables */ +extern u_char tTdvect[100]; /* trace vector */ + /* +** Miscellaneous information. +*/ + +/* +** The "no queue id" queue id for sm_syslog +*/ + +#define NOQID "*~*" + + +/* +** 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 + /* +** Global variables. +*/ + +EXTERN bool AllowBogusHELO; /* allow syntax errors on HELO command */ +#if !_FFR_REMOVE_AUTOREBUILD +EXTERN bool AutoRebuild; /* auto-rebuild the alias database as needed */ +#endif /* !_FFR_REMOVE_AUTOREBUILD */ +EXTERN bool CheckAliases; /* parse addresses during newaliases */ +EXTERN bool ChownAlwaysSafe; /* treat chown(2) as safe */ +EXTERN bool ColonOkInAddr; /* single colon legal in address */ +EXTERN bool ConfigFileRead; /* configuration file has been read */ +EXTERN bool DataProgress; /* have we sent anything since last check */ +EXTERN bool DisConnected; /* running with OutChannel redirected to xf */ +EXTERN bool DoQueueRun; /* non-interrupt time queue run needed */ +EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */ +EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */ +EXTERN bool DontLockReadFiles; /* don't read lock support files */ +EXTERN bool DontProbeInterfaces; /* don't probe interfaces for names */ +EXTERN bool DontPruneRoutes; /* don't prune source routes */ +EXTERN bool ForkQueueRuns; /* fork for each job when running the queue */ +EXTERN bool FromFlag; /* if set, "From" person is explicit */ +EXTERN bool GrabTo; /* if set, get recipients from msg */ +EXTERN bool HasEightBits; /* has at least one eight bit input byte */ +EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */ +EXTERN bool HoldErrs; /* only output errors to transcript */ +EXTERN bool IgnoreHostStatus; /* ignore long term host status files */ +EXTERN bool IgnrDot; /* don't let dot end messages */ +EXTERN bool InChild; /* true if running in an SMTP subprocess */ +EXTERN bool LogUsrErrs; /* syslog user errors (e.g., SMTP RCPT cmd) */ +EXTERN bool MatchGecos; /* look for user names in gecos field */ +EXTERN bool MeToo; /* send to the sender also */ +EXTERN bool NoAlias; /* suppress aliasing */ +EXTERN bool NoConnect; /* don't connect to non-local mailers */ +EXTERN bool OnlyOneError; /* .... or only want to give one SMTP reply */ +EXTERN bool QuickAbort; /* .... but only if we want a quick abort */ +EXTERN bool RrtImpliesDsn; /* turn Return-Receipt-To: into DSN */ +EXTERN bool SaveFrom; /* save leading "From" lines */ +EXTERN bool SendMIMEErrors; /* send error messages in MIME format */ +EXTERN bool SevenBitInput; /* force 7-bit data on input */ +EXTERN bool SingleLineFromHeader; /* force From: header to be one line */ +EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */ +EXTERN bool SuperSafe; /* be extra careful, even if expensive */ +EXTERN bool SuprErrs; /* set if we are suppressing errors */ +EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */ +EXTERN bool UseErrorsTo; /* use Errors-To: header (back compat) */ +EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */ +EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */ +EXTERN char InetMode; /* default network for daemon mode */ +EXTERN char OpMode; /* operation mode, see below */ +EXTERN char SpaceSub; /* substitution for */ +EXTERN int CheckpointInterval; /* queue file checkpoint interval */ +EXTERN int ConfigLevel; /* config file level */ +EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */ +EXTERN int CurChildren; /* current number of daemonic children */ +EXTERN int CurrentLA; /* current load average */ +EXTERN int DefaultNotify; /* default DSN notification flags */ +EXTERN int Errors; /* set if errors (local to single pass) */ +EXTERN int ExitStat; /* exit status code */ +EXTERN int FileMode; /* mode on files */ +EXTERN int LineNumber; /* line number in current input */ +EXTERN int LogLevel; /* level of logging to perform */ +EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */ +EXTERN int MaxChildren; /* maximum number of daemonic children */ +EXTERN int MaxForwardEntries; /* maximum number of forward entries */ +EXTERN int MaxHeadersLength; /* max length of headers */ +EXTERN int MaxHopCount; /* max # of hops until bounce */ +EXTERN int MaxMacroRecursion; /* maximum depth of macro recursion */ +EXTERN int MaxMciCache; /* maximum entries in MCI cache */ +EXTERN int MaxMimeFieldLength; /* maximum MIME field length */ +EXTERN int MaxMimeHeaderLength; /* maximum MIME header length */ +EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */ +EXTERN int MaxRcptPerMsg; /* max recipients per SMTP message */ +EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */ +EXTERN int MimeMode; /* MIME processing mode */ +EXTERN int NoRecipientAction; +EXTERN int NumPriorities; /* pointer into Priorities */ +EXTERN u_short PrivacyFlags; /* privacy flags */ +#if _FFR_QUEUE_FILE_MODE +EXTERN int QueueFileMode; /* mode on qf/tf/df files */ +#endif /* _FFR_QUEUE_FILE_MODE */ +EXTERN int QueueLA; /* load average starting forced queueing */ +EXTERN int QueueSortOrder; /* queue sorting order algorithm */ +EXTERN int RefuseLA; /* load average refusing connections are */ +EXTERN int VendorCode; /* vendor-specific operation enhancements */ +EXTERN int Verbose; /* set if blow-by-blow desired */ +EXTERN gid_t DefGid; /* default gid to run as */ +EXTERN gid_t RealGid; /* real gid of caller */ +EXTERN gid_t RunAsGid; /* GID to become for bulk of run */ +EXTERN uid_t DefUid; /* default uid to run as */ +EXTERN uid_t RealUid; /* real uid of caller */ +EXTERN uid_t RunAsUid; /* UID to become for bulk of run */ +EXTERN uid_t TrustedUid; /* uid of trusted user for files and startup */ +EXTERN size_t DataFileBufferSize; /* size of buffer for in-core df */ +EXTERN size_t XscriptFileBufferSize; /* size of buffer for in-core xf */ +EXTERN time_t DialDelay; /* delay between dial-on-demand tries */ +EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */ +EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */ +EXTERN time_t MinQueueAge; /* min delivery interval */ +EXTERN time_t QueueIntvl; /* intervals between running the queue */ +EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */ +EXTERN time_t ServiceCacheMaxAge; /* refresh interval for cache */ +EXTERN time_t ServiceCacheTime; /* time service switch was cached */ +EXTERN MODE_T OldUmask; /* umask when sendmail starts up */ +EXTERN long MaxMessageSize; /* advertised max size we will accept */ +EXTERN long MinBlocksFree; /* min # of blocks free on queue fs */ +EXTERN long QueueFactor; /* slope of queue function */ +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 */ +#if SASL +EXTERN char *AuthMechanisms; /* AUTH mechanisms */ +EXTERN char *SASLInfo; /* file with AUTH info */ +#endif /* SASL */ +EXTERN int SASLTryAuth; /* use AUTH= ? */ +EXTERN char *ConfFile; /* location of configuration file [conf.c] */ +EXTERN char *ControlSocketName; /* control socket filename [control.c] */ +EXTERN char *CurHostName; /* current host we are dealing with */ +EXTERN char *DeadLetterDrop; /* path to dead letter office */ +EXTERN char *DefUser; /* default user to run as (from DefUid) */ +EXTERN char *DefaultCharSet; /* default character set for MIME */ +EXTERN char *DoubleBounceAddr; /* where to send double bounces */ +EXTERN char *ErrMsgFile; /* file to prepend to all error messages */ +EXTERN char *FallBackMX; /* fall back MX host */ +EXTERN char *FileName; /* name to print on error messages */ +EXTERN char *ForwardPath; /* path to search for .forward files */ +EXTERN char *HelpFile; /* location of SMTP help file */ +EXTERN char *HostStatDir; /* location of host status information */ +EXTERN char *HostsFile; /* path to /etc/hosts file */ +EXTERN char *MustQuoteChars; /* quote these characters in phrases */ +EXTERN char *MyHostName; /* name of this host for SMTP messages */ +EXTERN char *OperatorChars; /* operators (old $o macro) */ +EXTERN char *PidFile; /* location of proc id file [conf.c] */ +EXTERN char *PostMasterCopy; /* address to get errs cc's */ +EXTERN char *ProcTitlePrefix; /* process title prefix */ +EXTERN char *QueueDir; /* location of queue directory */ +#if _FFR_QUEUEDELAY +EXTERN int QueueAlg; /* algorithm for queue delays */ +EXTERN time_t QueueInitDelay; /* initial queue delay */ +EXTERN time_t QueueMaxDelay; /* maximum queue delay */ +#endif /* _FFR_QUEUEDELAY */ +EXTERN char *RealHostName; /* name of host we are talking to */ +EXTERN char *RealUserName; /* real user name of caller */ +EXTERN char *RunAsUserName; /* user to become for bulk of run */ +EXTERN char *SafeFileEnv; /* chroot location for file delivery */ +EXTERN char *ServiceSwitchFile; /* backup service switch */ +EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */ +EXTERN char *SmtpPhase; /* current phase in SMTP processing */ +EXTERN char SmtpError[MAXLINE]; /* save failure error messages */ +EXTERN char *StatFile; /* location of statistics summary */ +EXTERN char *TimeZoneSpec; /* override time zone specification */ +EXTERN char *UdbSpec; /* user database source spec */ +EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */ +EXTERN char **ExternalEnviron; /* input environment */ + /* saved user environment */ +EXTERN BITMAP256 DontBlameSendmail; /* DontBlameSendmail bits */ +EXTERN FILE *InChannel; /* input connection */ +EXTERN FILE *OutChannel; /* output connection */ +EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */ +#ifdef HESIOD +EXTERN void *HesiodContext; +#endif /* HESIOD */ +EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */ +EXTERN EVENT *EventQueue; /* head of event queue */ +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 */ +EXTERN QUEUE_CHAR *QueueLimitRecipient; /* limit queue run to rcpt */ +EXTERN QUEUE_CHAR *QueueLimitSender; /* limit queue run to sender */ +EXTERN QUEUE_CHAR *QueueLimitId; /* limit queue run to id */ +EXTERN MAILER *Mailer[MAXMAILERS + 1]; +EXTERN struct rewrite *RewriteRules[MAXRWSETS]; +EXTERN char *RuleSetNames[MAXRWSETS]; /* ruleset number to name */ +EXTERN char *UserEnviron[MAXUSERENVIRON + 1]; +EXTERN struct priority Priorities[MAXPRIORITIES]; +EXTERN struct termescape TermEscape; /* terminal escape codes */ +EXTERN SOCKADDR ConnectOnlyTo; /* override connection address (for testing) */ +EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */ +EXTERN jmp_buf TopFrame; /* branch-to-top-of-loop-on-error frame */ +EXTERN TIMERS Timers; + +/* +** Declarations of useful functions +*/ + +#if SASL +extern char *intersect __P((char *, char *)); +extern char *iteminlist __P((char *, char *, char *)); +extern int proxy_policy __P((void *, const char *, const char *, const char **, const char **)); +# if SASL > 10515 +extern int safesaslfile __P((void *, char *, int)); +# else /* SASL > 10515 */ +extern int safesaslfile __P((void *, char *)); +# endif /* SASL > 10515 */ +extern int sasl_decode64 __P((const char *, unsigned, char *, unsigned *)); +extern int sasl_encode64 __P((const char *, unsigned, char *, unsigned, unsigned *)); +#endif /* SASL */ + + +/* Transcript file */ +extern void closexscript __P((ENVELOPE *)); +extern void openxscript __P((ENVELOPE *)); + +/* error related */ +extern void buffer_errors __P((void)); +extern void flush_errors __P((bool)); +extern void message __P((const char *, ...)); +extern void nmessage __P((const char *, ...)); +extern void syserr __P((const char *, ...)); +extern void usrerrenh __P((char *, const char *, ...)); +extern void usrerr __P((const char *, ...)); +extern int isenhsc __P((const char *, int)); +extern int extenhsc __P((const char *, int, char *)); + +/* alias file */ +extern void alias __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern bool aliaswait __P((MAP *, char *, bool)); +extern void forward __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern void readaliases __P((MAP *, FILE *, bool, bool)); +extern bool rebuildaliases __P((MAP *, bool)); +extern void setalias __P((char *)); + +/* logging */ +extern void logdelivery __P((MAILER *, MCI *, char *, const char *, ADDRESS *, time_t, ENVELOPE *)); +extern void logsender __P((ENVELOPE *, char *)); +extern void sm_syslog __P((int, const char *, const char *, ...)); + +/* SMTP */ +extern void giveresponse __P((int, char *, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *)); +extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)(), char **)); +extern void smtp __P((char *volatile, BITMAP256, ENVELOPE *volatile)); +#if SASL +extern int smtpauth __P((MAILER *, MCI *, ENVELOPE *)); +#endif /* SASL */ +extern int smtpdata __P((MAILER *, MCI *, ENVELOPE *)); +extern int smtpgetstat __P((MAILER *, MCI *, ENVELOPE *)); +extern int smtpmailfrom __P((MAILER *, MCI *, ENVELOPE *)); +extern void smtpmessage __P((char *, MAILER *, MCI *, ...)); +extern void smtpinit __P((MAILER *, MCI *, ENVELOPE *, bool)); +extern char *smtptodsn __P((int)); +extern int smtpprobe __P((MCI *)); +extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *)); +extern int smtprcpt __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *)); +extern void smtprset __P((MAILER *, MCI *, ENVELOPE *)); + +#define ISSMTPCODE(c) (isascii(c[0]) && isdigit(c[0]) && \ + isascii(c[1]) && isdigit(c[1]) && \ + isascii(c[2]) && isdigit(c[2])) +#define ISSMTPREPLY(c) (ISSMTPCODE(c) && \ + (c[3] == ' ' || c[3] == '-' || c[3] == '\0')) + +/* delivery */ +extern pid_t dowork __P((int, char *, bool, bool, ENVELOPE *)); +extern int endmailer __P((MCI *, ENVELOPE *, char **)); +extern int mailfile __P((char *volatile, MAILER *volatile, ADDRESS *, volatile long, ENVELOPE *)); +extern void sendall __P((ENVELOPE *, int)); + +/* stats */ +extern void markstats __P((ENVELOPE *, ADDRESS *, bool)); +extern void clearstats __P((void)); +extern void poststats __P((char *)); + +/* control socket */ +extern void closecontrolsocket __P((bool)); +extern void clrcontrol __P((void)); +extern void control_command __P((int, ENVELOPE *)); +extern int opencontrolsocket __P((void)); + +#if _FFR_MILTER +/* milter functions */ +extern int milter_open __P((struct milter *, bool, ENVELOPE *)); +extern void milter_parse_list __P((char *, struct milter **, int)); +extern void milter_parse_timeouts __P((char *, struct milter *)); +extern void milter_set_option __P((char *, char *, bool)); +extern bool milter_can_delrcpts __P((void)); +extern void milter_init __P((ENVELOPE *, char *)); +extern void milter_quit __P((ENVELOPE *)); +extern void milter_abort __P((ENVELOPE *)); +extern char *milter_connect __P((char *, SOCKADDR, ENVELOPE *, char *)); +extern char *milter_helo __P((char *, ENVELOPE *, char *)); +extern char *milter_envfrom __P((char **, ENVELOPE *, char *)); +extern char *milter_envrcpt __P((char **, ENVELOPE *, char *)); +extern char *milter_header __P((char *, char *, ENVELOPE *, char *)); +extern char *milter_eoh __P((ENVELOPE *, char *)); +extern char *milter_body __P((ENVELOPE *, char *)); +#endif /* _FFR_MILTER */ + +extern char *addquotes __P((char *)); +extern char *arpadate __P((char *)); +extern bool atobool __P((char *)); +extern int atooct __P((char *)); +extern void auth_warning __P((ENVELOPE *, const char *, ...)); +extern int blocksignal __P((int)); +extern bool bitintersect __P((BITMAP256, BITMAP256)); +extern bool bitzerop __P((BITMAP256)); +extern void buildfname __P((char *, char *, char *, int)); +extern int checkcompat __P((ADDRESS *, ENVELOPE *)); +#ifdef XDEBUG +extern void checkfd012 __P((char *)); +extern void checkfdopen __P((int, char *)); +#endif /* XDEBUG */ +extern void checkfds __P((char *)); +extern bool chownsafe __P((int, bool)); +extern void cleanstrcpy __P((char *, char *, int)); +extern void clrdaemon __P((void)); +extern void collect __P((FILE *, bool, HDR **, ENVELOPE *)); +extern time_t convtime __P((char *, int)); +extern char **copyplist __P((char **, bool)); +extern void copy_class __P((int, int)); +extern time_t curtime __P((void)); +extern char *defcharset __P((ENVELOPE *)); +extern char *denlstring __P((char *, bool, bool)); +extern void disconnect __P((int, ENVELOPE *)); +extern bool dns_getcanonname __P((char *, int, bool, int *)); +extern int dofork __P((void)); +extern int drop_privileges __P((bool)); +extern int dsntoexitstat __P((char *)); +extern void dumpfd __P((int, bool, bool)); +extern void dumpstate __P((char *)); +extern bool enoughdiskspace __P((long, bool)); +extern char *exitstat __P((char *)); +extern char *fgetfolded __P((char *, int, FILE *)); +extern void fill_fd __P((int, char *)); +extern char *find_character __P((char *, int)); +extern struct passwd *finduser __P((char *, bool *)); +extern void finis __P((bool, volatile int)); +extern void fixcrlf __P((char *, bool)); +extern long freediskspace __P((char *, long *)); +extern char *get_column __P((char *, int, int, char *, int)); +extern char *getauthinfo __P((int, bool *)); +extern char *getcfname __P((void)); +extern char *getextenv __P((const char *)); +extern int getdtsize __P((void)); +extern BITMAP256 *getrequests __P((ENVELOPE *)); +extern char *getvendor __P((int)); +extern void help __P((char *, ENVELOPE *)); +extern void init_md __P((int, char **)); +extern void initdaemon __P((void)); +extern void inithostmaps __P((void)); +extern void initmacros __P((ENVELOPE *)); +extern void initsetproctitle __P((int, char **, char **)); +extern void init_vendor_macros __P((ENVELOPE *)); +extern SIGFUNC_DECL intindebug __P((int)); +extern SIGFUNC_DECL intsig __P((int)); +extern bool isloopback __P((SOCKADDR sa)); +extern void load_if_names __P((void)); +extern bool lockfile __P((int, char *, char *, int)); +extern void log_sendmail_pid __P((ENVELOPE *)); +extern char lower __P((int)); +extern void makelower __P((char *)); +extern int makeconnection_ds __P((char *, MCI *)); +extern int makeconnection __P((char *, volatile u_int, MCI *, ENVELOPE *)); +extern char * munchstring __P((char *, char **, int)); +extern struct hostent *myhostname __P((char *, int)); +extern char *nisplus_default_domain __P((void)); /* extern for Sun */ +extern bool path_is_dir __P((char *, bool)); +extern char *pintvl __P((time_t, bool)); +extern void printav __P((char **)); +extern void printmailer __P((MAILER *)); +extern void printopenfds __P((bool)); +extern void printqueue __P((void)); +extern void printrules __P((void)); +extern int prog_open __P((char **, int *, ENVELOPE *)); +extern void putline __P((char *, MCI *)); +extern void putxline __P((char *, size_t, MCI *, int)); +extern void queueup_macros __P((int, FILE *, ENVELOPE *)); +extern SIGFUNC_DECL quiesce __P((int)); +extern void readcf __P((char *, bool, ENVELOPE *)); +extern SIGFUNC_DECL reapchild __P((int)); +extern bool refuseconnections __P((char *, ENVELOPE *, int)); +extern int releasesignal __P((int)); +extern void resetlimits __P((void)); +extern bool rfc822_string __P((char *)); +extern void savemail __P((ENVELOPE *, bool)); +extern void seed_random __P((void)); +extern void sendtoargv __P((char **, ENVELOPE *)); +extern void setclientoptions __P((char *)); +extern bool setdaemonoptions __P((char *)); +extern void setdefaults __P((ENVELOPE *)); +extern void setdefuser __P((void)); +extern bool setvendor __P((char *)); +extern void setoption __P((int, char *, bool, bool, ENVELOPE *)); +extern sigfunc_t setsignal __P((int, sigfunc_t)); +extern void setuserenv __P((const char *, const char *)); +extern void settime __P((ENVELOPE *)); +extern char *sfgets __P((char *, int, FILE *, time_t, char *)); +extern char *shortenstring __P((const char *, int)); +extern void shorten_hostname __P((char [])); +extern bool shorten_rfc822_string __P((char *, size_t)); +extern SIGFUNC_DECL sigusr1 __P((int)); +extern SIGFUNC_DECL sighup __P((int)); +extern void sm_dopr __P((char *, const char *, va_list)); +extern struct hostent *sm_gethostbyname __P((char *, int)); +extern struct hostent *sm_gethostbyaddr __P((char *, int, int)); +extern int sm_getla __P((ENVELOPE *)); +extern struct passwd *sm_getpwnam __P((char *)); +extern struct passwd *sm_getpwuid __P((UID_T)); +extern void sm_setproctitle __P((bool, ENVELOPE *, const char *, ...)); +extern int sm_strcasecmp __P((const char *, const char *)); +extern bool strcontainedin __P((char *, char *)); +extern void stripquotes __P((char *)); +extern int switch_map_find __P((char *, char *[], short [])); +extern bool transienterror __P((int)); +extern void tTflag __P((char *)); +extern void tTsetup __P((u_char *, int, char *)); +extern SIGFUNC_DECL tick __P((int)); +extern char *ttypath __P((void)); +extern void unlockqueue __P((ENVELOPE *)); +#if !HASUNSETENV +extern void unsetenv __P((char *)); +#endif /* !HASUNSETENV */ +extern char *username __P((void)); +extern bool usershellok __P((char *, char *)); +extern void vendor_post_defaults __P((ENVELOPE *)); +extern void vendor_pre_defaults __P((ENVELOPE *)); +extern int waitfor __P((pid_t)); +extern bool writable __P((char *, ADDRESS *, long)); +extern char *xalloc __P((int)); +extern void xputs __P((const char *)); +extern char *xtextify __P((char *, char *)); +extern bool xtextok __P((char *)); +extern void xunlink __P((char *)); +extern char *xuntextify __P((char *)); +#endif /* _SENDMAIL_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/sfsasl.c b/gnu/usr.sbin/sendmail/sendmail/sfsasl.c new file mode 100644 index 00000000000..8a82e000c30 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sfsasl.c @@ -0,0 +1,14 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: sfsasl.c,v 8.16 2000/02/01 21:55:24 ca Exp $"; +#endif /* ! lint */ + diff --git a/gnu/usr.sbin/sendmail/sendmail/sfsasl.h b/gnu/usr.sbin/sendmail/sendmail/sfsasl.h new file mode 100644 index 00000000000..4e6603594bd --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sfsasl.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: sfsasl.h,v 8.11 1999/07/13 22:00:03 ca Exp $" + */ + +#ifndef SFSASL_H +# define SFSASL_H + + + +#endif /* ! SFSASL_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/shmticklib.c b/gnu/usr.sbin/sendmail/sendmail/shmticklib.c new file mode 100644 index 00000000000..1c197a71f2c --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/shmticklib.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: shmticklib.c,v 8.6 2000/02/26 01:32:27 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_SHM_STATUS +# include +# include +# include +# include + +# include "statusd_shm.h" + + /* +** SHMTICK -- increment a shared memory variable +** +** Parameters: +** inc_me -- identity of shared memory segment +** what -- which variable to increment +** +** Returns: +** none +*/ + +void +shmtick(inc_me, what) + int inc_me; + int what; +{ + static int shmid = -1; + static STATUSD_SHM *sp = (STATUSD_SHM *)-1; + static unsigned int cookie = 0; + + if (shmid < 0) + { + int size = sizeof(STATUSD_SHM); + + shmid = shmget(STATUSD_SHM_KEY, size, 0); + if (shmid < 0) + return; + } + if ((unsigned long *)sp == (unsigned long *)-1) + { + sp = (STATUSD_SHM *)shmat(shmid, NULL, 0); + if ((unsigned long *)sp == (unsigned long *)-1) + return; + } + if (sp->magic != STATUSD_MAGIC) + { + /* + ** possible race condition, wait for + ** statusd to initialize. + */ + + return; + } + if (what >= STATUSD_LONGS) + what = STATUSD_LONGS - 1; + if (inc_me >= STATUSD_LONGS) + inc_me = STATUSD_LONGS - 1; + + if (sp->ul[STATUSD_COOKIE] != cookie) + { + cookie = sp->ul[STATUSD_COOKIE]; + ++(sp->ul[inc_me]); + } + ++(sp->ul[what]); +} +#endif /* _FFR_SHM_STATUS */ diff --git a/gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c b/gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c new file mode 100644 index 00000000000..4e502c06a7c --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/srvrsmtp.c @@ -0,0 +1,2646 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# if SMTP +static char id[] = "@(#)$Sendmail: srvrsmtp.c,v 8.457 2000/02/26 07:24:59 gshapiro Exp $ (with SMTP)"; +# else /* SMTP */ +static char id[] = "@(#)$Sendmail: srvrsmtp.c,v 8.457 2000/02/26 07:24:59 gshapiro Exp $ (without SMTP)"; +# endif /* SMTP */ +#endif /* ! lint */ + +#if SMTP +# if SASL +# define ENC64LEN(l) (((l) + 2) * 4 / 3 + 1) +static bool saslmechs __P((sasl_conn_t *, char **, bool)); +# endif /* SASL */ + +static time_t checksmtpattack __P((volatile int *, int, bool, + char *, ENVELOPE *)); +static void mail_esmtp_args __P((char *, char *, ENVELOPE *)); +static void printvrfyaddr __P((ADDRESS *, bool, bool)); +static void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *)); +static int runinchild __P((char *, ENVELOPE *)); +static char *skipword __P((char *volatile, char *)); +extern ENVELOPE BlankEnvelope; + +/* +** SMTP -- run the SMTP protocol. +** +** Parameters: +** nullserver -- if non-NULL, rejection message for +** all SMTP commands. +** e -- the envelope. +** +** Returns: +** never. +** +** Side Effects: +** Reads commands from the input channel and processes +** them. +*/ + +struct cmd +{ + char *cmd_name; /* command name */ + int cmd_code; /* internal code, see below */ +}; + +/* values for cmd_code */ +# 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) */ +# define CMDETRN 12 /* etrn -- flush queue */ +# if SASL +# define CMDAUTH 13 /* auth -- SASL authenticate */ +# endif /* SASL */ +/* non-standard commands */ +# define CMDONEX 16 /* onex -- sending one transaction only */ +# define CMDVERB 17 /* verb -- go into verbose mode */ +# define CMDXUSR 18 /* xusr -- initial (user) submission */ +/* unimplemented commands from RFC 821 */ +# define CMDUNIMPL 19 /* unimplemented rfc821 commands */ +/* 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 }, + { "etrn", CMDETRN }, + { "verb", CMDVERB }, + { "onex", CMDONEX }, + { "xusr", CMDXUSR }, + { "send", CMDUNIMPL }, + { "saml", CMDUNIMPL }, + { "soml", CMDUNIMPL }, + { "turn", CMDUNIMPL }, +# if SASL + { "auth", CMDAUTH, }, +# endif /* SASL */ + /* remaining commands are here only to trap and log attempts to use them */ + { "showq", CMDDBGQSHOW }, + { "debug", CMDDBGDEBUG }, + { "wiz", CMDLOGBOGUS }, + + { NULL, CMDERROR } +}; + +static bool OneXact = FALSE; /* one xaction only this run */ +static char *CurSmtpClient; /* who's at the other end of channel */ + +# define MAXBADCOMMANDS 25 /* maximum number of bad commands */ +# define MAXNOOPCOMMANDS 20 /* max "noise" commands before slowdown */ +# define MAXHELOCOMMANDS 3 /* max HELO/EHLO commands before slowdown */ +# define MAXVRFYCOMMANDS 6 /* max VRFY/EXPN commands before slowdown */ +# define MAXETRNCOMMANDS 8 /* max ETRN commands before slowdown */ +# define MAXTIMEOUT (4 * 60) /* max timeout for bad commands */ + +void +smtp(nullserver, d_flags, e) + char *volatile nullserver; + BITMAP256 d_flags; + register ENVELOPE *volatile e; +{ + register char *volatile p; + register struct cmd *volatile c = NULL; + 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 bool discard; + volatile int badcommands = 0; /* count of bad commands */ + volatile int nverifies = 0; /* count of VRFY/EXPN commands */ + volatile int n_etrn = 0; /* count of ETRN commands */ + volatile int n_noop = 0; /* count of NOOP/VERB/ONEX etc cmds */ + volatile int n_helo = 0; /* count of HELO/EHLO commands */ + volatile int delay = 1; /* timeout for bad commands */ + bool ok; + volatile bool tempfail = FALSE; +# if _FFR_MILTER + volatile bool milterize = (nullserver == NULL); +# endif /* _FFR_MILTER */ + volatile time_t wt; /* timeout after too many commands */ + volatile time_t previous; /* time after checksmtpattack() */ + volatile int lognullconnection = TRUE; + register char *q; + char *addr; + char *greetcode = "220"; + QUEUE_CHAR *new; + int argno; + char *args[MAXSMTPARGS]; + char inp[MAXLINE]; + char cmdbuf[MAXLINE]; +# if SASL + sasl_conn_t *conn; + volatile bool sasl_ok; + bool ismore; + int result; + volatile int authenticating; + char *hostname; + char *user; + char *in, *out, *out2; + const char *errstr; + int inlen, out2len; + unsigned int outlen; + char *volatile auth_type; + char *mechlist; + int len; + sasl_security_properties_t ssp; + sasl_external_properties_t ext_ssf; +# endif /* SASL */ + + if (fileno(OutChannel) != fileno(stdout)) + { + /* arrange for debugging output to go to remote host */ + (void) dup2(fileno(OutChannel), fileno(stdout)); + } + + settime(e); + (void)sm_getla(e); + peerhostname = RealHostName; + if (peerhostname == NULL) + peerhostname = "localhost"; + CurHostName = peerhostname; + CurSmtpClient = macvalue('_', e); + if (CurSmtpClient == NULL) + CurSmtpClient = CurHostName; + + /* check_relay may have set discard bit, save for later */ + discard = bitset(EF_DISCARD, e->e_flags); + + sm_setproctitle(TRUE, e, "server %s startup", CurSmtpClient); + +# if SASL + sasl_ok = FALSE; /* SASL can't be used (yet) */ + + /* SASL server new connection */ + hostname = macvalue('j', e); +# if SASL > 10505 + /* use empty realm: doesn't work in SASL <= 1.5.5 */ + result = sasl_server_new("smtp", hostname, "", NULL, 0, &conn); +# else /* SASL > 10505 */ + /* use no realm -> realm is set to hostname by SASL lib */ + result = sasl_server_new("smtp", hostname, NULL, NULL, 0, &conn); +# endif /* SASL > 10505 */ + if (result == SASL_OK) + { + sasl_ok = TRUE; + + /* + ** SASL set properties for sasl + ** set local/remote IP + ** XXX only IPv4: Cyrus SASL doesn't support anything else + ** + ** XXX where exactly are these used/required? + ** Kerberos_v4 + */ + +# if NETINET + in = macvalue(macid("{daemon_family}", NULL), e); + if (in != NULL && strcmp(in, "inet") == 0) + { + SOCKADDR_LEN_T addrsize; + struct sockaddr_in saddr_l; + struct sockaddr_in saddr_r; + + addrsize = sizeof(struct sockaddr_in); + if (getpeername(fileno(InChannel), + (struct sockaddr *)&saddr_r, + &addrsize) == 0) + { + sasl_setprop(conn, SASL_IP_REMOTE, &saddr_r); + addrsize = sizeof(struct sockaddr_in); + if (getsockname(fileno(InChannel), + (struct sockaddr *)&saddr_l, + &addrsize) == 0) + sasl_setprop(conn, SASL_IP_LOCAL, + &saddr_l); + } + } +# endif /* NETINET */ + + authenticating = SASL_NOT_AUTH; + auth_type = NULL; + mechlist = NULL; + user = NULL; +# if 0 + define(macid("{auth_author}", NULL), NULL, &BlankEnvelope); +# endif /* 0 */ + + /* set properties */ + (void) memset(&ssp, '\0', sizeof ssp); + sasl_ok = sasl_setprop(conn, SASL_SEC_PROPS, &ssp) == SASL_OK; + + if (sasl_ok) + { + /* + ** external security strength factor; + ** we have none so zero + */ + ext_ssf.ssf = 0; + ext_ssf.auth_id = NULL; + sasl_ok = sasl_setprop(conn, SASL_SSF_EXTERNAL, + &ext_ssf) == SASL_OK; + } + if (sasl_ok) + sasl_ok = saslmechs(conn, &mechlist, sasl_ok); + } + else + { + if (LogLevel > 9) + sm_syslog(LOG_WARNING, NOQID, + "SASL error: sasl_server_new failed=%d", + result); + } +# endif /* SASL */ + +# if _FFR_MILTER + if (milterize) + { + char state; + + /* initialize mail filter connection */ + milter_init(e, &state); + switch (state) + { + case SMFIR_REJECT: + greetcode = "554"; + nullserver = "Command rejected"; + milterize = FALSE; + break; + + case SMFIR_TEMPFAIL: + tempfail = TRUE; + milterize = FALSE; + break; + } + } + + if (milterize && !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + response = milter_connect(peerhostname, RealHostAddr, + e, &state); + switch (state) + { + case SMFIR_REPLYCODE: /* REPLYCODE shouldn't happen */ + case SMFIR_REJECT: + greetcode = "554"; + nullserver = "Command rejected"; + milterize = FALSE; + break; + + case SMFIR_DISCARD: + e->e_flags |= EF_DISCARD; + milterize = FALSE; + break; + + case SMFIR_TEMPFAIL: + tempfail = TRUE; + milterize = FALSE; + break; + } + } +# endif /* _FFR_MILTER */ + + /* 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)]; + if (p == NULL) + snprintf(cmdbuf, sizeof cmdbuf, + "%s %%.*s ESMTP%%s", greetcode); + else + snprintf(cmdbuf, sizeof cmdbuf, + "%s-%%.*s ESMTP%%s", greetcode); + message(cmdbuf, id - inp, inp, id); + + /* output remaining lines */ + while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL) + { + *p++ = '\0'; + if (isascii(*id) && isspace(*id)) + id++; + (void) snprintf(cmdbuf, sizeof cmdbuf, "%s-%%s", greetcode); + message(cmdbuf, id); + } + if (id != NULL) + { + if (isascii(*id) && isspace(*id)) + id++; + (void) snprintf(cmdbuf, sizeof cmdbuf, "%s %%s", greetcode); + message(cmdbuf, id); + } + + protocol = NULL; + sendinghost = macvalue('s', e); + gothello = FALSE; + gotmail = FALSE; + for (;;) + { + /* arrange for backout */ + (void) setjmp(TopFrame); + QuickAbort = FALSE; + HoldErrs = FALSE; + SuprErrs = FALSE; + LogUsrErrs = FALSE; + OnlyOneError = TRUE; + e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS); + + /* setup for the read */ + e->e_to = NULL; + Errors = 0; + FileName = NULL; + (void) fflush(stdout); + + /* read the input line */ + SmtpPhase = "server cmd read"; + sm_setproctitle(TRUE, e, "server %s cmd read", CurSmtpClient); +# if SASL + /* + ** SMTP AUTH requires accepting any length, + ** at least for challenge/response + ** XXX + */ +# endif /* SASL */ + + /* handle errors */ + if (ferror(OutChannel) || + (p = sfgets(inp, sizeof inp, InChannel, + TimeOuts.to_nextcommand, SmtpPhase)) == NULL) + { + char *d; + + d = macvalue(macid("{daemon_name}", NULL), e); + if (d == NULL) + d = "stdin"; + /* end of file, just die */ + disconnect(1, e); + +# if _FFR_MILTER + /* close out milter filters */ + milter_quit(e); +# endif /* _FFR_MILTER */ + + message("421 4.4.1 %s Lost input channel from %s", + MyHostName, CurSmtpClient); + if (LogLevel > (gotmail ? 1 : 19)) + sm_syslog(LOG_NOTICE, e->e_id, + "lost input channel from %.100s to %s after %s", + CurSmtpClient, d, + (c == NULL || c->cmd_name == NULL) ? "startup" : c->cmd_name); + /* + ** If have not accepted mail (DATA), do not bounce + ** bad addresses back to sender. + */ + + if (bitset(EF_CLRQUEUE, e->e_flags)) + e->e_sendqueue = NULL; + goto doquit; + } + + /* clean up end of line */ + fixcrlf(inp, TRUE); + +# if SASL + if (authenticating == SASL_PROC_AUTH) + { +# if 0 + if (*inp == '\0') + { + authenticating = SASL_NOT_AUTH; + message("501 5.5.2 missing input"); + continue; + } +# endif /* 0 */ + if (*inp == '*' && *(inp + 1) == '\0') + { + authenticating = SASL_NOT_AUTH; + + /* rfc 2254 4. */ + message("501 5.0.0 AUTH aborted"); + continue; + } + + /* could this be shorter? XXX */ + out = xalloc(strlen(inp)); + result = sasl_decode64(inp, strlen(inp), out, &outlen); + if (result != SASL_OK) + { + authenticating = SASL_NOT_AUTH; + + /* rfc 2254 4. */ + message("501 5.5.4 cannot decode AUTH parameter %s", + inp); + continue; + } + + result = sasl_server_step(conn, out, outlen, + &out, &outlen, &errstr); + + /* get an OK if we're done */ + if (result == SASL_OK) + { + authenticated: + message("235 2.0.0 OK Authenticated"); + authenticating = SASL_IS_AUTH; + define(macid("{auth_type}", NULL), + newstr(auth_type), &BlankEnvelope); + + result = sasl_getprop(conn, SASL_USERNAME, + (void **)&user); + if (result != SASL_OK) + { + user = ""; + define(macid("{auth_authen}", NULL), + NULL, &BlankEnvelope); + } + else + { + define(macid("{auth_authen}", NULL), + newstr(user), &BlankEnvelope); + } + +# if 0 + /* get realm? */ + sasl_getprop(conn, SASL_REALM, (void **) &data); +# endif /* 0 */ + + + if (LogLevel > 9) + sm_syslog(LOG_INFO, NOQID, + "SASL: connection from %.64s: mech=%.16s, id=%.64s", + CurSmtpClient, auth_type, + user); + } + else if (result == SASL_CONTINUE) + { + len = ENC64LEN(outlen); + out2 = xalloc(len); + result = sasl_encode64(out, outlen, out2, len, + (u_int *)&out2len); + if (result != SASL_OK) + { + /* correct code? XXX */ + /* 454 Temp. authentication failure */ + message("454 4.5.4 Internal error: unable to encode64"); + if (LogLevel > 5) + sm_syslog(LOG_WARNING, e->e_id, + "SASL encode64 error [%d for \"%s\"]", + result, out); + /* start over? */ + authenticating = SASL_NOT_AUTH; + } + else + { + message("334 %s", out2); + if (tTd(95, 2)) + dprintf("SASL continue: msg='%s' len=%d\n", + out2, out2len); + } + } + else + { + /* not SASL_OK or SASL_CONT */ + message("500 5.7.0 authentication failed"); + if (LogLevel > 9) + sm_syslog(LOG_WARNING, e->e_id, + "AUTH failure (%s): %s (%d)", + auth_type, + sasl_errstring(result, NULL, + NULL), + result); + authenticating = SASL_NOT_AUTH; + } + } + else + { + /* don't want to do any of this if authenticating */ +# endif /* SASL */ + + /* echo command to transcript */ + if (e->e_xfp != NULL) + fprintf(e->e_xfp, "<<< %s\n", inp); + + if (LogLevel >= 15) + sm_syslog(LOG_INFO, e->e_id, + "<-- %s", + inp); + + if (e->e_id == NULL) + sm_setproctitle(TRUE, e, "%s: %.80s", + CurSmtpClient, inp); + else + sm_setproctitle(TRUE, e, "%s %s: %.80s", + qid_printname(e), + 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->cmd_name != NULL; c++) + { + if (!strcasecmp(c->cmd_name, cmdbuf)) + break; + } + + /* reset errors */ + errno = 0; + + /* + ** Process command. + ** + ** If we are running as a null server, return 550 + ** to everything. + */ + + if (nullserver != NULL || bitnset(D_ETRNONLY, d_flags)) + { + switch (c->cmd_code) + { + case CMDQUIT: + case CMDHELO: + case CMDEHLO: + case CMDNOOP: + case CMDRSET: + /* process normally */ + break; + + case CMDETRN: + if (bitnset(D_ETRNONLY, d_flags) && + nullserver == NULL) + break; + continue; + + default: + if (++badcommands > MAXBADCOMMANDS) + { + delay *= 2; + if (delay >= MAXTIMEOUT) + delay = MAXTIMEOUT; + (void) sleep(delay); + } + if (nullserver != NULL) + { + if (ISSMTPREPLY(nullserver)) + usrerr(nullserver); + else + usrerr("550 5.0.0 %s", nullserver); + } + else + usrerr("452 4.4.5 Insufficient disk space; try again later"); + continue; + } + } + + /* non-null server */ + switch (c->cmd_code) + { + case CMDMAIL: + case CMDEXPN: + case CMDVRFY: + case CMDETRN: + lognullconnection = FALSE; + } + + switch (c->cmd_code) + { +# if SASL + case CMDAUTH: /* sasl */ + if (!sasl_ok) + { + message("503 5.3.3 AUTH not available"); + break; + } + if (authenticating == SASL_IS_AUTH) + { + message("503 5.5.0 Already Authenticated"); + break; + } + if (gotmail) + { + message("503 5.5.0 AUTH not permitted during a mail transaction"); + break; + } + ismore = FALSE; + + /* make sure it's a valid string */ + for (q = p; *q != '\0' && isascii(*q); q++) + { + if (isspace(*q)) + { + *q = '\0'; + while (*++q != '\0' && + isascii(*q) && isspace(*q)) + continue; + *(q - 1) = '\0'; + ismore = (*q != '\0'); + break; + } + } + + /* check whether mechanism is available */ + if (iteminlist(p, mechlist, " ") == NULL) + { + message("503 5.3.3 AUTH mechanism %s not available", + p); + break; + } + + if (ismore) + { + /* could this be shorter? XXX */ + in = xalloc(strlen(q)); + result = sasl_decode64(q, strlen(q), in, + (u_int *)&inlen); + if (result != SASL_OK) + { + message("501 5.5.4 cannot BASE64 decode '%s'", + q); + if (LogLevel > 5) + sm_syslog(LOG_WARNING, e->e_id, + "SASL decode64 error [%d for \"%s\"]", + result, q); + /* start over? */ + authenticating = SASL_NOT_AUTH; + in = NULL; + inlen = 0; + break; + } +# if 0 + if (tTd(95, 99)) + { + int i; + + dprintf("AUTH: more \""); + for (i = 0; i < inlen; i++) + { + if (isascii(in[i]) && + isprint(in[i])) + dprintf("%c", in[i]); + else + dprintf("_"); + } + dprintf("\"\n"); + } +# endif /* 0 */ + } + else + { + in = NULL; + inlen = 0; + } + + /* see if that auth type exists */ + result = sasl_server_start(conn, p, in, inlen, + &out, &outlen, &errstr); + + if (result != SASL_OK && result != SASL_CONTINUE) + { + message("500 5.7.0 authentication failed"); + if (LogLevel > 9) + sm_syslog(LOG_ERR, e->e_id, + "AUTH failure (%s): %s (%d)", + p, + sasl_errstring(result, NULL, + NULL), + result); + break; + } + auth_type = newstr(p); + + if (result == SASL_OK) + { + /* ugly, but same code */ + goto authenticated; + /* authenticated by the initial response */ + } + + /* len is at least 2 */ + len = ENC64LEN(outlen); + out2 = xalloc(len); + result = sasl_encode64(out, outlen, out2, len, + (u_int *)&out2len); + + if (result != SASL_OK) + { + message("454 4.5.4 Temporary authentication failure"); + if (LogLevel > 5) + sm_syslog(LOG_WARNING, e->e_id, + "SASL encode64 error [%d for \"%s\"]", + result, out); + + /* start over? */ + authenticating = SASL_NOT_AUTH; + } + else + { + message("334 %s", out2); + authenticating = SASL_PROC_AUTH; + } + + break; +# endif /* SASL */ + + + case CMDHELO: /* hello -- introduce yourself */ + case CMDEHLO: /* extended hello */ + if (c->cmd_code == CMDEHLO) + { + protocol = "ESMTP"; + SmtpPhase = "server EHLO"; + } + else + { + protocol = "SMTP"; + SmtpPhase = "server HELO"; + } + + /* avoid denial-of-service */ + (void) checksmtpattack(&n_helo, MAXHELOCOMMANDS, TRUE, + "HELO/EHLO", e); + + /* check for duplicate HELO/EHLO per RFC 1651 4.2 */ + if (gothello) + { + usrerr("503 %s Duplicate HELO/EHLO", + MyHostName); + break; + } + + /* check for valid domain name (re 1123 5.2.5) */ + if (*p == '\0' && !AllowBogusHELO) + { + usrerr("501 %s requires domain address", + cmdbuf); + break; + } + + /* check for long domain name (hides Received: info) */ + if (strlen(p) > MAXNAME) + { + usrerr("501 Invalid domain name"); + if (LogLevel > 9) + sm_syslog(LOG_INFO, CurEnv->e_id, + "invalid domain name (too long) from %.100s", + CurSmtpClient); + break; + } + + 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') + { + q = "pleased to meet you"; + sendinghost = newstr(p); + } + else if (!AllowBogusHELO) + { + usrerr("501 Invalid domain name"); + if (LogLevel > 9) + sm_syslog(LOG_INFO, CurEnv->e_id, + "invalid domain name (%.100s) from %.100s", + p, CurSmtpClient); + break; + } + else + { + q = "accepting invalid domain name"; + } + +# if _FFR_MILTER + if (milterize && !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + ok = TRUE; + response = milter_helo(p, e, &state); + switch (state) + { + case SMFIR_REPLYCODE: + milterize = FALSE; + ok = FALSE; + usrerr(response); + break; + + case SMFIR_REJECT: + ok = FALSE; + nullserver = "Command rejected"; + milterize = FALSE; + usrerr("550 HELO/EHLO rejected"); + break; + + case SMFIR_DISCARD: + e->e_flags |= EF_DISCARD; + milterize = FALSE; + break; + + case SMFIR_TEMPFAIL: + ok = FALSE; + tempfail = TRUE; + milterize = FALSE; + break; + } + if (response != NULL) + free(response); + if (!ok) + break; + } +# endif /* _FFR_MILTER */ + + gothello = TRUE; + + /* print HELO response message */ + if (c->cmd_code != CMDEHLO) + { + message("250 %s Hello %s, %s", + MyHostName, CurSmtpClient, q); + break; + } + + message("250-%s Hello %s, %s", + MyHostName, CurSmtpClient, q); + + /* offer ENHSC even for nullserver */ + if (nullserver != NULL) + { + message("250 ENHANCEDSTATUSCODES"); + break; + } + + /* print EHLO features list */ + message("250-ENHANCEDSTATUSCODES"); + if (!bitset(PRIV_NOEXPN, PrivacyFlags)) + { + message("250-EXPN"); + if (!bitset(PRIV_NOVERB, PrivacyFlags)) + message("250-VERB"); + } +# if MIME8TO7 + message("250-8BITMIME"); +# endif /* MIME8TO7 */ + if (MaxMessageSize > 0) + message("250-SIZE %ld", MaxMessageSize); + else + message("250-SIZE"); +# if DSN + if (SendMIMEErrors && + !bitset(PRIV_NORECEIPTS, PrivacyFlags)) + message("250-DSN"); +# endif /* DSN */ + message("250-ONEX"); + if (!bitset(PRIV_NOETRN, PrivacyFlags) && + !bitnset(D_NOETRN, d_flags)) + message("250-ETRN"); + message("250-XUSR"); + +# if SASL + if (sasl_ok && mechlist != NULL && *mechlist != '\0') + message("250-AUTH %s", mechlist); +# endif /* SASL */ + message("250 HELP"); + break; + + case CMDMAIL: /* mail -- designate sender */ + SmtpPhase = "server MAIL"; + + /* check for validity of this command */ + if (!gothello && bitset(PRIV_NEEDMAILHELO, PrivacyFlags)) + { + usrerr("503 5.0.0 Polite people say HELO first"); + break; + } + if (gotmail) + { + usrerr("503 5.5.0 Sender already specified"); + break; + } + if (InChild) + { + errno = 0; + syserr("503 5.5.0 Nested MAIL command: MAIL %s", p); + finis(TRUE, ExitStat); + } +# if SASL + if (bitnset(D_AUTHREQ, d_flags) && + authenticating != SASL_IS_AUTH) + { + usrerr("530 5.7.0 Authentication required"); + break; + } +# endif /* SASL */ + + if (tempfail) + { + if (LogLevel > 9) + sm_syslog(LOG_INFO, e->e_id, + "MAIL From:<%.100s> from %.100s tempfailed (from previous HELO/EHLO check)", + args[0], CurSmtpClient); + usrerr("451 4.7.1 Please try again later"); + break; + } + /* make sure we know who the sending host is */ + if (sendinghost == NULL) + sendinghost = peerhostname; + + p = skipword(p, "from"); + if (p == NULL) + break; + + /* fork a subprocess to process this command */ + if (runinchild("SMTP-MAIL", e) > 0) + break; + if (Errors > 0) + goto undo_subproc_no_pm; + if (!gothello) + { + auth_warning(e, + "%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 /* PICKY_HELO_CHECK */ + + if (protocol == NULL) + protocol = "SMTP"; + define('r', protocol, e); + define('s', sendinghost, e); + + if (Errors > 0) + goto undo_subproc_no_pm; + nrcpts = 0; + define(macid("{ntries}", NULL), "0", e); + e->e_flags |= EF_CLRQUEUE; + sm_setproctitle(TRUE, e, "%s %s: %.80s", + qid_printname(e), + CurSmtpClient, inp); + + /* child -- go do the processing */ + if (setjmp(TopFrame) > 0) + { + /* this failed -- undo work */ + undo_subproc_no_pm: + e->e_flags &= ~EF_PM_NOTIFY; + undo_subproc: + if (InChild) + { + QuickAbort = FALSE; + SuprErrs = TRUE; + e->e_flags &= ~EF_FATALERRS; + + if (LogLevel > 4 && + bitset(EF_LOGSENDER, e->e_flags)) + logsender(e, NULL); + e->e_flags &= ~EF_LOGSENDER; + + finis(TRUE, ExitStat); + } + break; + } + QuickAbort = TRUE; + + /* must parse sender first */ + delimptr = NULL; + setsender(p, e, &delimptr, ' ', FALSE); + if (delimptr != NULL && *delimptr != '\0') + *delimptr++ = '\0'; + if (Errors > 0) + goto undo_subproc_no_pm; + + /* Successfully set e_from, allow logging */ + e->e_flags |= EF_LOGSENDER; + + /* put resulting triple from parseaddr() into macros */ + if (e->e_from.q_mailer != NULL) + define(macid("{mail_mailer}", NULL), + e->e_from.q_mailer->m_name, e); + else + define(macid("{mail_mailer}", NULL), + NULL, e); + if (e->e_from.q_host != NULL) + define(macid("{mail_host}", NULL), + e->e_from.q_host, e); + else + define(macid("{mail_host}", NULL), + "localhost", e); + if (e->e_from.q_user != NULL) + define(macid("{mail_addr}", NULL), + e->e_from.q_user, e); + else + define(macid("{mail_addr}", NULL), + NULL, e); + if (Errors > 0) + goto undo_subproc_no_pm; + + /* 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; + addr = p; + argno = 0; + args[argno++] = p; + p = delimptr; + while (p != NULL && *p != '\0') + { + char *kp; + char *vp = NULL; + char *equal = NULL; + + /* 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 == '=') + { + equal = 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)) + dprintf("MAIL: got arg %s=\"%s\"\n", kp, + vp == NULL ? "" : vp); + + mail_esmtp_args(kp, vp, e); + if (equal != NULL) + *equal = '='; + args[argno++] = kp; + if (argno >= MAXSMTPARGS - 1) + usrerr("501 5.5.4 Too many parameters"); + if (Errors > 0) + goto undo_subproc_no_pm; + } + args[argno] = NULL; + if (Errors > 0) + goto undo_subproc_no_pm; + + /* do config file checking of the sender */ + if (rscheck("check_mail", addr, + NULL, e, TRUE, TRUE) != EX_OK || + Errors > 0) + goto undo_subproc_no_pm; + + if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) + { + usrerr("552 5.2.3 Message size exceeds fixed maximum message size (%ld)", + MaxMessageSize); + goto undo_subproc_no_pm; + } + + if (!enoughdiskspace(e->e_msgsize, TRUE)) + { + usrerr("452 4.4.5 Insufficient disk space; try again later"); + goto undo_subproc_no_pm; + } + if (Errors > 0) + goto undo_subproc_no_pm; + +# if _FFR_MILTER + if (milterize && !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + response = milter_envfrom(args, e, &state); + switch (state) + { + case SMFIR_REPLYCODE: + usrerr(response); + break; + + case SMFIR_REJECT: + usrerr("550 5.7.1 Command rejected"); + break; + + case SMFIR_DISCARD: + e->e_flags |= EF_DISCARD; + break; + + case SMFIR_TEMPFAIL: + usrerr("451 4.7.1 Try again later"); + break; + } + if (response != NULL) + free(response); + } +# endif /* _FFR_MILTER */ + if (Errors > 0) + goto undo_subproc_no_pm; + + message("250 2.1.0 Sender ok"); + gotmail = TRUE; + break; + + case CMDRCPT: /* rcpt -- designate recipient */ + if (!gotmail) + { + usrerr("503 5.0.0 Need MAIL before RCPT"); + break; + } + SmtpPhase = "server RCPT"; + if (setjmp(TopFrame) > 0) + { + e->e_flags &= ~(EF_FATALERRS|EF_PM_NOTIFY); + break; + } + QuickAbort = TRUE; + LogUsrErrs = TRUE; + + /* limit flooding of our machine */ + if (MaxRcptPerMsg > 0 && nrcpts >= MaxRcptPerMsg) + { + usrerr("452 4.5.3 Too many recipients"); + break; + } + + if (e->e_sendmode != SM_DELIVER) + e->e_flags |= EF_VRFYONLY; + +# if _FFR_MILTER + /* + ** If the filter will be deleting recipients, + ** don't expand them at RCPT time (in the call + ** to recipient()). If they are expanded, it + ** is impossible for removefromlist() to figure + ** out the expanded members of the original + ** recipient and mark them as QS_DONTSEND. + */ + + if (milter_can_delrcpts()) + e->e_flags |= EF_VRFYONLY; +# endif /* _FFR_MILTER */ + + p = skipword(p, "to"); + if (p == NULL) + break; +# if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), "e r", e); +# endif /* _FFR_ADDR_TYPE */ + a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e); +#if _FFR_ADDR_TYPE + define(macid("{addr_type}", NULL), NULL, e); +#endif /* _FFR_ADDR_TYPE */ + if (Errors > 0) + break; + if (a == NULL) + { + usrerr("501 5.0.0 Missing recipient"); + break; + } + + if (delimptr != NULL && *delimptr != '\0') + *delimptr++ = '\0'; + + /* put resulting triple from parseaddr() into macros */ + if (a->q_mailer != NULL) + define(macid("{rcpt_mailer}", NULL), + a->q_mailer->m_name, e); + else + define(macid("{rcpt_mailer}", NULL), + NULL, e); + if (a->q_host != NULL) + define(macid("{rcpt_host}", NULL), + a->q_host, e); + else + define(macid("{rcpt_host}", NULL), + "localhost", e); + if (a->q_user != NULL) + define(macid("{rcpt_addr}", NULL), + a->q_user, e); + else + define(macid("{rcpt_addr}", NULL), + NULL, e); + if (Errors > 0) + break; + + /* now parse ESMTP arguments */ + addr = p; + argno = 0; + args[argno++] = p; + p = delimptr; + while (p != NULL && *p != '\0') + { + char *kp; + char *vp = NULL; + char *equal = NULL; + + /* 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 == '=') + { + equal = 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)) + dprintf("RCPT: got arg %s=\"%s\"\n", kp, + vp == NULL ? "" : vp); + + rcpt_esmtp_args(a, kp, vp, e); + if (equal != NULL) + *equal = '='; + args[argno++] = kp; + if (argno >= MAXSMTPARGS - 1) + usrerr("501 5.5.4 Too many parameters"); + if (Errors > 0) + break; + } + args[argno] = NULL; + if (Errors > 0) + break; + + /* do config file checking of the recipient */ + if (rscheck("check_rcpt", addr, + NULL, e, TRUE, TRUE) != EX_OK || + Errors > 0) + break; + +# if _FFR_MILTER + if (milterize && !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + response = milter_envrcpt(args, e, &state); + switch (state) + { + case SMFIR_REPLYCODE: + usrerr(response); + break; + + case SMFIR_REJECT: + usrerr("550 5.7.1 Command rejected"); + break; + + case SMFIR_DISCARD: + e->e_flags |= EF_DISCARD; + break; + + case SMFIR_TEMPFAIL: + usrerr("451 4.7.1 Try again later"); + break; + } + if (response != NULL) + free(response); + } +# endif /* _FFR_MILTER */ + + define(macid("{rcpt_mailer}", NULL), NULL, e); + define(macid("{rcpt_relay}", NULL), NULL, e); + define(macid("{rcpt_addr}", NULL), NULL, e); + define(macid("{dsn_notify}", NULL), NULL, e); + if (Errors > 0) + break; + + /* 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 = a->q_paddr; + if (!QS_IS_BADADDR(a->q_state)) + { + if (e->e_queuedir == NOQDIR) + initsys(e); + message("250 2.1.5 Recipient ok%s", + QS_IS_QUEUEUP(a->q_state) ? + " (will queue)" : ""); + nrcpts++; + } + else + { + /* punt -- should keep message in ADDRESS.... */ + usrerr("550 5.1.1 Addressee unknown"); + } + break; + + case CMDDATA: /* data -- text of mail */ + SmtpPhase = "server DATA"; + if (!gotmail) + { + usrerr("503 5.0.0 Need MAIL command"); + break; + } + else if (nrcpts <= 0) + { + usrerr("503 5.0.0 Need RCPT (recipient)"); + break; + } + + /* put back discard bit */ + if (discard) + e->e_flags |= EF_DISCARD; + + /* check to see if we need to re-expand aliases */ + /* also reset QS_BADADDR on already-diagnosted addrs */ + doublequeue = FALSE; + for (a = e->e_sendqueue; a != NULL; a = a->q_next) + { + if (QS_IS_VERIFIED(a->q_state) && + !bitset(EF_DISCARD, e->e_flags)) + { + /* need to re-expand aliases */ + doublequeue = TRUE; + } + if (QS_IS_BADADDR(a->q_state)) + { + /* make this "go away" */ + a->q_state = QS_DONTSEND; + } + } + + /* collect the text of the message */ + SmtpPhase = "collect"; + buffer_errors(); + collect(InChannel, TRUE, NULL, e); + +# if _FFR_MILTER + if (milterize && + Errors <= 0 && + !bitset(EF_DISCARD, e->e_flags)) + { + char state; + char *response; + + response = milter_body(e, &state); + switch (state) + { + case SMFIR_REPLYCODE: + usrerr(response); + break; + + case SMFIR_REJECT: + usrerr("554 5.7.1 Command rejected"); + break; + + case SMFIR_DISCARD: + e->e_flags |= EF_DISCARD; + break; + + case SMFIR_TEMPFAIL: + usrerr("451 4.7.1 Try again later"); + break; + } + if (response != NULL) + free(response); + } + + /* abort message filters that didn't get the body */ + if (milterize) + milter_abort(e); +# endif /* _FFR_MILTER */ + + /* redefine message size */ + if ((q = macvalue(macid("{msg_size}", NULL), e)) + != NULL) + free(q); + snprintf(inp, sizeof inp, "%ld", e->e_msgsize); + define(macid("{msg_size}", NULL), newstr(inp), e); + if (Errors > 0) + { + /* Log who the mail would have gone to */ + if (LogLevel > 8 && + e->e_message != NULL) + { + for (a = e->e_sendqueue; + a != NULL; + a = a->q_next) + { + if (!QS_IS_UNDELIVERED(a->q_state)) + continue; + + e->e_to = a->q_paddr; + logdelivery(NULL, NULL, + a->q_status, + e->e_message, + NULL, + (time_t) 0, e); + } + e->e_to = NULL; + } + flush_errors(TRUE); + buffer_errors(); + 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"; + (void) bftruncate(e->e_xfp); + id = e->e_id; + + if (doublequeue) + { + /* make sure it is in the queue */ + queueup(e, FALSE); + } + else + { + /* send to all recipients */ +# if NAMED_BIND + _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; + _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; +# endif /* NAMED_BIND */ + sendall(e, SM_DEFAULT); + } + e->e_to = NULL; + + /* issue success message */ + message("250 2.0.0 %s Message accepted for delivery", id); + + /* if we just queued, poke it */ + if (doublequeue && + e->e_sendmode != SM_QUEUE && + e->e_sendmode != SM_DEFER) + { + CurrentLA = sm_getla(e); + + if (!shouldqueue(e->e_msgpriority, e->e_ctime)) + { + /* close all the queue files */ + closexscript(e); + if (e->e_dfp != NULL) + (void) bfclose(e->e_dfp); + e->e_dfp = NULL; + unlockqueue(e); + + (void) dowork(e->e_queuedir, id, + TRUE, TRUE, e); + } + } + + abortmessage: + if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) + logsender(e, NULL); + e->e_flags &= ~EF_LOGSENDER; + + /* if in a child, pop back to our parent */ + if (InChild) + finis(TRUE, ExitStat); + + /* clean up a bit */ + gotmail = FALSE; + dropenvelope(e, TRUE); + CurEnv = e = newenvelope(e, CurEnv); + e->e_flags = BlankEnvelope.e_flags; + break; + + case CMDRSET: /* rset -- reset state */ +# if _FFR_MILTER + /* abort milter filters */ + milter_abort(e); +# endif /* _FFR_MILTER */ + + if (tTd(94, 100)) + message("451 4.0.0 Test failure"); + else + message("250 2.0.0 Reset state"); + + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; + e->e_flags |= EF_CLRQUEUE; + + if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) + logsender(e, NULL); + e->e_flags &= ~EF_LOGSENDER; + + if (InChild) + finis(TRUE, ExitStat); + + /* clean up a bit */ + gotmail = FALSE; + SuprErrs = TRUE; + dropenvelope(e, TRUE); + CurEnv = e = newenvelope(e, CurEnv); + break; + + case CMDVRFY: /* vrfy -- verify address */ + case CMDEXPN: /* expn -- expand address */ + wt = checksmtpattack(&nverifies, MAXVRFYCOMMANDS, FALSE, + c->cmd_code == CMDVRFY ? "VRFY" : "EXPN", e); + previous = curtime(); + vrfy = c->cmd_code == CMDVRFY; + if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN, + PrivacyFlags)) + { + if (vrfy) + message("252 2.5.2 Cannot VRFY user; try RCPT to attempt delivery (or try finger)"); + else + message("502 5.7.0 Sorry, we do not allow this operation"); + if (LogLevel > 5) + sm_syslog(LOG_INFO, e->e_id, + "%.100s: %s [rejected]", + CurSmtpClient, + shortenstring(inp, MAXSHORTSTR)); + break; + } + else if (!gothello && + bitset(vrfy ? PRIV_NEEDVRFYHELO : PRIV_NEEDEXPNHELO, + PrivacyFlags)) + { + usrerr("503 5.0.0 I demand that you introduce yourself first"); + break; + } + if (runinchild(vrfy ? "SMTP-VRFY" : "SMTP-EXPN", e) > 0) + break; + if (Errors > 0) + goto undo_subproc; + if (LogLevel > 5) + sm_syslog(LOG_INFO, e->e_id, + "%.100s: %s", + CurSmtpClient, + shortenstring(inp, MAXSHORTSTR)); + if (setjmp(TopFrame) > 0) + goto undo_subproc; + QuickAbort = TRUE; + vrfyqueue = NULL; + if (vrfy) + e->e_flags |= EF_VRFYONLY; + while (*p != '\0' && isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + { + usrerr("501 5.5.2 Argument required"); + } + else + { + /* do config file checking of the address */ + if (rscheck(vrfy ? "check_vrfy" : "check_expn", + p, NULL, e, TRUE, FALSE) != EX_OK || + Errors > 0) + goto undo_subproc; + (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e); + } + if (wt > 0) + (void) sleep(wt - (curtime() - previous)); + if (Errors > 0) + goto undo_subproc; + if (vrfyqueue == NULL) + { + usrerr("554 5.5.2 Nothing to %s", vrfy ? "VRFY" : "EXPN"); + } + while (vrfyqueue != NULL) + { + if (!QS_IS_UNDELIVERED(vrfyqueue->q_state)) + { + vrfyqueue = vrfyqueue->q_next; + continue; + } + + /* see if there is more in the vrfy list */ + a = vrfyqueue; + while ((a = a->q_next) != NULL && + (!QS_IS_UNDELIVERED(vrfyqueue->q_state))) + continue; + printvrfyaddr(vrfyqueue, a == NULL, vrfy); + vrfyqueue = a; + } + if (InChild) + finis(TRUE, ExitStat); + break; + + case CMDETRN: /* etrn -- force queue flush */ + if (bitset(PRIV_NOETRN, PrivacyFlags) || + bitnset(D_NOETRN, d_flags)) + { + /* different message for MSA ? */ + message("502 5.7.0 Sorry, we do not allow this operation"); + if (LogLevel > 5) + sm_syslog(LOG_INFO, e->e_id, + "%.100s: %s [rejected]", + CurSmtpClient, + shortenstring(inp, MAXSHORTSTR)); + break; + } + + if (strlen(p) <= 0) + { + usrerr("500 5.5.2 Parameter required"); + break; + } + + /* crude way to avoid denial-of-service attacks */ + (void) checksmtpattack(&n_etrn, MAXETRNCOMMANDS, TRUE, + "ETRN", e); + + /* do config file checking of the parameter */ + if (rscheck("check_etrn", p, NULL, e, TRUE, FALSE) + != EX_OK || Errors > 0) + break; + + if (LogLevel > 5) + sm_syslog(LOG_INFO, e->e_id, + "%.100s: ETRN %s", + CurSmtpClient, + shortenstring(p, MAXSHORTSTR)); + + id = p; + if (*id == '@') + id++; + else + *--id = '@'; + + if ((new = (QUEUE_CHAR *)malloc(sizeof(QUEUE_CHAR))) == NULL) + { + syserr("500 5.5.0 ETRN out of memory"); + break; + } + new->queue_match = id; + new->queue_next = NULL; + QueueLimitRecipient = new; + ok = runqueue(TRUE, FALSE); + free(QueueLimitRecipient); + QueueLimitRecipient = NULL; + if (ok && Errors == 0) + message("250 2.0.0 Queuing for node %s started", p); + break; + + case CMDHELP: /* help -- give user info */ + help(p, e); + break; + + case CMDNOOP: /* noop -- do nothing */ + (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE, + "NOOP", e); + message("250 2.0.0 OK"); + break; + + case CMDQUIT: /* quit -- leave mail */ + message("221 2.0.0 %s closing connection", MyHostName); + + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; + +# if SASL + if (authenticating == SASL_IS_AUTH) + { + sasl_dispose(&conn); + authenticating = SASL_NOT_AUTH; + } +# endif /* SASL */ + +doquit: + /* avoid future 050 messages */ + disconnect(1, e); + +# if _FFR_MILTER + /* close out milter filters */ + milter_quit(e); +# endif /* _FFR_MILTER */ + + if (InChild) + ExitStat = EX_QUIT; + + if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags)) + logsender(e, NULL); + e->e_flags &= ~EF_LOGSENDER; + + if (lognullconnection && LogLevel > 5) + { + char *d; + + d = macvalue(macid("{daemon_name}", NULL), e); + if (d == NULL) + d = "stdin"; + sm_syslog(LOG_INFO, NULL, + "%.100s did not issue MAIL/EXPN/VRFY/ETRN during connection to %s", + CurSmtpClient, d); + } + finis(TRUE, ExitStat); + /* NOTREACHED */ + + case CMDVERB: /* set verbose mode */ + if (bitset(PRIV_NOEXPN, PrivacyFlags) || + bitset(PRIV_NOVERB, PrivacyFlags)) + { + /* this would give out the same info */ + message("502 5.7.0 Verbose unavailable"); + break; + } + (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE, + "VERB", e); + Verbose = 1; + set_delivery_mode(SM_DELIVER, e); + message("250 2.0.0 Verbose mode"); + break; + + case CMDONEX: /* doing one transaction only */ + (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE, + "ONEX", e); + OneXact = TRUE; + message("250 2.0.0 Only one transaction"); + break; + + case CMDXUSR: /* initial (user) submission */ + (void) checksmtpattack(&n_noop, MAXNOOPCOMMANDS, TRUE, + "XUSR", e); + define(macid("{daemon_flags}", NULL), "c u", CurEnv); + message("250 2.0.0 Initial submission"); + break; + +# if 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 2.0.0 Debug set"); + break; + +# else /* SMTPDEBUG */ + case CMDDBGQSHOW: /* show queues */ + case CMDDBGDEBUG: /* set debug mode */ +# endif /* SMTPDEBUG */ + case CMDLOGBOGUS: /* bogus command */ + if (LogLevel > 0) + sm_syslog(LOG_CRIT, e->e_id, + "\"%s\" command from %.100s (%.100s)", + c->cmd_name, CurSmtpClient, + anynet_ntoa(&RealHostAddr)); + /* FALLTHROUGH */ + + case CMDERROR: /* unknown command */ + if (++badcommands > MAXBADCOMMANDS) + { + message("421 4.7.0 %s Too many bad commands; closing connection", + MyHostName); + + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; + goto doquit; + } + + usrerr("500 5.5.1 Command unrecognized: \"%s\"", + shortenstring(inp, MAXSHORTSTR)); + break; + + case CMDUNIMPL: + usrerr("502 5.5.1 Command not implemented: \"%s\"", + shortenstring(inp, MAXSHORTSTR)); + break; + + default: + errno = 0; + syserr("500 5.5.0 smtp: unknown code %d", c->cmd_code); + break; + } +# if SASL + } +# endif /* SASL */ + } + +} + /* +** CHECKSMTPATTACK -- check for denial-of-service attack by repetition +** +** Parameters: +** pcounter -- pointer to a counter for this command. +** maxcount -- maximum value for this counter before we +** slow down. +** waitnow -- sleep now (in this routine)? +** cname -- command name for logging. +** e -- the current envelope. +** +** Returns: +** none. +** +** Side Effects: +** Slows down if we seem to be under attack. +*/ + +static time_t +checksmtpattack(pcounter, maxcount, waitnow, cname, e) + volatile int *pcounter; + int maxcount; + bool waitnow; + char *cname; + ENVELOPE *e; +{ + if (++(*pcounter) >= maxcount) + { + time_t s; + + if (*pcounter == maxcount && LogLevel > 5) + { + sm_syslog(LOG_INFO, e->e_id, + "%.100s: %.40s attack?", + CurSmtpClient, cname); + } + s = 1 << (*pcounter - maxcount); + if (s >= MAXTIMEOUT) + s = MAXTIMEOUT; + /* sleep at least 1 second before returning */ + (void) sleep(*pcounter / maxcount); + s -= *pcounter / maxcount; + if (waitnow) + { + (void) sleep(s); + return(0); + } + return(s); + } + return((time_t) 0); +} + /* +** 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 *volatile 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: + usrerr("501 5.5.2 Syntax error in parameters scanning \"%s\"", + shortenstring(firstp, MAXSHORTSTR)); + 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. +*/ + +static void +mail_esmtp_args(kp, vp, e) + char *kp; + char *vp; + ENVELOPE *e; +{ + if (strcasecmp(kp, "size") == 0) + { + if (vp == NULL) + { + usrerr("501 5.5.2 SIZE requires a value"); + /* NOTREACHED */ + } + define(macid("{msg_size}", NULL), newstr(vp), e); +# if defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) + e->e_msgsize = strtoul(vp, (char **) NULL, 10); +# else /* defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) */ + e->e_msgsize = strtol(vp, (char **) NULL, 10); +# endif /* defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) */ + } + else if (strcasecmp(kp, "body") == 0) + { + if (vp == NULL) + { + usrerr("501 5.5.2 BODY requires a value"); + /* NOTREACHED */ + } + else if (strcasecmp(vp, "8bitmime") == 0) + { + SevenBitInput = FALSE; + } + else if (strcasecmp(vp, "7bit") == 0) + { + SevenBitInput = TRUE; + } + else + { + usrerr("501 5.5.4 Unknown BODY type %s", + vp); + /* NOTREACHED */ + } + e->e_bodytype = newstr(vp); + } + else if (strcasecmp(kp, "envid") == 0) + { + if (bitset(PRIV_NORECEIPTS, PrivacyFlags)) + { + usrerr("504 5.7.0 Sorry, ENVID not supported, we do not allow DSN"); + /* NOTREACHED */ + } + if (vp == NULL) + { + usrerr("501 5.5.2 ENVID requires a value"); + /* NOTREACHED */ + } + if (!xtextok(vp)) + { + usrerr("501 5.5.4 Syntax error in ENVID parameter value"); + /* NOTREACHED */ + } + if (e->e_envid != NULL) + { + usrerr("501 5.5.0 Duplicate ENVID parameter"); + /* NOTREACHED */ + } + e->e_envid = newstr(vp); + define(macid("{dsn_envid}", NULL), newstr(vp), e); + } + else if (strcasecmp(kp, "ret") == 0) + { + if (bitset(PRIV_NORECEIPTS, PrivacyFlags)) + { + usrerr("504 5.7.0 Sorry, RET not supported, we do not allow DSN"); + /* NOTREACHED */ + } + if (vp == NULL) + { + usrerr("501 5.5.2 RET requires a value"); + /* NOTREACHED */ + } + if (bitset(EF_RET_PARAM, e->e_flags)) + { + usrerr("501 5.5.0 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 5.5.2 Bad argument \"%s\" to RET", vp); + /* NOTREACHED */ + } + define(macid("{dsn_ret}", NULL), newstr(vp), e); + } +# if SASL + else if (strcasecmp(kp, "auth") == 0) + { + int len; + char *q; + char *auth_param; /* the value of the AUTH=x */ + bool saveQuickAbort = QuickAbort; + bool saveSuprErrs = SuprErrs; + char pbuf[256]; + + if (vp == NULL) + { + usrerr("501 5.5.2 AUTH= requires a value"); + /* NOTREACHED */ + } + if (e->e_auth_param != NULL) + { + usrerr("501 5.5.0 Duplicate AUTH parameter"); + /* NOTREACHED */ + } + if ((q = strchr(vp, ' ')) != NULL) + len = q - vp + 1; + else + len = strlen(vp) + 1; + auth_param = xalloc(len); + (void) strlcpy(auth_param, vp, len); + if (!xtextok(auth_param)) + { + usrerr("501 5.5.4 Syntax error in AUTH parameter value"); + /* just a warning? */ + /* NOTREACHED */ + } + + /* XXX this might be cut off */ + snprintf(pbuf, sizeof pbuf, "%s", xuntextify(auth_param)); + /* xalloc() the buffer instead? */ + + /* XXX define this always or only if trusted? */ + define(macid("{auth_author}", NULL), newstr(pbuf), e); + + /* + ** call Strust_auth to find out whether + ** auth_param is acceptable (trusted) + ** we shouldn't trust it if not authenticated + ** (required by RFC, leave it to ruleset?) + */ + + SuprErrs = TRUE; + QuickAbort = FALSE; + if (strcmp(auth_param, "<>") != 0 && + (rscheck("trust_auth", pbuf, NULL, e, TRUE, FALSE) + != EX_OK || Errors > 0)) + { + if (tTd(95, 8)) + { + q = e->e_auth_param; + dprintf("auth=\"%.100s\" not trusted user=\"%.100s\"\n", + pbuf, (q == NULL) ? "" : q); + } + /* not trusted */ + e->e_auth_param = newstr("<>"); + } + else + { + if (tTd(95, 8)) + dprintf("auth=\"%.100s\" trusted\n", pbuf); + e->e_auth_param = newstr(auth_param); + } + free(auth_param); + /* reset values */ + Errors = 0; + QuickAbort = saveQuickAbort; + SuprErrs = saveSuprErrs; + } +# endif /* SASL */ + else + { + usrerr("501 5.5.4 %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. +*/ + +static void +rcpt_esmtp_args(a, kp, vp, e) + ADDRESS *a; + char *kp; + char *vp; + ENVELOPE *e; +{ + if (strcasecmp(kp, "notify") == 0) + { + char *p; + + if (bitset(PRIV_NORECEIPTS, PrivacyFlags)) + { + usrerr("504 5.7.0 Sorry, NOTIFY not supported, we do not allow DSN"); + /* NOTREACHED */ + } + if (vp == NULL) + { + usrerr("501 5.5.2 NOTIFY requires a value"); + /* NOTREACHED */ + } + a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY); + a->q_flags |= QHASNOTIFY; + define(macid("{dsn_notify}", NULL), newstr(vp), e); + + 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 5.5.4 Bad argument \"%s\" to NOTIFY", + vp); + /* NOTREACHED */ + } + } + } + else if (strcasecmp(kp, "orcpt") == 0) + { + if (bitset(PRIV_NORECEIPTS, PrivacyFlags)) + { + usrerr("504 5.7.0 Sorry, ORCPT not supported, we do not allow DSN"); + /* NOTREACHED */ + } + if (vp == NULL) + { + usrerr("501 5.5.2 ORCPT requires a value"); + /* NOTREACHED */ + } + if (strchr(vp, ';') == NULL || !xtextok(vp)) + { + usrerr("501 5.5.4 Syntax error in ORCPT parameter value"); + /* NOTREACHED */ + } + if (a->q_orcpt != NULL) + { + usrerr("501 5.5.0 Duplicate ORCPT parameter"); + /* NOTREACHED */ + } + a->q_orcpt = newstr(vp); + } + else + { + usrerr("501 5.5.4 %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. +** vrfy -- set if this is a VRFY command. +** +** Returns: +** none. +** +** Side Effects: +** Prints the appropriate 250 codes. +*/ +#define OFFF (3 + 1 + 5 + 1) /* offset in fmt: SMTP reply + enh. code */ + +static void +printvrfyaddr(a, last, vrfy) + register ADDRESS *a; + bool last; + bool vrfy; +{ + char fmtbuf[30]; + + if (vrfy && a->q_mailer != NULL && + !bitnset(M_VRFY250, a->q_mailer->m_flags)) + (void) strlcpy(fmtbuf, "252", sizeof fmtbuf); + else + (void) strlcpy(fmtbuf, "250", sizeof fmtbuf); + fmtbuf[3] = last ? ' ' : '-'; + (void) strlcpy(&fmtbuf[4], "2.1.5 ", sizeof fmtbuf - 4); + if (a->q_fullname == NULL) + { + if ((a->q_mailer == NULL || + a->q_mailer->m_addrtype == NULL || + strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) && + strchr(a->q_user, '@') == NULL) + (void) strlcpy(&fmtbuf[OFFF], "<%s@%s>", + sizeof fmtbuf - OFFF); + else + (void) strlcpy(&fmtbuf[OFFF], "<%s>", + sizeof fmtbuf - OFFF); + message(fmtbuf, a->q_user, MyHostName); + } + else + { + if ((a->q_mailer == NULL || + a->q_mailer->m_addrtype == NULL || + strcasecmp(a->q_mailer->m_addrtype, "rfc822") == 0) && + strchr(a->q_user, '@') == NULL) + (void) strlcpy(&fmtbuf[OFFF], "%s <%s@%s>", + sizeof fmtbuf - OFFF); + else + (void) strlcpy(&fmtbuf[OFFF], "%s <%s>", + sizeof fmtbuf - OFFF); + 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. +*/ + +static int +runinchild(label, e) + char *label; + register ENVELOPE *e; +{ + pid_t childpid; + + if (!OneXact) + { + extern int NumQueues; + + /* + ** advance state of PRNG + ** this is necessary because otherwise all child processes + ** will produce the same PRN sequence and hence the selection + ** of a queue directory is not "really" random. + */ + if (NumQueues > 1) + (void) get_random(); + + /* + ** Disable child process reaping, in case ETRN has preceded + ** MAIL command, and then fork. + */ + + (void) blocksignal(SIGCHLD); + + childpid = dofork(); + if (childpid < 0) + { + syserr("451 4.3.0 %s: cannot fork", label); + (void) releasesignal(SIGCHLD); + return 1; + } + if (childpid > 0) + { + auto int st; + + /* parent -- wait for child to complete */ + sm_setproctitle(TRUE, e, "server %s child wait", + CurSmtpClient); + st = waitfor(childpid); + if (st == -1) + syserr("451 4.3.0 %s: lost child", label); + else if (!WIFEXITED(st)) + syserr("451 4.3.0 %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(TRUE, ExitStat); + } + + /* restore the child signal */ + (void) releasesignal(SIGCHLD); + + return 1; + } + else + { + /* child */ + InChild = TRUE; + QuickAbort = FALSE; + clearstats(); + clearenvelope(e, FALSE); + assign_queueid(e); + (void) setsignal(SIGCHLD, SIG_DFL); + (void) releasesignal(SIGCHLD); + } + } + return 0; +} + +# if SASL + +static bool +saslmechs(conn, mechlist, sasl_ok) + sasl_conn_t *conn; + char **mechlist; + bool sasl_ok; +{ + int len, num, result; + + if (sasl_ok) + { + /* "user" is currently unused */ + result = sasl_listmech(conn, "user", /* XXX */ + "", " ", "", mechlist, + (u_int *)&len, (u_int *)&num); + if (result == SASL_OK && num > 0) + { + if (LogLevel > 11) + sm_syslog(LOG_INFO, NOQID, + "SASL: available mech=%s, allowed mech=%s", + *mechlist, AuthMechanisms); + *mechlist = intersect(AuthMechanisms, *mechlist); + } + else + { + sasl_ok = FALSE; + if (LogLevel > 9) + sm_syslog(LOG_WARNING, NOQID, + "SASL error: listmech=%d, num=%d", + result, num); + } + } + return sasl_ok; +} + +int +proxy_policy(context, auth_identity, requested_user, user, errstr) + void *context; + const char *auth_identity; + const char *requested_user; + const char **user; + const char **errstr; +{ + if (user != NULL) + { + *user = newstr(auth_identity); + return SASL_OK; + } + return SASL_FAIL; +} + +# endif /* SASL */ + +#endif /* SMTP */ + /* +** HELP -- implement the HELP command. +** +** Parameters: +** topic -- the topic we want help for. +** e -- envelope +** +** Returns: +** none. +** +** Side Effects: +** outputs the help file to message output. +*/ +#define HELPVSTR "#vers " +#define HELPVERSION 2 + +void +help(topic, e) + char *topic; + ENVELOPE *e; +{ + register FILE *hf; + register char *p; + int len; + bool noinfo; + bool first = TRUE; + long sff = SFF_OPENASROOT|SFF_REGONLY; + char buf[MAXLINE]; + char inp[MAXLINE]; + static int foundvers = -1; + extern char Version[]; + + if (DontLockReadFiles) + sff |= SFF_NOLOCK; + if (!bitnset(DBS_HELPFILEINUNSAFEDIRPATH, DontBlameSendmail)) + sff |= SFF_SAFEDIRPATH; + + if (HelpFile == NULL || + (hf = safefopen(HelpFile, O_RDONLY, 0444, sff)) == NULL) + { + /* no help */ + errno = 0; + message("502 5.3.0 Sendmail %s -- HELP not implemented", + Version); + return; + } + + if (topic == NULL || *topic == '\0') + { + topic = "smtp"; + noinfo = FALSE; + } + else + { + makelower(topic); + noinfo = TRUE; + } + + len = strlen(topic); + + while (fgets(buf, sizeof buf, hf) != NULL) + { + if (buf[0] == '#') + { + if (foundvers < 0 && + strncmp(buf, HELPVSTR, strlen(HELPVSTR)) == 0) + { + int h; + + if (sscanf(buf + strlen(HELPVSTR), "%d", + &h) == 1) + foundvers = h; + } + continue; + } + if (strncmp(buf, topic, len) == 0) + { + if (first) + { + first = FALSE; + + /* print version if no/old vers# in file */ + if (foundvers < 2 && !noinfo) + message("214-2.0.0 This is Sendmail version %s", Version); + } + p = strpbrk(buf, " \t"); + if (p == NULL) + p = buf + strlen(buf) - 1; + else + p++; + fixcrlf(p, TRUE); + if (foundvers >= 2) + { + translate_dollars(p); + expand(p, inp, sizeof inp, e); + p = inp; + } + message("214-2.0.0 %s", p); + noinfo = FALSE; + } + } + + if (noinfo) + message("504 5.3.0 HELP topic \"%.10s\" unknown", topic); + else + message("214 2.0.0 End of HELP info"); + + if (foundvers != 0 && foundvers < HELPVERSION) + { + if (LogLevel > 1) + sm_syslog(LOG_WARNING, e->e_id, + "%s too old (require version %d)", + HelpFile, HELPVERSION); + + /* avoid log next time */ + foundvers = 0; + } + + (void) fclose(hf); +} diff --git a/gnu/usr.sbin/sendmail/sendmail/stab.c b/gnu/usr.sbin/sendmail/sendmail/stab.c new file mode 100644 index 00000000000..8ce82d4312d --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/stab.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: stab.c,v 8.40 1999/11/04 23:31:07 gshapiro Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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; + int len; + + if (tTd(36, 5)) + dprintf("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)) + dprintf("(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) + dprintf("not found\n"); + else + { + long *lp = (long *) s->s_class; + + dprintf("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)) + dprintf("entered\n"); + + /* determine size of new entry */ + switch (type) + { + case ST_CLASS: + len = sizeof s->s_class; + break; + + case ST_ADDRESS: + len = sizeof s->s_address; + break; + + case ST_MAILER: + len = sizeof s->s_mailer; + break; + + case ST_ALIAS: + len = sizeof s->s_alias; + break; + + case ST_MAPCLASS: + len = sizeof s->s_mapclass; + break; + + case ST_MAP: + len = sizeof s->s_map; + break; + + case ST_HOSTSIG: + len = sizeof s->s_hostsig; + break; + + case ST_NAMECANON: + len = sizeof s->s_namecanon; + break; + + case ST_MACRO: + len = sizeof s->s_macro; + break; + + case ST_RULESET: + len = sizeof s->s_ruleset; + break; + + case ST_HEADER: + len = sizeof s->s_header; + break; + + case ST_SERVICE: + len = sizeof s->s_service; + break; + +#ifdef LDAPMAP + case ST_LDAP: + len = sizeof s->s_ldap; + break; +#endif /* LDAPMAP */ + +#if _FFR_MILTER + case ST_MILTER: + len = sizeof s->s_milter; + break; +#endif /* _FFR_MILTER */ + + default: + /* + ** Each mailer has it's own MCI stab entry: + ** + ** s = stab(host, ST_MCI + m->m_mno, ST_ENTER); + ** + ** Therefore, anything ST_MCI or larger is an s_mci. + */ + + if (type >= ST_MCI) + len = sizeof s->s_mci; + else + { + syserr("stab: unknown symbol type %d", type); + len = sizeof s->s_value; + } + break; + } + len += sizeof *s - sizeof s->s_value; + + if (tTd(36, 15)) + dprintf("size of stab entry: %d\n", len); + + /* make new entry */ + s = (STAB *) xalloc(len); + memset((char *) s, '\0', len); + s->s_name = newstr(name); + s->s_type = type; + s->s_len = len; + + /* link it in */ + *ps = s; + + /* set a default value for rulesets */ + if (type == ST_RULESET) + s->s_ruleset = -1; + + 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)) + dprintf("stabapply: trying %d/%s\n", + s->s_type, s->s_name); + func(s, arg); + } + } +} + /* +** QUEUEUP_MACROS -- queueup the macros in a class +** +** Write the macros listed in the specified class into the +** file referenced by qfp. +** +** Parameters: +** class -- class ID. +** qfp -- file pointer to the qf file. +** e -- the envelope. +** +** Returns: +** none. +*/ + +void +queueup_macros(class, qfp, e) + int class; + FILE *qfp; + ENVELOPE *e; +{ + register STAB **shead; + register STAB *s; + + if (e == NULL) + return; + + for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) + { + for (s = *shead; s != NULL; s = s->s_next) + { + int m; + char *p; + + if (s->s_type == ST_CLASS && + bitnset(class & 0xff, s->s_class) && + (m = macid(s->s_name, NULL)) != '\0' && + (p = macvalue(m, e)) != NULL) + { + fprintf(qfp, "$%s%s\n", + s->s_name, + denlstring(p, TRUE, FALSE)); + } + } + } +} + /* +** COPY_CLASS -- copy class members from one class to another +** +** Parameters: +** src -- source class. +** dst -- destination class. +** +** Returns: +** none. +*/ + +void +copy_class(src, dst) + int src; + int dst; +{ + register STAB **shead; + register STAB *s; + + for (shead = SymTab; shead < &SymTab[STABSIZE]; shead++) + { + for (s = *shead; s != NULL; s = s->s_next) + { + if (s->s_type == ST_CLASS && + bitnset(src & 0xff, s->s_class)) + setbitn(dst, s->s_class); + } + } +} diff --git a/gnu/usr.sbin/sendmail/sendmail/stats.c b/gnu/usr.sbin/sendmail/sendmail/stats.c new file mode 100644 index 00000000000..d081babc5ef --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/stats.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: stats.c,v 8.36 1999/12/06 21:17:02 ca Exp $"; +#endif /* ! lint */ + +#include +#include + +static struct statistics Stat; + +static 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 +** +** Parameters: +** e -- the envelope. +** to -- to address. +** reject -- whether this is a rejection. +** +** Returns: +** none. +** +** Side Effects: +** changes static Stat structure +*/ + +void +markstats(e, to, reject) + register ENVELOPE *e; + register ADDRESS *to; + bool reject; +{ + if (reject) + { + if (e->e_from.q_mailer != NULL) + { + if (bitset(EF_DISCARD, e->e_flags)) + Stat.stat_nd[e->e_from.q_mailer->m_mno]++; + else + Stat.stat_nr[e->e_from.q_mailer->m_mno]++; + } + Stat.stat_cr++; + } + else if (to == NULL) + { + Stat.stat_cf++; + 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_ct++; + Stat.stat_nt[to->q_mailer->m_mno]++; + Stat.stat_bt[to->q_mailer->m_mno] += KBYTES(e->e_msgsize); + } + GotStats = TRUE; +} + /* +** CLEARSTATS -- clear statistics structure +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** clears the Stat structure. +*/ + +void +clearstats() +{ + /* clear the structure to avoid future disappointment */ + memset(&Stat, '\0', sizeof Stat); + GotStats = FALSE; +} + /* +** 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; + long sff = SFF_REGONLY|SFF_OPENASROOT; + struct statistics stats; + extern off_t lseek(); + + if (sfile == NULL || !GotStats) + return; + + (void) time(&Stat.stat_itime); + Stat.stat_size = sizeof Stat; + Stat.stat_magic = STAT_MAGIC; + Stat.stat_version = STAT_VERSION; + + if (!bitnset(DBS_WRITESTATSTOSYMLINK, DontBlameSendmail)) + sff |= SFF_NOSLINK; + if (!bitnset(DBS_WRITESTATSTOHARDLINK, DontBlameSendmail)) + sff |= SFF_NOHLINK; + + fd = safeopen(sfile, O_RDWR, 0644, sff); + if (fd < 0) + { + if (LogLevel > 12) + sm_syslog(LOG_INFO, NOQID, "poststats: %s: %s", + sfile, errstring(errno)); + errno = 0; + return; + } + if (read(fd, (char *) &stats, sizeof stats) == sizeof stats && + stats.stat_size == sizeof stats && + stats.stat_magic == Stat.stat_magic && + stats.stat_version == Stat.stat_version) + { + /* merge current statistics into statfile */ + register int i; + + for (i = 0; i < MAXMAILERS; i++) + { + stats.stat_nf[i] += Stat.stat_nf[i]; + stats.stat_bf[i] += Stat.stat_bf[i]; + stats.stat_nt[i] += Stat.stat_nt[i]; + stats.stat_bt[i] += Stat.stat_bt[i]; + stats.stat_nr[i] += Stat.stat_nr[i]; + stats.stat_nd[i] += Stat.stat_nd[i]; + } + stats.stat_cr += Stat.stat_cr; + stats.stat_ct += Stat.stat_ct; + stats.stat_cf += Stat.stat_cf; + } + else + memmove((char *) &stats, (char *) &Stat, sizeof stats); + + /* write out results */ + (void) lseek(fd, (off_t) 0, 0); + (void) write(fd, (char *) &stats, sizeof stats); + (void) close(fd); + + /* clear the structure to avoid future disappointment */ + clearstats(); +} diff --git a/gnu/usr.sbin/sendmail/sendmail/statusd_shm.h b/gnu/usr.sbin/sendmail/sendmail/statusd_shm.h new file mode 100644 index 00000000000..5f61a447242 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/statusd_shm.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: statusd_shm.h,v 8.4 1999/05/18 08:00:04 gshapiro Exp $ + * + * Contributed by Exactis.com, Inc. + * + */ + +/* +** The shared memory part of statusd. +** +** Attach to STATUSD_SHM_KEY and update the counter appropriate +** for your type of service. +** +*/ + +#define STATUSD_MAGIC 110946 +#define STATUSD_SHM_KEY (key_t)(13) +#define STATUSD_LONGS (2) + +typedef struct { + unsigned long magic; + unsigned long ul[STATUSD_LONGS]; +} STATUSD_SHM; + +/* +** Offsets into ul[]. The appropriate program +** increments these as appropriate. +*/ + +#define STATUSD_COOKIE (0) /* reregister cookie */ + +/* sendmail */ +#define STATUSD_SM_NSENDMAIL (1) /* how many running */ + +extern void shmtick __P((int, int)); + diff --git a/gnu/usr.sbin/sendmail/sendmail/sysexits.c b/gnu/usr.sbin/sendmail/sendmail/sysexits.c new file mode 100644 index 00000000000..9410e0cf12f --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sysexits.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: sysexits.c,v 8.25 1999/09/23 19:59:24 ca Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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 5.0.0 Bad usage", + /* 65 DATAERR */ " 501 5.6.0 Data format error", + /* 66 NOINPUT */ ":550 5.3.0 Cannot open input", + /* 67 NOUSER */ " 550 5.1.1 User unknown", + /* 68 NOHOST */ " 550 5.1.2 Host unknown", + /* 69 UNAVAILABLE */ " 554 5.0.0 Service unavailable", + /* 70 SOFTWARE */ ":554 5.3.0 Internal error", + /* 71 OSERR */ ":451 4.0.0 Operating system error", + /* 72 OSFILE */ ":554 5.3.5 System file missing", + /* 73 CANTCREAT */ ":550 5.0.0 Can't create output", + /* 74 IOERR */ ":451 4.0.0 I/O error", + /* 75 TEMPFAIL */ " 450 4.0.0 Deferred", + /* 76 PROTOCOL */ " 554 5.5.0 Remote protocol error", + /* 77 NOPERM */ ":550 5.0.0 Insufficient permission", + /* 78 CONFIG */ " 554 5.3.5 Local configuration error", +}; + +int N_SysEx = sizeof(SysExMsg) / sizeof(SysExMsg[0]); + +static char *SysExitMsg[] = +{ + "command line usage error", + "data format error", + "cannot open input", + "addressee unknown", + "host name unknown", + "service unavailable", + "internal software error", + "system error (e.g., can't fork)", + "critical OS file missing", + "can't create (user) output file", + "input/output error", + "temp failure; user is invited to retry", + "remote error in protocol", + "permission denied", + "configuration error" +}; + + /* +** 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 accepting 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; +} + + /* +** EXITSTAT -- convert EX_ value to error text. +** +** Parameters: +** excode -- rstatus which might consists of an EX_* value. +** +** Returns: +** The corresponding error text or the original string. +*/ + +char * +exitstat(excode) + char *excode; +{ + char *c; + int i; + + if (excode == NULL || *excode == '\0') + return excode; + i = 0; + for (c = excode; *c != '\0'; c++) + { + if (isascii(*c) && isdigit(*c)) + i = i * 10 + (*c - '0'); + else + return excode; + } + i -= EX__BASE; + if (i >= 0 && i <= N_SysEx) + return SysExitMsg[i]; + return excode; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/sysexits.h b/gnu/usr.sbin/sendmail/sendmail/sysexits.h new file mode 100644 index 00000000000..46c892d1d0a --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/sysexits.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: sysexits.h,v 8.3 1999/05/18 00:49:35 gshapiro Exp $ + * @(#)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/gnu/usr.sbin/sendmail/sendmail/timers.c b/gnu/usr.sbin/sendmail/sendmail/timers.c new file mode 100644 index 00000000000..2d40b807882 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/timers.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: timers.c,v 8.13 1999/11/23 07:22:28 gshapiro Exp $"; +#endif /* ! lint */ + +#if _FFR_TIMERS +# include +# include +# include "sendmail.h" +# include /* Must be after sendmail.h for NCR MP-RAS */ + +static TIMER BaseTimer; /* current baseline */ +static int NTimers; /* current pointer into stack */ +static TIMER *TimerStack[MAXTIMERSTACK]; + +static void +# ifdef __STDC__ +warntimer(const char *msg, ...) +# else /* __STDC__ */ +warntimer(msg, va_alist) + const char *msg; + va_dcl +# endif /* __STDC__ */ +{ + char buf[MAXLINE]; + VA_LOCAL_DECL + +# if 0 + if (!tTd(98, 30)) + return; +# endif /* 0 */ + VA_START(msg); + vsnprintf(buf, sizeof buf, msg, ap); + VA_END; + sm_syslog(LOG_NOTICE, CurEnv->e_id, "%s; e_timers=0x%lx", + buf, (u_long) &CurEnv->e_timers); +} + +static void +zerotimer(ptimer) + TIMER *ptimer; +{ + memset(ptimer, '\0', sizeof *ptimer); +} + +static void +addtimer(ta, tb) + TIMER *ta; + TIMER *tb; +{ + tb->ti_wall_sec += ta->ti_wall_sec; + tb->ti_wall_usec += ta->ti_wall_usec; + if (tb->ti_wall_usec > 1000000) + { + tb->ti_wall_sec++; + tb->ti_wall_usec -= 1000000; + } + tb->ti_cpu_sec += ta->ti_cpu_sec; + tb->ti_cpu_usec += ta->ti_cpu_usec; + if (tb->ti_cpu_usec > 1000000) + { + tb->ti_cpu_sec++; + tb->ti_cpu_usec -= 1000000; + } +} + +static void +subtimer(ta, tb) + TIMER *ta; + TIMER *tb; +{ + tb->ti_wall_sec -= ta->ti_wall_sec; + tb->ti_wall_usec -= ta->ti_wall_usec; + if (tb->ti_wall_usec < 0) + { + tb->ti_wall_sec--; + tb->ti_wall_usec += 1000000; + } + tb->ti_cpu_sec -= ta->ti_cpu_sec; + tb->ti_cpu_usec -= ta->ti_cpu_usec; + if (tb->ti_cpu_usec < 0) + { + tb->ti_cpu_sec--; + tb->ti_cpu_usec += 1000000; + } +} + +static int +getcurtimer(ptimer) + TIMER *ptimer; +{ + struct rusage ru; + struct timeval now; + + if (getrusage(RUSAGE_SELF, &ru) < 0 || gettimeofday(&now, NULL) < 0) + return -1; + ptimer->ti_wall_sec = now.tv_sec; + ptimer->ti_wall_usec = now.tv_usec; + ptimer->ti_cpu_sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec; + ptimer->ti_cpu_usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec; + if (ptimer->ti_cpu_usec > 1000000) + { + ptimer->ti_cpu_sec++; + ptimer->ti_cpu_usec -= 1000000; + } + return 0; +} + +static void +getinctimer(ptimer) + TIMER *ptimer; +{ + TIMER cur; + + if (getcurtimer(&cur) < 0) + { + zerotimer(ptimer); + return; + } + if (BaseTimer.ti_wall_sec == 0) + { + /* first call */ + memset(ptimer, '\0', sizeof *ptimer); + } + else + { + *ptimer = cur; + subtimer(&BaseTimer, ptimer); + } + BaseTimer = cur; +} + +void +flushtimers() +{ + NTimers = 0; + (void) getcurtimer(&BaseTimer); +} + +void +pushtimer(ptimer) + TIMER *ptimer; +{ + int i; + int save_errno = errno; + TIMER incr; + + /* find how much time has changed since last call */ + getinctimer(&incr); + + /* add that into the old timers */ + i = NTimers; + if (i > MAXTIMERSTACK) + i = MAXTIMERSTACK; + while (--i >= 0) + { + addtimer(&incr, TimerStack[i]); + if (TimerStack[i] == ptimer) + { + warntimer("Timer@0x%lx already on stack, index=%d, NTimers=%d", + (u_long) ptimer, i, NTimers); + errno = save_errno; + return; + } + } + errno = save_errno; + + /* handle stack overflow */ + if (NTimers >= MAXTIMERSTACK) + return; + + /* now add the timer to the stack */ + TimerStack[NTimers++] = ptimer; +} + +void +poptimer(ptimer) + TIMER *ptimer; +{ + int i; + int save_errno = errno; + TIMER incr; + + /* find how much time has changed since last call */ + getinctimer(&incr); + + /* add that into the old timers */ + i = NTimers; + if (i > MAXTIMERSTACK) + i = MAXTIMERSTACK; + while (--i >= 0) + addtimer(&incr, TimerStack[i]); + + /* pop back to this timer */ + for (i = 0; i < NTimers; i++) + if (TimerStack[i] == ptimer) + break; + if (i != NTimers - 1) + warntimer("poptimer: odd pop (timer=0x%lx, index=%d, NTimers=%d)", + (u_long) ptimer, i, NTimers); + NTimers = i; + + /* clean up and return */ + errno = save_errno; +} + +char * +strtimer(ptimer) + TIMER *ptimer; +{ + static char buf[40]; + + snprintf(buf, sizeof buf, "%ld.%06ldr/%ld.%06ldc", + ptimer->ti_wall_sec, ptimer->ti_wall_usec, + ptimer->ti_cpu_sec, ptimer->ti_cpu_usec); + return buf; +} +#endif /* _FFR_TIMERS */ diff --git a/gnu/usr.sbin/sendmail/sendmail/timers.h b/gnu/usr.sbin/sendmail/sendmail/timers.h new file mode 100644 index 00000000000..16f948814a0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/timers.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Sendmail: timers.h,v 8.4 1999/11/04 19:31:26 ca Exp $ + * + * Contributed by Exactis.com, Inc. + * + */ + +#ifndef TIMERS_H +#define TIMERS_H 1 + +#define MAXTIMERSTACK 20 /* maximum timer depth */ + +#define TIMER struct _timer + +TIMER +{ + long ti_wall_sec; /* wall clock seconds */ + long ti_wall_usec; /* ... microseconds */ + long ti_cpu_sec; /* cpu time seconds */ + long ti_cpu_usec; /* ... microseconds */ +}; + +extern void pushtimer __P((TIMER *)); +extern void poptimer __P((TIMER *)); +extern char *strtimer __P((TIMER *)); +#endif /* TIMERS_H */ diff --git a/gnu/usr.sbin/sendmail/sendmail/trace.c b/gnu/usr.sbin/sendmail/sendmail/trace.c new file mode 100644 index 00000000000..35bd549b302 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/trace.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: trace.c,v 8.20 1999/08/02 21:44:36 ca Exp $"; +#endif /* ! lint */ + +#include + +/* +** 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. +*/ + +static u_char *tTvect; +static 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 (isascii(*s) && isdigit(*s)) + i = i * 10 + (*s++ - '0'); + first = i; + + /* find last flag to set */ + if (*s == '-') + { + i = 0; + while (isascii(*++s) && isdigit(*s)) + i = i * 10 + (*s - '0'); + } + last = i; + + /* find the level to set it to */ + i = 1; + if (*s == '.') + { + i = 0; + while (isascii(*++s) && 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/gnu/usr.sbin/sendmail/sendmail/udb.c b/gnu/usr.sbin/sendmail/sendmail/udb.c new file mode 100644 index 00000000000..705f0f7e8c3 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/udb.c @@ -0,0 +1,1310 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# if USERDB +static char id[] = "@(#)$Sendmail: udb.c,v 8.111 1999/11/16 02:04:04 gshapiro Exp $ (with USERDB)"; +# else /* USERDB */ +static char id[] = "@(#)$Sendmail: udb.c,v 8.111 1999/11/16 02:04:04 gshapiro Exp $ (without USERDB)"; +# endif /* USERDB */ +#endif /* ! lint */ + +#if USERDB + +# ifdef NEWDB +# include +# ifndef DB_VERSION_MAJOR +# define DB_VERSION_MAJOR 1 +# endif /* ! DB_VERSION_MAJOR */ +# else /* NEWDB */ +# define DBT struct _data_base_thang_ +DBT +{ + void *data; /* pointer to data */ + size_t size; /* length of data */ +}; +# endif /* NEWDB */ + +/* +** 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 */ + pid_t udb_pid; /* PID of process which opened db */ + char *udb_default; /* default host for outgoing mail */ + union + { +# if NETINET || NETINET6 + /* type UE_REMOTE -- do remote call for lookup */ + struct + { + SOCKADDR _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 +# endif /* NETINET || NETINET6 */ + + /* 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 /* NEWDB */ + } 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 udb_option +{ + char *udbo_name; + char *udbo_val; +}; + +# ifdef HESIOD +static int hes_udb_get __P((DBT *, DBT *)); +# endif /* HESIOD */ +static char *udbmatch __P((char *, char *)); +static int _udbx_init __P((ENVELOPE *)); +static int _udb_parsespec __P((char *, struct udb_option [], int)); + +/* +** 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. +*/ + +static struct udbent UdbEnts[MAXUDBENT + 1]; +static 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 *user; + char keybuf[MAXKEY]; + + memset(&key, '\0', sizeof key); + memset(&info, '\0', sizeof info); + + if (tTd(28, 1)) + dprintf("udbexpand(%s)\n", a->q_paddr); + + /* make certain we are supposed to send to this address */ + if (!QS_IS_SENDABLE(a->q_state)) + return EX_OK; + e->e_to = a->q_paddr; + + /* on first call, locate the database */ + if (!UdbInitialized) + { + if (_udbx_init(e) == EX_TEMPFAIL) + return EX_TEMPFAIL; + } + + /* short circuit the process if no chance of a match */ + if (UdbSpec == NULL || UdbSpec[0] == '\0') + return EX_OK; + + /* extract user to do userdb matching on */ + user = a->q_user; + + /* short circuit name begins with '\\' since it can't possibly match */ + /* (might want to treat this as unquoted instead) */ + if (user[0] == '\\') + return EX_OK; + + /* if name is too long, assume it won't match */ + if (strlen(user) > (SIZE_T) sizeof keybuf - 12) + return EX_OK; + + /* if name begins with a colon, it indicates our metadata */ + if (user[0] == ':') + return EX_OK; + + /* build actual database key */ + (void) strlcpy(keybuf, user, sizeof keybuf); + (void) strlcat(keybuf, ":maildrop", sizeof keybuf); + keylen = strlen(keybuf); + + breakout = FALSE; + for (up = UdbEnts; !breakout; up++) + { + int usersize; + int userleft; + char userbuf[MEMCHUNKSIZE]; +# if defined(HESIOD) && defined(HES_GETMAILHOST) + char pobuf[MAXNAME]; +# endif /* defined(HESIOD) && defined(HES_GETMAILHOST) */ +# if defined(NEWDB) && DB_VERSION_MAJOR > 1 + DBC *dbc = NULL; +# endif /* defined(NEWDB) && DB_VERSION_MAJOR > 1 */ + + user = userbuf; + userbuf[0] = '\0'; + usersize = sizeof userbuf; + userleft = sizeof userbuf - 1; + + /* + ** 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)) + dprintf("udbexpand: trying %s (%d) via db\n", + keybuf, keylen); +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR); +# else /* DB_VERSION_MAJOR < 2 */ + i = 0; + if (dbc == NULL && +# if DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 + (errno = (*up->udb_dbp->cursor)(up->udb_dbp, + NULL, &dbc, 0)) != 0) +# else /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */ + (errno = (*up->udb_dbp->cursor)(up->udb_dbp, + NULL, &dbc)) != 0) +# endif /* DB_VERSION_MAJOR > 2 || DB_VERSION_MINOR >= 6 */ + i = -1; + if (i != 0 || dbc == NULL || + (errno = dbc->c_get(dbc, &key, + &info, DB_SET)) != 0) + i = 1; +# endif /* DB_VERSION_MAJOR < 2 */ + if (i > 0 || info.size <= 0) + { + if (tTd(28, 2)) + dprintf("udbexpand: no match on %s (%d)\n", + keybuf, keylen); +# if DB_VERSION_MAJOR > 1 + if (dbc != NULL) + { + (void) dbc->c_close(dbc); + dbc = NULL; + } +# endif /* DB_VERSION_MAJOR > 1 */ + break; + } + if (tTd(28, 80)) + dprintf("udbexpand: match %.*s: %.*s\n", + (int) key.size, (char *) key.data, + (int) info.size, (char *) info.data); + + a->q_flags &= ~QSELFREF; + while (i == 0 && key.size == keylen && + memcmp(key.data, keybuf, keylen) == 0) + { + char *p; + + if (bitset(EF_VRFYONLY, e->e_flags)) + { + a->q_state = QS_VERIFIED; +# if DB_VERSION_MAJOR > 1 + if (dbc != NULL) + { + (void) dbc->c_close(dbc); + dbc = NULL; + } +# endif /* DB_VERSION_MAJOR > 1 */ + return EX_OK; + } + + breakout = TRUE; + if (info.size >= userleft - 1) + { + char *nuser; + int size = MEMCHUNKSIZE; + + if (info.size > MEMCHUNKSIZE) + size = info.size; + nuser = xalloc(usersize + size); + + memmove(nuser, user, usersize); + if (user != userbuf) + free(user); + user = nuser; + usersize += size; + userleft += size; + } + p = &user[strlen(user)]; + if (p != user) + { + *p++ = ','; + userleft--; + } + memmove(p, info.data, info.size); + p[info.size] = '\0'; + userleft -= info.size; + + /* get the next record */ +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT); +# else /* DB_VERSION_MAJOR < 2 */ + i = 0; + if ((errno = dbc->c_get(dbc, &key, + &info, DB_NEXT)) != 0) + i = 1; +# endif /* DB_VERSION_MAJOR < 2 */ + } + +# if DB_VERSION_MAJOR > 1 + if (dbc != NULL) + { + (void) dbc->c_close(dbc); + dbc = NULL; + } +# endif /* DB_VERSION_MAJOR > 1 */ + + /* if nothing ever matched, try next database */ + if (!breakout) + break; + + message("expanded to %s", user); + if (LogLevel > 10) + sm_syslog(LOG_INFO, e->e_id, + "expand %.100s => %s", + e->e_to, + shortenstring(user, MAXSHORTSTR)); + naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); + if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) + { + if (tTd(28, 5)) + { + dprintf("udbexpand: QS_EXPANDED "); + printaddr(a, FALSE); + } + a->q_state = QS_EXPANDED; + } + if (i < 0) + { + syserr("udbexpand: db-get %.*s stat %d", + (int) key.size, (char *) key.data, i); + return EX_TEMPFAIL; + } + + /* + ** If this address has a -request address, reflect + ** it into the envelope. + */ + + memset(&key, '\0', sizeof key); + memset(&info, '\0', sizeof info); + (void) strlcpy(keybuf, a->q_user, sizeof keybuf); + (void) strlcat(keybuf, ":mailsender", sizeof keybuf); + keylen = strlen(keybuf); + key.data = keybuf; + key.size = keylen; + +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); +# else /* DB_VERSION_MAJOR < 2 */ + i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL, + &key, &info, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + if (i != 0 || info.size <= 0) + break; + a->q_owner = xalloc(info.size + 1); + memmove(a->q_owner, info.data, 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 /* NEWDB */ + +# ifdef HESIOD + case UDB_HESIOD: + key.data = keybuf; + key.size = keylen; + if (tTd(28, 80)) + dprintf("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", + (int) key.size, (char *) key.data, i); + return EX_TEMPFAIL; + } + else if (i > 0 || info.size <= 0) + { +# if HES_GETMAILHOST + struct hes_postoffice *hp; +# endif /* HES_GETMAILHOST */ + + if (tTd(28, 2)) + dprintf("udbexpand: no match on %s (%d)\n", + (char *) keybuf, (int) keylen); +# if HES_GETMAILHOST + if (tTd(28, 8)) + dprintf(" ... 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)) + dprintf("hes_getmailhost(%s): %d\n", + a->q_user, hes_error()); + break; + } + if (strlen(hp->po_name) + strlen(hp->po_host) > + sizeof pobuf - 2) + { + if (tTd(28, 2)) + dprintf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n", + a->q_user, + hp->po_name, + hp->po_host); + break; + } + info.data = pobuf; + snprintf(pobuf, sizeof pobuf, "%s@%s", + hp->po_name, hp->po_host); + info.size = strlen(info.data); +# else /* HES_GETMAILHOST */ + break; +# endif /* HES_GETMAILHOST */ + } + if (tTd(28, 80)) + dprintf("udbexpand: match %.*s: %.*s\n", + (int) key.size, (char *) key.data, + (int) info.size, (char *) info.data); + a->q_flags &= ~QSELFREF; + + if (bitset(EF_VRFYONLY, e->e_flags)) + { + a->q_state = QS_VERIFIED; + return EX_OK; + } + + breakout = TRUE; + if (info.size >= usersize) + user = xalloc(info.size + 1); + memmove(user, info.data, info.size); + user[info.size] = '\0'; + + message("hesioded to %s", user); + if (LogLevel > 10) + sm_syslog(LOG_INFO, e->e_id, + "hesiod %.100s => %s", + e->e_to, + shortenstring(user, MAXSHORTSTR)); + naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); + + if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) + { + if (tTd(28, 5)) + { + dprintf("udbexpand: QS_EXPANDED "); + printaddr(a, FALSE); + } + a->q_state = QS_EXPANDED; + } + + /* + ** If this address has a -request address, reflect + ** it into the envelope. + */ + + (void) strlcpy(keybuf, a->q_user, sizeof keybuf); + (void) strlcat(keybuf, ":mailsender", sizeof keybuf); + 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); + memmove(a->q_owner, info.data, info.size); + a->q_owner[info.size] = '\0'; + break; +# endif /* HESIOD */ + + case UDB_REMOTE: + /* not yet implemented */ + break; + + case UDB_FORWARD: + if (bitset(EF_VRFYONLY, e->e_flags)) + { + a->q_state = QS_VERIFIED; + return EX_OK; + } + i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1; + if (i >= usersize) + { + usersize = i + 1; + user = xalloc(usersize); + } + (void) snprintf(user, usersize, "%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)) + { + dprintf("udbexpand: QS_EXPANDED "); + printaddr(a, FALSE); + } + a->q_state = QS_EXPANDED; + } + breakout = TRUE; + break; + + case UDB_EOLIST: + breakout = TRUE; + break; + + default: + /* unknown entry type */ + break; + } + if (user != userbuf) + free(user); + } + 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; +{ + return udbmatch(sender, "mailname"); +} + /* +** UDBMATCH -- match user in field, return result of lookup. +** +** Parameters: +** user -- the name of the user. +** field -- the field to lookup. +** +** Returns: +** The external name for this sender, if derivable from the +** database. +** NULL -- if nothing is changed from the database. +** +** Side Effects: +** none. +*/ + +static 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)) + dprintf("udbmatch(%s, %s)\n", user, field); + + if (!UdbInitialized) + { + if (_udbx_init(CurEnv) == 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 */ + i = strlen(field); + if (i < sizeof "maildrop") + i = sizeof "maildrop"; + if ((strlen(user) + i) > sizeof keybuf - 4) + return NULL; + + /* names beginning with colons indicate metadata */ + if (user[0] == ':') + return NULL; + + /* build database key */ + (void) snprintf(keybuf, sizeof keybuf, "%s:%s", user, 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: + memset(&key, '\0', sizeof key); + memset(&info, '\0', sizeof info); + key.data = keybuf; + key.size = keylen; +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); +# else /* DB_VERSION_MAJOR < 2 */ + i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL, + &key, &info, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + if (i != 0 || info.size <= 0) + { + if (tTd(28, 2)) + dprintf("udbmatch: no match on %s (%d) via db\n", + keybuf, keylen); + continue; + } + + p = xalloc(info.size + 1); + memmove(p, info.data, info.size); + p[info.size] = '\0'; + if (tTd(28, 1)) + dprintf("udbmatch ==> %s\n", p); + return p; +# endif /* NEWDB */ + +# 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)) + dprintf("udbmatch: no match on %s (%d) via hesiod\n", + keybuf, keylen); + continue; + } + + p = xalloc(info.size + 1); + memmove(p, info.data, info.size); + p[info.size] = '\0'; + if (tTd(28, 1)) + dprintf("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) strlcpy(keybuf, user, sizeof keybuf); + (void) strlcat(keybuf, ":maildrop", sizeof keybuf); + 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) + { + memset(&key, '\0', sizeof key); + memset(&info, '\0', sizeof info); + key.data = ":default:mailname"; + key.size = strlen(key.data); +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->get)(up->udb_dbp, + &key, &info, 0); +# else /* DB_VERSION_MAJOR < 2 */ + i = errno = (*up->udb_dbp->get)(up->udb_dbp, + NULL, &key, + &info, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + if (i != 0 || info.size <= 0) + { + /* no default case */ + up->udb_default = ""; + continue; + } + + /* save the default case */ + up->udb_default = xalloc(info.size + 1); + memmove(up->udb_default, info.data, info.size); + up->udb_default[info.size] = '\0'; + } + else if (up->udb_default[0] == '\0') + continue; + + /* we have a default case -- verify user:maildrop */ + memset(&key, '\0', sizeof key); + memset(&info, '\0', sizeof info); + key.data = keybuf; + key.size = keylen; +# if DB_VERSION_MAJOR < 2 + i = (*up->udb_dbp->get)(up->udb_dbp, &key, &info, 0); +# else /* DB_VERSION_MAJOR < 2 */ + i = errno = (*up->udb_dbp->get)(up->udb_dbp, NULL, + &key, &info, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + if (i != 0 || info.size <= 0) + { + /* nope -- no aliasing for this user */ + continue; + } + + /* they exist -- build the actual address */ + i = strlen(user) + strlen(up->udb_default) + 2; + p = xalloc(i); + (void) snprintf(p, i, "%s@%s", user, up->udb_default); + if (tTd(28, 1)) + dprintf("udbmatch ==> %s\n", p); + return p; +# endif /* NEWDB */ + +# 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); + memmove(up->udb_default, info.data, 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 */ + i = strlen(user) + strlen(up->udb_default) + 2; + p = xalloc(i); + (void) snprintf(p, i, "%s@%s", user, up->udb_default); + if (tTd(28, 1)) + dprintf("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. +*/ + +/* ARGSUSED3 */ +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)) + dprintf("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; + memmove(keybuf, name, 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: +** e -- the current envelope. +** +** 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 + +static int +_udbx_init(e) + ENVELOPE *e; +{ + int ents = 0; + register char *p; + register struct udbent *up; + + if (UdbInitialized) + return EX_OK; + +# ifdef UDB_DEFAULT_SPEC + if (UdbSpec == NULL) + UdbSpec = UDB_DEFAULT_SPEC; +# endif /* UDB_DEFAULT_SPEC */ + + p = UdbSpec; + up = UdbEnts; + while (p != NULL) + { + char *spec; + int l; + struct udb_option opts[MAXUDBOPTS + 1]; + + while (*p == ' ' || *p == '\t' || *p == ',') + p++; + if (*p == '\0') + break; + spec = p; + p = strchr(p, ','); + if (p != NULL) + *p++ = '\0'; + + if (ents >= MAXUDBENT) + { + syserr("Maximum number of UDB entries exceeded"); + break; + } + + /* extract options */ + (void) _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 -- 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) + { + case '@': /* forward to remote host */ + up->udb_type = UDB_FORWARD; + up->udb_pid = getpid(); + up->udb_fwdhost = spec + 1; + ents++; + up++; + break; + +# ifdef HESIOD + case 'h': /* use hesiod */ + case 'H': + if (strcasecmp(spec, "hesiod") != 0) + goto badspec; + up->udb_type = UDB_HESIOD; + up->udb_pid = getpid(); + ents++; + up++; + break; +# endif /* HESIOD */ + +# ifdef NEWDB + case '/': /* look up remote name */ + l = strlen(spec); + if (l > 3 && strcmp(&spec[l - 3], ".db") == 0) + { + up->udb_dbname = spec; + } + else + { + up->udb_dbname = xalloc(l + 4); + (void) strlcpy(up->udb_dbname, spec, l + 4); + (void) strlcat(up->udb_dbname, ".db", l + 4); + } + errno = 0; +# if DB_VERSION_MAJOR < 2 + up->udb_dbp = dbopen(up->udb_dbname, O_RDONLY, + 0644, DB_BTREE, NULL); +# else /* DB_VERSION_MAJOR < 2 */ + { + int flags = DB_RDONLY; +# if DB_VERSION_MAJOR > 2 + int ret; +# endif /* DB_VERSION_MAJOR > 2 */ + +# if !HASFLOCK && defined(DB_FCNTL_LOCKING) + flags |= DB_FCNTL_LOCKING; +# endif /* !HASFLOCK && defined(DB_FCNTL_LOCKING) */ + + up->udb_dbp = NULL; + +# if DB_VERSION_MAJOR > 2 + ret = db_create(&up->udb_dbp, NULL, 0); + if (ret != 0) + { + (void) up->udb_dbp->close(up->udb_dbp, + 0); + up->udb_dbp = NULL; + } + else + { + ret = up->udb_dbp->open(up->udb_dbp, + up->udb_dbname, + NULL, + DB_BTREE, + flags, + 0644); + if (ret != 0) + { + (void) up->udb_dbp->close(up->udb_dbp, 0); + up->udb_dbp = NULL; + } + } + errno = ret; +# else /* DB_VERSION_MAJOR > 2 */ + errno = db_open(up->udb_dbname, DB_BTREE, + flags, 0644, NULL, + NULL, &up->udb_dbp); +# endif /* DB_VERSION_MAJOR > 2 */ + } +# endif /* DB_VERSION_MAJOR < 2 */ + if (up->udb_dbp == NULL) + { + if (tTd(28, 1)) + { + int save_errno = errno; + +# if DB_VERSION_MAJOR < 2 + dprintf("dbopen(%s): %s\n", +# else /* DB_VERSION_MAJOR < 2 */ + dprintf("db_open(%s): %s\n", +# endif /* DB_VERSION_MAJOR < 2 */ + up->udb_dbname, + errstring(errno)); + errno = save_errno; + } + if (errno != ENOENT && errno != EACCES) + { + if (LogLevel > 2) + sm_syslog(LOG_ERR, e->e_id, +# if DB_VERSION_MAJOR < 2 + "dbopen(%s): %s", +# else /* DB_VERSION_MAJOR < 2 */ + "db_open(%s): %s", +# endif /* DB_VERSION_MAJOR < 2 */ + up->udb_dbname, + errstring(errno)); + up->udb_type = UDB_EOLIST; + if (up->udb_dbname != spec) + free(up->udb_dbname); + goto tempfail; + } + if (up->udb_dbname != spec) + free(up->udb_dbname); + break; + } + if (tTd(28, 1)) + { +# if DB_VERSION_MAJOR < 2 + dprintf("_udbx_init: dbopen(%s)\n", +# else /* DB_VERSION_MAJOR < 2 */ + dprintf("_udbx_init: db_open(%s)\n", +# endif /* DB_VERSION_MAJOR < 2 */ + up->udb_dbname); + } + up->udb_type = UDB_DBFETCH; + up->udb_pid = getpid(); + ents++; + up++; + break; +# endif /* NEWDB */ + + default: +# ifdef HESIOD +badspec: +# endif /* HESIOD */ + 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) + { +# if DAEMON + case UDB_REMOTE: + dprintf("REMOTE: addr %s, timeo %d\n", + anynet_ntoa((SOCKADDR *) &up->udb_addr), + up->udb_timeout); + break; +# endif /* DAEMON */ + + case UDB_DBFETCH: +# ifdef NEWDB + dprintf("FETCH: file %s\n", + up->udb_dbname); +# else /* NEWDB */ + dprintf("FETCH\n"); +# endif /* NEWDB */ + break; + + case UDB_FORWARD: + dprintf("FORWARD: host %s\n", + up->udb_fwdhost); + break; + + case UDB_HESIOD: + dprintf("HESIOD\n"); + break; + + default: + dprintf("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) + { +# if DB_VERSION_MAJOR < 2 + (*up->udb_dbp->close)(up->udb_dbp); +# else /* DB_VERSION_MAJOR < 2 */ + errno = (*up->udb_dbp->close)(up->udb_dbp, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + if (tTd(28, 1)) + dprintf("_udbx_init: db->close(%s)\n", + up->udb_dbname); + } + } +# endif /* NEWDB */ + return EX_TEMPFAIL; +} + +static int +_udb_parsespec(udbspec, opt, maxopts) + char *udbspec; + struct udb_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].udbo_name = spec; + opt[optnum].udbo_val = NULL; + p = strchr(spec, '='); + if (p != NULL) + opt[optnum].udbo_val = ++p; + } + return optnum; +} + /* +** _UDBX_CLOSE -- close all file based UDB entries. +** +** Parameters: +** none +** +** Returns: +** none +*/ +void +_udbx_close() +{ + pid_t pid; + struct udbent *up; + + if (!UdbInitialized) + return; + + pid = getpid(); + + for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) + { + if (up->udb_pid != pid) + continue; + +# ifdef NEWDB + if (up->udb_type == UDB_DBFETCH) + { +# if DB_VERSION_MAJOR < 2 + (*up->udb_dbp->close)(up->udb_dbp); +# else /* DB_VERSION_MAJOR < 2 */ + errno = (*up->udb_dbp->close)(up->udb_dbp, 0); +# endif /* DB_VERSION_MAJOR < 2 */ + } + if (tTd(28, 1)) + dprintf("_udbx_init: db->close(%s)\n", + up->udb_dbname); +# endif /* NEWDB */ + } +} + +# ifdef HESIOD + +static int +hes_udb_get(key, info) + DBT *key; + DBT *info; +{ + char *name, *type; + char **hp; + char kbuf[MAXKEY + 1]; + + if (strlcpy(kbuf, key->data, sizeof kbuf) >= (SIZE_T) sizeof kbuf) + return 0; + name = kbuf; + type = strrchr(name, ':'); + if (type == NULL) + return 1; + *type++ = '\0'; + if (strchr(name, '@') != NULL) + return 1; + + if (tTd(28, 1)) + dprintf("hes_udb_get(%s, %s)\n", name, type); + + /* make the hesiod query */ +# ifdef HESIOD_INIT + if (HesiodContext == NULL && hesiod_init(&HesiodContext) != 0) + return -1; + hp = hesiod_resolve(HesiodContext, name, type); +# else /* HESIOD_INIT */ + hp = hes_resolve(name, type); +# endif /* HESIOD_INIT */ + *--type = ':'; +# ifdef HESIOD_INIT + if (hp == NULL) + return 1; + if (*hp == NULL) + { + hesiod_free_list(HesiodContext, hp); + if (errno == ECONNREFUSED || errno == EMSGSIZE) + return -1; + return 1; + } +# else /* HESIOD_INIT */ + if (hp == NULL || hp[0] == NULL) + { + /* network problem or timeout */ + if (hes_error() == HES_ER_NET) + return -1; + + return 1; + } +# endif /* HESIOD_INIT */ + 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)) + dprintf("hes_udb_get => %s\n", *hp); + + return 0; +} +# endif /* HESIOD */ + +#else /* USERDB */ + +int +udbexpand(a, sendq, aliaslevel, e) + ADDRESS *a; + ADDRESS **sendq; + int aliaslevel; + ENVELOPE *e; +{ + return EX_OK; +} + +#endif /* USERDB */ diff --git a/gnu/usr.sbin/sendmail/sendmail/usersmtp.c b/gnu/usr.sbin/sendmail/sendmail/usersmtp.c new file mode 100644 index 00000000000..be15ea084a2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/usersmtp.c @@ -0,0 +1,2267 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +#ifndef lint +# if SMTP +static char id[] = "@(#)$Sendmail: usersmtp.c,v 8.240 2000/02/23 06:56:16 gshapiro Exp $ (with SMTP)"; +# else /* SMTP */ +static char id[] = "@(#)$Sendmail: usersmtp.c,v 8.240 2000/02/23 06:56:16 gshapiro Exp $ (without SMTP)"; +# endif /* SMTP */ +#endif /* ! lint */ + +#include + +#if SMTP + +static void datatimeout __P((void)); +static void esmtp_check __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); +static void helo_options __P((char *, bool, MAILER *, MCI *, ENVELOPE *)); + +/* +** 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" */ + +#define ENHSCN(e, d) (e) == NULL ? (d) : newstr(e) + +static char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */ +static char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */ +static bool SmtpNeedIntro; /* need "while talking" in transcript */ + /* +** SMTPINIT -- initialize SMTP. +** +** Opens the connection and sends the initial protocol. +** +** Parameters: +** m -- mailer to create connection to. +** mci -- the mailer connection info. +** e -- the envelope. +** onlyhelo -- send only helo command? +** +** Returns: +** none. +** +** Side Effects: +** creates connection and sends initial protocol. +*/ + +void +smtpinit(m, mci, e, onlyhelo) + MAILER *m; + register MCI *mci; + ENVELOPE *e; + bool onlyhelo; +{ + register int r; + register char *p; + register char *hn; + char *enhsc; + + enhsc = NULL; + if (tTd(18, 1)) + { + dprintf("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); + /* FALLTHROUGH */ + + case MCIS_OPEN: + if (!onlyhelo) + return; + break; + + case MCIS_ERROR: + case MCIS_QUITING: + case MCIS_SSD: + /* shouldn't happen */ + smtpquit(m, mci, e); + /* FALLTHROUGH */ + + case MCIS_CLOSED: + syserr("451 4.4.0 smtpinit: state CLOSED"); + return; + + case MCIS_OPENING: + break; + } + if (onlyhelo) + goto helo; + + 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"; + sm_setproctitle(TRUE, e, "%s %s: %s", + qid_printname(e), CurHostName, mci->mci_phase); + r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check, NULL); + if (r < 0) + goto tempfail1; + if (REPLYTYPE(r) == 4) + goto tempfail2; + if (REPLYTYPE(r) != 2) + goto unavailable; + + /* + ** Send the HELO command. + ** My mother taught me to always introduce myself. + */ + +helo: + if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags)) + mci->mci_flags |= MCIF_ESMTP; + hn = mci->mci_heloname ? mci->mci_heloname : MyHostName; + +tryhelo: + if (bitnset(M_LMTP, m->m_flags)) + { + smtpmessage("LHLO %s", m, mci, hn); + SmtpPhase = mci->mci_phase = "client LHLO"; + } + else if (bitset(MCIF_ESMTP, mci->mci_flags)) + { + smtpmessage("EHLO %s", m, mci, hn); + SmtpPhase = mci->mci_phase = "client EHLO"; + } + else + { + smtpmessage("HELO %s", m, mci, hn); + SmtpPhase = mci->mci_phase = "client HELO"; + } + sm_setproctitle(TRUE, e, "%s %s: %s", qid_printname(e), + CurHostName, mci->mci_phase); + r = reply(m, mci, e, TimeOuts.to_helo, helo_options, NULL); + if (r < 0) + goto tempfail1; + else if (REPLYTYPE(r) == 5) + { + if (bitset(MCIF_ESMTP, mci->mci_flags) && + !bitnset(M_LMTP, m->m_flags)) + { + /* try old SMTP instead */ + mci->mci_flags &= ~MCIF_ESMTP; + goto tryhelo; + } + goto unavailable; + } + else if (REPLYTYPE(r) != 2) + goto tempfail2; + + /* + ** 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) && + !bitnset(M_LMTP, m->m_flags) && + strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) + { + syserr("553 5.3.5 %s config error: mail loops back to me (MX problem?)", + CurHostName); + mci_setstat(mci, EX_CONFIG, "5.3.5", "system config error"); + 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, &enhsc); + if (r < 0) + goto tempfail1; + } + + if (mci->mci_state != MCIS_CLOSED) + { + mci->mci_state = MCIS_OPEN; + return; + } + + /* got a 421 error code during startup */ + + tempfail1: + if (mci->mci_errno == 0) + mci->mci_errno = errno; + mci_setstat(mci, EX_TEMPFAIL, ENHSCN(enhsc, "4.4.2"), NULL); + if (mci->mci_state != MCIS_CLOSED) + smtpquit(m, mci, e); + return; + + tempfail2: + if (mci->mci_errno == 0) + mci->mci_errno = errno; + /* XXX should use code from other end iff ENHANCEDSTATUSCODES */ + mci_setstat(mci, EX_TEMPFAIL, ENHSCN(enhsc, "4.5.0"), + SmtpReplyBuffer); + if (mci->mci_state != MCIS_CLOSED) + smtpquit(m, mci, e); + return; + + unavailable: + mci->mci_errno = errno; + mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer); + 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. +*/ + +static 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. +*/ + +static 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 = strpbrk(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; + else if (strcasecmp(line, "enhancedstatuscodes") == 0) + mci->mci_flags |= MCIF_ENHSTAT; +# if SASL + else if (strcasecmp(line, "auth") == 0) + { + if (p == NULL || *p == '\0') + { + /* no parameter? */ + mci->mci_saslcap = NULL; + } + else + { + int l; + + if (mci->mci_saslcap != NULL) + free(mci->mci_saslcap); + l = strlen(p) + 1; + mci->mci_saslcap = (char *)malloc(l); + + /* XXX this may be leaked */ + if (mci->mci_saslcap != NULL) + { + (void) strlcpy(mci->mci_saslcap, p, l); + mci->mci_flags |= MCIF_AUTH; + } + } + } +# endif /* SASL */ +} +# if SASL + + /* +** GETSASLDATA -- process the challenges from the SASL protocol +** +** This gets the relevant sasl response data out of the reply +** from the server +** +** 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 +getsasldata(line, firstline, m, mci, e) + char *line; + bool firstline; + MAILER *m; + register MCI *mci; + ENVELOPE *e; +{ + int len; + char *out; + int result; + + /* if not a continue we don't care about it */ + if ((strlen(line) <= 4) || + (line[0] != '3') || + (line[1] != '3') || + (line[2] != '4')) + { + mci->mci_sasl_string = NULL; + return; + } + + /* forget about "334 " */ + line += 4; + len = strlen(line); + + out = xalloc(len + 1); + result = sasl_decode64(line, len, out, (u_int *)&len); + if (result != SASL_OK) + { + len = 0; + *out = '\0'; + } + if (mci->mci_sasl_string != NULL) + { + if (mci->mci_sasl_string_len <= len) + { + free(mci->mci_sasl_string); + mci->mci_sasl_string = xalloc(len + 1); + } + } + else + mci->mci_sasl_string = xalloc(len + 1); + /* XXX this is probably leaked */ + memcpy(mci->mci_sasl_string, out, len); + mci->mci_sasl_string[len] = '\0'; + mci->mci_sasl_string_len = len; + free(out); + return; +} + + /* +** READAUTH -- read auth value from a file +** +** Parameters: +** l -- line to define. +** filename -- name of file to read. +** safe -- if set, this is a safe read. +** +** Returns: +** line from file +** +*/ + +/* lines in authinfo file */ +# define SASL_USER 1 +# define SASL_AUTHID 2 +# define SASL_PASSWORD 3 +# define SASL_DEFREALM 4 +# define SASL_MECH 5 + +static char *sasl_info_name[] = { + "", + "user id", + "authorization id", + "password", + "realm", + "mechanism" +}; + +static char * +readauth(l, filename, safe) + int l; + char *filename; + bool safe; +{ + FILE *f; + long sff; + pid_t pid; + int lc; + static char buf[MAXLINE]; + + if (filename == NULL || filename[0] == '\0') + return ""; +#if !_FFR_ALLOW_SASLINFO + /* + ** make sure we don't use a program that is not + ** accesible to the user who specified a different authinfo file. + ** However, currently we don't pass this info (authinfo file + ** specified by user) around, so we just turn off program access. + */ + if (filename[0] == '|') + { + auto int fd; + int i; + char *p; + 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 +#endif /* !_FFR_ALLOW_SASLINFO */ + { + pid = -1; + sff = SFF_REGONLY | SFF_SAFEDIRPATH | SFF_NOWLINK + | SFF_NOGWFILES | SFF_NOWWFILES | SFF_NORFILES; + if (DontLockReadFiles) + sff |= SFF_NOLOCK; +#if _FFR_ALLOW_SASLINFO + /* + ** XXX: make sure we don't read or open files that are not + ** accesible to the user who specified a different authinfo + ** file. + */ + sff |= SFF_MUSTOWN; +#else /* _FFR_ALLOW_SASLINFO */ + if (safe) + sff |= SFF_OPENASROOT; +#endif /* _FFR_ALLOW_SASLINFO */ + + f = safefopen(filename, O_RDONLY, 0, sff); + } + if (f == NULL) + { + syserr("readauth: cannot open %s", filename); + return ""; + } + + lc = 0; + while (lc < l && fgets(buf, sizeof buf, f) != NULL) + { + if (buf[0] != '#') + lc++; + } + + (void) fclose(f); + if (pid > 0) + (void) waitfor(pid); + if (lc < l) + { + if (LogLevel >= 9) + sm_syslog(LOG_WARNING, NOQID, "SASL: error: can't read %s from %s", + sasl_info_name[l], filename); + return ""; + } + lc = strlen(buf) - 1; + if (lc >= 0) + buf[lc] = '\0'; + if (tTd(95, 6)) + dprintf("readauth(%s, %d) = '%s'\n", filename, l, buf); + return buf; +} + +# ifndef __attribute__ +# define __attribute__(x) +# endif /* ! __attribute__ */ + +static int getsimple __P((void *, int, const char **, unsigned *)); +static int getsecret __P((sasl_conn_t *, void *, int, sasl_secret_t **)); +static int saslgetrealm __P((void *, int, const char **, const char **)); + +static sasl_callback_t callbacks[] = { + { SASL_CB_GETREALM, &saslgetrealm, NULL }, +# define CB_GETREALM_IDX 0 + { SASL_CB_PASS, &getsecret, NULL }, +# define CB_PASS_IDX 1 + { SASL_CB_USER, &getsimple, NULL }, +# define CB_USER_IDX 2 + { SASL_CB_AUTHNAME, &getsimple, NULL }, +# define CB_AUTHNAME_IDX 3 + { SASL_CB_VERIFYFILE, &safesaslfile, NULL }, + { SASL_CB_LIST_END, NULL, NULL } +}; + + /* +** GETSIMPLE -- callback to get userid or authid +** +** Parameters: +** context -- unused +** id -- what to do +** result -- (pointer to) result +** len -- (pointer to) length of result +** +** Returns: +** OK/failure values +*/ + +static int +getsimple(context, id, result, len) + void *context __attribute__((unused)); + int id; + const char **result; + unsigned *len; +{ + char *h; +# if SASL > 10509 + int addrealm; + static int addedrealm = FALSE; +# endif /* SASL > 10509 */ + static char *user = NULL; + static char *authid = NULL; + + if (result == NULL) + return SASL_BADPARAM; + + switch (id) { + case SASL_CB_USER: + if (user == NULL) + { + h = readauth(SASL_USER, SASLInfo, TRUE); + user = newstr(h); + } + *result = user; + if (tTd(95, 5)) + dprintf("AUTH username '%s'\n", *result); + if (len != NULL) + *len = user ? strlen(user) : 0; + break; + + case SASL_CB_AUTHNAME: +# if SASL > 10509 + /* XXX maybe other mechanisms too?! */ + addrealm = context != NULL && + strcasecmp(context, "CRAM-MD5") == 0; + if (addedrealm != addrealm && authid != NULL) + { + free(authid); + authid = NULL; + addedrealm = addrealm; + } +# endif /* SASL > 10509 */ + if (authid == NULL) + { + h = readauth(SASL_AUTHID, SASLInfo, TRUE); +# if SASL > 10509 + if (addrealm && strchr(h, '@') == NULL) + { + size_t l; + char *realm; + + realm = callbacks[CB_GETREALM_IDX].context; + l = strlen(h) + strlen(realm) + 2; + authid = xalloc(l); + snprintf(authid, l, "%s@%s", h, realm); + } + else +# endif /* SASL > 10509 */ + authid = newstr(h); + } + *result = authid; + if (tTd(95, 5)) + dprintf("AUTH authid '%s'\n", *result); + if (len != NULL) + *len = authid ? strlen(authid) : 0; + break; + + case SASL_CB_LANGUAGE: + *result = NULL; + if (len != NULL) + *len = 0; + break; + + default: + return SASL_BADPARAM; + } + return SASL_OK; +} + + /* +** GETSECRET -- callback to get password +** +** Parameters: +** conn -- connection information +** context -- unused +** id -- what to do +** psecret -- (pointer to) result +** +** Returns: +** OK/failure values +*/ + +static int +getsecret(conn, context, id, psecret) + sasl_conn_t *conn; + void *context __attribute__((unused)); + int id; + sasl_secret_t **psecret; +{ + char *h; + int len; + static char *authpass = NULL; + + if (conn == NULL || psecret == NULL || id != SASL_CB_PASS) + return SASL_BADPARAM; + + if (authpass == NULL) + { + h = readauth(SASL_PASSWORD, SASLInfo, TRUE); + authpass = newstr(h); + } + len = strlen(authpass); + *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len + 1); + if (*psecret == NULL) + return SASL_FAIL; + (void) strlcpy((*psecret)->data, authpass, len + 1); + (*psecret)->len = len; + return SASL_OK; +} + + /* +** SAFESASLFILE -- callback for sasl: is file safe? +** +** Parameters: +** context -- pointer to context between invocations (unused) +** file -- name of file to check +** type -- type of file to check +** +** Returns: +** SASL_OK: file can be used +** SASL_CONTINUE: don't use file +** SASL_FAIL: failure (not used here) +** +*/ +int +# if SASL > 10515 +safesaslfile(context, file, type) +# else /* SASL > 10515 */ +safesaslfile(context, file) +# endif /* SASL > 10515 */ + void *context; + char *file; +# if SASL > 10515 + int type; +# endif /* SASL > 10515 */ +{ + long sff; + int r; + char *p; + + if (file == NULL || *file == '\0') + return SASL_OK; + sff = SFF_SAFEDIRPATH|SFF_NOWLINK|SFF_NOGWFILES|SFF_NOWWFILES|SFF_ROOTOK; + if ((p = strrchr(file, '/')) == NULL) + p = file; + else + ++p; + +# if SASL <= 10515 + /* everything beside libs and .conf files must not be readable */ + r = strlen(p); + if ((r <= 3 || strncmp(p, "lib", 3) != 0) && + (r <= 5 || strncmp(p + r - 5, ".conf", 5) != 0) +# if _FFR_UNSAFE_SASL + && !bitnset(DBS_GROUPREADABLESASLFILE, DontBlameSendmail) +# endif /* _FFR_UNSAFE_SASL */ + ) + sff |= SFF_NORFILES; +# else /* SASL > 10515 */ + /* files containing passwords should be not readable */ + if (type == SASL_VRFY_PASSWD) + { +# if _FFR_UNSAFE_SASL + if (bitnset(DBS_GROUPREADABLESASLFILE, DontBlameSendmail)) + sff |= SFF_NOWRFILES; + else +# endif /* _FFR_UNSAFE_SASL */ + sff |= SFF_NORFILES; + } +# endif /* SASL <= 10515 */ + + if ((r = safefile(file, RunAsUid, RunAsGid, RunAsUserName, sff, + S_IRUSR, NULL)) == 0) + return SASL_OK; + if (LogLevel >= 11 || (r != ENOENT && LogLevel >= 9)) + sm_syslog(LOG_WARNING, NOQID, "error: safesasl(%s) failed: %s", + file, errstring(r)); + return SASL_CONTINUE; +} + +/* +** SASLGETREALM -- return the realm for SASL +** +** return the realm for the client +** +** Parameters: +** context -- context shared between invocations +** here: realm to return +** availrealms -- list of available realms +** {realm, realm, ...} +** result -- pointer to result +** +** Returns: +** failure/success +*/ +static int +saslgetrealm(context, id, availrealms, result) + void *context; + int id; + const char **availrealms; + const char **result; +{ + if (LogLevel > 12) + sm_syslog(LOG_INFO, NOQID, "saslgetrealm: realm %s available realms %s", + context, + availrealms == NULL ? "" : *availrealms); + if (context == NULL) + return SASL_FAIL; + + /* check whether context is in list? */ + if (availrealms != NULL) + { + if (iteminlist(context, (char *)(*availrealms + 1), " ,}") == + NULL) + { + if (LogLevel > 8) + sm_syslog(LOG_ERR, NOQID, + "saslgetrealm: realm %s not in list %s", + context, *availrealms); + return SASL_FAIL; + } + } + *result = (char *)context; + return SASL_OK; +} + /* +** ITEMINLIST -- does item appear in list? +** +** Check whether item appears in list (which must be separated by a +** character in delim) as a "word", i.e. it must appear at the begin +** of the list or after a space, and it must end with a space or the +** end of the list. +** +** Parameters: +** item -- item to search. +** list -- list of items. +** delim -- list of delimiters. +** +** Returns: +** pointer to occurrence (NULL if not found). +*/ + +char * +iteminlist(item, list, delim) + char *item; + char *list; + char *delim; +{ + char *s; + int len; + + if (list == NULL || *list == '\0') + return NULL; + if (item == NULL || *item == '\0') + return NULL; + s = list; + len = strlen(item); + while (s != NULL && *s != '\0') + { + if (strncasecmp(s, item, len) == 0 && + (s[len] == '\0' || strchr(delim, s[len]) != NULL)) + return s; + s = strpbrk(s, delim); + if (s != NULL) + while (*++s == ' ') + continue; + } + return NULL; +} + /* +** REMOVEMECH -- remove item [rem] from list [list] +** +** Parameters: +** rem -- item to remove +** list -- list of items +** +** Returns: +** pointer to new list (NULL in case of error). +*/ + +char * +removemech(rem, list) + char *rem; + char *list; +{ + char *ret; + char *needle; + int len; + + if (list == NULL) + return NULL; + if (rem == NULL || *rem == '\0') + { + /* take out what? */ + return NULL; + } + + /* find the item in the list */ + if ((needle = iteminlist(rem, list, " ")) == NULL) + { + /* not in there: return original */ + return list; + } + + /* length of string without rem */ + len = strlen(list) - strlen(rem); + if (len == 0) + { + ret = xalloc(1); /* XXX leaked */ + *ret = '\0'; + return ret; + } + ret = xalloc(len); /* XXX leaked */ + memset(ret, '\0', len); + + /* copy from start to removed item */ + memcpy(ret, list, needle - list); + + /* length of rest of string past removed item */ + len = strlen(needle) - strlen(rem) - 1; + if (len > 0) + { + /* not last item -- copy into string */ + memcpy(ret + (needle - list), + list + (needle - list) + strlen(rem) + 1, + len); + } + else + ret[(needle - list) - 1] = '\0'; + return ret; +} + /* +** INTERSECT -- create the intersection between two lists +** +** Parameters: +** s1, s2 -- lists of items (separated by single blanks). +** +** Returns: +** the intersection of both lists. +*/ + +char * +intersect(s1, s2) + char *s1, *s2; +{ + char *hr, *h1, *h, *res; + int l1, l2, rl; + + if (s1 == NULL || s2 == NULL) /* NULL string(s) -> NULL result */ + return NULL; + l1 = strlen(s1); + l2 = strlen(s2); + rl = min(l1, l2); + res = (char *)malloc(rl + 1); + if (res == NULL) + return NULL; + *res = '\0'; + if (rl == 0) /* at least one string empty? */ + return res; + hr = res; + h1 = s1; + h = s1; + + /* walk through s1 */ + while (h != NULL && *h1 != '\0') + { + /* is there something after the current word? */ + if ((h = strchr(h1, ' ')) != NULL) + *h = '\0'; + l1 = strlen(h1); + + /* does the current word appear in s2 ? */ + if (iteminlist(h1, s2, " ") != NULL) + { + /* add a blank if not first item */ + if (hr != res) + *hr++ = ' '; + + /* copy the item */ + memcpy(hr, h1, l1); + + /* advance pointer in result list */ + hr += l1; + *hr = '\0'; + } + if (h != NULL) + { + /* there are more items */ + *h = ' '; + h1 = h + 1; + } + } + return res; +} + /* +** ATTEMPTAUTH -- try to AUTHenticate using one mechanism +** +** Parameters: +** m -- the mailer. +** mci -- the mailer connection structure. +** e -- the envelope (including the sender to specify). +** mechused - filled in with mechanism used +** +** Returns: +** EX_OK/EX_TEMPFAIL +*/ + +int +attemptauth(m, mci, e, mechused) + MAILER *m; + MCI *mci; + ENVELOPE *e; + char **mechused; +{ + int saslresult, smtpresult; + sasl_external_properties_t ssf; + sasl_interact_t *client_interact = NULL; + char *out; + unsigned int outlen; + static char *mechusing; + sasl_security_properties_t ssp; + char in64[MAXOUTLEN]; +# if NETINET + extern SOCKADDR CurHostAddr; +# endif /* NETINET */ + + *mechused = NULL; + if (mci->mci_conn != NULL) + free(mci->mci_conn); + mci->mci_conn = NULL; + + /* make a new client sasl connection */ + saslresult = sasl_client_new(bitnset(M_LMTP, m->m_flags) ? "lmtp" + : "smtp", + CurHostName, NULL, 0, &mci->mci_conn); + + /* set properties */ + (void) memset(&ssp, '\0', sizeof ssp); + saslresult = sasl_setprop(mci->mci_conn, SASL_SEC_PROPS, &ssp); + if (saslresult != SASL_OK) + return EX_TEMPFAIL; + + /* external security strength factor; we have none so zero */ + ssf.ssf = 0; + ssf.auth_id = NULL; + saslresult = sasl_setprop(mci->mci_conn, SASL_SSF_EXTERNAL, &ssf); + if (saslresult != SASL_OK) + return EX_TEMPFAIL; + +# if NETINET + /* set local/remote ipv4 addresses */ + if (mci->mci_out != NULL && CurHostAddr.sa.sa_family == AF_INET) + { + SOCKADDR_LEN_T addrsize; + struct sockaddr_in saddr_l; + + if (sasl_setprop(mci->mci_conn, SASL_IP_REMOTE, + (struct sockaddr_in *) &CurHostAddr) + != SASL_OK) + return EX_TEMPFAIL; + addrsize = sizeof(struct sockaddr_in); + if (getsockname(fileno(mci->mci_out), + (struct sockaddr *) &saddr_l, &addrsize) != 0) + { + if (sasl_setprop(mci->mci_conn, SASL_IP_LOCAL, + &saddr_l) != SASL_OK) + return EX_TEMPFAIL; + } + } +# endif /* NETINET */ + + /* start client side of sasl */ + saslresult = sasl_client_start(mci->mci_conn, mci->mci_saslcap, + NULL, &client_interact, + &out, &outlen, + (const char **)&mechusing); + callbacks[CB_AUTHNAME_IDX].context = mechusing; + + if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) + { + return EX_TEMPFAIL; + } + + *mechused = mechusing; + + /* send the info across the wire */ + if (outlen > 0) + { + saslresult = sasl_encode64(out, outlen, in64, MAXOUTLEN, NULL); + if (saslresult != SASL_OK) /* internal error */ + { + if (LogLevel > 8) + sm_syslog(LOG_ERR, e->e_id, + "encode64 for AUTH failed"); + return EX_TEMPFAIL; + } + smtpmessage("AUTH %s %s", m, mci, mechusing, in64); + } + else + { + smtpmessage("AUTH %s", m, mci, mechusing); + } + + /* get the reply */ + smtpresult = reply(m, mci, e, TimeOuts.to_datafinal, getsasldata, NULL); + /* which timeout? XXX */ + + for (;;) + { + /* check return code from server */ + if (smtpresult == 235) + { + define(macid("{auth_type}", NULL), + newstr(mechusing), e); + if (LogLevel > 9) + sm_syslog(LOG_INFO, NOQID, + "SASL: outgoing connection to %.64s: mech=%.16s", + mci->mci_host, mechusing); + return EX_OK; + } + if (smtpresult == -1) + return EX_IOERR; + if (smtpresult != 334) + return EX_TEMPFAIL; + + saslresult = sasl_client_step(mci->mci_conn, + mci->mci_sasl_string, + mci->mci_sasl_string_len, + &client_interact, + &out, &outlen); + + if (saslresult != SASL_OK && saslresult != SASL_CONTINUE) + { + if (tTd(95, 5)) + dprintf("AUTH FAIL: %s (%d)\n", + sasl_errstring(saslresult, NULL, NULL), + saslresult); + + /* fail deliberately, see RFC 2254 4. */ + smtpmessage("*", m, mci); + + /* + ** but we should only fail for this authentication + ** mechanism; how to do that? + */ + + smtpresult = reply(m, mci, e, TimeOuts.to_datafinal, + getsasldata, NULL); + return EX_TEMPFAIL; + } + + if (outlen > 0) + { + saslresult = sasl_encode64(out, outlen, in64, + MAXOUTLEN, NULL); + if (saslresult != SASL_OK) + { + /* give an error reply to the other side! */ + smtpmessage("*", m, mci); + return EX_TEMPFAIL; + } + } + else + in64[0] = '\0'; + smtpmessage(in64, m, mci); + smtpresult = reply(m, mci, e, TimeOuts.to_datafinal, + getsasldata, NULL); + /* which timeout? XXX */ + } + /* NOTREACHED */ +} + + /* +** SMTPAUTH -- try to AUTHenticate +** +** This will try mechanisms in the order the sasl library decided until: +** - there are no more mechanisms +** - a mechanism succeeds +** - the sasl library fails initializing +** +** Parameters: +** m -- the mailer. +** mci -- the mailer connection info. +** e -- the envelope. +** +** Returns: +** EX_OK/EX_TEMPFAIL +*/ + +int +smtpauth(m, mci, e) + MAILER *m; + MCI *mci; + ENVELOPE *e; +{ + int result; + char *mechused; + char *h; + static char *defrealm = NULL; + + mci->mci_sasl_auth = FALSE; + if (defrealm == NULL) + { + h = readauth(SASL_DEFREALM, SASLInfo, TRUE); + if (h != NULL && *h != '\0') + defrealm = newstr(h); + } + if (defrealm == NULL || *defrealm == '\0') + defrealm = newstr(macvalue('j', CurEnv)); + callbacks[CB_GETREALM_IDX].context = defrealm; + + /* initialize sasl client library */ + result = sasl_client_init(callbacks); + if (result != SASL_OK) + return EX_TEMPFAIL; + do { + result = attemptauth(m, mci, e, &mechused); + if (result == EX_OK) + mci->mci_sasl_auth = TRUE; + else if (result == EX_TEMPFAIL) + { + mci->mci_saslcap = removemech(mechused, + mci->mci_saslcap); + if (mci->mci_saslcap == NULL || + *(mci->mci_saslcap) == '\0') + return EX_TEMPFAIL; + } + else /* all others for now */ + return EX_TEMPFAIL; + } while (result != EX_OK); + return result; +} +# endif /* SASL */ + + /* +** 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) + MAILER *m; + MCI *mci; + ENVELOPE *e; +{ + int r; + char *bufp; + char *bodytype; + char buf[MAXNAME + 1]; + char optbuf[MAXLINE]; + char *enhsc; + + if (tTd(18, 2)) + dprintf("smtpmailfrom: CurHost=%s\n", CurHostName); + enhsc = NULL; + + /* set up appropriate options to include */ + if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0) + { + snprintf(optbuf, sizeof optbuf, " SIZE=%ld", e->e_msgsize); + bufp = &optbuf[strlen(optbuf)]; + } + else + { + optbuf[0] = '\0'; + bufp = 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 && + SPACELEFT(optbuf, bufp) > strlen(bodytype) + 7) + { + snprintf(bufp, SPACELEFT(optbuf, bufp), + " BODY=%s", bodytype); + bufp += strlen(bufp); + } + } + else if (bitnset(M_8BITS, m->m_flags) || + !bitset(EF_HAS8BIT, e->e_flags) || + bitset(MCIF_8BITOK, mci->mci_flags)) + { + /* EMPTY */ + /* 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 /* MIME8TO7 */ + else if (!bitset(MM_PASS8BIT, MimeMode)) + { + /* cannot just send a 8-bit version */ + extern char MsgBuf[]; + + usrerrenh("5.6.3", "%s does not support 8BITMIME", CurHostName); + mci_setstat(mci, EX_NOTSTICKY, "5.6.3", MsgBuf); + return EX_DATAERR; + } + + if (bitset(MCIF_DSN, mci->mci_flags)) + { + if (e->e_envid != NULL && + SPACELEFT(optbuf, bufp) > strlen(e->e_envid) + 7) + { + snprintf(bufp, SPACELEFT(optbuf, bufp), + " ENVID=%s", e->e_envid); + bufp += strlen(bufp); + } + + /* RET= parameter */ + if (bitset(EF_RET_PARAM, e->e_flags) && + SPACELEFT(optbuf, bufp) > 9) + { + snprintf(bufp, SPACELEFT(optbuf, bufp), + " RET=%s", + bitset(EF_NO_BODY_RETN, e->e_flags) ? + "HDRS" : "FULL"); + bufp += strlen(bufp); + } + } + + if (bitset(MCIF_AUTH, mci->mci_flags) && e->e_auth_param != NULL && + SPACELEFT(optbuf, bufp) > strlen(e->e_auth_param) + 7 +# if SASL + && (SASLTryAuth != SASL_AUTH_AUTH || mci->mci_sasl_auth) +# endif /* SASL */ + ) + { + snprintf(bufp, SPACELEFT(optbuf, bufp), + " AUTH=%s", e->e_auth_param); + bufp += strlen(bufp); + } + + /* + ** 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)) + buf[0] = '\0'; + else + expand("\201g", buf, sizeof buf, e); + if (buf[0] == '<') + { + /* strip off (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"; + sm_setproctitle(TRUE, e, "%s %s: %s", qid_printname(e), + CurHostName, mci->mci_phase); + r = reply(m, mci, e, TimeOuts.to_mail, NULL, &enhsc); + if (r < 0) + { + /* communications failure */ + mci->mci_errno = errno; + mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); + smtpquit(m, mci, e); + return EX_TEMPFAIL; + } + else if (r == 421) + { + /* service shutting down */ + mci_setstat(mci, EX_TEMPFAIL, ENHSCN(enhsc, "4.5.0"), + SmtpReplyBuffer); + smtpquit(m, mci, e); + return EX_TEMPFAIL; + } + else if (REPLYTYPE(r) == 4) + { + mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, smtptodsn(r)), + SmtpReplyBuffer); + return EX_TEMPFAIL; + } + else if (REPLYTYPE(r) == 2) + { + return EX_OK; + } + else if (r == 501) + { + /* syntax error in arguments */ + mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.5.2"), + SmtpReplyBuffer); + return EX_DATAERR; + } + else if (r == 553) + { + /* mailbox name not allowed */ + mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.1.3"), + SmtpReplyBuffer); + return EX_DATAERR; + } + else if (r == 552) + { + /* exceeded storage allocation */ + mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.3.4"), + SmtpReplyBuffer); + if (bitset(MCIF_SIZE, mci->mci_flags)) + e->e_flags |= EF_NO_BODY_RETN; + return EX_UNAVAILABLE; + } + else if (REPLYTYPE(r) == 5) + { + /* unknown error */ + mci_setstat(mci, EX_NOTSTICKY, ENHSCN(enhsc, "5.0.0"), + SmtpReplyBuffer); + return EX_UNAVAILABLE; + } + + if (LogLevel > 1) + { + sm_syslog(LOG_CRIT, e->e_id, + "%.100s: SMTP MAIL protocol error: %s", + CurHostName, + shortenstring(SmtpReplyBuffer, 403)); + } + + /* protocol error -- close up */ + mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), + SmtpReplyBuffer); + 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 *bufp; + char optbuf[MAXLINE]; + char *enhsc; + + enhsc = NULL; + optbuf[0] = '\0'; + bufp = optbuf; + + /* + ** warning: in the following it is assumed that the free space + ** in bufp is sizeof optbuf + */ + if (bitset(MCIF_DSN, mci->mci_flags)) + { + /* NOTIFY= parameter */ + if (bitset(QHASNOTIFY, to->q_flags) && + bitset(QPRIMARY, to->q_flags) && + !bitnset(M_LOCALMAILER, m->m_flags)) + { + bool firstone = TRUE; + + (void) strlcat(bufp, " NOTIFY=", sizeof optbuf); + if (bitset(QPINGONSUCCESS, to->q_flags)) + { + (void) strlcat(bufp, "SUCCESS", sizeof optbuf); + firstone = FALSE; + } + if (bitset(QPINGONFAILURE, to->q_flags)) + { + if (!firstone) + (void) strlcat(bufp, ",", + sizeof optbuf); + (void) strlcat(bufp, "FAILURE", sizeof optbuf); + firstone = FALSE; + } + if (bitset(QPINGONDELAY, to->q_flags)) + { + if (!firstone) + (void) strlcat(bufp, ",", + sizeof optbuf); + (void) strlcat(bufp, "DELAY", sizeof optbuf); + firstone = FALSE; + } + if (firstone) + (void) strlcat(bufp, "NEVER", sizeof optbuf); + bufp += strlen(bufp); + } + + /* ORCPT= parameter */ + if (to->q_orcpt != NULL && + SPACELEFT(optbuf, bufp) > strlen(to->q_orcpt) + 7) + { + snprintf(bufp, SPACELEFT(optbuf, bufp), + " ORCPT=%s", to->q_orcpt); + bufp += strlen(bufp); + } + } + + smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf); + + SmtpPhase = mci->mci_phase = "client RCPT"; + sm_setproctitle(TRUE, e, "%s %s: %s", qid_printname(e), + CurHostName, mci->mci_phase); + r = reply(m, mci, e, TimeOuts.to_rcpt, NULL, &enhsc); + to->q_rstatus = newstr(SmtpReplyBuffer); + to->q_status = ENHSCN(enhsc, smtptodsn(r)); + if (!bitnset(M_LMTP, m->m_flags)) + 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) + { + to->q_status = ENHSCN(enhsc, "5.1.1"); + return EX_NOUSER; + } + else if (r == 551) + { + to->q_status = ENHSCN(enhsc, "5.1.6"); + return EX_NOUSER; + } + else if (r == 553) + { + to->q_status = ENHSCN(enhsc, "5.1.3"); + return EX_NOUSER; + } + else if (REPLYTYPE(r) == 5) + { + return EX_UNAVAILABLE; + } + + if (LogLevel > 1) + { + sm_syslog(LOG_CRIT, e->e_id, + "%.100s: SMTP RCPT protocol error: %s", + CurHostName, + shortenstring(SmtpReplyBuffer, 403)); + } + + mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), + SmtpReplyBuffer); + return EX_PROTOCOL; +} + /* +** SMTPDATA -- send the data and clean up the transaction. +** +** Parameters: +** m -- mailer being sent to. +** mci -- the mailer connection information. +** e -- the envelope for this message. +** +** Returns: +** exit status corresponding to DATA command. +** +** Side Effects: +** none. +*/ + +static jmp_buf CtxDataTimeout; + +int +smtpdata(m, mci, e) + MAILER *m; + register MCI *mci; + register ENVELOPE *e; +{ + register int r; + register EVENT *ev; + int rstat; + int xstat; + time_t timeout; + char *enhsc; + + enhsc = NULL; + /* + ** 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"; + sm_setproctitle(TRUE, e, "%s %s: %s", + qid_printname(e), CurHostName, mci->mci_phase); + r = reply(m, mci, e, TimeOuts.to_datainit, NULL, &enhsc); + 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 (REPLYTYPE(r) != 3) + { + if (LogLevel > 1) + { + sm_syslog(LOG_CRIT, e->e_id, + "%.100s: SMTP DATA-1 protocol error: %s", + CurHostName, + shortenstring(SmtpReplyBuffer, 403)); + } + smtprset(m, mci, e); + mci_setstat(mci, EX_PROTOCOL, ENHSCN(enhsc, "5.5.1"), + SmtpReplyBuffer); + 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_state = MCIS_ERROR; + mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL); + + /* + ** If putbody() couldn't finish due to a timeout, + ** rewind it here in the timeout handler. See + ** comments at the end of putbody() for reasoning. + */ + + if (e->e_dfp != NULL) + (void) bfrewind(e->e_dfp); + + errno = mci->mci_errno; + syserr("451 4.4.1 timeout writing message to %s", CurHostName); + smtpquit(m, mci, e); + return EX_TEMPFAIL; + } + + if (tTd(18, 101)) + { + /* simulate a DATA timeout */ + timeout = 1; + } + else + timeout = DATA_PROGRESS_TIMEOUT; + + ev = setevent(timeout, datatimeout, 0); + + if (tTd(18, 101)) + { + /* simulate a DATA timeout */ + (void) sleep(1); + } + + /* + ** Output the actual message. + */ + + (*e->e_puthdr)(mci, e->e_header, e, M87F_OUTER); + (*e->e_putbody)(mci, e, NULL); + + /* + ** Cleanup after sending message. + */ + + clrevent(ev); + +# if _FFR_CATCH_BROKEN_MTAS + { + fd_set readfds; + struct timeval timeout; + + FD_ZERO(&readfds); + FD_SET(fileno(mci->mci_in), &readfds); + timeout.tv_sec = 0; + timeout.tv_usec = 0; + if (select(fileno(mci->mci_in) + 1, FDSET_CAST &readfds, + NULL, NULL, &timeout) > 0 && + FD_ISSET(fileno(mci->mci_in), &readfds)) + { + /* terminate the message */ + fprintf(mci->mci_out, ".%s", m->m_eol); + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d >>> .\n", + (int) getpid()); + if (Verbose) + nmessage(">>> ."); + + mci->mci_errno = EIO; + mci->mci_state = MCIS_ERROR; + mci_setstat(mci, EX_PROTOCOL, "5.5.0", NULL); + smtpquit(m, mci, e); + return EX_PROTOCOL; + } + } +# endif /* _FFR_CATCH_BROKEN_MTAS */ + + if (ferror(mci->mci_out)) + { + /* error during processing -- don't send the dot */ + mci->mci_errno = EIO; + mci->mci_state = MCIS_ERROR; + mci_setstat(mci, EX_IOERR, "4.4.2", NULL); + 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", (int) getpid()); + if (Verbose) + nmessage(">>> ."); + + /* check for the results of the transaction */ + SmtpPhase = mci->mci_phase = "client DATA status"; + sm_setproctitle(TRUE, e, "%s %s: %s", qid_printname(e), + CurHostName, mci->mci_phase); + if (bitnset(M_LMTP, m->m_flags)) + return EX_OK; + r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc); + if (r < 0) + { + smtpquit(m, mci, e); + return EX_TEMPFAIL; + } + mci->mci_state = MCIS_OPEN; + xstat = EX_NOTSTICKY; + if (r == 452) + rstat = EX_TEMPFAIL; + else if (REPLYTYPE(r) == 4) + rstat = xstat = EX_TEMPFAIL; + else if (REPLYCLASS(r) != 5) + rstat = xstat = EX_PROTOCOL; + else if (REPLYTYPE(r) == 2) + rstat = xstat = EX_OK; + else if (REPLYTYPE(r) == 5) + rstat = EX_UNAVAILABLE; + else + rstat = EX_PROTOCOL; + mci_setstat(mci, xstat, ENHSCN(enhsc, smtptodsn(r)), + SmtpReplyBuffer); + if (e->e_statmsg != NULL) + free(e->e_statmsg); + if (bitset(MCIF_ENHSTAT, mci->mci_flags) && + (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) + r += 5; + else + r = 4; + e->e_statmsg = newstr(&SmtpReplyBuffer[r]); + if (rstat != EX_PROTOCOL) + return rstat; + if (LogLevel > 1) + { + sm_syslog(LOG_CRIT, e->e_id, + "%.100s: SMTP DATA-2 protocol error: %s", + CurHostName, + shortenstring(SmtpReplyBuffer, 403)); + } + return rstat; +} + + +static void +datatimeout() +{ + if (DataProgress) + { + time_t timeout; + register EVENT *ev; + + /* check back again later */ + if (tTd(18, 101)) + { + /* simulate a DATA timeout */ + timeout = 1; + } + else + timeout = DATA_PROGRESS_TIMEOUT; + + DataProgress = FALSE; + ev = setevent(timeout, datatimeout, 0); + } + else + { + /* no progress, give up */ + longjmp(CtxDataTimeout, 1); + } +} + /* +** SMTPGETSTAT -- get status code from DATA in LMTP +** +** Parameters: +** m -- the mailer to which we are sending the message. +** mci -- the mailer connection structure. +** e -- the current envelope. +** +** Returns: +** The exit status corresponding to the reply code. +*/ + +int +smtpgetstat(m, mci, e) + MAILER *m; + MCI *mci; + ENVELOPE *e; +{ + int r; + int status; + char *enhsc; + + enhsc = NULL; + /* check for the results of the transaction */ + r = reply(m, mci, e, TimeOuts.to_datafinal, NULL, &enhsc); + if (r < 0) + { + smtpquit(m, mci, e); + return EX_TEMPFAIL; + } + if (REPLYTYPE(r) == 4) + status = EX_TEMPFAIL; + else if (REPLYCLASS(r) != 5) + status = EX_PROTOCOL; + else if (REPLYTYPE(r) == 2) + status = EX_OK; + else if (REPLYTYPE(r) == 5) + status = EX_UNAVAILABLE; + else + status = EX_PROTOCOL; + if (e->e_statmsg != NULL) + free(e->e_statmsg); + if (bitset(MCIF_ENHSTAT, mci->mci_flags) && + (r = isenhsc(SmtpReplyBuffer + 4, ' ')) > 0) + r += 5; + else + r = 4; + e->e_statmsg = newstr(&SmtpReplyBuffer[r]); + mci_setstat(mci, status, ENHSCN(enhsc, smtptodsn(r)), + SmtpReplyBuffer); + if (LogLevel > 1 && status == EX_PROTOCOL) + { + sm_syslog(LOG_CRIT, e->e_id, + "%.100s: SMTP DATA-3 protocol error: %s", + CurHostName, + shortenstring(SmtpReplyBuffer, 403)); + } + return status; +} + /* +** SMTPQUIT -- close the SMTP connection. +** +** Parameters: +** m -- a pointer to the mailer. +** mci -- the mailer connection information. +** e -- the current envelope. +** +** 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; + int rcode; + + CurHostName = mci->mci_host; /* XXX UGLY XXX */ + if (CurHostName == NULL) + CurHostName = MyHostName; + + /* + ** 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 && + mci->mci_state != MCIS_QUITING) + { + int origstate = mci->mci_state; + + SmtpPhase = "client QUIT"; + mci->mci_state = MCIS_QUITING; + smtpmessage("QUIT", m, mci); + (void) reply(m, mci, e, TimeOuts.to_quit, NULL, NULL); + SuprErrs = oldSuprErrs; + if (mci->mci_state == MCIS_CLOSED || + origstate == MCIS_CLOSED) + return; + } + + /* now actually close the connection and pick up the zombie */ + rcode = endmailer(mci, e, NULL); + if (rcode != EX_OK) + { + char *mailer = NULL; + + if (mci->mci_mailer != NULL && + mci->mci_mailer->m_name != NULL) + mailer = mci->mci_mailer->m_name; + + /* look for naughty mailers */ + sm_syslog(LOG_ERR, e->e_id, + "smtpquit: mailer%s%s exited with exit value %d\n", + mailer == NULL ? "" : " ", + mailer == NULL ? "" : mailer, + rcode); + } + + SuprErrs = oldSuprErrs; +} + /* +** SMTPRSET -- send a RSET (reset) command +*/ + +void +smtprset(m, mci, e) + register MAILER *m; + register MCI *mci; + ENVELOPE *e; +{ + int r; + + CurHostName = mci->mci_host; /* XXX UGLY XXX */ + if (CurHostName == NULL) + CurHostName = MyHostName; + + SmtpPhase = "client RSET"; + smtpmessage("RSET", m, mci); + r = reply(m, mci, e, TimeOuts.to_rset, NULL, NULL); + if (r < 0) + mci->mci_state = MCIS_ERROR; + else + { + /* + ** Any response is deemed to be acceptable. + ** The standard does not state the proper action + ** to take when a value other than 250 is received. + */ + + 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; + ENVELOPE *e; + extern ENVELOPE BlankEnvelope; + + CurHostName = mci->mci_host; /* XXX UGLY XXX */ + if (CurHostName == NULL) + CurHostName = MyHostName; + + e = &BlankEnvelope; + SmtpPhase = "client probe"; + smtpmessage("RSET", m, mci); + r = reply(m, mci, e, TimeOuts.to_miscshort, NULL, 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, enhstat) + MAILER *m; + MCI *mci; + ENVELOPE *e; + time_t timeout; + void (*pfunc)(); + char **enhstat; +{ + register char *bufp; + register int r; + bool firstline = TRUE; + char junkbuf[MAXLINE]; + static char enhstatcode[ENHSCLEN]; + int save_errno; + + if (mci->mci_out != NULL) + (void) fflush(mci->mci_out); + + if (tTd(18, 1)) + dprintf("reply\n"); + + /* + ** Read the input line, being careful not to hang. + */ + + bufp = SmtpReplyBuffer; + for (;;) + { + register char *p; + + /* 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) + (void) 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; + extern char MsgBuf[]; + + /* 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; + oldholderrs = HoldErrs; + HoldErrs = TRUE; + usrerr("451 4.4.1 reply: read error from %s", + CurHostName == NULL ? "NO_HOST" : CurHostName); + + /* errors on QUIT should not be persistent */ + if (strncmp(SmtpMsgBuffer, "QUIT", 4) != 0) + mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf); + + /* if debugging, pause so we can see state */ + if (tTd(18, 100)) + (void) pause(); + mci->mci_state = MCIS_ERROR; + save_errno = errno; + smtpquit(m, mci, e); +# if XDEBUG + { + char wbuf[MAXLINE]; + int wbufleft = sizeof wbuf; + + p = wbuf; + if (e->e_to != NULL) + { + int plen; + + snprintf(p, wbufleft, "%s... ", + shortenstring(e->e_to, MAXSHORTSTR)); + plen = strlen(p); + p += plen; + wbufleft -= plen; + } + snprintf(p, wbufleft, "reply(%.100s) during %s", + CurHostName == NULL ? "NO_HOST" : CurHostName, + SmtpPhase); + checkfd012(wbuf); + } +# endif /* XDEBUG */ + errno = save_errno; + 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 == NULL ? "NO_HOST" : 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); + + /* ignore improperly formatted input */ + if (!ISSMTPREPLY(bufp)) + continue; + + if (bitset(MCIF_ENHSTAT, mci->mci_flags) && + enhstat != NULL && + extenhsc(bufp + 4, ' ', enhstatcode) > 0) + *enhstat = enhstatcode; + + /* process the line */ + if (pfunc != NULL) + (*pfunc)(bufp, firstline, m, mci, e); + + firstline = FALSE; + + /* decode the reply code */ + r = atoi(bufp); + + /* extra semantics: 0xx codes are "informational" */ + if (r < 100) + continue; + + /* if no continuation lines, return this line */ + if (bufp[3] != '-') + break; + + /* first line of real reply -- ignore rest */ + bufp = junkbuf; + } + + /* + ** 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' && + (bitnset(M_LMTP, m->m_flags) || SmtpError[0] == '\0')) + snprintf(SmtpError, sizeof SmtpError, "%s", 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 /* __STDC__ */ +smtpmessage(f, m, mci, va_alist) + char *f; + MAILER *m; + MCI *mci; + va_dcl +# endif /* __STDC__ */ +{ + 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", + (int) 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)) + { + dprintf("smtpmessage: NULL mci_out\n"); + } +} + +#endif /* SMTP */ diff --git a/gnu/usr.sbin/sendmail/sendmail/util.c b/gnu/usr.sbin/sendmail/sendmail/util.c new file mode 100644 index 00000000000..815509e218f --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/util.c @@ -0,0 +1,2458 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: util.c,v 8.224 1999/11/24 08:44:38 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include + +static void readtimeout __P((time_t)); + + /* +** 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. +*/ + +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'); +} + /* +** ADDQUOTES -- Adds quotes & quote bits to a string. +** +** Runs through a string and adds characters and quote bits. +** +** Parameters: +** s -- the string to modify. +** +** Returns: +** pointer to quoted string. +** +** Side Effects: +** none. +** +*/ + +char * +addquotes(s) + char *s; +{ + int len = 0; + char c; + char *p = s, *q, *r; + + if (s == NULL) + return NULL; + + /* Find length of quoted string */ + while ((c = *p++) != '\0') + { + len++; + if (c == '\\' || c == '"') + len++; + } + + q = r = xalloc(len + 3); + p = s; + + /* add leading quote */ + *q++ = '"'; + while ((c = *p++) != '\0') + { + /* quote \ or " */ + if (c == '\\' || c == '"') + *q++ = '\\'; + *q++ = c; + } + *q++ = '"'; + *q = '\0'; + return r; +} + /* +** RFC822_STRING -- Checks string for proper RFC822 string quoting. +** +** Runs through a string and verifies RFC822 special characters +** are only found inside comments, quoted strings, or backslash +** escaped. Also verified balanced quotes and parenthesis. +** +** Parameters: +** s -- the string to modify. +** +** Returns: +** TRUE -- if the string is RFC822 compliant. +** FALSE -- if the string is not RFC822 compliant. +** +** Side Effects: +** none. +** +*/ + +bool +rfc822_string(s) + char *s; +{ + bool quoted = FALSE; + int commentlev = 0; + char *c = s; + + if (s == NULL) + return FALSE; + + while (*c != '\0') + { + /* escaped character */ + if (*c == '\\') + { + c++; + if (*c == '\0') + return FALSE; + } + else if (commentlev == 0 && *c == '"') + quoted = !quoted; + else if (!quoted) + { + if (*c == ')') + { + /* unbalanced ')' */ + if (commentlev == 0) + return FALSE; + else + commentlev--; + } + else if (*c == '(') + commentlev++; + else if (commentlev == 0 && + strchr(MustQuoteChars, *c) != NULL) + return FALSE; + } + c++; + } + /* unbalanced '"' or '(' */ + if (quoted || commentlev != 0) + return FALSE; + else + return TRUE; +} + /* +** SHORTEN_RFC822_STRING -- Truncate and rebalance an RFC822 string +** +** Arbitrarily shorten (in place) an RFC822 string and rebalance +** comments and quotes. +** +** Parameters: +** string -- the string to shorten +** length -- the maximum size, 0 if no maximum +** +** Returns: +** TRUE if string is changed, FALSE otherwise +** +** Side Effects: +** Changes string in place, possibly resulting +** in a shorter string. +*/ + +bool +shorten_rfc822_string(string, length) + char *string; + size_t length; +{ + bool backslash = FALSE; + bool modified = FALSE; + bool quoted = FALSE; + size_t slen; + int parencount = 0; + char *ptr = string; + + /* + ** If have to rebalance an already short enough string, + ** need to do it within allocated space. + */ + slen = strlen(string); + if (length == 0 || slen < length) + length = slen; + + while (*ptr != '\0') + { + if (backslash) + { + backslash = FALSE; + goto increment; + } + + if (*ptr == '\\') + backslash = TRUE; + else if (*ptr == '(') + { + if (!quoted) + parencount++; + } + else if (*ptr == ')') + { + if (--parencount < 0) + parencount = 0; + } + + /* Inside a comment, quotes don't matter */ + if (parencount <= 0 && *ptr == '"') + quoted = !quoted; + +increment: + /* Check for sufficient space for next character */ + if (length - (ptr - string) <= ((backslash ? 1 : 0) + + parencount + + (quoted ? 1 : 0))) + { + /* Not enough, backtrack */ + if (*ptr == '\\') + backslash = FALSE; + else if (*ptr == '(' && !quoted) + parencount--; + else if (*ptr == '"' && parencount == 0) + quoted = FALSE; + break; + } + ptr++; + } + + /* Rebalance */ + while (parencount-- > 0) + { + if (*ptr != ')') + { + modified = TRUE; + *ptr = ')'; + } + ptr++; + } + if (quoted) + { + if (*ptr != '"') + { + modified = TRUE; + *ptr = '"'; + } + ptr++; + } + if (*ptr != '\0') + { + modified = TRUE; + *ptr = '\0'; + } + return modified; +} + /* +** FIND_CHARACTER -- find an unquoted character in an RFC822 string +** +** Find an unquoted, non-commented character in an RFC822 +** string and return a pointer to its location in the +** string. +** +** Parameters: +** string -- the string to search +** character -- the character to find +** +** Returns: +** pointer to the character, or +** a pointer to the end of the line if character is not found +*/ + +char * +find_character(string, character) + char *string; + int character; +{ + bool backslash = FALSE; + bool quoted = FALSE; + int parencount = 0; + + while (string != NULL && *string != '\0') + { + if (backslash) + { + backslash = FALSE; + if (!quoted && character == '\\' && *string == '\\') + break; + string++; + continue; + } + switch (*string) + { + case '\\': + backslash = TRUE; + break; + + case '(': + if (!quoted) + parencount++; + break; + + case ')': + if (--parencount < 0) + parencount = 0; + break; + } + + /* Inside a comment, nothing matters */ + if (parencount > 0) + { + string++; + continue; + } + + if (*string == '"') + quoted = !quoted; + else if (*string == character && !quoted) + break; + string++; + } + + /* Return pointer to the character */ + return string; +} + /* +** 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); + memmove((char *) newvp, (char *) list, (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 as QS_IS_DEAD() 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 (!QS_IS_DEAD(addr->q_state)) + { + newaddr = (ADDRESS *) xalloc(sizeof *newaddr); + STRUCTCOPY(*addr, *newaddr); + *tail = newaddr; + tail = &newaddr->q_next; + } + addr = addr->q_next; + } + *tail = NULL; + + return ret; +} + /* +** LOG_SENDMAIL_PID -- record sendmail pid and command line. +** +** Parameters: +** e -- the current envelope. +** +** Returns: +** none. +** +** Side Effects: +** writes pidfile. +*/ + +void +log_sendmail_pid(e) + ENVELOPE *e; +{ + long sff; + FILE *pidf; + char pidpath[MAXPATHLEN + 1]; + + /* write the pid to the log file for posterity */ + sff = SFF_NOLINK|SFF_ROOTOK|SFF_REGONLY|SFF_CREAT; + if (TrustedUid != 0 && RealUid == TrustedUid) + sff |= SFF_OPENASROOT; + expand(PidFile, pidpath, sizeof pidpath, e); + pidf = safefopen(pidpath, O_WRONLY|O_TRUNC, 0644, sff); + if (pidf == NULL) + { + sm_syslog(LOG_ERR, NOQID, "unable to write %s", pidpath); + } + else + { + extern char *CommandLineArgs; + + /* write the process id on line 1 */ + fprintf(pidf, "%ld\n", (long) getpid()); + + /* line 2 contains all command line flags */ + fprintf(pidf, "%s\n", CommandLineArgs); + + /* flush and close */ + (void) fclose(pidf); + } +} + /* +** SET_DELIVERY_MODE -- set and record the delivery mode +** +** Parameters: +** mode -- delivery mode +** e -- the current envelope. +** +** Returns: +** none. +** +** Side Effects: +** sets $&{deliveryMode} macro +*/ + +void +set_delivery_mode(mode, e) + int mode; + ENVELOPE *e; +{ + char buf[2]; + + e->e_sendmode = (char)mode; + buf[0] = (char)mode; + buf[1] = '\0'; + define(macid("{deliveryMode}", NULL), newstr(buf), e); +} + /* +** 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)) + dprintf("\n\t%08lx=", (u_long) *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 int 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; + bool shiftout = FALSE; + extern struct metamac MetaMacros[]; + + if (s == NULL) + { + printf("%s%s", TermEscape.te_rv_on, TermEscape.te_rv_off); + return; + } + while ((c = (*s++ & 0377)) != '\0') + { + if (shiftout) + { + printf("%s", TermEscape.te_rv_off); + shiftout = FALSE; + } + if (!isascii(c)) + { + if (c == MATCHREPL) + { + printf("%s$", TermEscape.te_rv_on); + shiftout = TRUE; + if (*s == '\0') + continue; + c = *s++ & 0377; + goto printchar; + } + if (c == MACROEXPAND || c == MACRODEXPAND) + { + printf("%s$", TermEscape.te_rv_on); + if (c == MACRODEXPAND) + (void) putchar('&'); + shiftout = TRUE; + if (*s == '\0') + continue; + if (strchr("=~&?", *s) != NULL) + (void) putchar(*s++); + if (bitset(0200, *s)) + printf("{%s}", macname(*s++ & 0377)); + else + printf("%c", *s++); + continue; + } + for (mp = MetaMacros; mp->metaname != '\0'; mp++) + { + if ((mp->metaval & 0377) == c) + { + printf("%s$%c", + TermEscape.te_rv_on, + mp->metaname); + shiftout = TRUE; + break; + } + } + if (c == MATCHCLASS || c == MATCHNCLASS) + { + if (bitset(0200, *s)) + printf("{%s}", macname(*s++ & 0377)); + else if (*s != '\0') + printf("%c", *s++); + } + if (mp->metaname != '\0') + continue; + + /* unrecognized meta character */ + printf("%sM-", TermEscape.te_rv_on); + shiftout = TRUE; + c &= 0177; + } + printchar: + if (isprint(c)) + { + (void) 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; + } + if (!shiftout) + { + printf("%s", TermEscape.te_rv_on); + shiftout = TRUE; + } + if (isprint(c)) + { + (void) putchar('\\'); + (void) putchar(c); + } + else + { + (void) putchar('^'); + (void) putchar(c ^ 0100); + } + } + if (shiftout) + printf("%s", TermEscape.te_rv_off); + (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. +*/ + +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. +** user -- the login name of this user (for &). +** buf -- place to put the result. +** buflen -- length of buf. +** +** Returns: +** none. +** +** Side Effects: +** none. +*/ + +void +buildfname(gecos, user, buf, buflen) + register char *gecos; + char *user; + char *buf; + int buflen; +{ + register char *p; + register char *bp = buf; + + if (*gecos == '*') + gecos++; + + /* copy gecos, interpolating & to be full name */ + for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++) + { + if (bp >= &buf[buflen - 1]) + { + /* buffer overflow -- just use login name */ + snprintf(buf, buflen, "%s", user); + return; + } + if (*p == '&') + { + /* interpolate full name */ + snprintf(bp, buflen - (bp - buf), "%s", user); + *bp = toupper(*bp); + bp += strlen(bp); + } + else + *bp++ = *p; + } + *bp = '\0'; +} + /* +** FIXCRLF -- fix in line. +** +** Looks for the combination and turns it into the +** UNIX canonical character. It only takes one line, +** i.e., it is assumed that the first 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'; +} + /* +** 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, strlen(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. +** len -- the length of the line. +** mci -- the mailer connection information. +** pxflags -- flag bits: +** PXLF_MAPFROM -- map From_ to >From_. +** PXLF_STRIP8BIT -- strip 8th bit. +** PXLF_HEADER -- map bare newline in header to newline space. +** +** Returns: +** none +** +** Side Effects: +** output of l to fp. +*/ + +void +putxline(l, len, mci, pxflags) + register char *l; + size_t len; + register MCI *mci; + int pxflags; +{ + bool dead = FALSE; + register char *p, *end; + int slop = 0; + + /* strip out 0200 bits -- these can look like TELNET protocol */ + if (bitset(MCIF_7BIT, mci->mci_flags) || + bitset(PXLF_STRIP8BIT, pxflags)) + { + register char svchar; + + for (p = l; (svchar = *p) != '\0'; ++p) + if (bitset(0200, svchar)) + *p = svchar &~ 0200; + } + + end = l + len; + do + { + /* find the end of the line */ + p = memchr(l, '\n', end - l); + if (p == NULL) + p = end; + + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d >>> ", (int) getpid()); + + /* check for line overflow */ + while (mci->mci_mailer->m_linelimit > 0 && + (p - l + slop) > mci->mci_mailer->m_linelimit) + { + char *l_base = l; + register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1]; + + if (l[0] == '.' && slop == 0 && + bitnset(M_XDOT, mci->mci_mailer->m_flags)) + { + if (putc('.', mci->mci_out) == EOF) + dead = TRUE; + 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)) + { + if (putc('>', mci->mci_out) == EOF) + dead = TRUE; + if (TrafficLogFile != NULL) + (void) putc('>', TrafficLogFile); + } + if (dead) + break; + + while (l < q) + { + if (putc(*l++, mci->mci_out) == EOF) + { + dead = TRUE; + break; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } + if (dead) + break; + + if (putc('!', mci->mci_out) == EOF || + fputs(mci->mci_mailer->m_eol, + mci->mci_out) == EOF || + putc(' ', mci->mci_out) == EOF) + { + dead = TRUE; + break; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + + if (TrafficLogFile != NULL) + { + for (l = l_base; l < q; l++) + (void) putc(*l, TrafficLogFile); + fprintf(TrafficLogFile, "!\n%05d >>> ", + (int) getpid()); + } + slop = 1; + } + + if (dead) + break; + + /* output last part */ + if (l[0] == '.' && slop == 0 && + bitnset(M_XDOT, mci->mci_mailer->m_flags)) + { + if (putc('.', mci->mci_out) == EOF) + break; + 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)) + { + if (putc('>', mci->mci_out) == EOF) + break; + if (TrafficLogFile != NULL) + (void) putc('>', TrafficLogFile); + } + for ( ; l < p; ++l) + { + if (TrafficLogFile != NULL) + (void) putc(*l, TrafficLogFile); + if (putc(*l, mci->mci_out) == EOF) + { + dead = TRUE; + break; + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } + if (dead) + break; + + if (TrafficLogFile != NULL) + (void) putc('\n', TrafficLogFile); + if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) + break; + if (l < end && *l == '\n') + { + if (*++l != ' ' && *l != '\t' && *l != '\0' && + bitset(PXLF_HEADER, pxflags)) + { + if (putc(' ', mci->mci_out) == EOF) + break; + if (TrafficLogFile != NULL) + (void) putc(' ', TrafficLogFile); + } + } + + /* record progress for DATA timeout */ + DataProgress = TRUE; + } while (l < end); +} + /* +** 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; + + if (LogLevel > 98) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "unlink %s", + f); + + i = unlink(f); + if (i < 0 && LogLevel > 97) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "%s: unlink-fail %d", + f, 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; + +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; + int save_errno; + + if (fp == NULL) + { + buf[0] = '\0'; + return NULL; + } + + /* set the timeout */ + if (timeout != 0) + { + if (setjmp(CtxReadTimeout) != 0) + { + if (LogLevel > 1) + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "timeout waiting for input from %.100s during %s", + CurHostName ? CurHostName : "local", + during); + buf[0] = '\0'; +#if XDEBUG + checkfd012(during); +#endif /* XDEBUG */ + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d <<< [TIMEOUT]\n", + (int) getpid()); + errno = 0; + return NULL; + } + ev = setevent(timeout, readtimeout, 0); + } + + /* try to read */ + p = NULL; + errno = 0; + while (!feof(fp) && !ferror(fp)) + { + errno = 0; + p = fgets(buf, siz, fp); + if (p != NULL || errno != EINTR) + break; + clearerr(fp); + } + save_errno = errno; + + /* 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", (int) getpid()); + errno = save_errno; + return NULL; + } + if (TrafficLogFile != NULL) + fprintf(TrafficLogFile, "%05d <<< %s", (int) 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; +} + +/* ARGSUSED */ +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); + memmove(nbp, bp, 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; +} + /* +** 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) + BITMAP256 a; + BITMAP256 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) + BITMAP256 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; + + for (i = 0; i < 3; i++) + fill_fd(i, where); +#endif /* XDEBUG */ +} + /* +** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging +** +** Parameters: +** fd -- file descriptor to check. +** where -- tag to print on failure. +** +** Returns: +** none. +*/ + +void +checkfdopen(fd, where) + int fd; + char *where; +{ +#if XDEBUG + struct stat st; + + if (fstat(fd, &st) < 0 && errno == EBADF) + { + syserr("checkfdopen(%d): %s not open as expected!", fd, where); + printopenfds(TRUE); + } +#endif /* XDEBUG */ +} + /* +** CHECKFDS -- check for new or missing file descriptors +** +** Parameters: +** where -- tag for printing. If null, take a base line. +** +** Returns: +** none +** +** Side Effects: +** If where is set, shows changes since the last call. +*/ + +void +checkfds(where) + char *where; +{ + int maxfd; + register int fd; + bool printhdr = TRUE; + int save_errno = errno; + static BITMAP256 baseline; + extern int DtableSize; + + if (DtableSize > 256) + maxfd = 256; + else + maxfd = DtableSize; + if (where == NULL) + clrbitmap(baseline); + + for (fd = 0; fd < maxfd; fd++) + { + struct stat stbuf; + + if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP) + { + if (!bitnset(fd, baseline)) + continue; + clrbitn(fd, baseline); + } + else if (!bitnset(fd, baseline)) + setbitn(fd, baseline); + else + continue; + + /* file state has changed */ + if (where == NULL) + continue; + if (printhdr) + { + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "%s: changed fds:", + where); + printhdr = FALSE; + } + dumpfd(fd, TRUE, TRUE); + } + errno = save_errno; +} + /* +** PRINTOPENFDS -- print the open file descriptors (for debugging) +** +** Parameters: +** logit -- if set, send output to syslog; otherwise +** print for debugging. +** +** Returns: +** none. +*/ + +#if NETINET || NETINET6 +# include +#endif /* NETINET || NETINET6 */ + +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; +#ifdef S_IFSOCK + SOCKADDR sa; +#endif /* S_IFSOCK */ + auto SOCKADDR_LEN_T slen; + int i; +#if STAT64 > 0 + struct stat64 st; +#else /* STAT64 > 0 */ + struct stat st; +#endif /* STAT64 > 0 */ + char buf[200]; + + p = buf; + snprintf(p, SPACELEFT(buf, p), "%3d: ", fd); + p += strlen(p); + + if ( +#if STAT64 > 0 + fstat64(fd, &st) +#else /* STAT64 > 0 */ + fstat(fd, &st) +#endif /* STAT64 > 0 */ + < 0) + { + if (errno != EBADF) + { + snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)", + errstring(errno)); + goto printit; + } + else if (printclosed) + { + snprintf(p, SPACELEFT(buf, p), "CLOSED"); + goto printit; + } + return; + } + + i = fcntl(fd, F_GETFL, NULL); + if (i != -1) + { + snprintf(p, SPACELEFT(buf, p), "fl=0x%x, ", i); + p += strlen(p); + } + + snprintf(p, SPACELEFT(buf, p), "mode=%o: ", (int) st.st_mode); + p += strlen(p); + switch (st.st_mode & S_IFMT) + { +#ifdef S_IFSOCK + case S_IFSOCK: + snprintf(p, SPACELEFT(buf, p), "SOCK "); + p += strlen(p); + slen = sizeof sa; + if (getsockname(fd, &sa.sa, &slen) < 0) + snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); + else + { + hp = hostnamebyanyaddr(&sa); + if (hp == NULL) + { + /* EMPTY */ + /* do nothing */ + } +# if NETINET + else if (sa.sa.sa_family == AF_INET) + snprintf(p, SPACELEFT(buf, p), "%s/%d", + hp, ntohs(sa.sin.sin_port)); +# endif /* NETINET */ +# if NETINET6 + else if (sa.sa.sa_family == AF_INET6) + snprintf(p, SPACELEFT(buf, p), "%s/%d", + hp, ntohs(sa.sin6.sin6_port)); +# endif /* NETINET6 */ + else + snprintf(p, SPACELEFT(buf, p), "%s", hp); + } + p += strlen(p); + snprintf(p, SPACELEFT(buf, p), "->"); + p += strlen(p); + slen = sizeof sa; + if (getpeername(fd, &sa.sa, &slen) < 0) + snprintf(p, SPACELEFT(buf, p), "(%s)", errstring(errno)); + else + { + hp = hostnamebyanyaddr(&sa); + if (hp == NULL) + { + /* EMPTY */ + /* do nothing */ + } +# if NETINET + else if (sa.sa.sa_family == AF_INET) + snprintf(p, SPACELEFT(buf, p), "%s/%d", + hp, ntohs(sa.sin.sin_port)); +# endif /* NETINET */ +# if NETINET6 + else if (sa.sa.sa_family == AF_INET6) + snprintf(p, SPACELEFT(buf, p), "%s/%d", + hp, ntohs(sa.sin6.sin6_port)); +# endif /* NETINET6 */ + else + snprintf(p, SPACELEFT(buf, p), "%s", hp); + } + break; +#endif /* S_IFSOCK */ + + case S_IFCHR: + snprintf(p, SPACELEFT(buf, p), "CHR: "); + p += strlen(p); + goto defprint; + + case S_IFBLK: + snprintf(p, SPACELEFT(buf, p), "BLK: "); + p += strlen(p); + goto defprint; + +#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) + case S_IFIFO: + snprintf(p, SPACELEFT(buf, p), "FIFO: "); + p += strlen(p); + goto defprint; +#endif /* defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK) */ + +#ifdef S_IFDIR + case S_IFDIR: + snprintf(p, SPACELEFT(buf, p), "DIR: "); + p += strlen(p); + goto defprint; +#endif /* S_IFDIR */ + +#ifdef S_IFLNK + case S_IFLNK: + snprintf(p, SPACELEFT(buf, p), "LNK: "); + p += strlen(p); + goto defprint; +#endif /* S_IFLNK */ + + default: +defprint: + /*CONSTCOND*/ + if (sizeof st.st_ino > sizeof (long)) + snprintf(p, SPACELEFT(buf, p), + "dev=%d/%d, ino=%s, nlink=%d, u/gid=%d/%d, ", + major(st.st_dev), minor(st.st_dev), + quad_to_string(st.st_ino), + (int) st.st_nlink, (int) st.st_uid, + (int) st.st_gid); + else + snprintf(p, SPACELEFT(buf, p), + "dev=%d/%d, ino=%lu, nlink=%d, u/gid=%d/%d, ", + major(st.st_dev), minor(st.st_dev), + (unsigned long) st.st_ino, + (int) st.st_nlink, (int) st.st_uid, + (int) st.st_gid); + /*CONSTCOND*/ + if (sizeof st.st_size > sizeof (long)) + snprintf(p, SPACELEFT(buf, p), "size=%s", + quad_to_string(st.st_size)); + else + snprintf(p, SPACELEFT(buf, p), "size=%lu", + (unsigned long) st.st_size); + break; + } + +printit: + if (logit) + sm_syslog(LOG_DEBUG, CurEnv ? CurEnv->e_id : NULL, + "%.800s", buf); + else + printf("%s\n", 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 save_errno; + 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]); + (void) close(fdv[0]); + (void) close(fdv[1]); + return -1; + } + if (pid > 0) + { + /* parent */ + (void) close(fdv[1]); + *pfd = fdv[0]; + return pid; + } + + /* child -- close stdin */ + (void) close(0); + + /* stdout goes back to parent */ + (void) close(fdv[0]); + if (dup2(fdv[1], 1) < 0) + { + syserr("%s: cannot dup2 for stdout", argv[0]); + _exit(EX_OSERR); + } + (void) close(fdv[1]); + + /* stderr goes to transcript if available */ + if (e->e_xfp != NULL) + { + int xfd; + + xfd = fileno(e->e_xfp); + if (xfd >= 0 && dup2(xfd, 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) + (void) close(fileno(e->e_lockfp)); + + /* chroot to the program mailer directory, if defined */ + if (ProgMailer != NULL && ProgMailer->m_rootdir != NULL) + { + expand(ProgMailer->m_rootdir, buf, sizeof buf, e); + if (chroot(buf) < 0) + syserr("prog_open: cannot chroot(%s)", buf); + if (chdir("/") < 0) + syserr("prog_open: cannot chdir(/)"); + } + + /* run as default user */ + endpwent(); + if (setgid(DefGid) < 0 && geteuid() == 0) + syserr("prog_open: setgid(%ld) failed", (long) DefGid); + if (setuid(DefUid) < 0 && geteuid() == 0) + syserr("prog_open: setuid(%ld) failed", (long) 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 | FD_CLOEXEC); + } + + /* now exec the process */ + (void) execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); + + /* woops! failed */ + save_errno = errno; + syserr("%s: cannot exec", argv[0]); + if (transienterror(save_errno)) + _exit(EX_OSERR); + _exit(EX_CONFIG); + return -1; /* avoid compiler warning on IRIX */ +} + /* +** 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. +** buflen -- the length of buf. +** +** Returns: +** buf if successful. +** NULL otherwise. +*/ + +char * +get_column(line, col, delim, buf, buflen) + char line[]; + int col; + int delim; + char buf[]; + int buflen; +{ + char *p; + char *begin, *end; + int i; + char delimbuf[4]; + + if ((char)delim == '\0') + (void) strlcpy(delimbuf, "\n\t ", sizeof delimbuf); + else + { + delimbuf[0] = (char)delim; + delimbuf[1] = '\0'; + } + + p = line; + if (*p == '\0') + return NULL; /* line empty */ + if (*p == (char)delim && col == 0) + return NULL; /* first column empty */ + + begin = line; + + if (col == 0 && (char)delim == '\0') + { + while (*begin != '\0' && isascii(*begin) && isspace(*begin)) + begin++; + } + + for (i = 0; i < col; i++) + { + if ((begin = strpbrk(begin, delimbuf)) == NULL) + return NULL; /* no such column */ + begin++; + if ((char)delim == '\0') + { + while (*begin != '\0' && isascii(*begin) && isspace(*begin)) + begin++; + } + } + + end = strpbrk(begin, delimbuf); + if (end == NULL) + i = strlen(begin); + else + i = end - begin; + if (i >= buflen) + i = buflen - 1; + (void) strlcpy(buf, begin, i + 1); + 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; +{ + /* check for newlines and log if necessary */ + (void) denlstring(f, TRUE, TRUE); + + if (l <= 0) + syserr("!cleanstrcpy: length == 0"); + + 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; + } + (void) strlcpy(bp, s, l); + for (p = bp; (p = strchr(p, '\n')) != NULL; ) + *p++ = ' '; + + if (logattacks) + { + sm_syslog(LOG_NOTICE, CurEnv->e_id, + "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", + RealHostName == NULL ? "[UNKNOWN]" : RealHostName, + shortenstring(bp, MAXSHORTSTR)); + } + + return bp; +} + /* +** PATH_IS_DIR -- check to see if file exists and is a directory. +** +** There are some additional checks for security violations in +** here. This routine is intended to be used for the host status +** support. +** +** Parameters: +** pathname -- pathname to check for directory-ness. +** createflag -- if set, create directory if needed. +** +** Returns: +** TRUE -- if the indicated pathname is a directory +** FALSE -- otherwise +*/ + +int +path_is_dir(pathname, createflag) + char *pathname; + bool createflag; +{ + struct stat statbuf; + +#if HASLSTAT + if (lstat(pathname, &statbuf) < 0) +#else /* HASLSTAT */ + if (stat(pathname, &statbuf) < 0) +#endif /* HASLSTAT */ + { + if (errno != ENOENT || !createflag) + return FALSE; + if (mkdir(pathname, 0755) < 0) + return FALSE; + return TRUE; + } + if (!S_ISDIR(statbuf.st_mode)) + { + errno = ENOTDIR; + return FALSE; + } + + /* security: don't allow writable directories */ + if (bitset(S_IWGRP|S_IWOTH, statbuf.st_mode)) + { + errno = EACCES; + return FALSE; + } + + return TRUE; +} + /* +** PROC_LIST_ADD -- add process id to list of our children +** +** Parameters: +** pid -- pid to add to list. +** task -- task of pid. +** type -- type of process. +** +** Returns: +** none +*/ + +static struct procs *ProcListVec = NULL; +static int ProcListSize = 0; + +void +proc_list_add(pid, task, type) + pid_t pid; + char *task; + int type; +{ + int i; + + for (i = 0; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == NO_PID) + break; + } + if (i >= ProcListSize) + { + /* probe the existing vector to avoid growing infinitely */ + proc_list_probe(); + + /* now scan again */ + for (i = 0; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == NO_PID) + break; + } + } + if (i >= ProcListSize) + { + /* grow process list */ + struct procs *npv; + + npv = (struct procs *) xalloc((sizeof *npv) * + (ProcListSize + PROC_LIST_SEG)); + if (ProcListSize > 0) + { + memmove(npv, ProcListVec, + ProcListSize * sizeof (struct procs)); + free(ProcListVec); + } + for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++) + { + npv[i].proc_pid = NO_PID; + npv[i].proc_task = NULL; + npv[i].proc_type = PROC_NONE; + } + i = ProcListSize; + ProcListSize += PROC_LIST_SEG; + ProcListVec = npv; + } + ProcListVec[i].proc_pid = pid; + if (ProcListVec[i].proc_task != NULL) + free(ProcListVec[i].proc_task); + ProcListVec[i].proc_task = newstr(task); + ProcListVec[i].proc_type = type; + + /* if process adding itself, it's not a child */ + if (pid != getpid()) + CurChildren++; +} + /* +** PROC_LIST_SET -- set pid task in process list +** +** Parameters: +** pid -- pid to set +** task -- task of pid +** +** Returns: +** none. +*/ + +void +proc_list_set(pid, task) + pid_t pid; + char *task; +{ + int i; + + for (i = 0; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == pid) + { + if (ProcListVec[i].proc_task != NULL) + free(ProcListVec[i].proc_task); + ProcListVec[i].proc_task = newstr(task); + break; + } + } +} + /* +** PROC_LIST_DROP -- drop pid from process list +** +** Parameters: +** pid -- pid to drop +** +** Returns: +** type of process +*/ + +int +proc_list_drop(pid) + pid_t pid; +{ + int i; + int type = PROC_NONE; + + for (i = 0; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == pid) + { + ProcListVec[i].proc_pid = NO_PID; + type = ProcListVec[i].proc_type; + break; + } + } + if (CurChildren > 0) + CurChildren--; + return type; +} + /* +** PROC_LIST_CLEAR -- clear the process list +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +proc_list_clear() +{ + int i; + + /* start from 1 since 0 is the daemon itself */ + for (i = 1; i < ProcListSize; i++) + { + ProcListVec[i].proc_pid = NO_PID; + } + CurChildren = 0; +} + /* +** PROC_LIST_PROBE -- probe processes in the list to see if they still exist +** +** Parameters: +** none +** +** Returns: +** none +*/ + +void +proc_list_probe() +{ + int i; + + /* start from 1 since 0 is the daemon itself */ + for (i = 1; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == NO_PID) + continue; + if (kill(ProcListVec[i].proc_pid, 0) < 0) + { + if (LogLevel > 3) + sm_syslog(LOG_DEBUG, CurEnv->e_id, + "proc_list_probe: lost pid %d", + (int) ProcListVec[i].proc_pid); + ProcListVec[i].proc_pid = NO_PID; + CurChildren--; + } + } + if (CurChildren < 0) + CurChildren = 0; +} + /* +** PROC_LIST_DISPLAY -- display the process list +** +** Parameters: +** out -- output file pointer +** +** Returns: +** none. +*/ + +void +proc_list_display(out) + FILE *out; +{ + int i; + + for (i = 0; i < ProcListSize; i++) + { + if (ProcListVec[i].proc_pid == NO_PID) + continue; + + fprintf(out, "%d %s%s\n", (int) ProcListVec[i].proc_pid, + ProcListVec[i].proc_task != NULL ? + ProcListVec[i].proc_task : "(unknown)", + (OpMode == MD_SMTP || + OpMode == MD_DAEMON || + OpMode == MD_ARPAFTP) ? "\r" : ""); + } +} + /* +** SM_STRCASECMP -- 8-bit clean version of strcasecmp +** +** Thank you, vendors, for making this all necessary. +*/ + +/* + * 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[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93"; +#endif /* defined(LIBC_SCCS) && !defined(lint) */ + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static const u_char charmap[] = { + 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, + 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, + 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, + 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, + 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, + 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, + 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, + 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, + 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, + 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, + 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, + 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, + 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, + 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, + 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, + 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, + 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, + 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, + 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, + 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, + 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, + 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, + 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, + 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, + 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, + 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, + 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, + 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, + 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, +}; + +int +sm_strcasecmp(s1, s2) + const char *s1, *s2; +{ + register const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + while (cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return 0; + return (cm[*us1] - cm[*--us2]); +} + +int +sm_strncasecmp(s1, s2, n) + const char *s1, *s2; + register size_t n; +{ + if (n != 0) { + register const u_char *cm = charmap, + *us1 = (const u_char *)s1, + *us2 = (const u_char *)s2; + + do { + if (cm[*us1] != cm[*us2++]) + return (cm[*us1] - cm[*--us2]); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return 0; +} diff --git a/gnu/usr.sbin/sendmail/sendmail/version.c b/gnu/usr.sbin/sendmail/sendmail/version.c new file mode 100644 index 00000000000..dd81833b7e0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/sendmail/version.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: version.c,v 8.36 2000/03/06 19:01:09 gshapiro Exp $"; +#endif /* ! lint */ + +char Version[] = "8.10.0"; diff --git a/gnu/usr.sbin/sendmail/smrsh/Build b/gnu/usr.sbin/sendmail/smrsh/Build new file mode 100644 index 00000000000..4c3f2ebdb64 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.4 1999/03/02 02:34:57 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/smrsh/Makefile b/gnu/usr.sbin/sendmail/smrsh/Makefile new file mode 100644 index 00000000000..e9597b4f0a5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.5 1999/09/23 22:36:43 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/smrsh/Makefile.m4 b/gnu/usr.sbin/sendmail/smrsh/Makefile.m4 new file mode 100644 index 00000000000..2174431577a --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/Makefile.m4 @@ -0,0 +1,15 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +PREPENDDEF(`confENVDEF', `confMAPDEF') + +bldPRODUCT_START(`executable', `smrsh') +define(`bldINSTALL_DIR', `E') +define(`bldSOURCES', `smrsh.c ') +bldPUSH_SMLIB(`smutil') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `smrsh') +define(`bldSOURCES', `smrsh.8') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/smrsh/README b/gnu/usr.sbin/sendmail/smrsh/README new file mode 100644 index 00000000000..7f0605b53b2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/README @@ -0,0 +1,156 @@ + +README smrsh - sendmail restricted shell. + +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. + +smrsh should build on most systems with the enclosed Build script: + + host.domain% sh Build + +To compile smrsh.c by hand, 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 + or + host.domain% sh Build LDOPTS=-Bstatic + +With gcc, the GNU C compiler, use the -static option. + + host.domain% cc -static -o smrsh smrsh.c + or + host.domain% sh Build LDOPTS=-static + + + +As root, install smrsh in /usr/libexec. Using the Build script: + + host.domain# sh Build install + +For manual installation: install smrsh in the /usr/libexec +directory, with mode 511. + + host.domain# mv smrsh /usr/libexec + host.domain# chmod 511 /usr/libexec/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/mail/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/libexec/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/libexec/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/libexec/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# cat /var/run/sendmail.pid + 130 + /usr/sbin/sendmail -bd -q30m + host.domain# /bin/kill -15 130 + host.domain# /usr/sbin/sendmail -bd -q30m + + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:42 $ diff --git a/gnu/usr.sbin/sendmail/smrsh/smrsh.0 b/gnu/usr.sbin/sendmail/smrsh/smrsh.0 new file mode 100644 index 00000000000..43273cf76a5 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/smrsh.0 @@ -0,0 +1,66 @@ + + + +SMRSH(8) SMRSH(8) + + +NNAAMMEE + smrsh - restricted shell for sendmail + +SSYYNNOOPPSSIISS + ssmmrrsshh --cc command + +DDEESSCCRRIIPPTTIIOONN + The _s_m_r_s_h program is intended as a replacement for _s_h for + use in the ``prog'' mailer in _s_e_n_d_m_a_i_l(8) configuration + files. It sharply limits the commands that can be run + using the ``|program'' syntax of _s_e_n_d_m_a_i_l 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, _s_m_r_s_h lim- + its the set of programs that he or she can execute. + + Briefly, _s_m_r_s_h limits programs to be in the directory + /usr/adm/sm.bin, allowing the system administrator to + choose the set of acceptable commands, and to the shell + builtin commands ``exec'', ``exit'', and ``echo''. It + also rejects any commands with the characters ``', `<', + `>', `;', `$', `(', `)', `\r' (carriage return), or `\n' + (newline) on the command line to prevent ``end run'' + attacks. It allows ``||'' and ``&&'' to enable commands + like: ``"|exec /usr/local/bin/procmail -f- /etc/procmail- + rcs/user || exit 75"'' + + 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''. + + System administrators should be conservative about popu- + lating /usr/adm/sm.bin. Reasonable additions are _v_a_c_a_- + _t_i_o_n(1), _p_r_o_c_m_a_i_l(1), and the like. No matter how brow- + beaten you may be, never include any shell or shell-like + program (such as _p_e_r_l(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. + +CCOOMMPPIILLAATTIIOONN + Compilation should be trivial on most systems. You may + need to use -DPATH=\"_p_a_t_h\" to adjust the default search + path (defaults to ``/bin:/usr/bin:/usr/ucb'') and/or + -DCMDBIN=\"_d_i_r\" to change the default program directory + (defaults to ``/usr/adm/sm.bin''). + +FFIILLEESS + /usr/adm/sm.bin - directory for restricted programs + +SSEEEE AALLSSOO + sendmail(8) + + + + + 11/02/93 1 + + diff --git a/gnu/usr.sbin/sendmail/smrsh/smrsh.8 b/gnu/usr.sbin/sendmail/smrsh/smrsh.8 new file mode 100644 index 00000000000..968b135aaa1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/smrsh.8 @@ -0,0 +1,87 @@ +.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1993 Eric P. Allman. All rights reserved. +.\" Copyright (c) 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: smrsh.8,v 8.11 1999/06/09 16:51:07 ca Exp $ +.\" +.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, +and to the shell builtin commands ``exec'', ``exit'', and ``echo''. +It also rejects any commands with the characters +`\`', `<', `>', `;', `$', `(', `)', `\er' (carriage return), +or `\en' (newline) +on the command line to prevent ``end run'' attacks. +It allows ``||'' and ``&&'' to enable commands like: +``"|exec /usr/local/bin/procmail -f- /etc/procmailrcs/user || exit 75"'' +.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/gnu/usr.sbin/sendmail/smrsh/smrsh.c b/gnu/usr.sbin/sendmail/smrsh/smrsh.c new file mode 100644 index 00000000000..2dea853e788 --- /dev/null +++ b/gnu/usr.sbin/sendmail/smrsh/smrsh.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1993 Eric P. Allman. All rights reserved. + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1993 Eric P. Allman. All rights reserved.\n\ + Copyright (c) 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: smrsh.c,v 8.28 1999/10/26 16:11:32 ca Exp $"; +#endif /* ! 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 +** The following characters are sometimes illegal: +** | & +** 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 +#include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK +#endif /* EX_OK */ +#include +#include +#include + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif /* ! TRUE */ + +/* directory in which all commands must reside */ +#ifndef CMDDIR +# define CMDDIR "/usr/adm/sm.bin" +#endif /* ! CMDDIR */ + +/* characters disallowed in the shell "-c" argument */ +#define SPECIALS "<|>^();&`$\r\n" + +/* default search path */ +#ifndef PATH +# define PATH "/bin:/usr/bin:/usr/ucb" +#endif /* ! PATH */ + +#ifndef __P +# include "sendmail/cdefs.h" +#endif /* ! __P */ + +extern size_t strlcpy __P((char *, const char *, size_t)); +extern size_t strlcat __P((char *, const char *, size_t)); + +char newcmdbuf[1000]; +char *prg, *par; + +/* +** ADDCMD -- add a string to newcmdbuf, check for overflow +** +** Parameters: +** s -- string to add +** cmd -- it's a command: prepend CMDDIR/ +** len -- length of string to add +** +** Side Effects: +** changes newcmdbuf or exits with a failure. +** +*/ + +void +addcmd(s, cmd, len) + char *s; + int cmd; + int len; +{ + if (s == NULL || *s == '\0') + return; + + if (sizeof newcmdbuf - strlen(newcmdbuf) <= + len + (cmd ? (strlen(CMDDIR) + 1) : 0)) + { + fprintf(stderr, "%s: command too long: %s\n", prg, par); +#ifndef DEBUG + syslog(LOG_WARNING, "command too long: %.40s", par); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + if (cmd) + { + (void) strlcat(newcmdbuf, CMDDIR, sizeof newcmdbuf); + (void) strlcat(newcmdbuf, "/", sizeof newcmdbuf); + } + (void) strlcat(newcmdbuf, s, sizeof newcmdbuf); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + register char *p; + register char *q; + register char *r; + register char *cmd; + int i; + int isexec; + int save_errno; + char *newenv[2]; + char cmdbuf[1000]; + char pathbuf[1000]; + char specialbuf[32]; + +#ifndef DEBUG +# ifndef LOG_MAIL + openlog("smrsh", 0); +# else /* ! LOG_MAIL */ + openlog("smrsh", LOG_ODELAY|LOG_CONS, LOG_MAIL); +# endif /* ! LOG_MAIL */ +#endif /* ! DEBUG */ + + (void) strlcpy(pathbuf, "PATH=", sizeof pathbuf); + (void) strlcat(pathbuf, PATH, sizeof pathbuf); + newenv[0] = pathbuf; + newenv[1] = NULL; + + /* + ** Do basic argv usage checking + */ + + prg = argv[0]; + par = argv[2]; + + if (argc != 3 || strcmp(argv[1], "-c") != 0) + { + fprintf(stderr, "Usage: %s -c command\n", prg); +#ifndef DEBUG + syslog(LOG_ERR, "usage"); +#endif /* ! DEBUG */ + 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. + */ + + if (strlen(SPECIALS) * 2 >= sizeof specialbuf) + { +#ifndef DEBUG + syslog(LOG_ERR, "too many specials: %.40s", SPECIALS); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + (void) strlcpy(specialbuf, SPECIALS, sizeof specialbuf); + for (p = specialbuf; *p != '\0'; p++) + *p |= '\200'; + (void) strlcat(specialbuf, SPECIALS, sizeof specialbuf); + + /* + ** Do a quick sanity check on command line length. + */ + + i = strlen(par); + if (i > (sizeof newcmdbuf - sizeof CMDDIR - 2)) + { + fprintf(stderr, "%s: command too long: %s\n", prg, par); +#ifndef DEBUG + syslog(LOG_WARNING, "command too long: %.40s", par); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + + q = par; + newcmdbuf[0] = '\0'; + isexec = FALSE; + + while (*q) + { + /* + ** Strip off a leading pathname on the command name. For + ** example, change /usr/ucb/vacation to vacation. + */ + + /* strip leading spaces */ + while (*q != '\0' && isascii(*q) && isspace(*q)) + q++; + if (*q == '\0') + { + if (isexec) + { + fprintf(stderr, "%s: missing command to exec\n", + prg); +#ifndef DEBUG + syslog(LOG_CRIT, "uid %d: missing command to exec", getuid()); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + break; + } + + /* 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 */ + + /* allow a few shell builtins */ + if (strcmp(q, "exec") == 0 && p != NULL) + { + addcmd("exec ", FALSE, strlen("exec ")); + /* test _next_ arg */ + q = ++p; + isexec = TRUE; + continue; + } + else if (strcmp(q, "exit") == 0 || strcmp(q, "echo") == 0) + { + addcmd(cmd, FALSE, strlen(cmd)); + /* test following chars */ + } + else + { + /* + ** Check to see if the command name is legal. + */ + (void) strlcpy(cmdbuf, CMDDIR, sizeof cmdbuf); + (void) strlcat(cmdbuf, "/", sizeof cmdbuf); + (void) strlcat(cmdbuf, cmd, sizeof cmdbuf); +#ifdef DEBUG + printf("Trying %s\n", cmdbuf); +#endif /* DEBUG */ + if (access(cmdbuf, X_OK) < 0) + { + /* oops.... crack attack possiblity */ + fprintf(stderr, + "%s: %s not available for sendmail programs\n", + prg, cmd); + if (p != NULL) + *p = ' '; +#ifndef DEBUG + syslog(LOG_CRIT, "uid %d: attempt to use %s", + getuid(), cmd); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + + /* + ** Create the actual shell input. + */ + + addcmd(cmd, TRUE, strlen(cmd)); + } + isexec = FALSE; + + if (p != NULL) + *p = ' '; + else + break; + + r = strpbrk(p, specialbuf); + if (r == NULL) { + addcmd(p, FALSE, strlen(p)); + break; + } +#if ALLOWSEMI + if (*r == ';') { + addcmd(p, FALSE, r - p + 1); + q = r + 1; + continue; + } +#endif /* ALLOWSEMI */ + if ((*r == '&' && *(r + 1) == '&') || + (*r == '|' && *(r + 1) == '|')) + { + addcmd(p, FALSE, r - p + 2); + q = r + 2; + continue; + } + + fprintf(stderr, "%s: cannot use %c in command\n", prg, *r); +#ifndef DEBUG + syslog(LOG_CRIT, "uid %d: attempt to use %c in command: %s", + getuid(), *r, par); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } /* end of while *q */ + if (isexec) + { + fprintf(stderr, "%s: missing command to exec\n", prg); +#ifndef DEBUG + syslog(LOG_CRIT, "uid %d: missing command to exec", getuid()); +#endif /* ! DEBUG */ + exit(EX_UNAVAILABLE); + } + /* make sure we created something */ + if (newcmdbuf[0] == '\0') + { + fprintf(stderr, "Usage: %s -c command\n", prg); +#ifndef DEBUG + syslog(LOG_ERR, "usage"); +#endif /* ! DEBUG */ + exit(EX_USAGE); + } + + /* + ** Now invoke the shell + */ + +#ifdef DEBUG + printf("%s\n", newcmdbuf); +#endif /* DEBUG */ + (void) execle("/bin/sh", "/bin/sh", "-c", newcmdbuf, NULL, newenv); + save_errno = errno; +#ifndef DEBUG + syslog(LOG_CRIT, "Cannot exec /bin/sh: %m"); +#endif /* ! DEBUG */ + errno = save_errno; + perror("/bin/sh"); + exit(EX_OSFILE); + /* NOTREACHED */ + return EX_OSFILE; +} diff --git a/gnu/usr.sbin/sendmail/test/Results b/gnu/usr.sbin/sendmail/test/Results new file mode 100644 index 00000000000..98001ed289e --- /dev/null +++ b/gnu/usr.sbin/sendmail/test/Results @@ -0,0 +1,160 @@ +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 + +FreeBSD 2.1-sta OK 96.04.14 Jaye Mathisen + +Ultrix 4.2A OK 93.07.19 eric +Ultrix 4.3A OK 93.07.19 Allan Johannesen +Ultrix 4.5 OK 96.09.18 Gregory Neil Shapiro + +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 +Solaris 2.3 FAIL 95.11.22 Scott J. Kramer +Solaris 2.5 OK 96.02.29 Carson Gaspar +Solaris 2.5.1 OK 96.11.29 Gregory Neil Shapiro + +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) +OSF/1 3.2D OK 96.09.18 Gregory Neil Shapiro +OSF/1 4.0 OK 96.09.18 Gregory Neil Shapiro + +CxOS 11.5 OK 96.07.08 Eric Schnoebelen +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 +AIX 3.2.4 FAIL 93.10.07 David J. N. Begley +AIX 3.2.5 FAIL 94.05.17 Steve Bauer +AIX 4.1 FAIL 96.10.21 Hakan Lindholm +AIX 4.2 OK 96.10.16 Steve Bauer + +IRIX 4.0.4 OK 93.09.25 Robert Elz +IRIX 5.2 OK 94.12.06 Mark Andrews +IRIX 5.3 OK 94.12.06 Mark Andrews +IRIX 6.2 OK 96.09.16 Kari E. Hurtta +IRIX 6.3 OK 97.02.10 Mark Andrews + +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 + +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 +Linux 1.0 OK 94.03.19 Shayne Smith +Linux 1.2.13 OK 95.11.02 Sven Neuhaus +Linux 2.0.17 OK 96.09.03 Horst von Brand +Linux 2.1.109 OK 98.07.21 John Kennedy + +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 + + + +The following are results of running t_seteuid on various architectures. + +OPSYS VERSION STATUS DATE TESTER/NOTES +===== ======= ====== ==== ============ + +Solaris 2.3 OK 95.11.22 Scott J. Kramer +Solaris 2.4 OK 95.09.22 Thomas 'Mike' Michlmayr +Solaris 2.5 OK 96.02.29 Carson Gaspar +Solaris 2.5.1 OK 96.11.29 Gregory Neil Shapiro + +Linux 1.2.13 FAIL 95.11.02 Sven Neuhaus +Linux 2.0.17 FAIL 96.09.03 Horst von Brand +Linux 2.1.109 FAIL 98.07.21 John Kennedy + +AIX 4.1 OK 96.10.21 Hakan Lindholm + +IRIX 5.2 OK 95.12.01 Mark Andrews +IRIX 5.3 OK 95.12.01 Mark Andrews +IRIX 6.2 OK 96.09.16 Kari E. Hurtta +IRIX 6.3 OK 97.02.10 Mark Andrews + +FreeBSD 2.1-sta OK 96.04.14 Jaye Mathisen + +Ultrix 4.5 FAIL 96.09.18 Gregory Neil Shapiro + +OSF/1 3.2D OK 96.09.18 Gregory Neil Shapiro +OSF/1 4.0 OK 96.09.18 Gregory Neil Shapiro + +CxOS 11.5 FAIL 96.07.08 Eric Schnoebelen + + +The following are the results of running t_pathconf.c. Safe means that +the underlying filesystem (in NFS, the filesystem on the server) does not +permit regular (non-root) users to chown their files to another user. +Unsafe means that they can. Typically, BSD-based systems do not permit +giveaway and System V-based systems do. However, some systems (e.g., +Solaris) can set this on a per-system or per-filesystem basis. Entries +are the return value of pathconf, the errno value, and a * if chown +disagreed with the result of the pathconf call, and a ? if the test has +not been run. A mark of [R] means that the local filesystem has +chown set to be restricted, [U] means that it is set to be unrestricted. + + Safe Filesystem Unsafe Filesystem +SYSTEM LOCAL NFS-V2 NFS-V3 NFS-V2 NFS-V3 + +SunOS 4.1.3_U1 1/0 -1/EINVAL* n/a -1/EINVAL? n/a +SunOS 4.1.4 1/0 -1/EINVAL* n/a -1/EINVAL n/a + +AIX 3.2 0/0 0/0 + +Solaris 2.4 1/0 -1/EINVAL* +Solaris 2.5 1/0 -1/EINVAL* 1/0 0/0? +Solaris 2.5.1 1/0 -1/EINVAL* 0/0 + +DEC OSF1 3.0 0/0 0/0 +DEC OSF1 3.2D-2 0/0 0/0 0/0 +DEC OSF1 4.0A 0/0 0/0 0/0 +DEC OSF 4.0B 0/0 0/0 0/0 + +Ultrix 4.3 0/0 0/0 n/a n/a +Ultrix 4.5 1/0 1/0 + +HP-UX 9.05 -1/0 -1/EOPNOTSUPP* -1/EOPNOTSUPP +HP-UX 9.05[R] 1/0 -1/EOPNOTSUPP* -1/EOPNOTSUPP* +HP-UX 10.10 -1/0 -1/EOPNOTSUPP* -1/EOPNOTSUPP +HP-UX 10.20 -1/EOPNOTSUPP? -1/EOPNOTSUPP? +HP-UX 10.30 -1/0 -1/EOPNOTSUPP -1/EOPNOTSUPP + +BSD/OS 2.1 1/0 + +FreeBSD 2.1.7 1/0 -1/EINVAL* -1/EINVAL + +Irix 5.3 -1/0* -1/0 +Irix 6.2 1/0 -1/0 0/0* +Irix 6.2 -1/0 -1/0 +Irix 6.3 R10000 -1/0 -1/0 0/0* + +A/UX 3.1.1 1/0 + +DomainOS [R] -1/0* +DomainOS [U] -1/0 + +NCR MP-RAS 2 -1/0 +NCR MP-RAS 3 -1/0 + +Linux 2.0.27 1/0 1/0 + +$Revision: 1.1.1.1 $, Last updated $Date: 2000/04/02 19:05:49 $ diff --git a/gnu/usr.sbin/sendmail/test/t_exclopen.c b/gnu/usr.sbin/sendmail/test/t_exclopen.c new file mode 100644 index 00000000000..5dc4000c4e2 --- /dev/null +++ b/gnu/usr.sbin/sendmail/test/t_exclopen.c @@ -0,0 +1,103 @@ +/* +** This program tests your system to see if you have the lovely +** security-defeating semantics that an open with O_CREAT|O_EXCL +** set will successfully open a file named by a symbolic link that +** points to a non-existent file. Sadly, Posix is mute on what +** should happen in this situation. +** +** Results to date: +** AIX 3.2 OK +** BSD family OK +** BSD/OS 2.1 OK +** FreeBSD 2.1 OK +** DEC OSF/1 3.0 OK +** HP-UX 9.04 FAIL +** HP-UX 9.05 FAIL +** HP-UX 9.07 OK +** HP-UX 10.01 OK +** HP-UX 10.10 OK +** HP-UX 10.20 OK +** Irix 5.3 OK +** Irix 6.2 OK +** Irix 6.3 OK +** Irix 6.4 OK +** Linux OK +** NeXT 2.1 OK +** Solaris 2.x OK +** SunOS 4.x OK +** Ultrix 4.3 OK +*/ + +#include +#include +#include +#include +#include +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: t_exclopen.c,v 8.5 1999/08/28 00:25:28 gshapiro Exp $"; +#endif /* ! lint */ + +static char Attacker[128]; +static char Attackee[128]; + +static void +bail(status) + int status; +{ + (void) unlink(Attacker); + (void) unlink(Attackee); + exit(status); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + struct stat st; + + sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL)); + sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL)); + + if (symlink(Attackee, Attacker) < 0) + { + printf("Could not create %s->%s symlink: %d\n", + Attacker, Attackee, errno); + bail(1); + } + (void) unlink(Attackee); + if (stat(Attackee, &st) >= 0) + { + printf("%s already exists -- remove and try again.\n", + Attackee); + bail(1); + } + if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0) + { + int save_errno = errno; + + if (stat(Attackee, &st) >= 0) + { + printf("Weird. Open failed but %s was created anyhow (errno = %d)\n", + Attackee, save_errno); + bail(1); + } + printf("Good show! Exclusive open works properly with symbolic links (errno = %d).\n", + save_errno); + bail(0); + } + if (stat(Attackee, &st) < 0) + { + printf("Weird. Open succeeded but %s was not created\n", + Attackee); + bail(2); + } + printf("Bad news: you can do an exclusive open through a symbolic link\n"); + printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n"); + bail(1); + + /* NOTREACHED */ + exit(0); +} diff --git a/gnu/usr.sbin/sendmail/test/t_pathconf.c b/gnu/usr.sbin/sendmail/test/t_pathconf.c new file mode 100644 index 00000000000..dbe8f0a207a --- /dev/null +++ b/gnu/usr.sbin/sendmail/test/t_pathconf.c @@ -0,0 +1,74 @@ +/* +** The following test program tries the pathconf(2) routine. It should +** be run in a non-NFS-mounted directory (e.g., /tmp) and on remote (NFS) +** mounted directories running both NFS-v2 and NFS-v3 from systems that +** both do and do not permit file giveaway. +*/ + +#include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: t_pathconf.c,v 8.5 1999/08/28 00:25:28 gshapiro Exp $"; +#endif /* ! lint */ + +int +main(argc, argv) + int argc; + char **argv; +{ + int fd; + int i; + char tbuf[100]; + extern int errno; + + if (geteuid() == 0) + { + printf("*** Run me as a non-root user! ***\n"); + exit(EX_USAGE); + } + + strcpy(tbuf, "TXXXXXX"); + fd = mkstemp(tbuf); + if (fd < 0) + { + printf("*** Could not create test file %s\n", tbuf); + exit(EX_CANTCREAT); + } + errno = 0; + i = pathconf(".", _PC_CHOWN_RESTRICTED); + printf("pathconf(.) returns %2d, errno = %d\n", i, errno); + errno = 0; + i = pathconf(tbuf, _PC_CHOWN_RESTRICTED); + printf("pathconf(%s) returns %2d, errno = %d\n", tbuf, i, errno); + errno = 0; + i = fpathconf(fd, _PC_CHOWN_RESTRICTED); + printf("fpathconf(%s) returns %2d, errno = %d\n", tbuf, i, errno); + if (errno == 0 && i >= 0) + { + /* so it claims that it doesn't work -- try anyhow */ + printf(" fpathconf claims that chown is safe "); + if (fchown(fd, 1, 1) >= 0) + printf("*** but fchown works anyhow! ***\n"); + else + printf("and fchown agrees\n"); + } + else + { + /* well, let's see what really happens */ + printf(" fpathconf claims that chown is not safe "); + if (fchown(fd, 1, 1) >= 0) + printf("as indeed it is not\n"); + else + printf("*** but in fact it is safe ***\n"); + } + (void) unlink(tbuf); + exit(EX_OK); +} diff --git a/gnu/usr.sbin/sendmail/test/t_seteuid.c b/gnu/usr.sbin/sendmail/test/t_seteuid.c new file mode 100644 index 00000000000..44fa5ba0de1 --- /dev/null +++ b/gnu/usr.sbin/sendmail/test/t_seteuid.c @@ -0,0 +1,129 @@ +/* +** 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 +#include +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: t_seteuid.c,v 8.4 1999/08/28 00:25:28 gshapiro Exp $"; +#endif /* ! lint */ + +#ifdef __hpux +# define seteuid(e) setresuid(-1, e, -1) +#endif /* __hpux */ + +static void +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()); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + 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); + } + + printf("\nIt is safe to define USESETEUID on this system\n"); + exit(0); +} diff --git a/gnu/usr.sbin/sendmail/test/t_setreuid.c b/gnu/usr.sbin/sendmail/test/t_setreuid.c new file mode 100644 index 00000000000..7d3f8485b47 --- /dev/null +++ b/gnu/usr.sbin/sendmail/test/t_setreuid.c @@ -0,0 +1,141 @@ +/* +** 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 +#include +#include + +#ifndef lint +static char id[] = "@(#)$Sendmail: t_setreuid.c,v 8.4 1999/08/28 00:25:28 gshapiro Exp $"; +#endif /* ! lint */ + +#ifdef __hpux +# define setreuid(r, e) setresuid(r, e, -1) +#endif /* __hpux */ + +static void +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()); +} + +int +main(argc, argv) + int argc; + char **argv; +{ + 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); + } + + printf("\nIt is safe to define HASSETREUID on this system\n"); + exit(0); +} diff --git a/gnu/usr.sbin/sendmail/vacation/Build b/gnu/usr.sbin/sendmail/vacation/Build new file mode 100644 index 00000000000..aca2894e9ec --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/Build @@ -0,0 +1,13 @@ +#!/bin/sh + +# Copyright (c) 1999 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# +# $Sendmail: Build,v 8.2 1999/03/02 02:35:21 peterh Exp $ + +exec ../devtools/bin/Build $* diff --git a/gnu/usr.sbin/sendmail/vacation/Makefile b/gnu/usr.sbin/sendmail/vacation/Makefile new file mode 100644 index 00000000000..b57df04a6ef --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/Makefile @@ -0,0 +1,17 @@ +# $Sendmail: Makefile,v 8.5 1999/09/23 22:36:45 ca Exp $ + +SHELL= /bin/sh +BUILD= ./Build +OPTIONS= $(CONFIG) $(FLAGS) + +all: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +clean: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ +install: FRC + $(SHELL) $(BUILD) $(OPTIONS) $@ + +fresh: FRC + $(SHELL) $(BUILD) $(OPTIONS) -c + +FRC: diff --git a/gnu/usr.sbin/sendmail/vacation/Makefile.m4 b/gnu/usr.sbin/sendmail/vacation/Makefile.m4 new file mode 100644 index 00000000000..71430eb2c1b --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/Makefile.m4 @@ -0,0 +1,19 @@ +include(confBUILDTOOLSDIR`/M4/switch.m4') + +# sendmail dir +SMSRCDIR= ifdef(`confSMSRCDIR', `confSMSRCDIR', `${SRCDIR}/sendmail') +PREPENDDEF(`confENVDEF', `confMAPDEF') +PREPENDDEF(`confINCDIRS', `-I${SMSRCDIR} ') + +bldPRODUCT_START(`executable', `vacation') +define(`bldSOURCES', `vacation.c ') +bldPUSH_SMLIB(`smutil') +bldPUSH_SMLIB(`smdb') +APPENDDEF(`confENVDEF', `-DNOT_SENDMAIL') +bldPRODUCT_END + +bldPRODUCT_START(`manpage', `vacation') +define(`bldSOURCES', `vacation.1') +bldPRODUCT_END + +bldFINISH diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.0 b/gnu/usr.sbin/sendmail/vacation/vacation.0 new file mode 100644 index 00000000000..857d4b92e34 --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/vacation.0 @@ -0,0 +1,132 @@ + + + +VACATION(1) VACATION(1) + + +NNAAMMEE + vvaaccaattiioonn - return ``I am not here'' indication + +SSYYNNOOPPSSIISS + vvaaccaattiioonn --ii [--rr _i_n_t_e_r_v_a_l] [--xx] vvaaccaattiioonn [--aa _a_l_i_a_s] [--ff + _d_a_t_a_b_a_s_e] [--mm _m_e_s_s_a_g_e] [--ss _a_d_d_r_e_s_s] [--zz] _l_o_g_i_n + +DDEESSCCRRIIPPTTIIOONN + VVaaccaattiioonn returns a message to the sender of a message + telling them that you are currently not reading your mail. + The intended use is in a _._f_o_r_w_a_r_d file. For example, your + _._f_o_r_w_a_r_d file might have: + + \eric, "|/usr/bin/vacation -a allman eric" + + which would send messages to you (assuming your login name + was eric) and reply to any messages for ``eric'' or ``all- + man''. + + Available options: + + --aa _a_l_i_a_s + Handle messages for in the same manner as those + received for the user's login name. + + --ff _f_i_l_e_n_a_m_e + Use _f_i_l_e_n_a_m_e as name of the database instead of + _~_/_._v_a_c_a_t_i_o_n_._d_b. Unless the _f_i_l_e_n_a_m_e starts with / + it is relative to ~. + + --ii Initialize the vacation database files. It should + be used before you modify your _._f_o_r_w_a_r_d file. + + --mm _f_i_l_e_n_a_m_e + Use _f_i_l_e_n_a_m_e as name of the file containing the + message to send instead of _~_/_._v_a_c_a_t_i_o_n_._m_s_g. Unless + the _f_i_l_e_n_a_m_e starts with / it is relative to ~. + + --rr _i_n_t_e_r_v_a_l + Set the reply interval to _i_n_t_e_r_v_a_l days. The + default is one week. An interval of ``0'' or + ``infinite'' (actually, any non-numeric character) + will never send more than one reply. + + --ss _a_d_d_r_e_s_s + Use _a_d_d_r_e_s_s instead of the sender address in the + _F_r_o_m line to determine the reply address. + + --xx reads an exclusion list from stdin (one address per + line). Mails coming from an address in this exclu- + sion list won't get a reply by vvaaccaattiioonn. It is + possible to exclude complete domains by specifying + ``@domain'' as element of the exclusion list. + + + + + $Date: 2000/04/02 19:05:58 $ 1 + + + + + +VACATION(1) VACATION(1) + + + --zz Set the sender of the vacation message to ``<>'' + instead of the user. This probably violates the + RFCs since vacation messages are not required by a + standards-track RFC to have a null reverse-path. + + No message will be sent unless _l_o_g_i_n (or an _a_l_i_a_s supplied + using the --aa option) is part of either the ``To:'' or + ``Cc:'' headers of the mail. No messages from + ``???-REQUEST'', ``Postmaster'', ``UUCP'', ``MAILER'', or + ``MAILER-DAEMON'' will be replied to (where these strings + are case insensitive) nor is a notification sent if a + ``Precedence: bulk'' or ``Precedence: junk'' line is + included in the mail headers. The people who have sent + you messages are maintained as a db(3) database in the + file _._v_a_c_a_t_i_o_n_._d_b in your home directory. + + VVaaccaattiioonn expects a file _._v_a_c_a_t_i_o_n_._m_s_g, in your home direc- + tory, containing a message to be sent back to each sender. + It should be an entire message (including headers). For + example, it might contain: + + From: eric@CS.Berkeley.EDU (Eric Allman) + Subject: I am on vacation + Delivered-By-The-Graces-Of: The Vacation program + Precedence: bulk + + I am on vacation until July 22. If you have something urgent, + please contact Keith Bostic . + --eric + + VVaaccaattiioonn reads the first line from the standard input for + a UNIX ``From'' line to determine the sender. Sendmail(8) + includes this ``From'' line automatically. + + Fatal errors, such as calling vvaaccaattiioonn with incorrect + arguments, or with non-existent _l_o_g_i_ns, are logged in the + system log file, using syslog(8). + +FFIILLEESS + ~/.vacation.db database file + + ~/.vacation.msg message to send + +SSEEEE AALLSSOO + sendmail(8), syslog(8) + +HHIISSTTOORRYY + The vvaaccaattiioonn command appeared in 4.3BSD. + + + + + + + + + + $Date: 2000/04/02 19:05:58 $ 2 + + diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.1 b/gnu/usr.sbin/sendmail/vacation/vacation.1 new file mode 100644 index 00000000000..506765cd2d0 --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/vacation.1 @@ -0,0 +1,194 @@ +.\" Copyright (c) 1999 Sendmail, Inc. and its suppliers. +.\" All rights reserved. +.\" Copyright (c) 1985, 1987, 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" +.\" By using this file, you agree to the terms and conditions set +.\" forth in the LICENSE file which can be found at the top level of +.\" the sendmail distribution. +.\" +.\" +.\" $Sendmail: vacation.1,v 8.9 1999/10/27 03:42:07 ca Exp $ +.\" +.TH VACATION 1 "$Date: 2000/04/02 19:05:58 $" +.SH NAME +.B vacation +\- return ``I am not here'' indication +.SH SYNOPSIS +.B vacation +.B \-i +.RB [ \-r +.IR interval ] +.RB [ \-x ] +.B vacation +.RB [ \-a +.IR alias ] +.RB [ \-f +.IR database ] +.RB [ \-m +.IR message ] +.RB [ \-s +.IR address ] +.RB [ \-z ] +.I login +.SH DESCRIPTION +.B Vacation +returns a message to the sender of a message telling them that you +are currently not reading your mail. The intended use is in a +.I .forward +file. For example, your +.I .forward +file might have: +.IP +\eeric, "|/usr/bin/vacation -a allman eric" +.PP +which would send messages to you (assuming your login name was eric) and +reply to any messages for +``eric'' +or +``allman''. +.PP +Available options: +.TP +.BI \-a " alias" +Handle messages for +.Ar alias +in the same manner as those received for the user's +login name. +.TP +.BI \-f " filename" +Use +.I filename +as name of the database instead of +.IR ~/.vacation.db . +Unless the +.I filename +starts with / it is relative to ~. +.TP +.B \-i +Initialize the vacation database files. It should be used +before you modify your +.I .forward +file. +.TP +.BI \-m " filename" +Use +.I filename +as name of the file containing the message to send instead of +.IR ~/.vacation.msg . +Unless the +.I filename +starts with / it is relative to ~. +.TP +.BI \-r " interval" +Set the reply interval to +.I interval +days. The default is one week. +An interval of ``0'' or +``infinite'' +(actually, any non-numeric character) will never send more than +one reply. +.TP +.BI \-s " address" +Use +.I address +instead of the sender address in the +.I From +line to determine the reply address. +.TP +.B \-x +reads an exclusion list from stdin (one address per line). +Mails coming from an address +in this exclusion list won't get a reply by +.BR vacation . +It is possible to exclude complete domains by specifying +``@domain'' +as element of the exclusion list. +.TP +.B \-z +Set the sender of the vacation message to +``<>'' +instead of the user. +This probably violates the RFCs since vacation messages are +not required by a standards-track RFC to have a null reverse-path. +.PP +No message will be sent unless +.I login +(or an +.I alias +supplied using the +.B \-a +option) is part of either the +``To:'' +or +``Cc:'' +headers of the mail. +No messages from +``???-REQUEST'', +``Postmaster'', +``UUCP'', +``MAILER'', +or +``MAILER-DAEMON'' +will be replied to (where these strings are +case insensitive) nor is a notification sent if a +``Precedence: bulk'' +or +``Precedence: junk'' +line is included in the mail headers. +The people who have sent you messages are maintained as a +db(3) +database in the file +.I .vacation.db +in your home directory. +.PP +.B Vacation +expects a file +.IR .vacation.msg , +in your home directory, containing a message to be sent back to each +sender. It should be an entire message (including headers). For +example, it might contain: +.IP +.nf +From: eric@CS.Berkeley.EDU (Eric Allman) +Subject: I am on vacation +Delivered-By-The-Graces-Of: The Vacation program +Precedence: bulk + +I am on vacation until July 22. If you have something urgent, +please contact Keith Bostic . +--eric +.fi +.PP +.B Vacation +reads the first line from the standard input for a +UNIX +``From'' +line to determine the sender. +Sendmail(8) +includes this +``From'' +line automatically. +.PP +Fatal errors, such as calling +.B vacation +with incorrect arguments, or with non-existent +.IR login s, +are logged in the system log file, using +syslog(8). +.SH FILES +.TP 1.8i +~/.vacation.db +database file +.TP +~/.vacation.msg +message to send +.SH SEE ALSO +sendmail(8), +syslog(8) +.SH HISTORY +The +.B vacation +command appeared in +4.3BSD. diff --git a/gnu/usr.sbin/sendmail/vacation/vacation.c b/gnu/usr.sbin/sendmail/vacation/vacation.c new file mode 100644 index 00000000000..8602d801f08 --- /dev/null +++ b/gnu/usr.sbin/sendmail/vacation/vacation.c @@ -0,0 +1,828 @@ +/* + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1983, 1987, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 1983 Eric P. Allman. All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ + All rights reserved.\n\ + Copyright (c) 1983, 1987, 1993\n\ + The Regents of the University of California. All rights reserved.\n\ + Copyright (c) 1983 Eric P. Allman. All rights reserved.\n"; +#endif /* ! lint */ + +#ifndef lint +static char id[] = "@(#)$Sendmail: vacation.c,v 8.63 2000/02/01 05:50:00 gshapiro Exp $"; +#endif /* ! lint */ + +#include +#include +#include +#include +#include +#ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +#endif /* EX_OK */ +#include + +#if defined(sun) && !defined(BSD) && !defined(SOLARIS) +# include +#endif /* sun && ! BSD && ! SOLARIS */ + +#include "sendmail/sendmail.h" +#include "libsmdb/smdb.h" + +#if defined(__hpux) && !defined(HPUX11) +# undef syslog /* Undo hard_syslog conf.h change */ +#endif /* defined(__hpux) && !defined(HPUX11) */ + +#ifndef _PATH_SENDMAIL +# define _PATH_SENDMAIL "/usr/lib/sendmail" +#endif /* ! _PATH_SENDMAIL */ + +#define ONLY_ONCE ((time_t) 0) /* send at most one reply */ +#define INTERVAL_UNDEF ((time_t) (-1)) /* no value given */ + +uid_t RealUid; +gid_t RealGid; +char *RealUserName; +uid_t RunAsUid; +uid_t RunAsGid; +char *RunAsUserName; +int Verbose = 2; +bool DontInitGroups = FALSE; +uid_t TrustedUid = 0; +BITMAP256 DontBlameSendmail; + +/* +** VACATION -- return a message to the sender when on vacation. +** +** This program is invoked as a message receiver. It returns a +** message specified by the user to whomever sent the mail, taking +** care not to return a message too often to prevent "I am on +** vacation" loops. +*/ + +#define VDB ".vacation" /* vacation database */ +#define VMSG ".vacation.msg" /* vacation message */ +#define SECSPERDAY (60 * 60 * 24) +#define DAYSPERWEEK 7 + +#ifndef TRUE +# define TRUE 1 +# define FALSE 0 +#endif /* ! TRUE */ + +#ifndef __P +# ifdef __STDC__ +# define __P(protos) protos +# else /* __STDC__ */ +# define __P(protos) () +# define const +# endif /* __STDC__ */ +#endif /* ! __P */ + +typedef struct alias +{ + char *name; + struct alias *next; +} ALIAS; + +ALIAS *Names = NULL; + +SMDB_DATABASE *Db; + +char From[MAXLINE]; + +int +main(argc, argv) + int argc; + char **argv; +{ + bool iflag, emptysender, exclude; + int ch; + int result; + time_t interval; + struct passwd *pw; + ALIAS *cur; + char *dbfilename = VDB; + char *msgfilename = VMSG; + SMDB_USER_INFO user_info; + static char rnamebuf[MAXNAME]; + extern int optind, opterr; + extern char *optarg; + extern void usage __P((void)); + extern void setinterval __P((time_t)); + extern void readheaders __P((void)); + extern bool recent __P((void)); + extern void setreply __P((char *, time_t)); + extern void sendmessage __P((char *, char *, bool)); + extern void xclude __P((FILE *)); + + /* Vars needed to link with smutil */ + clrbitmap(DontBlameSendmail); + RunAsUid = RealUid = getuid(); + RunAsGid = RealGid = getgid(); + pw = getpwuid(RealUid); + if (pw != NULL) + { + if (strlen(pw->pw_name) > MAXNAME - 1) + pw->pw_name[MAXNAME] = '\0'; + snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); + } + else + snprintf(rnamebuf, sizeof rnamebuf, + "Unknown UID %d", (int) RealUid); + RunAsUserName = RealUserName = rnamebuf; + +#ifdef LOG_MAIL + openlog("vacation", LOG_PID, LOG_MAIL); +#else /* LOG_MAIL */ + openlog("vacation", LOG_PID); +#endif /* LOG_MAIL */ + + opterr = 0; + iflag = FALSE; + emptysender = FALSE; + exclude = FALSE; + interval = INTERVAL_UNDEF; + *From = '\0'; + while ((ch = getopt(argc, argv, "a:f:Iim:r:s:xz")) != -1) + { + switch((char)ch) + { + case 'a': /* alias */ + cur = (ALIAS *)malloc((u_int)sizeof(ALIAS)); + if (cur == NULL) + { + syslog(LOG_NOTICE, + "vacation: can't allocate memory for alias %s.\n", + optarg); + break; + } + cur->name = optarg; + cur->next = Names; + Names = cur; + break; + + case 'f': /* alternate database */ + dbfilename = optarg; + break; + + case 'I': /* backward compatible */ + case 'i': /* init the database */ + iflag = TRUE; + break; + + case 'm': /* alternate message file */ + msgfilename = optarg; + break; + + case 'r': + if (isascii(*optarg) && isdigit(*optarg)) + { + interval = atol(optarg) * SECSPERDAY; + if (interval < 0) + usage(); + } + else + interval = ONLY_ONCE; + break; + + case 's': /* alternate sender name */ + (void) strlcpy(From, optarg, sizeof From); + break; + + case 't': /* SunOS: -t1d (default expire) */ + break; + + case 'x': + exclude = TRUE; + break; + + case 'z': + emptysender = TRUE; + break; + + case '?': + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + if (argc != 1) + { + if (!iflag && !exclude) + usage(); + if ((pw = getpwuid(getuid())) == NULL) + { + syslog(LOG_ERR, + "vacation: no such user uid %u.\n", getuid()); + exit(EX_NOUSER); + } + } + else if ((pw = getpwnam(*argv)) == NULL) + { + syslog(LOG_ERR, "vacation: no such user %s.\n", *argv); + exit(EX_NOUSER); + } + if (chdir(pw->pw_dir) != 0) + { + syslog(LOG_NOTICE, + "vacation: no such directory %s.\n", pw->pw_dir); + exit(EX_NOINPUT); + } + user_info.smdbu_id = pw->pw_uid; + user_info.smdbu_group_id = pw->pw_gid; + (void) strlcpy(user_info.smdbu_name, pw->pw_name, + SMDB_MAX_USER_NAME_LEN); + + result = smdb_open_database(&Db, dbfilename, + O_CREAT|O_RDWR | (iflag ? O_TRUNC : 0), + S_IRUSR|S_IWUSR, SFF_CREAT, + SMDB_TYPE_DEFAULT, &user_info, NULL); + if (result != SMDBE_OK) + { + syslog(LOG_NOTICE, "vacation: %s: %s\n", dbfilename, + errstring(result)); + exit(EX_DATAERR); + } + + if (interval != INTERVAL_UNDEF) + setinterval(interval); + + if (iflag) + { + result = Db->smdb_close(Db); + if (!exclude) + exit(EX_OK); + } + + if (exclude) + { + xclude(stdin); + result = Db->smdb_close(Db); + exit(EX_OK); + } + + if ((cur = (ALIAS *)malloc((u_int)sizeof(ALIAS))) == NULL) + { + syslog(LOG_NOTICE, + "vacation: can't allocate memory for username.\n"); + exit(EX_OSERR); + } + cur->name = pw->pw_name; + cur->next = Names; + Names = cur; + + readheaders(); + if (!recent()) + { + time_t now; + + (void) time(&now); + setreply(From, now); + result = Db->smdb_close(Db); + sendmessage(pw->pw_name, msgfilename, emptysender); + } + else + result = Db->smdb_close(Db); + exit(EX_OK); + /* NOTREACHED */ + return EX_OK; +} + +/* +** READHEADERS -- read mail headers +** +** Parameters: +** none. +** +** Returns: +** nothing. +** +*/ +void +readheaders() +{ + bool tome, cont; + register char *p; + register ALIAS *cur; + char buf[MAXLINE]; + extern bool junkmail __P((char *)); + extern bool nsearch __P((char *, char *)); + + cont = tome = FALSE; + while (!tome && fgets(buf, sizeof(buf), stdin) && *buf != '\n') + { + switch(*buf) + { + case 'F': /* "From " */ + cont = FALSE; + if (strncmp(buf, "From ", 5) == 0) + { + bool quoted = FALSE; + + p = buf + 5; + while (*p != '\0') + { + /* escaped character */ + if (*p == '\\') + { + p++; + if (*p == '\0') + { + syslog(LOG_NOTICE, + "vacation: badly formatted \"From \" line.\n"); + exit(EX_DATAERR); + } + } + else if (*p == '"') + quoted = !quoted; + else if (*p == '\r' || *p == '\n') + break; + else if (*p == ' ' && !quoted) + break; + p++; + } + if (quoted) + { + syslog(LOG_NOTICE, + "vacation: badly formatted \"From \" line.\n"); + exit(EX_DATAERR); + } + *p = '\0'; + + /* ok since both strings have MAXLINE length */ + if (*From == '\0') + (void)strlcpy(From, buf + 5, + sizeof From); + if ((p = strchr(buf + 5, '\n')) != NULL) + *p = '\0'; + if (junkmail(buf + 5)) + exit(EX_OK); + } + break; + + case 'P': /* "Precedence:" */ + case 'p': + cont = FALSE; + if (strlen(buf) <= 10 || + strncasecmp(buf, "Precedence", 10) != 0 || + (buf[10] != ':' && buf[10] != ' ' && + buf[10] != '\t')) + break; + if ((p = strchr(buf, ':')) == NULL) + break; + while (*++p != '\0' && isascii(*p) && isspace(*p)); + if (*p == '\0') + break; + if (strncasecmp(p, "junk", 4) == 0 || + strncasecmp(p, "bulk", 4) == 0 || + strncasecmp(p, "list", 4) == 0) + exit(EX_OK); + break; + + case 'C': /* "Cc:" */ + case 'c': + if (strncasecmp(buf, "Cc:", 3) != 0) + break; + cont = TRUE; + goto findme; + + case 'T': /* "To:" */ + case 't': + if (strncasecmp(buf, "To:", 3) != 0) + break; + cont = TRUE; + goto findme; + + default: + if (!isascii(*buf) || !isspace(*buf) || !cont || tome) + { + cont = FALSE; + break; + } +findme: + for (cur = Names; + !tome && cur != NULL; + cur = cur->next) + tome = nsearch(cur->name, buf); + } + } + if (!tome) + exit(EX_OK); + if (*From == '\0') + { + syslog(LOG_NOTICE, "vacation: no initial \"From \" line.\n"); + exit(EX_DATAERR); + } +} + +/* +** NSEARCH -- +** do a nice, slow, search of a string for a substring. +** +** Parameters: +** name -- name to search. +** str -- string in which to search. +** +** Returns: +** is name a substring of str? +** +*/ +bool +nsearch(name, str) + register char *name, *str; +{ + register size_t len; + register char *s; + + len = strlen(name); + + for (s = str; *s != '\0'; ++s) + { + /* + ** Check to make sure that the string matches and + ** the previous character is not an alphanumeric and + ** the next character after the match is not an alphanumeric. + ** + ** This prevents matching "eric" to "derick" while still + ** matching "eric" to "". + */ + + if (tolower(*s) == tolower(*name) && + strncasecmp(name, s, len) == 0 && + (s == str || !isascii(*(s - 1)) || !isalnum(*(s - 1))) && + (!isascii(*(s + len)) || !isalnum(*(s + len)))) + return TRUE; + } + return FALSE; +} + +/* +** JUNKMAIL -- +** read the header and return if automagic/junk/bulk/list mail +** +** Parameters: +** from -- sender address. +** +** Returns: +** is this some automated/junk/bulk/list mail? +** +*/ +bool +junkmail(from) + char *from; +{ + register size_t len; + register char *p; + register struct ignore *cur; + static struct ignore + { + char *name; + size_t len; + } ignore[] = + { + { "-request", 8 }, + { "postmaster", 10 }, + { "uucp", 4 }, + { "mailer-daemon", 13 }, + { "mailer", 6 }, + { "-relay", 6 }, + { NULL, 0 } + }; + + /* + * This is mildly amusing, and I'm not positive it's right; trying + * to find the "real" name of the sender, assuming that addresses + * will be some variant of: + * + * From site!site!SENDER%site.domain%site.domain@site.domain + */ + if ((p = strchr(from, '%')) == NULL && + (p = strchr(from, '@')) == NULL) + { + if ((p = strrchr(from, '!')) != NULL) + ++p; + else + p = from; + for (; *p; ++p) + continue; + } + len = p - from; + for (cur = ignore; cur->name != NULL; ++cur) + { + if (len >= cur->len && + strncasecmp(cur->name, p - cur->len, cur->len) == 0) + return TRUE; + } + return FALSE; +} + +#define VIT "__VACATION__INTERVAL__TIMER__" + +/* +** RECENT -- +** find out if user has gotten a vacation message recently. +** +** Parameters: +** none. +** +** Returns: +** TRUE iff user has gotten a vacation message recently. +** +*/ +bool +recent() +{ + SMDB_DBENT key, data; + time_t then, next; + bool trydomain = FALSE; + int st; + char *domain; + + memset(&key, '\0', sizeof key); + memset(&data, '\0', sizeof data); + + /* get interval time */ + key.data.data = VIT; + key.data.size = sizeof(VIT); + + st = Db->smdb_get(Db, &key, &data, 0); + if (st != SMDBE_OK) + next = SECSPERDAY * DAYSPERWEEK; + else + memmove(&next, data.data.data, sizeof(next)); + + memset(&data, '\0', sizeof data); + + /* get record for this address */ + key.data.data = From; + key.data.size = strlen(From); + + do + { + st = Db->smdb_get(Db, &key, &data, 0); + if (st == SMDBE_OK) + { + memmove(&then, data.data.data, sizeof(then)); + if (next == ONLY_ONCE || then == ONLY_ONCE || + then + next > time(NULL)) + return TRUE; + } + if ((trydomain = !trydomain) && + (domain = strchr(From, '@')) != NULL) + { + key.data.data = domain; + key.data.size = strlen(domain); + } + } while (trydomain); + return FALSE; +} + +/* +** SETINTERVAL -- +** store the reply interval +** +** Parameters: +** interval -- time interval for replies. +** +** Returns: +** nothing. +** +** Side Effects: +** stores the reply interval in database. +*/ +void +setinterval(interval) + time_t interval; +{ + SMDB_DBENT key, data; + + memset(&key, '\0', sizeof key); + memset(&data, '\0', sizeof data); + + key.data.data = VIT; + key.data.size = sizeof(VIT); + data.data.data = (char*) &interval; + data.data.size = sizeof(interval); + (void)(Db->smdb_put)(Db, &key, &data, 0); +} + +/* +** SETREPLY -- +** store that this user knows about the vacation. +** +** Parameters: +** from -- sender address. +** when -- last reply time. +** +** Returns: +** nothing. +** +** Side Effects: +** stores user/time in database. +*/ +void +setreply(from, when) + char *from; + time_t when; +{ + SMDB_DBENT key, data; + + memset(&key, '\0', sizeof key); + memset(&data, '\0', sizeof data); + + key.data.data = from; + key.data.size = strlen(from); + data.data.data = (char*) &when; + data.data.size = sizeof(when); + (void)(Db->smdb_put)(Db, &key, &data, 0); +} + +/* +** XCLUDE -- +** add users to vacation db so they don't get a reply. +** +** Parameters: +** f -- file pointer with list of address to exclude +** +** Returns: +** nothing. +** +** Side Effects: +** stores users in database. +*/ +void +xclude(f) + FILE *f; +{ + char buf[MAXLINE], *p; + + if (f == NULL) + return; + while (fgets(buf, sizeof buf, f)) + { + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + setreply(buf, ONLY_ONCE); + } +} + +/* +** SENDMESSAGE -- +** exec sendmail to send the vacation file to sender +** +** Parameters: +** myname -- user name. +** msgfn -- name of file with vacation message. +** emptysender -- use <> as sender address? +** +** Returns: +** nothing. +** +** Side Effects: +** sends vacation reply. +*/ +void +sendmessage(myname, msgfn, emptysender) + char *myname; + char *msgfn; + bool emptysender; +{ + FILE *mfp, *sfp; + int i; + int pvect[2]; + char buf[MAXLINE]; + + mfp = fopen(msgfn, "r"); + if (mfp == NULL) + { + if (msgfn[0] == '/') + syslog(LOG_NOTICE, "vacation: no %s file.\n", msgfn); + else + syslog(LOG_NOTICE, "vacation: no ~%s/%s file.\n", + myname, msgfn); + exit(EX_NOINPUT); + } + if (pipe(pvect) < 0) + { + syslog(LOG_ERR, "vacation: pipe: %s", errstring(errno)); + exit(EX_OSERR); + } + i = fork(); + if (i < 0) + { + syslog(LOG_ERR, "vacation: fork: %s", errstring(errno)); + exit(EX_OSERR); + } + if (i == 0) + { + (void) dup2(pvect[0], 0); + (void) close(pvect[0]); + (void) close(pvect[1]); + (void) fclose(mfp); + if (emptysender) + myname = "<>"; + (void) execl(_PATH_SENDMAIL, "sendmail", "-f", myname, "--", + From, NULL); + syslog(LOG_ERR, "vacation: can't exec %s: %s", + _PATH_SENDMAIL, errstring(errno)); + exit(EX_UNAVAILABLE); + } + /* check return status of the following calls? XXX */ + (void) close(pvect[0]); + if ((sfp = fdopen(pvect[1], "w")) != NULL) + { + (void) fprintf(sfp, "To: %s\n", From); + (void) fprintf(sfp, "Auto-Submitted: auto-generated\n"); + while (fgets(buf, sizeof buf, mfp)) + (void) fputs(buf, sfp); + (void) fclose(mfp); + (void) fclose(sfp); + } + else + { + (void) fclose(mfp); + syslog(LOG_ERR, "vacation: can't open pipe to sendmail"); + exit(EX_UNAVAILABLE); + } +} + +void +usage() +{ + syslog(LOG_NOTICE, "uid %u: usage: vacation [-i] [-a alias] [-f db] [-m msg] [-r interval] [-s sender] [-x] [-z] login\n", + getuid()); + exit(EX_USAGE); +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +message(const char *msg, ...) +#else /* __STDC__ */ +message(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} + +/*VARARGS1*/ +void +#ifdef __STDC__ +syserr(const char *msg, ...) +#else /* __STDC__ */ +syserr(msg, va_alist) + const char *msg; + va_dcl +#endif /* __STDC__ */ +{ + const char *m; + VA_LOCAL_DECL + + m = msg; + if (isascii(m[0]) && isdigit(m[0]) && + isascii(m[1]) && isdigit(m[1]) && + isascii(m[2]) && isdigit(m[2]) && m[3] == ' ') + m += 4; + VA_START(msg); + (void) vfprintf(stderr, m, ap); + VA_END; + (void) fprintf(stderr, "\n"); +} + +void +dumpfd(fd, printclosed, logit) + int fd; + bool printclosed; + bool logit; +{ + return; +}