aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src
diff options
context:
space:
mode:
authorcvs2svn <cvs2svn@FreeBSD.org>1997-02-05 04:29:56 +0000
committercvs2svn <cvs2svn@FreeBSD.org>1997-02-05 04:29:56 +0000
commit860c2cf2bc6592828a3468ab8ee661042b059ae8 (patch)
treefde30676422ab07fdec2d11fde3fc5693fdbb8cf /usr.sbin/sendmail/src
parentb61013aa0c73c687493c80193bc040d29b351fb8 (diff)
This commit was manufactured by cvs2svn to create tagupstream/2.1.6_cvsrelease/2.1.6_cvs
'RELENG_2_1_6_RELEASE'. This commit was manufactured to restore the state of the 2.1.6-RELEASE image. Releases prior to 5.3-RELEASE are omitting the secure/ and crypto/ subdirs.
Diffstat (limited to 'usr.sbin/sendmail/src')
-rw-r--r--usr.sbin/sendmail/src/Makefile9
-rw-r--r--usr.sbin/sendmail/src/READ_ME271
-rw-r--r--usr.sbin/sendmail/src/TRACEFLAGS4
-rw-r--r--usr.sbin/sendmail/src/alias.c47
-rw-r--r--usr.sbin/sendmail/src/arpadate.c4
-rw-r--r--usr.sbin/sendmail/src/clock.c4
-rw-r--r--usr.sbin/sendmail/src/collect.c37
-rw-r--r--usr.sbin/sendmail/src/conf.c987
-rw-r--r--usr.sbin/sendmail/src/conf.h429
-rw-r--r--usr.sbin/sendmail/src/convtime.c4
-rw-r--r--usr.sbin/sendmail/src/daemon.c193
-rw-r--r--usr.sbin/sendmail/src/deliver.c619
-rw-r--r--usr.sbin/sendmail/src/domain.c68
-rw-r--r--usr.sbin/sendmail/src/envelope.c174
-rw-r--r--usr.sbin/sendmail/src/err.c57
-rw-r--r--usr.sbin/sendmail/src/headers.c177
-rw-r--r--usr.sbin/sendmail/src/macro.c30
-rw-r--r--usr.sbin/sendmail/src/main.c506
-rw-r--r--usr.sbin/sendmail/src/makesendmail51
-rw-r--r--usr.sbin/sendmail/src/map.c803
-rw-r--r--usr.sbin/sendmail/src/mci.c862
-rw-r--r--usr.sbin/sendmail/src/mime.c341
-rw-r--r--usr.sbin/sendmail/src/parseaddr.c526
-rw-r--r--usr.sbin/sendmail/src/queue.c278
-rw-r--r--usr.sbin/sendmail/src/readcf.c398
-rw-r--r--usr.sbin/sendmail/src/recipient.c40
-rw-r--r--usr.sbin/sendmail/src/savemail.c164
-rw-r--r--usr.sbin/sendmail/src/sendmail.8197
-rw-r--r--usr.sbin/sendmail/src/sendmail.h273
-rw-r--r--usr.sbin/sendmail/src/sendmail.hf49
-rw-r--r--usr.sbin/sendmail/src/srvrsmtp.c213
-rw-r--r--usr.sbin/sendmail/src/stab.c71
-rw-r--r--usr.sbin/sendmail/src/stats.c4
-rw-r--r--usr.sbin/sendmail/src/sysexits.c4
-rw-r--r--usr.sbin/sendmail/src/trace.c4
-rw-r--r--usr.sbin/sendmail/src/udb.c116
-rw-r--r--usr.sbin/sendmail/src/useful.h4
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c195
-rw-r--r--usr.sbin/sendmail/src/util.c393
-rw-r--r--usr.sbin/sendmail/src/version.c4
40 files changed, 6930 insertions, 1680 deletions
diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile
index f92c20a78d62..c85896b1d37b 100644
--- a/usr.sbin/sendmail/src/Makefile
+++ b/usr.sbin/sendmail/src/Makefile
@@ -17,8 +17,11 @@ PROG= sendmail
# spiral snail, but it will work.
DBMDEF= -DNEWDB
-# To building this on a system without setproctitle, uncomment:
-CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO #-DDONT_HAVE_SETPROCTITLE
+# if you don't want NIS support, comment out this line
+# FreeBSD supports NIS
+NIS= -DNIS
+
+CFLAGS+=-I${.CURDIR} ${DBMDEF} ${NIS} #-DNETISO
SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
@@ -37,8 +40,6 @@ BINOWN= root
BINMODE=4555
beforeinstall:
-# ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
-# ${DESTDIR}/etc/sendmail.fc
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
${DESTDIR}/var/log/sendmail.st
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
diff --git a/usr.sbin/sendmail/src/READ_ME b/usr.sbin/sendmail/src/READ_ME
index 264b2ebaac99..afeac1bc7eb6 100644
--- a/usr.sbin/sendmail/src/READ_ME
+++ b/usr.sbin/sendmail/src/READ_ME
@@ -1,4 +1,4 @@
-# Copyright (c) 1983, 1995 Eric P. Allman
+# Copyright (c) 1983, 1995, 1996 Eric P. Allman
# Copyright (c) 1988 The Regents of the University of California.
# All rights reserved.
#
@@ -30,7 +30,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)READ_ME 8.113 (Berkeley) 11/29/95
+# @(#)READ_ME 8.130 (Berkeley) 11/10/96
#
This directory contains the source files for sendmail.
@@ -144,46 +144,56 @@ There are several database formats that can be used for the alias files
and for general maps. When used for alias files they interact in an
attempt to be back compatible.
-The three options are NEWDB (the new Berkeley DB package), NDBM (the
-older DBM implementation -- the very old V7 implementation is no
-longer supported), and NIS (Network Information Services). Used alone
-these just include the support they indicate. [If you are using NEWDB,
-get the latest version from FTP.CS.Berkeley.EDU in /ucb/4bsd/db.tar.Z
-(or db.tar.gz). DO NOT use the version from the Net2 distribution!
-However, if you are on BSD/386 or 386BSD-based systems, use the one
-that already exists on your system. You may need to #define OLD_NEWDB
-1 to do this.]
-
-[NOTE WELL: it is CRITICAL that you remove ndbm.o from libdb.a and
-ndbm.h from the appropriate include directories if you want to get
-ndbm support. These files OVERRIDE calls to ndbm routines -- in
-particular, if you leave ndbm.h in, you can find yourself using
-the new db package even if you don't define NEWDB.]
+The options are:
+
+NEWDB The new Berkeley DB package. Some systems (e.g., BSD/OS and
+ Digital UNIX 4.0) have this package pre-installed. If your
+ system does not have NEWDB installed, get the latest version
+ from FTP.CS.Berkeley.EDU in /ucb/4bsd/db.tar.gz (or db.tar.Z).
+ DO NOT use the version from the Net2 distribution. If you are
+ still running BSD/386 1.x, you will also need to define
+ OLD_NEWDB.
+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 ldap and lber libraries to use
+ this flag.
+
+>>> NOTE WELL for NEWDB support: it is CRITICAL that you remove ndbm.o
+>>> from libdb.a before you install it and DO NOT install ndbm.h if
+>>> you want to get ndbm support. If you don't delete these, there is
+>>> absolutely no point to including -DNDBM, since it will just get you
+>>> another (inferior) API to the same format database. These files
+>>> OVERRIDE calls to ndbm routines -- in particular, if you leave ndbm.h
+>>> in, you can find yourself using the new db package even if you don't
+>>> define NEWDB.
If NEWDB and NDBM are defined (but not NIS), then sendmail will read
NDBM format alias files, but the next time a newaliases is run the
format will be converted to NEWDB; that format will be used forever
-more. This is intended as a transition feature. [Note however that
-the NEWDB library also catches and maps NDBM calls; you will have to
-back out this feature to get this to work. See ``Quirks'' section
-below for details.]
+more. This is intended as a transition feature.
-If all three are defined and the name of the file includes the string
-"/yp/", sendmail will rebuild BOTH the NEWDB and NDBM format alias
-files. However, it will only read the NEWDB file; the NDBM format file
-is used only by the NIS subsystem.
+If 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.
-There is also preliminary support for NIS+ (-DNISPLUS), Hesiod
-(-DHESIOD), and NetInfo (-DNETINFO). These have not been well
-tested.
-
-All of -DNEWDB, -DNDBM, -DNIS, -DNISPLUS, -DHESIOD, and -DNETINFO are
-normally defined in the DBMDEF line in the Makefile.
+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
@@ -191,6 +201,11 @@ 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.
+
+
+---------------+
| COMPILE FLAGS |
@@ -340,11 +355,20 @@ LA_TYPE The type of load average your kernel supports. These
the dg_sys_info system call.
LA_HPUX (10) is an HP-UX specific version that uses the
pstat_getdynamic system call.
+ LA_IRIX6 (11) is an IRIX 6.x specific version that adapts
+ to 32 or 64 bit kernels; it is otherwise very similar
+ to LA_INT.
+ LA_KSTAT (12) uses the (Solaris-specific) kstat(3k)
+ implementation.
+ LA_DEVSHORT (13) reads a short from a system file (default:
+ /dev/table/avenrun) and scales it in the same manner
+ as LA_SHORT.
LA_INT, LA_SHORT, LA_FLOAT, and LA_READKSYM have several
other parameters that they try to divine: the name of your
kernel, the name of the variable in the kernel to examine,
the number of bits of precision in a fixed point load average,
- and so forth.
+ and so forth. LA_DEVSHORT uses _PATH_AVENRUN to find the
+ device to be read to find the load average.
In desperation, use LA_ZERO. The actual code is in
conf.c -- it can be tweaked if you are brave.
FSHIFT For LA_INT, LA_SHORT, and LA_READKSYM, this is the number
@@ -462,7 +486,7 @@ IP_SRCROUTE Define this to 1 to get IP source routing information
it won't compile properly (that is, no support for fetching
IP_OPTIONs), or it compiles but source-routed TCP connections
either refuse to open or open and hang for no apparent reason.
- Ultrix and AIX are known to fail this way.
+ 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
@@ -500,6 +524,19 @@ HES_GETMAILHOST Define this to 1 if you are using Hesiod with the
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).
+ This library is available on ftp.win.tue.nl in /pub/security;
+ grab tcp_wrappers_<VER>.tar.gz (where <VER> is the highest
+ numbered version).
+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.
+---------------------+
@@ -515,7 +552,10 @@ 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.
+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
@@ -587,6 +627,13 @@ Configuration file location
vendor location rather than changing the location in the sendmail
binary.
+ld: fatal: library -l44bsd: not found
+ Most of the Makefiles include -l44bsd in the LIBS= definition;
+ this is because several versions of BIND (4.9.0, 4.9.1, 4.9.2)
+ require this library. If you are running one of these versions,
+ install this library. Otherwise, just delete "-l44bsd" from the
+ LIBS= line in the Makefile.
+
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
@@ -631,17 +678,18 @@ SunOS 4.0.2 (Sun 386i)
(and change the Makefile to use this library).
Note that the sendmail.cf and aliases files are found in /etc.
-SunOS 4.1.3_U1
- Sendmail causes crashes on SunOS 4.1.3_U1. According to Sun
- bug number 1077939:
+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.
- This is fixed in patch 101790-01 (SunOS 4.1.3_U1: TCP socket and
- reset problems).
+ 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 is fixed in patch
+ 101790-01 (SunOS 4.1.3_U1: TCP socket and reset problems).
Solaris 2.x (SunOS 5.x)
To compile for Solaris, be sure you use -DSOLARIS.
@@ -751,6 +799,10 @@ OSF/1
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.
+
IRIX
The header files on SGI IRIX are completely prototyped, and as
a result you can sometimes get some warning messages during
@@ -766,6 +818,26 @@ IRIX
the developers' option in order to get the necessary include
files.
+ If you compile with -lmalloc (the fast memory allocator), you may
+ get warning messages such as the following:
+
+ ld32: WARNING 85: definition of _calloc in /usr/lib32/libmalloc.so
+ preempts that definition in /usr/lib32/mips3/libc.so.
+ ld32: WARNING 85: definition of _malloc in /usr/lib32/libmalloc.so
+ preempts that definition in /usr/lib32/mips3/libc.so.
+ ld32: WARNING 85: definition of _realloc in /usr/lib32/libmalloc.so
+ preempts that definition in /usr/lib32/mips3/libc.so.
+ ld32: WARNING 85: definition of _free in /usr/lib32/libmalloc.so
+ preempts that definition in /usr/lib32/mips3/libc.so.
+ ld32: WARNING 85: definition of _cfree in /usr/lib32/libmalloc.so
+ preempts that definition in /usr/lib32/mips3/libc.so.
+
+ These are unavoidable and innocuous -- just ignore them.
+
+ According to Dave Sill <de5@ornl.gov>, there is a version of the
+ Berkeley db library patched to run on Irix 6.2 available from
+ http://reality.sgi.com/ariel/db-1.85-irix.tar.Z .
+
NeXT or NEXTSTEP
NEXTSTEP 3.3 and earlier ship with the old DBM library. You will
need to acquire the new Berkeley DB from ftp.cs.berkeley.edu.
@@ -931,7 +1003,22 @@ Linux
of libc between 4.4.4 and 4.7.0 (snprintf improves security, so
you want to use this if at all possible).
-AIX
+ NOTE ON LINUX & BIND: By default, the Makefiles for linux include
+ 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.
+
+AIX 3.x
This version of sendmail does not support MB, MG, and MR resource
records, which are supported by AIX sendmail.
@@ -940,6 +1027,56 @@ AIX
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 <jmaki@hut.fi> 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 <markw@antimatr.houston.tx.us>
+ 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.
+
+ 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 <markw@antimatr.houston.tx.us>.
+ 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 the Makefile.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 the Makefile.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
@@ -1081,7 +1218,7 @@ Listproc 6.0c
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
+ 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.
@@ -1089,6 +1226,56 @@ Listproc 6.0c
cause it to use "HELO hostname" (which Z-mail apparently requires
as well. :)
+LDAP
+ LDAP was provided by Booker Bense <bbense@networking.stanford.edu> of
+ Stanford University. From Booker:
+
+ - The patch attached to this message implements an Ldap map class.
+ Currently we are using this at stanford to support campus-wide
+ email addressing. This project is discussed at
+ http://www-leland.stanford.edu/group/networking/project/sunetid.html
+
+ - Currently we are using the ldap map as follows:
+
+ Kluser ldapx
+ -h"localhost borax.stanford.edu borate.stanford.edu boron.stanford.edu"
+ -k"mailacceptinggeneralid=%s" -v maildrop
+
+ and in Rule set S5
+
+ # Now attempt to lookup in luser (ldap map)
+ R< $L > $+ $: < $L > $( luser $1 $)
+ R< $* > $+ @ $+ $: < $3 > $2 Rewrite if forward
+
+ - The map definition supports most of the standard Map args plus most
+ of the command line options of ldapsearch. The software is currently
+ limited to only accepting the first entry returned. It expects that
+ the map defines an ldap filter that returns at most 1 valid entry.
+ It requires the ldap and lber libraries from the Umich Ldap3.2
+ release.
+
+ - KNOWN BUGS: It does not work under Digital Unix 3.2c, with gcc and
+ ldap3.2 or ldap3.3. It dumps core after attempting to take strlen
+ of a garbage string pointer in the lber libraries routine
+ ber_printf.
+
+ The string pointer in question is set to 0x50000000, when the
+ program crashes. If anyone recognizes where this magic number comes
+ from that would be really helpful.
+
+ I've tested the software on Solaris.2.4 with gcc and on NeXTStep3.2
+ and it runs without problems. If you have any questions, please
+ send them along.
+
+TCP Wrappers
+ If you are using -DTCPWRAPPERS to get TCP Wrappers support, you will
+ also need to install libwrap.a (you can get it from ftp.win.tue.nl)
+ and modify the Makefile to include -lwrap in the LIBS line.
+
+ 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 your and forward it on to you.
+--------------+
@@ -1190,4 +1377,4 @@ version.c The version number and information about this
Eric Allman
-(Version 8.113, last update 11/29/95 11:05:14)
+(Version 8.130, last update 11/10/96 11:15:30)
diff --git a/usr.sbin/sendmail/src/TRACEFLAGS b/usr.sbin/sendmail/src/TRACEFLAGS
index f2499aac0913..a5b25656e76a 100644
--- a/usr.sbin/sendmail/src/TRACEFLAGS
+++ b/usr.sbin/sendmail/src/TRACEFLAGS
@@ -62,9 +62,11 @@
53 util.c xfclose
54 err.c putoutmsg
55 conf.c lockfile
-59 Extended Load Average implementation from Christophe Wolfhugel
+56 mci.c persistent host status
+57 util.c snprintf
60 map.c
61 conf.c sm_gethostbyname
+62 multiple file descriptor checking
80 content length
81 sun remote mode
91 mci.c syslogging of MCI cache information
diff --git a/usr.sbin/sendmail/src/alias.c b/usr.sbin/sendmail/src/alias.c
index 62b6af96de4f..95de1ee8ff6f 100644
--- a/usr.sbin/sendmail/src/alias.c
+++ b/usr.sbin/sendmail/src/alias.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -35,7 +35,7 @@
# include "sendmail.h"
#ifndef lint
-static char sccsid[] = "@(#)alias.c 8.52.1.3 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)alias.c 8.66 (Berkeley) 9/20/96";
#endif /* not lint */
@@ -152,8 +152,6 @@ alias(a, sendq, aliaslevel, e)
(void) strcat(obuf, "owner");
else
(void) strcat(obuf, a->q_user);
- if (!bitnset(M_USR_UPPER, a->q_mailer->m_flags))
- makelower(obuf);
owner = aliaslookup(obuf, &stat, e);
if (owner == NULL)
return;
@@ -207,6 +205,11 @@ aliaslookup(name, pstat, e)
}
if (!bitset(MF_OPEN, map->map_mflags))
return NULL;
+
+ /* special case POstMastER -- always use lower case */
+ if (strcasecmp(name, "postmaster") == 0)
+ name = "postmaster";
+
return (*map->map_class->map_lookup)(map, name, NULL, pstat);
}
/*
@@ -292,8 +295,7 @@ setalias(spec)
s = stab(class, ST_MAPCLASS, ST_FIND);
if (s == NULL)
{
- if (tTd(27, 1))
- printf("Unknown alias class %s\n", class);
+ syserr("setalias: unknown alias class %s", class);
}
else if (!bitset(MCF_ALIASOK, s->s_mapclass.map_cflags))
{
@@ -494,7 +496,7 @@ rebuildaliases(map, automatic)
!lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB))
{
/* yes, they are -- wait until done */
- message("Alias file %s is already being rebuilt",
+ message("Alias file %s is locked (maybe being rebuilt)",
map->map_file);
if (OpMode != MD_INITALIAS)
{
@@ -710,10 +712,12 @@ readaliases(map, af, announcestats, logstats)
}
/*
- ** Insert alias into symbol table or DBM file
+ ** Insert alias into symbol table or database file.
+ **
+ ** Special case pOStmaStER -- always make it lower case.
*/
- if (!bitnset(M_USR_UPPER, al.q_mailer->m_flags))
+ if (strcasecmp(al.q_user, "postmaster") == 0)
makelower(al.q_user);
lhssize = strlen(al.q_user);
@@ -776,6 +780,7 @@ forward(user, sendq, aliaslevel, e)
{
char *pp;
char *ep;
+ bool got_transient;
if (tTd(27, 1))
printf("forward(%s)\n", user->q_paddr);
@@ -786,7 +791,7 @@ forward(user, sendq, aliaslevel, e)
if (user->q_home == NULL)
{
syserr("554 forward: no home");
- user->q_home = "/nosuchdirectory";
+ user->q_home = "/no/such/directory";
}
/* good address -- look for .forward file in home */
@@ -796,11 +801,11 @@ forward(user, sendq, aliaslevel, e)
if (ForwardPath == NULL)
ForwardPath = newstr("\201z/.forward");
+ got_transient = FALSE;
for (pp = ForwardPath; pp != NULL; pp = ep)
{
int err;
char buf[MAXPATHLEN+1];
- extern int include();
ep = strchr(pp, ':');
if (ep != NULL)
@@ -808,6 +813,8 @@ forward(user, sendq, aliaslevel, e)
expand(pp, buf, sizeof buf, e);
if (ep != NULL)
*ep++ = ':';
+ if (buf[0] == '\0')
+ continue;
if (tTd(27, 3))
printf("forward: trying %s\n", buf);
@@ -816,7 +823,8 @@ forward(user, sendq, aliaslevel, e)
break;
else if (transienterror(err))
{
- /* we have to suspend this message */
+ /* we may have to suspend this message */
+ got_transient = TRUE;
if (tTd(27, 2))
printf("forward: transient error on %s\n", buf);
#ifdef LOG
@@ -825,9 +833,18 @@ forward(user, sendq, aliaslevel, e)
e->e_id == NULL ? "NOQUEUE" : e->e_id,
buf, errstring(err));
#endif
- message("%s: %s: message queued", buf, errstring(err));
- user->q_flags |= QQUEUEUP;
- return;
}
}
+ 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_flags |= QQUEUEUP;
+ return;
+ }
}
diff --git a/usr.sbin/sendmail/src/arpadate.c b/usr.sbin/sendmail/src/arpadate.c
index b207654f3130..418fd262e555 100644
--- a/usr.sbin/sendmail/src/arpadate.c
+++ b/usr.sbin/sendmail/src/arpadate.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)arpadate.c 8.4.1.1 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)arpadate.c 8.6 (Berkeley) 9/16/96";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/clock.c b/usr.sbin/sendmail/src/clock.c
index 1490137170e2..39862f1d9e19 100644
--- a/usr.sbin/sendmail/src/clock.c
+++ b/usr.sbin/sendmail/src/clock.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)clock.c 8.12 (Berkeley) 5/23/95";
+static char sccsid[] = "@(#)clock.c 8.13 (Berkeley) 2/21/96";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c
index 7e43c5f5ffa2..48b5b89e90ce 100644
--- a/usr.sbin/sendmail/src/collect.c
+++ b/usr.sbin/sendmail/src/collect.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)collect.c 8.49 (Berkeley) 10/29/95";
+static char sccsid[] = "@(#)collect.c 8.60 (Berkeley) 11/15/96";
#endif /* not lint */
# include <errno.h>
@@ -101,8 +101,8 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
int buflen;
int istate;
int mstate;
- char *pbp;
- char peekbuf[8];
+ u_char *pbp;
+ u_char peekbuf[8];
char dfname[20];
char bufbuf[MAXLINE];
extern bool isheader();
@@ -170,9 +170,10 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
if (setjmp(CtxCollectTimeout) != 0)
{
#ifdef LOG
- syslog(LOG_NOTICE,
- "timeout waiting for input from %s during message collect",
- CurHostName ? CurHostName : "<local machine>");
+ if (LogLevel > 2)
+ syslog(LOG_NOTICE,
+ "timeout waiting for input from %s during message collect",
+ CurHostName ? CurHostName : "<local machine>");
#endif
errno = 0;
usrerr("451 timeout waiting for input during message collect");
@@ -216,8 +217,6 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
c &= 0x7f;
else
HasEightBits |= bitset(0x80, c);
- if (!headeronly)
- e->e_msgsize++;
}
if (tTd(30, 94))
printf("istate=%d, c=%c (0x%x)\n",
@@ -253,7 +252,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
break;
case IS_DOTCR:
- if (c == '\n')
+ if (c == '\n' && !ignrdot)
goto readerr;
else
{
@@ -287,6 +286,8 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
istate = IS_NORM;
bufferchar:
+ if (!headeronly)
+ e->e_msgsize++;
if (mstate == MS_BODY)
{
/* just put the character out */
@@ -316,7 +317,13 @@ bufferchar:
if (obuf != bufbuf)
free(obuf);
}
- if (c != '\0')
+ if (c >= 0200 && c <= 0237)
+ {
+#if 0 /* causes complaints -- figure out something for 8.9 */
+ usrerr("Illegal character 0x%x in header", c);
+#endif
+ }
+ else if (c != '\0')
*bp++ = c;
if (istate == IS_BOL)
break;
@@ -481,7 +488,7 @@ readerr:
** Examples are who is the from person & the date.
*/
- eatheader(e, !requeueflag);
+ eatheader(e, TRUE);
if (GrabTo && e->e_sendqueue == NULL)
usrerr("No recipient addresses found in header");
@@ -550,6 +557,7 @@ readerr:
/* check for message too large */
if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize)
{
+ e->e_flags |= EF_NO_BODY_RETN;
e->e_status = "5.2.3";
usrerr("552 Message exceeds maximum fixed size (%ld)",
MaxMessageSize);
@@ -564,7 +572,8 @@ readerr:
if (HasEightBits)
{
e->e_flags |= EF_HAS8BIT;
- if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode))
+ if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
+ !bitset(EF_IS_MIME, e->e_flags))
{
e->e_status = "5.6.1";
usrerr("554 Eight bit data not allowed");
@@ -625,6 +634,7 @@ tferror(tf, e)
struct stat st;
long avail;
long bsize;
+ extern long freediskspace __P((char *, long *));
e->e_flags |= EF_NO_BODY_RETN;
if (fstat(fileno(tf), &st) < 0)
@@ -729,7 +739,6 @@ eatfrom(fm, e)
if (*p != '\0')
{
char *q;
- extern char *arpadate();
/* we have found a date */
q = xalloc(25);
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
index f82e88071c22..750bad0581cb 100644
--- a/usr.sbin/sendmail/src/conf.c
+++ b/usr.sbin/sendmail/src/conf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)conf.c 8.243.1.9 (Berkeley) 9/17/96";
+static char sccsid[] = "@(#)conf.c 8.315 (Berkeley) 11/10/96";
#endif /* not lint */
# include "sendmail.h"
@@ -78,49 +78,50 @@ static char sccsid[] = "@(#)conf.c 8.243.1.9 (Berkeley) 9/17/96";
struct hdrinfo HdrInfo[] =
{
/* originator fields, most to least significant */
- "resent-sender", H_FROM|H_RESENT,
- "resent-from", H_FROM|H_RESENT,
- "resent-reply-to", H_FROM|H_RESENT,
- "sender", H_FROM,
- "from", H_FROM,
- "reply-to", H_FROM,
- "full-name", H_ACHECK,
- "return-receipt-to", H_FROM|H_RECEIPTTO,
- "errors-to", H_FROM|H_ERRORSTO,
+ { "resent-sender", H_FROM|H_RESENT },
+ { "resent-from", H_FROM|H_RESENT },
+ { "resent-reply-to", H_FROM|H_RESENT },
+ { "sender", H_FROM },
+ { "from", H_FROM },
+ { "reply-to", H_FROM },
+ { "errors-to", H_FROM|H_ERRORSTO },
+ { "full-name", H_ACHECK },
+ { "return-receipt-to", H_RECEIPTTO },
/* destination fields */
- "to", H_RCPT,
- "resent-to", H_RCPT|H_RESENT,
- "cc", H_RCPT,
- "resent-cc", H_RCPT|H_RESENT,
- "bcc", H_RCPT|H_BCC,
- "resent-bcc", H_RCPT|H_BCC|H_RESENT,
- "apparently-to", H_RCPT,
+ { "to", H_RCPT },
+ { "resent-to", H_RCPT|H_RESENT },
+ { "cc", H_RCPT },
+ { "resent-cc", H_RCPT|H_RESENT },
+ { "bcc", H_RCPT|H_BCC },
+ { "resent-bcc", H_RCPT|H_BCC|H_RESENT },
+ { "apparently-to", H_RCPT },
/* message identification and control */
- "message-id", 0,
- "resent-message-id", H_RESENT,
- "message", H_EOH,
- "text", H_EOH,
+ { "message-id", 0 },
+ { "resent-message-id", H_RESENT },
+ { "message", H_EOH },
+ { "text", H_EOH },
/* date fields */
- "date", 0,
- "resent-date", H_RESENT,
+ { "date", 0 },
+ { "resent-date", H_RESENT },
/* trace fields */
- "received", H_TRACE|H_FORCE,
- "x400-received", H_TRACE|H_FORCE,
- "via", H_TRACE|H_FORCE,
- "mail-from", H_TRACE|H_FORCE,
+ { "received", H_TRACE|H_FORCE },
+ { "x400-received", H_TRACE|H_FORCE },
+ { "via", H_TRACE|H_FORCE },
+ { "mail-from", H_TRACE|H_FORCE },
/* miscellaneous fields */
- "comments", H_FORCE,
- "return-path", H_FORCE|H_ACHECK,
- "content-transfer-encoding", H_CTE,
- "content-type", H_CTYPE,
- "content-length", H_ACHECK,
-
- NULL, 0,
+ { "comments", H_FORCE|H_ENCODABLE },
+ { "return-path", H_FORCE|H_ACHECK },
+ { "content-transfer-encoding", H_CTE },
+ { "content-type", H_CTYPE },
+ { "content-length", H_ACHECK },
+ { "subject", H_ENCODABLE },
+
+ { NULL, 0 }
};
@@ -139,18 +140,18 @@ char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */
struct prival PrivacyValues[] =
{
- "public", PRIV_PUBLIC,
- "needmailhelo", PRIV_NEEDMAILHELO,
- "needexpnhelo", PRIV_NEEDEXPNHELO,
- "needvrfyhelo", PRIV_NEEDVRFYHELO,
- "noexpn", PRIV_NOEXPN,
- "novrfy", PRIV_NOVRFY,
- "restrictmailq", PRIV_RESTRICTMAILQ,
- "restrictqrun", PRIV_RESTRICTQRUN,
- "authwarnings", PRIV_AUTHWARNINGS,
- "noreceipts", PRIV_NORECEIPTS,
- "goaway", PRIV_GOAWAY,
- NULL, 0,
+ { "public", PRIV_PUBLIC },
+ { "needmailhelo", PRIV_NEEDMAILHELO },
+ { "needexpnhelo", PRIV_NEEDEXPNHELO },
+ { "needvrfyhelo", PRIV_NEEDVRFYHELO },
+ { "noexpn", PRIV_NOEXPN },
+ { "novrfy", PRIV_NOVRFY },
+ { "restrictmailq", PRIV_RESTRICTMAILQ },
+ { "restrictqrun", PRIV_RESTRICTQRUN },
+ { "authwarnings", PRIV_AUTHWARNINGS },
+ { "noreceipts", PRIV_NORECEIPTS },
+ { "goaway", PRIV_GOAWAY },
+ { NULL, 0 }
};
@@ -227,12 +228,15 @@ setdefaults(e)
TimeOuts.to_q_warning[i] = 0; /* option T */
}
ServiceSwitchFile = "/etc/service.switch";
+ ServiceCacheMaxAge = (time_t) 10;
HostsFile = _PATH_HOSTS;
MustQuoteChars = "@,;:\\()[].'";
MciInfoTimeout = 30 MINUTES;
MaxRuleRecursion = MAXRULERECURSION;
MaxAliasRecursion = 10;
+ MaxMacroRecursion = 10;
ColonOkInAddr = TRUE;
+ DoubleBounceAddr = "postmaster";
setdefuser();
setupmaps();
setupmailers();
@@ -276,6 +280,14 @@ host_map_init(MAP *map, char *args)
case 'a':
map->map_app = ++p;
break;
+
+ case 'm':
+ map->map_mflags |= MF_MATCHONLY;
+ break;
+
+ case 't':
+ map->map_mflags |= MF_NODEFER;
+ break;
}
while (*p != '\0' && !(isascii(*p) && isspace(*p)))
p++;
@@ -296,13 +308,13 @@ setupmailers()
char buf[100];
extern void makemailer();
- strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=DNS/RFC822/X-Unix, A=sh -c \201u");
+ strcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=DNS/RFC822/X-Unix, A=sh -c \201u");
makemailer(buf);
- strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=DNS/RFC822/X-Unix, A=FILE");
+ strcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE \201u");
makemailer(buf);
- strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE");
+ strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u");
makemailer(buf);
}
/*
@@ -359,6 +371,11 @@ setupmaps()
map_parseargs, nisplus_map_open, null_map_close,
nisplus_map_lookup, null_map_store);
#endif
+#ifdef LDAPMAP
+ MAPDEF("ldapx", NULL, 0,
+ ldap_map_parseargs, ldap_map_open, ldap_map_close,
+ ldap_map_lookup, null_map_store);
+#endif
#ifdef HESIOD
MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
@@ -566,7 +583,7 @@ inithostmaps()
else if (strcmp(maptype[i], "netinfo") == 0 &&
stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
{
- strcpy(buf, "aliases.netinfo netinfo /aliases");
+ strcpy(buf, "aliases.netinfo netinfo -z, /aliases");
(void) makemapentry(buf);
}
#endif
@@ -670,15 +687,12 @@ switch_map_find(service, maptype, mapreturn)
char *maptype[MAXMAPSTACK];
short mapreturn[MAXMAPACTIONS];
{
- register FILE *fp;
int svcno;
- static char buf[MAXLINE];
#ifdef _USE_SUN_NSSWITCH_
struct __nsw_switchconfig *nsw_conf;
enum __nsw_parse_err pserr;
struct __nsw_lookup *lk;
- int nsw_rc;
static struct __nsw_lookup lkp0 =
{ "files", {1, 0, 0, 0}, NULL, NULL };
static struct __nsw_switchconfig lkp_default =
@@ -759,44 +773,85 @@ switch_map_find(service, maptype, mapreturn)
** Fall-back mechanism.
*/
+ STAB *st;
+ time_t now = curtime();
+
for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
mapreturn[svcno] = 0;
- svcno = 0;
- fp = fopen(ServiceSwitchFile, "r");
- if (fp != NULL)
+ if ((now - ServiceCacheTime) > (time_t) ServiceCacheMaxAge)
{
- while (fgets(buf, sizeof buf, fp) != NULL)
+ /* (re)read service switch */
+ register FILE *fp;
+
+ if (ConfigFileRead)
+ ServiceCacheTime = now;
+ fp = fopen(ServiceSwitchFile, "r");
+ if (fp != NULL)
{
- register char *p;
-
- p = strpbrk(buf, "#\n");
- if (p != NULL)
- *p = '\0';
- p = strpbrk(buf, " \t");
- if (p != NULL)
- *p++ = '\0';
- if (strcmp(buf, service) != 0)
- continue;
-
- /* got the right service -- extract data */
- do
+ 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;
while (isspace(*p))
p++;
if (*p == '\0')
- break;
- maptype[svcno++] = p;
- p = strpbrk(p, " \t");
- if (p != NULL)
+ 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 (p != NULL);
+ while (isspace(*p))
+ p++;
+ }
+ if (svcno < MAXMAPSTACK)
+ st->s_service[svcno] = NULL;
+ }
fclose(fp);
- return svcno;
}
+ }
- /* service was not found -- use compiled in default */
- 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;
+ }
+ return --svcno;
}
#endif
@@ -1017,9 +1072,14 @@ setsignal(sig, handler)
struct sigaction n, o;
bzero(&n, sizeof n);
+# if USE_SA_SIGACTION
+ n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
+ n.sa_flags = SA_RESTART|SA_SIGINFO;
+# else
n.sa_handler = handler;
-# ifdef SA_RESTART
+# ifdef SA_RESTART
n.sa_flags = SA_RESTART;
+# endif
# endif
if (sigaction(sig, &n, &o) < 0)
return SIG_ERR;
@@ -1042,13 +1102,20 @@ releasesignal(sig)
int sig;
{
#ifdef BSD4_3
- return sigsetmask(sigblock(0) & ~(1 << sig));
+# ifndef sigmask
+# define sigmask(s) (1 << ((s) - 1))
+# endif
+ return sigsetmask(sigblock(0) & ~sigmask(sig));
#else
+# ifdef ALTOS_SYSTEM_V
+ sigrelse(sig) ;
+# else
sigset_t sset;
sigemptyset(&sset);
sigaddset(&sset, sig);
return sigprocmask(SIG_UNBLOCK, &sset, NULL);
+# endif
#endif
}
/*
@@ -1095,7 +1162,11 @@ rlsesigs()
*/
#ifdef _AUX_SOURCE
-# include <compat.h>
+# include <compat.h>
+#endif
+
+#if SHARE_V1
+# include <shares.h>
#endif
void
@@ -1107,6 +1178,29 @@ init_md(argc, argv)
setcompat(getcompat() | COMPAT_BSDPROT);
#endif
+#ifdef SUN_EXTENSIONS
+ init_md_sun();
+#endif
+
+#if _CONVEX_SOURCE
+ /* keep gethostby*() from stripping the local domain name */
+ set_domain_trim_off();
+#endif
+#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
+#endif
+
#ifdef VENDOR_DEFAULT
VendorCode = VENDOR_DEFAULT;
#else
@@ -1159,6 +1253,9 @@ init_vendor_macros(e)
#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 */
/* do guesses based on general OS type */
#ifndef LA_TYPE
@@ -1174,9 +1271,6 @@ init_vendor_macros(e)
# define FSHIFT 10
# endif
-# if defined(_AIX3)
-# define FSHIFT 16
-# endif
#endif
#ifndef FSHIFT
@@ -1228,6 +1322,7 @@ struct nlist Nl[] =
#endif
#define X_AVENRUN 0
+int
getla()
{
static int kmem = -1;
@@ -1245,22 +1340,12 @@ getla()
if (kmem < 0)
{
- kmem = open(_PATH_KMEM, 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- printf("getla: open(/dev/kmem): %s\n",
- errstring(errno));
- return (-1);
- }
- (void) fcntl(kmem, F_SETFD, 1);
-
#ifdef _AUX_SOURCE
strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN);
Nl[1].n_name[0] = '\0';
#endif
-#ifdef _AIX3
+#if defined(_AIX3) || defined(_AIX4)
if (knlist(Nl, 1, sizeof Nl[0]) < 0)
#else
if (nlist(_PATH_UNIX, Nl) < 0)
@@ -1281,6 +1366,16 @@ getla()
#ifdef NAMELISTMASK
Nl[X_AVENRUN].n_value &= NAMELISTMASK;
#endif
+
+ kmem = open(_PATH_KMEM, 0, 0);
+ if (kmem < 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: open(/dev/kmem): %s\n",
+ errstring(errno));
+ return (-1);
+ }
+ (void) fcntl(kmem, F_SETFD, 1);
}
if (tTd(3, 20))
printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value);
@@ -1295,9 +1390,15 @@ getla()
# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
if (tTd(3, 5))
{
+# if LA_TYPE == LA_SHORT
printf("getla: avenrun = %d", avenrun[0]);
if (tTd(3, 15))
printf(", %d, %d", avenrun[1], avenrun[2]);
+# else
+ printf("getla: avenrun = %ld", avenrun[0]);
+ if (tTd(3, 15))
+ printf(", %ld, %ld", avenrun[1], avenrun[2]);
+# endif
printf("\n");
}
if (tTd(3, 1))
@@ -1450,6 +1551,7 @@ getla()
# include <mach.h>
#endif
+int
getla()
{
processor_set_t default_set;
@@ -1460,14 +1562,22 @@ getla()
error = processor_set_default(host_self(), &default_set);
if (error != KERN_SUCCESS)
+ {
+ if (tTd(3, 1))
+ perror("getla: processor_set_default failed:");
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))
+ perror("getla: processor_set_info failed:");
return -1;
}
+ if (tTd(3, 1))
+ printf("getla: %d\n", (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE);
return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
}
@@ -1520,8 +1630,261 @@ getla()
#endif /* LA_TYPE == LA_PROCSTR */
+#if LA_TYPE == LA_IRIX6
+
+#include <nlist.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define X_AVENRUN 0
+struct nlist Nl32[] =
+{
+ { LA_AVENRUN },
+ { 0 },
+};
+struct nlist64 Nl64[] =
+{
+ { LA_AVENRUN },
+ { 0 },
+};
+
+int getla(void)
+{
+ static int kmem = -1;
+ static enum { getla_none, getla_32, getla_64 } kernel_type =
+ getla_none;
+ uint32_t avenrun32[3];
+ uint64_t avenrun64[3];
+
+ if (kernel_type == getla_none)
+ {
+ /* Try 32 bit kernel ... */
+ errno = 0;
+ if (nlist(_PATH_UNIX, Nl32) == 0)
+ {
+ if (tTd(3, 20))
+ printf("getla: Kernel is 32bit\n");
+
+ if (Nl32[X_AVENRUN].n_value == 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: nlist(%s, %s) ==> 0\n",
+ _PATH_UNIX, LA_AVENRUN);
+ }
+ else
+ kernel_type = getla_32;
+ }
+ else if (errno != 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: nlist(%s): %s\n",
+ _PATH_UNIX, errstring(errno));
+ }
+ else
+ {
+ if (tTd(3, 20))
+ printf("getla: Kernel is not 32bit\n");
+ }
+
+ /* Try 64 bit kernel ... */
+ errno = 0;
+ if (nlist64(_PATH_UNIX, Nl64) == 0)
+ {
+ if (tTd(3, 20))
+ printf("getla: Kernel is 64bit\n");
+
+ if (Nl64[X_AVENRUN].n_value == 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: nlist(%s, %s) ==> 0\n",
+ _PATH_UNIX, LA_AVENRUN);
+ }
+ else
+ kernel_type = getla_64;
+ }
+ else if (errno != 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: nlist64(%s): %s\n",
+ _PATH_UNIX, errstring(errno));
+ }
+ else
+ {
+ if (tTd(3, 20))
+ printf("getla: Kernel is not 64bit\n");
+ }
+ }
+
+ if (kernel_type == getla_none)
+ {
+ if (tTd(3, 1))
+ printf("getla: Failed to determine kernel type\n");
+ return -1;
+ }
+
+ if (kmem < 0)
+ {
+ kmem = open(_PATH_KMEM, 0, 0);
+ if (kmem < 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: open(/dev/kmem): %s\n",
+ errstring(errno));
+ return -1;
+ }
+ (void) fcntl(kmem, F_SETFD, 1);
+ }
+
+ switch (kernel_type)
+ {
+ case getla_32:
+ if (lseek(kmem, (off_t) Nl32[X_AVENRUN].n_value, SEEK_SET) == -1 ||
+ read(kmem, (char *) avenrun32, sizeof(avenrun32)) < sizeof(avenrun32))
+ {
+ if (tTd(3, 1))
+ printf("getla: lseek or read: %s\n",
+ errstring(errno));
+ return -1;
+ }
+ if (tTd(3, 5))
+ {
+ printf("getla: avenrun{32} = %ld",
+ (long int) avenrun32[0]);
+ if (tTd(3, 15))
+ printf(", %ld, %ld",
+ (long int)avenrun32[1],
+ (long int)avenrun32[2]);
+ printf("\n");
+ }
+ if (tTd(3, 1))
+ printf("getla: %d\n",
+ (int) (avenrun32[0] + FSCALE/2) >> FSHIFT);
+ return ((int) (avenrun32[0] + FSCALE/2) >> FSHIFT);
+
+ case getla_64:
+ /* Using of lseek64 is perhaps overkill ... */
+ if (lseek64(kmem, (off64_t) Nl64[X_AVENRUN].n_value, SEEK_SET) == -1 ||
+ read(kmem, (char *) avenrun64, sizeof(avenrun64)) <
+ sizeof(avenrun64))
+ {
+ if (tTd(3, 1))
+ printf("getla: lseek64 or read: %s\n",
+ errstring(errno));
+ return -1;
+ }
+ if (tTd(3, 5))
+ {
+ printf("getla: avenrun{64} = %lld",
+ (long long int) avenrun64[0]);
+ if (tTd(3, 15))
+ printf(", %lld, %lld",
+ (long long int) avenrun64[1],
+ (long long int) avenrun64[2]);
+ printf("\n");
+ }
+ if (tTd(3, 1))
+ printf("getla: %d\n",
+ (int) (avenrun64[0] + FSCALE/2) >> FSHIFT);
+ return ((int) (avenrun64[0] + FSCALE/2) >> FSHIFT);
+ }
+ return -1;
+}
+#endif
+
+#if LA_TYPE == LA_KSTAT
+
+#include <kstat.h>
+
+int
+getla()
+{
+ kstat_ctl_t *kc;
+ kstat_t *ksp;
+ kstat_named_t *ksn;
+ int la;
+
+ kc = kstat_open();
+ if (kc == NULL)
+ {
+ if (tTd(3, 1))
+ printf("getla: kstat_open(): %s\n",
+ errstring(errno));
+ return -1;
+ }
+ ksp = kstat_lookup(kc, "unix", 0, "system_misc"); /* NULL on error */
+ if (ksp == NULL)
+ {
+ if (tTd(3, 1))
+ printf("getla: kstat_lookup(): %s\n",
+ errstring(errno);
+ return -1;
+ }
+ if (kstat_read(kc, ksp, NULL) < 0)
+ {
+ if (tTd(3, 1))
+ printf("getla: kstat_read(): %s\n",
+ errstring(errno);
+ return -1;
+ }
+ ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
+ la = (ksn->value.ul + FSCALE/2) >> FSHIFT;
+ kstat_close(kc);
+ 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
+
+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)
+ {
+ syslog(LOG_ERR, "can't open %s: %m", _PATH_AVENRUN);
+ return -1;
+ }
+ }
+
+ r = read(afd, &avenrun, sizeof avenrun);
+
+ if (tTd(3, 5))
+ printf("getla: avenrun = %d\n", avenrun);
+ loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
+ if (tTd(3, 1))
+ printf("getla: %d\n", loadav);
+ return loadav;
+}
+
+#endif /* LA_TYPE == LA_DEVSHORT */
+
#if LA_TYPE == LA_ZERO
+int
getla()
{
if (tTd(3, 1))
@@ -1531,7 +1894,6 @@ getla()
#endif /* LA_TYPE == LA_ZERO */
-
/*
* Copyright 1989 Massachusetts Institute of Technology
*
@@ -1600,7 +1962,7 @@ shouldqueue(pri, ctime)
bool rval;
if (tTd(3, 30))
- printf("shouldqueue: CurrentLA=%d, pri=%d: ", CurrentLA, pri);
+ printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri);
if (CurrentLA < QueueLA)
{
if (tTd(3, 30))
@@ -1624,7 +1986,7 @@ shouldqueue(pri, ctime)
** REFUSECONNECTIONS -- decide if connections should be refused
**
** Parameters:
-** none.
+** port -- port number (for error messages only)
**
** Returns:
** TRUE if incoming SMTP connections should be refused
@@ -1636,8 +1998,12 @@ shouldqueue(pri, ctime)
*/
bool
-refuseconnections()
+refuseconnections(port)
+ int port;
{
+ time_t now;
+ static time_t lastconn = (time_t) 0;
+ static int conncnt = 0;
extern bool enoughdiskspace();
extern void setproctitle __P((const char *, ...));
@@ -1646,24 +2012,67 @@ refuseconnections()
return TRUE;
#endif
+ now = curtime();
+ if (now != lastconn)
+ {
+ lastconn = now;
+ conncnt = 0;
+ }
+ else if (conncnt++ > ConnRateThrottle && ConnRateThrottle > 0)
+ {
+ /* sleep to flatten out connection load */
+ setproctitle("deferring connections on port %d: %d per second",
+ port, ConnRateThrottle);
+#ifdef LOG
+ if (LogLevel >= 14)
+ syslog(LOG_INFO, "deferring connections on port %d: %d per second",
+ port, ConnRateThrottle);
+#endif
+ sleep(1);
+ }
+
+ CurrentLA = getla();
if (CurrentLA >= RefuseLA)
{
- setproctitle("rejecting connections: load average: %d",
- CurrentLA);
+ setproctitle("rejecting connections on port %d: load average: %d",
+ port, CurrentLA);
+#ifdef LOG
+ if (LogLevel >= 14)
+ syslog(LOG_INFO, "rejecting connections on port %d: load average: %d",
+ port, CurrentLA);
+#endif
+ return TRUE;
}
- else if (!enoughdiskspace(MinBlocksFree + 1))
+
+ if (!enoughdiskspace(MinBlocksFree + 1))
{
- setproctitle("rejecting connections: min free: %d",
- MinBlocksFree);
+ setproctitle("rejecting connections on port %d: min free: %d",
+ port, MinBlocksFree);
+#ifdef LOG
+ if (LogLevel >= 14)
+ syslog(LOG_INFO, "rejecting connections on port %d: min free: %d",
+ port, MinBlocksFree);
+#endif
+ return TRUE;
}
- else if (MaxChildren > 0 && CurChildren >= MaxChildren)
+
+ if (MaxChildren > 0 && CurChildren >= MaxChildren)
{
- setproctitle("rejecting connections: maximum children: %d",
- CurChildren);
+ proc_list_probe();
+ if (CurChildren >= MaxChildren)
+ {
+ setproctitle("rejecting connections on port %d: %d children, max %d",
+ port, CurChildren, MaxChildren);
+#ifdef LOG
+ if (LogLevel >= 14)
+ syslog(LOG_INFO, "rejecting connections on port %d: %d children, max %d",
+ port, CurChildren, MaxChildren);
+#endif
+ return TRUE;
+ }
}
- else
- return FALSE;
- return TRUE;
+
+ return FALSE;
}
/*
** SETPROCTITLE -- set process title for ps
@@ -1818,7 +2227,7 @@ setproctitle(fmt, va_alist)
/* print the argument string */
VA_START(fmt);
- (void) vsnprintf(p, sizeof buf - (p - buf), fmt, ap);
+ (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
VA_END;
i = strlen(buf);
@@ -1847,7 +2256,7 @@ setproctitle(fmt, va_alist)
}
buf[PSARGSZ - 1] = '\0';
seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
- if (lseek(kmem, (char *) seek_off, SEEK_SET) == seek_off)
+ if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
(void) write(kmem, buf, PSARGSZ);
# endif
# if SPT_TYPE == SPT_REUSEARGV
@@ -1884,10 +2293,10 @@ reapchild(sig)
int sig;
{
int olderrno = errno;
+ pid_t pid;
# ifdef HASWAITPID
auto int status;
int count;
- int pid;
count = 0;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
@@ -1895,24 +2304,26 @@ reapchild(sig)
if (count++ > 1000)
{
#ifdef LOG
- syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x",
- pid, status);
+ if (LogLevel > 0)
+ syslog(LOG_ALERT,
+ "reapchild: waitpid loop: pid=%d, status=%x",
+ pid, status);
#endif
break;
}
- CurChildren--;
+ proc_list_drop(pid);
}
# else
# ifdef WNOHANG
union wait status;
- while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
- CurChildren--;
+ while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
+ proc_list_drop(pid);
# else /* WNOHANG */
auto int status;
- while (wait(&status) > 0)
- CurChildren--;
+ while ((pid = wait(&status)) > 0)
+ proc_list_drop(pid);
# endif /* WNOHANG */
# endif
# ifdef SYS5SIGNALS
@@ -1953,7 +2364,7 @@ putenv(str)
* find out how much of str to match when searching
* for a string to replace.
*/
- if ((tmp = index(str, '=')) == NULL || tmp == str)
+ if ((tmp = strchr(str, '=')) == NULL || tmp == str)
matchlen = strlen(str);
else
matchlen = (int) (tmp - str);
@@ -2317,7 +2728,7 @@ getopt(nargc,nargv,ostr)
if (!*place) ++optind;
tell(": illegal option -- ");
}
- if (*++oli != ':') { /* don't need argument */
+ if (oli && *++oli != ':') { /* don't need argument */
optarg = NULL;
if (!*place) ++optind;
}
@@ -2402,6 +2813,7 @@ vsprintf(s, fmt, ap)
static void dopr();
static char *end;
+static int SnprfOverflow;
/* VARARGS3 */
int
@@ -2415,30 +2827,34 @@ snprintf(str, count, fmt, va_alist)
va_dcl
#endif
{
- VA_LOCAL_DECL
+ int len;
+ VA_LOCAL_DECL
- VA_START (fmt);
- (void) vsnprintf ( str, count, fmt, ap);
- VA_END;
- return( strlen( str ) );
+ 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;
+ char *str;
+ size_t count;
+ const char *fmt;
+ va_list args;
{
- str[0] = 0;
- end = str+count-1;
- dopr( str, fmt, args );
- if( count>0 ){
- end[0] = 0;
- }
- return(strlen(str));
+ str[0] = 0;
+ end = str + count - 1;
+ SnprfOverflow = 0;
+ dopr( str, fmt, args );
+ if (count > 0)
+ end[0] = 0;
+ if (SnprfOverflow && tTd(57, 2))
+ printf("\nvsnprintf overflow, len = %d, str = %s",
+ count, shortenstring(str, 203));
+ return strlen(str);
}
/*
@@ -2537,8 +2953,11 @@ dopr( buffer, format, args )
fmtnum( value,-16,0, ljust, len, zpad ); break;
case 's':
strvalue = va_arg( args, char *);
- if (maxwidth > 0 || !pointflag)
+ 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 );
@@ -2662,14 +3081,14 @@ dopr_outch( c )
#if 0
if( iscntrl(c) && c != '\n' && c != '\t' ){
c = '@' + (c & 0x1F);
- if( end == 0 || output < end ){
+ if( end == 0 || output < end )
*output++ = '^';
- }
}
#endif
- if( end == 0 || output < end ){
+ if( end == 0 || output < end )
*output++ = c;
- }
+ else
+ SnprfOverflow++;
}
# endif /* !luna2 */
@@ -2693,7 +3112,7 @@ dopr_outch( c )
# define _PATH_SHELLS "/etc/shells"
# endif
-# ifdef _AIX3
+# if defined(_AIX3) || defined(_AIX4)
# include <userconf.h>
# include <usersec.h>
# endif
@@ -2721,7 +3140,7 @@ char *DefaultUserShells[] =
"/bin/posix/sh",
# endif
#endif
-#ifdef _AIX3
+#if defined(_AIX3) || defined(_AIX4)
"/bin/ksh", /* Korn shell */
"/usr/bin/ksh",
"/bin/tsh", /* trusted shell */
@@ -3253,9 +3672,9 @@ chownsafe(fd)
tfd = open(s, O_RDONLY|O_CREAT, 0600);
rval = fchown(tfd, DefUid, DefGid) != 0;
close(tfd);
- unlink(s);
setresuid(o_uid, o_euid, -1);
setresgid(o_gid, o_egid, -1);
+ unlink(s);
return rval;
#else
# ifdef _POSIX_CHOWN_RESTRICTED
@@ -3300,7 +3719,7 @@ chownsafe(fd)
*/
#if HASSETRLIMIT
-# ifdef apollo
+# ifdef RLIMIT_NEEDS_SYS_TIME_H
# include <sys/time.h>
# endif
# include <sys/resource.h>
@@ -3408,10 +3827,21 @@ setvendor(vendor)
** none.
*/
+#if SHARE_V1
+int DefShareUid; /* default share uid to run as -- unused??? */
+#endif
+
void
vendor_pre_defaults(e)
ENVELOPE *e;
{
+#if SHARE_V1
+ /* OTHERUID is defined in shares.h, do not be alarmed */
+ DefShareUid = OTHERUID;
+#endif
+#ifdef SUN_EXTENSIONS
+ sun_pre_defaults(e);
+#endif
}
@@ -3419,6 +3849,91 @@ void
vendor_post_defaults(e)
ENVELOPE *e;
{
+#ifdef SUN_EXTENSIONS
+ sun_post_defaults(e);
+#endif
+}
+ /*
+** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
+*/
+
+void
+vendor_daemon_setup(e)
+ ENVELOPE *e;
+{
+#if SECUREWARE
+ if (getluid() != -1)
+ {
+ usrerr("Daemon cannot have LUID");
+ exit(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 and auditing inforation (luid's)
+ ** before we loose our ``root''ness.
+ */
+#if SHARE_V1
+ if (setupshares(uid, syserr) != 0)
+ syserr("Unable to set up shares");
+#endif
+#if SECUREWARE
+ (void) setup_secure(uid);
+#endif
+}
+ /*
+** 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:
+** TRUE -- if the connection should be accepted.
+** FALSE -- if it should be rejected.
+*/
+
+#if TCPWRAPPERS
+# include <tcpd.h>
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+#endif
+
+bool
+validate_connection(sap, hostname, e)
+ SOCKADDR *sap;
+ char *hostname;
+ ENVELOPE *e;
+{
+ if (rscheck("check_relay", hostname, anynet_ntoa(sap), e) != EX_OK)
+ return FALSE;
+
+#if TCPWRAPPERS
+ if (!hosts_ctl("sendmail", hostname, anynet_ntoa(sap), STRING_UNKNOWN))
+ return FALSE;
+#endif
+ return TRUE;
}
/*
** STRTOL -- convert string to long integer
@@ -3576,8 +4091,8 @@ sm_gethostbyname(name)
char *name;
{
struct hostent *h;
-#if defined(SOLARIS) && SOLARIS < 204 || defined(sony_news) && defined(__svr4)
-# if SOLARIS == 203
+#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();
@@ -3614,7 +4129,7 @@ sm_gethostbyname(name)
if (nmaps >= 0)
{
/* try short name */
- if (strlen(name) > sizeof hbuf - 1)
+ if (strlen(name) > (SIZE_T) sizeof hbuf - 1)
return NULL;
strcpy(hbuf, name);
shorten_hostname(hbuf);
@@ -3645,8 +4160,8 @@ sm_gethostbyaddr(addr, len, type)
int len;
int type;
{
-#if defined(SOLARIS) && SOLARIS < 204
-# if SOLARIS == 203
+#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
+# if SOLARIS == 20300 || SOLARIS == 203
static struct hostent hp;
static char buf[1000];
extern struct hostent *_switch_gethostbyaddr_r();
@@ -3679,6 +4194,68 @@ sm_getpwuid(uid)
return getpwuid(uid);
}
/*
+** 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 <sys/security.h>
+# include <prot.h>
+
+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;
+ }
+ exit(EX_NOPERM);
+ }
+}
+#endif /* SECUREWARE */
+ /*
** LOAD_IF_NAMES -- load interface-specific names into $=w
**
** Parameters:
@@ -3724,7 +4301,6 @@ load_if_names()
close(s);
return;
}
- close(s);
/* scan the list of IP address */
if (tTd(0, 40))
@@ -3737,6 +4313,9 @@ load_if_names()
struct sockaddr *sa = &ifr->ifr_addr;
struct in_addr ia;
struct hostent *hp;
+#ifdef SIOCGIFFLAGS
+ struct ifreq ifrf;
+#endif
char ip_addr[256];
extern char *inet_ntoa();
extern struct hostent *gethostbyaddr();
@@ -3751,19 +4330,35 @@ load_if_names()
if (tTd(0, 20))
printf("%s\n", anynet_ntoa((SOCKADDR *) sa));
- /* for some reason gcc 2.3 pukes on || here */
- if (!bitset(IFF_UP, ifr->ifr_flags))
- continue;
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
+#ifdef SIOCGIFFLAGS
+ bzero(&ifrf, sizeof(struct ifreq));
+ strncpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name));
+ ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
+ if (tTd(0, 41))
+ printf("\tflags: %x\n", ifrf.ifr_flags);
+ if (!bitset(IFF_UP, ifrf.ifr_flags))
+ continue;
+#else
+ if (!bitset(IFF_UP, ifr->ifr_flags))
+ continue;
+#endif
+
/* extract IP address from the list*/
ia = (((struct sockaddr_in *) sa)->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]",
sizeof ip_addr - 3,
- inet_ntoa(((struct sockaddr_in *) sa)->sin_addr));
+ inet_ntoa(ia));
if (!wordinclass(ip_addr, 'w'))
{
setclass('w', ip_addr);
@@ -3779,8 +4374,12 @@ load_if_names()
hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET);
if (hp == NULL)
{
- syslog(LOG_CRIT, "gethostbyaddr() failed for %.100s\n",
- inet_ntoa(ia));
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_WARNING,
+ "gethostbyaddr() failed for %.100s\n",
+ inet_ntoa(ia));
+#endif
continue;
}
@@ -3804,6 +4403,7 @@ load_if_names()
hp->h_aliases++;
}
}
+ close(s);
#endif
}
/*
@@ -3817,14 +4417,21 @@ load_if_names()
# define MAXSYSLOGTRIES 100
# undef syslog
+# ifdef V4FS
+# define XCNST const
+# define CAST (const char *)
+# else
+# define XCNST
+# define CAST
+# endif
-# ifdef __STDC__
void
-hard_syslog(int pri, char *msg, ...)
+# ifdef __STDC__
+hard_syslog(int pri, XCNST char *msg, ...)
# else
hard_syslog(pri, msg, va_alist)
int pri;
- char *msg;
+ XCNST char *msg;
va_dcl
# endif
{
@@ -3836,10 +4443,11 @@ hard_syslog(pri, msg, va_alist)
vsnprintf(buf, sizeof buf, msg, ap);
VA_END;
- for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; )
+ for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
continue;
}
+# undef CAST
#endif
/*
** LOCAL_HOSTNAME_LENGTH
@@ -3885,12 +4493,18 @@ char *CompileOptions[] =
#if HES_GETMAILHOST
"HES_GETMAILHOST",
#endif
+#if LDAPMAP
+ "LDAPMAP",
+#endif
#ifdef LOG
"LOG",
#endif
#if MATCHGECOS
"MATCHGECOS",
#endif
+#if MIME7TO8
+ "MIME7TO8",
+#endif
#if MIME8TO7
"MIME8TO7",
#endif
@@ -3927,12 +4541,24 @@ char *CompileOptions[] =
#if NISPLUS
"NISPLUS",
#endif
+#if QUEUE
+ "QUEUE",
+#endif
#if SCANF
"SCANF",
#endif
+#if SMTP
+ "SMTP",
+#endif
+#if SMTPDEBUG
+ "SMTPDEBUG",
+#endif
#if SUID_ROOT_FILES_OK
"SUID_ROOT_FILES_OK",
#endif
+#if TCPWRAPPERS
+ "TCPWRAPPERS",
+#endif
#if USERDB
"USERDB",
#endif
@@ -3958,6 +4584,9 @@ char *OsCompileOptions[] =
#if HASFLOCK
"HASFLOCK",
#endif
+#if HASGETDTABLESIZE
+ "HASGETDTABLESIZE",
+#endif
#if HASGETUSERSHELL
"HASGETUSERSHELL",
#endif
@@ -3970,18 +4599,36 @@ char *OsCompileOptions[] =
#if HASSETREUID
"HASSETREUID",
#endif
+#if HASSETRLIMIT
+ "HASSETRLIMIT",
+#endif
#if HASSETSID
"HASSETSID",
#endif
+#if HASSETUSERCONTEXT
+ "HASSETUSERCONTEXT",
+#endif
#if HASSETVBUF
"HASSETVBUF",
#endif
+#if HASSIGSETMASK
+ "HASSIGSETMASK",
+#endif
#if HASSNPRINTF
"HASSNPRINTF",
#endif
+#if HASULIMIT
+ "HASULIMIT",
+#endif
#if HASUNAME
"HASUNAME",
#endif
+#if HASUNSETENV
+ "HASUNSETENV",
+#endif
+#if HASWAITPID
+ "HASWAITPID",
+#endif
#if IDENTPROTO
"IDENTPROTO",
#endif
@@ -3994,12 +4641,24 @@ char *OsCompileOptions[] =
#if NOFTRUNCATE
"NOFTRUNCATE",
#endif
+#if RLIMIT_NEEDS_SYS_TIME_H
+ "RLIMIT_NEEDS_SYS_TIME_H",
+#endif
+#if SECUREWARE
+ "SECUREWARE",
+#endif
+#if SHARE_V1
+ "SHARE_V1",
+#endif
#if SYS5SETPGRP
"SYS5SETPGRP",
#endif
#if SYSTEM5
"SYSTEM5",
#endif
+#if USE_SA_SIGACTION
+ "USE_SA_SIGACTION",
+#endif
#if USESETEUID
"USESETEUID",
#endif
diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h
index 6f7f8c9200b8..0c3729b6c848 100644
--- a/usr.sbin/sendmail/src/conf.h
+++ b/usr.sbin/sendmail/src/conf.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)conf.h 8.220 (Berkeley) 11/29/95
+ * @(#)conf.h 8.272 (Berkeley) 11/16/96
*/
/*
@@ -41,7 +41,9 @@
** included in the next release.
*/
+#ifdef __GNUC__
struct rusage; /* forward declaration to get gcc to shut up in wait.h */
+#endif
# include <sys/param.h>
# include <sys/types.h>
@@ -66,7 +68,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define MAXMAILERS 25 /* maximum mailers known to system */
# define MAXRWSETS 200 /* max # of sets of rewriting rules */
# define MAXPRIORITIES 25 /* max values for Precedence: field */
-# define MAXMXHOSTS 20 /* max # of MX records */
+# define 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 */
@@ -183,9 +185,6 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
# endif
# define syslog hard_syslog
-# ifdef __STDC__
-extern void hard_syslog(int, char *, ...);
-# endif
# ifdef V4FS
/* HP-UX 10.x */
@@ -205,12 +204,29 @@ extern void hard_syslog(int, char *, ...);
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
+# ifdef __STDC__
+extern void hard_syslog(int, char *, ...);
+# endif
# endif
#endif
/*
+** IBM AIX 4.x
+*/
+
+#ifdef _AIX4
+# define _AIX3 1 /* pull in AIX3 stuff */
+# define USESETEUID 1 /* seteuid(2) works */
+# define TZ_TYPE TZ_NAME /* use tzname[] vector */
+# if _AIX4 >= 40200
+# define HASSETREUID 1 /* setreuid(2) works as of AIX 4.2 */
+# endif
+#endif
+
+
+/*
** IBM AIX 3.x -- actually tested for 3.2.3
*/
@@ -222,29 +238,89 @@ extern void hard_syslog(int, char *, ...);
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
-# define FORK fork /* no vfork primitive available */
# define GIDSET_T gid_t
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# define SPT_PADCHAR '\0' /* pad process title with nulls */
# define LA_TYPE LA_INT
+# define FSHIFT 16
# define LA_AVENRUN "avenrun"
#endif
/*
+** IBM AIX 2.2.1 -- actually tested for osupdate level 2706+1773
+**
+** From Mark Whetzel <markw@wg.waii.com>.
+*/
+
+#ifdef AIX /* AIX/RT compiler pre-defines this */
+# include <paths.h>
+# include <sys/time.h> /* 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 <sys/statfs.h> 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 */
+# define _PATH_VENDORCF "/usr/local/newmail/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid"
+# endif
+#endif
+
+
+/*
** Silicon Graphics IRIX
**
** Compiles on 4.0.1.
**
** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0).
** Use IRIX5 instead of IRIX for IRIX 5.x.
+**
+** 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 <ml@cvdev.rochester.edu>.
** IRIX5 changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>.
+** Adaptive changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>.
*/
-#if defined(IRIX64) || defined(IRIX5)
-# define IRIX
+#if defined(__sgi)
+# ifndef IRIX
+# define IRIX
+# endif
+# if _MIPS_SIM > 0 && !defined(IRIX5)
+# define IRIX5 /* IRIX5 or IRIX6 */
+# endif
+# if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64)
+# define IRIX6 /* IRIX6 */
+# endif
+
#endif
#ifdef IRIX
@@ -254,18 +330,24 @@ extern void hard_syslog(int, char *, ...);
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define IP_SRCROUTE 1 /* can check IP source routing */
-# define FORK fork /* no vfork primitive available */
# define setpgid BSDsetpgrp
# define GIDSET_T gid_t
# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
# define SFS_BAVAIL f_bfree /* alternate field name */
-# define LA_TYPE LA_INT
-# ifdef IRIX64
-# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */
+# ifdef IRIX6
+# define LA_TYPE LA_IRIX6 /* figure out at run time */
# else
-# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
+# define LA_TYPE LA_INT
+
+# ifdef IRIX64
+# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */
+# else
+# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
+# endif
# endif
-# if defined(IRIX64) || defined(IRIX5)
+# if defined(IRIX64) || defined(IRIX5)
+# include <sys/cdefs.h>
+# include <paths.h>
# define ARGV_T char *const *
# define HASSETRLIMIT 1 /* has setrlimit(2) syscall */
# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */
@@ -290,10 +372,16 @@ extern void hard_syslog(int, char *, ...);
# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define IP_SRCROUTE 1 /* can check IP source routing */
-# define LA_TYPE LA_INT
+# ifndef LA_TYPE
+# define LA_TYPE LA_INT
+# endif
# ifdef SOLARIS_2_3
-# define SOLARIS 203 /* for back compat only -- use -DSOLARIS=203 */
+# define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */
+# endif
+
+# if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4))
+# define SOLARIS 1 /* unknown Solaris version */
# endif
# ifdef SOLARIS
@@ -303,6 +391,7 @@ extern void hard_syslog(int, char *, ...);
# endif
# include <sys/time.h>
# define GIDSET_T gid_t
+# define USE_SA_SIGACTION 1 /* use sa_sigaction field */
# ifndef _PATH_UNIX
# define _PATH_UNIX "/dev/ksyms"
# endif
@@ -316,6 +405,23 @@ extern void hard_syslog(int, char *, ...);
# ifndef SYSLOG_BUFSIZE
# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
# endif
+# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203)
+# define USESETEUID 1 /* seteuid works as of 2.3 */
+# endif
+# if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205)
+# define HASSNPRINTF 1 /* has snprintf starting in 2.5 */
+# define HASSETREUID 1 /* setreuid works as of 2.5 */
+# if SOLARIS == 20500 || SOLARIS == 205
+# define snprintf __snprintf /* but names it oddly in 2.5 */
+# define vsnprintf __vsnprintf
+# endif
+# ifndef LA_TYPE
+# define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */
+# endif
+# endif
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
+# endif
# else
/* SunOS 4.0.3 or 4.1.x */
@@ -432,8 +538,6 @@ extern long dgux_inet_addr();
#ifdef __ksr__
# define __osf__ 1 /* get OSF/1 defines below */
-# define FORK fork /* no vfork primitive available */
-# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
# ifndef TZ_TYPE
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# endif
@@ -449,12 +553,16 @@ extern long dgux_inet_addr();
#ifdef __PARAGON__
# define __osf__ 1 /* get OSF/1 defines below */
-# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
+# endif
#endif
/*
-** OSF/1 (tested on Alpha)
+** OSF/1 (tested on Alpha) -- now known as Digital UNIX.
+**
+** Tested for 3.2 and 4.0.
*/
#ifdef __osf__
@@ -468,6 +576,7 @@ extern long dgux_inet_addr();
# endif
# define LA_TYPE LA_INT
# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
# endif
@@ -487,6 +596,8 @@ extern long dgux_inet_addr();
# 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 sleep sleepX
# define setpgid setpgrp
# ifndef LA_TYPE
@@ -512,6 +623,7 @@ typedef int pid_t;
*/
#if defined(BSD4_4) && !defined(__bsdi__)
+# include <paths.h>
# define HASUNSETENV 1 /* has unsetenv(3) call */
# define USESETEUID 1 /* has useable seteuid(2) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
@@ -529,11 +641,12 @@ typedef int pid_t;
/*
-** BSD/386 (all versions)
+** BSD/OS (was BSD/386) (all versions)
** From Tony Sanders, BSDI
*/
#ifdef __bsdi__
+# include <paths.h>
# define HASUNSETENV 1 /* has the unsetenv(3) call */
# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
# define USESETEUID 1 /* has useable seteuid(2) call */
@@ -592,24 +705,25 @@ typedef int pid_t;
# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1)
# undef SPT_TYPE
# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */
-# define setreuid __setreuid
# endif
# if defined(__FreeBSD__)
# undef SPT_TYPE
# if __FreeBSD__ == 2
-# if !defined(DONT_HAVE_SETPROCTITLE) /* add to the Makefile for < 2.0.5 */
-# define SPT_TYPE SPT_BUILTIN
+# include <osreldate.h> /* and this works */
+# if __FreeBSD_version >= 199512 /* 2.2-current right now */
# include <libutil.h>
+# define SPT_TYPE SPT_BUILTIN
# endif
# endif
# ifndef SPT_TYPE
# define SPT_TYPE SPT_REUSEARGV
-# define SPT_PADCHAR '\0' /* pad process title with nulls */
+# define SPT_PADCHAR '\0' /* pad process title with nulls */
# endif
# endif
#endif
+
/*
** Mach386
**
@@ -671,36 +785,76 @@ extern int errno;
/*
** SCO Unix
**
-** This includes two parts -- the first is for SCO Open Server 3.2v4
-** (contributed by Philippe Brand <phb@colombo.telesys-innov.fr>).
-** The second is, I believe, for an older version.
+** This includes three parts:
+**
+** The first is for SCO OpenServer 5.
+** (Contributed by Keith Reynolds <keithr@sco.COM>).
+**
+** 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 <phb@colombo.telesys-innov.fr>).
+**
+** The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier.
*/
+/* SCO OpenServer 5 */
+#if _SCO_DS >= 1
+# include <paths.h>
+# define _SCO_unix_4_2
+# define HASSNPRINTF 1 /* has snprintf(3) call */
+# define HASFCHMOD 1 /* has fchmod(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
+# define _PATH_AVENRUN "/dev/table/avenrun"
+#endif
+
+/* SCO UNIX 3.2v4.2/Open Desktop 3.0 */
#ifdef _SCO_unix_4_2
# define _SCO_unix_
# define HASSETREUID 1 /* has setreuid(2) call */
-# define _PATH_UNIX "/unix"
-# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
-# ifndef _PATH_SENDMAILPID
-# define _PATH_SENDMAILPID "/etc/sendmail.pid"
-# endif
#endif
+/* SCO UNIX 3.2v4.0 Open Desktop 2.0 and earlier */
#ifdef _SCO_unix_
# include <sys/stream.h> /* needed for IP_SRCROUTE */
# define SYSTEM5 1 /* include all the System V defines */
-# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
-# define NOFTRUNCATE 0 /* does not have ftruncate(3) call */
-# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
-# define FORK fork
+# define NOFTRUNCATE 0 /* has (simulated) ftruncate call */
# define MAXPATHLEN PATHSIZE
-# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_4ARGS /* use <sys/statfs.h> 4-arg impl */
# define SFS_BAVAIL f_bfree /* alternate field name */
# define SPT_TYPE SPT_SCO /* write kernel u. area */
# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
-# define NETUNIX 0 /* no unix domain socket support */
+# define UID_T uid_t
+# define GID_T gid_t
+# define GIDSET_T gid_t
+# define _PATH_UNIX "/unix"
+# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+
+/* stuff fixed in later releases */
+# ifndef _SCO_unix_4_2
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# endif
+
+# 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
+
#endif
@@ -720,7 +874,6 @@ extern int errno;
# define HASSETREUID 1 /* has setreuid(2) call */
# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
# define NETUNIX 0 /* no unix domain socket support */
-# define FORK fork
# define MAXPATHLEN 1024
# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
@@ -735,22 +888,24 @@ extern int errno;
/*
-** Altos System V.
-** Contributed by Tim Rice <timr@crl.com>.
+** Altos System V (5.3.1)
+** Contributed by Tim Rice <tim@trr.metro.net>.
*/
-#ifdef ALTOS_SYS_V
+#ifdef ALTOS_SYSTEM_V
+# include <sys/stream.h>
+# include <limits.h>
# define SYSTEM5 1 /* include all the System V defines */
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define WAITUNION 1 /* use "union wait" as wait argument type */
# define NEEDFSYNC 1 /* no fsync(2) in system library */
-# define FORK fork
-# define MAXPATHLEN PATHSIZE
+# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */
+# define MAXPATHLEN PATH_MAX
# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# define SFS_BAVAIL f_bfree /* alternate field name */
-# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
+# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# define NETUNIX 0 /* no unix domain socket support */
# undef WIFEXITED
# undef WEXITSTATUS
@@ -759,6 +914,17 @@ extern int errno;
typedef unsigned short uid_t;
typedef unsigned short gid_t;
typedef short pid_t;
+
+/* some stuff that should have been in the include files */
+# include <grp.h>
+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
@@ -767,13 +933,26 @@ typedef short pid_t;
**
** "Todd C. Miller" <millert@mroe.cs.colorado.edu> 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 BSD 1 /* include all the BSD defines */
+# 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 NEEDGETOPT 1 /* need replacement for getopt(3) */
+# 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 <sys/vfs.h> statfs() implementation */
@@ -786,8 +965,23 @@ typedef short pid_t;
# define S_IFCHR _S_IFCHR
# define S_IFBLK _S_IFBLK
# endif
+# ifndef TZ_TYPE
+# define TZ_TYPE TZ_TIMEZONE
+# endif
# ifndef IDENTPROTO
-# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# define IDENTPROTO 1
+# endif
+# ifndef SHARE_V1
+# define SHARE_V1 1 /* version 1 of the fair share scheduler */
+# endif
+# if !defined(__GNUC__ )
+# define UID_T int /* GNUC gets it right, ConvexC botches */
+# define GID_T int /* GNUC gets it right, ConvexC botches */
+# endif
+# if SECUREWARE
+# define FORK fork /* SecureWare wants the real fork! */
+# else
+# define FORK vfork /* the rest of the OS versions don't care */
# endif
#endif
@@ -838,9 +1032,14 @@ extern void *malloc();
** Florian La Roche <rzsfl@rz.uni-sb.de>
** Karl London <karl@borg.demon.co.uk>
**
-** Last compiled against: [09/06/95 @ 10:20:58 AM (Wednesday)]
-** sendmail 8.7-b14 named 4.9.3-beta17 db-1.85
-** gcc 2.7.0 libc-5.2.7 linux 1.2.13
+** Last compiled against: [06/10/96 @ 09:21:40 PM (Monday)]
+** sendmail 8.8-a4 named bind-4.9.4-T4B db-1.85
+** gcc 2.7.2 libc-5.3.12 linux 2.0.0
+**
+** 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__
@@ -856,7 +1055,12 @@ extern void *malloc();
# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */
# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */
# ifndef HASFLOCK
-# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */
+# include <linux/version.h>
+# if LINUX_VERSION_CODE < 66399
+# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */
+# else
+# define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */
+# endif
# endif
# ifndef LA_TYPE
# define LA_TYPE LA_PROCSTR
@@ -906,7 +1110,6 @@ extern void *malloc();
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
-# define FORK fork
# ifndef LA_TYPE
# define LA_TYPE LA_INT
# define FSHIFT 16
@@ -936,7 +1139,6 @@ extern void *malloc();
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
-# define FORK fork /* no vfork(2) primitive available */
# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
# define MAXPATHLEN PATH_MAX
extern struct passwd *getpwent(), *getpwnam(), *getpwuid();
@@ -1009,9 +1211,12 @@ typedef int pid_t;
** For DYNIX/ptx v1.x, undefine HASSETREUID.
**
** From Tim Wright <timw@sequent.com>.
+** Update from Jack Woolley <jwoolley@sctcorp.com>, 26 Dec 1995,
+** for DYNIX/ptx 4.0.2.
*/
#ifdef _SEQUENT_
+# include <sys/stream.h>
# define SYSTEM5 1 /* include all the System V defines */
# define HASSETSID 1 /* has POSIX setsid(2) call */
# define HASINITGROUPS 1 /* has initgroups(3) call */
@@ -1075,6 +1280,7 @@ typedef int pid_t;
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
+# define RLIMIT_NEEDS_SYS_TIME_H 1
#endif
@@ -1137,18 +1343,30 @@ typedef int pid_t;
/*
-** NCR 3000 Series (SysVr4)
+** NCR MP-RAS 2.x (SysVr4) with Wollongong TCP/IP
**
** From Kevin Darcy <kevin@tech.mis.cfc.com>.
*/
-#ifdef NCR3000
+#ifdef NCR_MP_RAS2
# include <sys/sockio.h>
# define __svr4__
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
-# undef BSD
-# define LA_AVENRUN "avenrun"
# define SYSLOG_BUFSIZE 1024
+# define SPT_TYPE SPT_NONE
+#endif
+
+
+/*
+** NCR MP-RAS 3.x (SysVr4) with STREAMware TCP/IP
+**
+** From Tom Moore <Tom.Moore@DaytonOH.NCR.COM>
+*/
+
+#ifdef NCR_MP_RAS3
+# define __svr4__
+# define SYSLOG_BUFSIZE 1024
+# define SPT_TYPE SPT_NONE
#endif
@@ -1371,20 +1589,75 @@ extern int errno;
** Fujitsu/ICL UXP/DS (For the DS/90 Series)
**
** From Diego R. Lopez <drlopez@cica.es>.
+** Additional changes from Fumio Moriya and Toshiaki Nomura of the
+** Fujitsu Fresoftware gruop <dsfrsoft@oai6.yk.fujitsu.co.jp>.
*/
-#ifdef UXPDS
+#ifdef __uxp__
+# include <arpa/nameser.h>
+# include <sys/sysmacros.h>
+# include <sys/mkdev.h>
# define __svr4__
-# define HASGETUSERSHELL 1
+# define HASGETUSERSHELL 0
# define HASFLOCK 0
+# if UXPDS == 10
+# define HASSNPRINTF 0 /* no snprintf(3) or vsnprintf(3) */
+# else
+# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
+# endif
# define _PATH_UNIX "/stand/unix"
-# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
+# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf"
# ifndef _PATH_SENDMAILPID
-# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid"
+# endif
+#endif
+
+/*
+** Pyramid DC/OSx
+**
+** From Earle Ake <akee@wpdis01.wpafb.af.mil>.
+*/
+
+#ifdef DCOSx
+# define GIDSET_T gid_t
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
#endif
+/*
+** Concurrent Computer Corporation Maxion
+**
+** From Donald R. Laster Jr. <laster@access.digex.net>.
+*/
+
+#ifdef __MAXION__
+
+# include <sys/stream.h>
+# 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
+
+# undef WUNTRACED
+# undef WIFEXITED
+# undef WIFSIGNALED
+# undef WIFSTOPPED
+# undef WEXITSTATUS
+# undef WTERMSIG
+# undef WSTOPSIG
+#endif
/**********************************************************************
** End of Per-Operating System defines
@@ -1417,13 +1690,16 @@ extern int errno;
# define SYSTEM5 1
# define USESETEUID 1 /* has useable seteuid(2) call */
# define HASINITGROUPS 1 /* has initgroups(3) call */
-# define BSD_COMP 1 /* get BSD ioctl calls */
+# define BSD_COMP 1 /* get BSD ioctl calls */
# ifndef HASSETRLIMIT
# define HASSETRLIMIT 1 /* has setrlimit(2) call */
# endif
# ifndef HASGETUSERSHELL
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# endif
+# ifndef HASFCHMOD
+# define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */
+# endif
# ifndef _PATH_UNIX
# define _PATH_UNIX "/unix"
@@ -1441,6 +1717,7 @@ extern int errno;
# define SFS_TYPE SFS_STATVFS
# endif
+/* SVr4 uses different routines for setjmp/longjmp with signal support */
# define jmp_buf sigjmp_buf
# define setjmp(env) sigsetjmp(env, 1)
# define longjmp(env, val) siglongjmp(env, val)
@@ -1498,7 +1775,7 @@ extern int errno;
# undef bcopy /* despite SystemV claim, uses BSD bcopy */
#endif
-#ifdef ALTOS_SYS_V
+#ifdef ALTOS_SYSTEM_V
# undef bcopy /* despite SystemV claim, uses BSD bcopy */
# undef bzero /* despite SystemV claim, uses BSD bzero */
# undef bcmp /* despite SystemV claim, uses BSD bcmp */
@@ -1560,6 +1837,10 @@ extern int errno;
# define OLD_NEWDB 0 /* assume newer version of newdb */
#endif
+#ifndef SECUREWARE
+# define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */
+#endif
+
/* heuristic setting of HASSETSIGMASK; can override above */
#ifndef HASSIGSETMASK
# ifdef SIGVTALRM
@@ -1583,10 +1864,18 @@ extern int errno;
# define UID_T uid_t
#endif
+#ifndef GID_T
+# define GID_T gid_t
+#endif
+
#ifndef SIZE_T
# define SIZE_T size_t
#endif
+#ifndef MODE_T
+# define MODE_T mode_t
+#endif
+
#ifndef ARGV_T
# define ARGV_T char **
#endif
@@ -1600,6 +1889,9 @@ extern int errno;
#ifndef S_ISREG
# define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG)
#endif
+#ifndef S_ISDIR
+# define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR)
+#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK)
#endif
@@ -1728,7 +2020,7 @@ struct utsname
};
#endif /* HASUNAME */
-#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYS_V)
+#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V)
# define MAXHOSTNAMELEN 256
#endif
@@ -1808,9 +2100,10 @@ typedef void (*sigfunc_t) __P((int));
*/
# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */
+
/* fork routine -- set above using #ifdef _osname_ or in Makefile */
# ifndef FORK
-# define FORK vfork /* function to call to fork mailer */
+# define FORK fork /* function to call to fork mailer */
# endif
/*
diff --git a/usr.sbin/sendmail/src/convtime.c b/usr.sbin/sendmail/src/convtime.c
index adc38f73ed5f..807ae6c64dda 100644
--- a/usr.sbin/sendmail/src/convtime.c
+++ b/usr.sbin/sendmail/src/convtime.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)convtime.c 8.4.1.1 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)convtime.c 8.7 (Berkeley) 9/15/96";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
index 9a11969bf2c2..283d7e4b4ec1 100644
--- a/usr.sbin/sendmail/src/daemon.c
+++ b/usr.sbin/sendmail/src/daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -37,9 +37,9 @@
#ifndef lint
#ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.148 (Berkeley) 11/8/96 (with daemon mode)";
#else
-static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.148 (Berkeley) 11/8/96 (without daemon mode)";
#endif
#endif /* not lint */
@@ -70,7 +70,7 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** thing yourself, I recommend chucking the entire file
** and starting from scratch. Basic semantics are:
**
-** getrequests()
+** getrequests(e)
** Opens a port and initiates a connection.
** Returns in a child. Must set InChannel and
** OutChannel appropriately.
@@ -80,7 +80,7 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** etc., to avoid having extra file descriptors during
** the queue run and to avoid confusing the network
** code (if it cares).
-** makeconnection(host, port, outfile, infile, usesecureport)
+** 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
@@ -93,10 +93,12 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** GETREQUESTS -- open mail IPC port and get requests.
**
** Parameters:
-** none.
+** e -- the current envelope.
**
** Returns:
-** none.
+** TRUE -- if a "null server" should be used -- that is, one
+** that rejects all commands.
+** FALSE -- to use a normal server.
**
** Side Effects:
** Waits until some interesting activity occurs. When
@@ -113,8 +115,9 @@ int ListenQueueSize = 10; /* size of listen queue */
int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
int TcpSndBufferSize = 0; /* size of TCP send buffer */
-void
-getrequests()
+bool
+getrequests(e)
+ ENVELOPE *e;
{
int t;
bool refusingconnections = TRUE;
@@ -124,6 +127,7 @@ getrequests()
bool j_has_dot;
#endif
extern void reapchild();
+ extern int opendaemonsocket __P((bool));
/*
** Set up the address for the mailer.
@@ -166,7 +170,7 @@ getrequests()
extern char *CommandLineArgs;
/* write the process id on line 1 */
- fprintf(pidf, "%d\n", getpid());
+ fprintf(pidf, "%ld\n", (long) getpid());
/* line 2 contains all command line flags */
fprintf(pidf, "%s\n", CommandLineArgs);
@@ -179,7 +183,7 @@ getrequests()
{
char jbuf[MAXHOSTNAMELEN];
- expand("\201j", jbuf, sizeof jbuf, CurEnv);
+ expand("\201j", jbuf, sizeof jbuf, e);
j_has_dot = strchr(jbuf, '.') != NULL;
}
#endif
@@ -189,14 +193,13 @@ getrequests()
for (;;)
{
- register int pid;
+ register pid_t pid;
auto int lotherend;
extern bool refuseconnections();
extern int getla();
/* see if we are rejecting connections */
- CurrentLA = getla();
- if (refuseconnections())
+ if (refuseconnections(ntohs(DaemonAddr.sin.sin_port)))
{
if (DaemonSocket >= 0)
{
@@ -220,8 +223,9 @@ getrequests()
/* check for disaster */
{
char jbuf[MAXHOSTNAMELEN];
+ extern void dumpstate __P((char *));
- expand("\201j", jbuf, sizeof jbuf, CurEnv);
+ expand("\201j", jbuf, sizeof jbuf, e);
if (!wordinclass(jbuf, 'w'))
{
dumpstate("daemon lost $j");
@@ -238,7 +242,18 @@ getrequests()
#endif
/* wait for a connection */
- setproctitle("accepting connections");
+ setproctitle("accepting connections on port %d",
+ ntohs(DaemonAddr.sin.sin_port));
+#if 0
+ /*
+ ** Andrew Sun <asun@ieps-sun.ml.com> claims that this will
+ ** fix the SVr4 problem. But it seems to have gone away,
+ ** so is it worth doing this?
+ */
+
+ if (SetNonBlocking(DaemonSocket, FALSE) < 0)
+ log an error here;
+#endif
do
{
errno = 0;
@@ -277,9 +292,9 @@ getrequests()
if (pid == 0)
{
char *p;
- extern char *hostnamebyanyaddr();
extern void intsig();
FILE *inchannel, *outchannel;
+ bool nullconn;
/*
** CHILD -- return to caller.
@@ -296,7 +311,7 @@ getrequests()
/* determine host name */
p = hostnamebyanyaddr(&RealHostAddr);
- if (strlen(p) > MAXNAME)
+ if (strlen(p) > (SIZE_T) MAXNAME)
p[MAXNAME] = '\0';
RealHostName = newstr(p);
setproctitle("startup with %s", p);
@@ -313,7 +328,13 @@ getrequests()
OutChannel = outchannel;
DisConnected = FALSE;
- /* should we check for illegal connection here? XXX */
+ /* validate the connection */
+ HoldErrs = TRUE;
+ nullconn = !validate_connection(&RealHostAddr, RealHostName, e);
+ HoldErrs = FALSE;
+ if (nullconn)
+ break;
+
#ifdef XLA
if (!xla_host_ok(RealHostName))
{
@@ -323,16 +344,19 @@ getrequests()
#endif
if (tTd(15, 2))
- printf("getreq: returning\n");
- return;
+ printf("getreq: returning (normal server)\n");
+ return FALSE;
}
- CurChildren++;
+ /* parent -- keep track of children */
+ proc_list_add(pid);
/* close the port so that others will hang (for a while) */
(void) close(t);
}
- /*NOTREACHED*/
+ if (tTd(15, 2))
+ printf("getreq: returning (null server)\n");
+ return TRUE;
}
/*
** OPENDAEMONSOCKET -- open the SMTP socket
@@ -446,6 +470,7 @@ opendaemonsocket(firsttime)
} while (ntries++ < MAXOPENTRIES && transienterror(saveerrno));
syserr("!opendaemonsocket: server SMTP socket wedged: exiting");
finis();
+ return -1; /* avoid compiler warning on IRIX */
}
/*
** CLRDAEMON -- reset the daemon connection
@@ -536,16 +561,16 @@ setdaemonoptions(p)
#if NETINET
case AF_INET:
if (isascii(*v) && isdigit(*v))
- DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v));
+ DaemonAddr.sin.sin_addr.s_addr = inet_addr(v);
else
{
- register struct netent *np;
+ register struct hostent *hp;
- np = getnetbyname(v);
- if (np == NULL)
- syserr("554 network \"%s\" unknown", v);
+ hp = sm_gethostbyname(v);
+ if (hp == NULL)
+ syserr("554 host \"%s\" unknown", v);
else
- DaemonAddr.sin.sin_addr.s_addr = np->n_net;
+ bcopy(hp->h_addr, &DaemonAddr.sin.sin_addr, INADDRSZ);
}
break;
#endif
@@ -630,8 +655,7 @@ setdaemonoptions(p)
** port -- the port number to connect to.
** mci -- a pointer to the mail connection information
** structure to be filled in.
-** usesecureport -- if set, use a low numbered (reserved)
-** port to provide some rudimentary authentication.
+** e -- the current envelope.
**
** Returns:
** An exit code telling whether the connection could be
@@ -653,11 +677,11 @@ connecttimeout()
SOCKADDR CurHostAddr; /* address of current host */
int
-makeconnection(host, port, mci, usesecureport)
+makeconnection(host, port, mci, e)
char *host;
u_short port;
register MCI *mci;
- bool usesecureport;
+ ENVELOPE *e;
{
register int i = 0;
register int s;
@@ -691,7 +715,7 @@ makeconnection(host, port, mci, usesecureport)
*p = '\0';
#if NETINET
hid = inet_addr(&host[1]);
- if (hid == -1)
+ if (hid == INADDR_NONE)
#endif
{
/* try it as a host name (avoid MX lookup) */
@@ -717,9 +741,11 @@ makeconnection(host, port, mci, usesecureport)
}
if (p == NULL)
{
+ extern char MsgBuf[];
+
usrerr("553 Invalid numeric domain spec \"%s\"", host);
- mci->mci_status = "5.1.2";
- return (EX_NOHOST);
+ mci_setstat(mci, EX_NOHOST, "5.1.2", MsgBuf);
+ return EX_NOHOST;
}
#if NETINET
addr.sin.sin_family = AF_INET; /*XXX*/
@@ -728,22 +754,25 @@ makeconnection(host, port, mci, usesecureport)
}
else
{
- register char *p = &host[strlen(host) - 1];
-
- hp = sm_gethostbyname(host);
- if (hp == NULL && *p == '.')
+ /* contortion to get around SGI cc complaints */
{
+ register char *p = &host[strlen(host) - 1];
+
+ hp = sm_gethostbyname(host);
+ if (hp == NULL && *p == '.')
+ {
#if NAMED_BIND
- int oldopts = _res.options;
+ int oldopts = _res.options;
- _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
+ _res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
#endif
- *p = '\0';
- hp = sm_gethostbyname(host);
- *p = '.';
+ *p = '\0';
+ hp = sm_gethostbyname(host);
+ *p = '.';
#if NAMED_BIND
- _res.options = oldopts;
+ _res.options = oldopts;
#endif
+ }
}
gothostent:
if (hp == NULL)
@@ -753,10 +782,11 @@ gothostent:
if (errno == ETIMEDOUT || h_errno == TRY_AGAIN ||
(errno == ECONNREFUSED && UseNameServer))
{
- mci->mci_status = "4.4.3";
- return (EX_TEMPFAIL);
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.3", NULL);
+ return EX_TEMPFAIL;
}
#endif
+ mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
return (EX_NOHOST);
}
addr.sa.sa_family = hp->h_addrtype;
@@ -818,6 +848,7 @@ gothostent:
default:
syserr("Can't connect to address family %d", addr.sa.sa_family);
+ mci_setstat(mci, EX_NOHOST, "5.1.2", NULL);
return (EX_NOHOST);
}
@@ -841,7 +872,7 @@ gothostent:
/* save for logging */
CurHostAddr = addr;
- if (usesecureport)
+ if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
{
int rport = IPPORT_RESERVED - 1;
@@ -855,7 +886,11 @@ gothostent:
{
sav_errno = errno;
syserr("makeconnection: cannot create socket");
- goto failure;
+#ifdef XLA
+ xla_host_end(host);
+#endif
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
+ return EX_TEMPFAIL;
}
#ifdef SO_SNDBUF
@@ -878,8 +913,8 @@ gothostent:
(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
(char *)&on, sizeof on);
}
- if (CurEnv->e_xfp != NULL)
- (void) fflush(CurEnv->e_xfp); /* for debugging */
+ if (e->e_xfp != NULL)
+ (void) fflush(e->e_xfp); /* for debugging */
errno = 0; /* for debugging */
/*
@@ -889,10 +924,12 @@ gothostent:
if (setjmp(CtxConnectTimeout) == 0)
{
- if (TimeOuts.to_connect == 0)
- ev = NULL;
- else
+ 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;
if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
{
if (ev != NULL)
@@ -941,18 +978,12 @@ gothostent:
continue;
}
- /* failure, decide if temporary or not */
- failure:
+ /* couldn't open connection */
#ifdef XLA
xla_host_end(host);
#endif
- if (transienterror(sav_errno))
- return EX_TEMPFAIL;
- else
- {
- message("%s", errstring(sav_errno));
- return (EX_UNAVAILABLE);
- }
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL);
+ return EX_TEMPFAIL;
}
/* connection ok, put it into canonical form */
@@ -961,9 +992,11 @@ gothostent:
(mci->mci_in = fdopen(s, "r")) == NULL)
{
syserr("cannot open SMTP client channel, fd=%d", s);
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
return EX_TEMPFAIL;
}
+ mci_setstat(mci, EX_OK, NULL, NULL);
return (EX_OK);
}
/*
@@ -986,7 +1019,6 @@ myhostname(hostbuf, size)
int size;
{
register struct hostent *hp;
- extern bool getcanonname();
if (gethostname(hostbuf, size) < 0)
{
@@ -1087,7 +1119,6 @@ getauthinfo(fd)
int nleft;
char ibuf[MAXNAME + 1];
static char hbuf[MAXNAME * 2 + 2];
- extern char *hostnamebyanyaddr();
falen = sizeof RealHostAddr;
if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 ||
@@ -1104,6 +1135,8 @@ getauthinfo(fd)
{
/* translate that to a host name */
RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
+ if (strlen(RealHostName) > MAXNAME)
+ RealHostName[MAXNAME - 1] = '\0';
}
if (TimeOuts.to_ident == 0)
@@ -1170,6 +1203,9 @@ getauthinfo(fd)
{
p += i;
nleft -= i;
+ *p = '\0';
+ if (strchr(ibuf, '\n') != NULL)
+ break;
}
(void) close(s);
clrevent(ev);
@@ -1207,14 +1243,6 @@ getauthinfo(fd)
}
/* p now points to the OSTYPE field */
- while (isascii(*p) && isspace(*p))
- p++;
- if (strncasecmp(p, "other", 5) == 0 &&
- (p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0'))
- {
- /* not useful information */
- goto noident;
- }
p = strchr(p, ':');
if (p == NULL)
{
@@ -1432,25 +1460,28 @@ host_map_lookup(map, name, av, statp)
if (*name != '[')
{
- extern bool getcanonname();
-
if (tTd(9, 1))
printf("host_map_lookup(%s) => ", name);
s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
- if (strlen(name) < sizeof hbuf)
snprintf(hbuf, sizeof hbuf, "%s", name);
if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
{
if (tTd(9, 1))
printf("%s\n", hbuf);
- cp = map_rewrite(map, hbuf, strlen(hbuf), av);
- s->s_namecanon.nc_cname = newstr(cp);
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ {
+ cp = map_rewrite(map, name, strlen(name), av);
+ s->s_namecanon.nc_cname = newstr(hbuf);
+ }
+ else
+ {
+ cp = map_rewrite(map, hbuf, strlen(hbuf), av);
+ s->s_namecanon.nc_cname = newstr(cp);
+ }
return cp;
}
else
{
- register struct hostent *hp;
-
s->s_namecanon.nc_errno = errno;
#if NAMED_BIND
s->s_namecanon.nc_herrno = h_errno;
diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c
index 34c6c1a82f1b..c019d2b07a5c 100644
--- a/usr.sbin/sendmail/src/deliver.c
+++ b/usr.sbin/sendmail/src/deliver.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)deliver.c 8.185.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)deliver.c 8.251 (Berkeley) 11/11/96";
#endif /* not lint */
#include "sendmail.h"
@@ -69,7 +69,7 @@ extern char SmtpError[];
void
sendall(e, mode)
ENVELOPE *e;
- char mode;
+ int mode;
{
register ADDRESS *q;
char *owner;
@@ -78,7 +78,7 @@ sendall(e, mode)
ENVELOPE *splitenv = NULL;
bool oldverbose = Verbose;
bool somedeliveries = FALSE;
- int pid;
+ pid_t pid;
extern void sendenvelope();
/*
@@ -125,6 +125,8 @@ sendall(e, mode)
*/
CurEnv = e;
+ if (tTd(62, 1))
+ checkfds(NULL);
if (e->e_hopcount > MaxHopCount)
{
@@ -184,12 +186,21 @@ sendall(e, mode)
q->q_owner = NULL;
}
+ if (tTd(13, 25))
+ {
+ printf("\nAfter first owner pass, sendq =\n");
+ printaddr(e->e_sendqueue, TRUE);
+ }
+
owner = "";
otherowners = 1;
while (owner != NULL && otherowners > 0)
{
+ if (tTd(13, 28))
+ printf("owner = \"%s\", otherowners = %d\n",
+ owner, otherowners);
owner = NULL;
- otherowners = 0;
+ otherowners = bitset(EF_SENDRECEIPT, e->e_flags) ? 1 : 0;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
@@ -204,27 +215,49 @@ sendall(e, mode)
printf(" ... QDONTSEND\n");
continue;
}
+ if (tTd(13, 29) && !tTd(13, 30))
+ {
+ printf("Checking ");
+ printaddr(q, FALSE);
+ }
if (q->q_owner != NULL)
{
if (owner == NULL)
+ {
+ if (tTd(13, 40))
+ printf(" ... 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))
+ printf(" ... Same owner = \"%s\"\n",
+ owner);
+
/* make future comparisons cheap */
q->q_owner = owner;
}
else
{
+ if (tTd(13, 40))
+ printf(" ... Another owner \"%s\"\n",
+ q->q_owner);
otherowners++;
}
owner = q->q_owner;
}
+ else if (tTd(13, 40))
+ printf(" ... Same owner = \"%s\"\n",
+ owner);
}
else
{
+ if (tTd(13, 40))
+ printf(" ... Null owner\n");
otherowners++;
}
@@ -273,8 +306,8 @@ sendall(e, mode)
(void) queuename(ee, '\0');
if (tTd(13, 1))
- printf("sendall: split %s into %s\n",
- e->e_id, ee->e_id);
+ printf("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);
@@ -299,7 +332,10 @@ sendall(e, mode)
if (q->q_owner == owner)
{
q->q_flags |= QDONTSEND;
- q->q_flags &= ~QQUEUEUP;
+ q->q_flags &= ~(QQUEUEUP|QBADADDR);
+ if (tTd(13, 6))
+ printf("\t... stripping %s from original envelope\n",
+ q->q_paddr);
}
}
for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
@@ -307,13 +343,19 @@ sendall(e, mode)
if (q->q_owner != owner)
{
q->q_flags |= QDONTSEND;
- q->q_flags &= ~QQUEUEUP;
+ q->q_flags &= ~(QQUEUEUP|QBADADDR);
+ if (tTd(13, 6))
+ printf("\t... dropping %s from cloned envelope\n",
+ q->q_paddr);
}
else
{
/* clear DSN parameters */
- q->q_flags &= ~(QHASNOTIFY|QPINGONSUCCESS);
- q->q_flags |= QPINGONFAILURE|QPINGONDELAY;
+ q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS);
+ q->q_flags |= DefaultNotify & ~QPINGONSUCCESS;
+ if (tTd(13, 6))
+ printf("\t... moving %s to cloned envelope\n",
+ q->q_paddr);
}
}
@@ -368,6 +410,7 @@ sendall(e, mode)
e->e_from.q_flags |= QDONTSEND;
e->e_errormode = EM_MAIL;
e->e_flags |= EF_NORECEIPT;
+ e->e_flags &= ~EF_FATALERRS;
}
/* if nothing to be delivered, just queue up everything */
@@ -382,7 +425,7 @@ sendall(e, mode)
# ifdef QUEUE
if ((mode == SM_QUEUE || mode == SM_DEFER || mode == SM_FORK ||
(mode != SM_VERIFY && SuperSafe)) &&
- !bitset(EF_INQUEUE, e->e_flags))
+ (!bitset(EF_INQUEUE, e->e_flags) || splitenv != NULL))
{
/* be sure everything is instantiated in the queue */
queueup(e, mode == SM_QUEUE || mode == SM_DEFER);
@@ -391,12 +434,31 @@ sendall(e, mode)
}
#endif /* QUEUE */
+ if (tTd(62, 10))
+ checkfds("after envelope splitting");
+
/*
** If we belong in background, fork now.
*/
if (tTd(13, 20))
+ {
printf("sendall: final mode = %c\n", mode);
+ if (tTd(13, 21))
+ {
+ printf("\n================ Final Send Queue(s) =====================\n");
+ printf("\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)
+ {
+ printf("\n *** Envelope %s, e_from=%s ***\n",
+ ee->e_id, ee->e_from.q_paddr);
+ printaddr(ee->e_sendqueue, TRUE);
+ }
+ printf("==========================================================\n\n");
+ }
+ }
switch (mode)
{
case SM_VERIFY:
@@ -428,15 +490,26 @@ sendall(e, mode)
/* now drop the envelope in the parent */
e->e_flags |= EF_INQUEUE;
- dropenvelope(e);
+ dropenvelope(e, FALSE);
- /* and reacquire in the child */
- (void) dowork(qid, TRUE, FALSE, e);
+ /* arrange to reacquire lock after fork */
+ e->e_id = qid;
}
- return;
+ 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;
+ }
-# else /* HASFLOCK */
+# endif /* !HASFLOCK */
pid = fork();
if (pid < 0)
@@ -445,6 +518,7 @@ sendall(e, mode)
}
else if (pid > 0)
{
+# if HASFLOCK
/* be sure we leave the temp files to our child */
/* can't call unlockqueue to avoid unlink of xfp */
if (e->e_lockfp != NULL)
@@ -456,8 +530,11 @@ sendall(e, mode)
if (e->e_dfp != NULL)
(void) xfclose(e->e_dfp, "sendenvelope dfp", e->e_id);
e->e_dfp = NULL;
- e->e_id = NULL;
e->e_flags &= ~EF_HAS_DF;
+# endif
+
+ /* make sure the parent doesn't own the envelope */
+ e->e_id = NULL;
/* catch intermediate zombie */
(void) waitfor(pid);
@@ -491,31 +568,33 @@ sendall(e, mode)
mci_flush(FALSE, NULL);
-# endif /* HASFLOCK */
-
+# if HASFLOCK
break;
- }
-
- if (splitenv != NULL)
- {
- if (tTd(13, 2))
- {
- printf("\nsendall: Split queue; remaining queue:\n");
- printaddr(e->e_sendqueue, TRUE);
- }
+# else
- for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
- {
- CurEnv = ee;
- if (mode != SM_VERIFY)
- openxscript(ee);
- sendenvelope(ee, mode);
- dropenvelope(ee);
- }
+ /*
+ ** Now reacquire and run the various queue files.
+ */
- CurEnv = e;
+ for (ee = splitenv; ee != NULL; ee = e->e_sibling)
+ (void) dowork(ee->e_id, FALSE, FALSE, ee);
+ (void) dowork(e->e_id, FALSE, FALSE, e);
+ finis();
+# 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();
@@ -563,6 +642,8 @@ sendenvelope(e, mode)
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 */
@@ -593,6 +674,8 @@ sendenvelope(e, mode)
}
else if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
{
+ extern int deliver __P((ENVELOPE *, ADDRESS *));
+
# ifdef QUEUE
/*
** Checkpoint the send list every few addresses
@@ -677,7 +760,7 @@ sendenvelope(e, mode)
int
dofork()
{
- register int pid = -1;
+ register pid_t pid = -1;
DOFORK(fork);
return (pid);
@@ -704,6 +787,13 @@ dofork()
** The standard input is passed off to someone.
*/
+#ifndef NO_UID
+# define NO_UID ((uid_t) -1)
+#endif
+#ifndef NO_GID
+# define NO_GID ((gid_t) -1)
+#endif
+
int
deliver(e, firstto)
register ENVELOPE *e;
@@ -716,15 +806,19 @@ deliver(e, firstto)
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 */
char *firstsig; /* signature of firstto */
- int pid = -1;
+ pid_t pid = -1;
char *volatile curhost;
+ register volatile u_short port = 0;
time_t xstart;
+ bool suidwarn;
+ bool anyok; /* at least one address was OK */
int mpvect[2];
int rpvect[2];
char *pv[MAXPV+1];
@@ -738,6 +832,8 @@ deliver(e, firstto)
if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags))
return (0);
+ suidwarn = geteuid() == 0;
+
#if NAMED_BIND
/* unless interactive, try twice, over a minute */
if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
@@ -888,7 +984,7 @@ deliver(e, firstto)
/* compute effective uid/gid when sending */
if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags))
- ctladdr = getctladdr(to);
+ contextaddr = ctladdr = getctladdr(to);
if (tTd(10, 2))
{
@@ -921,7 +1017,15 @@ deliver(e, firstto)
#if NAMED_BIND
h_errno = 0;
#endif
- rcode = checkcompat(to, e);
+
+ /* do config file checking of compatibility */
+ rcode = rscheck("check_compat",
+ e->e_from.q_paddr, to->q_paddr, e);
+ if (rcode == EX_OK)
+ {
+ /* do in-code checking */
+ rcode = checkcompat(to, e);
+ }
if (rcode != EX_OK)
{
markfailure(e, to, NULL, rcode);
@@ -956,9 +1060,6 @@ deliver(e, firstto)
if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
continue;
- /* save statistics.... */
- markstats(e, to);
-
/*
** See if this user name is "special".
** If the user name has a slash in it, assume that this
@@ -975,9 +1076,9 @@ deliver(e, firstto)
if (rcode == EX_OK)
{
to->q_flags |= QSENT;
+ markstats(e, to);
if (bitnset(M_LOCALMAILER, m->m_flags) &&
- (e->e_receiptto != NULL ||
- bitset(QPINGONSUCCESS, to->q_flags)))
+ bitset(QPINGONSUCCESS, to->q_flags))
{
to->q_flags |= QDELIVERED;
to->q_status = "2.1.5";
@@ -1114,6 +1215,9 @@ deliver(e, firstto)
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)
{
@@ -1129,7 +1233,6 @@ deliver(e, firstto)
{
#ifdef DAEMON
register int i;
- register volatile u_short port = 0;
if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0')
{
@@ -1172,11 +1275,12 @@ tryhost:
{
register char *p;
static char hostbuf[MAXNAME + 1];
+ extern int makeconnection __P((char *, u_short, MCI *, ENVELOPE *));
/* pull the next host from the signature */
p = strchr(curhost, ':');
if (p == NULL)
- p = &curhost[strlen(curhost)];
+ p = (char *) &curhost[strlen(curhost)];
if (p == curhost)
{
syserr("deliver: null host name in signature");
@@ -1209,12 +1313,21 @@ tryhost:
if (mci->mci_exitstat != EX_OK)
continue;
+ if (mci_lock_host(mci) != EX_OK)
+ {
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
+ continue;
+ }
+
/* try the connection */
setproctitle("%s %s: %s", e->e_id, hostbuf, "user open");
- message("Connecting to %s via %s...",
- hostbuf, m->m_name);
- i = makeconnection(hostbuf, port, mci,
- bitnset(M_SECURE_PORT, m->m_flags));
+ if (port == 0)
+ message("Connecting to %s via %s...",
+ hostbuf, m->m_name);
+ else
+ message("Connecting to %s port %d via %s...",
+ hostbuf, port, m->m_name);
+ i = makeconnection(hostbuf, port, mci, e);
mci->mci_lastuse = curtime();
mci->mci_exitstat = i;
mci->mci_errno = errno;
@@ -1226,13 +1339,17 @@ tryhost:
mci->mci_state = MCIS_OPENING;
mci_cache(mci);
if (TrafficLogFile != NULL)
- fprintf(TrafficLogFile, "%05d == CONNECT %s\n",
+ fprintf(TrafficLogFile, "%05d === CONNECT %s\n",
getpid(), hostbuf);
break;
}
- else if (tTd(11, 1))
- printf("openmailer: makeconnection => stat=%d, errno=%d\n",
- i, errno);
+ else
+ {
+ if (tTd(11, 1))
+ printf("openmailer: makeconnection => stat=%d, errno=%d\n",
+ i, errno);
+ mci_unlock_host(mci);
+ }
/* enter status of this host */
setstat(i);
@@ -1242,7 +1359,7 @@ tryhost:
if (mci == NULL)
{
syserr("deliver: no host name");
- rcode = EX_OSERR;
+ rcode = EX_SOFTWARE;
goto give_up;
}
mci->mci_pid = 0;
@@ -1274,6 +1391,10 @@ tryhost:
fprintf(TrafficLogFile, "\n");
}
+#if XDEBUG
+ checkfd012("before creating mail pipe");
+#endif
+
/* create a pipe to shove the mail through */
if (pipe(mpvect) < 0)
{
@@ -1285,19 +1406,59 @@ tryhost:
goto give_up;
}
- /* if this mailer speaks smtp, create a return pipe */
-#ifdef SMTP
- if (clever && pipe(rpvect) < 0)
+#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): pipe (from mailer)",
- shortenstring(e->e_to, 203), m->m_name);
- (void) close(mpvect[0]);
- (void) close(mpvect[1]);
+ syserr("%s... openmailer(%s): bogus mpvect %d %d",
+ shortenstring(e->e_to, 203), m->m_name,
+ mpvect[0], mpvect[1]);
+ printopenfds(TRUE);
if (tTd(11, 1))
printf("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, 203), m->m_name,
+ mpvect[0], mpvect[1]);
+ else
+ syserr("%s... openmailer(%s): overlapping mpvect %d %d, lockfp = %d",
+ shortenstring(e->e_to, 203), m->m_name,
+ mpvect[0], mpvect[1], fileno(e->e_lockfp));
+ }
+#endif
+
+ /* if this mailer speaks smtp, create a return pipe */
+#ifdef SMTP
+ if (clever)
+ {
+ if (pipe(rpvect) < 0)
+ {
+ syserr("%s... openmailer(%s): pipe (from mailer)",
+ shortenstring(e->e_to, 203), m->m_name);
+ (void) close(mpvect[0]);
+ (void) close(mpvect[1]);
+ if (tTd(11, 1))
+ printf("openmailer: NULL\n");
+ rcode = EX_OSERR;
+ goto give_up;
+ }
+# if XDEBUG
+ checkfdopen(rpvect[0], "rpvect[0]");
+ checkfdopen(rpvect[1], "rpvect[1]");
+# endif
+ }
#endif
/*
@@ -1339,6 +1500,9 @@ tryhost:
{
int i;
int saveerrno;
+ uid_t new_euid = NO_UID;
+ uid_t new_ruid = NO_UID;
+ gid_t new_gid = NO_GID;
struct stat stb;
extern int DtableSize;
@@ -1353,58 +1517,96 @@ tryhost:
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->m_uid,
+ LOGIN_SETRESOURCES|LOGIN_SETPRIORITY);
+ }
+#endif
+
/* tweak niceness */
if (m->m_nice != 0)
nice(m->m_nice);
/* reset group id */
if (bitnset(M_SPECIFIC_UID, m->m_flags))
- (void) setgid(m->m_gid);
+ new_gid = m->m_gid;
else if (bitset(S_ISGID, stb.st_mode))
- (void) setgid(stb.st_gid);
+ new_gid = stb.st_gid;
else if (ctladdr != NULL && ctladdr->q_gid != 0)
{
if (!DontInitGroups)
(void) initgroups(ctladdr->q_ruser != NULL ?
ctladdr->q_ruser : ctladdr->q_user,
ctladdr->q_gid);
- (void) setgid(ctladdr->q_gid);
+ new_gid = ctladdr->q_gid;
}
else
{
if (!DontInitGroups)
(void) initgroups(DefUser, DefGid);
if (m->m_gid == 0)
- (void) setgid(DefGid);
+ new_gid = DefGid;
else
- (void) setgid(m->m_gid);
+ new_gid = m->m_gid;
}
+ if (new_gid != NO_GID && setgid(new_gid) < 0 && suidwarn)
+ syserr("openmailer: setgid(%ld) failed",
+ (long) new_gid);
/* reset user id */
endpwent();
if (bitnset(M_SPECIFIC_UID, m->m_flags))
+ new_euid = m->m_uid;
+ 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 = DefUid;
+ else
+ new_ruid = m->m_uid;
+ }
+ if (new_euid != NO_UID)
{
+ vendor_set_uid(new_euid);
#if USESETEUID
- (void) seteuid(m->m_uid);
+ if (seteuid(new_euid) < 0 && suidwarn)
+ syserr("openmailer: seteuid(%ld) failed",
+ (long) new_euid);
#else
# if HASSETREUID
- (void) setreuid(-1, m->m_uid);
+ if (setreuid(new_ruid, new_euid) < 0 && suidwarn)
+ syserr("openmailer: setreuid(%ld, %ld) failed",
+ (long) new_ruid, (long) new_euid);
# else
- if (m->m_uid != geteuid())
- (void) setuid(m->m_uid);
+ if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn)
+ syserr("openmailer: setuid(%ld) failed",
+ (long) new_euid);
# endif
#endif
}
- else if (bitset(S_ISUID, stb.st_mode))
- (void) setuid(stb.st_uid);
- else if (ctladdr != NULL && ctladdr->q_uid != 0)
- (void) setuid(ctladdr->q_uid);
- else
+ else if (new_ruid != NO_UID)
{
- if (m->m_uid == 0)
- (void) setuid(DefUid);
- else
- (void) setuid(m->m_uid);
+ vendor_set_uid(new_ruid);
+ if (setuid(new_ruid) < 0 && suidwarn)
+ syserr("openmailer: setuid(%ld) failed",
+ (long) new_ruid);
}
if (tTd(11, 2))
@@ -1559,7 +1761,11 @@ tryhost:
mci->mci_flags |= MCIF_7BIT;
#ifdef SMTP
if (clever && mci->mci_state != MCIS_CLOSED)
+ {
+ extern void smtpinit __P((MAILER *, MCI *, ENVELOPE *));
+
smtpinit(m, mci, e);
+ }
#endif
if (bitset(EF_HAS8BIT, e->e_flags) &&
@@ -1569,6 +1775,22 @@ tryhost:
else
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
+
if (tTd(11, 1))
{
printf("openmailer: ");
@@ -1586,8 +1808,10 @@ tryhost:
if (rcode == EX_OK)
{
/* shouldn't happen */
- syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s",
- rcode, mci->mci_state, firstsig);
+ syserr("554 deliver: mci=%lx rcode=%d errno=%d state=%d sig=%s",
+ (long) mci, rcode, errno, mci->mci_state,
+ firstsig);
+ mci_dump_all(TRUE);
rcode = EX_SOFTWARE;
}
#ifdef DAEMON
@@ -1614,6 +1838,11 @@ tryhost:
else
#ifdef SMTP
{
+ extern int smtpmailfrom __P((MAILER *, MCI *, ENVELOPE *));
+ extern int smtprcpt __P((ADDRESS *, MAILER *, MCI *, ENVELOPE *));
+ extern int smtpdata __P((MAILER *, MCI *, ENVELOPE *));
+ extern int smtpgetstat __P((MAILER *, MCI *, ENVELOPE *));
+
/*
** Send the MAIL FROM: protocol
*/
@@ -1656,12 +1885,8 @@ tryhost:
e->e_to = tobuf + 1;
rcode = smtpdata(m, mci, e);
}
-
- /* now close the connection */
- if (!bitset(MCIF_CACHED, mci->mci_flags))
- smtpquit(m, mci, e);
}
- if (rcode != EX_OK && curhost != NULL && *curhost != '\0')
+ if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0')
{
/* try next MX site */
goto tryhost;
@@ -1679,13 +1904,8 @@ tryhost:
_res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */
#endif
- /* arrange a return receipt if requested */
- if (rcode == EX_OK && e->e_receiptto != NULL &&
- bitnset(M_LOCALMAILER, m->m_flags))
- {
- e->e_flags |= EF_SENDRECEIPT;
- /* do we want to send back more info? */
- }
+ if (tTd(62, 1))
+ checkfds("after delivery");
/*
** Do final status disposal.
@@ -1695,19 +1915,55 @@ tryhost:
*/
give_up:
- if (tobuf[0] != '\0')
- giveresponse(rcode, m, mci, ctladdr, xstart, e);
+#ifdef SMTP
+# if FFR_LMTP
+ if (bitnset(M_LMTP, m->m_flags))
+ {
+ tobuf[0] = '\0';
+ anyok = FALSE;
+ }
+ else
+# endif
+#endif
+ anyok = rcode == EX_OK;
+
for (to = tochain; to != NULL; to = to->q_tchain)
{
/* see if address already marked */
if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
continue;
- /* mark bad addresses */
- if (rcode != EX_OK)
+#ifdef SMTP
+# if FFR_LMTP
+ /* if running LMTP, get the status for each address */
+ if (bitnset(M_LMTP, m->m_flags))
{
- markfailure(e, to, mci, rcode);
- continue;
+ rcode = smtpgetstat(m, mci, e);
+ if (rcode == EX_OK)
+ {
+ strcat(tobuf, ",");
+ strcat(tobuf, to->q_paddr);
+ anyok = TRUE;
+ }
+ else
+ {
+ e->e_to = to->q_paddr;
+ markfailure(e, to, mci, rcode);
+ giveresponse(rcode, m, mci, ctladdr, xstart, e);
+ e->e_to = tobuf + 1;
+ continue;
+ }
+ }
+ else
+# endif
+#endif
+ {
+ /* mark bad addresses */
+ if (rcode != EX_OK)
+ {
+ markfailure(e, to, mci, rcode);
+ continue;
+ }
}
/* successful delivery */
@@ -1715,8 +1971,7 @@ tryhost:
to->q_statdate = curtime();
e->e_nsent++;
if (bitnset(M_LOCALMAILER, m->m_flags) &&
- (e->e_receiptto != NULL ||
- bitset(QPINGONSUCCESS, to->q_flags)))
+ bitset(QPINGONSUCCESS, to->q_flags))
{
to->q_flags |= QDELIVERED;
to->q_status = "2.1.5";
@@ -1733,6 +1988,38 @@ tryhost:
}
}
+#ifdef SMTP
+# if FFR_LMTP
+ 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->mci_state == MCIS_ACTIVE)
+ mci->mci_state = MCIS_OPEN;
+ }
+# endif
+#endif
+
+ if (tobuf[0] != '\0')
+ giveresponse(rcode, m, mci, ctladdr, xstart, e);
+ if (anyok)
+ markstats(e, tochain);
+ mci_store_persistent(mci);
+
+#ifdef SMTP
+ /* now close the connection */
+ if (clever && mci->mci_state != MCIS_CLOSED &&
+ !bitset(MCIF_CACHED, mci->mci_flags))
+ smtpquit(m, mci, e);
+#endif
+
/*
** Restore state and return.
*/
@@ -1798,11 +2085,17 @@ markfailure(e, q, mci, rcode)
}
/* find most specific error code possible */
- if (q->q_status == NULL && mci != NULL)
+ if (mci != NULL && mci->mci_status != NULL)
+ {
q->q_status = mci->mci_status;
- if (q->q_status == NULL)
+ q->q_rstatus = mci->mci_rstatus;
+ }
+ else if (e->e_status != NULL)
+ {
q->q_status = e->e_status;
- if (q->q_status == NULL)
+ q->q_rstatus = NULL;
+ }
+ else
{
switch (rcode)
{
@@ -1903,11 +2196,15 @@ endmailer(mci, e, pv)
if (mci->mci_pid == 0)
return (EX_OK);
+#ifdef FFR_TIMEOUT_WAIT
+ put a timeout around the wait
+#endif
+
/* wait for the mailer process to die and collect status */
st = waitfor(mci->mci_pid);
if (st == -1)
{
- syserr("endmailer %s: wait", pv[0]);
+ syserr("endmailer %s: wait", mci->mci_mailer->m_name);
return (EX_SOFTWARE);
}
@@ -2219,7 +2516,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
bp += strlen(bp);
(void) strcpy(bp, shortenstring(stat, (STATLEN)));
-
+
/* id, to: max 13 + TOBUFSIZE bytes */
l = SYSLOG_BUFSIZE - 100 - strlen(buf);
p = e->e_to;
@@ -2239,7 +2536,7 @@ logdelivery(m, mci, stat, ctladdr, xstart, e)
l = SYSLOG_BUFSIZE - 85;
p = e->e_to;
- while (strlen(p) >= l)
+ while (strlen(p) >= (SIZE_T) l)
{
register char *q = strchr(p + l, ',');
@@ -2342,6 +2639,7 @@ putfromline(mci, e)
{
char *template = UnixFromLine;
char buf[MAXLINE];
+ char xbuf[MAXLINE];
if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
return;
@@ -2349,14 +2647,29 @@ putfromline(mci, e)
if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
{
char *bang;
- char xbuf[MAXLINE];
expand("\201g", buf, sizeof buf, e);
bang = strchr(buf, '!');
if (bang == NULL)
{
- errno = 0;
- syserr("554 No ! in UUCP From address! (%s given)", buf);
+ 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
{
@@ -2461,6 +2774,12 @@ putbody(mci, e, separator)
boundaries[0] = NULL;
mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER);
}
+# if MIME7TO8
+ else if (bitset(MCIF_CVT7TO8, mci->mci_flags))
+ {
+ mime7to8(mci, e->e_header, e);
+ }
+# endif
else
#endif
{
@@ -2593,6 +2912,7 @@ putbody(mci, e, separator)
/* had a naked carriage return */
*pbp++ = c;
c = '\r';
+ ostate = OS_INLINE;
goto putch;
case OS_INLINE:
@@ -2631,8 +2951,10 @@ putch:
{
*bp = '\0';
fputs(buf, mci->mci_out);
- fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ pos += bp - buf;
}
+ if (pos > 0)
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
}
if (ferror(e->e_dfp))
@@ -2691,8 +3013,9 @@ mailfile(filename, ctladdr, sfflags, e)
register ENVELOPE *e;
{
register FILE *f;
- register int pid = -1;
+ register pid_t pid = -1;
int mode;
+ bool suidwarn = geteuid() == 0;
if (tTd(11, 1))
{
@@ -2704,6 +3027,14 @@ mailfile(filename, ctladdr, sfflags, e)
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;
+
+ /*
** Fork so we can change permissions here.
** Note that we MUST use fork, not vfork, because of
** the complications of calling subroutines, etc.
@@ -2717,7 +3048,6 @@ mailfile(filename, ctladdr, sfflags, e)
{
/* child -- actually write to file */
struct stat stb;
- struct stat fsb;
MCI mcibuf;
int oflags = O_WRONLY|O_APPEND;
@@ -2816,12 +3146,9 @@ mailfile(filename, ctladdr, sfflags, e)
RealGid = DefGid;
}
- /* now set the group and user ids */
- endpwent();
+ /* set group id list (needs /etc/group access) */
if (RealUserName != NULL && !DontInitGroups)
(void) initgroups(RealUserName, RealGid);
- (void) setgid(RealGid);
- (void) setuid(RealUid);
/* if you have a safe environment, go into it */
if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0')
@@ -2841,6 +3168,14 @@ mailfile(filename, ctladdr, sfflags, e)
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);
+
sfflags |= SFF_NOPATHCHECK;
sfflags &= ~SFF_OPENASROOT;
f = safefopen(filename, oflags, FileMode, sfflags);
@@ -2873,9 +3208,9 @@ mailfile(filename, ctladdr, sfflags, e)
/* reset ISUID & ISGID bits for paranoid systems */
#if HASFCHMOD
- (void) fchmod(fileno(f), (int) stb.st_mode);
+ (void) fchmod(fileno(f), (MODE_T) stb.st_mode);
#else
- (void) chmod(filename, (int) stb.st_mode);
+ (void) chmod(filename, (MODE_T) stb.st_mode);
#endif
(void) xfclose(f, "mailfile", filename);
(void) fflush(stdout);
@@ -2897,6 +3232,7 @@ mailfile(filename, ctladdr, sfflags, e)
}
/*NOTREACHED*/
}
+ return EX_UNAVAILABLE; /* avoid compiler warning on IRIX */
}
/*
** HOSTSIGNATURE -- return the "signature" for a host.
@@ -2929,7 +3265,6 @@ hostsignature(m, host, e)
int len;
#if NAMED_BIND
int nmx;
- auto int rcode;
char *hp;
char *endp;
int oldoptions = _res.options;
@@ -2969,23 +3304,33 @@ hostsignature(m, host, e)
if (endp != NULL)
*endp = '\0';
- nmx = getmxrr(hp, mxhosts, TRUE, &rcode);
-
- if (nmx <= 0)
+ if (bitnset(M_NOMX, m->m_flags))
{
- register MCI *mci;
-
- /* update the connection info for this host */
- mci = mci_get(hp, m);
- mci->mci_lastuse = curtime();
- mci->mci_exitstat = rcode;
- mci->mci_errno = errno;
- mci->mci_herrno = h_errno;
-
- /* and return the original host name as the signature */
+ /* skip MX lookups */
nmx = 1;
mxhosts[0] = hp;
}
+ else
+ {
+ auto int rcode;
+
+ nmx = getmxrr(hp, mxhosts, TRUE, &rcode);
+ if (nmx <= 0)
+ {
+ register MCI *mci;
+
+ /* update the connection info for this host */
+ mci = mci_get(hp, m);
+ mci->mci_errno = errno;
+ mci->mci_herrno = h_errno;
+ mci->mci_lastuse = curtime();
+ mci_setstat(mci, rcode, NULL, NULL);
+
+ /* use the original host name as signature */
+ nmx = 1;
+ mxhosts[0] = hp;
+ }
+ }
len = 0;
for (i = 0; i < nmx; i++)
diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c
index f446e741821d..ca2d8f8d86e9 100644
--- a/usr.sbin/sendmail/src/domain.c
+++ b/usr.sbin/sendmail/src/domain.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1986, 1995 Eric P. Allman
+ * Copyright (c) 1986, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if NAMED_BIND
-static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (with name server)";
+static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (with name server)";
#else
-static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (without name server)";
+static char sccsid[] = "@(#)domain.c 8.64 (Berkeley) 10/30/96 (without name server)";
#endif
#endif /* not lint */
@@ -46,21 +46,39 @@ static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (without name s
#include <errno.h>
#include <resolv.h>
+#include <arpa/inet.h>
+
+/*
+** 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
typedef union
{
HEADER qb1;
- u_char qb2[PACKETSZ];
+ u_char qb2[MAXPACKET];
} querybuf;
-static char MXHostBuf[MAXMXHOSTS*PACKETSZ];
+#ifndef MXHOSTBUFSIZE
+# define MXHOSTBUFSIZE (128 * MAXMXHOSTS)
+#endif
+
+static char MXHostBuf[MXHOSTBUFSIZE];
#ifndef MAXDNSRCH
-#define MAXDNSRCH 6 /* number of possible domains to search */
+# define MAXDNSRCH 6 /* number of possible domains to search */
#endif
#ifndef MAX
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef NO_DATA
@@ -114,32 +132,21 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
u_short pref, type;
u_short localpref = 256;
char *fallbackMX = FallBackMX;
- static bool firsttime = TRUE;
bool trycanon = FALSE;
int (*resfunc)();
extern int res_query(), res_search();
u_short prefer[MAXMXHOSTS];
int weight[MAXMXHOSTS];
- extern bool getcanonname();
+ extern int mxrand __P((char *));
if (tTd(8, 2))
printf("getmxrr(%s, droplocalhost=%d)\n", host, droplocalhost);
- if (fallbackMX != NULL)
+ if (fallbackMX != NULL && droplocalhost &&
+ wordinclass(fallbackMX, 'w'))
{
- if (firsttime &&
- res_query(FallBackMX, C_IN, T_A,
- (u_char *) &answer, sizeof answer) < 0)
- {
- /* this entry is bogus */
- fallbackMX = FallBackMX = NULL;
- }
- else if (droplocalhost && wordinclass(fallbackMX, 'w'))
- {
- /* don't use fallback for this pass */
- fallbackMX = NULL;
- }
- firsttime = FALSE;
+ /* don't use fallback for this pass */
+ fallbackMX = NULL;
}
*rcode = EX_OK;
@@ -212,6 +219,10 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
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;
@@ -356,8 +367,11 @@ punt:
if (p != NULL)
{
*p = '\0';
- if (inet_addr(&MXHostBuf[1]) != -1)
+ if (inet_addr(&MXHostBuf[1]) != INADDR_NONE)
+ {
+ nmx++;
*p = ']';
+ }
else
{
trycanon = TRUE;
@@ -518,7 +532,7 @@ dns_getcanonname(host, hbsize, trymx, statp)
int qtype;
int loopcnt;
char *xp;
- char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
+ char nbuf[MAX(MAXPACKET, MAXDNAME*2+2)];
char *searchlist[MAXDNSRCH+2];
extern char *gethostalias();
@@ -651,6 +665,10 @@ cnameloop:
else if (tTd(8, 7))
printf("\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
diff --git a/usr.sbin/sendmail/src/envelope.c b/usr.sbin/sendmail/src/envelope.c
index a22f73caa853..80e5ce60f969 100644
--- a/usr.sbin/sendmail/src/envelope.c
+++ b/usr.sbin/sendmail/src/envelope.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)envelope.c 8.76.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)envelope.c 8.96 (Berkeley) 11/11/96";
#endif /* not lint */
#include "sendmail.h"
@@ -82,6 +82,7 @@ newenvelope(e, parent)
**
** Parameters:
** e -- the envelope to deallocate.
+** fulldrop -- if set, do return receipts.
**
** Returns:
** none.
@@ -92,11 +93,14 @@ newenvelope(e, parent)
*/
void
-dropenvelope(e)
+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;
register ADDRESS *q;
char *id = e->e_id;
@@ -143,16 +147,35 @@ dropenvelope(e)
** Extract state information from dregs of send list.
*/
+ if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
+ message_timeout = TRUE;
+
e->e_flags &= ~EF_QUEUERUN;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
- if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags) ||
- bitset(QQUEUEUP, q->q_flags))
+ if (bitset(QQUEUEUP, q->q_flags) &&
+ bitset(QDONTSEND, q->q_flags))
+ {
+ /* I'm not sure how this happens..... */
+ if (tTd(50, 2))
+ {
+ printf("Bogus flags: ");
+ printaddr(q, FALSE);
+ }
+ q->q_flags &= ~QDONTSEND;
+ }
+ if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
queueit = TRUE;
+#if XDEBUG
+ else if (bitset(QQUEUEUP, q->q_flags))
+ syslog(LOG_DEBUG, "%s: q_flags = %x",
+ e->e_id, q->q_flags);
+#endif
/* see if a notification is needed */
- if (bitset(QBADADDR, q->q_flags) &&
- bitset(QPINGONFAILURE, q->q_flags))
+ if (bitset(QPINGONFAILURE, q->q_flags) &&
+ ((message_timeout && bitset(QQUEUEUP, q->q_flags)) ||
+ bitset(QBADADDR, q->q_flags)))
{
failure_return = TRUE;
if (q->q_owner == NULL && !emptyaddr(&e->e_from))
@@ -177,23 +200,25 @@ dropenvelope(e)
if (!queueit)
/* nothing to do */ ;
- else if (curtime() > e->e_ctime + TimeOuts.to_q_return[e->e_timeoutclass])
+ else if (message_timeout)
{
- (void) snprintf(buf, sizeof buf, "Cannot send message for %s",
- pintvl(TimeOuts.to_q_return[e->e_timeoutclass], FALSE));
- if (e->e_message != NULL)
- free(e->e_message);
- e->e_message = newstr(buf);
- message(buf);
- e->e_flags |= EF_CLRQUEUE;
- failure_return = TRUE;
+ 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 (bitset(QQUEUEUP, q->q_flags) ||
- !bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
+ if (!bitset(QBADADDR|QDONTSEND|QSENT, q->q_flags))
{
q->q_flags |= QBADADDR;
q->q_status = "4.4.7";
@@ -203,19 +228,7 @@ dropenvelope(e)
else if (TimeOuts.to_q_warning[e->e_timeoutclass] > 0 &&
curtime() > e->e_ctime + TimeOuts.to_q_warning[e->e_timeoutclass])
{
- bool delay_return = FALSE;
-
- for (q = e->e_sendqueue; q != NULL; q = q->q_next)
- {
- if (bitset(QQUEUEUP, q->q_flags) &&
- bitset(QPINGONDELAY, q->q_flags))
- {
- q->q_flags |= QDELAYED;
- delay_return = TRUE;
- }
- }
- if (delay_return &&
- !bitset(EF_WARNING|EF_RESPONSE, e->e_flags) &&
+ 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 &&
@@ -223,6 +236,18 @@ dropenvelope(e)
(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 (bitset(QQUEUEUP, q->q_flags) &&
+ 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));
@@ -231,7 +256,6 @@ dropenvelope(e)
e->e_message = newstr(buf);
message(buf);
e->e_flags |= EF_WARNING;
- failure_return = TRUE;
}
fprintf(e->e_xfp,
"Warning: message still undelivered after %s\n",
@@ -241,8 +265,8 @@ dropenvelope(e)
}
if (tTd(50, 2))
- printf("failure_return=%d success_return=%d queueit=%d\n",
- failure_return, success_return, queueit);
+ printf("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
@@ -263,21 +287,15 @@ dropenvelope(e)
** Send back return receipts as requested.
*/
-/*
- if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)
- && !bitset(PRIV_NORECEIPTS, PrivacyFlags))
-*/
- if (e->e_receiptto == NULL)
- e->e_receiptto = e->e_from.q_paddr;
- if (success_return && !failure_return &&
+ if (success_return && !failure_return && !delay_return && fulldrop &&
!bitset(PRIV_NORECEIPTS, PrivacyFlags) &&
- strcmp(e->e_receiptto, "<>") != 0)
+ strcmp(e->e_from.q_paddr, "<>") != 0)
{
auto ADDRESS *rlist = NULL;
e->e_flags |= EF_SENDRECEIPT;
- (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, 0, e);
- (void) returntosender("Return receipt", rlist, FALSE, e);
+ (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;
@@ -285,8 +303,12 @@ dropenvelope(e)
** Arrange to send error messages if there are fatal errors.
*/
- if (failure_return && e->e_errormode != EM_QUIET)
+ if ((failure_return || delay_return) && e->e_errormode != EM_QUIET)
+ {
+ extern void savemail __P((ENVELOPE *, bool));
+
savemail(e, !bitset(EF_NO_BODY_RETN, e->e_flags));
+ }
/*
** Arrange to send warning messages to postmaster as requested.
@@ -299,7 +321,7 @@ dropenvelope(e)
auto ADDRESS *rlist = NULL;
(void) sendtolist(PostMasterCopy, NULLADDR, &rlist, 0, e);
- (void) returntosender(e->e_message, rlist, FALSE, e);
+ (void) returntosender(e->e_message, rlist, RTSF_PM_BOUNCE, e);
}
/*
@@ -499,7 +521,6 @@ settime(e)
char tbuf[20]; /* holds "current" time */
char dbuf[30]; /* holds ctime(tbuf) */
register struct tm *tm;
- extern char *arpadate();
extern struct tm *gmtime();
now = curtime();
@@ -548,7 +569,7 @@ openxscript(e)
if (e->e_xfp != NULL)
return;
p = queuename(e, 'x');
- fd = open(p, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ fd = open(p, O_WRONLY|O_CREAT|O_APPEND, FileMode);
if (fd < 0)
{
syserr("Can't create transcript file %s", p);
@@ -754,7 +775,8 @@ setsender(from, e, delimptr, internal)
FullName = NULL;
}
- if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL)
+ if (e->e_from.q_user[0] != '\0' &&
+ (pw = sm_getpwnam(e->e_from.q_user)) != NULL)
{
/*
** Process passwd file entry.
@@ -782,6 +804,10 @@ setsender(from, e, delimptr, internal)
FullName = newstr(buf);
}
}
+ else
+ {
+ e->e_from.q_home = "/no/such/directory";
+ }
if (FullName != NULL && !internal)
define('x', FullName, e);
}
@@ -874,31 +900,31 @@ struct eflags
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
+ { "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
diff --git a/usr.sbin/sendmail/src/err.c b/usr.sbin/sendmail/src/err.c
index c231ef119d46..199fdd87ed87 100644
--- a/usr.sbin/sendmail/src/err.c
+++ b/usr.sbin/sendmail/src/err.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)err.c 8.42.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)err.c 8.50 (Berkeley) 9/20/96";
#endif /* not lint */
# include "sendmail.h"
@@ -145,10 +145,30 @@ syserr(fmt, va_alist)
CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
uname, &MsgBuf[4]);
# endif /* LOG */
- if (olderrno == EMFILE)
+ switch (olderrno)
{
+ case EBADF:
+ case ENFILE:
+ case EMFILE:
+ case ENOTTY:
+#ifdef EFBIG
+ case EFBIG:
+#endif
+#ifdef ESPIPE
+ case ESPIPE:
+#endif
+#ifdef EPIPE
+ case EPIPE:
+#endif
+#ifdef ENOBUFS
+ case ENOBUFS:
+#endif
+#ifdef ESTALE
+ case ESTALE:
+#endif
printopenfds(TRUE);
mci_dump_all(TRUE);
+ break;
}
if (panic)
{
@@ -384,6 +404,11 @@ putoutmsg(msg, holdmsg, heldmsg)
if (!heldmsg && CurEnv->e_xfp != NULL && strchr("45", msg[0]) != NULL)
fprintf(CurEnv->e_xfp, "%s\n", msg);
+#ifdef LOG
+ if (LogLevel >= 15 && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
+ syslog(LOG_INFO, "--> %s%s", msg, holdmsg ? " (held)" : "");
+#endif
+
if (msgcode == '8')
msg[0] = '0';
@@ -624,17 +649,29 @@ errstring(errnum)
case ECONNRESET:
bp = buf;
snprintf(bp, SPACELEFT(buf, bp), "%s", sys_errlist[errnum]);
- bp += strlen(buf);
+ 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, 203));
+ bp += strlen(buf);
+ }
if (SmtpPhase != NULL)
{
snprintf(bp, SPACELEFT(buf, bp), " during %s",
SmtpPhase);
- bp += strlen(bp);
- }
- if (CurHostName != NULL)
- {
- snprintf(bp, SPACELEFT(buf, bp), " with %s",
- shortenstring(CurHostName, 203));
}
return (buf);
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
index 72092d75d88e..6ab97e48e163 100644
--- a/usr.sbin/sendmail/src/headers.c
+++ b/usr.sbin/sendmail/src/headers.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)headers.c 8.82.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)headers.c 8.100 (Berkeley) 9/15/96";
#endif /* not lint */
# include <errno.h>
@@ -74,7 +74,6 @@ chompheader(line, def, hdrp, e)
bool cond = FALSE;
bool headeronly;
BITMAP mopts;
- char buf[MAXNAME + 1];
if (tTd(31, 6))
{
@@ -158,7 +157,6 @@ chompheader(line, def, hdrp, e)
if (bitset(H_EOH, hi->hi_flags))
return (hi->hi_flags);
-#ifdef LOTUS_NOTES_HACK
/*
** Horrible hack to work around problem with Lotus Notes SMTP
** mail gateway, which generates From: headers with newlines in
@@ -172,7 +170,6 @@ chompheader(line, def, hdrp, e)
while ((p = strchr(fvalue, '\n')) != NULL)
*p = ' ';
}
-#endif
/*
** Drop explicit From: if same as what we would generate.
@@ -195,46 +192,6 @@ chompheader(line, def, hdrp, e)
(strcmp(fvalue, e->e_from.q_paddr) == 0 ||
strcmp(fvalue, e->e_from.q_user) == 0))
return (hi->hi_flags);
-#ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
-#if USERDB
- else
- {
- auto ADDRESS a;
- char *fancy;
- bool oldSuprErrs = SuprErrs;
- extern char *crackaddr();
- extern char *udbsender();
-
- /*
- ** Try doing USERDB rewriting even on fully commented
- ** names; this saves the "comment" information (such
- ** as full name) and rewrites the electronic part.
- **
- ** XXX This code doesn't belong here -- parsing should
- ** XXX not be done during collect() phase because
- ** XXX error messages can confuse the SMTP phase.
- ** XXX Setting SuprErrs is a crude hack around this
- ** XXX problem.
- */
-
- if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
- SuprErrs = TRUE;
- fancy = crackaddr(fvalue);
- if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
- bitnset(M_CHECKUDB, a.q_mailer->m_flags) &&
- (p = udbsender(a.q_user)) != NULL)
- {
- char *oldg = macvalue('g', e);
-
- define('g', p, e);
- expand(fancy, buf, sizeof buf, e);
- define('g', oldg, e);
- fvalue = buf;
- }
- SuprErrs = oldSuprErrs;
- }
-#endif
-#endif
}
/* delete default value for this header */
@@ -433,6 +390,7 @@ eatheader(e, full)
int hopcnt = 0;
char *msgid;
char buf[MAXLINE];
+ extern int priencode __P((char *));
/*
** Set up macros for possible expansion in headers.
@@ -522,10 +480,6 @@ eatheader(e, full)
while (isascii(*msgid) && isspace(*msgid))
msgid++;
}
-
- /* see if this is a return-receipt header */
- if (bitset(H_RECEIPTTO, h->h_flags))
- e->e_receiptto = h->h_value;
}
if (tTd(32, 1))
printf("----------------------------\n");
@@ -558,11 +512,11 @@ eatheader(e, full)
if (p != NULL)
{
/* (this should be in the configuration file) */
- if (strcasecmp(p, "urgent"))
+ if (strcasecmp(p, "urgent") == 0)
e->e_timeoutclass = TOC_URGENT;
- else if (strcasecmp(p, "normal"))
+ else if (strcasecmp(p, "normal") == 0)
e->e_timeoutclass = TOC_NORMAL;
- else if (strcasecmp(p, "non-urgent"))
+ else if (strcasecmp(p, "non-urgent") == 0)
e->e_timeoutclass = TOC_NONURGENT;
}
@@ -807,6 +761,7 @@ crackaddr(addr)
int realcmtlev;
int anglelev, realanglelev;
int copylev;
+ int bracklev;
bool qmode;
bool realqmode;
bool skipping;
@@ -833,9 +788,10 @@ crackaddr(addr)
*/
bp = bufhead = buf;
- buflim = &buf[sizeof buf - 5];
+ buflim = &buf[sizeof buf - 6];
p = addrhead = addr;
copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
+ bracklev = 0;
qmode = realqmode = FALSE;
while ((c = *p++) != '\0')
@@ -892,7 +848,8 @@ crackaddr(addr)
realcmtlev++;
if (copylev++ <= 0)
{
- *bp++ = ' ';
+ if (bp != bufhead)
+ *bp++ = ' ';
*bp++ = c;
}
}
@@ -918,20 +875,33 @@ crackaddr(addr)
bp--;
}
+ /* count nesting on [ ... ] (for IPv6 domain literals) */
+ if (c == '[')
+ bracklev++;
+ else if (c == ']')
+ bracklev--;
+
/* check for group: list; syntax */
- if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr)
+ if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
+ !gotcolon && !ColonOkInAddr)
{
register char *q;
- if (*p == ':')
+ /*
+ ** 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 == '.')
{
- /* special case -- :: syntax */
if (cmtlev <= 0 && !qmode)
quoteit = TRUE;
if (copylev > 0 && !skipping)
{
*bp++ = c;
- *bp++ = c;
+ *bp++ = *p;
}
p++;
goto putg;
@@ -1086,6 +1056,8 @@ crackaddr(addr)
putg:
if (copylev <= 0 && !putgmac)
{
+ if (bp > bufhead && bp[-1] == ')')
+ *bp++ = ' ';
*bp++ = MACROEXPAND;
*bp++ = 'g';
putgmac = TRUE;
@@ -1102,7 +1074,11 @@ crackaddr(addr)
*bp++ = '\0';
if (tTd(33, 1))
- printf("crackaddr=>`%s'\n", buf);
+ {
+ printf("crackaddr=>`");
+ xputs(buf);
+ printf("'\n");
+ }
return (buf);
}
@@ -1129,11 +1105,12 @@ crackaddr(addr)
#endif
void
-putheader(mci, h, e)
+putheader(mci, hdr, e)
register MCI *mci;
- register HDR *h;
+ HDR *hdr;
register ENVELOPE *e;
{
+ register HDR *h;
char buf[MAX(MAXLINE,BUFSIZ)];
char obuf[MAXLINE];
@@ -1142,7 +1119,7 @@ putheader(mci, h, e)
mci->mci_mailer->m_name);
mci->mci_flags |= MCIF_INHEADER;
- for (; h != NULL; h = h->h_link)
+ for (h = hdr; h != NULL; h = h->h_link)
{
register char *p = h->h_value;
extern bool bitintersect();
@@ -1155,7 +1132,7 @@ putheader(mci, h, e)
/* suppress Content-Transfer-Encoding: if we are MIMEing */
if (bitset(H_CTE, h->h_flags) &&
- bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags))
+ bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags))
{
if (tTd(34, 11))
printf(" (skipped (content-transfer-encoding))\n");
@@ -1166,7 +1143,8 @@ putheader(mci, h, e)
{
if (tTd(34, 11))
printf("\n");
- goto vanilla;
+ put_vanilla_header(h, p, mci);
+ continue;
}
if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
@@ -1239,31 +1217,7 @@ putheader(mci, h, e)
}
else
{
- /* vanilla header line */
- register char *nlp;
- register char *obp;
-
-vanilla:
- obp = obuf;
- (void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ",
- h->h_field);
- obp = obuf + strlen(obuf);
- while ((nlp = strchr(p, '\n')) != NULL)
- {
-
- *nlp = '\0';
- snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
- sizeof obuf - (obp - obuf) - 1, p);
- *nlp = '\n';
- putline(obuf, mci);
- p = ++nlp;
- obp = obuf;
- if (*p != ' ' && *p != '\t')
- *obp++ = ' ';
- }
- snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
- sizeof obuf - (obp - obuf) - 1, p);
- putline(obuf, mci);
+ put_vanilla_header(h, p, mci);
}
}
@@ -1277,7 +1231,7 @@ vanilla:
bitset(EF_HAS8BIT, e->e_flags) &&
!bitset(EF_DONT_MIME, e->e_flags) &&
!bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
- !bitset(MCIF_CVT8TO7, mci->mci_flags))
+ !bitset(MCIF_CVT8TO7|MCIF_CVT7TO8, mci->mci_flags))
{
if (hvalue("MIME-Version", e->e_header) == NULL)
putline("MIME-Version: 1.0", mci);
@@ -1294,6 +1248,49 @@ vanilla:
#endif
}
/*
+** 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.
+*/
+
+void
+put_vanilla_header(h, v, mci)
+ HDR *h;
+ char *v;
+ MCI *mci;
+{
+ register char *nlp;
+ register char *obp;
+ char obuf[MAXLINE];
+
+ (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 (sizeof obuf - (obp - obuf) < l)
+ l = sizeof obuf - (obp - obuf);
+
+ snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
+ putline(obuf, mci);
+ v += l + 1;
+ obp = obuf;
+ if (*v != ' ' && *v != '\t')
+ *obp++ = ' ';
+ }
+ snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
+ sizeof obuf - (obp - obuf) - 1, v);
+ putline(obuf, mci);
+}
+ /*
** COMMAIZE -- output a header field, making a comma-translated list.
**
** Parameters:
diff --git a/usr.sbin/sendmail/src/macro.c b/usr.sbin/sendmail/src/macro.c
index 94ef834bb082..e31d0deb21cb 100644
--- a/usr.sbin/sendmail/src/macro.c
+++ b/usr.sbin/sendmail/src/macro.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)macro.c 8.13 (Berkeley) 7/10/95";
+static char sccsid[] = "@(#)macro.c 8.17 (Berkeley) 5/13/96";
#endif /* not lint */
# include "sendmail.h"
@@ -70,8 +70,10 @@ expand(s, buf, bufsize, e)
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[BUFSIZ];
+ static int explevel = 0;
if (tTd(35, 24))
{
@@ -81,6 +83,7 @@ expand(s, buf, bufsize, e)
}
skipping = FALSE;
+ skiplev = 0;
iflev = 0;
if (s == NULL)
s = "";
@@ -98,23 +101,29 @@ expand(s, buf, bufsize, e)
switch (c & 0377)
{
case CONDIF: /* see if var set */
+ iflev++;
c = *++s;
if (skipping)
- iflev++;
+ skiplev++;
else
skipping = macvalue(c, e) == NULL;
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)
- iflev--;
+ skiplev--;
continue;
case MACROEXPAND: /* macro interpolation */
@@ -135,7 +144,7 @@ expand(s, buf, bufsize, e)
** Interpolate q or output one character
*/
- if (skipping || xp >= &xbuf[sizeof xbuf])
+ if (skipping || xp >= &xbuf[sizeof xbuf - 1])
continue;
if (q == NULL)
*xp++ = c;
@@ -163,8 +172,15 @@ expand(s, buf, bufsize, e)
/* recurse as appropriate */
if (recurse)
{
- expand(xbuf, buf, bufsize, e);
- return;
+ if (explevel < MaxMacroRecursion)
+ {
+ explevel++;
+ expand(xbuf, buf, bufsize, e);
+ explevel--;
+ return;
+ }
+ syserr("expand: recursion too deep (%d max)",
+ MaxMacroRecursion);
}
/* copy results out */
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index e19efa489aef..9da0e3282def 100644
--- a/usr.sbin/sendmail/src/main.c
+++ b/usr.sbin/sendmail/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -39,12 +39,13 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.162.1.3 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)main.c 8.215 (Berkeley) 11/16/96";
#endif /* not lint */
#define _DEFINE
#include "sendmail.h"
+#include <arpa/inet.h>
#if NAMED_BIND
#include <resolv.h>
#endif
@@ -75,14 +76,16 @@ char edata, end;
** See the associated documentation for details.
**
** Author:
-** Eric Allman, UCB/INGRES (until 10/81)
+** Eric Allman, UCB/INGRES (until 10/81).
** Britton-Lee, Inc., purveyors of fine
-** database computers (from 11/81)
-** Now back at UCB at the Mammoth project.
-** The support of the INGRES Project and Britton-Lee is
-** gratefully acknowledged. Britton-Lee in
-** particular had absolutely nothing to gain from
-** my involvement in this project.
+** 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 - 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.
*/
@@ -97,6 +100,8 @@ bool Warn_Q_option = FALSE; /* warn about Q option use */
char **SaveArgv; /* argument vector for re-execing */
static void obsolete();
+extern void printmailer __P((MAILER *));
+extern void tTflag __P((char *));
#ifdef DAEMON
#ifndef SMTP
@@ -104,7 +109,7 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
#endif /* SMTP */
#endif /* DAEMON */
-#define MAXCONFIGLEVEL 6 /* highest config version level known */
+#define MAXCONFIGLEVEL 7 /* highest config version level known */
int
main(argc, argv, envp)
@@ -124,26 +129,40 @@ main(argc, argv, envp)
bool safecf = TRUE;
bool warn_C_flag = FALSE;
char warn_f_flag = '\0';
+ bool run_in_foreground = FALSE; /* -bD mode */
static bool reenter = FALSE;
struct passwd *pw;
struct stat stb;
struct hostent *hp;
+ bool nullserver;
char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */
static char rnamebuf[MAXNAME]; /* holds RealUserName */
+ char *emptyenviron[1];
extern int DtableSize;
extern int optind;
extern int opterr;
+ extern char *optarg;
+ extern char **environ;
extern time_t convtime();
extern void intsig();
extern struct hostent *myhostname();
- extern char *arpadate();
extern char *getauthinfo();
extern char *getcfname();
- extern char *optarg;
- extern char **environ;
extern void sigusr1();
extern void sighup();
extern void initmacros __P((ENVELOPE *));
+ extern void init_md __P((int, char **));
+ extern int getdtsize __P((void));
+ extern void tTsetup __P((u_char *, int, char *));
+ extern void setdefaults __P((ENVELOPE *));
+ extern void initsetproctitle __P((int, char **, char **));
+ extern void init_vendor_macros __P((ENVELOPE *));
+ extern void load_if_names __P((void));
+ extern void vendor_pre_defaults __P((ENVELOPE *));
+ extern void vendor_post_defaults __P((ENVELOPE *));
+ extern void readcf __P((char *, bool, ENVELOPE *));
+ extern void printqueue __P((void));
+ extern void sendtoargv __P((char **, ENVELOPE *));
extern void resetlimits __P((void));
/*
@@ -159,6 +178,9 @@ main(argc, argv, envp)
}
reenter = TRUE;
+ /* avoid null pointer dereferences */
+ TermEscape.te_rv_on = TermEscape.te_rv_off = "";
+
/* do machine-dependent initializations */
init_md(argc, argv);
@@ -205,6 +227,42 @@ main(argc, argv, envp)
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+ /* Handle any non-getoptable constructions. */
+ obsolete(argv);
+
+ /*
+ ** Do a quick prescan of the argument list.
+ */
+
+#if defined(__osf__) || defined(_AIX3)
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:x"
+#endif
+#if defined(sony_news)
+# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
+#endif
+#ifndef OPTIONS
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:"
+#endif
+ opterr = 0;
+ while ((j = getopt(argc, argv, OPTIONS)) != EOF)
+ {
+ 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;
+ }
+ }
+ opterr = 1;
+
/* set up the blank envelope */
BlankEnvelope.e_puthdr = putheader;
BlankEnvelope.e_putbody = putbody;
@@ -247,35 +305,6 @@ main(argc, argv, envp)
}
SaveArgv[i] = NULL;
- /* Handle any non-getoptable constructions. */
- obsolete(argv);
-
- /*
- ** Do a quick prescan of the argument list.
- */
-
-#if defined(__osf__) || defined(_AIX3)
-# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x"
-#endif
-#if defined(sony_news)
-# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mnO:o:p:q:r:sTtvX:"
-#endif
-#ifndef OPTIONS
-# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:"
-#endif
- opterr = 0;
- while ((j = getopt(argc, argv, OPTIONS)) != EOF)
- {
- switch (j)
- {
- case 'd':
- tTflag(optarg);
- setbuf(stdout, (char *) NULL);
- break;
- }
- }
- opterr = 1;
-
if (tTd(0, 1))
{
int ll;
@@ -308,7 +337,7 @@ main(argc, argv, envp)
int ll;
extern char *OsCompileOptions[];
- printf(" OS Defines:", Version);
+ printf(" OS Defines:");
av = OsCompileOptions;
ll = 7;
while (*av != NULL)
@@ -332,7 +361,7 @@ main(argc, argv, envp)
#ifdef _PATH_UNIX
printf("Kernel symbols:\t%s\n", _PATH_UNIX);
#endif
- printf(" Config file:\t%s\n", getcfname());
+ printf(" Def Conf file:\t%s\n", getcfname());
printf(" Pid file:\t%s\n", PidFile);
}
@@ -342,6 +371,11 @@ main(argc, argv, envp)
/* initialize for setproctitle */
initsetproctitle(argc, argv, envp);
+ /* clear sendmail's environment */
+ ExternalEnviron = environ;
+ emptyenviron[0] = NULL;
+ environ = emptyenviron;
+
/* prime the child environment */
setuserenv("AGENT", "sendmail");
@@ -351,14 +385,20 @@ main(argc, argv, envp)
(void) setsignal(SIGPIPE, SIG_IGN);
OldUmask = umask(022);
OpMode = MD_DELIVER;
- FullName = getenv("NAME");
+ FullName = getextenv("NAME");
+
+ /*
+ ** Initialize name server if it is going to be used.
+ */
#if NAMED_BIND
- if (tTd(8, 8))
- {
+ if (!bitset(RES_INIT, _res.options))
res_init();
+ if (tTd(8, 8))
_res.options |= RES_DEBUG;
- }
+# ifdef RES_NOALIASES
+ _res.options |= RES_NOALIASES;
+# endif
#endif
errno = 0;
@@ -393,6 +433,8 @@ main(argc, argv, envp)
while (p != NULL && strchr(&p[1], '.') != NULL)
{
*p = '\0';
+ if (tTd(0, 4))
+ printf("\ta.k.a.: %s\n", jbuf);
setclass('w', jbuf);
*p++ = '.';
p = strchr(p, '.');
@@ -449,13 +491,6 @@ main(argc, argv, envp)
define('b', arpadate((char *) NULL), CurEnv);
/*
- ** Find our real host name for future logging.
- */
-
- p = getauthinfo(STDIN_FILENO);
- define('_', p, CurEnv);
-
- /*
** Crack argv.
*/
@@ -469,6 +504,10 @@ main(argc, argv, envp)
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)) != EOF)
@@ -479,13 +518,8 @@ main(argc, argv, envp)
switch (j = *optarg)
{
case MD_DAEMON:
-# ifdef DAEMON
- if (RealUid != 0) {
- usrerr("Permission denied");
- exit (EX_USAGE);
- }
- (void) unsetenv("HOSTALIASES");
-# else
+ case MD_FGDAEMON:
+# ifndef DAEMON
usrerr("Daemon mode not implemented");
ExitStat = EX_USAGE;
break;
@@ -496,11 +530,14 @@ main(argc, argv, envp)
ExitStat = EX_USAGE;
break;
# endif /* SMTP */
+
+ case MD_INITALIAS:
case MD_DELIVER:
case MD_VERIFY:
case MD_TEST:
- case MD_INITALIAS:
case MD_PRINT:
+ case MD_HOSTSTAT:
+ case MD_PURGESTAT:
case MD_ARPAFTP:
OpMode = j;
break;
@@ -557,7 +594,6 @@ main(argc, argv, envp)
{
usrerr("Bad hop count (%s)", optarg);
ExitStat = EX_USAGE;
- break;
}
break;
@@ -565,6 +601,29 @@ main(argc, argv, envp)
NoAlias = TRUE;
break;
+ case 'N': /* delivery status notifications */
+ DefaultNotify |= QHASNOTIFY;
+ 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;
@@ -595,7 +654,6 @@ main(argc, argv, envp)
case 'q': /* run queue files at intervals */
# ifdef QUEUE
- (void) unsetenv("HOSTALIASES");
FullName = NULL;
queuemode = TRUE;
switch (optarg[0])
@@ -622,10 +680,41 @@ main(argc, argv, envp)
# 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;
+ }
+ break;
+
case 't': /* read recipients from message */
GrabTo = TRUE;
break;
+ case 'U': /* initial (user) submission */
+ UserSubmission = TRUE;
+ 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);
+ break;
+
case 'X': /* traffic log file */
endpwent();
setgid(RealGid);
@@ -634,6 +723,7 @@ main(argc, argv, envp)
if (TrafficLogFile == NULL)
{
syserr("cannot open %s", optarg);
+ ExitStat = EX_CANTCREAT;
break;
}
#ifdef HASSETVBUF
@@ -706,11 +796,28 @@ main(argc, argv, envp)
#endif
vendor_pre_defaults(CurEnv);
readcf(getcfname(), safecf, CurEnv);
+ ConfigFileRead = TRUE;
vendor_post_defaults(CurEnv);
/* avoid denial-of-service attacks */
resetlimits();
+ if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
+ {
+ /* drop privileges -- daemon mode done after socket/bind */
+ if (RunAsGid != 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != 0)
+ (void) setuid(RunAsUid);
+ }
+
+ /*
+ ** Find our real host name for future logging.
+ */
+
+ p = getauthinfo(STDIN_FILENO);
+ define('_', p, CurEnv);
+
/* suppress error printing if errors mailed back or whatever */
if (CurEnv->e_errormode != EM_PRINT)
HoldErrs = TRUE;
@@ -734,18 +841,6 @@ main(argc, argv, envp)
}
/*
- ** Initialize name server if it is going to be used.
- */
-
-#if NAMED_BIND
- if (UseNameServer && !bitset(RES_INIT, _res.options))
- res_init();
-# ifdef RES_NOALIASES
- _res.options |= RES_NOALIASES;
-# endif
-#endif
-
- /*
** Do more command line checking -- these are things that
** have to modify the results of reading the config file.
*/
@@ -770,6 +865,10 @@ main(argc, argv, envp)
CurEnv->e_bodytype = NULL;
}
+ /* tweak default DSN notifications */
+ if (DefaultNotify == 0)
+ DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
+
/* Enforce use of local time (null string overrides this) */
if (TimeZoneSpec == NULL)
unsetenv("TZ");
@@ -782,8 +881,22 @@ main(argc, argv, envp)
/* check for sane configuration level */
if (ConfigLevel > MAXCONFIGLEVEL)
{
- syserr("Warning: .cf version level (%d) exceeds program functionality (%d)",
- 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");
}
if (MeToo)
@@ -791,13 +904,43 @@ main(argc, argv, envp)
switch (OpMode)
{
+ case MD_TEST:
+ /* don't have persistent host status in test mode */
+ HostStatDir = NULL;
+ break;
+
+ case MD_FGDAEMON:
+ run_in_foreground = TRUE;
+ OpMode = MD_DAEMON;
+ /* fall through ... */
+
case MD_DAEMON:
+ /* check for permissions */
+ if (RealUid != 0)
+ {
+#ifdef LOG
+ if (LogLevel > 1)
+ syslog(LOG_ALERT, "user %d attempted to run daemon",
+ RealUid);
+#endif
+ usrerr("Permission denied");
+ exit(EX_USAGE);
+ }
+ vendor_daemon_setup(CurEnv);
+
/* remove things that don't make sense in daemon mode */
FullName = NULL;
GrabTo = FALSE;
/* arrange to restart on hangup signal */
+#ifdef LOG
+ if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
+ syslog(LOG_WARNING, "daemon invoked without full pathname; kill -1 won't work");
+#endif
setsignal(SIGHUP, sighup);
+
+ /* workaround: can't seem to release the signal in the parent */
+ releasesignal(SIGHUP);
break;
case MD_INITALIAS:
@@ -908,11 +1051,20 @@ main(argc, argv, envp)
setuserenv("ISP", NULL);
setuserenv("SYSTYPE", NULL);
}
+ 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/* subtypes that can be treated as messages */
+ /* MIME message/xxx subtypes that can be treated as messages */
setclass('s', "rfc822");
/* MIME Content-Transfer-Encodings that can be encoded */
@@ -920,11 +1072,36 @@ main(argc, argv, envp)
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
+
/* operate in queue directory */
- if (OpMode != MD_TEST && chdir(QueueDir) < 0)
+ if (OpMode == MD_TEST)
+ /* nothing -- just avoid further if clauses */ ;
+ else if (QueueDir == NULL)
+ {
+ syserr("QueueDirectory (Q) option must be set");
+ ExitStat = EX_CONFIG;
+ }
+ else if (chdir(QueueDir) < 0)
{
syserr("cannot chdir(%s)", QueueDir);
- ExitStat = EX_SOFTWARE;
+ ExitStat = EX_CONFIG;
+ }
+
+ /* check host status directory for validity */
+ if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE))
+ {
+ /* cannot use this value */
+ if (tTd(0, 2))
+ printf("Cannot use HostStatusDirectory = %s: %s\n",
+ HostStatDir, errstring(errno));
+ HostStatDir = NULL;
}
# ifdef QUEUE
@@ -965,7 +1142,7 @@ main(argc, argv, envp)
case MD_PRINT:
/* print the queue */
#ifdef QUEUE
- dropenvelope(CurEnv);
+ dropenvelope(CurEnv, TRUE);
printqueue();
endpwent();
setuid(RealUid);
@@ -975,15 +1152,33 @@ main(argc, argv, envp)
finis();
#endif /* QUEUE */
+ case MD_HOSTSTAT:
+ mci_traverse_persistent(mci_print_persistent, NULL);
+ exit(EX_OK);
+ break;
+
+ case MD_PURGESTAT:
+ mci_traverse_persistent(mci_purge_persistent, NULL);
+ exit(EX_OK);
+ break;
+
case MD_INITALIAS:
/* initialize alias database */
initmaps(TRUE, CurEnv);
endpwent();
setuid(RealUid);
- exit(EX_OK);
+ exit(ExitStat);
- case MD_DAEMON:
case MD_SMTP:
+ nullserver = FALSE;
+ /* fall through... */
+
+ case MD_DAEMON:
+ /* reset DSN parameters */
+ DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
+ CurEnv->e_envid = NULL;
+ CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
+
/* don't open alias database -- done in srvrsmtp */
break;
@@ -995,6 +1190,8 @@ main(argc, argv, envp)
if (tTd(0, 15))
{
+ extern void printrules __P((void));
+
/* print configuration table (or at least part of it) */
if (tTd(0, 90))
printrules();
@@ -1075,8 +1272,9 @@ main(argc, argv, envp)
if (OpMode == MD_DAEMON || QueueIntvl != 0)
{
char dtype[200];
+ extern bool getrequests __P((ENVELOPE *));
- if (!tTd(99, 100))
+ if (!run_in_foreground && !tTd(99, 100))
{
/* put us in background */
i = fork();
@@ -1116,10 +1314,16 @@ main(argc, argv, envp)
pause();
}
# endif /* QUEUE */
- dropenvelope(CurEnv);
+ dropenvelope(CurEnv, TRUE);
#ifdef DAEMON
- getrequests();
+ nullserver = getrequests(CurEnv);
+
+ /* drop privileges */
+ if (RunAsGid != 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != 0)
+ (void) setuid(RunAsUid);
/* at this point we are in a child: reset state */
(void) newenvelope(CurEnv, CurEnv);
@@ -1129,8 +1333,7 @@ main(argc, argv, envp)
*/
p = getauthinfo(fileno(InChannel));
- define('_', p, CurEnv);
-
+ define('_', p, &BlankEnvelope);
#endif /* DAEMON */
}
@@ -1141,14 +1344,34 @@ main(argc, argv, envp)
*/
if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
- smtp(CurEnv);
+ {
+ char pbuf[20];
+ extern void smtp __P((bool, ENVELOPE *));
+
+ /*
+ ** Save some macros for check_* rulesets.
+ */
+
+ define(macid("{client_name}", NULL), RealHostName, &BlankEnvelope);
+ define(macid("{client_addr}", NULL),
+ newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope);
+ if (RealHostAddr.sa.sa_family == AF_INET)
+ snprintf(pbuf, sizeof pbuf, "%d", RealHostAddr.sin.sin_port);
+ else
+ snprintf(pbuf, sizeof pbuf, "0");
+ define(macid("{client_port}", NULL), newstr(pbuf), &BlankEnvelope);
+
+ smtp(nullserver, CurEnv);
+ }
# endif /* SMTP */
+ clearenvelope(CurEnv, FALSE);
if (OpMode == MD_VERIFY)
{
CurEnv->e_sendmode = SM_VERIFY;
- CurEnv->e_errormode = EM_QUIET;
+ CurEnv->e_errormode = EM_PRINT;
PostMasterCopy = NULL;
+ HoldErrs = FALSE;
}
else
{
@@ -1224,6 +1447,8 @@ main(argc, argv, envp)
*/
finis();
+ /*NOTREACHED*/
+ return -1;
}
@@ -1264,7 +1489,8 @@ finis()
/* clean up temp files */
CurEnv->e_to = NULL;
- dropenvelope(CurEnv);
+ if (CurEnv->e_id != NULL)
+ dropenvelope(CurEnv, TRUE);
/* flush any cached connections */
mci_flush(TRUE, NULL);
@@ -1307,6 +1533,11 @@ finis()
void
intsig()
{
+#ifdef LOG
+ if (LogLevel > 79)
+ syslog(LOG_DEBUG, "%s: interrupt",
+ CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id);
+#endif
FileName = NULL;
unlockqueue(CurEnv);
#ifdef XLA
@@ -1338,24 +1569,24 @@ intsig()
struct metamac MetaMacros[] =
{
/* LHS pattern matching characters */
- '*', MATCHZANY, '+', MATCHANY, '-', MATCHONE,
- '=', MATCHCLASS, '~', MATCHNCLASS,
+ { '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE },
+ { '=', MATCHCLASS }, { '~', MATCHNCLASS },
/* these are RHS metasymbols */
- '#', CANONNET, '@', CANONHOST, ':', CANONUSER,
- '>', CALLSUBR,
+ { '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER },
+ { '>', CALLSUBR },
/* the conditional operations */
- '?', CONDIF, '|', CONDELSE, '.', CONDFI,
+ { '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI },
/* the hostname lookup characters */
- '[', HOSTBEGIN, ']', HOSTEND,
- '(', LOOKUPBEGIN, ')', LOOKUPEND,
+ { '[', HOSTBEGIN }, { ']', HOSTEND },
+ { '(', LOOKUPBEGIN }, { ')', LOOKUPEND },
/* miscellaneous control characters */
- '&', MACRODEXPAND,
+ { '&', MACRODEXPAND },
- '\0'
+ { '\0' }
};
#define MACBINDING(name, mid) \
@@ -1427,6 +1658,11 @@ disconnect(droplev, e)
printf("don't\n");
return;
}
+#ifdef LOG
+ if (LogLevel > 93)
+ syslog(LOG_DEBUG, "%s: disconnect level %d",
+ e->e_id == NULL ? "[NOQUEUE]" : e->e_id, droplev);
+#endif
/* be sure we don't get nasty signals */
(void) setsignal(SIGINT, SIG_IGN);
@@ -1576,7 +1812,7 @@ auth_warning(e, msg, va_alist)
(void) snprintf(buf, sizeof buf, "%s: ", hostbuf);
p = &buf[strlen(buf)];
VA_START(msg);
- vsnprintf(p, sizeof buf - (p - buf), msg, ap);
+ vsnprintf(p, SPACELEFT(buf, p), msg, ap);
VA_END;
addheader("X-Authentication-Warning", buf, &e->e_header);
#ifdef LOG
@@ -1587,6 +1823,31 @@ auth_warning(e, msg, va_alist)
}
}
/*
+** 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:
@@ -1611,7 +1872,7 @@ setuserenv(envar, value)
if (value == NULL)
{
- value = getenv(envar);
+ value = getextenv(envar);
if (value == NULL)
return;
}
@@ -1650,6 +1911,7 @@ dumpstate(when)
{
#ifdef LOG
register char *j = macvalue('j', CurEnv);
+ int rs;
syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
when,
@@ -1664,16 +1926,18 @@ dumpstate(when)
printopenfds(TRUE);
syslog(LOG_DEBUG, "--- connection cache: ---");
mci_dump_all(TRUE);
- if (RewriteRules[89] != NULL)
+ rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
+ if (rs > 0)
{
int stat;
register char **pvp;
char *pv[MAXATOM + 1];
pv[0] = NULL;
- stat = rewrite(pv, 89, 0, CurEnv);
- syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
- stat);
+ stat = rewrite(pv, rs, 0, CurEnv);
+ syslog(LOG_DEBUG,
+ "--- ruleset debug_dumpstate returns stat %d, pv: ---",
+ stat);
for (pvp = pv; *pvp != NULL; pvp++)
syslog(LOG_DEBUG, "%s", *pvp);
}
@@ -1697,6 +1961,15 @@ sighup()
syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]);
#endif
releasesignal(SIGHUP);
+ if (setgid(RealGid) < 0 || setuid(RealUid) < 0)
+ {
+#ifdef LOG
+ if (LogLevel > 0)
+ syslog(LOG_ALERT, "could not set[ug]id(%d, %d): %m",
+ RealUid, RealGid);
+#endif
+ exit(EX_OSERR);
+ }
execv(SaveArgv[0], (ARGV_T) SaveArgv);
#ifdef LOG
if (LogLevel > 0)
@@ -1739,6 +2012,7 @@ testmodeline(line, e)
extern char *crackaddr __P((char *));
extern void dump_class __P((STAB *, int));
extern void translate_dollars __P((char *));
+ extern void help __P((char *));
switch (line[0])
{
@@ -1805,7 +2079,10 @@ testmodeline(line, e)
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;
@@ -1827,7 +2104,7 @@ testmodeline(line, e)
putchar(' ');
}
putchar('\n');
- } while (rw = rw->r_next);
+ } while ((rw = rw->r_next) != NULL);
break;
case 'M':
@@ -1926,7 +2203,6 @@ testmodeline(line, e)
}
else if (strcasecmp(&line[1], "canon") == 0)
{
- auto int rcode = EX_OK;
char host[MAXHOSTNAMELEN];
if (*p == '\0')
@@ -1940,9 +2216,8 @@ testmodeline(line, e)
return;
}
strcpy(host, p);
- getcanonname(host, sizeof(host), HasWildcardMX, &rcode);
- printf("getcanonname(%s) returns %s (%d)\n",
- p, host, rcode);
+ (void) getcanonname(host, sizeof(host), HasWildcardMX);
+ printf("getcanonname(%s) returns %s\n", p, host);
}
else if (strcasecmp(&line[1], "map") == 0)
{
@@ -2006,6 +2281,7 @@ testmodeline(line, e)
p = remotename(q, m, tryflags, &rcode, CurEnv);
printf("Rcode = %d, addr = %s\n",
rcode, p == NULL ? "<NULL>" : p);
+ e->e_to = NULL;
}
else if (strcasecmp(&line[1], "tryflags") == 0)
{
@@ -2061,6 +2337,7 @@ testmodeline(line, e)
else
printf("mailer %s, user %s\n",
a.q_mailer->m_name, a.q_user);
+ e->e_to = NULL;
}
else
{
@@ -2098,7 +2375,10 @@ testmodeline(line, e)
int rs = strtorwset(p, NULL, ST_FIND);
if (rs < 0)
+ {
+ printf("Undefined ruleset %s\n", p);
break;
+ }
stat = rewrite(pvp, rs, 0, e);
if (stat != EX_OK)
printf("== Ruleset %s (%d) status %d\n",
diff --git a/usr.sbin/sendmail/src/makesendmail b/usr.sbin/sendmail/src/makesendmail
index df202e9163e2..1b266c3564a5 100644
--- a/usr.sbin/sendmail/src/makesendmail
+++ b/usr.sbin/sendmail/src/makesendmail
@@ -1,6 +1,6 @@
#!/bin/sh
-# Copyright (c) 1993 Eric P. Allman
+# Copyright (c) 1993, 1996 Eric P. Allman
# Copyright (c) 1993 The Regents of the University of California.
# All rights reserved.
#
@@ -32,7 +32,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)makesendmail 8.29 (Berkeley) 8/1/95
+# @(#)makesendmail 8.41 (Berkeley) 9/23/96
#
#
@@ -51,12 +51,12 @@ fi
#
# Do heuristic guesses !ONLY! for machines that do not have uname
#
-if [ -d /LocalApps -a ! -f /bin/uname -a ! -f /usr/bin/uname ]
+if [ -d /NextApps -a ! -f /bin/uname -a ! -f /usr/bin/uname ]
then
# probably a NeXT box
- arch=NeXT
- os=Mach
- rel=`strings /mach | grep 'Mach.*:' | sed -e 's/.* Mach //' -e 's/:.*//'`
+ 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
@@ -85,8 +85,8 @@ fi
if [ ! "$arch" -a ! "$os" -a ! "$rel" ]
then
arch=`uname -m | sed -e 's/ //g'`
- os=`uname -s | sed 's/\//-/g'`
- rel=`uname -r`
+ os=`uname -s | sed -e 's/\//-/g' -e 's/ //g'`
+ rel=`uname -r | sed -e 's/(/-/g' -e 's/)//g'`
fi
#
@@ -104,6 +104,8 @@ in
sun4*) arch=sun4;;
9000/*) arch=`echo $arch | sed -e 's/9000.//' -e 's/..$/xx/'`;;
+
+ DS/907000) arch=ds90;;
esac
# tweak operating system type and release
@@ -112,12 +114,27 @@ in
DYNIX-ptx) os=PTX;;
Paragon*) os=Paragon;;
HP-UX) rel=`echo $rel | sed -e 's/^[^.]*\.0*//'`;;
- AIX) rel=`uname -v`;;
+ AIX) rel=`uname -v`
+ if [ "$rel" = "2" ]
+ then
+ arch=""
+ fi;;
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;;
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" ]
@@ -164,11 +181,13 @@ else
sfx=".${SENDMAIL_SUFFIX}"
fi
-echo "Configuration: os=$os, rel=$rel, rbase=$rbase, arch=$arch, sfx=$sfx"
+echo "Configuration: os=$os, rel=$rel, rbase=$rbase, rroot=$rroot, arch=$arch, sfx=$sfx"
# now try to find a reasonable object directory
if [ -r obj.$os.$rel.$arch$sfx ]; then
obj=obj.$os.$rel.$arch$sfx
+elif [ -r obj.$os.$rroot.$arch$sfx ]; then
+ obj=obj.$os.$rroot.$arch$sfx
elif [ -r obj.$os.$rbase.x.$arch$sfx ]; then
obj=obj.$os.$rbase.x.$arch$sfx
elif [ -r obj.$os.$rel$sfx ]; then
@@ -196,6 +215,10 @@ else
makefile=Makefile.$os.$rel.$arch$sfx
elif [ -r Makefiles/Makefile.$os.$rel.$arch ]; then
makefile=Makefile.$os.$rel.$arch
+ elif [ -r Makefiles/Makefile.$os.$rroot.$arch$sfx ]; then
+ makefile=Makefile.$os.$rroot.$arch$sfx
+ elif [ -r Makefiles/Makefile.$os.$rroot.$arch ]; then
+ makefile=Makefile.$os.$rroot.$arch
elif [ -r Makefiles/Makefile.$os.$rbase.x.$arch$sfx ]; then
makefile=Makefile.$os.$rbase.x.$arch$sfx
elif [ -r Makefiles/Makefile.$os.$rbase.x.$arch ]; then
@@ -204,6 +227,10 @@ else
makefile=Makefile.$os.$rel$sfx
elif [ -r Makefiles/Makefile.$os.$rel ]; then
makefile=Makefile.$os.$rel
+ elif [ -r Makefiles/Makefile.$os.$rroot$sfx ]; then
+ makefile=Makefile.$os.$rroot$sfx
+ elif [ -r Makefiles/Makefile.$os.$rroot ]; then
+ makefile=Makefile.$os.$rroot
elif [ -r Makefiles/Makefile.$os.$rbase.x$sfx ]; then
makefile=Makefile.$os.$rbase.x$sfx
elif [ -r Makefiles/Makefile.$os.$rbase.x ]; then
@@ -216,6 +243,10 @@ else
makefile=Makefile.$rel.$arch$sfx
elif [ -r Makefiles/Makefile.$rel.$arch ]; then
makefile=Makefile.$rel.$arch
+ elif [ -r Makefiles/Makefile.$rroot.$arch$sfx ]; then
+ makefile=Makefile.$rroot.$arch$sfx
+ elif [ -r Makefiles/Makefile.$rroot.$arch ]; then
+ makefile=Makefile.$rroot.$arch
elif [ -r Makefiles/Makefile.$rbase.x.$arch$sfx ]; then
makefile=Makefile.$rbase.x.$arch$sfx
elif [ -r Makefiles/Makefile.$rbase.x.$arch ]; then
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c
index 13d38ce97bec..34e6fce289b1 100644
--- a/usr.sbin/sendmail/src/map.c
+++ b/usr.sbin/sendmail/src/map.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1992, 1995 Eric P. Allman.
+ * Copyright (c) 1992, 1995, 1996 Eric P. Allman.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,25 +33,29 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)map.c 8.108.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)map.c 8.144 (Berkeley) 11/16/96";
#endif /* not lint */
#include "sendmail.h"
#ifdef NDBM
# include <ndbm.h>
-#endif
-#ifdef NEWDB
# ifdef R_FIRST
ERROR README: You are running the Berkeley DB version of ndbm.h. See
ERROR README: the READ_ME file about tweaking Berkeley DB so it can
- ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile.
+ ERROR README: coexist with NDBM, or delete -DNDBM from the Makefile
+ ERROR README: and use -DNEWDB instead.
# endif
+#endif
+#ifdef NEWDB
# include <db.h>
#endif
#ifdef NIS
struct dom_binding; /* forward reference needed on IRIX */
# include <rpcsvc/ypclnt.h>
+# ifdef NDBM
+# define NDBM_YP_COMPAT /* create YP-compatible NDBM files */
+# endif
#endif
/*
@@ -96,12 +100,14 @@ static char sccsid[] = "@(#)map.c 8.108.1.2 (Berkeley) 9/16/96";
#define DBMMODE 0644
-#define EX_NOTFOUND EX_NOHOST
+#ifndef EX_NOTFOUND
+# define EX_NOTFOUND EX_NOHOST
+#endif
extern bool aliaswait __P((MAP *, char *, int));
extern bool extract_canonname __P((char *, char *, char[], int));
-#if defined(O_EXLOCK) && HASFLOCK
+#if O_EXLOCK && HASFLOCK
# define LOCK_ON_OPEN 1 /* we can open/create a locked file */
#else
# define LOCK_ON_OPEN 0 /* no such luck -- bend over backwards */
@@ -204,6 +210,11 @@ map_parseargs(map, ap)
}
}
break;
+
+ case 't':
+ map->map_mflags |= MF_NODEFER;
+ break;
+
#ifdef RESERVED_FOR_SUN
case 'd':
map->map_mflags |= MF_DOMAIN_WIDE;
@@ -632,10 +643,10 @@ getcanonname(host, hbsize, trymx)
printf("getcanonname(%s), failed, stat=%d\n", host, stat);
#if NAMED_BIND
- if (stat == EX_NOHOST && !got_tempfail)
- h_errno = HOST_NOT_FOUND;
- else
+ if (got_tempfail)
h_errno = TRY_AGAIN;
+ else
+ h_errno = HOST_NOT_FOUND;
#endif
return FALSE;
@@ -679,6 +690,8 @@ extract_canonname(name, line, cbuf, cbuflen)
p = get_column(line, i, '\0', nbuf, sizeof nbuf);
if (p == NULL)
break;
+ if (*p == '\0')
+ continue;
if (cbuf[0] == '\0' ||
(strchr(cbuf, '.') == NULL && strchr(p, '.') != NULL))
{
@@ -724,6 +737,7 @@ ndbm_map_open(map, mode)
if (tTd(38, 2))
printf("ndbm_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
+ map->map_lockfd = -1;
#if LOCK_ON_OPEN
if (mode == O_RDONLY)
@@ -733,7 +747,7 @@ ndbm_map_open(map, mode)
#else
if (mode == O_RDWR)
{
-# ifdef NOFTRUNCATE
+# if NOFTRUNCATE
/*
** Warning: race condition. Try to lock the file as
** quickly as possible after opening it.
@@ -768,15 +782,15 @@ ndbm_map_open(map, mode)
if (!lockfile(dirfd, map->map_file, ".dir", LOCK_EX))
syserr("ndbm_map_open: cannot lock %s.dir",
map->map_file);
- if (ftruncate(dirfd, 0) < 0)
+ if (ftruncate(dirfd, (off_t) 0) < 0)
syserr("ndbm_map_open: cannot truncate %s.dir",
map->map_file);
- if (ftruncate(pagfd, 0) < 0)
+ if (ftruncate(pagfd, (off_t) 0) < 0)
syserr("ndbm_map_open: cannot truncate %s.pag",
map->map_file);
- /* we can safely unlock because others will wait for @:@ */
- close(dirfd);
+ /* have to save the lock for the duration (bletch) */
+ map->map_lockfd = dirfd;
close(pagfd);
# endif
}
@@ -807,12 +821,7 @@ ndbm_map_open(map, mode)
}
else
{
- /* exclusive lock for duration of rebuild */
-#if !LOCK_ON_OPEN
- if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
- lockfile(fd, map->map_file, ".dir", LOCK_EX))
-#endif
- map->map_mflags |= MF_LOCKED;
+ map->map_mflags |= MF_LOCKED;
}
if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
map->map_mtime = st.st_mtime;
@@ -845,7 +854,8 @@ ndbm_map_lookup(map, name, av, statp)
{
if (key.dsize > sizeof keybuf - 1)
key.dsize = sizeof keybuf - 1;
- bcopy(key.dptr, keybuf, key.dsize + 1);
+ bcopy(key.dptr, keybuf, key.dsize);
+ keybuf[key.dsize] = '\0';
makelower(keybuf);
key.dptr = keybuf;
}
@@ -890,6 +900,7 @@ ndbm_map_store(map, lhs, rhs)
datum key;
datum data;
int stat;
+ char keybuf[MAXNAME + 1];
if (tTd(38, 12))
printf("ndbm_map_store(%s, %s, %s)\n",
@@ -897,6 +908,15 @@ ndbm_map_store(map, 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;
+ bcopy(key.dptr, keybuf, key.dsize);
+ keybuf[key.dsize] = '\0';
+ makelower(keybuf);
+ key.dptr = keybuf;
+ }
data.dsize = strlen(rhs);
data.dptr = rhs;
@@ -920,7 +940,7 @@ ndbm_map_store(map, lhs, rhs)
datum old;
old.dptr = ndbm_map_lookup(map, key.dptr, NULL, &xstat);
- if (old.dptr != NULL && *old.dptr != '\0')
+ if (old.dptr != NULL && *(char *) old.dptr != '\0')
{
old.dsize = strlen(old.dptr);
if (data.dsize + old.dsize + 2 > bufsiz)
@@ -959,7 +979,7 @@ ndbm_map_close(map)
if (bitset(MF_WRITABLE, map->map_mflags))
{
-#ifdef NIS
+#ifdef NDBM_YP_COMPAT
bool inclnull;
char buf[200];
@@ -968,11 +988,17 @@ ndbm_map_close(map)
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)
@@ -983,6 +1009,12 @@ ndbm_map_close(map)
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
}
#endif
@@ -1004,15 +1036,30 @@ ndbm_map_close(map)
** be pokey about it. That's hard to do.
*/
+extern bool db_map_open __P((MAP *, int, DBTYPE, const void *));
+
+/* these should be K line arguments */
+#ifndef DB_CACHE_SIZE
+# define DB_CACHE_SIZE (1024 * 1024) /* database memory cache size */
+#endif
+#ifndef DB_HASH_NELEM
+# define DB_HASH_NELEM 4096 /* (starting) size of hash table */
+#endif
+
bool
bt_map_open(map, mode)
MAP *map;
int mode;
{
+ BTREEINFO btinfo;
+
if (tTd(38, 2))
printf("bt_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
- return db_map_open(map, mode, DB_BTREE);
+
+ bzero(&btinfo, sizeof btinfo);
+ btinfo.cachesize = DB_CACHE_SIZE;
+ return db_map_open(map, mode, DB_BTREE, &btinfo);
}
bool
@@ -1020,17 +1067,24 @@ hash_map_open(map, mode)
MAP *map;
int mode;
{
+ HASHINFO hinfo;
+
if (tTd(38, 2))
printf("hash_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
- return db_map_open(map, mode, DB_HASH);
+
+ bzero(&hinfo, sizeof hinfo);
+ hinfo.nelem = DB_HASH_NELEM;
+ hinfo.cachesize = DB_CACHE_SIZE;
+ return db_map_open(map, mode, DB_HASH, &hinfo);
}
bool
-db_map_open(map, mode, dbtype)
+db_map_open(map, mode, dbtype, openinfo)
MAP *map;
int mode;
DBTYPE dbtype;
+ const void *openinfo;
{
DB *db;
int i;
@@ -1044,6 +1098,7 @@ db_map_open(map, mode, dbtype)
i = strlen(buf);
if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
(void) strcat(buf, ".db");
+ map->map_lockfd = -1;
omode = mode;
@@ -1068,8 +1123,8 @@ db_map_open(map, mode, dbtype)
if (fd < 0)
{
- syserr("db_map_open: cannot pre-open database %s",
- buf);
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("db_map_open: cannot pre-open database %s", buf);
close(fd);
return FALSE;
}
@@ -1080,12 +1135,14 @@ db_map_open(map, mode, dbtype)
omode |= O_TRUNC;
#endif
- db = dbopen(buf, omode, DBMMODE, dbtype, NULL);
+ db = dbopen(buf, omode, DBMMODE, dbtype, openinfo);
saveerrno = errno;
#if !LOCK_ON_OPEN
- /* we can safely unlock now because others will wait for @:@ */
- close(fd);
+ if (mode == O_RDWR)
+ map->map_lockfd = fd;
+ else
+ (void) close(fd);
#endif
if (db == NULL)
@@ -1098,21 +1155,15 @@ db_map_open(map, mode, dbtype)
syserr("Cannot open DB database %s", map->map_file);
return FALSE;
}
+
+ if (mode == O_RDWR)
+ map->map_mflags |= MF_LOCKED;
#if !OLD_NEWDB
fd = db->fd(db);
# if LOCK_ON_OPEN
- if (fd >= 0)
+ if (fd >= 0 && mode == O_RDONLY)
{
- if (mode == O_RDONLY)
- (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
- else
- map->map_mflags |= MF_LOCKED;
- }
-# else
- if (mode == O_RDWR && fd >= 0)
- {
- if (lockfile(fd, map->map_file, ".db", LOCK_EX))
- map->map_mflags |= MF_LOCKED;
+ (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
}
# endif
#endif
@@ -1162,7 +1213,8 @@ db_map_lookup(map, name, av, statp)
if (key.size > sizeof keybuf - 1)
key.size = sizeof keybuf - 1;
key.data = keybuf;
- bcopy(name, keybuf, key.size + 1);
+ bcopy(name, keybuf, key.size);
+ keybuf[key.size] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
#if !OLD_NEWDB
@@ -1217,6 +1269,7 @@ db_map_store(map, lhs, rhs)
DBT key;
DBT data;
register DB *db = map->map_db2;
+ char keybuf[MAXNAME + 1];
if (tTd(38, 12))
printf("db_map_store(%s, %s, %s)\n",
@@ -1224,6 +1277,15 @@ db_map_store(map, 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;
+ bcopy(key.data, keybuf, key.size);
+ keybuf[key.size] = '\0';
+ makelower(keybuf);
+ key.data = keybuf;
+ }
data.size = strlen(rhs);
data.data = rhs;
@@ -1293,6 +1355,11 @@ db_map_close(map)
if (db->close(db) != 0)
syserr("readaliases: db close failure");
+
+#if !LOCK_ON_OPEN
+ if (map->map_lockfd >= 0)
+ (void) close(map->map_lockfd);
+#endif
}
#endif
@@ -1356,7 +1423,7 @@ nis_map_open(map, mode)
if (yperr != 0)
{
if (!bitset(MF_OPTIONAL, map->map_mflags))
- syserr("421 NIS map %s specified, but NIS not running\n",
+ syserr("421 NIS map %s specified, but NIS not running",
map->map_file);
return FALSE;
}
@@ -1418,7 +1485,8 @@ nis_map_lookup(map, name, av, statp)
buflen = strlen(name);
if (buflen > sizeof keybuf - 1)
buflen = sizeof keybuf - 1;
- bcopy(name, keybuf, buflen + 1);
+ bcopy(name, keybuf, buflen);
+ keybuf[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
yperr = YPERR_KEY;
@@ -1559,12 +1627,9 @@ nisplus_map_open(map, mode)
MAP *map;
int mode;
{
- register char *p;
- char qbuf[MAXLINE + NIS_MAXNAMELEN];
nis_result *res = NULL;
- u_int objs_len;
- nis_object *obj_ptr;
int retry_cnt, max_col, i;
+ char qbuf[MAXLINE + NIS_MAXNAMELEN];
if (tTd(38, 2))
printf("nisplus_map_open(%s, %s, %d)\n",
@@ -1727,7 +1792,8 @@ nisplus_map_lookup(map, name, av, statp)
buflen = strlen(name);
if (buflen > sizeof search_key - 1)
buflen = sizeof search_key - 1;
- bcopy(name, search_key, buflen + 1);
+ bcopy(name, search_key, buflen);
+ search_key[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(search_key);
@@ -1851,7 +1917,6 @@ nisplus_getcanonname(name, hbsize, statp)
if (result->status == NIS_SUCCESS)
{
int count;
- char *str;
char *domain;
if ((count = NIS_RES_NUMOBJ(result)) != 1)
@@ -1865,7 +1930,8 @@ nisplus_getcanonname(name, hbsize, statp)
/* ignore second entry */
if (tTd(38, 20))
- printf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n", name);
+ printf("nisplus_getcanoname(%s), got %d entries, all but first ignored\n",
+ name, count);
}
if (tTd(38, 20))
@@ -1934,6 +2000,559 @@ nisplus_default_domain()
#endif /* NISPLUS */
/*
+** LDAP Modules
+**
+** Contributed by Booker C. Bense <bbense@networking.stanford.edu>.
+** Get your support from him.
+*/
+
+#ifdef LDAPMAP
+
+# undef NEEDGETOPT /* used for something else in LDAP */
+
+# include <lber.h>
+# include <ldap.h>
+# include "ldap_map.h"
+
+/*
+** LDAP_MAP_OPEN -- open LDAP map
+**
+** Since LDAP is TCP-based there is not much we can or should do
+** here. It might be a good idea to attempt an open/close here.
+*/
+
+bool
+ldap_map_open(map, mode)
+ MAP *map;
+ int mode;
+{
+ if (tTd(38, 2))
+ printf("ldap_map_open(%s, %d)\n", map->map_mname, mode);
+
+ if (mode != O_RDONLY)
+ {
+ /* issue a pseudo-error message */
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+# ifdef EFTYPE
+ errno = EFTYPE;
+# else
+ errno = ENXIO;
+# endif
+#endif
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+/*
+** LDAP_MAP_START -- actually open LDAP map
+**
+** Caching should be investigated.
+*/
+
+bool
+ldap_map_start(map)
+ MAP *map;
+{
+ LDAP_MAP_STRUCT *lmap;
+ LDAP *ld;
+
+ if (tTd(38, 2))
+ printf("ldap_map_start(%s)\n", map->map_mname);
+
+ lmap = (LDAP_MAP_STRUCT *) map->map_db1;
+
+ if (tTd(38,9))
+ printf("ldap_open(%s, %d)\n", lmap->ldaphost, lmap->ldapport);
+
+ if ((ld = ldap_open(lmap->ldaphost,lmap->ldapport)) == NULL)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ syserr("ldapopen failed to %s in map %s",
+ lmap->ldaphost, map->map_mname);
+ }
+ return FALSE;
+ }
+
+ ld->ld_deref = lmap->deref;
+ ld->ld_timelimit = lmap->timelimit;
+ ld->ld_sizelimit = lmap->sizelimit;
+ ld->ld_options = lmap->ldap_options;
+
+ if (ldap_bind_s(ld, lmap->binddn,lmap->passwd,lmap->method) != LDAP_SUCCESS)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ syserr("421 Cannot bind to map %s in ldap server %s",
+ map->map_mname, lmap->ldaphost);
+ }
+ }
+ else
+ {
+ /* We need to cast ld into the map structure */
+ lmap->ld = ld;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*
+** LDAP_MAP_CLOSE -- close ldap map
+*/
+
+void
+ldap_map_close(map)
+ MAP *map;
+{
+ LDAP_MAP_STRUCT *lmap ;
+ lmap = (LDAP_MAP_STRUCT *) map->map_db1;
+ if (lmap->ld != NULL)
+ ldap_unbind(lmap->ld);
+}
+
+
+#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 */
+/*
+** LDAP_MAP_LOOKUP -- look up a datum in a LDAP map
+*/
+
+char *
+ldap_map_lookup(map, name, av, statp)
+ MAP *map;
+ char *name;
+ char **av;
+ int *statp;
+{
+ LDAP_MAP_STRUCT *lmap = NULL;
+ LDAPMessage *entry;
+ char *vp;
+ auto int vsize;
+ char keybuf[MAXNAME + 1];
+ char filter[LDAP_MAP_MAX_FILTER + 1];
+ char **attr_values = NULL;
+ char *result;
+ int name_len;
+
+ if (tTd(38, 20))
+ printf("ldap_map_lookup(%s, %s)\n", map->map_mname, name);
+
+ /* actually open the map */
+ if (!ldap_map_start(map))
+ {
+ result = NULL;
+ *statp = EX_TEMPFAIL;
+ goto quick_exit;
+ }
+
+ /* Get ldap struct pointer from map */
+ lmap = (LDAP_MAP_STRUCT *) map->map_db1;
+
+ name_len = strlen(name);
+ if (name_len > MAXNAME)
+ name_len = MAXNAME;
+ strncpy(keybuf, name, name_len);
+ keybuf[name_len] = '\0';
+
+ if (!bitset(MF_NOFOLDCASE, map->map_mflags))
+#ifdef SUNET_ID
+ sunet_id_hash(keybuf);
+#else
+ makelower(keybuf);
+#endif /*SUNET_ID */
+
+ /* sprintf keybuf into filter */
+ snprintf(filter, sizeof filter, lmap->filter, keybuf);
+
+ if (ldap_search_st(lmap->ld, lmap->base,lmap->scope,filter,
+ &(lmap->attr), lmap->attrsonly, &(lmap->timeout),
+ &(lmap->res)) != LDAP_SUCCESS)
+ {
+ /* try close/opening map */
+ ldap_map_close(map);
+ if (!ldap_map_start(map))
+ {
+ result = NULL;
+ *statp = EX_TEMPFAIL;
+ goto quick_exit;
+ }
+ if (ldap_search_st(lmap->ld, lmap->base, lmap->scope, filter,
+ &(lmap->attr), lmap->attrsonly,
+ &(lmap->timeout), &(lmap->res))
+ != LDAP_SUCCESS)
+ {
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ {
+ syserr("Error in ldap_search_st using %s in map %s",
+ filter, map->map_mname);
+ }
+ result = NULL;
+ *statp = EX_UNAVAILABLE;
+ goto quick_exit;
+ }
+ }
+
+ entry = ldap_first_entry(lmap->ld,lmap->res);
+ if (entry == NULL)
+ {
+ result = NULL;
+ *statp = EX_NOTFOUND;
+ goto quick_exit;
+ }
+
+ /* Need to build the args for map_rewrite here */
+ attr_values = ldap_get_values(lmap->ld,entry,lmap->attr);
+ if (attr_values == NULL)
+ {
+ /* bad things happened */
+ result = NULL;
+ *statp = EX_NOTFOUND;
+ goto quick_exit;
+ }
+
+ *statp = EX_OK;
+
+ /* If there is more that one use the first */
+ vp = attr_values[0];
+ vsize = strlen(vp);
+
+# ifdef LOG
+ if (LogLevel > 9)
+ syslog(LOG_INFO, "%s: ldap %.100s => %s",
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
+ name, vp);
+# endif
+ if (bitset(MF_MATCHONLY, map->map_mflags))
+ result = map_rewrite(map, name, strlen(name), NULL);
+ else
+ result = map_rewrite(map, vp, vsize, av);
+
+ quick_exit:
+ if (attr_values != NULL)
+ ldap_value_free(attr_values);
+ if (lmap != NULL)
+ ldap_msgfree(lmap->res);
+ ldap_map_close(map);
+ return result ;
+}
+
+
+/*
+** LDAP_MAP_DEQUOTE - helper routine for ldap_map_parseargs
+*/
+
+char *
+ldap_map_dequote(str)
+ char *str;
+{
+ char *p;
+ char *start;
+ p = str;
+
+ if (*p == '"')
+ {
+ start = ++p;
+ /* Should probably swallow initial whitespace here */
+ }
+ else
+ {
+ return(str);
+ }
+ while (*p != '"' && *p != '\0')
+ {
+ p++;
+ }
+ if (*p != '\0')
+ *p = '\0';
+ return start;
+}
+
+/*
+** LDAP_MAP_PARSEARGS -- parse ldap map definition args.
+*/
+
+bool
+ldap_map_parseargs(map,args)
+ MAP *map;
+ char *args;
+{
+ register char *p = args;
+ register int done;
+ LDAP_MAP_STRUCT *lmap;
+
+ /* We need to alloc an LDAP_MAP_STRUCT struct */
+ lmap = (LDAP_MAP_STRUCT *) xalloc(sizeof(LDAP_MAP_STRUCT));
+
+ /* Set default int's here , default strings below */
+ lmap->ldapport = DEFAULT_LDAP_MAP_PORT;
+ lmap->deref = DEFAULT_LDAP_MAP_DEREF;
+ lmap->timelimit = DEFAULT_LDAP_MAP_TIMELIMIT;
+ lmap->sizelimit = DEFAULT_LDAP_MAP_SIZELIMIT;
+ lmap->ldap_options = DEFAULT_LDAP_MAP_LDAP_OPTIONS;
+ lmap->method = DEFAULT_LDAP_MAP_METHOD;
+ lmap->scope = DEFAULT_LDAP_MAP_SCOPE;
+ lmap->attrsonly = DEFAULT_LDAP_MAP_ATTRSONLY;
+ lmap->timeout.tv_sec = DEFAULT_LDAP_MAP_TIMELIMIT;
+ lmap->timeout.tv_usec = 0;
+
+ /* Default char ptrs to NULL */
+ lmap->binddn = NULL;
+ lmap->passwd = NULL;
+ lmap->base = NULL;
+ lmap->ldaphost = NULL;
+ 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;
+
+ /* Start of ldap_map specific args */
+ case 'k': /* search field */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ lmap->filter = p;
+ break;
+
+ case 'v': /* attr to return */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ lmap->attr = p;
+ 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 -- no values */
+ lmap->attrsonly += 1;
+ break;
+
+ case 's': /* search scope */
+ if (strncasecmp(p, "base", 4) == 0)
+ {
+ lmap->scope = LDAP_SCOPE_BASE;
+ }
+ else if (strncasecmp(p, "one", 3) == 0)
+ {
+ lmap->scope = LDAP_SCOPE_ONELEVEL;
+ }
+ else if (strncasecmp(p, "sub", 3) == 0)
+ {
+ lmap->scope = LDAP_SCOPE_SUBTREE;
+ }
+ else
+ { /* bad config line */
+ if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
+ {
+ syserr("Scope must be [base|one|sub] not %s in map %s",
+ p, map->map_mname);
+ return FALSE;
+ }
+ }
+ break;
+
+ case 'h': /* ldap host */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ map->map_domain = p;
+ lmap->ldaphost = p;
+ break;
+
+ case 'b': /* search base */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ lmap->base = p;
+ break;
+
+ case 'p': /* ldap port */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ lmap->ldapport = atoi(p);
+ break;
+
+ case 'l': /* time limit */
+ while (isascii(*++p) && isspace(*p))
+ continue;
+ lmap->timelimit = atoi(p);
+ break;
+
+ }
+
+ /* need to account for quoted strings here arggg... */
+ 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(ldap_map_dequote(map->map_app));
+
+ if (map->map_domain != NULL)
+ map->map_domain = newstr(ldap_map_dequote(map->map_domain));
+
+ /*
+ ** We need to swallow up all the stuff into a struct
+ ** and dump it into map->map_dbptr1
+ */
+
+ if (lmap->ldaphost != NULL)
+ lmap->ldaphost = newstr(ldap_map_dequote(lmap->ldaphost));
+ else
+ {
+ syserr("LDAP map: -h flag is required");
+ return FALSE;
+ }
+
+ if (lmap->binddn != NULL)
+ lmap->binddn = newstr(ldap_map_dequote(lmap->binddn));
+ else
+ lmap->binddn = DEFAULT_LDAP_MAP_BINDDN;
+
+
+ if (lmap->passwd != NULL)
+ lmap->passwd = newstr(ldap_map_dequote(lmap->passwd));
+ else
+ lmap->passwd = DEFAULT_LDAP_MAP_PASSWD;
+
+ if (lmap->base != NULL)
+ lmap->base = newstr(ldap_map_dequote(lmap->base));
+ else
+ {
+ syserr("LDAP map: -b flag is required");
+ return FALSE;
+ }
+
+
+ if (lmap->filter != NULL)
+ lmap->filter = newstr(ldap_map_dequote(lmap->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->attr != NULL)
+ lmap->attr = newstr(ldap_map_dequote(lmap->attr));
+ else
+ {
+ if (!bitset(MCF_OPTFILE, map->map_class->map_cflags))
+ {
+ syserr("No return attribute in %s", map->map_mname);
+ return FALSE;
+ }
+ }
+
+ map->map_db1 = (ARBPTR_T) lmap;
+ return TRUE;
+}
+
+#endif /* LDAP Modules */
+ /*
** HESIOD Modules
*/
@@ -2066,7 +2685,7 @@ ni_map_open(map, mode)
{
char *p;
- if (tTd(38, 20))
+ if (tTd(38, 2))
printf("ni_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
@@ -2240,6 +2859,9 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
}
strcat(keybuf, keyval);
+ if (tTd(38, 21))
+ printf("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
@@ -2248,11 +2870,13 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
** and return it.
*/
- for (i = 0; i < MAX_NI_LEVELS; ++i)
+ 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))
+ printf("ni_open(LOCAL) = %d\n", nis);
}
else
{
@@ -2260,6 +2884,8 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
ni_free(lastni);
lastni = ni;
nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
+ if (tTd(38, 20))
+ printf("ni_open(PARENT) = %d\n", nis);
}
/*
@@ -2287,6 +2913,8 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
continue;
+ if (tTd(38, 20))
+ printf("ni_lookupprop: len=%d\n", ninl.ni_namelist_len);
/*
** See if we have an acceptable number of values.
*/
@@ -2327,6 +2955,8 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
ni_free(ni);
if (lastni != NULL && ni != lastni)
ni_free(lastni);
+ if (tTd(38, 20))
+ printf("ni_propval returns: '%s'\n", propval);
return propval;
}
@@ -2362,37 +2992,41 @@ text_map_open(map, mode)
if (*map->map_file == '\0')
{
- if (tTd(38, 2))
- printf("text_map_open(%s): file name required\n",
- map->map_mname);
+ syserr("text map \"%s\": file name required",
+ map->map_mname);
return FALSE;
}
if (map->map_file[0] != '/')
{
- if (tTd(38, 2))
- printf("text_map_open(%s, %s): file name must be fully qualified\n",
- map->map_mname, map->map_file);
+ syserr("text map \"%s\": file name must be fully qualified",
+ map->map_mname);
return FALSE;
}
/* check to see if this map actually accessable */
if (access(map->map_file, R_OK) <0)
+ {
+ if (tTd(38, 2))
+ printf("text_map_open(%s, %s): cannot access: %s\n",
+ map->map_mname, map->map_file, errstring(errno));
+ if (!bitset(MF_OPTIONAL, map->map_mflags))
+ syserr("text map \"%s\": cannot access file %s",
+ map->map_mname, map->map_file);
return FALSE;
+ }
/* check to see if this map actually exist */
if (stat(map->map_file, &sbuf) <0)
{
- if (tTd(38, 2))
- printf("text_map_open(%s, %s): cannot stat\n",
- map->map_mname, map->map_file);
+ syserr("text_map_open(%s, %s): cannot stat",
+ map->map_mname, map->map_file);
return FALSE;
}
if (!S_ISREG(sbuf.st_mode))
{
- if (tTd(38, 2))
- printf("text_map_open(%s): %s is not a regular file\n",
- map->map_mname, map->map_file);
+ syserr("text map \"%s\": %s is not a regular file",
+ map->map_mname, map->map_file);
return FALSE;
}
@@ -2402,10 +3036,9 @@ text_map_open(map, mode)
{
if (!isdigit(*map->map_keycolnm))
{
- if (tTd(38, 2))
- printf("text_map_open(%s, %s): -k should specify a number, not %s\n",
- map->map_mname, map->map_file,
- map->map_keycolnm);
+ 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);
@@ -2417,8 +3050,7 @@ text_map_open(map, mode)
{
if (!isdigit(*map->map_valcolnm))
{
- if (tTd(38, 2))
- printf("text_map_open(%s, %s): -v should specify a number, not %s\n",
+ syserr("text map \"%s\", file %s: -v should specify a number, not %s",
map->map_mname, map->map_file,
map->map_valcolnm);
return FALSE;
@@ -2470,7 +3102,8 @@ text_map_lookup(map, name, av, statp)
buflen = strlen(name);
if (buflen > sizeof search_key - 1)
buflen = sizeof search_key - 1;
- bcopy(name, search_key, buflen + 1);
+ bcopy(name, search_key, buflen);
+ search_key[buflen] = '\0';
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(search_key);
@@ -2526,19 +3159,17 @@ text_getcanonname(name, hbsize, statp)
int hbsize;
int *statp;
{
- int key_idx;
bool found;
FILE *f;
char linebuf[MAXLINE];
char cbuf[MAXNAME + 1];
- char fbuf[MAXNAME + 1];
char nbuf[MAXNAME + 1];
extern char *get_column __P((char *, int, char, char *, int));
if (tTd(38, 20))
printf("text_getcanonname(%s)\n", name);
- if (strlen(name) >= sizeof nbuf)
+ if (strlen(name) >= (SIZE_T) sizeof nbuf)
{
*statp = EX_UNAVAILABLE;
return FALSE;
@@ -2569,7 +3200,7 @@ text_getcanonname(name, hbsize, statp)
return FALSE;
}
- if (hbsize >= strlen(cbuf))
+ if ((SIZE_T) hbsize >= strlen(cbuf))
{
strcpy(name, cbuf);
*statp = EX_OK;
@@ -2736,9 +3367,9 @@ impl_map_open(map, mode)
map->map_mflags |= MF_IMPL_HASH;
if (hash_map_open(map, mode))
{
-#if defined(NDBM) && defined(NIS)
+# ifdef NDBM_YP_COMPAT
if (mode == O_RDONLY || strstr(map->map_file, "/yp/") == NULL)
-#endif
+# endif
return TRUE;
}
else
@@ -2866,12 +3497,13 @@ user_map_lookup(map, key, av, statp)
int *statp;
{
struct passwd *pw;
+ auto bool fuzzy;
if (tTd(38, 20))
printf("user_map_lookup(%s, %s)\n",
map->map_mname, key);
- pw = sm_getpwnam(key);
+ pw = finduser(key, &fuzzy);
if (pw == NULL)
return NULL;
if (bitset(MF_MATCHONLY, map->map_mflags))
@@ -2986,13 +3618,14 @@ prog_map_lookup(map, name, av, statp)
map->map_mname, errstring(errno));
rval = NULL;
}
- else if (i == 0 && tTd(38, 20))
+ else if (i == 0)
{
- printf("prog_map_lookup(%s): empty answer\n",
- map->map_mname);
+ if (tTd(38, 20))
+ printf("prog_map_lookup(%s): empty answer\n",
+ map->map_mname);
rval = NULL;
}
- if (i > 0)
+ else
{
buf[i] = '\0';
p = strchr(buf, '\n');
diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c
index beff01977351..18e951a36008 100644
--- a/usr.sbin/sendmail/src/mci.c
+++ b/usr.sbin/sendmail/src/mci.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995 Eric P. Allman
+ * Copyright (c) 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,10 +33,11 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)mci.c 8.22.1.1 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)mci.c 8.46 (Berkeley) 11/3/96";
#endif /* not lint */
#include "sendmail.h"
+#include <dirent.h>
/*
** Mail Connection Information (MCI) Caching Module.
@@ -62,10 +63,17 @@ static char sccsid[] = "@(#)mci.c 8.22.1.1 (Berkeley) 9/16/96";
** 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.
*/
MCI **MciCache; /* the open connection cache */
+extern int mci_generate_persistent_path __P((const char *, char *, int, bool));
+extern void mci_load_persistent __P((MCI *));
extern void mci_uncache __P((MCI **, bool));
/*
** MCI_CACHE -- enter a connection structure into the open connection cache
@@ -84,7 +92,6 @@ mci_cache(mci)
register MCI *mci;
{
register MCI **mcislot;
- extern MCI **mci_scan();
/*
** Find the best slot. This may cause expired connections
@@ -204,6 +211,8 @@ mci_uncache(mcislot, doquit)
return;
*mcislot = NULL;
+ mci_unlock_host(mci);
+
if (tTd(42, 5))
printf("mci_uncache: uncaching %x (%s) from slot %d (%d)\n",
mci, mci->mci_host, mcislot - MciCache, doquit);
@@ -279,7 +288,6 @@ mci_get(host, m)
{
register MCI *mci;
register STAB *s;
- extern MCI **mci_scan();
#ifdef DAEMON
extern SOCKADDR CurHostAddr;
@@ -297,6 +305,8 @@ mci_get(host, m)
mci = &s->s_mci;
mci->mci_host = s->s_name;
+ mci_load_persistent(mci);
+
if (tTd(42, 2))
{
printf("mci_get(%s %s): mci_state=%d, _flags=%x, _exitstat=%d, _errno=%d\n",
@@ -307,8 +317,10 @@ mci_get(host, m)
#ifdef SMTP
if (mci->mci_state == MCIS_OPEN)
{
+ extern int smtpprobe __P((MCI *));
+
/* poke the connection to see if it's still alive */
- smtpprobe(mci);
+ (void) smtpprobe(mci);
/* reset the stored state in the event of a timeout */
if (mci->mci_state != MCIS_OPEN)
@@ -330,7 +342,6 @@ mci_get(host, m)
# endif
}
#endif
-#ifdef MAYBE_NEXT_RELEASE
if (mci->mci_state == MCIS_CLOSED)
{
time_t now = curtime();
@@ -343,11 +354,38 @@ mci_get(host, m)
mci->mci_exitstat = EX_OK;
}
}
-#endif
return mci;
}
/*
+** 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;
+{
+ 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:
@@ -360,6 +398,32 @@ mci_get(host, m)
** none.
*/
+struct mcifbits
+{
+ int mcif_bit; /* flag bit */
+ char *mcif_name; /* flag name */
+};
+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;
@@ -379,9 +443,25 @@ mci_dump(mci, logit)
snprintf(p, SPACELEFT(buf, p), "NULL");
goto printit;
}
+ snprintf(p, SPACELEFT(buf, p), "flags=%x", 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),
- "flags=%x, errno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
- mci->mci_flags, mci->mci_errno, mci->mci_herrno,
+ ",%serrno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
+ sep, mci->mci_errno, mci->mci_herrno,
mci->mci_exitstat, mci->mci_state, mci->mci_pid, sep);
p += strlen(p);
snprintf(p, SPACELEFT(buf, p),
@@ -392,6 +472,12 @@ mci_dump(mci, logit)
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));
@@ -426,3 +512,761 @@ mci_dump_all(logit)
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))
+ printf("mci_lock_host: NULL mci\n");
+ return EX_OK;
+ }
+
+ if (!SingleThreadDelivery)
+ return EX_OK;
+
+ return mci_lock_host_statfile(mci);
+}
+
+int
+mci_lock_host_statfile(mci)
+ MCI *mci;
+{
+ int savedErrno = errno;
+ int retVal = EX_OK;
+ char fname[MAXPATHLEN+1];
+
+ if (HostStatDir == NULL || mci->mci_host == NULL)
+ return EX_OK;
+
+ if (tTd(56, 2))
+ printf("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))
+ printf("mci_lock_host: Failed to generate host path for %s\n",
+ mci->mci_host);
+
+ retVal = EX_TEMPFAIL;
+ goto cleanup;
+ }
+
+ if ((mci->mci_statfile = fopen(fname, "r+")) == NULL)
+ mci->mci_statfile = fopen(fname, "w");
+
+ 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))
+ printf("mci_lock_host: couldn't get lock on %s\n",
+ fname);
+ fclose(mci->mci_statfile);
+ mci->mci_statfile = NULL;
+ retVal = EX_TEMPFAIL;
+ goto cleanup;
+ }
+
+ if (tTd(56, 12) && mci->mci_statfile != NULL)
+ printf("mci_lock_host: Sanity check -- lock is good\n");
+
+cleanup:
+ errno = savedErrno;
+ 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 saveErrno = errno;
+
+ if (mci == NULL)
+ {
+ if (tTd(56, 1))
+ printf("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))
+ printf("mci_unlock_host: stat file already locked\n");
+ }
+ else
+ {
+ if (tTd(56, 2))
+ printf("mci_unlock_host: store prior to unlock\n");
+
+ mci_store_persistent(mci);
+ }
+
+ if (mci->mci_statfile != NULL)
+ {
+ fclose(mci->mci_statfile);
+ mci->mci_statfile = NULL;
+ }
+
+ errno = saveErrno;
+}
+ /*
+** 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:
+** none.
+*/
+
+void
+mci_load_persistent(mci)
+ MCI *mci;
+{
+ int saveErrno = errno;
+ FILE *fp;
+ int status;
+ char fname[MAXPATHLEN+1];
+
+ if (mci == NULL)
+ {
+ if (tTd(56, 1))
+ printf("mci_load_persistent: NULL mci\n");
+ return;
+ }
+
+ if (HostStatDir == NULL || mci->mci_host == NULL)
+ return;
+
+ if (tTd(56, 1))
+ printf("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))
+ printf("mci_load_persistent: Couldn't generate host path\n");
+ goto cleanup;
+ }
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ {
+ /* I can't think of any reason this should ever happen */
+ if (tTd(56, 1))
+ printf("mci_load_persistent: open(%s): %s\n",
+ fname, errstring(errno));
+ goto cleanup;
+ }
+
+ FileName = fname;
+ (void) mci_read_persistent(fp, mci);
+ FileName = NULL;
+ fclose(fp);
+
+cleanup:
+ errno = saveErrno;
+ return;
+}
+ /*
+** 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.
+*/
+
+int
+mci_read_persistent(fp, mci)
+ FILE *fp;
+ register MCI *mci;
+{
+ int ver;
+ register char *p;
+ 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))
+ {
+ printf("mci_read_persistent: fp=%x, mci=", fp);
+ mci_dump(mci, FALSE);
+ }
+
+ mci->mci_status = NULL;
+ if (mci->mci_rstatus != NULL)
+ free(mci->mci_rstatus);
+ mci->mci_rstatus = NULL;
+
+ rewind(fp);
+ while (fgets(buf, sizeof buf, fp) != NULL)
+ {
+ 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:
+ syserr("Unknown host status line \"%s\"", buf);
+ 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 saveErrno = errno;
+
+ if (mci == NULL)
+ {
+ if (tTd(56, 1))
+ printf("mci_store_persistent: NULL mci\n");
+ return;
+ }
+
+ if (HostStatDir == NULL || mci->mci_host == NULL)
+ return;
+
+ if (tTd(56, 1))
+ printf("mci_store_persistent: Storing information for %s\n",
+ mci->mci_host);
+
+ if (mci->mci_statfile == NULL)
+ {
+ if (tTd(56, 1))
+ printf("mci_store_persistent: no statfile\n");
+ return;
+ }
+
+ rewind(mci->mci_statfile);
+#if !NOFTRUNCATE
+ (void) ftruncate(fileno(mci->mci_statfile), (off_t) 0);
+#endif
+
+ 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", mci->mci_lastuse);
+ fprintf(mci->mci_statfile, ".\n");
+
+ fflush(mci->mci_statfile);
+
+cleanup:
+ errno = saveErrno;
+ 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 = 0;
+
+ if (pathname == NULL)
+ pathname = HostStatDir;
+ if (pathname == NULL)
+ return -1;
+
+ if (tTd(56, 1))
+ printf("mci_traverse: pathname is %s\n", pathname);
+
+ ret = stat(pathname, &statbuf);
+ if (ret < 0)
+ {
+ if (tTd(56, 2))
+ printf("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];
+
+ if ((d = opendir(pathname)) == NULL)
+ {
+ if (tTd(56, 2))
+ printf("mci_traverse: opendir %s: %s\n",
+ pathname, errstring(errno));
+ return -1;
+ }
+
+ if (strlen(pathname) >= sizeof newpath - MAXNAMLEN - 3)
+ {
+ if (tTd(56, 2))
+ printf("mci_traverse: path \"%s\" too long",
+ pathname);
+ return -1;
+ }
+ strcpy(newpath, pathname);
+ newptr = newpath + strlen(newpath);
+ *newptr++ = '/';
+
+ while ((e = readdir(d)) != NULL)
+ {
+ if (e->d_name[0] == '.')
+ continue;
+
+ strncpy(newptr, e->d_name,
+ sizeof newpath - (newptr - newpath) - 1);
+ newpath[sizeof newpath - 1] = '\0';
+
+ ret = mci_traverse_persistent(action, newpath);
+ if (ret < 0)
+ break;
+
+ /*
+ ** The following appears to be
+ ** necessary during purgest, since
+ ** we modify the directory structure
+ */
+
+ if (action == mci_purge_persistent)
+ rewinddir(d);
+ }
+ 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 persisten 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 status;
+ int width = Verbose ? 78 : 25;
+ bool locked;
+ char *p;
+ MCI mcib;
+
+ if (!initflag)
+ {
+ initflag = TRUE;
+ printf(" -------------- Hostname --------------- How long ago ---------Results---------\n");
+ }
+
+ fp = fopen(pathname, "r+");
+
+ if (fp == NULL)
+ {
+ if (tTd(56, 1))
+ printf("mci_print_persistent: cannot open %s: %s\n",
+ pathname, errstring(errno));
+ return 0;
+ }
+
+ bzero(&mcib, sizeof mcib);
+ if (mci_read_persistent(fp, &mcib) < 0)
+ {
+ syserr("%s: could not read status file", pathname);
+ fclose(fp);
+ return 0;
+ }
+
+ locked = !lockfile(fileno(fp), pathname, "", LOCK_EX|LOCK_NB);
+ fclose(fp);
+
+ 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.
+**
+** Returns:
+** 0
+*/
+
+int
+mci_purge_persistent(pathname, hostname)
+ char *pathname;
+ char *hostname;
+{
+ char *end = pathname + strlen(pathname) - 1;
+
+ if (tTd(56, 1))
+ printf("mci_purge_persistent: purging %s\n", pathname);
+
+ /* remove the file */
+ if (unlink(pathname) < 0)
+ {
+ if (tTd(56, 2))
+ printf("mci_purge_persistent: failed to unlink %s: %s\n",
+ pathname, errstring(errno));
+ return -1;
+ }
+
+ /*
+ ** remove empty parent directories.
+ */
+
+ for (;;)
+ {
+ while (*end != '/')
+ end--;
+ *(end--) = '\0';
+
+ if (*end != '.')
+ break;
+
+ if (tTd(56, 1))
+ printf("mci_purge_persistent: dpurge %s\n", pathname);
+
+ if (rmdir(pathname) < 0)
+ {
+ if (errno == ENOENT || errno == EEXIST)
+ break; /* directory is not empty */
+#ifdef ENOTEMTPY
+ if (errno == ENOTEMPTY)
+ break; /* BSDism */
+#endif
+ if (tTd(56, 2))
+ printf("mci_purge_persistent: rmdir %s: %s\n",
+ pathname, errstring(errno));
+ break;
+ }
+
+ }
+
+ 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
+*/
+
+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];
+
+ /*
+ ** Rationality check the arguments.
+ */
+
+ if (host == NULL)
+ syserr("mci_generate_persistent_path: null host");
+ if (path == NULL)
+ syserr("mci_generate_persistent_path: null path");
+
+ if (tTd(56, 80))
+ printf("mci_generate_persistent_path(%s): ", host);
+
+ /* make certain this is not a bracketed host number */
+ if (strlen(host) > sizeof t_host - 1)
+ return -1;
+ if (host[0] == '[')
+ strcpy(t_host, host + 1);
+ else
+ strcpy(t_host, 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] == '.' || elem[-1] == ']'))
+ *--elem = '\0';
+
+ /* check for what will be the final length of the path */
+ len = strlen(HostStatDir) + 2;
+ for (p = (char *) host; *p != '\0'; p++)
+ {
+ if (*p == '|' || *p != '.')
+ len++;
+ len++;
+ }
+ if (len > pathlen)
+ return -1;
+
+ strcpy(path, HostStatDir);
+ 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 (isupper(ch))
+ ch = tolower(ch);
+ if (ch == '|')
+ *p++ = '|'; /* | -> || */
+ else if (ch == '/')
+ ch = '|'; /* / -> | */
+ *p++ = ch;
+ }
+ if (elem >= t_host)
+ *p++ = '.';
+ *p = '\0';
+ }
+
+ if (tTd(56, 80))
+ {
+ if (ret < 0)
+ printf("FAILURE %d\n", ret);
+ else
+ printf("SUCCESS %s\n", path);
+ }
+
+ return (ret);
+}
diff --git a/usr.sbin/sendmail/src/mime.c b/usr.sbin/sendmail/src/mime.c
index 1c71a84ac6bb..9ee726adb112 100644
--- a/usr.sbin/sendmail/src/mime.c
+++ b/usr.sbin/sendmail/src/mime.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994 Eric P. Allman
+ * Copyright (c) 1994, 1996 Eric P. Allman
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
@@ -36,7 +36,7 @@
# include <string.h>
#ifndef lint
-static char sccsid[] = "@(#)mime.c 8.30.1.1 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)mime.c 8.49 (Berkeley) 10/30/96";
#endif /* not lint */
/*
@@ -72,6 +72,10 @@ static char *MimeBoundaryNames[] =
{
"SYNTAX", "NOTSEP", "INTERMED", "FINAL"
};
+
+bool MapNLtoCRLF;
+
+extern int mimeboundary __P((char *, char **));
/*
** MIME8TO7 -- output 8 bit body in 7 bit format
**
@@ -125,11 +129,14 @@ mime8to7(mci, header, e, boundaries, flags)
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];
+ extern int mime_getchar __P((FILE *, char **, int *));
+ extern int mime_getchar_crlf __P((FILE *, char **, int *));
if (tTd(43, 1))
{
@@ -143,6 +150,7 @@ mime8to7(mci, header, e, boundaries, flags)
}
printf("\n");
}
+ MapNLtoCRLF = TRUE;
p = hvalue("Content-Transfer-Encoding", header);
if (p == NULL ||
(pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL,
@@ -226,6 +234,13 @@ mime8to7(mci, header, e, boundaries, flags)
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
+ if (wordinclass(buf, 'q') || wordinclass(type, 'q'))
+ use_qp = TRUE;
+
/*
** Multipart requires special processing.
**
@@ -246,8 +261,12 @@ mime8to7(mci, header, e, boundaries, flags)
}
if (i >= argc)
{
- syserr("mime8to7: Content-Type: %s missing boundary", p);
+ syserr("mime8to7: Content-Type: \"%s\": missing boundary",
+ p);
p = "---";
+
+ /* avoid bounce loops */
+ e->e_flags |= EF_DONT_MIME;
}
else
{
@@ -260,6 +279,9 @@ mime8to7(mci, header, e, boundaries, flags)
syserr("mime8to7: multipart boundary \"%s\" too long",
p);
blen = sizeof bbuf - 1;
+
+ /* avoid bounce loops */
+ e->e_flags |= EF_DONT_MIME;
}
strncpy(bbuf, p, blen);
bbuf[blen] = '\0';
@@ -269,7 +291,12 @@ mime8to7(mci, header, e, boundaries, flags)
if (boundaries[i] == NULL)
break;
if (i >= MAXMIMENESTING)
+ {
syserr("mime8to7: multipart nesting boundary too deep");
+
+ /* avoid bounce loops */
+ e->e_flags |= EF_DONT_MIME;
+ }
else
{
boundaries[i] = bbuf;
@@ -332,7 +359,7 @@ mime8to7(mci, header, e, boundaries, flags)
}
/*
- ** Message/* types -- recurse exactly once.
+ ** Message/xxx types -- recurse exactly once.
**
** Class 's' is predefined to have "rfc822" only.
*/
@@ -422,9 +449,11 @@ mime8to7(mci, header, e, boundaries, flags)
if (tTd(43, 8))
{
- printf("mime8to7: %ld high bit(s) in %ld byte(s), cte=%s\n",
+ printf("mime8to7: %ld high bit(s) in %ld byte(s), cte=%s, type=%s/%s\n",
sectionhighbits, sectionsize,
- cte == NULL ? "[none]" : cte);
+ cte == NULL ? "[none]" : cte,
+ type == NULL ? "[none]" : type,
+ subtype == NULL ? "[none]" : subtype);
}
if (cte != NULL && strcasecmp(cte, "binary") == 0)
sectionsize = sectionhighbits;
@@ -453,14 +482,19 @@ mime8to7(mci, header, e, boundaries, flags)
if (feof(e->e_dfp))
bt = MBT_FINAL;
}
- else if (sectionsize / 8 < sectionhighbits)
+ else if (!MapNLtoCRLF ||
+ (sectionsize / 8 < sectionhighbits && !use_qp))
{
/* use base64 encoding */
int c1, c2;
- putline("Content-Transfer-Encoding: base64", mci);
if (tTd(43, 36))
printf(" ...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)
@@ -519,9 +553,13 @@ mime8to7(mci, header, e, boundaries, flags)
for (p = "!\"#$@[\\]^`{|}~"; *p != '\0'; p++)
setbitn(*p, badchars);
- putline("Content-Transfer-Encoding: quoted-printable", mci);
if (tTd(43, 36))
printf(" ...Content-Transfer-Encoding: quoted-printable\n");
+ putline("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;
@@ -693,7 +731,7 @@ mime_getchar(fp, boundaries, btp)
*bp++ = c;
}
*bp = '\0';
- bt = mimeboundary(&buf[1], boundaries);
+ bt = mimeboundary((char *) &buf[1], boundaries);
switch (bt)
{
case MBT_FINAL:
@@ -746,7 +784,7 @@ mime_getchar_crlf(fp, boundaries, btp)
return '\n';
}
c = mime_getchar(fp, boundaries, btp);
- if (c == '\n')
+ if (c == '\n' && MapNLtoCRLF)
{
sendlf = TRUE;
return '\r';
@@ -776,6 +814,7 @@ mimeboundary(line, boundaries)
int type = MBT_NOTSEP;
int i;
int savec;
+ extern int isboundary __P((char *, char **));
if (line[0] != '-' || line[1] != '-' || boundaries == NULL)
return MBT_NOTSEP;
@@ -864,4 +903,282 @@ isboundary(line, boundaries)
return -1;
}
-#endif /* MIME */
+#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 <marius@rhi.hi.is>.
+**
+** Parameters:
+** mci -- mailer connection information.
+** header -- the header for this body part.
+** e -- envelope.
+**
+** Returns:
+** none.
+*/
+
+extern int mime_fromqp __P((u_char *, u_char **, int, int));
+
+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 *obp;
+ u_char ch, *fbufp, *obufp;
+ char buf[MAXLINE];
+ u_char obuf[MAXLINE + 1];
+ 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 ? "<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);
+
+ 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 nchar = 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' || fbuf >= &fbuf[MAXLINE])
+ {
+ if (*--fbufp != '\n' || *--fbufp != '\r')
+ fbufp++;
+ *fbufp = '\0';
+ putline((char *) fbuf, mci);
+ fbufp = fbuf;
+ }
+ if (c3 == '=')
+ continue;
+ c3 = CHAR64(c3);
+ *fbufp = ((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2);
+ if (*fbufp++ == '\n' || fbuf >= &fbuf[MAXLINE])
+ {
+ if (*--fbufp != '\n' || *--fbufp != '\r')
+ fbufp++;
+ *fbufp = '\0';
+ putline((char *) fbuf, mci);
+ fbufp = fbuf;
+ }
+ if (c4 == '=')
+ continue;
+ c4 = CHAR64(c4);
+ *fbufp = ((c3 & 0x03) << 6) | c4;
+ if (*fbufp++ == '\n' || fbuf >= &fbuf[MAXLINE])
+ {
+ if (*--fbufp != '\n' || *--fbufp != '\r')
+ fbufp++;
+ *fbufp = '\0';
+ putline((char *) fbuf, mci);
+ fbufp = fbuf;
+ }
+ }
+
+ /* force out partial last line */
+ if (fbufp > fbuf)
+ {
+ *fbufp = '\0';
+ putline((char *) fbuf, mci);
+ }
+ }
+ else
+ {
+ /* quoted-printable */
+ obp = obuf;
+ while (fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ {
+ if (mime_fromqp((u_char *) buf, &obp, 0, &obuf[MAXLINE] - obp) == 0)
+ continue;
+
+ putline((char *) obuf, mci);
+ obp = obuf;
+ }
+ }
+ if (tTd(43, 3))
+ printf("\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)])
+
+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') /* ignore it */
+ {
+ if (state == 0)
+ return 0;
+ }
+ else
+ {
+ if ((c2 = *infile++) == '\0')
+ break;
+
+ c1 = HEXCHAR(c1);
+ c2 = HEXCHAR(c2);
+
+ if (++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/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c
index 7507b8371be4..3b466f9ba709 100644
--- a/usr.sbin/sendmail/src/parseaddr.c
+++ b/usr.sbin/sendmail/src/parseaddr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)parseaddr.c 8.87.1.1 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)parseaddr.c 8.114 (Berkeley) 9/20/96";
#endif /* not lint */
# include "sendmail.h"
@@ -169,7 +169,7 @@ parseaddr(addr, a, flags, delim, delimptr, e)
** If there was a parsing failure, mark it for queueing.
*/
- if (queueup)
+ if (queueup && OpMode != MD_INITALIAS)
{
char *msg = "Transient parse error -- message queued for future delivery";
@@ -220,14 +220,6 @@ invalidaddr(addr, delimptr)
if (savedelim != '\0')
*delimptr = '\0';
}
-#if 0
- /* for testing.... */
- if (strcmp(addr, "INvalidADDR") == 0)
- {
- usrerr("553 INvalid ADDRess");
- goto addrfailure;
- }
-#endif
for (; *addr != '\0'; addr++)
{
if ((*addr & 0340) == 0200)
@@ -241,7 +233,6 @@ invalidaddr(addr, delimptr)
}
setstat(EX_USAGE);
usrerr("553 Address contained invalid control characters");
- addrfailure:
if (delimptr != NULL && savedelim != '\0')
*delimptr = savedelim;
return TRUE;
@@ -343,12 +334,12 @@ allocaddr(a, flags, paddr)
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,
+ /*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 */
@@ -444,6 +435,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
register int c;
char **avp;
bool bslashmode;
+ bool route_syntax;
int cmntcnt;
int anglecnt;
char *tok;
@@ -483,6 +475,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
q = pvpbuf;
bslashmode = FALSE;
+ route_syntax = FALSE;
cmntcnt = 0;
anglecnt = 0;
avp = av;
@@ -510,7 +503,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (q >= &pvpbuf[pvpbsize - 5])
{
usrerr("553 Address too long");
- if (strlen(addr) > MAXNAME)
+ if (strlen(addr) > (SIZE_T) MAXNAME)
addr[MAXNAME] = '\0';
returnnull:
if (delimptr != NULL)
@@ -548,9 +541,19 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
p--;
}
- else if (c == delim && anglecnt <= 0 &&
- cmntcnt <= 0 && state != QST)
- break;
+ 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))
printf("c=%c, s=%d; ", c, state);
@@ -600,7 +603,15 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
else if (cmntcnt > 0)
c = NOCHAR;
else if (c == '<')
+ {
+ char *q = p;
+
anglecnt++;
+ while (isascii(*q) && isspace(*q))
+ q++;
+ if (*q == '@')
+ route_syntax = TRUE;
+ }
else if (c == '>')
{
if (anglecnt <= 0)
@@ -610,6 +621,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
}
else
anglecnt--;
+ route_syntax = FALSE;
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
@@ -743,10 +755,11 @@ rewrite(pvp, ruleset, reclevel, e)
int loopcount;
struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
+ extern int callsubr __P((char**, int, ENVELOPE *));
if (OpMode == MD_TEST || tTd(21, 1))
{
- printf("rewrite: ruleset %2d input:", ruleset);
+ printf("rewrite: ruleset %3d input:", ruleset);
printav(pvp);
}
if (ruleset < 0 || ruleset >= MAXRWSETS)
@@ -772,6 +785,12 @@ rewrite(pvp, ruleset, reclevel, e)
loopcount = 0;
for (rwr = RewriteRules[ruleset]; rwr != NULL; )
{
+ int stat;
+
+ /* if already canonical, quit now */
+ if (pvp[0] != NULL && (pvp[0][0] & 0377) == CANONNET)
+ break;
+
if (tTd(21, 12))
{
printf("-----trying rule:");
@@ -1002,8 +1021,6 @@ rewrite(pvp, ruleset, reclevel, e)
rvp++;
rwr = NULL;
}
- else if ((*rp & 0377) == CANONNET)
- rwr = NULL;
/* substitute */
for (avp = npvp; *rvp != NULL; rvp++)
@@ -1091,6 +1108,7 @@ rewrite(pvp, ruleset, reclevel, e)
char *argvect[10];
char pvpbuf[PSBUFSIZE];
char *nullpvp[1];
+ extern char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *));
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
@@ -1173,55 +1191,7 @@ rewrite(pvp, ruleset, reclevel, e)
/* look it up */
cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
argvect[0] = buf;
- if (e->e_sendmode == SM_DEFER)
- {
- /* don't do any map lookups */
- if (tTd(60, 1))
- printf("map_lookup(%s, %s) => DEFERRED\n",
- mapname, buf);
- replac = NULL;
- rstat = EX_TEMPFAIL;
- }
- else if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
- {
- auto int stat = EX_OK;
-
- if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
- stripquotes(buf);
-
- /* XXX should try to auto-open the map here */
-
- if (tTd(60, 1))
- printf("map_lookup(%s, %s) => ",
- mapname, buf);
- replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
- buf, argvect, &stat);
- if (tTd(60, 1))
- printf("%s (%d)\n",
- replac ? replac : "NOT FOUND",
- stat);
-
- /* should recover if stat == EX_TEMPFAIL */
- if (stat == EX_TEMPFAIL)
- {
- rstat = EX_TEMPFAIL;
- if (tTd(60, 1))
- printf("map_lookup(%s, %s) tempfail: errno=%d\n",
- mapname, buf, errno);
- if (e->e_message == NULL)
- {
- char mbuf[300];
-
- snprintf(mbuf, sizeof mbuf,
- "%.80s map: lookup (%s): deferred",
- mapname,
- shortenstring(buf, 203));
- e->e_message = newstr(mbuf);
- }
- }
- }
- else
- replac = NULL;
+ replac = map_lookup(map, buf, argvect, &rstat, e);
/* if no replacement, use default */
if (replac == NULL && default_rvp != NULL)
@@ -1273,38 +1243,16 @@ rewrite(pvp, ruleset, reclevel, e)
** Check for subroutine calls.
*/
- if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
- {
- int stat;
+ stat = callsubr(npvp, reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
- if (npvp[1] == NULL)
- {
- syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
- ruleset, ruleno);
- *pvp = NULL;
- }
- else
- {
- int ruleset;
- STAB *s;
-
- bcopy((char *) &npvp[2], (char *) pvp,
- (int) (avp - npvp - 2) * sizeof *avp);
- if (tTd(21, 3))
- printf("-----callsubr %s\n", npvp[1]);
- ruleset = strtorwset(npvp[1], NULL, ST_FIND);
- stat = rewrite(pvp, ruleset, reclevel, e);
- if (rstat == EX_OK || stat == EX_TEMPFAIL)
- rstat = stat;
- if (*pvp != NULL && (**pvp & 0377) == CANONNET)
- rwr = NULL;
- }
- }
- else
- {
- bcopy((char *) npvp, (char *) pvp,
- (int) (avp - npvp) * sizeof *avp);
- }
+ /* copy vector back into original space. */
+ for (avp = npvp; *avp++ != NULL;)
+ continue;
+ bcopy((char *) npvp, (char *) pvp,
+ (int) (avp - npvp) * sizeof *avp);
+
if (tTd(21, 4))
{
printf("rewritten as:");
@@ -1314,13 +1262,192 @@ rewrite(pvp, ruleset, reclevel, e)
if (OpMode == MD_TEST || tTd(21, 1))
{
- printf("rewrite: ruleset %2d returns:", ruleset);
+ printf("rewrite: ruleset %3d returns:", ruleset);
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.
+*/
+
+int
+callsubr(pvp, reclevel, e)
+ char **pvp;
+ int reclevel;
+ ENVELOPE *e;
+{
+ char **avp;
+ char **rvp;
+ register int i;
+ int subr;
+ int stat;
+ int rstat = EX_OK;
+ char *tpvp[MAXATOM + 1];
+
+ for (avp = pvp; *avp != NULL; avp++)
+ {
+ if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
+ {
+ subr = strtorwset(avp[1], NULL, ST_FIND);
+ if (subr < 0)
+ {
+ syserr("Unknown ruleset %s", avp[1]);
+ return EX_CONFIG;
+ }
+
+ if (tTd(21, 3))
+ printf("-----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;
+
+ stat = callsubr(tpvp, reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
+
+ /*
+ ** 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.
+ */
+
+ stat = rewrite(tpvp, subr, reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
+
+ /*
+ ** 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 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.
+*/
+
+char *
+map_lookup(map, key, argvect, pstat, e)
+ STAB *map;
+ char key[];
+ char **argvect;
+ int *pstat;
+ ENVELOPE *e;
+{
+ auto int stat = EX_OK;
+ char *replac;
+
+ if (e->e_sendmode == SM_DEFER)
+ {
+ /* don't do any map lookups */
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) => DEFERRED\n",
+ map->s_name, key);
+ *pstat = EX_TEMPFAIL;
+ return NULL;
+ }
+ if (map == NULL || !bitset(MF_OPEN, map->s_map.map_mflags))
+ return NULL;
+
+ if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
+ stripquotes(key);
+
+ /* XXX should try to auto-open the map here */
+
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) => ",
+ map->s_name, key);
+ replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
+ key, argvect, &stat);
+ if (tTd(60, 1))
+ printf("%s (%d)\n",
+ replac != NULL ? replac : "NOT FOUND",
+ stat);
+
+ /* should recover if stat == EX_TEMPFAIL */
+ if (stat == EX_TEMPFAIL && !bitset(MF_NODEFER, map->s_map.map_mflags))
+ {
+ *pstat = EX_TEMPFAIL;
+ if (tTd(60, 1))
+ printf("map_lookup(%s, %s) tempfail: errno=%d\n",
+ map->s_name, key, errno);
+ if (e->e_message == NULL)
+ {
+ char mbuf[300];
+
+ snprintf(mbuf, sizeof mbuf,
+ "%.80s map: lookup (%s): deferred",
+ map->s_name,
+ shortenstring(key, 203));
+ e->e_message = newstr(mbuf);
+ }
+ }
+ return replac;
+}
+ /*
** BUILDADDR -- build address from token vector.
**
** Parameters:
@@ -1345,17 +1472,17 @@ struct errcodes
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,
+ { "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,
+ { "config", EX_CONFIG },
#endif
- NULL, EX_UNAVAILABLE,
+ { NULL, EX_UNAVAILABLE }
};
ADDRESS *
@@ -1386,7 +1513,7 @@ buildaddr(tv, a, flags, e)
bzero((char *) a, sizeof *a);
/* set up default error return flags */
- a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
+ a->q_flags |= DefaultNotify;
/* figure out what net/mailer to use */
if (*tv == NULL || (**tv & 0377) != CANONNET)
@@ -1407,7 +1534,7 @@ badaddr:
mname = *++tv;
/* extract host and user portions */
- if ((**++tv & 0377) == CANONHOST)
+ if (*++tv != NULL && (**tv & 0377) == CANONHOST)
hostp = ++tv;
else
hostp = NULL;
@@ -1433,6 +1560,8 @@ badaddr:
if (strchr(hbuf, '.') != NULL)
{
+ extern int dsntoexitstat __P((char *));
+
a->q_status = newstr(hbuf);
setstat(dsntoexitstat(hbuf));
}
@@ -1703,27 +1832,27 @@ struct qflags
struct qflags AddressFlags[] =
{
- "QDONTSEND", QDONTSEND,
- "QBADADDR", QBADADDR,
- "QGOODUID", QGOODUID,
- "QPRIMARY", QPRIMARY,
- "QQUEUEUP", QQUEUEUP,
- "QSENT", QSENT,
- "QNOTREMOTE", QNOTREMOTE,
- "QSELFREF", QSELFREF,
- "QVERIFIED", QVERIFIED,
- "QBOGUSSHELL", QBOGUSSHELL,
- "QUNSAFEADDR", QUNSAFEADDR,
- "QPINGONSUCCESS", QPINGONSUCCESS,
- "QPINGONFAILURE", QPINGONFAILURE,
- "QPINGONDELAY", QPINGONDELAY,
- "QHASNOTIFY", QHASNOTIFY,
- "QRELAYED", QRELAYED,
- "QEXPANDED", QEXPANDED,
- "QDELIVERED", QDELIVERED,
- "QDELAYED", QDELAYED,
- "QTHISPASS", QTHISPASS,
- NULL
+ { "QDONTSEND", QDONTSEND },
+ { "QBADADDR", QBADADDR },
+ { "QGOODUID", QGOODUID },
+ { "QPRIMARY", QPRIMARY },
+ { "QQUEUEUP", QQUEUEUP },
+ { "QSENT", QSENT },
+ { "QNOTREMOTE", QNOTREMOTE },
+ { "QSELFREF", QSELFREF },
+ { "QVERIFIED", QVERIFIED },
+ { "QBOGUSSHELL", QBOGUSSHELL },
+ { "QUNSAFEADDR", QUNSAFEADDR },
+ { "QPINGONSUCCESS", QPINGONSUCCESS },
+ { "QPINGONFAILURE", QPINGONFAILURE },
+ { "QPINGONDELAY", QPINGONDELAY },
+ { "QHASNOTIFY", QHASNOTIFY },
+ { "QRELAYED", QRELAYED },
+ { "QEXPANDED", QEXPANDED },
+ { "QDELIVERED", QDELIVERED },
+ { "QDELAYED", QDELAYED },
+ { "QTHISPASS", QTHISPASS },
+ { NULL }
};
void
@@ -1781,10 +1910,14 @@ printaddr(a, follow)
a->q_owner == NULL ? "(none)" : a->q_owner,
a->q_home == NULL ? "(none)" : a->q_home,
a->q_fullname == NULL ? "(none)" : a->q_fullname);
- printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n",
+ 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, ctime(&a->q_statdate));
if (!follow)
return;
@@ -1993,7 +2126,12 @@ maplocaluser(a, sendq, aliaslevel, e)
if (pvp == NULL)
return;
- (void) rewrite(pvp, 5, 0, e);
+ if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL)
+ {
+ a->q_flags |= QQUEUEUP;
+ a->q_status = "4.4.3";
+ return;
+ }
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
return;
@@ -2154,5 +2292,111 @@ dequote_map(map, name, av, statp)
quotemode || quotecnt <= 0 || spacecnt != 0)
return NULL;
*q++ = '\0';
- return name;
+ 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.
+**
+** Returns:
+** EX_OK -- if the rwset doesn't resolve to $#error
+** else -- the failure status (message printed)
+*/
+
+int
+rscheck(rwset, p1, p2, e)
+ char *rwset;
+ char *p1;
+ char *p2;
+ ENVELOPE *e;
+{
+ char *buf;
+ int bufsize;
+ int saveexitstat;
+ int rstat;
+ char **pvp;
+ int rsno;
+ auto ADDRESS a1;
+ bool saveQuickAbort = QuickAbort;
+ char buf0[MAXLINE];
+ char pvpbuf[PSBUFSIZE];
+ extern char MsgBuf[];
+
+ if (tTd(48, 2))
+ printf("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);
+ }
+ pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
+ if (pvp == NULL)
+ {
+ 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)
+ return EX_OK;
+
+ /* got an error -- process it */
+ saveexitstat = ExitStat;
+ QuickAbort = FALSE;
+ (void) buildaddr(pvp, &a1, 0, e);
+ QuickAbort = saveQuickAbort;
+ rstat = ExitStat;
+ ExitStat = saveexitstat;
+
+#ifdef LOG
+ if (LogLevel >= 4)
+ {
+ if (p2 == NULL)
+ syslog(LOG_NOTICE, "Ruleset %s (%s) rejection: %s",
+ rwset, p1, MsgBuf);
+ else
+ syslog(LOG_NOTICE, "Ruleset %s (%s, %s) rejection: %s",
+ rwset, p1, p2, MsgBuf);
+ }
+#endif
+
+ if (QuickAbort)
+ longjmp(TopFrame, 2);
+
+ /* clean up */
+ finis:
+ setstat(rstat);
+ if (buf != buf0)
+ free(buf);
+ return rstat;
}
diff --git a/usr.sbin/sendmail/src/queue.c b/usr.sbin/sendmail/src/queue.c
index eb5176eade91..299a0167ef9c 100644
--- a/usr.sbin/sendmail/src/queue.c
+++ b/usr.sbin/sendmail/src/queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef QUEUE
-static char sccsid[] = "@(#)queue.c 8.98.1.3 (Berkeley) 9/16/96 (with queueing)";
+static char sccsid[] = "@(#)queue.c 8.131 (Berkeley) 11/8/96 (with queueing)";
#else
-static char sccsid[] = "@(#)queue.c 8.98.1.3 (Berkeley) 9/16/96 (without queueing)";
+static char sccsid[] = "@(#)queue.c 8.131 (Berkeley) 11/8/96 (without queueing)";
#endif
#endif /* not lint */
@@ -71,6 +71,8 @@ WORK *WorkQ; /* queue of things to be done */
#if !defined(NGROUPS_MAX) && defined(NGROUPS)
# define NGROUPS_MAX NGROUPS /* POSIX naming convention */
#endif
+
+extern int orderq __P((bool));
/*
** QUEUEUP -- queue a message up for future transmission.
**
@@ -261,6 +263,12 @@ queueup(e, announce)
*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);
@@ -288,38 +296,45 @@ queueup(e, announce)
printctladdr(NULL, NULL);
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
- if (bitset(QQUEUEUP, q->q_flags) ||
- !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
+ if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
{
- printctladdr(q, tfp);
- if (q->q_orcpt != NULL)
- fprintf(tfp, "Q%s\n",
- denlstring(q->q_orcpt, TRUE, FALSE));
- putc('R', tfp);
- if (bitset(QPRIMARY, q->q_flags))
- putc('P', tfp);
- if (bitset(QPINGONSUCCESS, q->q_flags))
- putc('S', tfp);
- if (bitset(QPINGONFAILURE, q->q_flags))
- putc('F', tfp);
- if (bitset(QPINGONDELAY, q->q_flags))
- putc('D', tfp);
- putc(':', tfp);
- fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
- if (announce)
- {
- e->e_to = q->q_paddr;
- message("queued");
- if (LogLevel > 8)
- logdelivery(q->q_mailer, NULL, "queued",
- NULL, (time_t) 0, e);
- e->e_to = NULL;
- }
- if (tTd(40, 1))
- {
- printf("queueing ");
- printaddr(q, FALSE);
- }
+#if XDEBUG
+ if (bitset(QQUEUEUP, q->q_flags))
+ syslog(LOG_DEBUG, "%s: q_flags = %x",
+ e->e_id, q->q_flags);
+#endif
+ continue;
+ }
+ printctladdr(q, tfp);
+ if (q->q_orcpt != NULL)
+ fprintf(tfp, "Q%s\n",
+ denlstring(q->q_orcpt, TRUE, FALSE));
+ putc('R', tfp);
+ if (bitset(QPRIMARY, q->q_flags))
+ putc('P', tfp);
+ if (bitset(QHASNOTIFY, q->q_flags))
+ putc('N', tfp);
+ if (bitset(QPINGONSUCCESS, q->q_flags))
+ putc('S', tfp);
+ if (bitset(QPINGONFAILURE, q->q_flags))
+ putc('F', tfp);
+ if (bitset(QPINGONDELAY, q->q_flags))
+ putc('D', tfp);
+ putc(':', tfp);
+ fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
+ if (announce)
+ {
+ e->e_to = q->q_paddr;
+ message("queued");
+ if (LogLevel > 8)
+ logdelivery(q->q_mailer, NULL, "queued",
+ NULL, (time_t) 0, e);
+ e->e_to = NULL;
+ }
+ if (tTd(40, 1))
+ {
+ printf("queueing ");
+ printaddr(q, FALSE);
}
}
@@ -534,6 +549,7 @@ runqueue(forkflag)
int njobs;
int sequenceno = 0;
extern ENVELOPE BlankEnvelope;
+ extern void clrdaemon __P((void));
/*
** If no work will ever be selected, don't even bother reading
@@ -563,7 +579,7 @@ runqueue(forkflag)
if (forkflag)
{
- int pid;
+ pid_t pid;
extern void intsig();
#ifdef SIGCHLD
extern void reapchild();
@@ -578,7 +594,7 @@ runqueue(forkflag)
#ifndef SIGCHLD
(void) waitfor(pid);
#else
- CurChildren++;
+ proc_list_add(pid);
#endif /* SIGCHLD */
if (QueueIntvl != 0)
(void) setevent(QueueIntvl, runqueue, TRUE);
@@ -592,6 +608,7 @@ runqueue(forkflag)
(void) setsignal(SIGCHLD, SIG_DFL);
#endif /* SIGCHLD */
(void) setsignal(SIGHUP, intsig);
+ Verbose = FALSE;
}
setproctitle("running queue: %s", QueueDir);
@@ -613,6 +630,15 @@ runqueue(forkflag)
/* force it to run expensive jobs */
NoConnect = FALSE;
+ /* drop privileges */
+ if (geteuid() == (uid_t) 0)
+ {
+ if (RunAsGid != (gid_t) 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != (uid_t) 0)
+ (void) setuid(RunAsUid);
+ }
+
/*
** Create ourselves an envelope
*/
@@ -628,6 +654,15 @@ runqueue(forkflag)
initmaps(FALSE, e);
/*
+ ** If we are running part of the queue, always ignore stored
+ ** host status.
+ */
+
+ if (QueueLimitId != NULL || QueueLimitSender != NULL ||
+ QueueLimitRecipient != NULL)
+ HostStatDir = NULL;
+
+ /*
** Start making passes through the queue.
** First, read and sort the entire queue.
** Then, process the work in that order.
@@ -643,6 +678,7 @@ runqueue(forkflag)
WORK *w = WorkQ;
WorkQ = WorkQ->w_next;
+ e->e_to = NULL;
/*
** Ignore jobs that are too expensive for the moment.
@@ -652,8 +688,11 @@ runqueue(forkflag)
if (shouldqueue(w->w_pri, w->w_ctime))
{
if (Verbose)
- printf("\nSkipping %s (sequence %d of %d)\n",
+ {
+ message("");
+ message("Skipping %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
+ }
}
else
{
@@ -661,8 +700,11 @@ runqueue(forkflag)
extern pid_t dowork();
if (Verbose)
- printf("\nRunning %s (sequence %d of %d)\n",
+ {
+ message("");
+ message("Running %s (sequence %d of %d)",
w->w_name + 2, sequenceno, njobs);
+ }
pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
errno = 0;
if (pid != 0)
@@ -850,10 +892,15 @@ orderq(doall)
i |= NEED_R;
while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
{
+ int qfver = 0;
extern bool strcontainedin();
switch (lbuf[0])
{
+ case 'V':
+ qfver = atoi(&lbuf[1]);
+ break;
+
case 'P':
w->w_pri = atol(&lbuf[1]);
i &= ~NEED_P;
@@ -868,8 +915,20 @@ orderq(doall)
if (w->w_host == NULL &&
(p = strrchr(&lbuf[1], '@')) != NULL)
w->w_host = newstr(&p[1]);
- if (QueueLimitRecipient == NULL ||
- strcontainedin(QueueLimitRecipient, &lbuf[1]))
+ if (QueueLimitRecipient == NULL)
+ {
+ i &= ~NEED_R;
+ break;
+ }
+ if (qfver > 0)
+ {
+ p = strchr(&lbuf[1], ':');
+ if (p == NULL)
+ p = &lbuf[1];
+ }
+ else
+ p = &lbuf[1];
+ if (strcontainedin(QueueLimitRecipient, p))
i &= ~NEED_R;
break;
@@ -958,6 +1017,16 @@ orderq(doall)
qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
}
+ else if (QueueSortOrder == QS_BYTIME)
+ {
+ extern workcmpf3();
+
+ /*
+ ** Simple sort based on submission time only.
+ */
+
+ qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
+ }
else
{
extern workcmpf0();
@@ -1165,6 +1234,34 @@ workcmpf2(a, b)
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.
+*/
+
+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;
+}
+ /*
** DOWORK -- do a work request.
**
** Parameters:
@@ -1276,7 +1373,7 @@ dowork(id, forkflag, requeueflag, e)
if (forkflag)
finis();
else
- dropenvelope(e);
+ dropenvelope(e, TRUE);
}
e->e_id = NULL;
return pid;
@@ -1304,13 +1401,13 @@ readqf(e)
struct stat st;
char *bp;
int qfver = 0;
+ long hdrsize = 0;
register char *p;
char *orcpt = NULL;
bool nomore = FALSE;
char qf[20];
char buf[MAXLINE];
extern ADDRESS *setctluser __P((char *, int));
- extern void loseqfile();
/*
** Read and process the file.
@@ -1355,7 +1452,8 @@ readqf(e)
return FALSE;
}
- if (st.st_uid != geteuid() || bitset(S_IWOTH|S_IWGRP, st.st_mode))
+ if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
+ bitset(S_IWOTH|S_IWGRP, st.st_mode))
{
# ifdef LOG
if (LogLevel > 0)
@@ -1374,6 +1472,9 @@ readqf(e)
if (st.st_size == 0)
{
/* must be a bogus file -- just remove it */
+ qf[0] = 'd';
+ (void) unlink(qf);
+ qf[0] = 'q';
(void) unlink(qf);
fclose(qfp);
return FALSE;
@@ -1408,6 +1509,8 @@ readqf(e)
register char *p;
u_long qflags;
ADDRESS *q;
+ int mid;
+ auto char *ep;
if (tTd(40, 4))
printf("+++++ %s\n", bp);
@@ -1448,6 +1551,10 @@ readqf(e)
{
switch (*p)
{
+ case 'N':
+ qflags |= QHASNOTIFY;
+ break;
+
case 'S':
qflags |= QPINGONSUCCESS;
break;
@@ -1472,6 +1579,8 @@ readqf(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);
@@ -1485,6 +1594,7 @@ readqf(e)
case 'H': /* header */
(void) chompheader(&bp[1], FALSE, NULL, e);
+ hdrsize += strlen(&bp[1]);
break;
case 'M': /* message */
@@ -1508,8 +1618,7 @@ readqf(e)
break;
case 'I': /* data file's inode number */
- if (e->e_dfino == -1)
- e->e_dfino = atol(&buf[1]);
+ /* regenerated below */
break;
case 'K': /* time of last deliver attempt */
@@ -1518,6 +1627,26 @@ readqf(e)
case 'N': /* number of delivery attempts */
e->e_ntries = atoi(&buf[1]);
+
+ /* if this has been tried recently, let it be */
+ if (e->e_ntries > 0 &&
+ (curtime() - e->e_dtime) < MinQueueAge)
+ {
+ char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
+ extern void unlockqueue();
+
+ if (Verbose || tTd(40, 8))
+ printf("%s: too young (%s)\n",
+ e->e_id, howlong);
+#ifdef LOG
+ if (LogLevel > 19)
+ syslog(LOG_DEBUG, "%s: too young (%s)",
+ e->e_id, howlong);
+#endif
+ e->e_id = NULL;
+ unlockqueue(e);
+ return FALSE;
+ }
break;
case 'P': /* message priority */
@@ -1548,6 +1677,18 @@ readqf(e)
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;
@@ -1557,7 +1698,8 @@ readqf(e)
break;
case '$': /* define macro */
- define(bp[1], newstr(&bp[2]), e);
+ mid = macid(&bp[1], &ep);
+ define(mid, newstr(ep), e);
break;
case '.': /* terminate file */
@@ -1566,7 +1708,7 @@ readqf(e)
default:
syserr("readqf: %s: line %d: bad line \"%s\"",
- qf, LineNumber, bp);
+ qf, LineNumber, shortenstring(bp, 203));
fclose(qfp);
loseqfile(e, "unrecognized line");
return FALSE;
@@ -1588,25 +1730,6 @@ readqf(e)
return TRUE;
}
- /* if this has been tried recently, let it be */
- if (e->e_ntries > 0 && (curtime() - e->e_dtime) < MinQueueAge)
- {
- char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
- extern void unlockqueue();
-
- if (Verbose || tTd(40, 8))
- printf("%s: too young (%s)\n",
- e->e_id, howlong);
-#ifdef LOG
- if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: too young (%s)",
- e->e_id, howlong);
-#endif
- e->e_id = NULL;
- unlockqueue(e);
- return FALSE;
- }
-
/*
** Arrange to read the data file.
*/
@@ -1622,7 +1745,7 @@ readqf(e)
e->e_flags |= EF_HAS_DF;
if (fstat(fileno(e->e_dfp), &st) >= 0)
{
- e->e_msgsize = st.st_size;
+ e->e_msgsize = st.st_size + hdrsize;
e->e_dfdev = st.st_dev;
e->e_dfino = st.st_ino;
}
@@ -1706,8 +1829,8 @@ printqueue()
CurrentLA = getla(); /* get load average */
printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
- if (nrequests > WorkListSize)
- printf(", only %d printed", WorkListSize);
+ if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
+ printf(", only %d printed", MaxQueueRun);
if (Verbose)
printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
else
@@ -1775,7 +1898,7 @@ printqueue()
case 'S': /* sender name */
if (Verbose)
- printf("%8ld %10ld%c%.12s %.38s",
+ printf("%8ld %10ld%c%.12s %.78s",
dfsize,
w->w_pri,
bitset(EF_WARNING, flags) ? '+' : ' ',
@@ -1788,13 +1911,15 @@ printqueue()
{
printf("\n %10.10s", bodytype);
if (statmsg[0] != '\0')
- printf(" (%.60s)", statmsg);
+ printf(" (%.*s)",
+ Verbose ? 100 : 60,
+ statmsg);
}
break;
case 'C': /* controlling user */
if (Verbose)
- printf("\n\t\t\t\t (---%.34s---)",
+ printf("\n\t\t\t\t (---%.74s---)",
&buf[1]);
break;
@@ -1808,7 +1933,7 @@ printqueue()
p++;
}
if (Verbose)
- printf("\n\t\t\t\t\t %.38s", p);
+ printf("\n\t\t\t\t\t %.78s", p);
else
printf("\n\t\t\t\t %.45s", p);
break;
@@ -1863,7 +1988,7 @@ queuename(e, type)
register ENVELOPE *e;
int type;
{
- static int pid = -1;
+ static pid_t pid = -1;
static char c0;
static char c1;
static char c2;
@@ -1966,7 +2091,8 @@ unlockqueue(e)
ENVELOPE *e;
{
if (tTd(51, 4))
- printf("unlockqueue(%s)\n", e->e_id);
+ printf("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)
@@ -2090,7 +2216,7 @@ loseqfile(e, why)
if (e == NULL || e->e_id == NULL)
return;
- if (strlen(e->e_id) > sizeof buf - 4)
+ if (strlen(e->e_id) > (SIZE_T) sizeof buf - 4)
return;
strcpy(buf, queuename(e, 'q'));
p = queuename(e, 'Q');
diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c
index b41c8ac0535d..9313f0f090f4 100644
--- a/usr.sbin/sendmail/src/readcf.c
+++ b/usr.sbin/sendmail/src/readcf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)readcf.c 8.139 (Berkeley) 11/29/95";
+static char sccsid[] = "@(#)readcf.c 8.176 (Berkeley) 11/10/96";
#endif /* not lint */
# include "sendmail.h"
@@ -112,10 +112,11 @@ readcf(cfname, safe, e)
char exbuf[MAXLINE];
char pvpbuf[MAXLINE + MAXATOM];
static char *null_list[1] = { NULL };
- extern char *munchstring __P((char *, char **));
+ extern char *munchstring __P((char *, char **, int));
extern void fileclass __P((int, char *, char *, bool, bool));
extern void toomany __P((int, int));
extern void translate_dollars __P((char *));
+ extern void inithostmaps __P((void));
FileName = cfname;
LineNumber = 0;
@@ -246,10 +247,6 @@ readcf(cfname, safe, e)
botch = "$?";
break;
- case CONDELSE:
- botch = "$|";
- break;
-
case CONDFI:
botch = "$.";
break;
@@ -354,16 +351,17 @@ readcf(cfname, safe, e)
rwp = RewriteRules[ruleset];
if (rwp != NULL)
{
+ if (OpMode == MD_TEST || tTd(37, 1))
+ printf("WARNING: Ruleset %s has multiple definitions\n",
+ &bp[1]);
while (rwp->r_next != NULL)
rwp = rwp->r_next;
- fprintf(stderr, "WARNING: Ruleset %s redefined\n",
- &bp[1]);
}
break;
case 'D': /* macro definition */
mid = macid(&bp[1], &ep);
- p = munchstring(ep, NULL);
+ p = munchstring(ep, NULL, '\0');
define(mid, newstr(p), e);
break;
@@ -441,6 +439,13 @@ readcf(cfname, safe, e)
break;
#endif
+#ifdef SUN_EXTENSIONS
+ case 'L': /* lookup macro */
+ case 'G': /* lookup class */
+ /* reserved for Sun -- NIS+ database lookup */
+ goto badline;
+#endif
+
case 'M': /* define mailer */
makemailer(&bp[1]);
break;
@@ -499,6 +504,8 @@ readcf(cfname, safe, e)
if (*ep++ == '/')
{
+ extern bool setvendor __P((char *));
+
/* extract vendor code */
for (p = ep; isascii(*p) && isalpha(*p); )
p++;
@@ -708,7 +715,7 @@ fileclass(class, filename, fmt, safe, optional)
{
FILE *f;
int sff;
- int pid;
+ pid_t pid;
register char *p;
char buf[MAXLINE];
@@ -837,13 +844,11 @@ makemailer(line)
auto char *endp;
extern int NextMailer;
extern char **makeargv();
- extern char *munchstring();
+ extern char *munchstring __P((char *, char **, int));
/* allocate a mailer and set up defaults */
m = (struct mailer *) xalloc(sizeof *m);
bzero((char *) m, sizeof *m);
- m->m_eol = "\n";
- m->m_uid = m->m_gid = 0;
/* collect the mailer name */
for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++)
@@ -875,7 +880,7 @@ makemailer(line)
p++;
/* p now points to the field body */
- p = munchstring(p, &delimptr);
+ p = munchstring(p, &delimptr, ',');
/* install the field into the mailer struct */
switch (fcode)
@@ -1019,6 +1024,10 @@ makemailer(line)
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++;
@@ -1089,6 +1098,29 @@ makemailer(line)
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++)
+ {
+ char *p;
+
+ 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)
@@ -1110,15 +1142,17 @@ makemailer(line)
** 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)
+munchstring(p, delimptr, delim)
register char *p;
char **delimptr;
+ int delim;
{
register char *q;
bool backslash = FALSE;
@@ -1157,7 +1191,7 @@ munchstring(p, delimptr)
backslash = TRUE;
else if (*p == '"')
quotemode = !quotemode;
- else if (quotemode || *p != ',')
+ else if (quotemode || *p != delim)
*q++ = *p;
else
break;
@@ -1322,17 +1356,17 @@ struct resolverflags
long rf_bits; /* bits to set/clear */
} ResolverFlags[] =
{
- "debug", RES_DEBUG,
- "aaonly", RES_AAONLY,
- "usevc", RES_USEVC,
- "primary", RES_PRIMARY,
- "igntc", RES_IGNTC,
- "recurse", RES_RECURSE,
- "defnames", RES_DEFNAMES,
- "stayopen", RES_STAYOPEN,
- "dnsrch", RES_DNSRCH,
- "true", 0, /* to avoid error on old syntax */
- NULL, 0
+ { "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
@@ -1344,108 +1378,112 @@ struct optioninfo
bool o_safe; /* safe for random people to use */
} OptionTab[] =
{
- "SevenBitInput", '7', TRUE,
+ { "SevenBitInput", '7', TRUE },
#if MIME8TO7
- "EightBitMode", '8', TRUE,
+ { "EightBitMode", '8', TRUE },
#endif
- "AliasFile", 'A', FALSE,
- "AliasWait", 'a', FALSE,
- "BlankSub", 'B', FALSE,
- "MinFreeBlocks", 'b', TRUE,
- "CheckpointInterval", 'C', TRUE,
- "HoldExpensive", 'c', FALSE,
- "AutoRebuildAliases", 'D', FALSE,
- "DeliveryMode", 'd', TRUE,
- "ErrorHeader", 'E', FALSE,
- "ErrorMode", 'e', TRUE,
- "TempFileMode", 'F', FALSE,
- "SaveFromLine", 'f', FALSE,
- "MatchGECOS", 'G', FALSE,
- "HelpFile", 'H', FALSE,
- "MaxHopCount", 'h', FALSE,
- "ResolverOptions", 'I', FALSE,
- "IgnoreDots", 'i', TRUE,
- "ForwardPath", 'J', FALSE,
- "SendMimeErrors", 'j', TRUE,
- "ConnectionCacheSize", 'k', FALSE,
- "ConnectionCacheTimeout", 'K', FALSE,
- "UseErrorsTo", 'l', FALSE,
- "LogLevel", 'L', FALSE,
- "MeToo", 'm', TRUE,
- "CheckAliases", 'n', FALSE,
- "OldStyleHeaders", 'o', TRUE,
- "DaemonPortOptions", 'O', FALSE,
- "PrivacyOptions", 'p', TRUE,
- "PostmasterCopy", 'P', FALSE,
- "QueueFactor", 'q', FALSE,
- "QueueDirectory", 'Q', FALSE,
- "DontPruneRoutes", 'R', FALSE,
- "Timeout", 'r', TRUE,
- "StatusFile", 'S', FALSE,
- "SuperSafe", 's', TRUE,
- "QueueTimeout", 'T', FALSE,
- "TimeZoneSpec", 't', FALSE,
- "UserDatabaseSpec", 'U', FALSE,
- "DefaultUser", 'u', FALSE,
- "FallbackMXhost", 'V', FALSE,
- "Verbose", 'v', TRUE,
- "TryNullMXList", 'w', TRUE,
- "QueueLA", 'x', FALSE,
- "RefuseLA", 'X', FALSE,
- "RecipientFactor", 'y', FALSE,
- "ForkEachJob", 'Y', FALSE,
- "ClassFactor", 'z', FALSE,
- "RetryFactor", 'Z', FALSE,
+ { "AliasFile", 'A', FALSE },
+ { "AliasWait", 'a', FALSE },
+ { "BlankSub", 'B', FALSE },
+ { "MinFreeBlocks", 'b', TRUE },
+ { "CheckpointInterval", 'C', TRUE },
+ { "HoldExpensive", 'c', FALSE },
+ { "AutoRebuildAliases", 'D', FALSE },
+ { "DeliveryMode", 'd', TRUE },
+ { "ErrorHeader", 'E', FALSE },
+ { "ErrorMode", 'e', TRUE },
+ { "TempFileMode", 'F', FALSE },
+ { "SaveFromLine", 'f', FALSE },
+ { "MatchGECOS", 'G', FALSE },
+ { "HelpFile", 'H', FALSE },
+ { "MaxHopCount", 'h', FALSE },
+ { "ResolverOptions", 'I', FALSE },
+ { "IgnoreDots", 'i', TRUE },
+ { "ForwardPath", 'J', FALSE },
+ { "SendMimeErrors", 'j', TRUE },
+ { "ConnectionCacheSize", 'k', FALSE },
+ { "ConnectionCacheTimeout", 'K', FALSE },
+ { "UseErrorsTo", 'l', FALSE },
+ { "LogLevel", 'L', TRUE },
+ { "MeToo", 'm', TRUE },
+ { "CheckAliases", 'n', FALSE },
+ { "OldStyleHeaders", 'o', TRUE },
+ { "DaemonPortOptions", 'O', FALSE },
+ { "PrivacyOptions", 'p', TRUE },
+ { "PostmasterCopy", 'P', FALSE },
+ { "QueueFactor", 'q', FALSE },
+ { "QueueDirectory", 'Q', FALSE },
+ { "DontPruneRoutes", 'R', FALSE },
+ { "Timeout", 'r', FALSE },
+ { "StatusFile", 'S', FALSE },
+ { "SuperSafe", 's', TRUE },
+ { "QueueTimeout", 'T', FALSE },
+ { "TimeZoneSpec", 't', FALSE },
+ { "UserDatabaseSpec", 'U', FALSE },
+ { "DefaultUser", 'u', FALSE },
+ { "FallbackMXhost", 'V', FALSE },
+ { "Verbose", 'v', TRUE },
+ { "TryNullMXList", 'w', TRUE },
+ { "QueueLA", 'x', FALSE },
+ { "RefuseLA", 'X', FALSE },
+ { "RecipientFactor", 'y', FALSE },
+ { "ForkEachJob", 'Y', FALSE },
+ { "ClassFactor", 'z', FALSE },
+ { "RetryFactor", 'Z', FALSE },
#define O_QUEUESORTORD 0x81
- "QueueSortOrder", O_QUEUESORTORD, TRUE,
+ { "QueueSortOrder", O_QUEUESORTORD, TRUE },
#define O_HOSTSFILE 0x82
- "HostsFile", O_HOSTSFILE, FALSE,
+ { "HostsFile", O_HOSTSFILE, FALSE },
#define O_MQA 0x83
- "MinQueueAge", O_MQA, TRUE,
-#define O_MHSA 0x84
-/*
- "MaxHostStatAge", O_MHSA, TRUE,
-*/
+ { "MinQueueAge", O_MQA, TRUE },
#define O_DEFCHARSET 0x85
- "DefaultCharSet", O_DEFCHARSET, TRUE,
+ { "DefaultCharSet", O_DEFCHARSET, TRUE },
#define O_SSFILE 0x86
- "ServiceSwitchFile", O_SSFILE, FALSE,
+ { "ServiceSwitchFile", O_SSFILE, FALSE },
#define O_DIALDELAY 0x87
- "DialDelay", O_DIALDELAY, TRUE,
+ { "DialDelay", O_DIALDELAY, TRUE },
#define O_NORCPTACTION 0x88
- "NoRecipientAction", O_NORCPTACTION, TRUE,
+ { "NoRecipientAction", O_NORCPTACTION, TRUE },
#define O_SAFEFILEENV 0x89
- "SafeFileEnvironment", O_SAFEFILEENV, FALSE,
+ { "SafeFileEnvironment", O_SAFEFILEENV, FALSE },
#define O_MAXMSGSIZE 0x8a
- "MaxMessageSize", O_MAXMSGSIZE, FALSE,
+ { "MaxMessageSize", O_MAXMSGSIZE, FALSE },
#define O_COLONOKINADDR 0x8b
- "ColonOkInAddr", O_COLONOKINADDR, TRUE,
+ { "ColonOkInAddr", O_COLONOKINADDR, TRUE },
#define O_MAXQUEUERUN 0x8c
- "MaxQueueRunSize", O_MAXQUEUERUN, TRUE,
+ { "MaxQueueRunSize", O_MAXQUEUERUN, TRUE },
#define O_MAXCHILDREN 0x8d
-/*
- "MaxDaemonChildren", O_MAXCHILDREN, FALSE,
-*/
+ { "MaxDaemonChildren", O_MAXCHILDREN, FALSE },
#define O_KEEPCNAMES 0x8e
- "DontExpandCnames", O_KEEPCNAMES, FALSE,
+ { "DontExpandCnames", O_KEEPCNAMES, FALSE },
#define O_MUSTQUOTE 0x8f
-/*
- "MustQuoteChars", O_MUSTQUOTE, FALSE,
-*/
+ { "MustQuoteChars", O_MUSTQUOTE, FALSE },
#define O_SMTPGREETING 0x90
- "SmtpGreetingMessage", O_SMTPGREETING, FALSE,
+ { "SmtpGreetingMessage", O_SMTPGREETING, FALSE },
#define O_UNIXFROM 0x91
- "UnixFromLine", O_UNIXFROM, FALSE,
+ { "UnixFromLine", O_UNIXFROM, FALSE },
#define O_OPCHARS 0x92
- "OperatorChars", O_OPCHARS, FALSE,
+ { "OperatorChars", O_OPCHARS, FALSE },
#define O_DONTINITGRPS 0x93
- "DontInitGroups", O_DONTINITGRPS, TRUE,
+ { "DontInitGroups", O_DONTINITGRPS, TRUE },
#define O_SLFH 0x94
-#ifdef LOTUS_NOTES_HACK
- "SingleLineFromHeader", O_SLFH, TRUE,
-#endif
-
- NULL, '\0', FALSE,
+ { "SingleLineFromHeader", O_SLFH, TRUE },
+#define O_ABH 0x95
+ { "AllowBogusHELO", O_ABH, TRUE },
+#define O_CONNTHROT 0x97
+ { "ConnectionRateThrottle", O_CONNTHROT, FALSE },
+#define O_UGW 0x99
+ { "UnsafeGroupWrites", O_UGW, FALSE },
+#define O_DBLBOUNCE 0x9a
+ { "DoubleBounceAddress", O_DBLBOUNCE, FALSE },
+#define O_HSDIR 0x9b
+ { "HostStatusDirectory", O_HSDIR, FALSE },
+#define O_SINGTHREAD 0x9c
+ { "SingleThreadDelivery", O_SINGTHREAD, FALSE },
+#define O_RUNASUSER 0x9d
+ { "RunAsUser", O_RUNASUSER, FALSE },
+
+ { NULL, '\0', FALSE }
};
@@ -1461,12 +1499,18 @@ setoption(opt, val, safe, sticky, e)
register char *p;
register struct optioninfo *o;
char *subopt;
+ int mid;
+ auto char *ep;
char buf[50];
extern bool atobool();
extern time_t convtime();
extern int QueueLA;
extern int RefuseLA;
extern bool Warn_Q_option;
+ extern void setalias __P((char *));
+ extern int atooct __P((char *));
+ extern void setdefuser __P((void));
+ extern void setdaemonoptions __P((char *));
errno = 0;
if (opt == ' ')
@@ -1843,10 +1887,11 @@ setoption(opt, val, safe, sticky, e)
break;
case 'M': /* define macro */
- p = newstr(&val[1]);
+ mid = macid(val, &ep);
+ p = newstr(ep);
if (!safe)
cleanstrcpy(p, p, MAXNAME);
- define(val[0], p, CurEnv);
+ define(mid, p, CurEnv);
sticky = FALSE;
break;
@@ -1986,6 +2031,14 @@ setoption(opt, val, safe, sticky, e)
DefGid = pw->pw_gid;
}
}
+
+#ifdef UID_MAX
+ if (DefUid > UID_MAX)
+ {
+ syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored",
+ DefUid, UID_MAX);
+ }
+#endif
setdefuser();
/* handle the group if it is there */
@@ -1995,7 +2048,8 @@ setoption(opt, val, safe, sticky, e)
goto g_opt;
case 'V': /* fallback MX host */
- FallBackMX = newstr(val);
+ if (val[0] != '\0')
+ FallBackMX = newstr(val);
break;
case 'v': /* run in verbose mode */
@@ -2045,6 +2099,11 @@ setoption(opt, val, safe, sticky, e)
QueueSortOrder = QS_BYPRIORITY;
break;
+ case 't': /* Submission time */
+ case 'T':
+ QueueSortOrder = QS_BYTIME;
+ break;
+
default:
syserr("Invalid queue sort order \"%s\"", val);
}
@@ -2058,10 +2117,6 @@ setoption(opt, val, safe, sticky, e)
MinQueueAge = convtime(val, 'm');
break;
- case O_MHSA: /* maximum age of cached host status */
- MaxHostStatAge = convtime(val, 'm');
- break;
-
case O_DEFCHARSET: /* default character set for mimefying */
DefaultCharSet = newstr(denlstring(val, TRUE, TRUE));
break;
@@ -2115,21 +2170,21 @@ setoption(opt, val, safe, sticky, e)
case O_MUSTQUOTE: /* must quote these characters in phrases */
strcpy(buf, "@,;:\\()[]");
- if (strlen(val) < sizeof buf - 10)
+ if (strlen(val) < (SIZE_T) sizeof buf - 10)
strcat(buf, val);
MustQuoteChars = newstr(buf);
break;
case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */
- SmtpGreeting = newstr(munchstring(val, NULL));
+ SmtpGreeting = newstr(munchstring(val, NULL, '\0'));
break;
case O_UNIXFROM: /* UNIX From_ line (old $l macro) */
- UnixFromLine = newstr(munchstring(val, NULL));
+ UnixFromLine = newstr(munchstring(val, NULL, '\0'));
break;
case O_OPCHARS: /* operator characters (old $o macro) */
- OperatorChars = newstr(munchstring(val, NULL));
+ OperatorChars = newstr(munchstring(val, NULL, '\0'));
break;
case O_DONTINITGRPS: /* don't call initgroups(3) */
@@ -2140,6 +2195,75 @@ setoption(opt, val, safe, sticky, e)
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 */
+ UnsafeGroupWrites = atobool(val);
+ 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))
+ RunAsUid = atoi(val);
+ else
+ {
+ register struct passwd *pw;
+
+ pw = sm_getpwnam(val);
+ if (pw == NULL)
+ syserr("readcf: option RunAsUser: unknown user %s", val);
+ else
+ {
+ RunAsUid = pw->pw_uid;
+ RunAsGid = pw->pw_gid;
+ }
+ }
+ if (*p == '\0')
+ break;
+ if (isascii(*p) && isdigit(*p))
+ DefGid = atoi(p);
+ else
+ {
+ register struct group *gr;
+
+ gr = getgrnam(p);
+ if (gr == NULL)
+ syserr("readcf: option RunAsUser: unknown group %s",
+ p);
+ else
+ RunAsGid = gr->gr_gid;
+ }
+ break;
+
default:
if (tTd(37, 1))
{
@@ -2249,7 +2373,7 @@ makemapentry(line)
if (tTd(37, 5))
{
- printf("map %s, class %s, flags %x, file %s,\n",
+ printf("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);
@@ -2327,10 +2451,7 @@ strtorwset(p, endp, stabmode)
*p = delim;
if (s == NULL)
- {
- syserr("unknown ruleset %s", q);
return -1;
- }
if (stabmode == ST_ENTER && delim == '=')
{
@@ -2368,7 +2489,7 @@ strtorwset(p, endp, stabmode)
if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset)
{
syserr("%s: ruleset changed value (old %d, new %d)",
- q, ruleset, s->s_ruleset);
+ q, s->s_ruleset, ruleset);
ruleset = s->s_ruleset;
}
else if (ruleset > 0)
@@ -2403,6 +2524,8 @@ inittimeouts(val)
register char *p;
extern time_t convtime();
+ if (tTd(37, 2))
+ printf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val);
if (val == NULL)
{
TimeOuts.to_connect = (time_t) 0 SECONDS;
@@ -2423,6 +2546,24 @@ inittimeouts(val)
TimeOuts.to_ident = (time_t) 0 SECONDS;
#endif
TimeOuts.to_fileopen = (time_t) 60 SECONDS;
+ if (tTd(37, 5))
+ {
+ printf("Timeouts:\n");
+ printf(" connect = %ld\n", TimeOuts.to_connect);
+ printf(" initial = %ld\n", TimeOuts.to_initial);
+ printf(" helo = %ld\n", TimeOuts.to_helo);
+ printf(" mail = %ld\n", TimeOuts.to_mail);
+ printf(" rcpt = %ld\n", TimeOuts.to_rcpt);
+ printf(" datainit = %ld\n", TimeOuts.to_datainit);
+ printf(" datablock = %ld\n", TimeOuts.to_datablock);
+ printf(" datafinal = %ld\n", TimeOuts.to_datafinal);
+ printf(" rset = %ld\n", TimeOuts.to_rset);
+ printf(" quit = %ld\n", TimeOuts.to_quit);
+ printf(" nextcommand = %ld\n", TimeOuts.to_nextcommand);
+ printf(" miscshort = %ld\n", TimeOuts.to_miscshort);
+ printf(" ident = %ld\n", TimeOuts.to_ident);
+ printf(" fileopen = %ld\n", TimeOuts.to_fileopen);
+ }
return;
}
@@ -2482,6 +2623,9 @@ settimeout(name, val)
time_t to;
extern time_t convtime();
+ if (tTd(37, 2))
+ printf("settimeout(%s = %s)\n", name, val);
+
to = convtime(val, 'm');
p = strchr(name, '.');
if (p != NULL)
@@ -2515,6 +2659,8 @@ settimeout(name, val)
TimeOuts.to_fileopen = to;
else if (strcasecmp(name, "connect") == 0)
TimeOuts.to_connect = to;
+ else if (strcasecmp(name, "iconnect") == 0)
+ TimeOuts.to_iconnect = to;
else if (strcasecmp(name, "queuewarn") == 0)
{
to = convtime(val, 'h');
@@ -2551,6 +2697,8 @@ settimeout(name, val)
else
syserr("settimeout: invalid queuereturn subtimeout %s", p);
}
+ else if (strcasecmp(name, "hoststatus") == 0)
+ MciInfoTimeout = convtime(val, 'm');
else
syserr("settimeout: invalid timeout %s", name);
}
diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c
index 4675247e11cf..dae5156a0c3e 100644
--- a/usr.sbin/sendmail/src/recipient.c
+++ b/usr.sbin/sendmail/src/recipient.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)recipient.c 8.108.1.1 (Berkeley) 9/12/96";
+static char sccsid[] = "@(#)recipient.c 8.116 (Berkeley) 8/17/96";
#endif /* not lint */
# include "sendmail.h"
@@ -241,7 +241,7 @@ recipient(a, sendq, aliaslevel, e)
int i;
char *buf;
char buf0[MAXNAME + 1]; /* unquoted image of the user name */
- extern int safefile();
+ extern void alias __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
e->e_to = a->q_paddr;
m = a->q_mailer;
@@ -267,7 +267,7 @@ recipient(a, sendq, aliaslevel, e)
if (aliaslevel > MaxAliasRecursion)
{
a->q_status = "5.4.6";
- usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max",
+ usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max)",
aliaslevel, MaxAliasRecursion);
return (a);
}
@@ -482,6 +482,8 @@ recipient(a, sendq, aliaslevel, e)
ConfigLevel >= 2 && RewriteRules[5] != NULL &&
bitnset(M_TRYRULESET5, m->m_flags))
{
+ extern void maplocaluser __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
+
maplocaluser(a, sendq, aliaslevel + 1, e);
}
@@ -495,7 +497,7 @@ recipient(a, sendq, aliaslevel, e)
{
auto bool fuzzy;
register struct passwd *pw;
- extern struct passwd *finduser();
+ extern void forward __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
/* warning -- finduser may trash buf */
pw = finduser(buf, &fuzzy);
@@ -738,8 +740,7 @@ finduser(name, fuzzyp)
{
if (tTd(29, 4))
printf("found (case wrapped)\n");
- *fuzzyp = TRUE;
- return pw;
+ break;
}
# endif
@@ -749,17 +750,22 @@ finduser(name, fuzzyp)
if (tTd(29, 4))
printf("fuzzy matches %s\n", pw->pw_name);
message("sending to login name %s", pw->pw_name);
- *fuzzyp = TRUE;
- return (pw);
+ break;
}
}
- if (tTd(29, 4))
+ if (pw != NULL)
+ *fuzzyp = TRUE;
+ else if (tTd(29, 4))
printf("no fuzzy match found\n");
+# if DEC_OSF_BROKEN_GETPWENT /* DEC OSF/1 3.2 or earlier */
+ endpwent();
+# endif
+ return pw;
#else
if (tTd(29, 4))
printf("not found (fuzzy disabled)\n");
+ return NULL;
#endif
- return (NULL);
}
/*
** WRITABLE -- predicate returning if the file is writable.
@@ -1122,19 +1128,21 @@ resetuid:
/*
** Check to see if some bad guy can write this file
**
- ** This should really do something clever with group
- ** permissions; currently we just view world writable
- ** as unsafe. Also, we don't check for writable
+ ** Group write checking could be more clever, e.g.,
+ ** guessing as to which groups are actually safe ("sys"
+ ** may be; "user" probably is not).
+ ** Also, we don't check for writable
** directories in the path. We've got to leave
** something for the local sysad to do.
*/
- if (bitset(S_IWOTH, st.st_mode))
+ if (bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st.st_mode))
{
#ifdef LOG
if (LogLevel >= 12)
- syslog(LOG_INFO, "%s: world writable %s file, marked unsafe",
+ syslog(LOG_INFO, "%s: %s writable %s file, marked unsafe",
shortenstring(fname, 203),
+ bitset(S_IWOTH, st.st_mode) ? "world" : "group",
forwarding ? "forward" : ":include:");
#endif
ctladdr->q_flags |= QUNSAFEADDR;
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c
index 80639b12cf34..baa1a04d446a 100644
--- a/usr.sbin/sendmail/src/savemail.c
+++ b/usr.sbin/sendmail/src/savemail.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)savemail.c 8.87.1.2 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)savemail.c 8.100 (Berkeley) 9/27/96";
#endif /* not lint */
# include "sendmail.h"
@@ -86,7 +86,7 @@ savemail(e, sendbody)
auto ADDRESS *q = NULL;
register char *p;
MCI mcibuf;
- int sfflags;
+ int flags;
char buf[MAXLINE+1];
extern char *ttypath();
typedef int (*fnptr)();
@@ -283,7 +283,9 @@ savemail(e, sendbody)
break;
}
if (returntosender(e->e_message, e->e_errorqueue,
- sendbody, e) == 0)
+ sendbody ? RTSF_SEND_BODY
+ : RTSF_NO_BODY,
+ e) == 0)
{
state = ESM_DONE;
break;
@@ -299,14 +301,17 @@ savemail(e, sendbody)
*/
q = NULL;
- if (sendtolist("postmaster", NULL, &q, 0, e) <= 0)
+ if (sendtolist(DoubleBounceAddr, NULL, &q, 0, e) <= 0)
{
- syserr("553 cannot parse postmaster!");
+ syserr("553 cannot parse %s!", DoubleBounceAddr);
ExitStat = EX_SOFTWARE;
state = ESM_USRTMP;
break;
}
- if (returntosender(e->e_message, q, sendbody, e) == 0)
+ flags = RTSF_PM_BOUNCE;
+ if (sendbody)
+ flags |= RTSF_SEND_BODY;
+ if (returntosender(e->e_message, q, flags, e) == 0)
{
state = ESM_DONE;
break;
@@ -344,9 +349,9 @@ savemail(e, sendbody)
/* we have a home directory; write dead.letter */
define('z', p, e);
expand("\201z/dead.letter", buf, sizeof buf, e);
- sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
+ flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
e->e_to = buf;
- if (mailfile(buf, NULL, sfflags, e) == EX_OK)
+ if (mailfile(buf, NULL, flags, e) == EX_OK)
{
bool oldverb = Verbose;
@@ -378,10 +383,10 @@ savemail(e, sendbody)
snprintf(buf, sizeof buf, "%sdead.letter", _PATH_VARTMP);
- sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
- if (!writable(buf, NULL, sfflags) ||
+ flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
+ if (!writable(buf, NULL, flags) ||
(fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND,
- FileMode, sfflags)) == NULL)
+ FileMode, flags)) == NULL)
{
state = ESM_PANIC;
break;
@@ -398,7 +403,9 @@ savemail(e, sendbody)
(*e->e_putbody)(&mcibuf, e, NULL);
putline("\n", &mcibuf);
(void) fflush(fp);
- if (!ferror(fp))
+ if (ferror(fp))
+ state = ESM_PANIC;
+ else
{
bool oldverb = Verbose;
@@ -410,9 +417,7 @@ savemail(e, sendbody)
syslog(LOG_NOTICE, "Saved message in %s", buf);
#endif
state = ESM_DONE;
- break;
}
- state = ESM_PANIC;
(void) xfclose(fp, "savemail", buf);
break;
@@ -434,8 +439,10 @@ savemail(e, sendbody)
** Parameters:
** msg -- the explanatory message.
** returnq -- the queue of people to send the message to.
-** sendbody -- if TRUE, also send back the body of the
-** message; otherwise just send the header.
+** 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:
@@ -451,10 +458,10 @@ savemail(e, sendbody)
#define ERRORFUDGE 100 /* nominal size of error message text */
int
-returntosender(msg, returnq, sendbody, e)
+returntosender(msg, returnq, flags, e)
char *msg;
ADDRESS *returnq;
- bool sendbody;
+ int flags;
register ENVELOPE *e;
{
register ENVELOPE *ee;
@@ -509,16 +516,21 @@ returntosender(msg, returnq, sendbody, e)
ee->e_flags &= ~EF_OLDSTYLE;
ee->e_sendqueue = returnq;
ee->e_msgsize = ERRORFUDGE;
- if (sendbody)
+ if (bitset(RTSF_SEND_BODY, flags))
ee->e_msgsize += e->e_msgsize;
else
ee->e_flags |= EF_NO_BODY_RETN;
initsys(ee);
for (q = returnq; q != NULL; q = q->q_next)
{
+ extern bool pruneroute __P((char *));
+
if (bitset(QBADADDR, q->q_flags))
continue;
+ q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS);
+ q->q_flags |= QPINGONFAILURE;
+
if (!DontPruneRoutes && pruneroute(q->q_paddr))
{
register ADDRESS *p;
@@ -543,8 +555,10 @@ returntosender(msg, returnq, sendbody, e)
{
if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags))
p = "return to sender";
- else
+ else if (bitset(RTSF_PM_BOUNCE, flags))
p = "postmaster notify";
+ else
+ p = "DSN";
syslog(LOG_INFO, "%s: %s: %s: %s",
e->e_id, ee->e_id, p, shortenstring(msg, 203));
}
@@ -589,6 +603,13 @@ returntosender(msg, returnq, sendbody, e)
addheader("Subject", msg, &ee->e_header);
p = "return-receipt";
}
+ else if (bitset(RTSF_PM_BOUNCE, flags))
+ {
+ snprintf(buf, sizeof buf, "Postmaster notify: %.*s",
+ sizeof buf - 20, msg);
+ addheader("Subject", buf, &ee->e_header);
+ p = "postmaster-notification";
+ }
else
{
snprintf(buf, sizeof buf, "Returned mail: %.*s",
@@ -608,6 +629,8 @@ returntosender(msg, returnq, sendbody, e)
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 */
@@ -623,7 +646,7 @@ returntosender(msg, returnq, sendbody, e)
sendall(ee, SM_DEFAULT);
/* restore state */
- dropenvelope(ee);
+ dropenvelope(ee, TRUE);
CurEnv = oldcur;
returndepth--;
@@ -647,7 +670,6 @@ returntosender(msg, returnq, sendbody, e)
** mci -- the mailer connection information.
** e -- the envelope we are working in.
** separator -- any possible MIME separator.
-** flags -- to modify the behaviour.
**
** Returns:
** none
@@ -667,8 +689,8 @@ errbody(mci, e, separator)
register ADDRESS *q;
bool printheader;
bool sendbody;
+ bool pm_notify;
char buf[MAXLINE];
- extern char *xuntextify();
if (bitset(MCIF_INHEADER, mci->mci_flags))
{
@@ -699,10 +721,17 @@ errbody(mci, e, separator)
** Output introductory information.
*/
- for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
- if (bitset(QBADADDR, q->q_flags))
- break;
- if (q == NULL &&
+ 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 (bitset(QBADADDR, q->q_flags))
+ break;
+ }
+ if (!pm_notify && q == NULL &&
!bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
{
putline(" **********************************************",
@@ -757,16 +786,63 @@ errbody(mci, e, separator)
printheader = TRUE;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
- if (bitset(QBADADDR, q->q_flags))
+ if (!bitset(QBADADDR, q->q_flags) ||
+ !bitset(QPINGONFAILURE, q->q_flags))
+ continue;
+
+ if (printheader)
{
- if (!bitset(QPINGONFAILURE, q->q_flags))
- continue;
- p = "unrecoverable error";
+ putline(" ----- The following addresses had permanent fatal errors -----",
+ mci);
+ printheader = FALSE;
}
- else if (!bitset(QPRIMARY, q->q_flags))
+
+ snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, 203));
+ putline(buf, mci);
+ if (q->q_alias != NULL)
+ {
+ snprintf(buf, sizeof buf, " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr, 203));
+ putline(buf, mci);
+ }
+ }
+ if (!printheader)
+ putline("", mci);
+
+ printheader = TRUE;
+ for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QBADADDR, q->q_flags) ||
+ !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, 203));
+ putline(buf, mci);
+ if (q->q_alias != NULL)
+ {
+ snprintf(buf, sizeof buf, " (expanded from: %s)",
+ shortenstring(q->q_alias->q_paddr, 203));
+ putline(buf, mci);
+ }
+ }
+ if (!printheader)
+ putline("", mci);
+
+ printheader = TRUE;
+ for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+ {
+ if (bitset(QBADADDR, q->q_flags) ||
+ !bitset(QPRIMARY, q->q_flags) ||
+ bitset(QDELAYED, q->q_flags))
continue;
- else if (bitset(QDELAYED, q->q_flags))
- p = "transient failure";
else if (!bitset(QPINGONSUCCESS, q->q_flags))
continue;
else if (bitset(QRELAYED, q->q_flags))
@@ -785,7 +861,7 @@ errbody(mci, e, separator)
if (printheader)
{
- putline(" ----- The following addresses have delivery notifications -----",
+ putline(" ----- The following addresses had successful delivery notifications -----",
mci);
printheader = FALSE;
}
@@ -801,7 +877,7 @@ errbody(mci, e, separator)
}
}
if (!printheader)
- putline("\n", mci);
+ putline("", mci);
/*
** Output transcript of errors
@@ -1164,14 +1240,16 @@ smtptodsn(smtpstat)
**
** 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)
+xtextify(t, taboo)
register char *t;
+ char *taboo;
{
register char *p;
int l;
@@ -1179,6 +1257,9 @@ xtextify(t)
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++)
@@ -1186,7 +1267,8 @@ xtextify(t)
register int c = (*p & 0xff);
/* ASCII dependence here -- this is the way the spec words it */
- if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
+ if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
+ strchr(taboo, c) != NULL)
nbogus++;
l++;
}
@@ -1209,7 +1291,8 @@ xtextify(t)
register int c = (*t++ & 0xff);
/* ASCII dependence here -- this is the way the spec words it */
- if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
+ if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
+ strchr(taboo, c) != NULL)
{
*p++ = '+';
*p++ = "0123456789abcdef"[c >> 4];
@@ -1298,6 +1381,7 @@ xuntextify(t)
c -= 'a' - 10;
*p++ |= c;
}
+ *p = '\0';
return bp;
}
/*
diff --git a/usr.sbin/sendmail/src/sendmail.8 b/usr.sbin/sendmail/src/sendmail.8
index 58060deeeaca..34c3f4415567 100644
--- a/usr.sbin/sendmail/src/sendmail.8
+++ b/usr.sbin/sendmail/src/sendmail.8
@@ -29,14 +29,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)sendmail.8 8.6 (Berkeley) 5/27/95
+.\" @(#)sendmail.8 8.10 (Berkeley) 9/20/96
.\"
-.Dd May 27, 1995
+.Dd September 20, 1996
.Dt SENDMAIL 8
.Os BSD 4
.Sh NAME
.Nm sendmail
-.Nd send mail over the internet
+.Nd an electronic mail transport agent
.Sh SYNOPSIS
.Nm sendmail
.Op Ar flags
@@ -108,6 +108,14 @@ listening on socket 25 for incoming
connections.
This is normally run from
.Pa /etc/rc .
+.It Fl bD
+Same as
+.Fl bd
+except runs in foreground.
+.It Fl bh
+Print the persistent host status database.
+.It Fl bH
+Purge the persistent host status database.
.It Fl bi
Initialize the alias database.
.It Fl bm
@@ -165,14 +173,41 @@ the mail is returned with an error message,
the victim of an aliasing loop.
If not specified,
``Received:'' lines in the message are counted.
+.It Fl i
+Ignore dots alone on lines by themselves in incoming messages.
+This should be set if you are reading data from a file.
+.It Fl N Ar dsn
+Set delivery status notification conditions to
+.Ar dsn,
+which can be
+.Ql never
+for no notifications
+or a comma separated list of the values
+.Ql failure
+to be notified if delivery failed,
+.Ql delay
+to be notified if delivery is delayed, and
+.Ql success
+to be notified when the message is successfully delivered.
.It Fl n
Don't do aliasing.
+.It Fl O Ar option Ns = Ns Em value
+Set option
+.Ar option
+to the specified
+.Em value .
+This form uses long names.
+See below for more details.
.It Fl o Ns Ar x Em value
Set option
.Ar x
to the specified
.Em value .
-Options are described below.
+This form uses single character names only.
+The short names are not described in this manual page;
+see the
+.%T "Sendmail Installation and Operation Guide"
+for details.
.It Fl p Ns Ar protocol
Set the name of the protocol used to receive the message.
This can be a simple protocol name such as ``UUCP''
@@ -221,6 +256,16 @@ as a substring of one of the recipients.
Limit processed jobs to those containing
.Ar substr
as a substring of the sender.
+.It Fl R Ar return
+Set the amount of the message to be returned
+if the message bounces.
+The
+.Ar return
+parameter can be
+.Ql full
+to return the entire message or
+.Ql hdrs
+to return only the headers.
.It Fl r Ns Ar name
An alternate and obsolete form of the
.Fl f
@@ -234,6 +279,22 @@ that is,
they will
.Em not
receive copies even if listed in the message header.
+.It Fl U
+Initial (user) submission.
+This should
+.Em always
+be set when called from a user agent such as
+.Nm Mail
+or
+.Nm exmh
+and
+.Em never
+be set when called by a network delivery agent such as
+.Nm rmail .
+.It Fl V Ar envid
+Set the original envelope id.
+This is propogated across SMTP to servers that support DSNs
+and is returned in DSN-compliant error messages.
.It Fl v
Go into verbose mode.
Alias expansions will be announced, etc.
@@ -249,22 +310,25 @@ Normally these will only be used by a system administrator.
Options may be set either on the command line
using the
.Fl o
-flag
+flag (for short names),
+the
+.Fl O
+flag (for long names),
or in the configuration file.
-This is a partial list;
+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
.%T "Sendmail Installation and Operation Guide" .
The options are:
.Bl -tag -width Fl
-.It Li A Ns Ar file
+.It Li AliasFile= Ns Ar file
Use alternate alias file.
-.It Li b Ns Ar nblocks
-The minimum number of free blocks needed on the spool filesystem.
-.It Li c
+.It Li HoldExpensive
On mailers that are considered ``expensive'' to connect to,
don't initiate immediate connection.
This requires queueing.
-.It Li C Ar N
+.It Li CheckpointInterval= Ns Ar N
Checkpoint the queue file after every
.Ar N
successful deliveries (default 10).
@@ -272,7 +336,7 @@ This avoids excessive duplicate deliveries
when sending to long mailing lists
interrupted by system crashes.
.ne 1i
-.It Li d Ns Ar x
+.It Li DeliveryMode= Ns Ar x
Set the delivery mode to
.Ar x .
Delivery modes are
@@ -280,14 +344,14 @@ Delivery modes are
for interactive (synchronous) delivery,
.Ql b
for background (asynchronous) delivery,
-and
.Ql q
for queue only \- i.e.,
-actual delivery is done the next time the queue is run.
-.It Li D
-Try to automatically rebuild the alias database
-if necessary.
-.It Li e Ns Ar x
+actual delivery is done the next time the queue is run, and
+.Ql d
+for deferred \- the same as
+.Ql q
+except that database lookups (notably DNS and NIS lookups) are avoided.
+.It Li ErrorMode= Ns Ar x
Set error processing to mode
.Ar x .
Valid modes are
@@ -315,41 +379,33 @@ and if the sender is local to this machine,
a copy of the message is appended to the file
.Pa dead.letter
in the sender's home directory.
-.It Li f
+.It Li SaveFromLine
Save
.Tn UNIX Ns \-style
From lines at the front of messages.
-.It Li G
-Match local mail names against the GECOS portion of the password file.
-.It Li g Ar N
-The default group id to use when calling mailers.
-.It Li H Ns Ar file
-The
-.Tn SMTP
-help file.
-.It Li h Ar N
+.It Li MaxHopCount= Ar N
The maximum number of times a message is allowed to ``hop''
before we decide it is in a loop.
-.It Li i
+.It Li IgnoreDots
Do not take dots on a line by themselves
as a message terminator.
-.It Li j
+.It Li SendMimeErrors
Send error messages in MIME format.
-.It Li K Ns Ar timeout
+If not set, the DSN (Delivery Status Notification) SMTP extension
+is disabled.
+.It Li ConnectionCacheTimeout= Ns Ar timeout
Set connection cache timeout.
-.It Li k Ns Ar N
+.It Li ConnectionCacheSize= Ns Ar N
Set connection cache size.
-.It Li L Ns Ar n
+.It Li LogLevel= Ns Ar n
The log level.
-.It Li l
-Pay attention to the Errors-To: header.
-.It Li m
+.It Li MeToo
Send to ``me'' (the sender) also if I am in an alias expansion.
-.It Li n
+.It Li CheckAliases
Validate the right hand side of aliases during a
.Xr newaliases 1
command.
-.It Li o
+.It Li OldStyleHeaders
If set, this message may have
old style headers.
If not set,
@@ -357,24 +413,18 @@ this message is guaranteed to have new style headers
(i.e., commas instead of spaces between addresses).
If set, an adaptive algorithm is used that will correctly
determine the header format in most cases.
-.It Li Q Ns Ar queuedir
+.It Li QueueDirectory= Ns Ar queuedir
Select the directory in which to queue messages.
-.It Li S Ns Ar file
+.It Li StatusFile= Ns Ar file
Save statistics in the named file.
-.It Li s
-Always instantiate the queue file,
-even under circumstances where it is not strictly necessary.
-This provides safety against system crashes during delivery.
-.It Li T Ns Ar time
+.It Li Timeout.queuereturn= Ns Ar time
Set the timeout on undelivered messages in the queue to the specified time.
After delivery has failed
(e.g., because of a host being down)
for this amount of time,
failed messages will be returned to the sender.
-The default is three days.
-.It Li t Ns Ar stz , Ar dtz
-Set the name of the time zone.
-.It Li U Ns Ar userdatabase
+The default is five days.
+.It Li UserDatabaseSpec= Ns Ar userdatabase
If set, a user database is consulted to get forwarding information.
You can consider this an adjunct to the aliasing mechanism,
except that the database is intended to be distributed;
@@ -382,13 +432,54 @@ aliases are local to a particular host.
This may not be available if your sendmail does not have the
.Dv USERDB
option compiled in.
-.It Li u Ns Ar N
-Set the default user id for mailers.
-.It Li Y
+.It Li ForkEachJob
Fork each job during queue runs.
May be convenient on memory-poor machines.
-.It Li 7
+.It Li SevenBitInput
Strip incoming messages to seven bits.
+.It Li EightBitMode= Ns Ar mode
+Set the handling of eight bit input to seven bit destinations to
+.Ar mode :
+.Li m
+(mimefy) will convert to seven-bit MIME format,
+.Li p
+(pass) will pass it as eight bits (but violates protocols),
+and
+.Li s
+(strict) will bounce the message.
+.It Li MinQueueAge= Ns Ar timeout
+Sets how long a job must ferment in the queue between attempts to send it.
+.It Li DefaultCharSet= Ns Ar charset
+Sets the default character set used to label 8-bit data
+that is not otherwise labelled.
+.It Li DialDelay= Ns Ar sleeptime
+If opening a connection fails,
+sleep for
+.Ar sleeptime
+seconds and try again.
+Useful on dial-on-demand sites.
+.It Li NoRecipientAction= Ns Ar action
+Set the behaviour when there are no recipient headers (To:, Cc: or Bcc:)
+in the message to
+.Ar action :
+.Li none
+leaves the message unchanged,
+.Li add-to
+adds a To: header with the envelope recipients,
+.Li add-apparently-to
+adds an Apparently-To: header with the envelope recipients,
+.Li add-bcc
+adds an empty Bcc: header, and
+.Li add-to-undisclosed
+adds a header reading
+.Ql "To: undisclosed-recipients:;" .
+.It Li MaxDaemonChildren= Ns Ar N
+Sets the maximum number of children that an incoming SMTP daemon
+will allow to spawn at any time to
+.Ar N .
+.It Li ConnectionRateThrottle= Ns Ar N
+Sets the maximum number of connections per second to the SMTP port to
+.Ar N .
.El
.Pp
In aliases,
diff --git a/usr.sbin/sendmail/src/sendmail.h b/usr.sbin/sendmail/src/sendmail.h
index fb2f1452ddaf..2dc30e4c6277 100644
--- a/usr.sbin/sendmail/src/sendmail.h
+++ b/usr.sbin/sendmail/src/sendmail.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)sendmail.h 8.159.1.3 (Berkeley) 9/16/96
+ * @(#)sendmail.h 8.209 (Berkeley) 11/8/96
*/
/*
@@ -41,7 +41,7 @@
# ifdef _DEFINE
# define EXTERN
# ifndef lint
-static char SmailSccsId[] = "@(#)sendmail.h 8.159.1.3 9/16/96";
+static char SmailSccsId[] = "@(#)sendmail.h 8.209 11/8/96";
# endif
# else /* _DEFINE */
# define EXTERN extern
@@ -179,12 +179,15 @@ typedef struct address ADDRESS;
# define QEXPANDED 0x00020000 /* DSN: undergone list expansion */
# define QDELIVERED 0x00040000 /* DSN: successful final delivery */
# define QDELAYED 0x00080000 /* DSN: message delayed */
-# define QTHISPASS 0x80000000 /* temp: address set this pass */
+# define QTHISPASS 0x40000000 /* temp: address set this pass */
+
+# define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY)
# define NULLADDR ((ADDRESS *) NULL)
/* functions */
extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *));
+extern ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern char **prescan __P((char *, int, char[], int, char **, u_char *));
extern int rewrite __P((char **, int, int, ENVELOPE *));
@@ -250,6 +253,7 @@ struct mailer
# 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 */
@@ -259,6 +263,7 @@ struct mailer
# 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 */
@@ -270,6 +275,8 @@ struct mailer
# 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_EBCDIC '3' /* extend Q-P encoding for EBCDIC */
# define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */
# define M_7BITS '7' /* use 7-bit path */
@@ -279,6 +286,7 @@ struct mailer
# 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 */
EXTERN MAILER *Mailer[MAXMAILERS+1];
@@ -287,52 +295,6 @@ EXTERN MAILER *ProgMailer; /* ptr to program mailer */
EXTERN MAILER *FileMailer; /* ptr to *file* mailer */
EXTERN MAILER *InclMailer; /* ptr to *include* mailer */
/*
-** Header structure.
-** This structure is used internally to store header items.
-*/
-
-struct header
-{
- char *h_field; /* the name of the field */
- char *h_value; /* the value of that field */
- struct header *h_link; /* the next header */
- u_short h_flags; /* status bits, see below */
- BITMAP h_mflags; /* m_flags bits needed */
-};
-
-typedef struct header HDR;
-
-/*
-** Header information structure.
-** Defined in conf.c, this struct declares the header fields
-** that have some magic meaning.
-*/
-
-struct hdrinfo
-{
- char *hi_field; /* the name of the field */
- u_short hi_flags; /* status bits, see below */
-};
-
-extern struct hdrinfo HdrInfo[];
-
-/* bits for h_flags and hi_flags */
-# define H_EOH 0x0001 /* this field terminates header */
-# define H_RCPT 0x0002 /* contains recipient addresses */
-# define H_DEFAULT 0x0004 /* if another value is found, drop this */
-# define H_RESENT 0x0008 /* this address is a "Resent-..." address */
-# define H_CHECK 0x0010 /* check h_mflags against m_flags */
-# define H_ACHECK 0x0020 /* ditto, but always (not just default) */
-# define H_FORCE 0x0040 /* force this field, even if default */
-# define H_TRACE 0x0080 /* this field contains trace information */
-# define H_FROM 0x0100 /* this is a from-type field */
-# define H_VALID 0x0200 /* this field has a validated value */
-# define H_RECEIPTTO 0x0400 /* this field has return receipt info */
-# define H_ERRORSTO 0x0800 /* this field has error address info */
-# define H_CTE 0x1000 /* this field is a content-transfer-encoding */
-# define H_CTYPE 0x2000 /* this is a content-type field */
-# define H_BCC 0x4000 /* Bcc: header: strip value or delete */
- /*
** Information about currently open connections to mailers, or to
** hosts that we have looked up recently.
*/
@@ -349,12 +311,14 @@ MCI
long mci_maxsize; /* max size this server will accept */
FILE *mci_in; /* input side of connection */
FILE *mci_out; /* output side of connection */
- int mci_pid; /* process id of subordinate proc */
+ 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 */
};
@@ -388,6 +352,72 @@ MCI
extern MCI *mci_get __P((char *, MAILER *));
extern void mci_cache __P((MCI *));
extern void mci_flush __P((bool, MCI *));
+extern void mci_dump __P((MCI *, bool));
+extern void mci_dump_all __P((bool));
+extern MCI **mci_scan __P((MCI *));
+extern int mci_traverse_persistent __P((int (), char *));
+extern int mci_print_persistent __P((char *, char *));
+extern int mci_purge_persistent __P((char *, char *));
+extern int mci_lock_host __P((MCI *));
+extern void mci_unlock_host __P((MCI *));
+extern int mci_lock_host_statfile __P((MCI *));
+extern void mci_store_persistent __P((MCI *));
+extern int mci_read_persistent __P((FILE *, 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_short h_flags; /* status bits, see below */
+ BITMAP h_mflags; /* m_flags bits needed */
+};
+
+typedef struct header HDR;
+
+/*
+** Header information structure.
+** Defined in conf.c, this struct declares the header fields
+** that have some magic meaning.
+*/
+
+struct hdrinfo
+{
+ char *hi_field; /* the name of the field */
+ u_short hi_flags; /* status bits, see below */
+};
+
+extern struct hdrinfo HdrInfo[];
+
+/* bits for h_flags and hi_flags */
+# define H_EOH 0x0001 /* this field terminates header */
+# define H_RCPT 0x0002 /* contains recipient addresses */
+# define H_DEFAULT 0x0004 /* if another value is found, drop this */
+# define H_RESENT 0x0008 /* this address is a "Resent-..." address */
+# define H_CHECK 0x0010 /* check h_mflags against m_flags */
+# define H_ACHECK 0x0020 /* ditto, but always (not just default) */
+# define H_FORCE 0x0040 /* force this field, even if default */
+# define H_TRACE 0x0080 /* this field contains trace information */
+# define H_FROM 0x0100 /* this is a from-type field */
+# define H_VALID 0x0200 /* this field has a validated value */
+# define H_RECEIPTTO 0x0400 /* this field has return receipt info */
+# define H_ERRORSTO 0x0800 /* this field has error address info */
+# define H_CTE 0x1000 /* this field is a content-transfer-encoding */
+# define H_CTYPE 0x2000 /* this is a content-type field */
+# define H_BCC 0x4000 /* Bcc: header: strip value or delete */
+# define H_ENCODABLE 0x8000 /* field can be RFC 1522 encoded */
+
+/* functions */
+extern void addheader __P((char *, char *, HDR **));
+extern char *hvalue __P((char *, HDR *));
+extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
+extern void put_vanilla_header __P((HDR *, char *, MCI *));
+extern void eatheader __P((ENVELOPE *e, bool));
+extern int chompheader __P((char *, bool, HDR **, ENVELOPE *));
/*
** Envelope structure.
** This structure defines the message itself. There is usually
@@ -403,7 +433,6 @@ struct envelope
long e_msgpriority; /* adjusted priority of this message */
time_t e_ctime; /* time message appeared in the queue */
char *e_to; /* the target person */
- char *e_receiptto; /* return receipt address */
ADDRESS e_from; /* the person it is from */
char *e_sender; /* e_from.q_paddr w comments stripped */
char **e_fromdomain; /* the domain part of the sender */
@@ -472,7 +501,7 @@ EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */
/* functions */
extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *));
-extern void dropenvelope __P((ENVELOPE *));
+extern void dropenvelope __P((ENVELOPE *, bool));
extern void clearenvelope __P((ENVELOPE *, bool));
extern void putheader __P((MCI *, HDR *, ENVELOPE *));
@@ -636,7 +665,8 @@ MAP
char *map_domain; /* the (nominal) NIS domain */
char *map_rebuild; /* program to run to do auto-rebuild */
time_t map_mtime; /* last database modification time */
- short map_specificity; /* specificity of alaases */
+ 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 */
};
@@ -659,6 +689,7 @@ MAP
# define MF_UNSAFEDB 0x00004000 /* this map is world writable */
# define MF_APPEND 0x00008000 /* append new entry on rebuiled */
# define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */
+# define MF_NODEFER 0x00020000 /* don't defer if map lookup fails */
/* indices for map_actions */
# define MA_NOTFOUND 0 /* member map returned "not found" */
@@ -695,6 +726,7 @@ MAPCLASS
/* functions */
extern char *map_rewrite __P((MAP *, char *, int, char **));
extern MAP *makemapentry __P((char *));
+extern void initmaps __P((bool, ENVELOPE *));
/*
** Symbol table definitions
*/
@@ -702,7 +734,8 @@ extern MAP *makemapentry __P((char *));
struct symtab
{
char *s_name; /* name to be entered */
- char s_type; /* general type (see below) */
+ short s_type; /* general type (see below) */
+ short s_len; /* length of this entry */
struct symtab *s_next; /* pointer to next in chain */
union
{
@@ -717,6 +750,7 @@ struct symtab
NAMECANON sv_namecanon; /* canonical name cache */
int sv_macro; /* macro name => id mapping */
int sv_ruleset; /* ruleset index */
+ char *sv_service[MAXMAPSTACK]; /* service switch */
} s_value;
};
@@ -734,6 +768,7 @@ typedef struct symtab STAB;
# 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_MCI 16 /* mailer connection info (offset) */
# define s_class s_value.sv_class
@@ -747,6 +782,7 @@ typedef struct symtab STAB;
# 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
extern STAB *stab __P((char *, int, int));
extern void stabapply __P((void (*)(STAB *, int), int));
@@ -802,12 +838,14 @@ EXTERN char OpMode; /* operation mode, see below */
#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 */
/* values for e_sendmode -- send modes */
#define SM_DELIVER 'i' /* interactive delivery */
@@ -841,6 +879,7 @@ EXTERN int QueueSortOrder;
#define QS_BYPRIORITY 0 /* sort by message priority */
#define QS_BYHOST 1 /* sort by first host name */
+#define QS_BYTIME 2 /* sort by submission time */
/* how to handle messages without any recipient addresses */
@@ -856,7 +895,7 @@ EXTERN int NoRecipientAction;
/* flags to putxline */
#define PXLF_NOTHINGSPECIAL 0 /* no special mapping */
#define PXLF_MAPFROM 0x0001 /* map From_ to >From_ */
-#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit *e
+#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit */
/*
** Additional definitions
*/
@@ -918,6 +957,9 @@ struct prival
/* flags that are actually specific to safefopen */
#define SFF_OPENASROOT 0x1000 /* open as root instead of real user */
+/* functions */
+extern int safefile __P((char *, UID_T, GID_T, char *, int, int, struct stat *));
+
/*
** Flags passed to mime8to7.
@@ -929,6 +971,15 @@ struct prival
/*
+** 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 */
+
+
+/*
** Regular UNIX sockaddrs are too small to handle ISO addresses, so
** we are forced to declare a supertype here.
*/
@@ -957,6 +1008,8 @@ union bigsockaddr
#define SOCKADDR union bigsockaddr
EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */
+
+extern char *hostnamebyanyaddr __P((SOCKADDR *));
extern char *anynet_ntoa __P((SOCKADDR *));
#endif
@@ -983,6 +1036,34 @@ extern char *anynet_ntoa __P((SOCKADDR *));
#define VENDOR_IBM 4 /* IBM specific config syntax */
EXTERN int VendorCode; /* vendor-specific operation enhancements */
+
+/* prototypes for vendor-specific hook routines */
+extern void vendor_set_uid __P((UID_T));
+extern void vendor_daemon_setup __P((ENVELOPE *));
+
+
+/*
+** 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 */
+};
+
+EXTERN struct termescape TermEscape;
+
+
+/*
+** Error return from inet_addr(3), in case not defined in /usr/include.
+*/
+
+#ifndef INADDR_NONE
+# define INADDR_NONE 0xffffffff
+#endif
/*
** Global variables.
*/
@@ -1005,6 +1086,7 @@ EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */
EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */
EXTERN bool SevenBitInput; /* force 7-bit data on input */
EXTERN bool HasEightBits; /* has at least one eight bit input byte */
+EXTERN bool ConfigFileRead; /* configuration file has been read */
EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */
EXTERN FILE *InChannel; /* input connection */
EXTERN FILE *OutChannel; /* output connection */
@@ -1014,7 +1096,7 @@ EXTERN gid_t RealGid; /* real gid of caller */
EXTERN uid_t DefUid; /* default uid to run as */
EXTERN gid_t DefGid; /* default gid to run as */
EXTERN char *DefUser; /* default user to run as (from DefUid) */
-EXTERN int OldUmask; /* umask when sendmail starts up */
+EXTERN MODE_T OldUmask; /* umask when sendmail starts up */
EXTERN int Errors; /* set if errors (local to single pass) */
EXTERN int ExitStat; /* exit status code */
EXTERN int LineNumber; /* line number in current input */
@@ -1061,11 +1143,11 @@ EXTERN char *ForwardPath; /* path to search for .forward files */
EXTERN long MinBlocksFree; /* min # of blocks free on queue fs */
EXTERN char *FallBackMX; /* fall back MX host */
EXTERN long MaxMessageSize; /* advertised max size we will accept */
-EXTERN time_t MaxHostStatAge; /* max age of cached host status info */
EXTERN time_t MinQueueAge; /* min delivery interval */
EXTERN time_t DialDelay; /* delay between dial-on-demand tries */
EXTERN char *SafeFileEnv; /* chroot location for file delivery */
EXTERN char *HostsFile; /* path to /etc/hosts file */
+EXTERN char *HostStatDir; /* location of host status information */
EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */
EXTERN int MaxChildren; /* maximum number of daemonic children */
EXTERN int CurChildren; /* current number of daemonic children */
@@ -1073,8 +1155,17 @@ EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */
EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */
EXTERN char *OperatorChars; /* operators (old $o macro) */
EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
+EXTERN int DefaultNotify; /* default DSN notification flags */
+EXTERN bool AllowBogusHELO; /* allow syntax errors on HELO command */
+EXTERN bool UserSubmission; /* initial (user) mail submission */
+EXTERN uid_t RunAsUid; /* UID to become for bulk of run */
+EXTERN gid_t RunAsGid; /* GID to become for bulk of run */
+EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */
+EXTERN bool UnsafeGroupWrites; /* group-writable files are unsafe */
EXTERN bool SingleLineFromHeader; /* force From: header to be one line */
+EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */
EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */
+EXTERN int MaxMacroRecursion; /* maximum depth of macro recursion */
EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */
EXTERN char *MustQuoteChars; /* quote these characters in phrases */
EXTERN char *ServiceSwitchFile; /* backup service switch */
@@ -1085,12 +1176,16 @@ EXTERN int CheckpointInterval; /* queue file checkpoint interval */
EXTERN bool DontPruneRoutes; /* don't prune source routes */
EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */
EXTERN int MaxMciCache; /* maximum entries in MCI cache */
+EXTERN time_t ServiceCacheTime; /* time service switch was cached */
+EXTERN time_t ServiceCacheMaxAge; /* refresh interval for cache */
EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */
EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */
EXTERN char *QueueLimitRecipient; /* limit queue runs to this recipient */
EXTERN char *QueueLimitSender; /* limit queue runs to this sender */
EXTERN char *QueueLimitId; /* limit queue runs to this id */
EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
+EXTERN char *DoubleBounceAddr; /* where to send double bounces */
+EXTERN char **ExternalEnviron; /* input environment */
EXTERN char *UserEnviron[MAXUSERENVIRON + 1];
/* saved user environment */
extern int errno;
@@ -1113,7 +1208,8 @@ EXTERN struct
time_t to_datafinal; /* DATA completion [10m] */
time_t to_nextcommand; /* next command [5m] */
/* following timeouts are not mentioned in RFC 1123 */
- time_t to_connect; /* initial connection timeout */
+ time_t to_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 */
@@ -1161,6 +1257,7 @@ EXTERN u_char tTdvect[100];
#define STRUCTCOPY(s, d) d = s
+
/*
** Declarations of useful functions
*/
@@ -1181,8 +1278,6 @@ extern void openxscript __P((ENVELOPE *));
extern void closexscript __P((ENVELOPE *));
extern char *shortenstring __P((const char *, int));
extern bool usershellok __P((char *, char *));
-extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
-extern char *hvalue __P((char *, HDR *));
extern char *defcharset __P((ENVELOPE *));
extern bool wordinclass __P((char *, int));
extern char *denlstring __P((char *, bool, bool));
@@ -1197,6 +1292,7 @@ extern void logsender __P((ENVELOPE *, char *));
extern void smtprset __P((MAILER *, MCI *, ENVELOPE *));
extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *));
extern void setuserenv __P((const char *, const char *));
+extern char *getextenv __P((const char *));
extern void disconnect __P((int, ENVELOPE *));
extern void putxline __P((char *, MCI *, int));
extern void dumpfd __P((int, bool, bool));
@@ -1208,15 +1304,66 @@ extern void inittimeouts __P((char *));
extern void logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
extern void giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
extern void buildfname __P((char *, char *, char *, int));
+extern void mci_setstat __P((MCI *, int, char *, char *));
+extern char *smtptodsn __P((int));
+extern int rscheck __P((char *, char *, char *, ENVELOPE *e));
+extern void mime7to8 __P((MCI *, HDR *, ENVELOPE *));
+extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));
+extern void xfclose __P((FILE *, char *, char *));
+extern int switch_map_find __P((char *, char *[], short []));
+extern void shorten_hostname __P((char []));
+extern int waitfor __P((pid_t));
+extern void proc_list_add __P((pid_t));
+extern void proc_list_drop __P((pid_t));
+extern void buffer_errors __P((void));
+extern void flush_errors __P((bool));
+extern void putline __P((char *, MCI *));
+extern void putxline __P((char *, MCI *, int));
+extern bool xtextok __P((char *));
+extern char *xtextify __P((char *, char *));
+extern char *xuntextify __P((char *));
+extern void cleanstrcpy __P((char *, char *, int));
+extern int getmxrr __P((char *, char **, bool, int *));
+extern int strtorwset __P((char *, char **, int));
+extern void printav __P((char **));
+extern void printopenfds __P((bool));
+extern int endmailer __P((MCI *, ENVELOPE *, char **));
+extern void fixcrlf __P((char *, bool));
+extern int dofork __P((void));
+extern void initsys __P((ENVELOPE *));
+extern void collect __P((FILE *, bool, bool, HDR **, ENVELOPE *));
+extern void stripquotes __P((char *));
+extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));
+extern void unlockqueue __P((ENVELOPE *));
+extern void xunlink __P((char *));
+extern void runqueue __P((bool));
+extern int getla __P((void));
+extern void sendall __P((ENVELOPE *, int));
+extern void queueup __P((ENVELOPE *, bool));
+extern void checkfds __P((char *));
+extern int returntosender __P((char *, ADDRESS *, int, ENVELOPE *));
+extern void markstats __P((ENVELOPE *, ADDRESS *));
+extern void poststats __P((char *));
+extern char *arpadate __P((char *));
+extern int mailfile __P((char *, ADDRESS *, int, ENVELOPE *));
+extern void loseqfile __P((ENVELOPE *, char *));
+extern int prog_open __P((char **, int *, ENVELOPE *));
+extern bool getcanonname __P((char *, int, bool));
+extern bool validate_connection __P((SOCKADDR *, char *, ENVELOPE *));
+extern bool path_is_dir __P((char *, bool));
+extern pid_t dowork __P((char *, bool, bool, ENVELOPE *));
extern const char *errstring __P((int));
extern sigfunc_t setsignal __P((int, sigfunc_t));
+extern int releasesignal __P((int));
extern struct hostent *sm_gethostbyname __P((char *));
extern struct hostent *sm_gethostbyaddr __P((char *, int, int));
extern struct passwd *sm_getpwnam __P((char *));
extern struct passwd *sm_getpwuid __P((UID_T));
+extern struct passwd *finduser __P((char *, bool *));
#ifdef XDEBUG
+extern void checkfdopen __P((int, char *));
extern void checkfd012 __P((char *));
#endif
@@ -1227,12 +1374,14 @@ extern void syserr(const char *, ...);
extern void usrerr(const char *, ...);
extern void message(const char *, ...);
extern void nmessage(const char *, ...);
+extern void setproctitle(const char *fmt, ...);
#else
extern void auth_warning();
extern void syserr();
extern void usrerr();
extern void message();
extern void nmessage();
+extern void setproctitle();
#endif
#if !HASSNPRINTF
diff --git a/usr.sbin/sendmail/src/sendmail.hf b/usr.sbin/sendmail/src/sendmail.hf
index 14db22c68ee5..add62c1ae6de 100644
--- a/usr.sbin/sendmail/src/sendmail.hf
+++ b/usr.sbin/sendmail/src/sendmail.hf
@@ -1,14 +1,14 @@
cpyr
-cpyr Copyright (c) 1983, 1995 Eric P. Allman
+cpyr Copyright (c) 1983, 1995, 1996 Eric P. Allman
cpyr Copyright (c) 1988, 1993
cpyr The Regents of the University of California. All rights reserved.
cpyr
-cpyr @(#)sendmail.hf 8.7 (Berkeley) 10/1/95
+cpyr @(#)sendmail.hf 8.11 (Berkeley) 9/11/96
cpyr
-smtp Commands:
+smtp Topics:
smtp HELO EHLO MAIL RCPT DATA
smtp RSET NOOP QUIT HELP VRFY
-smtp EXPN VERB
+smtp EXPN VERB ETRN DSN
smtp For more info use "HELP <topic>".
smtp To report bugs in the implementation send email to
smtp sendmail-bugs@sendmail.org.
@@ -19,10 +19,29 @@ helo HELO <hostname>
helo Introduce yourself.
ehlo EHLO <hostname>
ehlo Introduce yourself, and request extended SMTP mode.
-mail MAIL FROM: <sender>
-mail Specifies the sender.
-rcpt RCPT TO: <recipient>
+ehlo Possible replies include:
+ehlo SEND Send as mail [RFC821]
+ehlo SOML Send as mail or terminal [RFC821]
+ehlo SAML Send as mail and terminal [RFC821]
+ehlo EXPN Expand the mailing list [RFC821]
+ehlo HELP Supply helpful information [RFC821]
+ehlo TURN Turn the operation around [RFC821]
+ehlo 8BITMIME Use 8-bit data [RFC1652]
+ehlo SIZE Message size declaration [RFC1870]
+ehlo VERB Verbose [Allman]
+ehlo ONEX One message transaction only [Allman]
+ehlo CHUNKING Chunking [RFC1830]
+ehlo BINARYMIME Binary MIME [RFC1830]
+ehlo PIPELINING Command Pipelining [RFC1854]
+ehlo DSN Delivery Status Notification [RFC1891]
+ehlo ETRN Remote Message Queue Starting [RFC1985]
+ehlo XUSR Initial (user) submission [Allman]
+mail MAIL FROM: <sender> [ <parameters> ]
+mail Specifies the sender. Parameters are ESMTP extensions.
+mail See "HELP DSN" for details.
+rcpt RCPT TO: <recipient> [ <parameters> ]
rcpt Specifies the recipient. Can be used any number of times.
+rcpt Parameters are ESMTP extensions. See "HELP DSN" for details.
data DATA
data Following text is collected as the message.
data End with a single dot.
@@ -56,6 +75,20 @@ saml implementation.
turn TURN
turn Reverses the direction of the connection. Not currently
turn implemented.
+etrn ETRN [ <hostname> | @<domain> | #<queuename> ]
+etrn Run the queue for the specified <hostname>, or
+etrn all hosts within a given <domain>, or a specially-named
+etrn <queuename> (implementation-specific).
+dsn MAIL FROM: <sender> [ RET={ FULL | HDRS} ] [ ENVID=<envid> ]
+dsn RCPT TO: <recipient> [ NOTIFY={NEVER,SUCCESS,FAILURE,DELAY} ]
+dsn [ ORCPT=<recipient> ]
+dsn SMTP Delivery Status Notifications.
+dsn Descriptions:
+dsn RET Return either the full message or only headers.
+dsn ENVID Sender's "envelope identifier" for tracking.
+dsn NOTIFY When to send a DSN. Multiple options are OK, comma-
+dsn delimited. NEVER must appear by itself.
+dsn ORCPT Original recipient.
-bt Help for test mode:
-bt ? :this help message.
-bt .Dmvalue :define macro `m' to `value'.
@@ -76,3 +109,5 @@ turn implemented.
-bt flags for header recipients.
-bt /canon hostname :try to canonify hostname.
-bt /map mapname key :look up `key' in the indicated `mapname'.
+-bt rules addr :run the indicated address through the named rules.
+-bt Rules can be a comma separated list of rules.
diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c
index 69a4fbe35007..9c78859551d8 100644
--- a/usr.sbin/sendmail/src/srvrsmtp.c
+++ b/usr.sbin/sendmail/src/srvrsmtp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (with SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.125 (Berkeley) 11/8/96 (with SMTP)";
#else
-static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (without SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.125 (Berkeley) 11/8/96 (without SMTP)";
#endif
#endif /* not lint */
@@ -79,9 +79,11 @@ struct cmd
# 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 */
/* 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 */
/* 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 */
@@ -90,27 +92,27 @@ struct cmd
static struct cmd CmdTab[] =
{
- "mail", CMDMAIL,
- "rcpt", CMDRCPT,
- "data", CMDDATA,
- "rset", CMDRSET,
- "vrfy", CMDVRFY,
- "expn", CMDEXPN,
- "help", CMDHELP,
- "noop", CMDNOOP,
- "quit", CMDQUIT,
- "helo", CMDHELO,
- "ehlo", CMDEHLO,
- "verb", CMDVERB,
- "onex", CMDONEX,
- /*
- * remaining commands are here only
- * to trap and log attempts to use them
- */
- "showq", CMDDBGQSHOW,
- "debug", CMDDBGDEBUG,
- "wiz", CMDLOGBOGUS,
- NULL, CMDERROR,
+ { "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 },
+ /* remaining commands are here only to trap and log attempts to use them */
+ { "showq", CMDDBGQSHOW },
+ { "debug", CMDDBGDEBUG },
+ { "wiz", CMDLOGBOGUS },
+
+ { NULL, CMDERROR }
};
bool OneXact = FALSE; /* one xaction only this run */
@@ -122,7 +124,8 @@ static char *skipword();
#define MAXBADCOMMANDS 25 /* maximum number of bad commands */
void
-smtp(e)
+smtp(nullserver, e)
+ bool nullserver;
register ENVELOPE *volatile e;
{
register char *p;
@@ -141,10 +144,15 @@ smtp(e)
volatile int nrcpts = 0; /* number of RCPT commands */
bool doublequeue;
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 */
char inp[MAXLINE];
char cmdbuf[MAXLINE];
extern ENVELOPE BlankEnvelope;
extern void help __P((char *));
+ extern void settime __P((ENVELOPE *));
+ extern bool enoughdiskspace __P((long));
+ extern int runinchild __P((char *, ENVELOPE *));
if (fileno(OutChannel) != fileno(stdout))
{
@@ -253,6 +261,11 @@ smtp(e)
if (e->e_xfp != NULL)
fprintf(e->e_xfp, "<<< %s\n", inp);
+#ifdef LOG
+ if (LogLevel >= 15)
+ syslog(LOG_INFO, "<-- %s", inp);
+#endif
+
if (e->e_id == NULL)
setproctitle("%s: %.80s", CurSmtpClient, inp);
else
@@ -282,7 +295,20 @@ smtp(e)
/* reset errors */
errno = 0;
- /* process command */
+ /*
+ ** Process command.
+ **
+ ** If we are running as a null server, return 550
+ ** to everything.
+ */
+
+ if (nullserver && c->cmdcode != CMDQUIT)
+ {
+ message("550 Access denied");
+ continue;
+ }
+
+ /* non-null server */
switch (c->cmdcode)
{
case CMDHELO: /* hello -- introduce yourself */
@@ -299,7 +325,7 @@ smtp(e)
}
/* check for valid domain name (re 1123 5.2.5) */
- if (*p == '\0')
+ if (*p == '\0' && !AllowBogusHELO)
{
message("501 %s requires domain address",
cmdbuf);
@@ -325,11 +351,23 @@ smtp(e)
}
if (*q != '\0')
{
- message("501 Invalid domain name");
+ if (!AllowBogusHELO)
+ message("501 Invalid domain name");
+ else
+ message("250 %s Invalid domain name, accepting anyway",
+ MyHostName);
break;
}
}
+ /* check for duplicate HELO/EHLO per RFC 1651 4.2 */
+ if (gothello)
+ {
+ message("503 %s Duplicate HELO/EHLO",
+ MyHostName);
+ break;
+ }
+
sendinghost = newstr(p);
gothello = TRUE;
if (c->cmdcode != CMDEHLO)
@@ -344,7 +382,10 @@ smtp(e)
message("250-%s Hello %s, pleased to meet you",
MyHostName, CurSmtpClient);
if (!bitset(PRIV_NOEXPN, PrivacyFlags))
+ {
message("250-EXPN");
+ message("250-VERB");
+ }
#if MIME8TO7
message("250-8BITMIME");
#endif
@@ -356,8 +397,9 @@ smtp(e)
if (SendMIMEErrors)
message("250-DSN");
#endif
- message("250-VERB");
message("250-ONEX");
+ message("250-ETRN");
+ message("250-XUSR");
message("250 HELP");
break;
@@ -391,13 +433,17 @@ smtp(e)
finis();
}
+ p = skipword(p, "from");
+ if (p == NULL)
+ break;
+
/* fork a subprocess to process this command */
if (runinchild("SMTP-MAIL", e) > 0)
break;
if (!gothello)
{
auth_warning(e,
- "Host %s didn't use HELO protocol",
+ "%s didn't use HELO protocol",
CurSmtpClient);
}
#ifdef PICKY_HELO_CHECK
@@ -420,12 +466,10 @@ smtp(e)
setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
/* child -- go do the processing */
- p = skipword(p, "from");
- if (p == NULL)
- break;
if (setjmp(TopFrame) > 0)
{
/* this failed -- undo work */
+ undo_subproc:
if (InChild)
{
QuickAbort = FALSE;
@@ -440,9 +484,12 @@ smtp(e)
/* must parse sender first */
delimptr = NULL;
setsender(p, e, &delimptr, FALSE);
- p = delimptr;
- if (p != NULL && *p != '\0')
- *p++ = '\0';
+ if (delimptr != NULL && *delimptr != '\0')
+ *delimptr++ = '\0';
+
+ /* do config file checking of the sender */
+ if (rscheck("check_mail", p, NULL, e) != EX_OK)
+ goto undo_subproc;
/* check for possible spoofing */
if (RealUid != 0 && OpMode == MD_SMTP &&
@@ -456,6 +503,7 @@ smtp(e)
/* now parse ESMTP arguments */
e->e_msgsize = 0;
+ p = delimptr;
while (p != NULL && *p != '\0')
{
char *kp;
@@ -470,7 +518,7 @@ smtp(e)
kp = p;
/* skip to the value portion */
- while (isascii(*p) && isalnum(*p) || *p == '-')
+ while ((isascii(*p) && isalnum(*p)) || *p == '-')
p++;
if (*p == '=')
{
@@ -534,9 +582,15 @@ smtp(e)
a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e);
if (a == NULL)
break;
- p = delimptr;
+ if (delimptr != NULL && *delimptr != '\0')
+ *delimptr++ = '\0';
+
+ /* do config file checking of the recipient */
+ if (rscheck("check_rcpt", p, NULL, e) != EX_OK)
+ break;
/* now parse ESMTP arguments */
+ p = delimptr;
while (p != NULL && *p != '\0')
{
char *kp;
@@ -551,7 +605,7 @@ smtp(e)
kp = p;
/* skip to the value portion */
- while (isascii(*p) && isalnum(*p) || *p == '-')
+ while ((isascii(*p) && isalnum(*p)) || *p == '-')
p++;
if (*p == '=')
{
@@ -582,7 +636,7 @@ smtp(e)
break;
/* no errors during parsing, but might be a duplicate */
- e->e_to = p;
+ e->e_to = a->q_paddr;
if (!bitset(QBADADDR, a->q_flags))
{
message("250 Recipient ok%s",
@@ -698,7 +752,7 @@ smtp(e)
/* clean up a bit */
gotmail = FALSE;
- dropenvelope(e);
+ dropenvelope(e, TRUE);
CurEnv = e = newenvelope(e, CurEnv);
e->e_flags = BlankEnvelope.e_flags;
break;
@@ -714,12 +768,24 @@ smtp(e)
/* clean up a bit */
gotmail = FALSE;
- dropenvelope(e);
+ dropenvelope(e, TRUE);
CurEnv = e = newenvelope(e, CurEnv);
break;
case CMDVRFY: /* vrfy -- verify address */
case CMDEXPN: /* expn -- expand address */
+ if (++nverifies >= MAXBADCOMMANDS)
+ {
+#ifdef LOG
+ if (nverifies == MAXBADCOMMANDS &&
+ LogLevel > 5)
+ {
+ syslog(LOG_INFO, "%.100s: VRFY attack?",
+ CurSmtpClient);
+ }
+#endif
+ sleep(1);
+ }
vrfy = c->cmdcode == CMDVRFY;
if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
PrivacyFlags))
@@ -778,20 +844,47 @@ smtp(e)
}
while (vrfyqueue != NULL)
{
- extern void printvrfyaddr __P((ADDRESS *, bool));
+ extern void printvrfyaddr __P((ADDRESS *, bool, bool));
a = vrfyqueue;
while ((a = a->q_next) != NULL &&
bitset(QDONTSEND|QBADADDR, a->q_flags))
continue;
if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
- printvrfyaddr(vrfyqueue, a == NULL);
+ printvrfyaddr(vrfyqueue, a == NULL, vrfy);
vrfyqueue = vrfyqueue->q_next;
}
if (InChild)
finis();
break;
+ case CMDETRN: /* etrn -- force queue flush */
+ if (strlen(p) <= 0)
+ {
+ message("500 Parameter required");
+ break;
+ }
+
+ /* crude way to avoid denial-of-service attacks */
+ if (n_etrn++ >= 3)
+ sleep(3);
+ id = p;
+ if (*id == '@')
+ id++;
+ else
+ *--id = '@';
+#ifdef LOG
+ if (LogLevel > 5)
+ syslog(LOG_INFO, "%.100s: ETRN %s",
+ CurSmtpClient,
+ shortenstring(id, 203));
+#endif
+ QueueLimitRecipient = id;
+ runqueue(TRUE);
+ QueueLimitRecipient = NULL;
+ message("250 Queuing for node %s started", p);
+ break;
+
case CMDHELP: /* help -- give user info */
help(p);
break;
@@ -831,6 +924,11 @@ doquit:
message("250 Only one transaction");
break;
+ case CMDXUSR: /* initial (user) submission */
+ UserSubmission = TRUE;
+ message("250 Initial submission");
+ break;
+
# ifdef SMTPDEBUG
case CMDDBGQSHOW: /* show queues */
printf("Send Queue=");
@@ -1112,6 +1210,7 @@ rcpt_esmtp_args(a, kp, vp, e)
** Parameters:
** a -- the address to print
** last -- set if this is the last one.
+** vrfy -- set if this is a VRFY command.
**
** Returns:
** none.
@@ -1121,13 +1220,18 @@ rcpt_esmtp_args(a, kp, vp, e)
*/
void
-printvrfyaddr(a, last)
+printvrfyaddr(a, last, vrfy)
register ADDRESS *a;
bool last;
+ bool vrfy;
{
char fmtbuf[20];
- strcpy(fmtbuf, "250");
+ if (vrfy && a->q_mailer != NULL &&
+ !bitnset(M_VRFY250, a->q_mailer->m_flags))
+ strcpy(fmtbuf, "252");
+ else
+ strcpy(fmtbuf, "250");
fmtbuf[3] = last ? ' ' : '-';
if (a->q_fullname == NULL)
@@ -1166,10 +1270,20 @@ runinchild(label, e)
char *label;
register ENVELOPE *e;
{
- int childpid;
+ pid_t childpid;
+ sigfunc_t chldsig;
if (!OneXact)
{
+ /*
+ ** Disable child process reaping, in case ETRN has preceeded
+ ** MAIL command.
+ */
+
+#ifdef SIGCHLD
+ chldsig = setsignal(SIGCHLD, SIG_IGN);
+#endif
+
childpid = dofork();
if (childpid < 0)
{
@@ -1196,6 +1310,11 @@ runinchild(label, e)
finis();
}
+#ifdef SIGCHLD
+ /* restore the child signal */
+ (void) setsignal(SIGCHLD, chldsig);
+#endif
+
return (1);
}
else
diff --git a/usr.sbin/sendmail/src/stab.c b/usr.sbin/sendmail/src/stab.c
index cfb02c69686b..5f707b118581 100644
--- a/usr.sbin/sendmail/src/stab.c
+++ b/usr.sbin/sendmail/src/stab.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)stab.c 8.6 (Berkeley) 8/31/95";
+static char sccsid[] = "@(#)stab.c 8.9 (Berkeley) 10/17/96";
#endif /* not lint */
# include "sendmail.h"
@@ -71,6 +71,7 @@ stab(name, type, op)
register STAB **ps;
register int hfunc;
register char *p;
+ int len;
extern char lower();
if (tTd(36, 5))
@@ -129,11 +130,73 @@ stab(name, type, op)
if (tTd(36, 5))
printf("entered\n");
+ /* determine size of new entry */
+#ifdef FFR_MEMORY_MISER
+ if (type >= ST_MCI)
+ len = sizeof s->s_mci;
+ else
+ len = -1;
+ 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;
+
+ 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_SERVICE:
+ len = sizeof s->s_service;
+ break;
+ }
+ if (len < 0)
+ {
+ syserr("stab: unknown symbol type %d", type);
+ len = sizeof s->s_value;
+ }
+ len += sizeof *s - sizeof s->s_value;
+#else
+ len = sizeof *s;
+#endif
+
/* make new entry */
- s = (STAB *) xalloc(sizeof *s);
- bzero((char *) s, sizeof *s);
+ s = (STAB *) xalloc(len);
+ bzero((char *) s, len);
s->s_name = newstr(name);
s->s_type = type;
+ s->s_len = len;
/* link it in */
*ps = s;
diff --git a/usr.sbin/sendmail/src/stats.c b/usr.sbin/sendmail/src/stats.c
index f59885a60674..6d3aaedca4db 100644
--- a/usr.sbin/sendmail/src/stats.c
+++ b/usr.sbin/sendmail/src/stats.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)stats.c 8.5 (Berkeley) 5/28/95";
+static char sccsid[] = "@(#)stats.c 8.6 (Berkeley) 2/21/96";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/sysexits.c b/usr.sbin/sendmail/src/sysexits.c
index ad4f1e1cffb8..cc1022a14e7d 100644
--- a/usr.sbin/sendmail/src/sysexits.c
+++ b/usr.sbin/sendmail/src/sysexits.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)sysexits.c 8.5 (Berkeley) 5/24/95";
+static char sccsid[] = "@(#)sysexits.c 8.6 (Berkeley) 2/21/96";
#endif /* not lint */
#include <sendmail.h>
diff --git a/usr.sbin/sendmail/src/trace.c b/usr.sbin/sendmail/src/trace.c
index 9762cab18f59..380ecb565400 100644
--- a/usr.sbin/sendmail/src/trace.c
+++ b/usr.sbin/sendmail/src/trace.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)trace.c 8.4 (Berkeley) 5/28/95";
+static char sccsid[] = "@(#)trace.c 8.5 (Berkeley) 2/21/96";
#endif /* not lint */
# include "sendmail.h"
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
index e9834ebea082..075f197c8026 100644
--- a/usr.sbin/sendmail/src/udb.c
+++ b/usr.sbin/sendmail/src/udb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#if USERDB
-static char sccsid [] = "@(#)udb.c 8.33.1.2 (Berkeley) 9/16/96 (with USERDB)";
+static char sccsid [] = "@(#)udb.c 8.42 (Berkeley) 9/18/96 (with USERDB)";
#else
-static char sccsid [] = "@(#)udb.c 8.33.1.2 (Berkeley) 9/16/96 (without USERDB)";
+static char sccsid [] = "@(#)udb.c 8.42 (Berkeley) 9/18/96 (without USERDB)";
#endif
#endif
@@ -119,6 +119,8 @@ struct option
char *name;
char *val;
};
+
+extern int _udbx_init __P((void));
/*
** UDBEXPAND -- look up user in database and expand
**
@@ -159,7 +161,6 @@ udbexpand(a, sendq, aliaslevel, e)
int keylen;
int naddrs;
char keybuf[MAXKEY];
- char buf[BUFSIZ];
if (tTd(28, 1))
printf("udbexpand(%s)\n", a->q_paddr);
@@ -172,8 +173,6 @@ udbexpand(a, sendq, aliaslevel, e)
/* on first call, locate the database */
if (!UdbInitialized)
{
- extern int _udbx_init();
-
if (_udbx_init() == EX_TEMPFAIL)
return EX_TEMPFAIL;
}
@@ -187,7 +186,7 @@ udbexpand(a, sendq, aliaslevel, e)
return EX_OK;
/* if name is too long, assume it won't match */
- if (strlen(a->q_user) > sizeof keybuf - 12)
+ if (strlen(a->q_user) > (SIZE_T) sizeof keybuf - 12)
return EX_OK;
/* if name begins with a colon, it indicates our metadata */
@@ -203,6 +202,16 @@ udbexpand(a, sendq, aliaslevel, e)
for (up = UdbEnts; !breakout; up++)
{
char *user;
+ int usersize;
+ int userleft;
+ char userbuf[MEMCHUNKSIZE];
+#if defined(HESIOD) && defined(HES_GETMAILHOST)
+ char pobuf[MAXNAME];
+#endif
+
+ user = userbuf;
+ usersize = sizeof userbuf;
+ userleft = sizeof userbuf - 1;
/*
** Select action based on entry type.
@@ -227,17 +236,18 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 2))
printf("udbexpand: no match on %s (%d)\n",
keybuf, keylen);
- continue;
+ break;
}
if (tTd(28, 80))
printf("udbexpand: match %.*s: %.*s\n",
key.size, key.data, info.size, info.data);
- naddrs = 0;
a->q_flags &= ~QSELFREF;
while (i == 0 && key.size == keylen &&
bcmp(key.data, keybuf, keylen) == 0)
{
+ char *p;
+
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_flags |= QVERIFIED;
@@ -245,24 +255,26 @@ udbexpand(a, sendq, aliaslevel, e)
}
breakout = TRUE;
- if (info.size < sizeof buf)
- user = buf;
- else
- user = xalloc(info.size + 1);
+ if (info.size >= userleft - 1)
+ {
+ char *nuser = xalloc(usersize + MEMCHUNKSIZE);
+
+ bcopy(user, nuser, usersize);
+ if (user != userbuf)
+ free(user);
+ user = nuser;
+ usersize += MEMCHUNKSIZE;
+ userleft += MEMCHUNKSIZE;
+ }
+ p = &user[strlen(user)];
+ if (p != user)
+ {
+ *p++ = ',';
+ userleft--;
+ }
bcopy(info.data, user, info.size);
user[info.size] = '\0';
-
- message("expanded to %s", user);
-#ifdef LOG
- if (LogLevel >= 10)
- syslog(LOG_INFO, "%s: expand %.100s => %s",
- e->e_id, e->e_to,
- shortenstring(user, 203));
-#endif
- naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e);
-
- if (user != buf)
- free(user);
+ userleft -= info.size;
/* get the next record */
i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
@@ -270,8 +282,16 @@ udbexpand(a, sendq, aliaslevel, e)
/* if nothing ever matched, try next database */
if (!breakout)
- continue;
+ break;
+ message("expanded to %s", user);
+#ifdef LOG
+ if (LogLevel >= 10)
+ syslog(LOG_INFO, "%s: expand %.100s => %s",
+ e->e_id, e->e_to,
+ shortenstring(user, 203));
+#endif
+ naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
@@ -357,13 +377,24 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 2))
printf("hes_getmailhost(%s): %d\n",
a->q_user, hes_error());
- continue;
+ break;
}
+ if (strlen(hp->po_name) + strlen(hp->po_host) >
+ sizeof pobuf - 2)
+ {
+ if (tTd(28, 2))
+ printf("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
- continue;
+ break;
#endif
}
if (tTd(28, 80))
@@ -378,9 +409,7 @@ udbexpand(a, sendq, aliaslevel, e)
}
breakout = TRUE;
- if (info.size < sizeof buf)
- user = buf;
- else
+ if (info.size >= usersize)
user = xalloc(info.size + 1);
bcopy(info.data, user, info.size);
user[info.size] = '\0';
@@ -394,9 +423,6 @@ udbexpand(a, sendq, aliaslevel, e)
#endif
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
- if (user != buf)
- free(user);
-
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
@@ -428,17 +454,18 @@ udbexpand(a, sendq, aliaslevel, e)
case UDB_REMOTE:
/* not yet implemented */
- continue;
+ break;
case UDB_FORWARD:
if (bitset(EF_VRFYONLY, e->e_flags))
return EX_OK;
i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
- if (i < sizeof buf)
- user = buf;
- else
- user = xalloc(i + 1);
- (void) snprintf(user, i, "%s@%s",
+ 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;
@@ -452,19 +479,19 @@ udbexpand(a, sendq, aliaslevel, e)
}
a->q_flags |= QDONTSEND;
}
- if (user != buf)
- free(user);
breakout = TRUE;
break;
case UDB_EOLIST:
breakout = TRUE;
- continue;
+ break;
default:
/* unknown entry type */
- continue;
+ break;
}
+ if (user != userbuf)
+ free(user);
}
return EX_OK;
}
@@ -798,6 +825,7 @@ _udbx_init()
char *mxhosts[MAXMXHOSTS + 1];
# endif
struct option opts[MAXUDBOPTS + 1];
+ extern int _udb_parsespec __P((char *, struct option [], int));
while (*p == ' ' || *p == '\t' || *p == ',')
p++;
diff --git a/usr.sbin/sendmail/src/useful.h b/usr.sbin/sendmail/src/useful.h
index 8f9009ecf0b0..309a0df9db0f 100644
--- a/usr.sbin/sendmail/src/useful.h
+++ b/usr.sbin/sendmail/src/useful.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995 Eric P. Allman
+ * Copyright (c) 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)useful.h 8.4 (Berkeley) 4/21/95
+ * @(#)useful.h 8.5 (Berkeley) 2/21/96
*/
# include <sys/types.h>
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
index edfe7beb8d53..97248595532f 100644
--- a/usr.sbin/sendmail/src/usersmtp.c
+++ b/usr.sbin/sendmail/src/usersmtp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (with SMTP)";
#else
-static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.75 (Berkeley) 11/6/96 (without SMTP)";
#endif
#endif /* not lint */
@@ -64,6 +64,7 @@ int SmtpPid; /* pid of mailer */
bool SmtpNeedIntro; /* need "while talking" in transcript */
extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
+extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));
/*
** SMTPINIT -- initialize SMTP.
**
@@ -83,7 +84,7 @@ extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
void
smtpinit(m, mci, e)
- struct mailer *m;
+ MAILER *m;
register MCI *mci;
ENVELOPE *e;
{
@@ -142,8 +143,10 @@ smtpinit(m, mci, e)
SmtpPhase = mci->mci_phase = "client greeting";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
r = reply(m, mci, e, TimeOuts.to_initial, esmtp_check);
- if (r < 0 || REPLYTYPE(r) == 4)
+ if (r < 0)
goto tempfail1;
+ if (REPLYTYPE(r) == 4)
+ goto tempfail2;
if (REPLYTYPE(r) != 2)
goto unavailable;
@@ -152,11 +155,24 @@ smtpinit(m, mci, e)
** My mother taught me to always introduce myself.
*/
+#if FFR_LMTP
+ if (bitnset(M_ESMTP, m->m_flags) || bitnset(M_LMTP, m->m_flags))
+#else
if (bitnset(M_ESMTP, m->m_flags))
+#endif
mci->mci_flags |= MCIF_ESMTP;
tryhelo:
+#if FFR_LMTP
+ if (bitnset(M_LMTP, m->m_flags))
+ {
+ smtpmessage("LHLO %s", m, mci, MyHostName);
+ SmtpPhase = mci->mci_phase = "client LHLO";
+ }
+ else if (bitset(MCIF_ESMTP, mci->mci_flags))
+#else
if (bitset(MCIF_ESMTP, mci->mci_flags))
+#endif
{
smtpmessage("EHLO %s", m, mci, MyHostName);
SmtpPhase = mci->mci_phase = "client EHLO";
@@ -172,7 +188,12 @@ tryhelo:
goto tempfail1;
else if (REPLYTYPE(r) == 5)
{
+#if FFR_LMTP
+ if (bitset(MCIF_ESMTP, mci->mci_flags) &&
+ !bitnset(M_LMTP, m->m_flags))
+#else
if (bitset(MCIF_ESMTP, mci->mci_flags))
+#endif
{
/* try old SMTP instead */
mci->mci_flags &= ~MCIF_ESMTP;
@@ -181,7 +202,7 @@ tryhelo:
goto unavailable;
}
else if (REPLYTYPE(r) != 2)
- goto tempfail1;
+ goto tempfail2;
/*
** Check to see if we actually ended up talking to ourself.
@@ -193,11 +214,14 @@ tryhelo:
if (p != NULL)
*p = '\0';
if (!bitnset(M_NOLOOPCHECK, m->m_flags) &&
+#if FFR_LMTP
+ !bitnset(M_LMTP, m->m_flags) &&
+#endif
strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
{
syserr("553 %s config error: mail loops back to me (MX problem?)",
mci->mci_host);
- mci->mci_exitstat = EX_CONFIG;
+ mci_setstat(mci, EX_CONFIG, NULL, NULL);
mci->mci_errno = 0;
smtpquit(m, mci, e);
return;
@@ -214,7 +238,7 @@ tryhelo:
smtpmessage("VERB", m, mci);
r = reply(m, mci, e, TimeOuts.to_miscshort, NULL);
if (r < 0)
- goto tempfail2;
+ goto tempfail1;
}
if (mci->mci_state != MCIS_CLOSED)
@@ -226,17 +250,25 @@ tryhelo:
/* got a 421 error code during startup */
tempfail1:
+ if (mci->mci_errno == 0)
+ mci->mci_errno = errno;
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
+ if (mci->mci_state != MCIS_CLOSED)
+ smtpquit(m, mci, e);
+ return;
+
tempfail2:
- mci->mci_exitstat = EX_TEMPFAIL;
if (mci->mci_errno == 0)
mci->mci_errno = errno;
+ /* XXX should use code from other end iff ENHANCEDSTATUSCODES */
+ mci_setstat(mci, EX_TEMPFAIL, "4.5.0", SmtpReplyBuffer);
if (mci->mci_state != MCIS_CLOSED)
smtpquit(m, mci, e);
return;
unavailable:
- mci->mci_exitstat = EX_UNAVAILABLE;
mci->mci_errno = errno;
+ mci_setstat(mci, EX_UNAVAILABLE, "5.5.0", SmtpReplyBuffer);
smtpquit(m, mci, e);
return;
}
@@ -327,7 +359,7 @@ helo_options(line, firstline, m, mci, e)
int
smtpmailfrom(m, mci, e)
- struct mailer *m;
+ MAILER *m;
MCI *mci;
ENVELOPE *e;
{
@@ -383,14 +415,16 @@ smtpmailfrom(m, mci, e)
else if (!bitset(MM_PASS8BIT, MimeMode))
{
/* cannot just send a 8-bit version */
+ extern char MsgBuf[];
+
usrerr("%s does not support 8BITMIME", mci->mci_host);
- mci->mci_status = "5.6.3";
+ mci_setstat(mci, EX_DATAERR, "5.6.3", MsgBuf);
return EX_DATAERR;
}
if (bitset(MCIF_DSN, mci->mci_flags))
{
- if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) l)
+ if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) (l - 7))
{
strcat(optbuf, " ENVID=");
strcat(optbuf, e->e_envid);
@@ -444,16 +478,24 @@ smtpmailfrom(m, mci, e)
SmtpPhase = mci->mci_phase = "client MAIL";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
r = reply(m, mci, e, TimeOuts.to_mail, NULL);
- if (r < 0 || r == 421)
+ if (r < 0)
{
- /* communications failure/service shutting down */
- mci->mci_exitstat = EX_TEMPFAIL;
+ /* 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, "4.5.0", SmtpReplyBuffer);
smtpquit(m, mci, e);
return EX_TEMPFAIL;
}
else if (REPLYTYPE(r) == 4)
{
+ mci_setstat(mci, EX_TEMPFAIL, smtptodsn(r), SmtpReplyBuffer);
return EX_TEMPFAIL;
}
else if (REPLYTYPE(r) == 2)
@@ -463,24 +505,25 @@ smtpmailfrom(m, mci, e)
else if (r == 501)
{
/* syntax error in arguments */
- mci->mci_status = "5.5.2";
+ mci_setstat(mci, EX_DATAERR, "5.5.2", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 553)
{
/* mailbox name not allowed */
- mci->mci_status = "5.1.3";
+ mci_setstat(mci, EX_DATAERR, "5.1.3", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 552)
{
/* exceeded storage allocation */
- mci->mci_status = "5.2.2";
+ mci_setstat(mci, EX_UNAVAILABLE, "5.2.2", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
else if (REPLYTYPE(r) == 5)
{
/* unknown error */
+ mci_setstat(mci, EX_UNAVAILABLE, "5.0.0", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
@@ -494,6 +537,7 @@ smtpmailfrom(m, mci, e)
#endif
/* protocol error -- close up */
+ mci_setstat(mci, EX_PROTOCOL, "5.5.1", SmtpReplyBuffer);
smtpquit(m, mci, e);
return EX_PROTOCOL;
}
@@ -523,7 +567,6 @@ smtprcpt(to, m, mci, e)
register int r;
int l;
char optbuf[MAXLINE];
- extern char *smtptodsn();
strcpy(optbuf, "");
l = sizeof optbuf - 1;
@@ -531,7 +574,8 @@ smtprcpt(to, m, mci, e)
{
/* NOTIFY= parameter */
if (bitset(QHASNOTIFY, to->q_flags) &&
- bitset(QPRIMARY, to->q_flags))
+ bitset(QPRIMARY, to->q_flags) &&
+ !bitnset(M_LOCALMAILER, m->m_flags))
{
bool firstone = TRUE;
@@ -581,10 +625,25 @@ smtprcpt(to, m, mci, e)
return EX_TEMPFAIL;
else if (REPLYTYPE(r) == 2)
return EX_OK;
- else if (r == 550 || r == 551 || r == 553)
+ else if (r == 550)
+ {
+ to->q_status = "5.1.1";
+ return EX_NOUSER;
+ }
+ else if (r == 551)
+ {
+ to->q_status = "5.1.6";
+ return EX_NOUSER;
+ }
+ else if (r == 553)
+ {
+ to->q_status = "5.1.3";
return EX_NOUSER;
+ }
else if (REPLYTYPE(r) == 5)
+ {
return EX_UNAVAILABLE;
+ }
#ifdef LOG
if (LogLevel > 1)
@@ -602,6 +661,7 @@ smtprcpt(to, m, mci, e)
**
** Parameters:
** m -- mailer being sent to.
+** mci -- the mailer connection information.
** e -- the envelope for this message.
**
** Returns:
@@ -616,12 +676,13 @@ static void datatimeout();
int
smtpdata(m, mci, e)
- struct mailer *m;
+ MAILER *m;
register MCI *mci;
register ENVELOPE *e;
{
register int r;
register EVENT *ev;
+ int rstat;
time_t timeout;
/*
@@ -670,8 +731,8 @@ smtpdata(m, mci, e)
if (setjmp(CtxDataTimeout) != 0)
{
mci->mci_errno = errno;
- mci->mci_exitstat = EX_TEMPFAIL;
mci->mci_state = MCIS_ERROR;
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", NULL);
syserr("451 timeout writing message to %s", mci->mci_host);
smtpquit(m, mci, e);
return EX_TEMPFAIL;
@@ -700,8 +761,8 @@ smtpdata(m, mci, e)
{
/* error during processing -- don't send the dot */
mci->mci_errno = EIO;
- mci->mci_exitstat = EX_IOERR;
mci->mci_state = MCIS_ERROR;
+ mci_setstat(mci, EX_IOERR, "4.4.2", NULL);
smtpquit(m, mci, e);
return EX_IOERR;
}
@@ -714,8 +775,12 @@ smtpdata(m, mci, e)
nmessage(">>> .");
/* check for the results of the transaction */
- SmtpPhase = mci->mci_phase = "client DATA 250";
+ SmtpPhase = mci->mci_phase = "client DATA status";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
+#if FFR_LMTP
+ if (bitnset(M_LMTP, m->m_flags))
+ return EX_OK;
+#endif
r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
if (r < 0)
{
@@ -723,15 +788,22 @@ smtpdata(m, mci, e)
return EX_TEMPFAIL;
}
mci->mci_state = MCIS_OPEN;
- e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
if (REPLYTYPE(r) == 4)
- return EX_TEMPFAIL;
+ rstat = EX_TEMPFAIL;
else if (REPLYCLASS(r) != 5)
- /* fall through */ ;
+ rstat = EX_PROTOCOL;
else if (REPLYTYPE(r) == 2)
- return EX_OK;
+ rstat = EX_OK;
else if (REPLYTYPE(r) == 5)
- return EX_UNAVAILABLE;
+ rstat = EX_UNAVAILABLE;
+ else
+ rstat = EX_PROTOCOL;
+ mci_setstat(mci, rstat, smtptodsn(r), SmtpReplyBuffer);
+ if (e->e_statmsg != NULL)
+ free(e->e_statmsg);
+ e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+ if (rstat != EX_PROTOCOL)
+ return rstat;
#ifdef LOG
if (LogLevel > 1)
{
@@ -740,7 +812,7 @@ smtpdata(m, mci, e)
shortenstring(SmtpReplyBuffer, 403));
}
#endif
- return EX_PROTOCOL;
+ return rstat;
}
@@ -750,10 +822,66 @@ datatimeout()
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.
+*/
+
+#if FFR_LMTP
+
+int
+smtpgetstat(m, mci, e)
+ MAILER *m;
+ MCI *mci;
+ ENVELOPE *e;
+{
+ int r;
+ int stat;
+
+ /* check for the results of the transaction */
+ r = reply(m, mci, e, TimeOuts.to_datafinal, NULL);
+ if (r < 0)
+ {
+ smtpquit(m, mci, e);
+ return EX_TEMPFAIL;
+ }
+ if (e->e_statmsg != NULL)
+ free(e->e_statmsg);
+ e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
+ if (REPLYTYPE(r) == 4)
+ stat = EX_TEMPFAIL;
+ else if (REPLYCLASS(r) != 5)
+ stat = EX_PROTOCOL;
+ else if (REPLYTYPE(r) == 2)
+ stat = EX_OK;
+ else if (REPLYTYPE(r) == 5)
+ stat = EX_UNAVAILABLE;
+ mci_setstat(mci, stat, smtptodsn(r), SmtpReplyBuffer);
+#ifdef LOG
+ if (LogLevel > 1 && stat == EX_PROTOCOL)
+ {
+ syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-3 protocol error: %s",
+ e->e_id, mci->mci_host,
+ shortenstring(SmtpReplyBuffer, 403));
+ }
+#endif
+ return stat;
+}
+
+#endif
+ /*
** SMTPQUIT -- close the SMTP connection.
**
** Parameters:
** m -- a pointer to the mailer.
+** mci -- the mailer connection information.
+** e -- the current envelope.
**
** Returns:
** none.
@@ -906,6 +1034,7 @@ reply(m, mci, e, timeout, pfunc)
if (p == NULL)
{
bool oldholderrs;
+ extern char MsgBuf[];
/* if the remote end closed early, fake an error */
if (errno == 0)
@@ -916,10 +1045,10 @@ reply(m, mci, e, timeout, pfunc)
# endif /* ECONNRESET */
mci->mci_errno = errno;
- mci->mci_exitstat = EX_TEMPFAIL;
oldholderrs = HoldErrs;
HoldErrs = TRUE;
usrerr("451 reply: read error from %s", mci->mci_host);
+ mci_setstat(mci, EX_TEMPFAIL, "4.4.2", MsgBuf);
/* if debugging, pause so we can see state */
if (tTd(18, 100))
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c
index 7abc67176cb4..c3eb822744b3 100644
--- a/usr.sbin/sendmail/src/util.c
+++ b/usr.sbin/sendmail/src/util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1983, 1995 Eric P. Allman
+ * Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)util.c 8.84.1.4 (Berkeley) 9/16/96";
+static char sccsid[] = "@(#)util.c 8.109 (Berkeley) 11/16/96";
#endif /* not lint */
# include "sendmail.h"
@@ -260,50 +260,71 @@ xputs(s)
{
register int c;
register struct metamac *mp;
+ bool shiftout = FALSE;
extern struct metamac MetaMacros[];
if (s == NULL)
{
- printf("<null>");
+ printf("%s<null>%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)
{
- putchar('$');
- continue;
+ printf("%s$", TermEscape.te_rv_on);
+ shiftout = TRUE;
+ if (*s == '\0')
+ continue;
+ c = *s++ & 0377;
+ goto printchar;
}
if (c == MACROEXPAND)
{
- putchar('$');
+ printf("%s$", TermEscape.te_rv_on);
+ shiftout = TRUE;
if (strchr("=~&?", *s) != NULL)
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("$%c", mp->metaname);
+ printf("%s$%c",
+ TermEscape.te_rv_on,
+ mp->metaname);
+ shiftout = TRUE;
break;
}
}
if (c == MATCHCLASS || c == MATCHNCLASS)
{
- if (!bitset(0200, *s))
- continue;
- printf("{%s}", macname(*s++ & 0377));
+ if (bitset(0200, *s))
+ printf("{%s}", macname(*s++ & 0377));
+ else
+ printf("%c", *s++);
}
if (mp->metaname != '\0')
continue;
- (void) putchar('\\');
+
+ /* unrecognized meta character */
+ printf("%sM-", TermEscape.te_rv_on);
+ shiftout = TRUE;
c &= 0177;
}
+ printchar:
if (isprint(c))
{
putchar(c);
@@ -324,15 +345,25 @@ xputs(s)
case '\t':
c = 't';
break;
-
- default:
+ }
+ 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);
- continue;
}
- (void) putchar('\\');
- (void) putchar(c);
}
+ if (shiftout)
+ printf("%s", TermEscape.te_rv_off);
(void) fflush(stdout);
}
/*
@@ -397,27 +428,18 @@ buildfname(gecos, login, buf, buflen)
if (*gecos == '*')
gecos++;
- /* find length of final string */
- l = 0;
- for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
- {
- if (*p == '&')
- l += strlen(login);
- else
- l++;
- }
- if (l > buflen - 1)
- {
- /* not a good sign */
- snprintf(buf, buflen, "%s", gecos);
- return;
- }
-
- /* now fill in buf */
+ /* 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", login);
+ return;
+ }
if (*p == '&')
{
+ /* interpolate full name */
snprintf(bp, buflen - (bp - buf), "%s", login);
*bp = toupper(*bp);
bp += strlen(bp);
@@ -470,8 +492,8 @@ buildfname(gecos, login, buf, buflen)
int
safefile(fn, uid, gid, uname, flags, mode, st)
char *fn;
- uid_t uid;
- gid_t gid;
+ UID_T uid;
+ GID_T gid;
char *uname;
int flags;
int mode;
@@ -552,7 +574,7 @@ safefile(fn, uid, gid, uname, flags, mode, st)
bitset(S_IXGRP, stbuf.st_mode))
continue;
#ifndef NO_GROUP_SET
- if (uname != NULL &&
+ if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
(gr = getgrgid(stbuf.st_gid)) != NULL))
{
@@ -651,7 +673,7 @@ safefile(fn, uid, gid, uname, flags, mode, st)
if (st->st_gid == gid)
;
#ifndef NO_GROUP_SET
- else if (uname != NULL &&
+ else if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == st->st_gid) ||
(gr = getgrgid(st->st_gid)) != NULL))
{
@@ -815,12 +837,12 @@ struct omodes
char *farg;
} OpenModes[] =
{
- O_ACCMODE, O_RDONLY, "r",
- O_ACCMODE|O_APPEND, O_WRONLY, "w",
- O_ACCMODE|O_APPEND, O_WRONLY|O_APPEND, "a",
- O_TRUNC, 0, "w+",
- O_APPEND, O_APPEND, "a+",
- 0, 0, "r+",
+ { O_ACCMODE, O_RDONLY, "r" },
+ { O_ACCMODE|O_APPEND, O_WRONLY, "w" },
+ { O_ACCMODE|O_APPEND, O_WRONLY|O_APPEND, "a" },
+ { O_TRUNC, 0, "w+" },
+ { O_APPEND, O_APPEND, "a+" },
+ { 0, 0, "r+" },
};
FILE *
@@ -990,6 +1012,15 @@ putxline(l, mci, pxflags)
if (TrafficLogFile != NULL)
(void) putc('.', TrafficLogFile);
}
+ else if (l[0] == 'F' && slop == 0 &&
+ bitset(PXLF_MAPFROM, pxflags) &&
+ strncmp(l, "From ", 5) == 0 &&
+ bitnset(M_ESCFROM, mci->mci_mailer->m_flags))
+ {
+ (void) putc('>', mci->mci_out);
+ if (TrafficLogFile != NULL)
+ (void) putc('>', TrafficLogFile);
+ }
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%.*s\n", p - l, l);
for ( ; l < p; ++l)
@@ -1109,9 +1140,11 @@ sfgets(buf, siz, fp, timeout, during)
if (setjmp(CtxReadTimeout) != 0)
{
# ifdef LOG
- syslog(LOG_NOTICE,
- "timeout waiting for input from %.100s during %s",
- CurHostName? CurHostName: "local", during);
+ if (LogLevel > 1)
+ syslog(LOG_NOTICE,
+ "timeout waiting for input from %.100s during %s",
+ CurHostName ? CurHostName : "local",
+ during);
# endif
errno = 0;
usrerr("451 timeout waiting for input during %s",
@@ -1339,19 +1372,21 @@ atooct(s)
int
waitfor(pid)
- int pid;
+ pid_t pid;
{
#ifdef WAITUNION
union wait st;
#else
auto int st;
#endif
- int i;
+ pid_t i;
do
{
errno = 0;
i = wait(&st);
+ if (i > 0)
+ proc_list_drop(i);
} while ((i >= 0 || errno == EINTR) && i != pid);
if (i < 0)
return -1;
@@ -1470,7 +1505,7 @@ checkfd012(where)
for (i = 0; i < 3; i++)
{
- if (fstat(i, &stbuf) < 0 && errno != EOPNOTSUPP)
+ if (fstat(i, &stbuf) < 0 && errno == EBADF)
{
/* oops.... */
int fd;
@@ -1487,6 +1522,90 @@ checkfd012(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
+}
+ /*
+** 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 BITMAP 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)
+ {
+ syslog(LOG_DEBUG, "%s: changed fds:", where);
+ printhdr = FALSE;
+ }
+ dumpfd(fd, TRUE, TRUE);
+ }
+ errno = save_errno;
+}
+ /*
** PRINTOPENFDS -- print the open file descriptors (for debugging)
**
** Parameters:
@@ -1542,12 +1661,17 @@ dumpfd(fd, printclosed, logit)
if (fstat(fd, &st) < 0)
{
- if (printclosed || errno != EBADF)
+ 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;
}
@@ -1812,8 +1936,10 @@ prog_open(argv, pfd, e)
/* run as default user */
endpwent();
- setgid(DefGid);
- setuid(DefUid);
+ if (setgid(DefGid) < 0)
+ syserr("prog_open: setgid(%ld) failed", (long) DefGid);
+ if (setuid(DefUid) < 0)
+ syserr("prog_open: setuid(%ld) failed", (long) DefUid);
/* run in some directory */
if (ProgMailer != NULL)
@@ -1856,6 +1982,7 @@ prog_open(argv, pfd, e)
if (transienterror(saveerrno))
_exit(EX_OSERR);
_exit(EX_CONFIG);
+ return -1; /* avoid compiler warning on IRIX */
}
/*
** GET_COLUMN -- look up a Column in a line buffer
@@ -1904,7 +2031,7 @@ get_column(line, col, delim, buf, buflen)
if (col == 0 && delim == '\0')
{
- while (*begin && isspace(*begin))
+ while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
@@ -1915,14 +2042,14 @@ get_column(line, col, delim, buf, buflen)
begin++;
if (delim == '\0')
{
- while (*begin && isspace(*begin))
+ while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
}
end = strpbrk(begin, delimbuf);
if (end == NULL)
- i = strlen(buf);
+ i = strlen(begin);
else
i = end - begin;
if (i >= buflen)
@@ -2022,3 +2149,159 @@ denlstring(s, strict, logattacks)
return bp;
}
+ /*
+** PATH_IS_DIR -- check to see if file exists and is a directory.
+**
+** 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 (stat(pathname, &statbuf) < 0)
+ {
+ 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;
+ }
+ return TRUE;
+}
+ /*
+** PROC_LIST_ADD -- add process id to list of our children
+**
+** Parameters:
+** pid -- pid to add to list.
+**
+** Returns:
+** none
+*/
+
+static pid_t *ProcListVec = NULL;
+static int ProcListSize = 0;
+
+#define NO_PID ((pid_t) 0)
+#ifndef PROC_LIST_SEG
+# define PROC_LIST_SEG 32 /* number of pids to alloc at a time */
+#endif
+
+void
+proc_list_add(pid)
+ pid_t pid;
+{
+ int i;
+ extern void proc_list_probe __P((void));
+
+ for (i = 0; i < ProcListSize; i++)
+ {
+ if (ProcListVec[i] == 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] == NO_PID)
+ break;
+ }
+ }
+ if (i >= ProcListSize)
+ {
+ /* grow process list */
+ pid_t *npv;
+
+ npv = (pid_t *) xalloc(sizeof (pid_t) * (ProcListSize + PROC_LIST_SEG));
+ if (ProcListSize > 0)
+ {
+ bcopy(ProcListVec, npv, ProcListSize * sizeof (pid_t));
+ free(ProcListVec);
+ }
+ for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++)
+ npv[i] = NO_PID;
+ i = ProcListSize;
+ ProcListSize += PROC_LIST_SEG;
+ ProcListVec = npv;
+ }
+ ProcListVec[i] = pid;
+ CurChildren++;
+}
+ /*
+** PROC_LIST_DROP -- drop pid from process list
+**
+** Parameters:
+** pid -- pid to drop
+**
+** Returns:
+** none.
+*/
+
+void
+proc_list_drop(pid)
+ pid_t pid;
+{
+ int i;
+
+ for (i = 0; i < ProcListSize; i++)
+ {
+ if (ProcListVec[i] == pid)
+ {
+ ProcListVec[i] = NO_PID;
+ break;
+ }
+ }
+ if (CurChildren > 0)
+ CurChildren--;
+}
+ /*
+** PROC_LIST_PROBE -- probe processes in the list to see if they still exist
+**
+** Parameters:
+** none
+**
+** Returns:
+** none
+*/
+
+void
+proc_list_probe()
+{
+ int i;
+
+ for (i = 0; i < ProcListSize; i++)
+ {
+ if (ProcListVec[i] == NO_PID)
+ continue;
+ if (kill(ProcListVec[i], 0) < 0)
+ {
+#ifdef LOG
+ if (LogLevel > 3)
+ syslog(LOG_DEBUG, "proc_list_probe: lost pid %d",
+ ProcListVec[i]);
+#endif
+ ProcListVec[i] = NO_PID;
+ CurChildren--;
+ }
+ }
+ if (CurChildren < 0)
+ CurChildren = 0;
+}
diff --git a/usr.sbin/sendmail/src/version.c b/usr.sbin/sendmail/src/version.c
index 6197db912f97..8a53f2967ef7 100644
--- a/usr.sbin/sendmail/src/version.c
+++ b/usr.sbin/sendmail/src/version.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)version.c 8.7.6.4 (Berkeley) 9/17/96";
+static char sccsid[] = "@(#)version.c 8.8.3.2 (Berkeley) 11/16/96";
#endif /* not lint */
-char Version[] = "8.7.6";
+char Version[] = "8.8.3";