aboutsummaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src')
-rw-r--r--usr.sbin/sendmail/src/Makefile15
-rw-r--r--usr.sbin/sendmail/src/Makefile.AIX99
-rw-r--r--usr.sbin/sendmail/src/Makefile.HPUX107
-rw-r--r--usr.sbin/sendmail/src/Makefile.IRIX101
-rw-r--r--usr.sbin/sendmail/src/Makefile.OSF199
-rw-r--r--usr.sbin/sendmail/src/Makefile.Solaris103
-rw-r--r--usr.sbin/sendmail/src/Makefile.SunOS36
-rw-r--r--usr.sbin/sendmail/src/Makefile.ULTRIX34
-rw-r--r--usr.sbin/sendmail/src/Makefile.Utah42
-rw-r--r--usr.sbin/sendmail/src/Makefile.dist56
-rw-r--r--usr.sbin/sendmail/src/READ_ME773
-rw-r--r--usr.sbin/sendmail/src/TRACEFLAGS5
-rw-r--r--usr.sbin/sendmail/src/alias.c175
-rw-r--r--usr.sbin/sendmail/src/aliases3
-rw-r--r--usr.sbin/sendmail/src/aliases.56
-rw-r--r--usr.sbin/sendmail/src/cdefs.h66
-rw-r--r--usr.sbin/sendmail/src/clock.c62
-rw-r--r--usr.sbin/sendmail/src/collect.c65
-rw-r--r--usr.sbin/sendmail/src/conf.c1239
-rw-r--r--usr.sbin/sendmail/src/conf.h933
-rw-r--r--usr.sbin/sendmail/src/daemon.c292
-rw-r--r--usr.sbin/sendmail/src/deliver.c814
-rw-r--r--usr.sbin/sendmail/src/domain.c269
-rw-r--r--usr.sbin/sendmail/src/envelope.c182
-rw-r--r--usr.sbin/sendmail/src/err.c166
-rw-r--r--usr.sbin/sendmail/src/headers.c350
-rw-r--r--usr.sbin/sendmail/src/macro.c18
-rw-r--r--usr.sbin/sendmail/src/mailq.188
-rw-r--r--usr.sbin/sendmail/src/main.c659
-rwxr-xr-xusr.sbin/sendmail/src/makesendmail113
-rw-r--r--usr.sbin/sendmail/src/map.c241
-rw-r--r--usr.sbin/sendmail/src/mci.c99
-rw-r--r--usr.sbin/sendmail/src/newaliases.123
-rw-r--r--usr.sbin/sendmail/src/parseaddr.c427
-rw-r--r--usr.sbin/sendmail/src/pathnames.h6
-rw-r--r--usr.sbin/sendmail/src/queue.c296
-rw-r--r--usr.sbin/sendmail/src/readcf.c204
-rw-r--r--usr.sbin/sendmail/src/recipient.c460
-rw-r--r--usr.sbin/sendmail/src/savemail.c230
-rw-r--r--usr.sbin/sendmail/src/sendmail.814
-rw-r--r--usr.sbin/sendmail/src/sendmail.h194
-rw-r--r--usr.sbin/sendmail/src/sendmail.hf5
-rw-r--r--usr.sbin/sendmail/src/srvrsmtp.c183
-rw-r--r--usr.sbin/sendmail/src/stats.c5
-rw-r--r--usr.sbin/sendmail/src/trace.c6
-rw-r--r--usr.sbin/sendmail/src/udb.c54
-rw-r--r--usr.sbin/sendmail/src/useful.h10
-rw-r--r--usr.sbin/sendmail/src/usersmtp.c103
-rw-r--r--usr.sbin/sendmail/src/util.c433
-rw-r--r--usr.sbin/sendmail/src/version.c4
50 files changed, 7055 insertions, 2912 deletions
diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile
index f49a5b3e03c1..3cdf3ba7d23e 100644
--- a/usr.sbin/sendmail/src/Makefile
+++ b/usr.sbin/sendmail/src/Makefile
@@ -1,4 +1,7 @@
-# @(#)Makefile 8.1 (Berkeley) 6/7/93
+#
+# Makefile for FreeBSD
+#
+# @(#)Makefile.FreeBSD 8.1 (Berkeley) 2/26/94
PROG= sendmail
@@ -12,16 +15,16 @@ PROG= sendmail
# spiral snail, but it will work.
DBMDEF= -DNEWDB
-CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO -DNO_SYSCONF
+CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO -DMIME -DUSEUNAME
SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
util.c version.c
-DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
-LDADD= ${LIBUTIL}
-MAN1= newaliases.1
+DPADD=
+LDADD= -lutil
+MAN1= mailq.1 newaliases.1
MAN5= aliases.5
MAN8= sendmail.8
LINKS= /usr/sbin/sendmail /usr/bin/newaliases \
@@ -34,7 +37,7 @@ BINMODE=6555
beforeinstall:
# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
# ${DESTDIR}/etc/sendmail.fc
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+ install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
${DESTDIR}/var/log/sendmail.st
install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
${DESTDIR}/usr/share/misc
diff --git a/usr.sbin/sendmail/src/Makefile.AIX b/usr.sbin/sendmail/src/Makefile.AIX
deleted file mode 100644
index d676e02a5869..000000000000
--- a/usr.sbin/sendmail/src/Makefile.AIX
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# This Makefile is designed to work on the old "make" program. It does
-# not use the obj subdirectory. It also does not install documentation
-# automatically -- think of it as a quick start for sites that have the
-# old make program (I recommend that you get and port the new make if you
-# are going to be doing any signficant work on sendmail).
-#
-# This has been tested on Ultrix.
-#
-# @(#)Makefile.dist 6.5 (Berkeley) 2/26/93
-#
-
-# use O=-O (usual) or O=-g (debugging)
-O= -g
-
-# define the database mechanism used for alias lookups:
-# -DNDBM -- use new DBM
-# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
-#
-DBMDEF= -DNEWDB
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
-
-# define UNSETENV if you need to compile in a local version of setenv
-ENVDEF= -D_AIX3
-
-# see also conf.h for additional compilation flags
-
-# include directories
-#INCDIRS=-I/usr/sww/include/db
-
-# library directories
-#LIBDIRS=-L/usr/sww/lib
-
-# libraries required on your system
-LIBS= -ldbm -ldb
-
-# location of sendmail binary (usually /usr/sbin or /usr/lib)
-BINDIR= ${DESTDIR}/usr/sbin
-
-# location of sendmail.st file (usually /var/log or /usr/lib)
-STDIR= ${DESTDIR}/var/log
-
-# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
-HFDIR= ${DESTDIR}/usr/share/misc
-
-################### end of user configuration flags ######################
-
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
-
-OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
- deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
- map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
- savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
-
-LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
-
-aliases.0: aliases.5
- nroff -h -mandoc aliases.5 > aliases.0
-
-newaliases.0: newaliases.1
- nroff -h -mandoc newaliases.1 > newaliases.0
-
-sendmail.0: sendmail.8
- nroff -h -mandoc sendmail.8 > sendmail.0
-
-install: install-sendmail install-docs
-
-install-sendmail: sendmail
- install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${STDIR}/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
-
-# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
-
-clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
-
-# dependencies
-# gross overkill, and yet still not quite enough....
-${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.HPUX b/usr.sbin/sendmail/src/Makefile.HPUX
deleted file mode 100644
index 7394b15bbe8e..000000000000
--- a/usr.sbin/sendmail/src/Makefile.HPUX
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# This Makefile is designed to work on the old "make" program. It does
-# not use the obj subdirectory. It also does not install documentation
-# automatically -- think of it as a quick start for sites that have the
-# old make program (I recommend that you get and port the new make if you
-# are going to be doing any signficant work on sendmail).
-#
-# This has been tested on Ultrix.
-#
-# @(#)Makefile.dist 6.5 (Berkeley) 2/26/93
-#
-
-# use O=-O (usual) or O=-g (debugging)
-# +O is OK on 7xx, and 300xx at 9.0
-O= +O1
-
-# define the database mechanism used for alias lookups:
-# -DNDBM -- use new DBM
-# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
-#
-DBMDEF= -DNEWDB
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
-
-# define UNSETENV if you need to compile in a local version of setenv
-#ENVDEF= -DUNSETENV
-
-# see also conf.h for additional compilation flags
-
-# include directories
-INCDIRS=-I/usr/sww/include/db
-
-# library directories
-LIBDIRS=-L/usr/sww/lib
-
-# libraries required on your system
-LIBS= -ldb -ldbm
-
-# location of sendmail binary (usually /usr/sbin or /usr/lib)
-BINDIR= ${DESTDIR}/usr/lib
-
-# location of sendmail.st file (usually /var/log or /usr/lib)
-STDIR= ${DESTDIR}/var/log
-
-# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
-HFDIR= ${DESTDIR}/usr/lib
-
-# Stirling - watch out for pollution of name space by sys/sysmacros.h
-# - this hits definitions of m_flags in db.h
-# currently only on 300 series.
-# - sys/sysmacros.h is being included by machine/param.h
-# - which is included by sys/param.h
-XCFLAGS=-D_SYS_SYSMACROS_INCLUDED
-
-################### end of user configuration flags ######################
-
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF} ${XCFLAGS}
-
-OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
- deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
- map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
- savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
-
-LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
-
-aliases.0: aliases.5
- nroff -h -mandoc aliases.5 > aliases.0
-
-newaliases.0: newaliases.1
- nroff -h -mandoc newaliases.1 > newaliases.0
-
-sendmail.0: sendmail.8
- nroff -h -mandoc sendmail.8 > sendmail.0
-
-install: install-sendmail install-docs
-
-install-sendmail: sendmail
- install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${STDIR}/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
-
-# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
-
-clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
-
-# dependencies
-# gross overkill, and yet still not quite enough....
-${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.IRIX b/usr.sbin/sendmail/src/Makefile.IRIX
deleted file mode 100644
index 314fd0002a9e..000000000000
--- a/usr.sbin/sendmail/src/Makefile.IRIX
+++ /dev/null
@@ -1,101 +0,0 @@
-#
-# This Makefile is designed to work on the old "make" program. It does
-# not use the obj subdirectory. It also does not install documentation
-# automatically -- think of it as a quick start for sites that have the
-# old make program (I recommend that you get and port the new make if you
-# are going to be doing any signficant work on sendmail).
-#
-# This has been tested on IRIX
-#
-# @(#)Makefile.dist 8.1 (Berkeley) 6/7/93
-#
-
-# use O=-O (usual) or O=-g (debugging)
-O= -O
-CC=gcc
-
-# define the database mechanisms available for map & alias lookups:
-# -DNDBM -- use new DBM
-# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# -DNIS -- include client NIS support
-# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
-#
-DBMDEF= -DNDBM
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
-
-# define UNSETENV if you need to compile in a local version of setenv
-#ENVDEF= -DUNSETENV
-ENVDEF= -DIRIX
-
-# see also conf.h for additional compilation flags
-
-# include directories
-INCDIRS=
-
-# library directories
-LIBDIRS=
-
-# libraries required on your system
-LIBS= -lmld
-
-# location of sendmail binary (usually /usr/sbin or /usr/lib)
-BINDIR= ${DESTDIR}/usr/lib
-
-# location of sendmail.st file (usually /var/log or /usr/lib)
-STDIR= ${DESTDIR}/usr/lib
-
-# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
-HFDIR= ${DESTDIR}/usr/lib
-
-################### end of user configuration flags ######################
-
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
-
-OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
- deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
- map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
- savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
-
-LINKS= ${DESTDIR}/usr/bsd/newaliases ${DESTDIR}/usr/bsd/mailq
-BINOWN= root
-BINGRP= sys
-BINMODE=6555
-
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
-
-aliases.0: aliases.5
- nroff -h -mandoc aliases.5 > aliases.0
-
-newaliases.0: newaliases.1
- nroff -h -mandoc newaliases.1 > newaliases.0
-
-sendmail.0: sendmail.8
- nroff -h -mandoc sendmail.8 > sendmail.0
-
-install: install-sendmail install-docs
-
-install-sendmail: sendmail
- install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${STDIR}/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
-
-# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
-
-clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
-
-# dependencies
-# gross overkill, and yet still not quite enough....
-${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.OSF1 b/usr.sbin/sendmail/src/Makefile.OSF1
deleted file mode 100644
index dc5a425e75fc..000000000000
--- a/usr.sbin/sendmail/src/Makefile.OSF1
+++ /dev/null
@@ -1,99 +0,0 @@
-#
-# This Makefile is designed to work on the old "make" program. It does
-# not use the obj subdirectory. It also does not install documentation
-# automatically -- think of it as a quick start for sites that have the
-# old make program (I recommend that you get and port the new make if you
-# are going to be doing any signficant work on sendmail).
-#
-# This has been tested on Ultrix.
-#
-# @(#)Makefile.dist 6.5 (Berkeley) 2/26/93
-#
-
-# use O=-O (usual) or O=-g (debugging)
-O= -O
-
-# define the database mechanism used for alias lookups:
-# -DNDBM -- use new DBM
-# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
-#
-DBMDEF= -DNDBM
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
-
-# define UNSETENV if you need to compile in a local version of setenv
-#ENVDEF= -DUNSETENV
-
-# see also conf.h for additional compilation flags
-
-# include directories
-INCDIRS=-I/usr/sww/include/db
-
-# library directories
-LIBDIRS=-L/usr/sww/lib
-
-# libraries required on your system
-LIBS= -ldbm
-
-# location of sendmail binary (usually /usr/sbin or /usr/lib)
-BINDIR= ${DESTDIR}/usr/sbin
-
-# location of sendmail.st file (usually /var/log or /usr/lib)
-STDIR= ${DESTDIR}/var/log
-
-# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
-HFDIR= ${DESTDIR}/usr/share/misc
-
-################### end of user configuration flags ######################
-
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
-
-OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
- deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
- map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
- savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
-
-LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
-
-aliases.0: aliases.5
- nroff -h -mandoc aliases.5 > aliases.0
-
-newaliases.0: newaliases.1
- nroff -h -mandoc newaliases.1 > newaliases.0
-
-sendmail.0: sendmail.8
- nroff -h -mandoc sendmail.8 > sendmail.0
-
-install: install-sendmail install-docs
-
-install-sendmail: sendmail
- install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${STDIR}/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
-
-# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
-
-clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
-
-# dependencies
-# gross overkill, and yet still not quite enough....
-${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.Solaris b/usr.sbin/sendmail/src/Makefile.Solaris
deleted file mode 100644
index 2e77620206b9..000000000000
--- a/usr.sbin/sendmail/src/Makefile.Solaris
+++ /dev/null
@@ -1,103 +0,0 @@
-#
-# This Makefile is designed to work on the old "make" program. It does
-# not use the obj subdirectory. It also does not install documentation
-# automatically -- think of it as a quick start for sites that have the
-# old make program (I recommend that you get and port the new make if you
-# are going to be doing any signficant work on sendmail).
-#
-# This has been tested on Ultrix.
-#
-# @(#)Makefile.dist 6.5 (Berkeley) 2/26/93
-#
-
-# use O=-O (usual) or O=-g (debugging)
-O= -O
-
-CC= gcc -V2.3.3
-
-# define the database mechanism used for alias lookups:
-# -DNDBM -- use new DBM
-# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -- use both new DBM and new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
-#
-DBMDEF= -DNDBM
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
-
-ENVDEF= -D_PATH_SENDMAILCF=\"/etc/mail/sendmail.cf\" \
- -D_PATH_SENDMAILPID=\"/etc/sendmail/sendmail.pid\"
-
-# see also conf.h for additional compilation flags
-
-# include directories
-INCDIRS=-I/usr/sww/include/db
-
-# library directories
-LIBDIRS=-L/usr/sww/lib -L/usr/ucblib
-
-# libraries required on your system
-#LIBS= -lresolv -lsocket -lnsl -lucb -lelf
-LIBS= -lresolv -lsocket -lnsl -lelf
-
-# location of sendmail binary (usually /usr/sbin or /usr/lib)
-BINDIR= ${DESTDIR}/usr/sbin
-
-# location of sendmail.st file (usually /var/log or /usr/lib)
-STDIR= ${DESTDIR}/var/log
-
-# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
-HFDIR= ${DESTDIR}/usr/share/misc
-
-################### end of user configuration flags ######################
-
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF} -DSOLARIS
-
-OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
- deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
- map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
- savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
-
-LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
-BINOWN= root
-BINGRP= sys
-BINMODE=6555
-INSTALL=/usr/ucb/install
-
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
-
-aliases.0: aliases.5
- nroff -h -mandoc aliases.5 > aliases.0
-
-newaliases.0: newaliases.1
- nroff -h -mandoc newaliases.1 > newaliases.0
-
-sendmail.0: sendmail.8
- nroff -h -mandoc sendmail.8 > sendmail.0
-
-install: install-sendmail install-docs
-
-install-sendmail: sendmail
- ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${STDIR}/sendmail.st
- ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
-
-# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
-
-clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
-
-# dependencies
-# gross overkill, and yet still not quite enough....
-${OBJS}: sendmail.h conf.h
diff --git a/usr.sbin/sendmail/src/Makefile.SunOS b/usr.sbin/sendmail/src/Makefile.SunOS
deleted file mode 100644
index b7be76d9844e..000000000000
--- a/usr.sbin/sendmail/src/Makefile.SunOS
+++ /dev/null
@@ -1,36 +0,0 @@
-# @(#)Makefile 5.22 (Berkeley) 7/26/91
-
-PROG= sendmail
-
-DBMDEF= -DNEWDB -DNDBM -DNIS
-INCLS= -I/usr/local/include -I/usr/sww/include/db
-CFLAGS+=-I${.CURDIR} ${INCLS} ${DBMDEF} ${OPTNS}
-
-SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
- deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
- mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
- stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
- util.c version.c
-DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
-LDADD= -L/usr/sww/lib -ldb -ldbm -lresolv -Bstatic
-#LDADD= /usr/sww/build/lib/db/libdb.a -ldbm
-#MAN1= newaliases.0
-#MAN5= aliases.0
-#MAN8= sendmail.0
-NOMAN=
-LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
- ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
-BINDIR= /usr/sbin
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-beforeinstall:
- install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
- ${DESTDIR}/etc/sendmail.fc
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${DESTDIR}/var/log/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
- ${DESTDIR}/usr/share/misc
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.ULTRIX b/usr.sbin/sendmail/src/Makefile.ULTRIX
deleted file mode 100644
index ccacfe594418..000000000000
--- a/usr.sbin/sendmail/src/Makefile.ULTRIX
+++ /dev/null
@@ -1,34 +0,0 @@
-# @(#)Makefile 5.22 (Berkeley) 7/26/91
-
-PROG= sendmail
-
-CFLAGS+=-I${.CURDIR} -I/usr/local/include -I/usr/sww/include/db -DNEWDB -DNDBM
-
-SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
- deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
- mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
- stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
- util.c version.c unsetenv.c
-DPADD= ${LIBDBM} ${LIBCOMPAT} ${LIBUTIL}
-LDADD= -L/usr/sww/lib -ldb
-#LDADD= /usr/sww/build/lib/db/libdb.a -ldbm
-#MAN1= newaliases.0
-#MAN5= aliases.0
-#MAN8= sendmail.0
-NOMAN=
-LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
- ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
-BINDIR= /usr/sbin
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-beforeinstall:
- install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
- ${DESTDIR}/etc/sendmail.fc
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${DESTDIR}/var/log/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
- ${DESTDIR}/usr/share/misc
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.Utah b/usr.sbin/sendmail/src/Makefile.Utah
deleted file mode 100644
index 4ff06ff00b24..000000000000
--- a/usr.sbin/sendmail/src/Makefile.Utah
+++ /dev/null
@@ -1,42 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/7/93
-
-PROG= sendmail
-
-# define the database format to use for aliases et al. Can be -DNEWDB (for
-# the new BSD database package -- this is preferred) or -DNDBM for the NDBM
-# database package. The old putrescent V7 DBM package is no longer
-# supported.
-# You can define both NEWDB and NDBM during a transition period; old
-# databases are read, but the new format will be used on any rebuilds. On
-# really gnarly systems, you can set this to null; it will crawl like a high
-# spiral snail, but it will work.
-DBMDEF= -DNEWDB -DNDBM -DOLD_NEWDB
-
-CFLAGS+=-I${.CURDIR} ${DBMDEF} -Dsetpgid=setpgrp
-
-SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \
- deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \
- mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \
- stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \
- util.c version.c
-DPADD= ${LIBDBM} ${LIBCOMPAT}
-LDADD=
-MAN1= newaliases.0
-MAN5= aliases.0
-MAN8= sendmail.0
-LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \
- ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq
-BINDIR= /usr/sbin
-BINOWN= root
-BINGRP= kmem
-BINMODE=6555
-
-beforeinstall:
-# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
-# ${DESTDIR}/etc/sendmail.fc
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
- ${DESTDIR}/var/log/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \
- ${DESTDIR}/usr/share/misc
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/sendmail/src/Makefile.dist b/usr.sbin/sendmail/src/Makefile.dist
index f85dfebdae1a..f8fd7deec4ae 100644
--- a/usr.sbin/sendmail/src/Makefile.dist
+++ b/usr.sbin/sendmail/src/Makefile.dist
@@ -5,9 +5,7 @@
# old make program (I recommend that you get and port the new make if you
# are going to be doing any signficant work on sendmail).
#
-# This has been tested on Ultrix.
-#
-# @(#)Makefile.dist 8.1 (Berkeley) 6/7/93
+# @(#)Makefile.dist 8.11 (Berkeley) 3/5/94
#
# use O=-O (usual) or O=-g (debugging)
@@ -16,27 +14,23 @@ O= -O
# define the database mechanisms available for map & alias lookups:
# -DNDBM -- use new DBM
# -DNEWDB -- use new Berkeley DB
-# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility
-# -DNIS -- include client NIS support
+# -DNIS -- include NIS support
# The really old (V7) DBM library is no longer supported.
-# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build
-# both the NEWDB and DBM libraries (the DBM just for YP).
+# See READ_ME for a description of how these flags interact.
#
-DBMDEF= -DNEWDB
-
-# define the load average calculation on your system: -DLA_TYPE=LA_INT,
-# -DLA_TYPE=LA_FLOAT, -DLA_TYPE=LA_SUBR, or -DLA_TYPE=LA_ZERO
-# leave undefined to use internal guess
-#LADEF= -DLA_TYPE=LA_SUBR
+DBMDEF= -DNDBM -DNEWDB
-# define UNSETENV if you need to compile in a local version of setenv
-#ENVDEF= -DUNSETENV
+# environment definitions (e.g., -D_AIX3)
+ENVDEF=
# see also conf.h for additional compilation flags
# include directories
INCDIRS=-I/usr/sww/include/db
+# loader options
+LDOPTS=
+
# library directories
LIBDIRS=-L/usr/sww/lib
@@ -52,47 +46,59 @@ STDIR= ${DESTDIR}/var/log
# location of sendmail.hf file (usually /usr/share/misc or /usr/lib)
HFDIR= ${DESTDIR}/usr/share/misc
+# additional .o files needed
+OBJADD=
+
################### end of user configuration flags ######################
-CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${LADEF} ${ENVDEF}
+CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF}
OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \
deliver.o domain.o envelope.o err.o headers.o macro.o main.o \
map.o mci.o parseaddr.o queue.o readcf.o recipient.o \
savemail.o srvrsmtp.o stab.o stats.o sysexits.o \
- trace.o udb.o usersmtp.o util.o version.o
+ trace.o udb.o usersmtp.o util.o version.o ${OBJADD}
LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq
BINOWN= root
BINGRP= kmem
BINMODE=6555
-sendmail: ${OBJS}
- ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS}
+ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
+
+all: ${ALL}
+
+sendmail: ${BEFORE} ${OBJS}
+ ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS}
aliases.0: aliases.5
nroff -h -mandoc aliases.5 > aliases.0
+mailq.0: mailq.1
+ nroff -h -mandoc mailq.1 > mailq.0
+
newaliases.0: newaliases.1
nroff -h -mandoc newaliases.1 > newaliases.0
sendmail.0: sendmail.8
nroff -h -mandoc sendmail.8 > sendmail.0
+INSTALL=install
+
install: install-sendmail install-docs
install-sendmail: sendmail
- install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
- for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
- install -c -o ${BINOWN} -g ${BINGRP} -m 666 /dev/null \
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR}
+ for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \
${STDIR}/sendmail.st
- install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
+ ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR}
# doesn't actually install them -- you may want to install pre-nroff versions
-install-docs: aliases.0 newaliases.0 sendmail.0
+install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0
clean:
- rm -f ${OBJS} sendmail aliases.0 newaliases.0 sendmail.0
+ rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0
# dependencies
# gross overkill, and yet still not quite enough....
diff --git a/usr.sbin/sendmail/src/READ_ME b/usr.sbin/sendmail/src/READ_ME
index b1a0f804a62f..50f75fba9913 100644
--- a/usr.sbin/sendmail/src/READ_ME
+++ b/usr.sbin/sendmail/src/READ_ME
@@ -30,7 +30,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# @(#)READ_ME 8.3 (Berkeley) 7/13/93
+# @(#)READ_ME 8.58 (Berkeley) 3/13/94
#
This directory contains the source files for sendmail.
@@ -39,19 +39,137 @@ For detailed instructions, please read the document ../doc/op.me:
eqn ../doc/op.me | pic | ditroff -me
-The Makefile is for the new Berkeley make, available from ftp.uu.net
-in the directory /systems/unix/bsd-sources/usr.bin/make. There is
-also a Makefile.dist which is much less clever, but works on the old
-traditional make. You can use this using:
+The Makefile is for the new (4.4BSD) Berkeley make and uses syntax
+that is not recognized by older makes. It also has assumptions
+about the 4.4 file system layout built in. See below for details
+about other Makefiles.
+
+There is also a Makefile.dist which is much less clever, but works on
+the old traditional make. You can use this using:
make -f Makefile.dist
-There are a couple of other Makefiles for other systems -- these are
-the ones that I use, they have "Berkeley quirks" in them, and I don't
-guarantee that they will work in your environment. To make it worse,
-some are for the new Berkeley make, and some are for the old make.
-I provide them for information only. Still, they may help you get
-started. They have names like "Makefile.HPUX".
+**************************************************
+** Read below for more details of Makefiles. **
+**************************************************
+
+There is also a shell script (makesendmail) that tries to be clever
+about using object subdirectories. It's pretty straightforward, and
+may help if you share a source tree among different architectures.
+
+**************************************************************************
+** IMPORTANT: DO NOT USE OPTIMIZATION (``-O'') IF YOU ARE RUNNING **
+** GCC 2.4.x or 2.5.x. THERE IS A BUG IN THE GCC OPTIMIZER THAT **
+** CAUSES SENDMAIL COMPILES TO FAIL MISERABLY. **
+**************************************************************************
+
+Jim Wilson of Cygnus believes he has found the problem -- it will
+probably be fixed in GCC 2.5.6 -- but until this is verified, be
+very suspicious of gcc -O.
+
+**************************************************************************
+** IMPORTANT: Read the appropriate paragraphs in the section on **
+** ``Operating System and Compile Quirks''. **
+**************************************************************************
+
+
++-----------+
+| MAKEFILES |
++-----------+
+
+The "Makefile"s in these directories are from 4.4 BSD, and hence
+really only work properly if you are on a 4.4 system. In particular,
+they use new syntax that will not be recognized on old make programs,
+and some of them do things like ``.include ../../Makefile.inc'' to
+pick up some system defines. If you are getting sendmail separately,
+these files won't be included in the distribution, as they are
+outside of the sendmail tree.
+
+Instead, you should use one of the other Makefiles, such as
+Makefile.SunOS for a SunOS system, and so forth. These should
+work with the version of make that is appropriate for that
+system.
+
+There are a bunch of other Makefiles for other systems with names
+like Makefile.HPUX for an HP-UX system. They use the version of
+make that is native for that system. These are the Makefiles that
+I use, and they have "Berkeley quirks" in them. I can't guarantee
+that they will work unmodified in your environment. Many of them
+include -I/usr/sww/include/db and -L/usr/sww/lib -- this is Berkeley's
+location (the ``Software Warehouse'') for the new database libraries,
+described below. You don't have to remove these definitions if you
+don't have these directories.
+
+Please look for an appropriate Makefile before you start trying to
+compile with Makefile or Makefile.dist.
+
+If you want to port the new Berkeley make, you can get it from
+ftp.uu.net in the directory /systems/unix/bsd-sources/usr.bin/make.
+Diffs and instructions for building this version of make under
+SunOS 4.1.x are available on ftp.css.itd.umich.edu in
+/pub/systems/sun/Net2-make.sun4.diff.Z. Diffs and instructions
+for building this version of make under IBM AIX 3.2.4 are available
+on ftp.uni-stuttgart.de in /sw/src/patches/bsd-make-rus-patches.
+Paul Southworth <pauls@umich.edu> published a description of porting
+this make in comp.unix.bsd.
+
+The complete text of the Makefile.inc that is in the parent of the
+sendmail directory is:
+
+ # @(#)Makefile.inc 8.1 (Berkeley) 6/6/93
+
+ BINDIR?= /usr/sbin
+
+
++----------------------+
+| DATABASE DEFINITIONS |
++----------------------+
+
+There are several database formats that can be used for the alias files
+and for general maps. When used for alias files they interact in an
+attempt to be back compatible.
+
+The three options are NEWDB (the new Berkeley DB package), NDBM (the
+older DBM implementation -- the very old V7 implementation is no
+longer supported), and NIS (Network Information Services). Used alone
+these just include the support they indicate. [If you are using NEWDB,
+get the latest version from FTP.CS.Berkeley.EDU in /ucb/4bsd. 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 to do this.]
+
+[NOTE WELL: it is CRITICAL that you remove ndbm.o from libdb.a and
+ndbm.h from the appropriate include directories if you want to get
+ndbm support. These files OVERRIDE calls to ndbm routines -- in
+particular, if you leave ndbm.h in, you can find yourself using
+the new db package even if you don't define NEWDB.]
+
+If NEWDB and NDBM are defined (but not NIS), then sendmail will read
+NDBM format alias files, but the next time a newaliases is run the
+format will be converted to NEWDB; that format will be used forever
+more. This is intended as a transition feature. [Note however that
+the NEWDB library also catches and maps NDBM calls; you will have to
+back out this feature to get this to work. See ``Quirks'' section
+below for details.]
+
+If all three are defined, sendmail operates as described above, and also
+looks for the file /var/yp/Makefile. If it exists, newaliases will
+build BOTH the NEWDB and NDBM format alias files. However, it will
+only use the NEWDB file; the NDBM format file is used only by the
+NIS subsystem.
+
+If NDBM and NIS are defined (regardless of the definition of NEWDB
+or the existance of /var/yp/Makefile), sendmail adds the special
+tokens "YP_LAST_MODIFIED" and "YP_MASTER_NAME", both of which are
+required if the NDBM file is to be used as an NIS map.
+
+All of -DNEWDB, -DNDBM, and -DNIS are normally defined in the DBMDEF
+line in the Makefile.
+
+
++---------------+
+| COMPILE FLAGS |
++---------------+
Whereever possible, I try to make sendmail pull in the correct
compilation options needed to compile on various environments based on
@@ -60,60 +178,158 @@ symbols availble, requiring the following compilation flags in the
Makefile:
SOLARIS Define this if you are running Solaris 2.0 or higher.
-__NeXT__ Define this if you are on a NeXT box. (This one may
- be pre-defined for you.)
+SOLARIS_2_3 Define this if you are running Solaris 2.3 or higher.
+SUNOS403 Define this if you are running SunOS 4.0.3.
+NeXT Define this if you are on a NeXT box. (This one may
+ be pre-defined for you.) There are other hacks you
+ have to make -- see below.
_AIX3 Define this if you are IBM AIX 3.x.
+RISCOS Define this if you are running RISC/os from MIPS.
+IRIX Define this if you are running IRIX from SGI.
+_SCO_unix_ Define this if you are on SCO UNIX.
+_SCO_unix_4_2 Define this if you are on SCO Open Server 3.2v4.
If you are a system that sendmail has already been ported to, you
probably won't have to touch these. But if you are porting, you may
-have to tweak the following compilation flags in order to get
-it to compile and link properly:
-
-UNSETENV Define this if your system library does NOT include the
- "unsetenv" subroutine.
-SYSTEM5 Adjust for System V.
-LOCKF Set this if you do not have the flock system call -- it
- will revert to System V file locking. There are some
- semantic gotchas, so flock is preferred. Implied by
- SYSTEM5.
-SYS5TZ Use System V-style time zones. If not set, the TZ
- environment variable is ignored. Implied by SYSTEM5.
+have to tweak the following compilation flags in conf.h in order to
+get it to compile and link properly:
+
+SYSTEM5 Adjust for System V (not necessarily Release 4).
+SYS5SIGNALS Use System V signal semantics -- the signal handler
+ is automatically dropped when the signal is caught.
+ If this is not set, use POSIX/BSD semantics, where the
+ signal handler stays in force until an exec or an
+ explicit delete. Implied by SYSTEM5.
+SYS5SETPGRP Use System V setpgrp() semantics. Implied by SYSTEM5.
+HASFLOCK Set this if you prefer to use the flock(2) system call
+ rather than using fcntl-based locking. Fcntl locking
+ has some semantic gotchas, but many vendor systems
+ also interface it to lockd(8) to do NFS-style locking.
+ For this reason, this should not be set unless you
+ don't have an alternative.
HASUNAME Set if you have the "uname" system call. Implied by
SYSTEM5.
-HASSTATFS Define this if you have the statfs(2) system call. It's
- not a disaster to get this wrong -- but you do lose the
- queue free space code.
-HASUSTAT Define this if you have the ustat(2) system call. It's
- not a disaster to get this wrong -- but you do lose the
- queue free space code.
+HASUNSETENV Define this if your system library has the "unsetenv"
+ subroutine.
HASSETSID Define this if you have the setsid(2) system call. This
is implied if your system appears to be POSIX compliant.
HASINITGROUPS Define this if you have the initgroups(3) routine.
HASSETVBUF Define this if you have the setvbuf(3) library call.
If you don't, setlinebuf will be used instead. This
defaults on if your compiler defines __STDC__.
-HASSETEUID Define this if you have seteuid(2) ***AND*** root can use
- it to change to an arbitrary user. This second condition
- is not satisfied on AIX 3.x. You may find that
- your system has setreuid(2) or setresuid(2), in which
- case you will also have to #define seteuid(uid) to be
- the appropriate call. The important thing is that you
- have a call that will set the effective uid and NOT
- set the real or saved uid. Setting this improves the
- security somewhat, since sendmail doesn't have to read
- .forward and :include: files as root.
+HASSETREUID Define this if you have setreuid(2) ***AND*** root can
+ use setreuid to change to an arbitrary user. This second
+ condition is not satisfied on AIX 3.x. You may find that
+ your system has setresuid(2), (for example, on HP-UX) in
+ which case you will also have to #define setreuid(r, e)
+ to be the appropriate call. Some systems (such as Solaris)
+ have a compatibility routine that doesn't work properly,
+ but may have "saved user ids" properly implemented so you
+ can ``#define setreuid(r, e) seteuid(e)'' and have it work.
+ The important thing is that you have a call that will set
+ the effective uid independently of the real or saved uid
+ and be able to set the effective uid back again when done.
+ There's a test program in ../test/t_setreuid.c that will
+ try things on your system. Setting this improves the
+ security, since sendmail doesn't have to read .forward
+ and :include: files as root. There are certain attacks
+ that may be unpreventable without this call.
+HASLSTAT Define this if you have symbolic links (and thus the
+ lstat(2) system call). This improves security. Unlike
+ most other options, this one is on by default, so you
+ need to #undef it in conf.h if you don't have symbolic
+ links (these days everyone does).
+NEEDGETOPT Define this if you need a reimplementation of getopt(3).
+ On some systems, getopt does very odd things if called
+ to scan the arguments twice. This flag will ask sendmail
+ to compile in a local version of getopt that works
+ properly.
+NEEDSTRTOL Define this if your standard C library does not define
+ strtol(3). This will compile in a local version.
+NEEDVPRINTF Define this if your standard C library does not define
+ vprintf(3). Note that the resulting fake implementation
+ is not very elegant and may not even work on some
+ architectures.
+HASGETUSERSHELL Define this to 1 if you have getusershell(3) in your
+ standard C library. If this is not defined, or is defined
+ to be 0, sendmail will scan the /etc/shells file (no
+ NIS-style support, defaults to /bin/sh and /bin/csh if
+ that file does not exist) to get a list of unrestricted
+ user shells. This is used to determine whether users
+ are allowed to forward their mail to a program or a file.
+GIDSET_T The type of entries in a gidset passed as the second
+ argument to getgroups(2). Historically this has been an
+ int, so this is the default, but some systems (such as
+ IRIX) pass it as a gid_t, which is an unsigned short.
+ This will make a difference, so it is important to get
+ this right! However, it is only an issue if you have
+ group sets.
+SLEEP_T The type returned by the system sleep() function.
+ Defaults to "unsigned int". Don't worry about this
+ if you don't have compilation problems.
+ARBPTR_T The type of an arbitrary pointer -- defaults to "void *".
+ If you are an very old compiler you may need to define
+ this to be "char *".
LA_TYPE The type of load average your kernel supports. These
- can be LA_SUBR (4) if you have the getloadavg(3) routine,
+ can be one of:
+ LA_ZERO (1) -- it always returns the load average as
+ "zero" (and does so on all architectures).
+ LA_SUBR (4) if you have the getloadavg(3) routine,
+ LA_MACH (5) to use MACH-style load averages (calls
+ processor_set_info()),
+ LA_PROCSTR (7) to read /proc/loadavg and interpret it
+ as a string representing a floating-point
+ number (Linux-style),
LA_FLOAT (3) if you read kmem and interpret the value
- as a floating point number, LA_INT (2) to interpret as
- an integer. These last two have several other parameters
- that they try to divine: the name of your kernel, the name
- of the variable in the kernel to examine, the number of
- bits of precision in a fixed point load average, and so
- forth. In desparation, use LA_ZERO -- it always returns
- the load average as "zero" (and does so on all architectures).
- The actual code is in conf.c -- it can be tweaked if you
- are brave.
+ as a floating point number,
+ LA_INT (2) to interpret as a long integer,
+ LA_SHORT (6) to interpret as a short integer.
+ These last three have several other parameters that they
+ try to divine: the name of your kernel, the name of the
+ variable in the kernel to examine, the number of bits of
+ precision in a fixed point load average, and so forth.
+ In desperation, use LA_ZERO. The actual code is in
+ conf.c -- it can be tweaked if you are brave.
+SFS_TYPE Encodes how your kernel can locate the amount of free
+ space on a disk partition. This can be set to SFS_NONE
+ (0) if you have no way of getting this information,
+ SFS_USTAT (1) if you have the ustat(2) system call,
+ SFS_4ARGS (2) if you have a four-argument statfs(2)
+ system call (and the include file is <sys/statfs.h>),
+ and SFS_VFS (3), SFS_MOUNT (4), or SFS_STATFS (5) if
+ you have the two-argument statfs(2) system call, with
+ includes in <sys/vfs.h>, <sys/mount.h>, or <sys/statfs.h>
+ respectively. The default if nothing is defined is
+ SFS_NONE.
+ERRLIST_PREDEFINED
+ If set, assumes that some header file defines sys_errlist.
+ This may be needed if you get type conflicts on this
+ variable -- otherwise don't worry about it.
+WAITUNION The wait(2) routine takes a "union wait" argument instead
+ of an integer argument. This is for compatibility with
+ old versions of BSD.
+SCANF You can set this to extend the F command to accept a
+ scanf string -- this gives you a primitive parser for
+ class definitions -- BUT it can make you vulnerable to
+ core dumps if the target file is poorly formed.
+SYSLOG_BUFSIZE You can define this to be the size of the buffer that
+ syslog accepts. If it is not defined, it assumes a
+ 1024-byte buffer. If the buffer is very small (under
+ 256 bytes) the log message format changes -- each
+ e-mail message will log many more messages, since it
+ will log each piece of information as a separate line
+ in syslog.
+BROKEN_RES_SEARCH
+ On Ultrix (and maybe other systems?) if you use the
+ res_search routine with an unknown host name, it returns
+ -1 but sets h_errno to 0 instead of HOST_NOT_FOUND. If
+ you set this, sendmail considers 0 to be the same as
+ HOST_NOT_FOUND.
+
+
++-----------------------+
+| COMPILE-TIME FEATURES |
++-----------------------+
There are a bunch of features that you can decide to compile in, such
as selecting various database packages and special protocol support.
@@ -122,23 +338,19 @@ Several are assumed based on other compilation flags -- if you want to
flags that add support for special features include:
NDBM Include support for "new" DBM library for aliases and maps.
+ Normally defined in the Makefile.
NEWDB Include support for Berkeley "db" package (hash & btree)
- for aliases and maps.
+ for aliases and maps. Normally defined in the Makefile.
NIS Define this to get NIS (YP) support for aliases and maps.
-YPCOMPAT Define this to force building of DBM versions of alias
- files even if you have NEWDB defined; this will only
- occur on NIS master machines. It is independent of NIS.
+ Normally defined in the Makefile.
USERDB Include support for the User Information Database. Implied
- by NEWDB conf.h.
-IDENTPROTO Define this to get IDENT (RFC 1413) protocol support.
+ by NEWDB in conf.h.
+IDENTPROTO Define this as 1 to get IDENT (RFC 1413) protocol support.
This is assumed unless you are running on Ultrix or
HP-UX, both of which have a problem in the UDP
- implementation.
+ implementation. You can define it to be 0 to explicitly
+ turn off IDENT protocol support.
MIME Include support for MIME-encapsulated error messages.
-FROZENCONFIG Define this to get support for frozen configuration
- files. Frozen configurations make sense if your I/O system
- is fast relative to your processor. At this point this
- is NOT recommended.
LOG Set this to get syslog(3) support. Defined by default
in conf.h. You want this if at all possible.
NETINET Set this to get TCP/IP support. Defined by default
@@ -163,23 +375,432 @@ SETPROCTITLE Try to set the string printed by "ps" to something
informative about what sendmail is doing. Defined by
default in conf.h.
-If you are compiling on SunOS and want to use frozen configuration
-files, you must use -Bstatic -- if you do not, frozen configuration
-files fail in bizarre ways and you will open up several security holes.
-If you are compiling on OSF/1 (DEC Alpha), you must use -lmld.
++---------------------+
+| DNS/RESOLVER ISSUES |
++---------------------+
+
+Many systems have old versions of the resolver library. At a minimum,
+you should be running BIND 4.8.3; older versions may compile, but they
+have known bugs that should give you pause.
+
+Common problems in old versions include "undefined" errors for
+dn_skipname.
+
+Some people have had a problem with BIND 4.9; it uses some routines
+that it expects to be externally defined such as strerror(). It may
+help to link with "-l44bsd" to solve this problem.
+
+!PLEASE! be sure to link with the same version of the resolver as
+the header files you used -- some people have used the 4.9 headers
+and linked with BIND 4.8 or vice versa, and it doesn't work.
+Unfortunately, it doesn't fail in an obvious way -- things just
+subtly don't work.
+
+
++-------------------------------------+
+| OPERATING SYSTEM AND COMPILE QUIRKS |
++-------------------------------------+
+
+GCC 2.5.x problems *** IMPORTANT ***
+ Date: Mon, 29 Nov 93 19:08:44 PST
+ From: wilson@cygnus.com (Jim Wilson)
+ Message-Id: <9311300308.AA04608@cygnus.com>
+ To: kenner@vlsi1.ultra.nyu.edu
+ Subject: [cattelan@thebarn.com: gcc 2.5.4-2.5.5 -O bug]
+ Cc: cattelan@thebarn.com, rms@gnu.ai.mit.edu, sendmail@cs.berkeley.edu
+
+ This fixes a problem that occurs when gcc 2.5.5 is used to compile
+ sendmail 8.6.4 with optimization on a sparc.
+
+ Mon Nov 29 19:00:14 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * reload.c (find_reloads_toplev): Replace obsolete reference to
+ BYTE_LOADS_*_EXTEND with LOAD_EXTEND_OP.
+
+ *** clean-ss-931128/reload.c Sun Nov 14 16:20:01 1993
+ --- ss-931128/reload.c Mon Nov 29 18:52:55 1993
+ *************** find_reloads_toplev (x, opnum, type, ind
+ *** 3888,3894 ****
+ force a reload in that case. So we should not do anything here. */
+
+ else if (regno >= FIRST_PSEUDO_REGISTER
+ ! #if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
+ && (GET_MODE_SIZE (GET_MODE (x))
+ <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ #endif
+ --- 3888,3894 ----
+ force a reload in that case. So we should not do anything here. */
+
+ else if (regno >= FIRST_PSEUDO_REGISTER
+ ! #ifdef LOAD_EXTEND_OP
+ && (GET_MODE_SIZE (GET_MODE (x))
+ <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ #endif
+
+
+SunOS 4.x (Solaris 1.x)
+ You may have to use -lresolv on SunOS. However, beware that
+ this links in a new version of gethostbyname that does not
+ understand NIS, so you must have all of your hosts in DNS.
+
+ Some people have reported problems with the SunOS version of
+ -lresolv and/or in.named, and suggest that you get a newer
+ version. The symptoms are delays when you connect to the
+ SMTP server on a SunOS machine or having your domain added to
+ addresses inappropriately. There is a version of BIND
+ version 4.9 on gatekeeper.DEC.COM in pub/BSD/bind/4.9.
+
+ There is substantial disagreement about whether you can make
+ this work with resolv+, which allows you to specify a search-path
+ of services. Some people report that it works fine, others
+ claim it doesn't work at all (including causing sendmail to
+ drop core when it tries to do multiple resolv+ lookups for a
+ single job). I haven't tried resolv+, as we use DNS exclusively.
+
+ Should you want to try resolv+, it is on ftp.uu.net in
+ /networking/ip/dns.
+
+Solaris 2.x (SunOS 5.x)
+ To compile for Solaris, be sure you use -DSOLARIS.
+
+ To the best of my knowledge, Solaris does not have the
+ gethostbyname problem described above. However, it does
+ have another one:
+
+ From a correspondent:
+
+ For solaris 2.2, I have
+
+ hosts: files dns
+
+ in /etc/nsswitch.conf and /etc/hosts has to have the fully
+ qualified host name. I think "files" has to be before "dns"
+ in /etc/nsswitch.conf during bootup.
+
+ From another correspondent:
+
+ When running sendmail under Solaris, the gethostbyname()
+ hack in conf.c which should perform proper canonicalization
+ of host names could fail. Result: the host name is not
+ canonicalized despite the hack, and you'll have to define $j
+ and $m in sendmail.cf somewhere.
+
+ The reason could be that /etc/nsswitch.conf is improperly
+ configured (at least from sendmail's point of view). For
+ example, the line
+
+ hosts: files nisplus dns
+
+ will make gethostbyname() look in /etc/hosts first, then ask
+ nisplus, then dns. However, if /etc/hosts does not contain
+ the full canonicalized hostname, then no amount of
+ gethostbyname()s will work.
+
+ Solution (or rather, a workaround): Ask nisplus first, then
+ dns, then local files:
+
+ hosts: nisplus dns [NOTFOUND=return] files
+
+ The Solaris "syslog" function is apparently limited to something
+ about 90 characters because of a kernel limitation. If you have
+ source code, you can probably up this number. You can get patches
+ that fix this problem: the patch ids are:
+
+ Solaris 2.1 100834
+ Solaris 2.2 100999
+ Solaris 2.3 101318
+
+ Be sure you have the appropriate patch installed or you won't
+ see system logging.
+
+OSF/1
+ If you are compiling on OSF/1 (DEC Alpha), you must use
+ -L/usr/shlib (otherwise it core dumps on startup). You may also
+ need -mld to get the nlist() function, although some versions
+ apparently don't need this.
+
+ Also, the enclosed makefile removed /usr/sbin/smtpd; if you need
+ it, just create the link to the sendmail binary.
+
+IRIX
+ The header files on SGI IRIX are completely prototyped, and as
+ a result you can sometimes get some warning messages during
+ compilation. These can be ignored. There are two errors in
+ deliver only if you are using gcc, both of the form ``warning:
+ passing arg N of `execve' from incompatible pointer type''.
+ Also, if you compile with -DNIS, you will get a complaint
+ about a declaration of struct dom_binding in a prototype
+ when compiling map.c; this is not important because the
+ function being prototyped is not used in that file.
+
+NeXT
+ If you are compiling on NeXT, you will have to create an empty
+ file "unistd.h" and create a file "dirent.h" containing:
+
+ #include <sys/dir.h>
+ #define dirent direct
+
+ (The Makefile.NeXT should try to do both of these for you.)
+
+ Apparently, there is a bug in getservbyname on Nextstep 3.0
+ that causes it to fail under some circumstances with the
+ message "SYSERR: service "smtp" unknown" logged. You should
+ be able to work around this by including the line:
+
+ OOPort=25
+
+ in your .cf file.
+
+ You may have to use -DNeXT.
+
+BSDI (BSD/386) 1.0, NetBSD 0.9, FreeBSD 1.0
+ The "m4" from BSDI won't handle the config files properly.
+ I haven't had a chance to test this myself.
+
+ The M4 shipped in FreeBSD and NetBSD 0.9 don't handle the config
+ files properly. One must use either GNU m4 1.1 or the PD-M4
+ recently posted in comp.os.386bsd.bugs (and maybe others).
+ NetBSD-current includes the PD-M4 (as stated in the NetBSD file
+ CHANGES).
+
+ FreeBSD 1.0 RELEASE has uname(2) now. Use -DUSEUNAME in order to
+ use it (look into Makefile.FreeBSD). NetBSD-current may have
+ it too but it has not been verified.
+
+ You cannot port the latest version of the Berkeley db library
+ and use it with sendmail without recompiling the world. This
+ is because C library routines use the older version which have
+ incompatible header files -- the result is that it can't read
+ other system files, such as /etc/passwd, unless you use the
+ new db format throughout your system. You should normally just
+ use the version of db supplied in your release. You may need
+ to use -DOLD_NEWDB to make this work -- this turns off some
+ new interface calls (for file locking) that are not in older
+ versions of db. You'll get compile errors if you need this
+ flag and don't have it set.
+
+4.3BSD
+ If you are running a "virgin" version of 4.3BSD, you'll have
+ a very old resolver and be missing some header files. The
+ header files are simple -- create empty versions and everything
+ will work fine. For the resolver you should really port a new
+ version (4.8.3 or later) of the resolver; 4.9 is available on
+ gatekeeper.DEC.COM in pub/BSD/bind/4.9. If you are really
+ determined to continue to use your old, buggy version (or as
+ a shortcut to get sendmail working -- I'm sure you have the
+ best intentions to port a modern version of BIND), you can
+ copy ../contrib/oldbind.compat.c into src and add
+ oldbind.compat.o to OBJADD in the Makefile.
+
+A/UX
+ Date: Tue, 12 Oct 1993 18:28:28 -0400 (EDT)
+ From: "Eric C. Hagberg" <hagberg@med.cornell.edu>
+ Subject: Fix for A/UX ndbm
+
+ I guess this isn't really a sendmail bug, however, it is something
+ that A/UX users should be aware of when compiling sendmail 8.6.
+
+ Apparently, the calls that sendmail is using to the ndbm routines
+ in A/UX 3.0.x contain calls to "broken" routines, in that the
+ aliases database will break when it gets "just a little big"
+ (sorry I don't have exact numbers here, but it broke somewhere
+ around 20-25 aliases for me.), making all aliases non-functional
+ after exceeding this point.
+
+ What I did was to get the gnu-dbm-1.6 package, compile it, and
+ then re-compile sendmail with "-lgdbm", "-DNDBM", and using the
+ ndbm.h header file that comes with the gnu-package. This makes
+ things behave properly.
+
+ I suppose porting the New Berkeley db package is another route,
+ however, I made a quick attempt at it, and found it difficult
+ (not easy at least); the gnu-dbm package "configured" and
+ compiled easily.
+
+DG/UX
+ Apparently, /bin/mail doesn't work properly for delivery on
+ DG/UX -- the person who has this working, Douglas Anderson
+ <dlander@afterlife.ncsc.mil>, used procmail instead.
+
+Apollo DomainOS
+ If you are compiling on Apollo, you will have to create an empty
+ file "unistd.h" and create a file "dirent.h" containing:
+
+ #include <sys/dir.h>
+ #define dirent direct
+
+ (The Makefile.DomainOS will attempt to do both of these for you.)
+
+HP-UX 8.00
+ Date: Mon, 24 Jan 1994 13:25:45 +0200
+ From: Kimmo Suominen <Kimmo.Suominen@lut.fi>
+ Subject: 8.6.5 w/ HP-UX 8.00 on s300
+
+ Just compiled and fought with sendmail 8.6.5 on a HP9000/360 (ie. a
+ series 300 machine) running HP-UX 8.00.
+
+ I was getting segmentation fault when delivering to a local user.
+ With debugging I saw it was faulting when doing _free@libc... *sigh*
+ It seems the new implementation of malloc on s300 is buggy as of 8.0,
+ so I tried out the one in -lmalloc (malloc(3X)). With that it seems
+ to work just dandy.
+
+ When linking, you will get the following error:
+
+ ld: multiply defined symbol _freespace in file /usr/lib/libmalloc.a
+
+ but you can just ignore it. You might want to add this info to the
+ README file for the future...
+
+Linux
+ Something broke between versions 0.99.13 and 0.99.14 of Linux:
+ the flock() system call gives errors. If you are running .14,
+ you must not use flock. You can do this with -DHASFLOCK=0.
+
+AIX
+ This version of sendmail does not support MB, MG, and MR resource
+ records, which are supported by AIX sendmail.
+
+RISC/os
+ RISC/os from MIPS is a merged AT&T/Berkeley system. When you
+ compile on that platform you will get duplicate definitions
+ on many files. You can ignore these.
+
+System V Release 4 Based Systems
+ There is a single Makefile that is intended for all SVR4-based
+ systems (called Makefile.SVR4). It defines __svr4__, which is
+ predefined by some compilers. If your compiler already defines
+ this compile variable, you can delete the definition from the
+ Makefile.
+
+ It's been tested on Dell Issue 2.2.
+
+DELL SVR4
+ Date: Mon, 06 Dec 1993 10:42:29 EST
+ From: "Kimmo Suominen" <kim@grendel.lut.fi>
+ Message-ID: <2d0352f9.lento29@lento29.UUCP>
+ To: eric@cs.berkeley.edu
+ Cc: sendmail@cs.berkeley.edu
+ Subject: Notes for DELL SVR4
+
+ Eric,
+
+ Here are some notes for compiling Sendmail 8.6.4 on DELL SVR4. I ran
+ across these things when helping out some people who contacted me by
+ e-mail.
+
+ 1) Use gcc 2.4.5 (or later?). Dell distributes gcc 2.1 with their
+ Issue 2.2 Unix. It is too old, and gives you problems with
+ clock.c, because sigset_t won't get defined in <sys/signal.h>.
+ This is due to a problematic protection rule in there, and is
+ fixed with gcc 2.4.5.
+
+ 2) If you don't use the new Berkeley DB (-DNEWDB), then you need
+ to add "-lc -lucb" to the libraries to link with. This is because
+ the -ldbm distributed by Dell needs the bcopy, bcmp and bzero
+ functions. It is important that you specify both libraries in
+ the given order to be sure you only get the BSTRING functions
+ from the UCB library (and not the signal routines etc.).
+
+ 3) Don't leave out "-lelf" even if compiling with "-lc -lucb".
+ The UCB library also has another copy of the nlist routines,
+ but we do want the ones from "-lelf".
+
+ If anyone needs a compiled gcc 2.4.5 and/or a ported DB library, they
+ can use anonymous ftp to fetch them from lut.fi in the /kim directory.
+ They are copies of what I use on grendel.lut.fi, and offering them
+ does not imply that I would also support them. I have sent the DB
+ port for SVR4 back to Keith Bostic for inclusion in the official
+ distribution, but I haven't heard anything from him as of today.
+
+ - gcc-2.4.5-svr4.tar.gz (gcc 2.4.5 and the corresponding libg++)
+ - db-1.72.tar.gz (with source, objects and a installed copy)
+
+ Cheers
+ + Kim
+ --
+ * Kimmo.Suominen@lut.fi * SysVr4 enthusiast at GRENDEL.LUT.FI *
+ * KIM@FINFILES.BITNET * Postmaster and Hostmaster at LUT.FI *
+ * + 358 200 865 718 * Unix area moderator at NIC.FUNET.FI *
+
+
+Non-DNS based sites
+ This version of sendmail always tries to connect to the Domain
+ Name System (DNS) to resolve names, regardless of the setting
+ of the `I' option. On most systems that are not running DNS,
+ this will fail quickly and sendmail will continue, but on some
+ systems it has a long timeout. If you have this problem, you
+ will have to recompile without NAMED_BIND. Some people have
+ claimed that they have successfully used "OI+USEVC" to force
+ sendmail to use a virtual circuit -- this will always time out
+ quickly, but also tells sendmail that a failed connection
+ should requeue the message (probably not what you intended).
+ A future release of sendmail will correct this problem.
+
+Both NEWDB and NDBM
+ If you use both -DNDBM and -DNEWDB, you must delete the module
+ ndbm.o from libdb.a and delete the file "ndbm.h" from the files
+ that get installed (that is, use the OLD ndbm.h, not the new
+ ndbm.h). This compatibility module maps ndbm calls into DB
+ calls, and breaks things rather badly.
+
+GNU getopt
+ I'm told that GNU getopt has a problem in that it gets confused
+ by the double call. Use the version in conf.c instead.
+
+BIND 4.9.2 and Ultrix
+ If you are running on Ultrix, be sure you read the conf/Info.Ultrix
+ carefully -- there is information in there that you need to know
+ in order to avoid errors of the form:
+
+ /lib/libc.a(gethostent.o): sethostent: multiply defined
+ /lib/libc.a(gethostent.o): endhostent: multiply defined
+ /lib/libc.a(gethostent.o): gethostbyname: multiply defined
+ /lib/libc.a(gethostent.o): gethostbyaddr: multiply defined
+
+ during the link stage.
+
+
++--------------+
+| MANUAL PAGES |
++--------------+
+
+The manual pages have been written against the -mandoc macros
+instead of the -man macros. The latest version of groff has them
+included. You can also get a copy from FTP.UU.NET in directory
+/systems/unix/bsd-sources/share/tmac.
+
+
++-----------------+
+| DEBUGGING HOOKS |
++-----------------+
+
+As of 8.6.5, sendmail daemons will catch a SIGUSR1 signal and log
+some debugging output (logged at LOG_DEBUG severity). The
+information dumped is:
+
+ * The value of the $j macro.
+ * A warning if $j is not in the set $=w.
+ * A list of the open file descriptors.
+ * The contents of the connection cache.
+ * If ruleset 89 is defined, it is evaluated and the results printed.
+
+This allows you to get information regarding the runtime state of the
+daemon on the fly. This should not be done too frequently, since
+the process of rewriting may lose memory which will not be recovered.
+Also, ruleset 89 may call non-reentrant routines, so there is a small
+non-zero probability that this will cause other problems. It is
+really only for debugging serious problems.
+
+A typical formulation of ruleset 89 would be:
-If you are compiling on NeXT, you will have to create an empty file
-"unistd.h".
+ R$* $@ $>0 some test address
-If you use both -DNDBM and -DNEWDB, you must delete the module ndbm.o
-from libdb.a and delete the file "ndbm.h" from the files that get
-installed (that is, use the OLD ndbm.h, not the new ndbm.h). This
-compatibility module maps ndbm calls into DB calls, and breaks things
-rather badly.
-You probably want to look over the compilation options in conf.h
-before you compile. These are intended to be per-site information.
++-----------------------------+
+| DESCRIPTION OF SOURCE FILES |
++-----------------------------+
The following list describes the files in this directory:
@@ -240,4 +861,4 @@ version.c The version number and information about this
Eric Allman
-(Version 8.3, last update 7/13/93 12:57:56)
+(Version 8.58, last update 3/13/94 09:38:06)
diff --git a/usr.sbin/sendmail/src/TRACEFLAGS b/usr.sbin/sendmail/src/TRACEFLAGS
index 3fd00b728053..f05c219c8711 100644
--- a/usr.sbin/sendmail/src/TRACEFLAGS
+++ b/usr.sbin/sendmail/src/TRACEFLAGS
@@ -51,9 +51,14 @@
41 queue.c orderq
42 mci.c mci_get
45 envelope.c setsender
+46 envelope.c openxscript
+49 conf.c checkcompat
50 envelope.c dropenvelope
51 queue.c unlockqueue
52 main.c disconnect
53 util.c xfclose
+54 err.c putoutmsg
+55 conf.c lockfile
59 Extended Load Average implementation from Christophe Wolfhugel
60 map.c
+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 eb579b22b93d..20a316200cad 100644
--- a/usr.sbin/sendmail/src/alias.c
+++ b/usr.sbin/sendmail/src/alias.c
@@ -33,11 +33,10 @@
*/
# include "sendmail.h"
-# include <signal.h>
# include <pwd.h>
#ifndef lint
-static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)alias.c 8.24 (Berkeley) 2/28/94";
#endif /* not lint */
@@ -115,13 +114,15 @@ alias(a, sendq, e)
message("aliased to %s", p);
#ifdef LOG
if (LogLevel > 9)
- syslog(LOG_INFO, "%s: alias %s => %s", e->e_id, a->q_paddr, p);
+ syslog(LOG_INFO, "%s: alias %s => %s",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ a->q_paddr, p);
#endif
a->q_flags &= ~QSELFREF;
AliasLevel++;
naliases = sendtolist(p, a, sendq, e);
AliasLevel--;
- if (naliases > 0 && !bitset(QSELFREF, a->q_flags))
+ if (!bitset(QSELFREF, a->q_flags))
{
if (tTd(27, 5))
{
@@ -145,7 +146,7 @@ alias(a, sendq, e)
owner = aliaslookup(obuf, e);
if (owner != NULL)
{
- if (strchr(owner, ',') != NULL)
+ if (strpbrk(owner, ",:/|\"") != NULL)
owner = obuf;
a->q_owner = newstr(owner);
}
@@ -280,13 +281,27 @@ setalias(spec)
** ALIASWAIT -- wait for distinguished @:@ token to appear.
**
** This can decide to reopen or rebuild the alias file
+**
+** Parameters:
+** map -- a pointer to the map descriptor for this alias file.
+** ext -- the filename extension (e.g., ".db") for the
+** database file.
+** isopen -- if set, the database is already open, and we
+** should check for validity; otherwise, we are
+** just checking to see if it should be created.
+**
+** Returns:
+** TRUE -- if the database is open when we return.
+** FALSE -- if the database is closed when we return.
*/
-aliaswait(map, ext)
+bool
+aliaswait(map, ext, isopen)
MAP *map;
char *ext;
+ int isopen;
{
- int atcnt;
+ bool attimeout = FALSE;
time_t mtime;
struct stat stb;
char buf[MAXNAME];
@@ -294,26 +309,41 @@ aliaswait(map, ext)
if (tTd(27, 3))
printf("aliaswait(%s:%s)\n",
map->map_class->map_cname, map->map_file);
+ if (bitset(MF_ALIASWAIT, map->map_mflags))
+ return isopen;
+ map->map_mflags |= MF_ALIASWAIT;
- atcnt = SafeAlias * 2;
- if (atcnt > 0)
+ if (SafeAlias > 0)
{
auto int st;
+ time_t toolong = curtime() + SafeAlias;
+ unsigned int sleeptime = 2;
- while (atcnt-- >= 0 &&
+ while (isopen &&
map->map_class->map_lookup(map, "@", NULL, &st) == NULL)
{
+ if (curtime() > toolong)
+ {
+ /* we timed out */
+ attimeout = TRUE;
+ break;
+ }
+
/*
** Close and re-open the alias database in case
** the one is mv'ed instead of cp'ed in.
*/
if (tTd(27, 2))
- printf("aliaswait: sleeping\n");
+ printf("aliaswait: sleeping for %d seconds\n",
+ sleeptime);
map->map_class->map_close(map);
- sleep(30);
- map->map_class->map_open(map, O_RDONLY);
+ sleep(sleeptime);
+ sleeptime *= 2;
+ if (sleeptime > 60)
+ sleeptime = 60;
+ isopen = map->map_class->map_open(map, O_RDONLY);
}
}
@@ -322,25 +352,30 @@ aliaswait(map, ext)
{
if (tTd(27, 3))
printf("aliaswait: not rebuildable\n");
- return;
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
}
if (stat(map->map_file, &stb) < 0)
{
if (tTd(27, 3))
printf("aliaswait: no source file\n");
- return;
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
}
mtime = stb.st_mtime;
(void) strcpy(buf, map->map_file);
if (ext != NULL)
(void) strcat(buf, ext);
- if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || atcnt < 0)
+ if (stat(buf, &stb) < 0 || stb.st_mtime < mtime || attimeout)
{
/* database is out of date */
if (AutoRebuild && stb.st_ino != 0 && stb.st_uid == geteuid())
{
message("auto-rebuilding alias database %s", buf);
+ if (isopen)
+ map->map_class->map_close(map);
rebuildaliases(map, TRUE);
+ isopen = map->map_class->map_open(map, O_RDONLY);
}
else
{
@@ -352,6 +387,8 @@ aliaswait(map, ext)
message("Warning: alias database %s out of date", buf);
}
}
+ map->map_mflags &= ~MF_ALIASWAIT;
+ return isopen;
}
/*
** REBUILDALIASES -- rebuild the alias database.
@@ -373,31 +410,37 @@ rebuildaliases(map, automatic)
bool automatic;
{
FILE *af;
- void (*oldsigint)();
+ bool nolock = FALSE;
+ sigfunc_t oldsigint;
if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
return;
-#ifdef LOG
- if (LogLevel > 7)
- {
- syslog(LOG_NOTICE, "alias database %s %srebuilt by %s",
- map->map_file, automatic ? "auto" : "", username());
- }
-#endif /* LOG */
-
/* try to lock the source file */
if ((af = fopen(map->map_file, "r+")) == NULL)
{
- if (tTd(27, 1))
- printf("Can't open %s: %s\n",
- map->map_file, errstring(errno));
- errno = 0;
- return;
+ if ((errno != EACCES && errno != EROFS) || automatic ||
+ (af = fopen(map->map_file, "r")) == NULL)
+ {
+ int saveerr = errno;
+
+ if (tTd(27, 1))
+ printf("Can't open %s: %s\n",
+ map->map_file, errstring(saveerr));
+ if (!automatic)
+ message("newaliases: cannot open %s: %s",
+ map->map_file, errstring(saveerr));
+ errno = 0;
+ return;
+ }
+ nolock = TRUE;
+ message("warning: cannot lock %s: %s",
+ map->map_file, errstring(errno));
}
/* see if someone else is rebuilding the alias file */
- if (!lockfile(fileno(af), map->map_file, LOCK_EX|LOCK_NB))
+ if (!nolock &&
+ !lockfile(fileno(af), map->map_file, NULL, LOCK_EX|LOCK_NB))
{
/* yes, they are -- wait until done */
message("Alias file %s is already being rebuilt",
@@ -405,18 +448,26 @@ rebuildaliases(map, automatic)
if (OpMode != MD_INITALIAS)
{
/* wait for other rebuild to complete */
- (void) lockfile(fileno(af), map->map_file,
+ (void) lockfile(fileno(af), map->map_file, NULL,
LOCK_EX);
}
- (void) fclose(af);
+ (void) xfclose(af, "rebuildaliases1", map->map_file);
errno = 0;
return;
}
- oldsigint = signal(SIGINT, SIG_IGN);
+ oldsigint = setsignal(SIGINT, SIG_IGN);
if (map->map_class->map_open(map, O_RDWR))
{
+#ifdef LOG
+ if (LogLevel > 7)
+ {
+ syslog(LOG_NOTICE, "alias database %s %srebuilt by %s",
+ map->map_file, automatic ? "auto" : "",
+ username());
+ }
+#endif /* LOG */
map->map_mflags |= MF_OPEN|MF_WRITABLE;
readaliases(map, af, automatic);
}
@@ -431,14 +482,14 @@ rebuildaliases(map, automatic)
}
/* close the file, thus releasing locks */
- fclose(af);
+ xfclose(af, "rebuildaliases2", map->map_file);
/* add distinguished entries and close the database */
if (bitset(MF_OPEN, map->map_mflags))
map->map_class->map_close(map);
/* restore the old signal */
- (void) signal(SIGINT, oldsigint);
+ (void) setsignal(SIGINT, oldsigint);
}
/*
** READALIASES -- read and process the alias file.
@@ -519,9 +570,9 @@ readaliases(map, af, automatic)
syserr("554 missing colon");
continue;
}
- if (parseaddr(line, &al, 1, ':', NULL, CurEnv) == NULL)
+ if (parseaddr(line, &al, RF_COPYALL, ':', NULL, CurEnv) == NULL)
{
- syserr("554 illegal alias name");
+ syserr("554 %.40s... illegal alias name", line);
continue;
}
@@ -555,7 +606,8 @@ readaliases(map, af, automatic)
p++;
if (*p == '\0')
break;
- if (parseaddr(p, &bl, -1, ',', &delimptr, CurEnv) == NULL)
+ if (parseaddr(p, &bl, RF_COPYNONE, ',',
+ &delimptr, CurEnv) == NULL)
usrerr("553 %s... bad address", p);
p = delimptr;
}
@@ -586,7 +638,8 @@ readaliases(map, af, automatic)
}
if (al.q_mailer != LocalMailer)
{
- syserr("554 cannot alias non-local names");
+ syserr("554 %s... cannot alias non-local names",
+ al.q_paddr);
continue;
}
@@ -653,10 +706,6 @@ forward(user, sendq, e)
{
char *pp;
char *ep;
-#ifdef HASSETEUID
- register ADDRESS *ca;
- uid_t saveduid, uid;
-#endif
if (tTd(27, 1))
printf("forward(%s)\n", user->q_paddr);
@@ -676,14 +725,6 @@ forward(user, sendq, e)
if (ForwardPath == NULL)
ForwardPath = newstr("\201z/.forward");
-#ifdef HASSETEUID
- ca = getctladdr(user);
- if (ca != NULL)
- uid = ca->q_uid;
- else
- uid = DefUid;
-#endif
-
for (pp = ForwardPath; pp != NULL; pp = ep)
{
int err;
@@ -698,33 +739,10 @@ forward(user, sendq, e)
if (tTd(27, 3))
printf("forward: trying %s\n", buf);
- if (tTd(27, 9))
- printf("forward: old uid = %d/%d\n", getuid(), geteuid());
-
-#ifdef HASSETEUID
- saveduid = geteuid();
- if (saveduid == 0 && uid != 0)
- (void) seteuid(uid);
-#endif
-
- if (tTd(27, 9))
- printf("forward: new uid = %d/%d\n", getuid(), geteuid());
-
err = include(buf, TRUE, user, sendq, e);
-
-#ifdef HASSETEUID
- if (saveduid == 0 && uid != 0)
- if (seteuid(saveduid) < 0)
- syserr("seteuid(%d) failure (real=%d, eff=%d)",
- saveduid, getuid(), geteuid());
-#endif
-
- if (tTd(27, 9))
- printf("forward: reset uid = %d/%d\n", getuid(), geteuid());
-
if (err == 0)
break;
- if (transienterror(err))
+ else if (transienterror(err))
{
/* we have to suspend this message */
if (tTd(27, 2))
@@ -732,10 +750,11 @@ forward(user, sendq, e)
#ifdef LOG
if (LogLevel > 2)
syslog(LOG_ERR, "%s: forward %s: transient error: %s",
- e->e_id, buf, errstring(err));
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ buf, errstring(err));
#endif
message("%s: %s: message queued", buf, errstring(err));
- user->q_flags |= QQUEUEUP|QDONTSEND;
+ user->q_flags |= QQUEUEUP;
return;
}
}
diff --git a/usr.sbin/sendmail/src/aliases b/usr.sbin/sendmail/src/aliases
index 9a9508b7254c..7540eeae3f62 100644
--- a/usr.sbin/sendmail/src/aliases
+++ b/usr.sbin/sendmail/src/aliases
@@ -1,5 +1,5 @@
#
-# @(#)aliases 8.1 (Berkeley) 6/9/93
+# @(#)aliases 8.2 (Berkeley) 3/5/94
#
# Aliases in this file will NOT be expanded in the header from
# Mail, but WILL be visible over networks or from /bin/mail.
@@ -34,6 +34,7 @@ decode: root
# OFFICIAL CSRG/BUG ADDRESSES
# Ftp maintainer.
+ftp: ftp-bugs
ftp-bugs: bigbug@cs.berkeley.edu
# Distribution office.
diff --git a/usr.sbin/sendmail/src/aliases.5 b/usr.sbin/sendmail/src/aliases.5
index 39f380516ecd..f40f64de10bc 100644
--- a/usr.sbin/sendmail/src/aliases.5
+++ b/usr.sbin/sendmail/src/aliases.5
@@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)aliases.5 8.1 (Berkeley) 6/16/93
+.\" @(#)aliases.5 8.2 (Berkeley) 12/11/93
.\"
-.Dd June 16, 1993
+.Dd December 11, 1993
.Dt ALIASES 5
.Os BSD 4
.Sh NAME
@@ -94,7 +94,7 @@ change to take effect.
If you have compiled
.Xr sendmail
with DBM support instead of NEWDB,
-you may have encounter problems in
+you may have encountered problems in
.Xr dbm 3
restricting a single alias to about 1000 bytes of information.
You can get longer aliases by ``chaining''; that is, make the last name in
diff --git a/usr.sbin/sendmail/src/cdefs.h b/usr.sbin/sendmail/src/cdefs.h
index a04665e30e49..c104b9e964dd 100644
--- a/usr.sbin/sendmail/src/cdefs.h
+++ b/usr.sbin/sendmail/src/cdefs.h
@@ -2,6 +2,9 @@
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
*
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -30,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)cdefs.h 8.1 (Berkeley) 6/2/93
+ * @(#)cdefs.h 8.7 (Berkeley) 1/21/94
*/
#ifndef _CDEFS_H_
@@ -56,39 +59,64 @@
#define __CONCAT(x,y) x ## y
#define __STRING(x) #x
+#define __const const /* define reserved names to standard */
+#define __signed signed
+#define __volatile volatile
+#if defined(__cplusplus)
+#define __inline inline /* convert to C++ keyword */
+#else
+#ifndef __GNUC__
+#define __inline /* delete GCC keyword */
+#endif /* !__GNUC__ */
+#endif /* !__cplusplus */
+
#else /* !(__STDC__ || __cplusplus) */
#define __P(protos) () /* traditional C preprocessor */
#define __CONCAT(x,y) x/**/y
#define __STRING(x) "x"
-#ifdef __GNUC__
-#define const __const /* GCC: ANSI C with -traditional */
-#define inline __inline
-#define signed __signed
-#define volatile __volatile
-
-#else /* !__GNUC__ */
+#ifndef __GNUC__
+#define __const /* delete pseudo-ANSI C keywords */
+#define __inline
+#define __signed
+#define __volatile
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * When using a compiler other than gcc, programs using the ANSI C keywords
+ * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS.
+ * When using "gcc -traditional", we assume that this is the intent; if
+ * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone.
+ */
+#ifndef NO_ANSI_KEYWORDS
#define const /* delete ANSI C keywords */
#define inline
#define signed
#define volatile
+#endif
#endif /* !__GNUC__ */
#endif /* !(__STDC__ || __cplusplus) */
/*
- * GCC has extensions for declaring functions as `pure' (always returns
- * the same value given the same inputs, i.e., has no external state and
- * no side effects) and `dead' (nonreturning). These mainly affect
- * optimization and warnings. Unfortunately, GCC complains if these are
- * used under strict ANSI mode (`gcc -ansi -pedantic'), hence we need to
- * define them only if compiling without this.
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of
+ * these work for GNU C++ (modulo a slight glitch in the C++ grammar
+ * in the distribution version of 2.5.5).
*/
+#if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < 5
+#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-#define __dead __volatile
-#define __pure __const
-#else
-#define __dead
-#define __pure
+#define __dead __volatile
+#define __pure __const
+#endif
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define __dead
+#define __pure
#endif
#endif /* !_CDEFS_H_ */
diff --git a/usr.sbin/sendmail/src/clock.c b/usr.sbin/sendmail/src/clock.c
index 96675c096a72..45ef1c2782c6 100644
--- a/usr.sbin/sendmail/src/clock.c
+++ b/usr.sbin/sendmail/src/clock.c
@@ -33,11 +33,10 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)clock.c 8.2 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)clock.c 8.8 (Berkeley) 1/12/94";
#endif /* not lint */
# include "sendmail.h"
-# include <signal.h>
# ifndef sigmask
# define sigmask(s) (1 << ((s) - 1))
@@ -61,7 +60,7 @@ static char sccsid[] = "@(#)clock.c 8.2 (Berkeley) 7/13/93";
** none.
*/
-static void tick();
+static void tick __P((int));
EVENT *
setevent(intvl, func, arg)
@@ -79,6 +78,7 @@ setevent(intvl, func, arg)
return (NULL);
}
+ (void) setsignal(SIGALRM, SIG_IGN);
(void) time(&now);
/* search event queue for correct position */
@@ -101,7 +101,7 @@ setevent(intvl, func, arg)
printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
intvl, now + intvl, func, arg, ev);
- tick();
+ tick(0);
return (ev);
}
/*
@@ -128,7 +128,7 @@ clrevent(ev)
return;
/* find the parent event */
- (void) signal(SIGALRM, SIG_IGN);
+ (void) setsignal(SIGALRM, SIG_IGN);
for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
{
if (*evp == ev)
@@ -143,7 +143,7 @@ clrevent(ev)
}
/* restore clocks and pick up anything spare */
- tick();
+ tick(0);
}
/*
** TICK -- take a clock tick
@@ -151,7 +151,7 @@ clrevent(ev)
** Called by the alarm clock. This routine runs events as needed.
**
** Parameters:
-** none.
+** One that is ignored; for compatibility with signal handlers.
**
** Returns:
** none.
@@ -161,16 +161,18 @@ clrevent(ev)
*/
static void
-tick()
+tick(arg)
+ int arg;
{
register time_t now;
register EVENT *ev;
int mypid = getpid();
+ int olderrno = errno;
#ifdef SIG_UNBLOCK
sigset_t ss;
#endif
- (void) signal(SIGALRM, SIG_IGN);
+ (void) setsignal(SIGALRM, SIG_IGN);
(void) alarm(0);
now = curtime();
@@ -192,19 +194,6 @@ tick()
ev->ev_func, ev->ev_arg, ev->ev_pid);
/* we must be careful in here because ev_func may not return */
- (void) signal(SIGALRM, tick);
-#ifdef SIG_UNBLOCK
- /* unblock SIGALRM signal */
- sigemptyset(&ss);
- sigaddset(&ss, SIGALRM);
- sigprocmask(SIG_UNBLOCK, &ss, NULL);
-#else
-#ifdef SIGVTALRM
- /* reset 4.2bsd signal mask to allow future alarms */
- (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
-#endif /* SIGVTALRM */
-#endif /* SIG_UNBLOCK */
-
f = ev->ev_func;
arg = ev->ev_arg;
pid = ev->ev_pid;
@@ -218,13 +207,31 @@ tick()
else
(void) alarm(3);
}
+
+ /* restore signals so that we can take ticks while in ev_func */
+ (void) setsignal(SIGALRM, tick);
+#ifdef SIG_UNBLOCK
+ /* unblock SIGALRM signal */
+ sigemptyset(&ss);
+ sigaddset(&ss, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &ss, NULL);
+#else
+#ifdef SIGVTALRM
+ /* reset 4.2bsd signal mask to allow future alarms */
+ (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
+#endif /* SIGVTALRM */
+#endif /* SIG_UNBLOCK */
+
+ /* call ev_func */
+ errno = olderrno;
(*f)(arg);
(void) alarm(0);
now = curtime();
}
- (void) signal(SIGALRM, tick);
+ (void) setsignal(SIGALRM, tick);
if (EventQueue != NULL)
(void) alarm((unsigned) (EventQueue->ev_time - now));
+ errno = olderrno;
}
/*
** SLEEP -- a version of sleep that works with this stuff
@@ -244,13 +251,16 @@ tick()
*/
static bool SleepDone;
+static int endsleep();
-unsigned int
+#ifndef SLEEP_T
+# define SLEEP_T unsigned int
+#endif
+
+SLEEP_T
sleep(intvl)
unsigned int intvl;
{
- static int endsleep();
-
if (intvl == 0)
return;
SleepDone = FALSE;
diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c
index 4398b8572147..b434d4900eb8 100644
--- a/usr.sbin/sendmail/src/collect.c
+++ b/usr.sbin/sendmail/src/collect.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)collect.c 8.1 (Berkeley) 6/7/93";
+static char sccsid[] = "@(#)collect.c 8.9 (Berkeley) 1/31/94";
#endif /* not lint */
# include <errno.h>
@@ -72,6 +72,7 @@ collect(smtpmode, requeueflag, e)
bool ignrdot = smtpmode ? FALSE : IgnrDot;
char buf[MAXLINE], buf2[MAXLINE];
register char *workbuf, *freebuf;
+ bool inputerr = FALSE;
extern char *hvalue();
extern bool isheader(), flusheol();
@@ -79,7 +80,8 @@ collect(smtpmode, requeueflag, e)
** Create the temp file name and create the file.
*/
- e->e_df = newstr(queuename(e, 'd'));
+ e->e_df = queuename(e, 'd');
+ e->e_df = newstr(e->e_df);
if ((tf = dfopen(e->e_df, O_WRONLY|O_CREAT, FileMode)) == NULL)
{
syserr("Cannot create %s", e->e_df);
@@ -158,7 +160,10 @@ collect(smtpmode, requeueflag, e)
if (sfgets(freebuf, MAXLINE, InChannel,
TimeOuts.to_datablock,
"message header read") == NULL)
- goto readerr;
+ {
+ freebuf[0] = '\0';
+ break;
+ }
/* is this a continuation line? */
if (*freebuf != ' ' && *freebuf != '\t')
@@ -244,7 +249,7 @@ collect(smtpmode, requeueflag, e)
** Collect the body of the message.
*/
- do
+ for (;;)
{
register char *bp = buf;
@@ -255,7 +260,8 @@ collect(smtpmode, requeueflag, e)
break;
/* check for transparent dot */
- if (OpMode == MD_SMTP && bp[0] == '.' && bp[1] == '.')
+ if ((OpMode == MD_SMTP || OpMode == MD_DAEMON) &&
+ bp[0] == '.' && bp[1] == '.')
bp++;
/*
@@ -268,39 +274,64 @@ collect(smtpmode, requeueflag, e)
fputs("\n", tf);
if (ferror(tf))
tferror(tf, e);
- } while (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
- "message body read") != NULL);
+ if (sfgets(buf, MAXLINE, InChannel, TimeOuts.to_datablock,
+ "message body read") == NULL)
+ goto readerr;
+ }
+ if (feof(InChannel) || ferror(InChannel))
+ {
readerr:
+ if (tTd(30, 1))
+ printf("collect: read error\n");
+ inputerr = TRUE;
+ }
+
if (fflush(tf) != 0)
tferror(tf, e);
- (void) fsync(fileno(tf));
- (void) fclose(tf);
+ if (fsync(fileno(tf)) < 0 || fclose(tf) < 0)
+ {
+ syserr("cannot sync message data to disk (%s)", e->e_df);
+ finis();
+ }
/* An EOF when running SMTP is an error */
- if ((feof(InChannel) || ferror(InChannel)) && OpMode == MD_SMTP)
+ if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
{
char *host;
+ char *problem;
host = RealHostName;
if (host == NULL)
host = "localhost";
+ if (feof(InChannel))
+ problem = "unexpected close";
+ else if (ferror(InChannel))
+ problem = "I/O error";
+ else
+ problem = "read timeout";
# ifdef LOG
if (LogLevel > 0 && feof(InChannel))
syslog(LOG_NOTICE,
- "collect: unexpected close on connection from %s, sender=%s: %m\n",
- host, e->e_from.q_paddr);
+ "collect: %s on connection from %s, sender=%s: %m\n",
+ problem, host, e->e_from.q_paddr);
# endif
- (feof(InChannel) ? usrerr : syserr)
- ("451 collect: unexpected close on connection from %s, from=%s",
- host, e->e_from.q_paddr);
+ if (feof(InChannel))
+ usrerr("451 collect: %s on connection from %s, from=%s",
+ problem, host, e->e_from.q_paddr);
+ else
+ syserr("451 collect: %s on connection from %s, from=%s",
+ problem, host, e->e_from.q_paddr);
/* don't return an error indication */
e->e_to = NULL;
e->e_flags &= ~EF_FATALERRS;
+ e->e_flags |= EF_CLRQUEUE;
/* and don't try to deliver the partial message either */
+ if (InChild)
+ ExitStat = EX_QUIT;
finis();
}
@@ -311,6 +342,10 @@ readerr:
eatheader(e, !requeueflag);
+ /* collect statistics */
+ if (OpMode != MD_VERIFY)
+ markstats(e, (ADDRESS *) NULL);
+
/*
** Add an Apparently-To: line if we have no recipient lines.
*/
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
index f87534803fd2..1a9646365b88 100644
--- a/usr.sbin/sendmail/src/conf.c
+++ b/usr.sbin/sendmail/src/conf.c
@@ -33,15 +33,15 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)conf.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)conf.c 8.82 (Berkeley) 3/6/94";
#endif /* not lint */
+# include "sendmail.h"
+# include "pathnames.h"
# include <sys/ioctl.h>
# include <sys/param.h>
-# include <signal.h>
+# include <netdb.h>
# include <pwd.h>
-# include "sendmail.h"
-# include "pathnames.h"
/*
** CONF.C -- Sendmail Configuration Tables.
@@ -87,7 +87,7 @@ struct hdrinfo HdrInfo[] =
"from", H_FROM,
"reply-to", H_FROM,
"full-name", H_ACHECK,
- "return-receipt-to", H_FROM /* |H_RECEIPTTO */,
+ "return-receipt-to", H_FROM|H_RECEIPTTO,
"errors-to", H_FROM|H_ERRORSTO,
/* destination fields */
@@ -128,8 +128,6 @@ struct hdrinfo HdrInfo[] =
** Location of system files/databases/etc.
*/
-char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */
-char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */
char *PidFile = _PATH_SENDMAILPID; /* stores daemon proc id */
@@ -146,7 +144,8 @@ struct prival PrivacyValues[] =
"needvrfyhelo", PRIV_NEEDVRFYHELO,
"noexpn", PRIV_NOEXPN,
"novrfy", PRIV_NOVRFY,
- "restrictmailq", PRIV_RESTRMAILQ,
+ "restrictmailq", PRIV_RESTRICTMAILQ,
+ "restrictqrun", PRIV_RESTRICTQRUN,
"authwarnings", PRIV_AUTHWARNINGS,
"goaway", PRIV_GOAWAY,
NULL, 0,
@@ -159,6 +158,25 @@ struct prival PrivacyValues[] =
*/
int DtableSize = 50; /* max open files; reset in 4.2bsd */
+
+
+/*
+** Following should be config parameters (and probably will be in
+** future releases). In the meantime, setting these is considered
+** unsupported, and is intentionally undocumented.
+*/
+
+#ifdef BROKENSMTPPEERS
+bool BrokenSmtpPeers = TRUE; /* set if you have broken SMTP peers */
+#else
+bool BrokenSmtpPeers = FALSE; /* set if you have broken SMTP peers */
+#endif
+#ifdef NOLOOPBACKCHECK
+bool CheckLoopBack = FALSE; /* set to check HELO loopback */
+#else
+bool CheckLoopBack = TRUE; /* set to check HELO loopback */
+#endif
+
/*
** SETDEFAULTS -- set default values
**
@@ -491,7 +509,12 @@ checkcompat(to, e)
# ifdef lint
if (to == NULL)
to++;
-# endif lint
+# endif /* lint */
+
+ if (tTd(49, 1))
+ printf("checkcompat(to=%s, from=%s)\n",
+ to->q_paddr, e->e_from.q_paddr);
+
# ifdef EXAMPLE_CODE
/* this code is intended as an example only */
register STAB *s;
@@ -508,6 +531,29 @@ checkcompat(to, e)
return (EX_OK);
}
/*
+** SETSIGNAL -- set a signal handler
+**
+** This is essentially old BSD "signal(3)".
+*/
+
+sigfunc_t
+setsignal(sig, handler)
+ int sig;
+ sigfunc_t handler;
+{
+#if defined(SYS5SIGNALS) || defined(BSD4_3) || defined(_AUX_SOURCE)
+ return signal(sig, handler);
+#else
+ struct sigaction n, o;
+
+ bzero(&n, sizeof n);
+ n.sa_handler = handler;
+ if (sigaction(sig, &n, &o) < 0)
+ return SIG_ERR;
+ return o.sa_handler;
+#endif
+}
+ /*
** HOLDSIGS -- arrange to hold all signals
**
** Parameters:
@@ -542,6 +588,25 @@ rlsesigs()
{
}
/*
+** INIT_MD -- do machine dependent initializations
+**
+** Systems that have global modes that should be set should do
+** them here rather than in main.
+*/
+
+#ifdef _AUX_SOURCE
+# include <compat.h>
+#endif
+
+init_md(argc, argv)
+ int argc;
+ char **argv;
+{
+#ifdef _AUX_SOURCE
+ setcompat(getcompat() | COMPAT_BSDPROT);
+#endif
+}
+ /*
** GETLA -- get the current load average
**
** This code stolen from la.c.
@@ -558,71 +623,37 @@ rlsesigs()
/* try to guess what style of load average we have */
#define LA_ZERO 1 /* always return load average as zero */
-#define LA_INT 2 /* read kmem for avenrun; interpret as int */
+#define LA_INT 2 /* read kmem for avenrun; interpret as long */
#define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */
#define LA_SUBR 4 /* call getloadavg */
+#define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
+#define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
+#define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
+/* do guesses based on general OS type */
#ifndef LA_TYPE
-# if defined(sun) && !defined(BSD)
-# define LA_TYPE LA_INT
-# endif
-# if defined(mips) || defined(__alpha)
- /* Ultrix or OSF/1 or RISC/os */
-# define LA_TYPE LA_INT
-# define LA_AVENRUN "avenrun"
-# endif
-# if defined(__hpux)
-# define LA_TYPE LA_FLOAT
-# define LA_AVENRUN "avenrun"
-# endif
-# if defined(__NeXT__)
-# define LA_TYPE LA_ZERO
-# endif
-
-/* now do the guesses based on general OS type */
-# ifndef LA_TYPE
-# if defined(SYSTEM5)
-# define LA_TYPE LA_INT
-# define LA_AVENRUN "avenrun"
-# else
-# if defined(BSD)
-# define LA_TYPE LA_SUBR
-# else
-# define LA_TYPE LA_ZERO
-# endif
-# endif
-# endif
+# define LA_TYPE LA_ZERO
#endif
-#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT)
+#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT)
#include <nlist.h>
#ifndef LA_AVENRUN
-#define LA_AVENRUN "_avenrun"
+# ifdef SYSTEM5
+# define LA_AVENRUN "avenrun"
+# else
+# define LA_AVENRUN "_avenrun"
+# endif
#endif
/* _PATH_UNIX should be defined in <paths.h> */
#ifndef _PATH_UNIX
-# if defined(__hpux)
-# define _PATH_UNIX "/hp-ux"
-# endif
-# if defined(mips) && !defined(ultrix)
- /* powerful RISC/os */
-# define _PATH_UNIX "/unix"
-# endif
-# if defined(Solaris2)
- /* Solaris 2 */
-# define _PATH_UNIX "/kernel/unix"
-# endif
-# if defined(SYSTEM5)
-# ifndef _PATH_UNIX
-# define _PATH_UNIX "/unix"
-# endif
-# endif
-# ifndef _PATH_UNIX
-# define _PATH_UNIX "/vmunix"
-# endif
+# if defined(SYSTEM5)
+# define _PATH_UNIX "/unix"
+# else
+# define _PATH_UNIX "/vmunix"
+# endif
#endif
struct nlist Nl[] =
@@ -641,12 +672,12 @@ struct nlist Nl[] =
# define FSHIFT 10
# endif
-# if (LA_TYPE == LA_INT)
+# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
# define FSHIFT 8
# endif
#endif
-#if (LA_TYPE == LA_INT) && !defined(FSCALE)
+#if ((LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)) && !defined(FSCALE)
# define FSCALE (1 << FSHIFT)
#endif
@@ -656,7 +687,11 @@ getla()
#if LA_TYPE == LA_INT
long avenrun[3];
#else
+# if LA_TYPE == LA_SHORT
+ short avenrun[3];
+# else
double avenrun[3];
+# endif
#endif
extern off_t lseek();
extern int errno;
@@ -697,7 +732,7 @@ getla()
printf("getla: lseek or read: %s\n", errstring(errno));
return (-1);
}
-#if LA_TYPE == LA_INT
+#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
if (tTd(3, 5))
{
printf("getla: avenrun = %d", avenrun[0]);
@@ -725,6 +760,22 @@ getla()
#else
#if LA_TYPE == LA_SUBR
+#ifdef DGUX
+
+#include <sys/dg_sys_info.h>
+
+int getla()
+{
+ struct dg_sys_info_load_info load_info;
+
+ dg_sys_info((long *)&load_info,
+ DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
+
+ return((int) (load_info.one_minute + 0.5));
+}
+
+#else
+
getla()
{
double avenrun[3];
@@ -740,6 +791,88 @@ getla()
return ((int) (avenrun[0] + 0.5));
}
+#endif /* DGUX */
+#else
+#if LA_TYPE == LA_MACH
+
+/*
+** This has been tested on NEXTSTEP release 2.1/3.X.
+*/
+
+#if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
+# include <mach/mach.h>
+#else
+# include <mach.h>
+#endif
+
+getla()
+{
+ processor_set_t default_set;
+ kern_return_t error;
+ unsigned int info_count;
+ struct processor_set_basic_info info;
+ host_t host;
+
+ error = processor_set_default(host_self(), &default_set);
+ if (error != KERN_SUCCESS)
+ return -1;
+ info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
+ if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
+ &host, (processor_set_info_t)&info,
+ &info_count) != KERN_SUCCESS)
+ {
+ return -1;
+ }
+ return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
+}
+
+
+#else
+#if LA_TYPE == LA_PROCSTR
+
+/*
+** Read /proc/loadavg for the load average. This is assumed to be
+** in a format like "0.15 0.12 0.06".
+**
+** Initially intended for Linux. This has been in the kernel
+** since at least 0.99.15.
+*/
+
+# ifndef _PATH_LOADAVG
+# define _PATH_LOADAVG "/proc/loadavg"
+# endif
+
+int
+getla()
+{
+ double avenrun;
+ register int result;
+ FILE *fp;
+
+ fp = fopen(_PATH_LOADAVG, "r");
+ if (fp == NULL)
+ {
+ if (tTd(3, 1))
+ printf("getla: fopen(%s): %s\n",
+ _PATH_LOADAVG, errstring(errno));
+ return -1;
+ }
+ result = fscanf(fp, "%lf", &avenrun);
+ fclose(fp);
+ if (result != 1)
+ {
+ if (tTd(3, 1))
+ printf("getla: fscanf() = %d: %s\n",
+ result, errstring(errno));
+ return -1;
+ }
+
+ if (tTd(3, 1))
+ printf("getla(): %.2f\n", avenrun);
+
+ return ((int) (avenrun + 0.5));
+}
+
#else
getla()
@@ -751,6 +884,55 @@ getla()
#endif
#endif
+#endif
+#endif
+
+
+/*
+ * Copyright 1989 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. M.I.T. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Many and varied...
+ */
+
+/* Non Apollo stuff removed by Don Lewis 11/15/93 */
+#ifndef lint
+static char rcsid[] = "@(#)$Id: conf.c,v 1.5.2.1 1994/04/18 03:53:45 rgrimes Exp $";
+#endif /* !lint */
+
+#ifdef apollo
+# undef volatile
+# include <apollo/base.h>
+
+/* ARGSUSED */
+int getloadavg( call_data )
+ caddr_t call_data; /* pointer to (double) return value */
+{
+ double *avenrun = (double *) call_data;
+ int i;
+ status_$t st;
+ long loadav[3];
+ proc1_$get_loadav(loadav, &st);
+ *avenrun = loadav[0] / (double) (1 << 16);
+ return(0);
+}
+# endif /* apollo */
/*
** SHOULDQUEUE -- should this message be queued or sent?
**
@@ -822,12 +1004,19 @@ refuseconnections()
*/
#ifdef SETPROCTITLE
+# ifdef HASSETPROCTITLE
+ *** ERROR *** Cannot have both SETPROCTITLE and HASSETPROCTITLE defined
+# endif
# ifdef __hpux
# include <sys/pstat.h>
# endif
# ifdef BSD4_4
# include <machine/vmparam.h>
# include <sys/exec.h>
+# ifdef __bsdi__
+# undef PS_STRINGS /* BSDI 1.0 doesn't do PS_STRINGS as we expect */
+# define PROCTITLEPAD '\0'
+# endif
# ifdef PS_STRINGS
# define SETPROC_STATIC static
# endif
@@ -837,6 +1026,12 @@ refuseconnections()
# endif
#endif
+#ifndef PROCTITLEPAD
+# define PROCTITLEPAD ' '
+#endif
+
+#ifndef HASSETPROCTITLE
+
/*VARARGS1*/
#ifdef __STDC__
setproctitle(char *fmt, ...)
@@ -886,11 +1081,13 @@ setproctitle(fmt, va_alist)
(void) strcpy(Argv[0], buf);
p = &Argv[0][i];
while (p < LastArgv)
- *p++ = ' ';
+ *p++ = PROCTITLEPAD;
# endif
# endif
# endif /* SETPROCTITLE */
}
+
+#endif
/*
** REAPCHILD -- pick up the body of my child, lest it become a zombie
**
@@ -904,12 +1101,11 @@ setproctitle(fmt, va_alist)
** Picks up extant zombies.
*/
-# include <sys/wait.h>
-
void
reapchild()
{
-# if defined(WIFEXITED) && !defined(__NeXT__)
+ int olderrno = errno;
+# ifdef HASWAITPID
auto int status;
int count;
int pid;
@@ -937,9 +1133,10 @@ reapchild()
continue;
# endif /* WNOHANG */
# endif
-# ifdef SYSTEM5
- (void) signal(SIGCHLD, reapchild);
+# ifdef SYS5SIGNALS
+ (void) setsignal(SIGCHLD, reapchild);
# endif
+ errno = olderrno;
}
/*
** UNSETENV -- remove a variable from the environment
@@ -960,7 +1157,7 @@ reapchild()
** Modifies environ.
*/
-#ifdef UNSETENV
+#ifndef HASUNSETENV
void
unsetenv(name)
@@ -981,7 +1178,7 @@ unsetenv(name)
*pp = pp[1];
}
-#endif /* UNSETENV */
+#endif
/*
** GETDTABLESIZE -- return number of file descriptors
**
@@ -1011,11 +1208,11 @@ getdtsize()
return rl.rlim_cur;
#endif
-# if defined(_SC_OPEN_MAX) && !defined(NO_SYSCONF)
- return sysconf(_SC_OPEN_MAX);
-# else
-# ifdef HASGETDTABLESIZE
+# ifdef HASGETDTABLESIZE
return getdtablesize();
+# else
+# ifdef _SC_OPEN_MAX
+ return sysconf(_SC_OPEN_MAX);
# else
return NOFILE;
# endif
@@ -1090,12 +1287,6 @@ uname(name)
*/
#ifndef HASINITGROUPS
-# if !defined(SYSTEM5) || defined(__hpux)
-# define HASINITGROUPS
-# endif
-#endif
-
-#ifndef HASINITGROUPS
initgroups(name, basegid)
char *name;
@@ -1114,61 +1305,317 @@ initgroups(name, basegid)
pid_t
setsid __P ((void))
{
-# ifdef SYSTEM5
+#ifdef TIOCNOTTY
+ int fd;
+
+ fd = open("/dev/tty", 2);
+ if (fd >= 0)
+ {
+ (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
+ (void) close(fd);
+ }
+#endif /* TIOCNOTTY */
+# ifdef SYS5SETPGRP
return setpgrp();
# else
- return 0;
+ return setpgid(0, getpid());
# endif
}
#endif
/*
-** ENOUGHSPACE -- check to see if there is enough free space on the queue fs
+** DGUX_INET_ADDR -- inet_addr for DG/UX
**
-** Only implemented if you have statfs.
+** Data General DG/UX version of inet_addr returns a struct in_addr
+** instead of a long. This patches things.
+*/
+
+#ifdef DGUX
+
+#undef inet_addr
+
+long
+dgux_inet_addr(host)
+ char *host;
+{
+ struct in_addr haddr;
+
+ haddr = inet_addr(host);
+ return haddr.s_addr;
+}
+
+#endif
+ /*
+** GETOPT -- for old systems or systems with bogus implementations
+*/
+
+#ifdef NEEDGETOPT
+
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+
+/*
+** this version hacked to add `atend' flag to allow state machine
+** to reset if invoked by the program to scan args for a 2nd time
+*/
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+
+/*
+ * get option letter from argument vector
+ */
+#ifdef _CONVEX_SOURCE
+extern int optind, opterr;
+#else
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+#endif
+int optopt; /* character checked for validity */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define EMSG ""
+#define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \
+ fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
+
+getopt(nargc,nargv,ostr)
+ int nargc;
+ char *const *nargv;
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ static char atend = 0;
+ register char *oli; /* option letter list index */
+
+ if (atend) {
+ atend = 0;
+ place = EMSG;
+ }
+ if(!*place) { /* update scanning pointer */
+ if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
+ atend++;
+ return(EOF);
+ }
+ if (*place == '-') { /* found "--" */
+ ++optind;
+ atend++;
+ return(EOF);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
+ if (!*place) ++optind;
+ tell(": illegal option -- ");
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place) ++optind;
+ }
+ else { /* need an argument */
+ if (*place) optarg = place; /* no white space */
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ tell(": option requires an argument -- ");
+ }
+ else optarg = nargv[optind]; /* white space */
+ place = EMSG;
+ ++optind;
+ }
+ return(optopt); /* dump back option letter */
+}
+
+#endif
+ /*
+** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version
+*/
+
+#ifdef NEEDVPRINTF
+
+#define MAXARG 16
+
+vfprintf(fp, fmt, ap)
+ FILE * fp;
+ char * fmt;
+ char ** ap;
+{
+ char * bp[MAXARG];
+ int i = 0;
+
+ while (*ap && i < MAXARG)
+ bp[i++] = *ap++;
+ fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3],
+ bp[4], bp[5], bp[6], bp[7],
+ bp[8], bp[9], bp[10], bp[11],
+ bp[12], bp[13], bp[14], bp[15]);
+}
+
+vsprintf(s, fmt, ap)
+ char * s;
+ char * fmt;
+ char ** ap;
+{
+ char * bp[MAXARG];
+ int i = 0;
+
+ while (*ap && i < MAXARG)
+ bp[i++] = *ap++;
+ sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3],
+ bp[4], bp[5], bp[6], bp[7],
+ bp[8], bp[9], bp[10], bp[11],
+ bp[12], bp[13], bp[14], bp[15]);
+}
+
+#endif
+ /*
+** USERSHELLOK -- tell if a user's shell is ok for unrestricted use
**
** Parameters:
-** msize -- the size to check against. If zero, we don't yet
-** know how big the message will be, so just check for
-** a "reasonable" amount.
+** shell -- the user's shell from /etc/passwd
**
** Returns:
-** TRUE if there is enough space.
-** FALSE otherwise.
+** TRUE -- if it is ok to use this for unrestricted access.
+** FALSE -- if the shell is restricted.
*/
-#ifndef HASSTATFS
-# if defined(BSD4_4) || defined(__osf__)
-# define HASSTATFS
+#if !HASGETUSERSHELL
+
+# ifndef _PATH_SHELLS
+# define _PATH_SHELLS "/etc/shells"
# endif
+
+char *DefaultUserShells[] =
+{
+ "/bin/sh",
+ "/usr/bin/sh",
+ "/bin/csh",
+ "/usr/bin/csh",
+#ifdef __hpux
+ "/bin/rsh",
+ "/bin/ksh",
+ "/bin/rksh",
+ "/bin/pam",
+ "/usr/bin/keysh",
+ "/bin/posix/sh",
#endif
+ NULL
+};
-#ifdef HASSTATFS
-# undef HASUSTAT
#endif
-#if defined(HASUSTAT)
-# include <ustat.h>
+#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
+
+bool
+usershellok(shell)
+ char *shell;
+{
+#if HASGETUSERSHELL
+ register char *p;
+ extern char *getusershell();
+
+ setusershell();
+ while ((p = getusershell()) != NULL)
+ if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
+ break;
+ endusershell();
+ return p != NULL;
+#else
+ register FILE *shellf;
+ char buf[MAXLINE];
+
+ shellf = fopen(_PATH_SHELLS, "r");
+ if (shellf == NULL)
+ {
+ /* no /etc/shells; see if it is one of the std shells */
+ char **d;
+
+ for (d = DefaultUserShells; *d != NULL; d++)
+ {
+ if (strcmp(shell, *d) == 0)
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ while (fgets(buf, sizeof buf, shellf) != NULL)
+ {
+ register char *p, *q;
+
+ p = buf;
+ while (*p != '\0' && *p != '#' && *p != '/')
+ p++;
+ if (*p == '#' || *p == '\0')
+ continue;
+ q = p;
+ while (*p != '\0' && *p != '#' && !isspace(*p))
+ p++;
+ *p = '\0';
+ if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
+ {
+ fclose(shellf);
+ return TRUE;
+ }
+ }
+ fclose(shellf);
+ return FALSE;
#endif
+}
+ /*
+** FREESPACE -- see how much free space is on the queue filesystem
+**
+** Only implemented if you have statfs.
+**
+** Parameters:
+** dir -- the directory in question.
+** bsize -- a variable into which the filesystem
+** block size is stored.
+**
+** Returns:
+** The number of bytes free on the queue filesystem.
+** -1 if the statfs call fails.
+**
+** Side effects:
+** Puts the filesystem block size into bsize.
+*/
-#ifdef HASSTATFS
-# if defined(sgi) || defined(apollo)
-# include <sys/statfs.h>
-# else
-# if (defined(sun) && !defined(BSD)) || defined(__hpux)
-# include <sys/vfs.h>
-# else
-# include <sys/mount.h>
-# endif
-# endif
+/* statfs types */
+#define SFS_NONE 0 /* no statfs implementation */
+#define SFS_USTAT 1 /* use ustat */
+#define SFS_4ARGS 2 /* use four-argument statfs call */
+#define SFS_VFS 3 /* use <sys/vfs.h> implementation */
+#define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
+#define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
+
+#ifndef SFS_TYPE
+# define SFS_TYPE SFS_NONE
#endif
-bool
-enoughspace(msize)
- long msize;
+#if SFS_TYPE == SFS_USTAT
+# include <ustat.h>
+#endif
+#if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
+# include <sys/statfs.h>
+#endif
+#if SFS_TYPE == SFS_VFS
+# include <sys/vfs.h>
+#endif
+#if SFS_TYPE == SFS_MOUNT
+# include <sys/mount.h>
+#endif
+
+long
+freespace(dir, bsize)
+ char *dir;
+ long *bsize;
{
-#if defined(HASSTATFS) || defined(HASUSTAT)
-# if defined(HASUSTAT)
+#if SFS_TYPE != SFS_NONE
+# if SFS_TYPE == SFS_USTAT
struct ustat fs;
struct stat statbuf;
# define FSBLOCKSIZE DEV_BSIZE
@@ -1181,46 +1628,81 @@ enoughspace(msize)
# else
struct statfs fs;
# define FSBLOCKSIZE fs.f_bsize
+# if defined(_SCO_unix_) || defined(IRIX) || defined(apollo)
+# define f_bavail f_bfree
+# endif
# endif
# endif
extern int errno;
- if (MinBlocksFree <= 0 && msize <= 0)
- {
- if (tTd(4, 80))
- printf("enoughspace: no threshold\n");
- return TRUE;
- }
-
-# if defined(HASUSTAT)
- if (stat(QueueDir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
+# if SFS_TYPE == SFS_USTAT
+ if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
# else
-# if defined(sgi) || defined(apollo)
- if (statfs(QueueDir, &fs, sizeof fs, 0) == 0)
+# if SFS_TYPE == SFS_4ARGS
+ if (statfs(dir, &fs, sizeof fs, 0) == 0)
# else
# if defined(ultrix)
- if (statfs(QueueDir, &fs) > 0)
+ if (statfs(dir, &fs) > 0)
# else
- if (statfs(QueueDir, &fs) == 0)
+ if (statfs(dir, &fs) == 0)
# endif
# endif
# endif
{
+ if (bsize != NULL)
+ *bsize = FSBLOCKSIZE;
+ return (fs.f_bavail);
+ }
+#endif
+ return (-1);
+}
+ /*
+** ENOUGHSPACE -- check to see if there is enough free space on the queue fs
+**
+** Only implemented if you have statfs.
+**
+** Parameters:
+** msize -- the size to check against. If zero, we don't yet
+** know how big the message will be, so just check for
+** a "reasonable" amount.
+**
+** Returns:
+** TRUE if there is enough space.
+** FALSE otherwise.
+*/
+
+bool
+enoughspace(msize)
+ long msize;
+{
+ long bfree, bsize;
+
+ if (MinBlocksFree <= 0 && msize <= 0)
+ {
+ if (tTd(4, 80))
+ printf("enoughspace: no threshold\n");
+ return TRUE;
+ }
+
+ if ((bfree = freespace(QueueDir, &bsize)) >= 0)
+ {
if (tTd(4, 80))
printf("enoughspace: bavail=%ld, need=%ld\n",
- fs.f_bavail, msize);
+ bfree, msize);
/* convert msize to block count */
- msize = msize / FSBLOCKSIZE + 1;
+ msize = msize / bsize + 1;
if (MinBlocksFree >= 0)
msize += MinBlocksFree;
- if (fs.f_bavail < msize)
+ if (bfree < msize)
{
#ifdef LOG
if (LogLevel > 0)
- syslog(LOG_ALERT, "%s: low on space (have %ld, need %ld)",
- QueueDir, fs.f_bavail, msize);
+ syslog(LOG_ALERT,
+ "%s: low on space (have %ld, %s needs %ld in %s)",
+ CurEnv->e_id, bfree,
+ CurHostName, msize, QueueDir);
#endif
return FALSE;
}
@@ -1228,7 +1710,6 @@ enoughspace(msize)
else if (tTd(4, 80))
printf("enoughspace failure: min=%ld, need=%ld: %s\n",
MinBlocksFree, msize, errstring(errno));
-#endif
return TRUE;
}
/*
@@ -1322,7 +1803,10 @@ transienterror(err)
#ifdef EADDRNOTAVAIL
case EADDRNOTAVAIL: /* Can't assign requested address */
#endif
-#ifdef ENOSR
+#ifdef ETXTBSY
+ case ETXTBSY: /* (Apollo) file locked */
+#endif
+#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
case ENOSR: /* Out of streams resources */
#endif
return TRUE;
@@ -1332,11 +1816,12 @@ transienterror(err)
return FALSE;
}
/*
-** LOCKFILE -- lock a file using flock or (shudder) lockf
+** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
**
** Parameters:
** fd -- the file descriptor of the file.
** filename -- the file name (for error messages).
+** ext -- the filename extension.
** type -- type of the lock. Bits can be:
** LOCK_EX -- exclusive lock.
** LOCK_NB -- non-blocking.
@@ -1347,15 +1832,20 @@ transienterror(err)
*/
bool
-lockfile(fd, filename, type)
+lockfile(fd, filename, ext, type)
int fd;
char *filename;
+ char *ext;
int type;
{
-# ifdef LOCKF
+# if !HASFLOCK
int action;
struct flock lfd;
+ if (ext == NULL)
+ ext = "";
+
+ bzero(&lfd, sizeof lfd);
if (bitset(LOCK_UN, type))
lfd.l_type = F_UNLCK;
else if (bitset(LOCK_EX, type))
@@ -1368,19 +1858,492 @@ lockfile(fd, filename, type)
else
action = F_SETLKW;
- lfd.l_whence = lfd.l_start = lfd.l_len = 0;
+ if (tTd(55, 60))
+ printf("lockfile(%s%s, action=%d, type=%d): ",
+ filename, ext, action, lfd.l_type);
if (fcntl(fd, action, &lfd) >= 0)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
return TRUE;
+ }
+
+ if (tTd(55, 60))
+ printf("(%s) ", errstring(errno));
+
+ /*
+ ** On SunOS, if you are testing using -oQ/tmp/mqueue or
+ ** -oA/tmp/aliases or anything like that, and /tmp is mounted
+ ** as type "tmp" (that is, served from swap space), the
+ ** previous fcntl will fail with "Invalid argument" errors.
+ ** Since this is fairly common during testing, we will assume
+ ** that this indicates that the lock is successfully grabbed.
+ */
+
+ if (errno == EINVAL)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
+ return TRUE;
+ }
if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN))
- syserr("cannot lockf(%s, %o)", filename, type);
+ {
+ int omode = -1;
+# ifdef F_GETFL
+ int oerrno = errno;
+
+ (void) fcntl(fd, F_GETFL, &omode);
+ errno = oerrno;
+# endif
+ syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
+ filename, ext, fd, type, omode, geteuid());
+ }
# else
+ if (ext == NULL)
+ ext = "";
+
+ if (tTd(55, 60))
+ printf("lockfile(%s%s, type=%o): ", filename, ext, type);
+
if (flock(fd, type) >= 0)
+ {
+ if (tTd(55, 60))
+ printf("SUCCESS\n");
return TRUE;
+ }
+
+ if (tTd(55, 60))
+ printf("(%s) ", errstring(errno));
if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK)
- syserr("cannot flock(%s, %o)", filename, type);
+ {
+ int omode = -1;
+# ifdef F_GETFL
+ int oerrno = errno;
+
+ (void) fcntl(fd, F_GETFL, &omode);
+ errno = oerrno;
+# endif
+ syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
+ filename, ext, fd, type, omode, geteuid());
+ }
# endif
+ if (tTd(55, 60))
+ printf("FAIL\n");
+ return FALSE;
+}
+ /*
+** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
+**
+** Parameters:
+** fd -- the file descriptor to check.
+**
+** Returns:
+** TRUE -- if only root can chown the file to an arbitrary
+** user.
+** FALSE -- if an arbitrary user can give away a file.
+*/
+
+#if defined(__FreeBSD__) && defined(_POSIX_CHOWN_RESTRICTED)
+# undef _POSIX_CHOWN_RESTRICTED
+# define _POSIX_CHOWN_RESTRICTED 1
+#endif
+
+bool
+chownsafe(fd)
+ int fd;
+{
+#ifdef __hpux
+ char *s;
+ int tfd;
+ uid_t o_uid, o_euid;
+ gid_t o_gid, o_egid;
+ bool rval;
+ struct stat stbuf;
+
+ o_uid = getuid();
+ o_euid = geteuid();
+ o_gid = getgid();
+ o_egid = getegid();
+ fstat(fd, &stbuf);
+ setresuid(stbuf.st_uid, stbuf.st_uid, -1);
+ setresgid(stbuf.st_gid, stbuf.st_gid, -1);
+ s = tmpnam(NULL);
+ tfd = open(s, O_RDONLY|O_CREAT, 0600);
+ rval = fchown(tfd, DefUid, DefGid) != 0;
+ close(tfd);
+ unlink(s);
+ setreuid(o_uid, o_euid);
+ setresgid(o_gid, o_egid, -1);
+ return rval;
+#else
+# ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED == -1
+ return FALSE;
+# else
+ return TRUE;
+# endif
+# else
+# ifdef _PC_CHOWN_RESTRICTED
+ return fpathconf(fd, _PC_CHOWN_RESTRICTED) > 0;
+# else
+# ifdef BSD
+ return TRUE;
+# else
+ return FALSE;
+# endif
+# endif
+# endif
+#endif
+}
+ /*
+** GETCFNAME -- return the name of the .cf file.
+**
+** Some systems (e.g., NeXT) determine this dynamically.
+*/
+
+char *
+getcfname()
+{
+ if (ConfFile != NULL)
+ return ConfFile;
+#ifdef NETINFO
+ {
+ extern char *ni_propval();
+ char *cflocation;
+
+ cflocation = ni_propval("/locations/sendmail", "sendmail.cf");
+ if (cflocation != NULL)
+ return cflocation;
+ }
+#endif
+ return _PATH_SENDMAILCF;
+}
+ /*
+** SETVENDOR -- process vendor code from V configuration line
+**
+** Parameters:
+** vendor -- string representation of vendor.
+**
+** Returns:
+** TRUE -- if ok.
+** FALSE -- if vendor code could not be processed.
+**
+** Side Effects:
+** It is reasonable to set mode flags here to tweak
+** processing in other parts of the code if necessary.
+** For example, if you are a vendor that uses $%y to
+** indicate YP lookups, you could enable that here.
+*/
+
+bool
+setvendor(vendor)
+ char *vendor;
+{
+ if (strcasecmp(vendor, "Berkeley") == 0)
+ return TRUE;
+
+ /* add vendor extensions here */
+
return FALSE;
}
+ /*
+** STRTOL -- convert string to long integer
+**
+** For systems that don't have it in the C library.
+**
+** This is taken verbatim from the 4.4-Lite C library.
+*/
+
+#ifdef NEEDSTRTOL
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+
+long
+strtol(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
+{
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+
+#endif
+ /*
+** SOLARIS_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
+**
+** Solaris versions prior through 2.3 don't properly deliver a
+** canonical h_name field. This tries to work around it.
+*/
+
+#ifdef SOLARIS
+
+struct hostent *
+solaris_gethostbyname(name)
+ const char *name;
+{
+# ifdef SOLARIS_2_3
+ static struct hostent hp;
+ static char buf[1000];
+ extern struct hostent *_switch_gethostbyname_r();
+
+ return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
+# else
+ extern struct hostent *__switch_gethostbyname();
+
+ return __switch_gethostbyname(name);
+# endif
+}
+
+struct hostent *
+solaris_gethostbyaddr(addr, len, type)
+ const char *addr;
+ int len;
+ int type;
+{
+# ifdef SOLARIS_2_3
+ static struct hostent hp;
+ static char buf[1000];
+ extern struct hostent *_switch_gethostbyaddr_r();
+
+ return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno);
+# else
+ extern struct hostent *__switch_gethostbyaddr();
+
+ return __switch_gethostbyaddr(addr, len, type);
+# endif
+}
+
+#endif
+ /*
+** NI_PROPVAL -- netinfo property value lookup routine
+**
+** Parameters:
+** directory -- the Netinfo directory name.
+** propname -- the Netinfo property name.
+**
+** Returns:
+** NULL -- if:
+** 1. the directory is not found
+** 2. the property name is not found
+** 3. the property contains multiple values
+** 4. some error occured
+** else -- the location of the config file.
+**
+** Notes:
+** Caller should free the return value of ni_proval
+*/
+
+#ifdef NETINFO
+
+# include <netinfo/ni.h>
+
+# define LOCAL_NETINFO_DOMAIN "."
+# define PARENT_NETINFO_DOMAIN ".."
+# define MAX_NI_LEVELS 256
+
+char *
+ni_propval(directory, propname)
+ char *directory;
+ char *propname;
+{
+ char *propval = NULL;
+ int i;
+ void *ni = NULL;
+ void *lastni = NULL;
+ ni_status nis;
+ ni_id nid;
+ ni_namelist ninl;
+
+ /*
+ ** If the passed directory and property name are found
+ ** in one of netinfo domains we need to search (starting
+ ** from the local domain moving all the way back to the
+ ** root domain) set propval to the property's value
+ ** and return it.
+ */
+
+ for (i = 0; i < MAX_NI_LEVELS; ++i)
+ {
+ if (i == 0)
+ {
+ nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
+ }
+ else
+ {
+ if (lastni != NULL)
+ ni_free(lastni);
+ lastni = ni;
+ nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
+ }
+
+ /*
+ ** Don't bother if we didn't get a handle on a
+ ** proper domain. This is not necessarily an error.
+ ** We would get a positive ni_status if, for instance
+ ** we never found the directory or property and tried
+ ** to open the parent of the root domain!
+ */
+
+ if (nis != 0)
+ break;
+
+ /*
+ ** Find the path to the server information.
+ */
+
+ if (ni_pathsearch(ni, &nid, directory) != 0)
+ continue;
+
+ /*
+ ** Find "host" information.
+ */
+
+ if (ni_lookupprop(ni, &nid, propname, &ninl) != 0)
+ continue;
+
+ /*
+ ** If there's only one name in
+ ** the list, assume we've got
+ ** what we want.
+ */
+
+ if (ninl.ni_namelist_len == 1)
+ {
+ propval = ni_name_dup(ninl.ni_namelist_val[0]);
+ break;
+ }
+ }
+
+ /*
+ ** Clean up.
+ */
+
+ if (ni != NULL)
+ ni_free(ni);
+ if (lastni != NULL && ni != lastni)
+ ni_free(lastni);
+
+ return propval;
+}
+
+#endif /* NETINFO */
+ /*
+** HARD_SYSLOG -- call syslog repeatedly until it works
+**
+** Needed on HP-UX, which apparently doesn't guarantee that
+** syslog succeeds during interrupt handlers.
+*/
+
+#ifdef __hpux
+
+# define MAXSYSLOGTRIES 100
+# undef syslog
+
+# ifdef __STDC__
+hard_syslog(int pri, char *msg, ...)
+# else
+hard_syslog(pri, msg, va_alist)
+ int pri;
+ char *msg;
+ va_dcl
+# endif
+{
+ int i;
+ char buf[SYSLOG_BUFSIZE * 2];
+ VA_LOCAL_DECL;
+
+ VA_START(msg);
+ vsprintf(buf, msg, ap);
+ VA_END;
+
+ for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; )
+ continue;
+}
+
+#endif
diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h
index e3ea48719830..8341de5cb2de 100644
--- a/usr.sbin/sendmail/src/conf.h
+++ b/usr.sbin/sendmail/src/conf.h
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)conf.h 8.3 (Berkeley) 7/13/93
+ * @(#)conf.h 8.96 (Berkeley) 3/11/94
*/
/*
@@ -39,13 +39,17 @@
*/
# include <sys/param.h>
+# include <sys/types.h>
# include <sys/stat.h>
+# include <sys/file.h>
+# include <sys/wait.h>
# include <fcntl.h>
+# include <signal.h>
-/*
+/**********************************************************************
** Table sizes, etc....
** There shouldn't be much need to change these....
-*/
+**********************************************************************/
# define MAXLINE 2048 /* max line length */
# define MAXNAME 256 /* max length of a name */
@@ -59,146 +63,846 @@
# define MAXKEY 128 /* maximum size of a database key */
# define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */
# define MAXUSERENVIRON 100 /* max envars saved, must be >= 3 */
-# define MAXIPADDR 16 /* max # of IP addrs for this host */
# define MAXALIASDB 12 /* max # of alias databases */
-# define PSBUFSIZE (MAXLINE + MAXATOM) /* size of prescan buffer */
# ifndef QUEUESIZE
# define QUEUESIZE 1000 /* max # of jobs per queue run */
# endif
-/*
+/**********************************************************************
** Compilation options.
**
** #define these if they are available; comment them out otherwise.
-*/
+**********************************************************************/
# define LOG 1 /* enable logging */
# define UGLYUUCP 1 /* output ugly UUCP From lines */
+# define NETUNIX 1 /* include unix domain support */
# define NETINET 1 /* include internet support */
# define SETPROCTITLE 1 /* munge argv to display current status */
-# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */
# define MATCHGECOS 1 /* match user names from gecos field */
# define XDEBUG 1 /* enable extended debugging */
-
# ifdef NEWDB
# define USERDB 1 /* look in user database (requires NEWDB) */
# endif
+/**********************************************************************
+** 0/1 Compilation options.
+** #define these to 1 if they are available;
+** #define them to 0 otherwise.
+**********************************************************************/
+
+# ifndef NAMED_BIND
+# define NAMED_BIND 1 /* use Berkeley Internet Domain Server */
+# endif
+
/*
-** Operating system configuration.
+** Most systems have symbolic links today, so default them on. You
+** can turn them off by #undef'ing this below.
+*/
+
+# define HASLSTAT 1 /* has lstat(2) call */
+
+/*
+** General "standard C" defines.
**
-** Unless you are porting to a new OS, you shouldn't have to
-** change these.
+** These may be undone later, to cope with systems that claim to
+** be Standard C but aren't. Gcc is the biggest offender -- it
+** doesn't realize that the library is part of the language.
+**
+** Life would be much easier if we could get rid of this sort
+** of bozo problems.
*/
-/* general "standard C" defines */
#ifdef __STDC__
-# define HASSETVBUF 1 /* yes, we have setvbuf in libc */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
#endif
-/* general POSIX defines */
-#ifdef _POSIX_VERSION
-# define HASSETSID 1 /* has setsid(2) call */
-#endif
+/**********************************************************************
+** Operating system configuration.
+**
+** Unless you are porting to a new OS, you shouldn't have to
+** change these.
+**********************************************************************/
/*
** Per-Operating System defines
*/
-/* HP-UX -- tested for 8.07 */
+
+/*
+** HP-UX -- tested for 8.07, 9.00, and 9.01.
+*/
+
# ifdef __hpux
+/* avoid m_flags conflict between db.h & sys/sysmacros.h on HP 300 */
+# undef m_flags
# define SYSTEM5 1 /* include all the System V defines */
-# define UNSETENV 1 /* need unsetenv(3) support */
-# define HASSETEUID 1 /* we have seteuid call */
-# define seteuid(uid) setresuid(-1, uid, -1)
-# ifndef __STDC__
-# define HASSETVBUF 1 /* we have setvbuf in libc (but not __STDC__) */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define setreuid(r, e) setresuid(r, e, -1)
+# define LA_TYPE LA_FLOAT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# define GIDSET_T gid_t
+# define _PATH_UNIX "/hp-ux"
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
+# endif
+# define syslog hard_syslog
+# ifdef __STDC__
+extern int syslog(int, char *, ...);
# endif
# endif
-/* IBM AIX 3.x -- actually tested for 3.2.3 */
+
+/*
+** IBM AIX 3.x -- actually tested for 3.2.3
+*/
+
# ifdef _AIX3
-# define LOCKF 1 /* use System V lockf instead of flock */
+# 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 FORK fork /* no vfork primitive available */
-# define UNSETENV 1 /* need unsetenv(3) support */
-# define SYS5TZ 1 /* use System V style timezones */
+# undef SETPROCTITLE /* setproctitle confuses AIX */
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# endif
-/* Silicon Graphics IRIX */
+
+/*
+** Silicon Graphics IRIX
+**
+** Compiles on 4.0.1.
+*/
+
# ifdef IRIX
+# include <sys/sysmacros.h>
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define FORK fork /* no vfork primitive available */
-# define UNSETENV 1 /* need unsetenv(3) support */
-# define setpgrp BSDsetpgrp
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define setpgid BSDsetpgrp
+# define GIDSET_T gid_t
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
# endif
-/* various systems from Sun Microsystems */
+
+/*
+** SunOS and Solaris
+**
+** Tested on SunOS 4.1.x (a.k.a. Solaris 1.1.x) and
+** Solaris 2.2 (a.k.a. SunOS 5.2).
+*/
+
#if defined(sun) && !defined(BSD)
-# define UNSETENV 1 /* need unsetenv(3) support */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
+# define LA_TYPE LA_INT
+
+# ifdef SOLARIS_2_3
+# define SOLARIS
+# endif
# ifdef SOLARIS
- /* Solaris 2.x */
-# define LOCKF 1 /* use System V lockf instead of flock */
-# define HASUSTAT 1 /* has the ustat(2) syscall */
-# define bcopy(s, d, l) (memmove((d), (s), (l)))
-# define bzero(d, l) (memset((d), '\0', (l)))
-# define bcmp(s, d, l) (memcmp((s), (d), (l)))
+ /* Solaris 2.x (a.k.a. SunOS 5.x) */
+# ifndef __svr4__
+# define __svr4__ /* use all System V Releae 4 defines below */
+# endif
# include <sys/time.h>
+# define gethostbyname solaris_gethostbyname /* get working version */
+# define gethostbyaddr solaris_gethostbyaddr /* get working version */
+# define GIDSET_T gid_t
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/kernel/unix"
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/etc/mail/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
+# endif
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
+# endif
# else
- /* SunOS 4.1.x */
-# define HASSTATFS 1 /* has the statfs(2) syscall */
-# define HASSETEUID 1 /* we have seteuid call */
+ /* SunOS 4.0.3 or 4.1.x */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
# include <vfork.h>
+# ifdef SUNOS403
+ /* special tweaking for SunOS 4.0.3 */
+# include <malloc.h>
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# undef WIFEXITED
+# undef WEXITSTATUS
+# undef HASUNAME
+# define setpgid setpgrp
+typedef int pid_t;
+extern char *getenv();
+
+# endif
+# endif
+#endif
+
+/*
+** DG/UX
+**
+** Tested on 5.4.2
+*/
+
+#ifdef DGUX
+# define SYSTEM5 1
+# define LA_TYPE LA_SUBR
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
+# undef SETPROCTITLE
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+
+/* these include files must be included early on DG/UX */
+# include <netinet/in.h>
+# include <arpa/inet.h>
+
+# define inet_addr dgux_inet_addr
+extern long dgux_inet_addr();
#endif
-/* Digital Ultrix 4.2A or 4.3 */
+
+/*
+** Digital Ultrix 4.2A or 4.3
+**
+** Apparently, fcntl locking is broken on 4.2A, in that locks are
+** not dropped when the process exits. This causes major problems,
+** so flock is the only alternative.
+*/
+
#ifdef ultrix
-# define HASSTATFS 1 /* has the statfs(2) syscall */
-# define HASSETEUID 1 /* we have seteuid call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */
+# ifdef vax
+# define LA_TYPE LA_FLOAT
+# else
+# define LA_TYPE LA_INT
+# define LA_AVENRUN "avenrun"
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
#endif
-/* OSF/1 (tested on Alpha) */
+
+/*
+** OSF/1 (tested on Alpha)
+*/
+
#ifdef __osf__
-# define HASSETEUID 1 /* we have seteuid call */
-# define seteuid(uid) setreuid(-1, uid)
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define LA_TYPE LA_INT
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
+# endif
#endif
-/* NeXTstep */
-#ifdef __NeXT__
+
+/*
+** NeXTstep
+*/
+
+#ifdef NeXT
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define WAITUNION 1 /* use "union wait" as wait argument type */
# define sleep sleepX
-# define UNSETENV 1 /* need unsetenv(3) support */
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_MACH
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# ifndef _POSIX_SOURCE
+typedef int pid_t;
+# undef WEXITSTATUS
+# undef WIFEXITED
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/etc/sendmail/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid"
+# endif
#endif
-/* various flavors of BSD */
-#ifdef BSD
-# define HASGETDTABLESIZE 1 /* we have getdtablesize(2) call */
+
+/*
+** 4.4 BSD
+**
+** See also BSD defines.
+*/
+
+#ifdef BSD4_4
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# include <sys/cdefs.h>
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
#endif
-#if defined(NetBSD)
-#define NO_SYSCONF
+
+/*
+** BSD/386 (all versions)
+** From Tony Sanders, BSDI
+*/
+
+#ifdef __bsdi__
+# define HASUNSETENV 1 /* has the unsetenv(3) call */
+# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
+# if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312
+# define HASSETPROCTITLE 1 /* setproctitle is in libc */
+# else
+# define SETPROCTITLE 1
+# endif
+# include <sys/cdefs.h>
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
#endif
-/* 4.4BSD */
-#ifdef BSD4_4
+
+
+/*
+** 386BSD / FreeBSD 1.0E / NetBSD (all architectures, all versions)
+**
+** 4.3BSD clone, closer to 4.4BSD
+**
+** See also BSD defines.
+*/
+
+#if defined(__386BSD__) || defined(__FreeBSD__) || defined(__NetBSD__)
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
# include <sys/cdefs.h>
-# define HASSETEUID 1 /* we have seteuid(2) call */
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# ifndef LA_TYPE
+# define LA_TYPE LA_SUBR
+# endif
+# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
#endif
+
/*
-** End of Per-Operating System defines
+** Mach386
+**
+** For mt Xinu's Mach386 system.
*/
+#if defined(MACH) && defined(i386)
+# define MACH386 1
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define NEEDSTRTOL 1 /* need the strtol() function */
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_FLOAT
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# undef HASSETVBUF /* don't actually have setvbuf(3) */
+# undef WEXITSTATUS
+# undef WIFEXITED
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** 4.3 BSD -- this is for very old systems
+**
+** Should work for mt Xinu MORE/BSD and Mips UMIPS-BSD 2.1.
+**
+** You'll also have to install a new resolver library.
+** I don't guarantee that support for this environment is complete.
+*/
+
+#if defined(oldBSD43) || defined(MORE_BSD) || defined(umipsbsd)
+# define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define ARBPTR_T char *
+# define setpgid setpgrp
+# ifndef LA_TYPE
+# define LA_TYPE LA_FLOAT
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# undef WEXITSTATUS
+# undef WIFEXITED
+typedef short pid_t;
+extern int errno;
+#endif
+
+
+/*
+** SCO Unix
+**
+** This includes two parts -- the first is for SCO Open Server 3.2v4
+** (contributed by Philippe Brand <phb@colombo.telesys-innov.fr>).
+** The second is, I believe, for an older version.
+*/
+
+#ifdef _SCO_unix_4_2
+# define _SCO_unix_
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define _PATH_UNIX "/unix"
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+#ifdef _SCO_unix_
+# 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 FORK fork
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_SHORT
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# undef NETUNIX /* no unix domain socket support */
+#endif
+
+
+/*
+** ConvexOS 11.0 and later
+**
+** "Todd C. Miller" <millert@mroe.cs.colorado.edu> claims this
+** works on 9.1 as well.
+*/
+
+#ifdef _CONVEX_SOURCE
+# define BSD 1 /* include all the BSD defines */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define NEEDGETOPT 1 /* need replacement for getopt(3) */
+# define LA_TYPE LA_FLOAT
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef S_IREAD
+# define S_IREAD _S_IREAD
+# define S_IWRITE _S_IWRITE
+# define S_IEXEC _S_IEXEC
+# define S_IFMT _S_IFMT
+# define S_IFCHR _S_IFCHR
+# define S_IFBLK _S_IFBLK
+# endif
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+#endif
+
+
+/*
+** RISC/os 4.52
+**
+** Gives a ton of warning messages, but otherwise compiles.
+*/
+
+#ifdef RISCOS
+
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+# define WAITUNION 1 /* use "union wait" as wait argument type */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define LA_TYPE LA_INT
+# define LA_AVENRUN "avenrun"
+# define _PATH_UNIX "/unix"
+# undef WIFEXITED
+
+# define setpgid setpgrp
+
+extern int errno;
+typedef int pid_t;
+#define SIGFUNC_DEFINED
+typedef int (*sigfunc_t)();
+extern char *getenv();
+extern void *malloc();
+
+#endif
+
+
+/*
+** Linux 0.99pl10 and above...
+**
+** Thanks to, in reverse order of contact:
+**
+** John Kennedy <warlock@csuchico.edu>
+** Florian La Roche <rzsfl@rz.uni-sb.de>
+** Karl London <karl@borg.demon.co.uk>
+**
+** Last compiled against: [03/02/94 @ 05:34 PM (Wednesday)]
+** sendmail 8.6.6.b9 named 4.9.2-931205-p1 db-1.73
+** gcc 2.5.8 libc.so.4.5.19
+** slackware 1.1.2 linux 0.99.15
+*/
+
+#ifdef __linux__
+# define BSD 1 /* include BSD defines */
+# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASUNSETENV 1 /* has unsetenv(3) call */
+# define ERRLIST_PREDEFINED /* don't declare sys_errlist */
+# define GIDSET_T gid_t /* from <linux/types.h> */
+# ifndef LA_TYPE
+# define LA_TYPE LA_PROCSTR
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() impl */
+# include <sys/sysmacros.h>
+# undef atol /* wounded in <stdlib.h> */
+#endif
+
+
+/*
+** DELL SVR4 Issue 2.2, and others
+** From Kimmo Suominen <kim@grendel.lut.fi>
+**
+** It's on #ifdef DELL_SVR4 because Solaris also gets __svr4__
+** defined, and the definitions conflict.
+**
+** Peter Wemm <peter@perth.DIALix.oz.au> claims that the setreuid
+** trick works on DELL 2.2 (SVR4.0/386 version 4.0) and ESIX 4.0.3A
+** (SVR4.0/386 version 3.0).
+*/
+
+#ifdef DELL_SVR4
+ /* no changes necessary */
+ /* see general __svr4__ defines below */
+#endif
+
+
+/*
+** Apple A/UX 3.0
+*/
+
+#ifdef _AUX_SOURCE
+# include <sys/sysmacros.h>
+# define BSD /* has BSD routines */
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# define SIGFUNC_DEFINED /* sigfunc_t already defined */
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# define FORK fork
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef LA_TYPE
+# define LA_TYPE LA_ZERO
+# endif
+# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Encore UMAX V
+**
+** Not extensively tested.
+*/
+
+#ifdef UMAXV
+# include <limits.h>
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
+# define FORK fork /* no vfork(2) primitive available */
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# define MAXPATHLEN PATH_MAX
+extern struct passwd *getpwent(), *getpwnam(), *getpwuid();
+extern struct group *getgrent(), *getgrnam(), *getgrgid();
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Stardent Titan 3000 running TitanOS 4.2.
+**
+** Must be compiled in "cc -43" mode.
+**
+** From Kate Hedstrom <kate@ahab.rutgers.edu>.
+**
+** Note the tweaking below after the BSD defines are set.
+*/
+
+#ifdef titan
+# define setpgid setpgrp
+typedef int pid_t;
+# undef WIFEXITED
+# undef WEXITSTATUS
+#endif
+
+
+/*
+** Sequent DYNIX 3.2.0
+**
+** From Jim Davis <jdavis@cs.arizona.edu>.
+*/
+
+#ifdef sequent
+
+# define BSD 1
+# define HASUNSETENV 1
+# define BSD4_3 1 /* to get signal() in conf.c */
+# define WAITUNION 1
+# define LA_TYPE LA_FLOAT
+# ifdef _POSIX_VERSION
+# undef _POSIX_VERSION /* set in <unistd.h> */
+# endif
+# undef HASSETVBUF /* don't actually have setvbuf(3) */
+# define setpgid setpgrp
+
+/* Have to redefine WIFEXITED to take an int, to work with waitfor() */
+# undef WIFEXITED
+# define WIFEXITED(s) (((union wait*)&(s))->w_stopval != WSTOPPED && \
+ ((union wait*)&(s))->w_termsig == 0)
+# define WEXITSTATUS(s) (((union wait*)&(s))->w_retcode)
+typedef int pid_t;
+# define isgraph(c) (isprint(c) && (c != ' '))
+
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/dynix"
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+
+#endif
+
+
+/*
+** Sequent DYNIX/ptx v2.0 (and higher)
+**
+** For DYNIX/ptx v1.x, undefine HASSETREUID.
+**
+** From Tim Wright <timw@sequent.com>.
+*/
+
+#ifdef _SEQUENT_
+# define SYSTEM5 1 /* include all the System V defines */
+# define HASSETSID 1 /* has POSIX setsid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(3) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# define GIDSET_T gid_t
+# define LA_TYPE LA_INT
+# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
+# undef SETPROCTITLE
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+#endif
+
+
+/*
+** Cray Unicos
+**
+** Ported by David L. Kensiski, Sterling Sofware <kensiski@nas.nasa.gov>
+*/
+
+#ifdef UNICOS
+# define SYSTEM5 1 /* include all the System V defines */
+# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
+# define MAXPATHLEN PATHSIZE
+# define LA_TYPE LA_ZERO
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+#endif
+
+
+/*
+** Apollo DomainOS
+**
+** From Todd Martin <tmartint@tus.ssi1.com> & Don Lewis <gdonl@gv.ssi1.com>
+**
+** 15 Jan 1994
+**
+*/
+
+#ifdef apollo
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(2) call */
+# undef SETPROCTITLE
+# define LA_TYPE LA_SUBR /* use getloadavg.c */
+# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/etc/sendmail.pid"
+# endif
+# undef S_IFSOCK /* S_IFSOCK and S_IFIFO are the same */
+# undef S_IFIFO
+# define S_IFIFO 0010000
+# ifndef IDENTPROTO
+# define IDENTPROTO 0 /* TCP/IP implementation is broken */
+# endif
+#endif
+
+
+
+
+/**********************************************************************
+** End of Per-Operating System defines
+**********************************************************************/
+
+/**********************************************************************
+** More general defines
+**********************************************************************/
+
+/* general BSD defines */
+#ifdef BSD
+# define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */
+# define HASSETREUID 1 /* has setreuid(2) call */
+# define HASINITGROUPS 1 /* has initgroups(2) call */
+# ifndef HASFLOCK
+# define HASFLOCK 1 /* has flock(2) call */
+# endif
+#endif
+
+/* general System V Release 4 defines */
+#ifdef __svr4__
+# define SYSTEM5 1
+# define HASSETREUID 1 /* has seteuid(2) call & working saved uids */
+# ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
+# endif
+# define setreuid(r, e) seteuid(e)
+
+# ifndef _PATH_UNIX
+# define _PATH_UNIX "/unix"
+# endif
+# ifndef _PATH_SENDMAILCF
+# define _PATH_SENDMAILCF "/usr/ucblib/sendmail.cf"
+# endif
+# ifndef _PATH_SENDMAILPID
+# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid"
+# endif
+# ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 128
+# endif
+#endif
+
/* general System V defines */
-# ifdef SYSTEM5
-# define LOCKF 1 /* use System V lockf instead of flock */
-# define SYS5TZ 1 /* use System V style timezones */
-# define HASUNAME 1 /* use System V uname system call */
-# define NEEDGETDTABLESIZE 1 /* needs a replacement getdtablesize */
+#ifdef SYSTEM5
+# include <sys/sysmacros.h>
+# define HASUNAME 1 /* use System V uname(2) system call */
+# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
+# define HASSETVBUF 1 /* we have setvbuf(3) in libc */
+# ifndef LA_TYPE
+# define LA_TYPE LA_INT /* assume integer load average */
# endif
+# ifndef SFS_TYPE
+# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */
+# endif
+# define bcopy(s, d, l) (memmove((d), (s), (l)))
+# define bzero(d, l) (memset((d), '\0', (l)))
+# define bcmp(s, d, l) (memcmp((s), (d), (l)))
+#endif
+
+/* general POSIX defines */
+#ifdef _POSIX_VERSION
+# define HASSETSID 1 /* has Posix setsid(2) call */
+# define HASWAITPID 1 /* has Posix waitpid(2) call */
+#endif
+
+/*
+** If no type for argument two of getgroups call is defined, assume
+** it's an integer -- unfortunately, there seem to be several choices
+** here.
+*/
+
+#ifndef GIDSET_T
+# define GIDSET_T int
+#endif
+
+/*
+** Tweaking for systems that (for example) claim to be BSD but
+** don't have all the standard BSD routines (boo hiss).
+*/
+
+#ifdef titan
+# undef HASINITGROUPS /* doesn't have initgroups(3) call */
+#endif
+
/*
** Due to a "feature" in some operating systems such as Ultrix 4.3 and
@@ -207,22 +911,35 @@
** are closed. Some firewalls return this error if you try to connect
** to the IDENT port (113), so you can't receive email from these hosts
** on these systems. The firewall really should use a more specific
-** message such as ICMP_UNREACH_PROTOCOL or _PORT or _NET_PROHIB.
+** message such as ICMP_UNREACH_PROTOCOL or _PORT or _NET_PROHIB. If
+** not explicitly set to zero above, default it on.
*/
-#if !defined(ultrix) && !defined(__hpux)
+#ifndef IDENTPROTO
# define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */
#endif
-/*
+#ifndef HASGETUSERSHELL
+# define HASGETUSERSHELL 1 /* libc has getusershell(3) call */
+#endif
+
+#ifndef HASFLOCK
+# define HASFLOCK 0 /* assume no flock(2) support */
+#endif
+
+
+/**********************************************************************
** Remaining definitions should never have to be changed. They are
** primarily to provide back compatibility for older systems -- for
** example, it includes some POSIX compatibility definitions
-*/
+**********************************************************************/
/* System 5 compatibility */
#ifndef S_ISREG
-#define S_ISREG(foo) ((foo & S_IFREG) == S_IFREG)
+# define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK)
#endif
#ifndef S_IWGRP
#define S_IWGRP 020
@@ -240,6 +957,28 @@
# define EX_CONFIG 78 /* configuration error */
# endif
+/* pseudo-code used in server SMTP */
+# define EX_QUIT 22 /* drop out of server immediately */
+
+
+/*
+** These are used in a few cases where we need some special
+** error codes, but where the system doesn't provide something
+** reasonable. They are printed in errstring.
+*/
+
+#ifndef E_PSEUDOBASE
+# define E_PSEUDOBASE 256
+#endif
+
+#define EOPENTIMEOUT (E_PSEUDOBASE + 0) /* timeout on open */
+#define E_DNSBASE (E_PSEUDOBASE + 20) /* base for DNS h_errno */
+
+/* type of arbitrary pointer */
+#ifndef ARBPTR_T
+# define ARBPTR_T void *
+#endif
+
#ifndef __P
# include "cdefs.h"
#endif
@@ -290,8 +1029,8 @@ struct utsname
};
#endif /* HASUNAME */
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
+#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_)
+# define MAXHOSTNAMELEN 256
#endif
#if !defined(SIGCHLD) && defined(SIGCLD)
@@ -310,16 +1049,31 @@ struct utsname
#define STDERR_FILENO 2
#endif
-#ifdef LOCKF
-#define LOCK_SH 0x01 /* shared lock */
-#define LOCK_EX 0x02 /* exclusive lock */
-#define LOCK_NB 0x04 /* non-blocking lock */
-#define LOCK_UN 0x08 /* unlock */
+#ifndef LOCK_SH
+# define LOCK_SH 0x01 /* shared lock */
+# define LOCK_EX 0x02 /* exclusive lock */
+# define LOCK_NB 0x04 /* non-blocking lock */
+# define LOCK_UN 0x08 /* unlock */
+#endif
+
+#ifndef SIG_ERR
+# define SIG_ERR ((void (*)()) -1)
+#endif
-#else
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(st) (((st) >> 8) & 0377)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(st) (((st) & 0377) == 0)
+#endif
-# include <sys/file.h>
+#ifndef SIGFUNC_DEFINED
+typedef void (*sigfunc_t) __P((int));
+#endif
+/* size of syslog buffer */
+#ifndef SYSLOG_BUFSIZE
+# define SYSLOG_BUFSIZE 1024
#endif
/*
@@ -329,10 +1083,29 @@ struct utsname
*/
#ifndef TOBUFSIZE
-# define TOBUFSIZE (1024 - 256)
+# if (SYSLOG_BUFSIZE) > 512
+# define TOBUFSIZE (SYSLOG_BUFSIZE - 256)
+# else
+# define TOBUFSIZE 256
+# endif
#endif
+/*
+** Size of prescan buffer.
+** Despite comments in the _sendmail_ book, this probably should
+** not be changed; there are some hard-to-define dependencies.
+*/
+
+# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */
/* fork routine -- set above using #ifdef _osname_ or in Makefile */
# ifndef FORK
# define FORK vfork /* function to call to fork mailer */
# endif
+
+/*
+** If we are going to link scanf anyway, use it in readcf
+*/
+
+#if !defined(HASUNAME) && !defined(SCANF)
+# define SCANF 1
+#endif
diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c
index cfbfec6b18e9..f7876825161a 100644
--- a/usr.sbin/sendmail/src/daemon.c
+++ b/usr.sbin/sendmail/src/daemon.c
@@ -33,24 +33,22 @@
*/
#include <errno.h>
-#include <signal.h>
#include "sendmail.h"
#ifndef lint
#ifdef DAEMON
-static char sccsid[] = "@(#)daemon.c 8.2 (Berkeley) 7/13/93 (with daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.39 (Berkeley) 3/13/94 (with daemon mode)";
#else
-static char sccsid[] = "@(#)daemon.c 8.2 (Berkeley) 7/13/93 (without daemon mode)";
+static char sccsid[] = "@(#)daemon.c 8.39 (Berkeley) 3/13/94 (without daemon mode)";
#endif
#endif /* not lint */
#ifdef DAEMON
# include <netdb.h>
-# include <sys/wait.h>
-# include <sys/time.h>
+# include <arpa/inet.h>
-#ifdef NAMED_BIND
+#if NAMED_BIND
# include <arpa/nameser.h>
# include <resolv.h>
#endif
@@ -105,14 +103,16 @@ static char sccsid[] = "@(#)daemon.c 8.2 (Berkeley) 7/13/93 (without daemon mode
int DaemonSocket = -1; /* fd describing socket */
SOCKADDR DaemonAddr; /* socket for incoming */
int ListenQueueSize = 10; /* size of listen queue */
+int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
+int TcpSndBufferSize = 0; /* size of TCP send buffer */
getrequests()
{
int t;
- register struct servent *sp;
int on = 1;
bool refusingconnections = TRUE;
FILE *pidf;
+ int socksize;
extern void reapchild();
/*
@@ -125,17 +125,16 @@ getrequests()
DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY;
if (DaemonAddr.sin.sin_port == 0)
{
+ register struct servent *sp;
+
sp = getservbyname("smtp", "tcp");
if (sp == NULL)
{
syserr("554 service \"smtp\" unknown");
- goto severe;
+ DaemonAddr.sin.sin_port = htons(25);
}
-#ifdef _SCO_unix_
- DaemonAddr.sin.sin_port = htons(sp->s_port);
-#else
- DaemonAddr.sin.sin_port = sp->s_port;
-#endif
+ else
+ DaemonAddr.sin.sin_port = sp->s_port;
}
/*
@@ -166,39 +165,57 @@ getrequests()
(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
+#ifdef SO_RCVBUF
+ if (TcpRcvBufferSize > 0)
+ {
+ if (setsockopt(DaemonSocket, SOL_SOCKET, SO_RCVBUF,
+ (char *) &TcpRcvBufferSize,
+ sizeof(TcpRcvBufferSize)) < 0)
+ syserr("getrequests: setsockopt(SO_RCVBUF)");
+ }
+#endif
+
switch (DaemonAddr.sa.sa_family)
{
# ifdef NETINET
case AF_INET:
- t = sizeof DaemonAddr.sin;
+ socksize = sizeof DaemonAddr.sin;
break;
# endif
# ifdef NETISO
case AF_ISO:
- t = sizeof DaemonAddr.siso;
+ socksize = sizeof DaemonAddr.siso;
break;
# endif
default:
- t = sizeof DaemonAddr;
+ socksize = sizeof DaemonAddr;
break;
}
- if (bind(DaemonSocket, &DaemonAddr.sa, t) < 0)
+ if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0)
{
syserr("getrequests: cannot bind");
(void) close(DaemonSocket);
goto severe;
}
- (void) signal(SIGCHLD, reapchild);
+ (void) setsignal(SIGCHLD, reapchild);
/* write the pid to the log file for posterity */
pidf = fopen(PidFile, "w");
if (pidf != NULL)
{
+ extern char *CommandLineArgs;
+
+ /* write the process id on line 1 */
fprintf(pidf, "%d\n", getpid());
+
+ /* line 2 contains all command line flags */
+ fprintf(pidf, "%s\n", CommandLineArgs);
+
+ /* flush and close */
fclose(pidf);
}
@@ -245,7 +262,7 @@ getrequests()
do
{
errno = 0;
- lotherend = sizeof RealHostAddr;
+ lotherend = socksize;
t = accept(DaemonSocket,
(struct sockaddr *)&RealHostAddr, &lotherend);
} while (t < 0 && errno == EINTR);
@@ -274,6 +291,7 @@ getrequests()
if (pid == 0)
{
+ char *p;
extern char *hostnamebyanyaddr();
/*
@@ -282,14 +300,19 @@ getrequests()
** Verify calling user id if possible here.
*/
- (void) signal(SIGCHLD, SIG_DFL);
- OpMode = MD_SMTP;
+ (void) setsignal(SIGCHLD, SIG_DFL);
+ DisConnected = FALSE;
+
+ setproctitle("startup with %s",
+ anynet_ntoa(&RealHostAddr));
/* determine host name */
- RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
+ p = hostnamebyanyaddr(&RealHostAddr);
+ RealHostName = newstr(p);
+ setproctitle("startup with %s", p);
#ifdef LOG
- if (LogLevel > 10)
+ if (LogLevel > 11)
{
/* log connection information */
syslog(LOG_INFO, "connect from %s (%s)",
@@ -298,8 +321,13 @@ getrequests()
#endif
(void) close(DaemonSocket);
- InChannel = fdopen(t, "r");
- OutChannel = fdopen(dup(t), "w");
+ if ((InChannel = fdopen(t, "r")) == NULL ||
+ (t = dup(t)) < 0 ||
+ (OutChannel = fdopen(t, "w")) == NULL)
+ {
+ syserr("cannot open SMTP server channel, fd=%d", t);
+ exit(0);
+ }
/* should we check for illegal connection here? XXX */
#ifdef XLA
@@ -434,7 +462,7 @@ setdaemonoptions(p)
#ifdef NETINET
case AF_INET:
if (isascii(*v) && isdigit(*v))
- DaemonAddr.sin.sin_port = atoi(v);
+ DaemonAddr.sin.sin_port = htons(atoi(v));
else
{
register struct servent *sp;
@@ -443,13 +471,7 @@ setdaemonoptions(p)
if (sp == NULL)
syserr("554 service \"%s\" unknown", v);
else
- {
-#ifdef _SCO_unix_
- DaemonAddr.sin.sin_port = htons(sp->s_port);
-#else
DaemonAddr.sin.sin_port = sp->s_port;
-#endif
- }
}
break;
#endif
@@ -458,7 +480,7 @@ setdaemonoptions(p)
case AF_ISO:
/* assume two byte transport selector */
if (isascii(*v) && isdigit(*v))
- port = atoi(v);
+ port = htons(atoi(v));
else
{
register struct servent *sp;
@@ -483,6 +505,14 @@ setdaemonoptions(p)
case 'L': /* listen queue size */
ListenQueueSize = atoi(v);
break;
+
+ case 'S': /* send buffer size */
+ TcpSndBufferSize = atoi(v);
+ break;
+
+ case 'R': /* receive buffer size */
+ TcpRcvBufferSize = atoi(v);
+ break;
}
}
}
@@ -519,7 +549,7 @@ makeconnection(host, port, mci, usesecureport)
SOCKADDR addr;
int sav_errno;
int addrlen;
-#ifdef NAMED_BIND
+#if NAMED_BIND
extern int h_errno;
#endif
@@ -528,11 +558,12 @@ makeconnection(host, port, mci, usesecureport)
** Accept "[a.b.c.d]" syntax for host name.
*/
-#ifdef NAMED_BIND
+#if NAMED_BIND
h_errno = 0;
#endif
errno = 0;
bzero(&CurHostAddr, sizeof CurHostAddr);
+ SmtpPhase = mci->mci_phase = "initial connection";
CurHostName = host;
if (host[0] == '[')
@@ -550,6 +581,12 @@ makeconnection(host, port, mci, usesecureport)
{
/* try it as a host name (avoid MX lookup) */
hp = gethostbyname(&host[1]);
+ if (hp == NULL && p[-1] == '.')
+ {
+ p[-1] = '\0';
+ hp = gethostbyname(&host[1]);
+ p[-1] = '.';
+ }
*p = ']';
goto gothostent;
}
@@ -567,11 +604,19 @@ makeconnection(host, port, mci, usesecureport)
}
else
{
+ register char *p = &host[strlen(host) - 1];
+
hp = gethostbyname(host);
+ if (hp == NULL && *p == '.')
+ {
+ *p = '\0';
+ hp = gethostbyname(host);
+ *p = '.';
+ }
gothostent:
if (hp == NULL)
{
-#ifdef NAMED_BIND
+#if NAMED_BIND
if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
return (EX_TEMPFAIL);
@@ -588,7 +633,7 @@ gothostent:
case AF_INET:
bcopy(hp->h_addr,
&addr.sin.sin_addr,
- hp->h_length);
+ sizeof addr.sin.sin_addr);
break;
#endif
@@ -614,13 +659,10 @@ gothostent:
if (sp == NULL)
{
syserr("554 makeconnection: service \"smtp\" unknown");
- return (EX_OSERR);
+ port = htons(25);
}
-#ifdef _SCO_unix_
- port = htons(sp->s_port);
-#else
- port = sp->s_port;
-#endif
+ else
+ port = sp->s_port;
}
switch (addr.sa.sa_family)
@@ -681,6 +723,16 @@ gothostent:
goto failure;
}
+#ifdef SO_SNDBUF
+ if (TcpSndBufferSize > 0)
+ {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ (char *) &TcpSndBufferSize,
+ sizeof(TcpSndBufferSize)) < 0)
+ syserr("makeconnection: setsockopt(SO_SNDBUF)");
+ }
+#endif
+
if (tTd(16, 1))
printf("makeconnection: fd=%d\n", s);
@@ -711,7 +763,7 @@ gothostent:
case AF_INET:
bcopy(hp->h_addr_list[i++],
&addr.sin.sin_addr,
- hp->h_length);
+ sizeof addr.sin.sin_addr);
break;
#endif
@@ -739,8 +791,13 @@ gothostent:
}
/* connection ok, put it into canonical form */
- mci->mci_out = fdopen(s, "w");
- mci->mci_in = fdopen(dup(s), "r");
+ if ((mci->mci_out = fdopen(s, "w")) == NULL ||
+ (s = dup(s)) < 0 ||
+ (mci->mci_in = fdopen(s, "r")) == NULL)
+ {
+ syserr("cannot open SMTP client channel, fd=%d", s);
+ return EX_TEMPFAIL;
+ }
return (EX_OK);
}
@@ -755,11 +812,9 @@ gothostent:
** A list of aliases for this host.
**
** Side Effects:
-** Sets the MyIpAddrs buffer to a list of my IP addresses.
+** Adds numeric codes to $=w.
*/
-struct in_addr MyIpAddrs[MAXIPADDR + 1];
-
char **
myhostname(hostbuf, size)
char hostbuf[];
@@ -782,13 +837,14 @@ myhostname(hostbuf, size)
{
register int i;
- for (i = 0; i < MAXIPADDR; i++)
+ for (i = 0; hp->h_addr_list[i] != NULL; i++)
{
- if (hp->h_addr_list[i] == NULL)
- break;
- MyIpAddrs[i].s_addr = *(u_long *) hp->h_addr_list[i];
+ char ipbuf[100];
+
+ sprintf(ipbuf, "[%s]",
+ inet_ntoa(*((struct in_addr *) hp->h_addr_list[i])));
+ setclass('w', ipbuf);
}
- MyIpAddrs[i].s_addr = 0;
}
return (hp->h_aliases);
@@ -806,12 +862,9 @@ myhostname(hostbuf, size)
**
** Returns:
** The user@host information associated with this descriptor.
-**
-** Side Effects:
-** Sets RealHostName to the name of the host at the other end.
*/
-#ifdef IDENTPROTO
+#if IDENTPROTO
static jmp_buf CtxAuthTimeout;
@@ -830,7 +883,7 @@ getauthinfo(fd)
SOCKADDR fa;
int falen;
register char *p;
-#ifdef IDENTPROTO
+#if IDENTPROTO
SOCKADDR la;
int lalen;
register struct servent *sp;
@@ -843,19 +896,19 @@ getauthinfo(fd)
extern char RealUserName[]; /* main.c */
falen = sizeof fa;
- if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0)
+ if (getpeername(fd, &fa.sa, &falen) < 0 || falen <= 0 ||
+ fa.sa.sa_family == 0)
{
- RealHostName = "localhost";
(void) sprintf(hbuf, "%s@localhost", RealUserName);
if (tTd(9, 1))
printf("getauthinfo: %s\n", hbuf);
return hbuf;
}
- RealHostName = newstr(hostnamebyanyaddr(&fa));
- RealHostAddr = fa;
+#if IDENTPROTO
+ if (TimeOuts.to_ident == 0)
+ goto noident;
-#ifdef IDENTPROTO
lalen = sizeof la;
if (fa.sa.sa_family != AF_INET ||
getsockname(fd, &la.sa, &lalen) < 0 || lalen <= 0 ||
@@ -870,18 +923,12 @@ getauthinfo(fd)
ntohs(fa.sin.sin_port), ntohs(la.sin.sin_port));
/* create local address */
- bzero(&la, sizeof la);
+ la.sin.sin_port = 0;
/* create foreign address */
sp = getservbyname("auth", "tcp");
if (sp != NULL)
- {
-#ifdef _SCO_unix_
- fa.sin.sin_port = htons(sp->s_port);
-#else
fa.sin.sin_port = sp->s_port;
-#endif
- }
else
fa.sin.sin_port = htons(113);
@@ -894,21 +941,19 @@ getauthinfo(fd)
}
/* put a timeout around the whole thing */
- ev = setevent((time_t) 30, authtimeout, 0);
+ ev = setevent(TimeOuts.to_ident, authtimeout, 0);
- /* connect to foreign IDENT server */
+ /* connect to foreign IDENT server using same address as SMTP socket */
s = socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
{
clrevent(ev);
goto noident;
}
- if (connect(s, &fa.sa, sizeof fa.sin) < 0)
+ if (bind(s, &la.sa, sizeof la.sin) < 0 ||
+ connect(s, &fa.sa, sizeof fa.sin) < 0)
{
-closeident:
- (void) close(s);
- clrevent(ev);
- goto noident;
+ goto closeident;
}
if (tTd(9, 10))
@@ -967,16 +1012,27 @@ closeident:
continue;
/* p now points to the authenticated name */
- (void) sprintf(hbuf, "%s@%s", p, RealHostName);
+ (void) sprintf(hbuf, "%s@%s",
+ p, RealHostName == NULL ? "localhost" : RealHostName);
goto finish;
+closeident:
+ (void) close(s);
+ clrevent(ev);
+
#endif /* IDENTPROTO */
noident:
+ if (RealHostName == NULL)
+ {
+ if (tTd(9, 1))
+ printf("getauthinfo: NULL\n");
+ return NULL;
+ }
(void) strcpy(hbuf, RealHostName);
finish:
- if (RealHostName[0] != '[')
+ if (RealHostName != NULL && RealHostName[0] != '[')
{
p = &hbuf[strlen(hbuf)];
(void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr));
@@ -1020,7 +1076,9 @@ host_map_lookup(map, name, av, statp)
register STAB *s;
char hbuf[MAXNAME];
extern struct hostent *gethostbyaddr();
+#if NAMED_BIND
extern int h_errno;
+#endif
/*
** See if we have already looked up this name. If so, just
@@ -1034,8 +1092,16 @@ host_map_lookup(map, name, av, statp)
printf("host_map_lookup(%s) => CACHE %s\n",
name, s->s_namecanon.nc_cname);
errno = s->s_namecanon.nc_errno;
+#if NAMED_BIND
h_errno = s->s_namecanon.nc_herrno;
+#endif
*statp = s->s_namecanon.nc_stat;
+ if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL)
+ {
+ sprintf(hbuf, "%s: Name server timeout",
+ shortenstring(name, 33));
+ CurEnv->e_message = newstr(hbuf);
+ }
return s->s_namecanon.nc_cname;
}
@@ -1054,7 +1120,7 @@ host_map_lookup(map, name, av, statp)
printf("host_map_lookup(%s) => ", name);
s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
(void) strcpy(hbuf, name);
- if (getcanonname(hbuf, sizeof hbuf - 1))
+ if (getcanonname(hbuf, sizeof hbuf - 1, TRUE))
{
if (tTd(9, 1))
printf("%s\n", hbuf);
@@ -1066,20 +1132,21 @@ host_map_lookup(map, name, av, statp)
{
register struct hostent *hp;
- if (tTd(9, 1))
- printf("FAIL (%d)\n", h_errno);
s->s_namecanon.nc_errno = errno;
+#if NAMED_BIND
s->s_namecanon.nc_herrno = h_errno;
+ if (tTd(9, 1))
+ printf("FAIL (%d)\n", h_errno);
switch (h_errno)
{
case TRY_AGAIN:
if (UseNameServer)
{
- char *msg = "Recipient domain nameserver timed out";
-
- message(msg);
+ sprintf(hbuf, "%s: Name server timeout",
+ shortenstring(name, 33));
+ message("%s", hbuf);
if (CurEnv->e_message == NULL)
- CurEnv->e_message = newstr(msg);
+ CurEnv->e_message = newstr(hbuf);
}
*statp = EX_TEMPFAIL;
break;
@@ -1096,6 +1163,11 @@ host_map_lookup(map, name, av, statp)
*statp = EX_UNAVAILABLE;
break;
}
+#else
+ if (tTd(9, 1))
+ printf("FAIL\n");
+ *statp = EX_NOHOST;
+#endif
s->s_namecanon.nc_stat = *statp;
if (*statp != EX_TEMPFAIL || UseNameServer)
return NULL;
@@ -1123,19 +1195,12 @@ host_map_lookup(map, name, av, statp)
*cp = '\0';
in_addr = inet_addr(&name[1]);
- /* check to see if this is one of our addresses */
- for (i = 0; MyIpAddrs[i].s_addr != 0; i++)
- {
- if (MyIpAddrs[i].s_addr == in_addr)
- {
- return map_rewrite(map, MyHostName, strlen(MyHostName), av);
- }
- }
-
/* nope -- ask the name server */
hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET);
s->s_namecanon.nc_errno = errno;
+#if NAMED_BIND
s->s_namecanon.nc_herrno = h_errno;
+#endif
s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
if (hp == NULL)
{
@@ -1166,7 +1231,7 @@ anynet_ntoa(sap)
register char *bp;
register char *ap;
int l;
- static char buf[80];
+ static char buf[100];
/* check for null/zero family */
if (sap == NULL)
@@ -1174,15 +1239,29 @@ anynet_ntoa(sap)
if (sap->sa.sa_family == 0)
return "0";
-#ifdef NETINET
- if (sap->sa.sa_family == AF_INET)
+ switch (sap->sa.sa_family)
{
- extern char *inet_ntoa();
+#ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/
+#ifdef NETUNIX
+ case AF_UNIX:
+ if (sap->sunix.sun_path[0] != '\0')
+ sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path);
+ else
+ sprintf(buf, "[UNIX: localhost]");
+ return buf;
+#endif
+#endif
+#ifdef NETINET
+ case AF_INET:
return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr);
- }
#endif
+ default:
+ /* this case is only to ensure syntactic correctness */
+ break;
+ }
+
/* unknown family -- just dump bytes */
(void) sprintf(buf, "Family %d: ", sap->sa.sa_family);
bp = &buf[strlen(buf)];
@@ -1213,10 +1292,9 @@ hostnamebyanyaddr(sap)
register SOCKADDR *sap;
{
register struct hostent *hp;
-
-#ifdef NAMED_BIND
int saveretry;
+#if NAMED_BIND
/* shorten name server timeout to avoid higher level timeouts */
saveretry = _res.retry;
_res.retry = 3;
@@ -1240,6 +1318,12 @@ hostnamebyanyaddr(sap)
break;
#endif
+#ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/
+ case AF_UNIX:
+ hp = NULL;
+ break;
+#endif
+
default:
hp = gethostbyaddr(sap->sa.sa_data,
sizeof sap->sa.sa_data,
@@ -1247,7 +1331,7 @@ hostnamebyanyaddr(sap)
break;
}
-#ifdef NAMED_BIND
+#if NAMED_BIND
_res.retry = saveretry;
#endif /* NAMED_BIND */
diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c
index ef9fd82330c8..692dffe932a7 100644
--- a/usr.sbin/sendmail/src/deliver.c
+++ b/usr.sbin/sendmail/src/deliver.c
@@ -33,20 +33,21 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)deliver.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)deliver.c 8.78 (Berkeley) 3/11/94";
#endif /* not lint */
#include "sendmail.h"
-#include <signal.h>
#include <netdb.h>
#include <errno.h>
-#ifdef NAMED_BIND
+#if NAMED_BIND
#include <arpa/nameser.h>
#include <resolv.h>
extern int h_errno;
#endif
+extern char SmtpError[];
+
/*
** SENDALL -- actually send all the messages.
**
@@ -76,14 +77,22 @@ sendall(e, mode)
ENVELOPE *splitenv = NULL;
bool announcequeueup;
- if (bitset(EF_FATALERRS, e->e_flags))
+ /*
+ ** If we have had global, fatal errors, don't bother sending
+ ** the message at all if we are in SMTP mode. Local errors
+ ** (e.g., a single address failing) will still cause the other
+ ** addresses to be sent.
+ */
+
+ if (bitset(EF_FATALERRS, e->e_flags) &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON))
{
- /* this will get a return message -- so don't send it */
e->e_flags |= EF_CLRQUEUE;
return;
}
/* determine actual delivery mode */
+ CurrentLA = getla();
if (mode == SM_DEFAULT)
{
mode = e->e_sendmode;
@@ -97,7 +106,8 @@ sendall(e, mode)
if (tTd(13, 1))
{
- printf("\nSENDALL: mode %c, e_from ", mode);
+ printf("\n===== SENDALL: mode %c, id %s, e_from ",
+ mode, e->e_id);
printaddr(&e->e_from, FALSE);
printf("sendqueue:\n");
printaddr(e->e_sendqueue, TRUE);
@@ -114,8 +124,10 @@ sendall(e, mode)
if (e->e_hopcount > MaxHopCount)
{
errno = 0;
- syserr("554 too many hops %d (%d max): from %s, to %s",
+ e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE;
+ syserr("554 too many hops %d (%d max): from %s via %s, to %s",
e->e_hopcount, MaxHopCount, e->e_from.q_paddr,
+ RealHostName == NULL ? "localhost" : RealHostName,
e->e_sendqueue->q_paddr);
return;
}
@@ -129,7 +141,8 @@ sendall(e, mode)
** is instantiated in the queue as a recipient.
*/
- if (!MeToo && !bitset(QQUEUEUP, e->e_from.q_flags))
+ if (!bitset(EF_METOO, e->e_flags) &&
+ !bitset(QQUEUEUP, e->e_from.q_flags))
{
if (tTd(13, 5))
{
@@ -229,7 +242,6 @@ sendall(e, mode)
ee->e_from.q_flags |= QDONTSEND;
ee->e_dfp = NULL;
ee->e_xfp = NULL;
- ee->e_lockfp = NULL;
ee->e_df = NULL;
ee->e_errormode = EM_MAIL;
ee->e_sibling = splitenv;
@@ -237,28 +249,32 @@ sendall(e, mode)
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
if (q->q_owner == owner)
+ {
q->q_flags |= QDONTSEND;
+ q->q_flags &= ~QQUEUEUP;
+ }
for (q = ee->e_sendqueue; q != NULL; q = q->q_next)
if (q->q_owner != owner)
+ {
q->q_flags |= QDONTSEND;
+ q->q_flags &= ~QQUEUEUP;
+ }
if (e->e_df != NULL && mode != SM_VERIFY)
{
ee->e_dfp = NULL;
- ee->e_df = newstr(queuename(ee, 'd'));
+ ee->e_df = queuename(ee, 'd');
+ ee->e_df = newstr(ee->e_df);
if (link(e->e_df, ee->e_df) < 0)
{
syserr("sendall: link(%s, %s)",
e->e_df, ee->e_df);
}
}
-
- if (mode != SM_VERIFY)
- openxscript(ee);
#ifdef LOG
if (LogLevel > 4)
- syslog(LOG_INFO, "%s: clone %s",
- ee->e_id, e->e_id);
+ syslog(LOG_INFO, "%s: clone %s, owner=%s",
+ ee->e_id, e->e_id, owner);
#endif
}
}
@@ -298,15 +314,15 @@ sendall(e, mode)
for (ee = splitenv; ee != NULL; ee = ee->e_sibling)
{
CurEnv = ee;
+ if (mode != SM_VERIFY)
+ openxscript(ee);
sendenvelope(ee, mode);
+ dropenvelope(ee);
}
CurEnv = e;
}
sendenvelope(e, mode);
-
- for (; splitenv != NULL; splitenv = splitenv->e_sibling)
- dropenvelope(splitenv);
}
sendenvelope(e, mode)
@@ -316,9 +332,22 @@ sendenvelope(e, mode)
bool oldverbose;
int pid;
register ADDRESS *q;
-#ifdef LOCKF
- struct flock lfd;
-#endif
+ char *qf;
+ char *id;
+
+ /*
+ ** If we have had global, fatal errors, don't bother sending
+ ** the message at all if we are in SMTP mode. Local errors
+ ** (e.g., a single address failing) will still cause the other
+ ** addresses to be sent.
+ */
+
+ if (bitset(EF_FATALERRS, e->e_flags) &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON))
+ {
+ e->e_flags |= EF_CLRQUEUE;
+ return;
+ }
oldverbose = Verbose;
switch (mode)
@@ -336,20 +365,27 @@ sendenvelope(e, mode)
if (e->e_xfp != NULL)
(void) fflush(e->e_xfp);
-# ifdef LOCKF
+# if !HASFLOCK
/*
- ** Since lockf has the interesting semantic that the
- ** lock is lost when we fork, we have to risk losing
- ** the lock here by closing before the fork, and then
- ** trying to get it back in the child.
+ ** Since fcntl locking has the interesting semantic that
+ ** the lock is owned by a process, not by an open file
+ ** descriptor, we have to flush this to the queue, and
+ ** then restart from scratch in the child.
*/
- if (e->e_lockfp != NULL)
- {
- (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
- e->e_lockfp = NULL;
- }
-# endif /* LOCKF */
+ /* save id for future use */
+ id = e->e_id;
+
+ /* now drop the envelope in the parent */
+ e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
+ dropenvelope(e);
+
+ /* and reacquire in the child */
+ (void) dowork(id, TRUE, FALSE, e);
+
+ return;
+
+# else /* HASFLOCK */
pid = fork();
if (pid < 0)
@@ -359,60 +395,37 @@ sendenvelope(e, mode)
else if (pid > 0)
{
/* be sure we leave the temp files to our child */
- e->e_id = e->e_df = NULL;
-# ifndef LOCKF
+ /* can't call unlockqueue to avoid unlink of xfp */
if (e->e_lockfp != NULL)
- {
(void) xfclose(e->e_lockfp, "sendenvelope", "lockfp");
- e->e_lockfp = NULL;
- }
-# endif
+ e->e_lockfp = NULL;
/* close any random open files in the envelope */
+ closexscript(e);
if (e->e_dfp != NULL)
- {
- (void) xfclose(e->e_dfp, "sendenvelope", "dfp");
- e->e_dfp = NULL;
- }
- if (e->e_xfp != NULL)
- {
- (void) xfclose(e->e_xfp, "sendenvelope", "xfp");
- e->e_xfp = NULL;
- }
+ (void) xfclose(e->e_dfp, "sendenvelope", e->e_df);
+ e->e_dfp = NULL;
+ e->e_id = e->e_df = NULL;
+
+ /* catch intermediate zombie */
+ (void) waitfor(pid);
return;
}
/* double fork to avoid zombies */
- if (fork() > 0)
+ pid = fork();
+ if (pid > 0)
exit(EX_OK);
/* be sure we are immune from the terminal */
- disconnect(FALSE, e);
-
-# ifdef LOCKF
- /*
- ** Now try to get our lock back.
- */
+ disconnect(1, e);
- lfd.l_type = F_WRLCK;
- lfd.l_whence = lfd.l_start = lfd.l_len = 0;
- e->e_lockfp = fopen(queuename(e, 'q'), "r+");
- if (e->e_lockfp == NULL ||
- fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0)
+ /* prevent parent from waiting if there was an error */
+ if (pid < 0)
{
- /* oops.... lost it */
- if (tTd(13, 1))
- printf("sendenvelope: %s lost lock: lockfp=%x, %s\n",
- e->e_id, e->e_lockfp, errstring(errno));
-
-# ifdef LOG
- if (LogLevel > 29)
- syslog(LOG_NOTICE, "%s: lost lock: %m",
- e->e_id);
-# endif /* LOG */
- exit(EX_OK);
+ e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
+ finis();
}
-# endif /* LOCKF */
/*
** Close any cached connections.
@@ -426,25 +439,44 @@ sendenvelope(e, mode)
mci_flush(FALSE, NULL);
+# endif /* HASFLOCK */
+
break;
}
/*
** Run through the list and send everything.
+ **
+ ** Set EF_GLOBALERRS so that error messages during delivery
+ ** result in returned mail.
*/
e->e_nsent = 0;
+ e->e_flags |= EF_GLOBALERRS;
+
+ /* now run through the queue */
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
+#ifdef XDEBUG
+ char wbuf[MAXNAME + 20];
+
+ (void) sprintf(wbuf, "sendall(%s)", q->q_paddr);
+ checkfd012(wbuf);
+#endif
if (mode == SM_VERIFY)
{
e->e_to = q->q_paddr;
if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
{
- message("deliverable: mailer %s, host %s, user %s",
- q->q_mailer->m_name,
- q->q_host,
- q->q_user);
+ if (q->q_host != NULL && q->q_host[0] != '\0')
+ message("deliverable: mailer %s, host %s, user %s",
+ q->q_mailer->m_name,
+ q->q_host,
+ q->q_user);
+ else
+ message("deliverable: mailer %s, user %s",
+ q->q_mailer->m_name,
+ q->q_user);
}
}
else if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
@@ -465,37 +497,9 @@ sendenvelope(e, mode)
}
Verbose = oldverbose;
- /*
- ** Now run through and check for errors.
- */
-
- if (mode == SM_VERIFY)
- {
- return;
- }
-
- for (q = e->e_sendqueue; q != NULL; q = q->q_next)
- {
- if (tTd(13, 3))
- {
- printf("Checking ");
- printaddr(q, FALSE);
- }
-
- /* only send errors if the message failed */
- if (!bitset(QBADADDR, q->q_flags) ||
- bitset(QDONTSEND, q->q_flags))
- continue;
-
- if (tTd(13, 3))
- printf("FATAL ERRORS\n");
-
- e->e_flags |= EF_FATALERRS;
-
- if (q->q_owner == NULL && strcmp(e->e_from.q_paddr, "<>") != 0)
- (void) sendtolist(e->e_from.q_paddr, NULL,
- &e->e_errorqueue, e);
- }
+#ifdef XDEBUG
+ checkfd012("end of sendenvelope");
+#endif
if (mode == SM_FORK)
finis();
@@ -611,15 +615,15 @@ deliver(e, firstto)
char buf[MAXNAME];
char rpathbuf[MAXNAME]; /* translated return path */
extern int checkcompat();
- extern FILE *fdopen();
errno = 0;
if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags))
return (0);
-#ifdef NAMED_BIND
+#if NAMED_BIND
/* unless interactive, try twice, over a minute */
- if (OpMode == MD_DAEMON || OpMode == MD_SMTP) {
+ if (OpMode == MD_DAEMON || OpMode == MD_SMTP)
+ {
_res.retrans = 30;
_res.retry = 2;
}
@@ -629,10 +633,13 @@ deliver(e, firstto)
host = to->q_host;
CurEnv = e; /* just in case */
e->e_statmsg = NULL;
+ SmtpError[0] = '\0';
if (tTd(10, 1))
- printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",
- m->m_mno, host, to->q_user);
+ printf("\n--deliver, id=%s, mailer=%s, host=`%s', first user=`%s'\n",
+ e->e_id, m->m_name, host, to->q_user);
+ if (tTd(10, 100))
+ printopenfds(FALSE);
/*
** If this mailer is expensive, and if we don't want to make
@@ -644,19 +651,18 @@ deliver(e, firstto)
** This should be on a per-mailer basis.
*/
- if (NoConnect && !bitset(EF_QUEUERUN, e->e_flags) &&
- bitnset(M_EXPENSIVE, m->m_flags) && !Verbose)
+ if (NoConnect && bitnset(M_EXPENSIVE, m->m_flags) && !Verbose)
{
for (; to != NULL; to = to->q_next)
{
if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) ||
to->q_mailer != m)
continue;
- to->q_flags |= QQUEUEUP|QDONTSEND;
+ to->q_flags |= QQUEUEUP;
e->e_to = to->q_paddr;
message("queued");
if (LogLevel > 8)
- logdelivery(m, NULL, "queued", e);
+ logdelivery(m, NULL, "queued", NULL, e);
}
e->e_to = NULL;
return (0);
@@ -740,7 +746,7 @@ deliver(e, firstto)
*pvp = NULL;
# else /* SMTP */
/* oops! we don't implement SMTP */
- syserr("554 SMTP style mailer");
+ syserr("554 SMTP style mailer not implemented");
return (EX_SOFTWARE);
# endif /* SMTP */
}
@@ -779,7 +785,9 @@ deliver(e, firstto)
}
/* compute effective uid/gid when sending */
- if (to->q_mailer == ProgMailer)
+ /* XXX perhaps this should be to->q_mailer != LocalMailer ?? */
+ /* XXX perhaps it should be a mailer flag? */
+ if (to->q_mailer == ProgMailer || to->q_mailer == FileMailer)
ctladdr = getctladdr(to);
user = to->q_user;
@@ -800,14 +808,14 @@ deliver(e, firstto)
{
NoReturn = TRUE;
usrerr("552 Message is too large; %ld bytes max", m->m_maxsize);
- giveresponse(EX_UNAVAILABLE, m, NULL, e);
+ giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e);
continue;
}
rcode = checkcompat(to, e);
if (rcode != EX_OK)
{
markfailure(e, to, rcode);
- giveresponse(rcode, m, NULL, e);
+ giveresponse(rcode, m, NULL, ctladdr, e);
continue;
}
@@ -851,8 +859,8 @@ deliver(e, firstto)
if (m == FileMailer)
{
- rcode = mailfile(user, getctladdr(to), e);
- giveresponse(rcode, m, NULL, e);
+ rcode = mailfile(user, ctladdr, e);
+ giveresponse(rcode, m, NULL, ctladdr, e);
if (rcode == EX_OK)
to->q_flags |= QSENT;
continue;
@@ -871,7 +879,10 @@ deliver(e, firstto)
(void) strcat(tobuf, ",");
(void) strcat(tobuf, to->q_paddr);
define('u', user, e); /* to user */
- define('z', to->q_home, e); /* user's home */
+ p = to->q_home;
+ if (p == NULL && ctladdr != NULL)
+ p = ctladdr->q_home;
+ define('z', p, e); /* user's home */
/*
** Expand out this user into argument list.
@@ -920,9 +931,12 @@ deliver(e, firstto)
** If we are running SMTP, we just need to clean up.
*/
- if (ctladdr == NULL && m != ProgMailer)
+ /*XXX this seems a bit wierd */
+ if (ctladdr == NULL && m != ProgMailer &&
+ bitset(QGOODUID, e->e_from.q_flags))
ctladdr = &e->e_from;
-#ifdef NAMED_BIND
+
+#if NAMED_BIND
if (ConfigLevel < 2)
_res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */
#endif
@@ -946,6 +960,18 @@ deliver(e, firstto)
*/
curhost = NULL;
+ SmtpPhase = NULL;
+ mci = NULL;
+
+#ifdef XDEBUG
+ {
+ char wbuf[MAXLINE];
+
+ /* make absolutely certain 0, 1, and 2 are in use */
+ sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name);
+ checkfd012(wbuf);
+ }
+#endif
/* check for Local Person Communication -- not for mortals!!! */
if (strcmp(m->m_mailer, "[LPC]") == 0)
@@ -964,12 +990,19 @@ deliver(e, firstto)
register int i;
register u_short port;
+ if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0')
+ {
+ syserr("null host name for %s mailer", m->m_mailer);
+ rcode = EX_CONFIG;
+ goto give_up;
+ }
+
CurHostName = pv[1];
curhost = hostsignature(m, pv[1], e);
if (curhost == NULL || curhost[0] == '\0')
{
- syserr("null signature");
+ syserr("null host signature for %s", pv[1]);
rcode = EX_OSERR;
goto give_up;
}
@@ -977,7 +1010,7 @@ deliver(e, firstto)
if (!clever)
{
syserr("554 non-clever IPC");
- rcode = EX_OSERR;
+ rcode = EX_CONFIG;
goto give_up;
}
if (pv[2] != NULL)
@@ -985,18 +1018,21 @@ deliver(e, firstto)
else
port = 0;
tryhost:
- mci = NULL;
while (*curhost != '\0')
{
register char *p;
static char hostbuf[MAXNAME];
- mci = NULL;
-
/* pull the next host from the signature */
p = strchr(curhost, ':');
if (p == NULL)
p = &curhost[strlen(curhost)];
+ if (p == curhost)
+ {
+ syserr("deliver: null host name in signature");
+ curhost++;
+ continue;
+ }
strncpy(hostbuf, curhost, p - curhost);
hostbuf[p - curhost] = '\0';
if (*p != '\0')
@@ -1011,7 +1047,7 @@ tryhost:
if (tTd(11, 1))
{
printf("openmailer: ");
- mci_dump(mci);
+ mci_dump(mci, FALSE);
}
CurHostName = mci->mci_host;
break;
@@ -1028,7 +1064,7 @@ tryhost:
bitnset(M_SECURE_PORT, m->m_flags));
mci->mci_exitstat = i;
mci->mci_errno = errno;
-#ifdef NAMED_BIND
+#if NAMED_BIND
mci->mci_herrno = h_errno;
#endif
if (i == EX_OK)
@@ -1044,28 +1080,28 @@ tryhost:
printf("openmailer: makeconnection => stat=%d, errno=%d\n",
i, errno);
-
/* enter status of this host */
setstat(i);
+
+ /* should print some message here for -v mode */
+ }
+ if (mci == NULL)
+ {
+ syserr("deliver: no host name");
+ rcode = EX_OSERR;
+ goto give_up;
}
mci->mci_pid = 0;
#else /* no DAEMON */
syserr("554 openmailer: no IPC");
if (tTd(11, 1))
printf("openmailer: NULL\n");
- return NULL;
+ rcode = EX_UNAVAILABLE;
+ goto give_up;
#endif /* DAEMON */
}
else
{
-#ifdef XDEBUG
- char wbuf[MAXLINE];
-
- /* make absolutely certain 0, 1, and 2 are in use */
- sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name);
- checkfd012(wbuf);
-#endif
-
if (TrafficLogFile != NULL)
{
char **av;
@@ -1112,7 +1148,7 @@ tryhost:
(void) fflush(e->e_xfp); /* for debugging */
(void) fflush(stdout);
# ifdef SIGCHLD
- (void) signal(SIGCHLD, SIG_DFL);
+ (void) setsignal(SIGCHLD, SIG_DFL);
# endif /* SIGCHLD */
DOFORK(FORK);
/* pid is set by DOFORK */
@@ -1143,13 +1179,32 @@ tryhost:
extern int DtableSize;
/* child -- set up input & exec mailer */
- /* make diagnostic output be standard output */
- (void) signal(SIGINT, SIG_IGN);
- (void) signal(SIGHUP, SIG_IGN);
- (void) signal(SIGTERM, SIG_DFL);
+ (void) setsignal(SIGINT, SIG_IGN);
+ (void) setsignal(SIGHUP, SIG_IGN);
+ (void) setsignal(SIGTERM, SIG_DFL);
- /* close any other cached connections */
- mci_flush(FALSE, mci);
+ /* reset user and group */
+ if (!bitnset(M_RESTR, m->m_flags))
+ {
+ if (ctladdr == NULL || ctladdr->q_uid == 0)
+ {
+ (void) initgroups(DefUser, DefGid);
+ (void) setgid(DefGid);
+ (void) setuid(DefUid);
+ }
+ else
+ {
+ (void) initgroups(ctladdr->q_ruser?
+ ctladdr->q_ruser: ctladdr->q_user,
+ ctladdr->q_gid);
+ (void) setgid(ctladdr->q_gid);
+ (void) setuid(ctladdr->q_uid);
+ }
+ }
+
+ if (tTd(11, 2))
+ printf("openmailer: running as r/euid=%d/%d\n",
+ getuid(), geteuid());
/* move into some "safe" directory */
if (m->m_execdir != NULL)
@@ -1185,7 +1240,8 @@ tryhost:
}
(void) close(rpvect[1]);
}
- else if (OpMode == MD_SMTP || HoldErrs)
+ else if (OpMode == MD_SMTP || OpMode == MD_DAEMON ||
+ HoldErrs || DisConnected)
{
/* put mailer output in transcript */
if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0)
@@ -1212,38 +1268,30 @@ tryhost:
_exit(EX_OSERR);
}
(void) close(mpvect[0]);
- if (!bitnset(M_RESTR, m->m_flags))
- {
- if (ctladdr == NULL || ctladdr->q_uid == 0)
- {
- (void) setgid(DefGid);
- (void) initgroups(DefUser, DefGid);
- (void) setuid(DefUid);
- }
- else
- {
- (void) setgid(ctladdr->q_gid);
- (void) initgroups(ctladdr->q_ruser?
- ctladdr->q_ruser: ctladdr->q_user,
- ctladdr->q_gid);
- (void) setuid(ctladdr->q_uid);
- }
- }
/* arrange for all the files to be closed */
for (i = 3; i < DtableSize; i++)
{
register int j;
+
if ((j = fcntl(i, F_GETFD, 0)) != -1)
- (void)fcntl(i, F_SETFD, j|1);
+ (void) fcntl(i, F_SETFD, j | 1);
}
- /* set up the mailer environment */
+ /*
+ ** Set up the mailer environment
+ ** TZ is timezone information.
+ ** SYSTYPE is Apollo software sys type (required).
+ ** ISP is Apollo hardware system type (required).
+ */
+
i = 0;
env[i++] = "AGENT=sendmail";
for (ep = environ; *ep != NULL; ep++)
{
- if (strncmp(*ep, "TZ=", 3) == 0)
+ if (strncmp(*ep, "TZ=", 3) == 0 ||
+ strncmp(*ep, "ISP=", 4) == 0 ||
+ strncmp(*ep, "SYSTYPE=", 8) == 0)
env[i++] = *ep;
}
env[i++] = NULL;
@@ -1268,10 +1316,33 @@ tryhost:
mci->mci_pid = pid;
(void) close(mpvect[0]);
mci->mci_out = fdopen(mpvect[1], "w");
+ if (mci->mci_out == NULL)
+ {
+ syserr("deliver: cannot create mailer output channel, fd=%d",
+ mpvect[1]);
+ (void) close(mpvect[1]);
+ if (clever)
+ {
+ (void) close(rpvect[0]);
+ (void) close(rpvect[1]);
+ }
+ rcode = EX_OSERR;
+ goto give_up;
+ }
if (clever)
{
(void) close(rpvect[1]);
mci->mci_in = fdopen(rpvect[0], "r");
+ if (mci->mci_in == NULL)
+ {
+ syserr("deliver: cannot create mailer input channel, fd=%d",
+ mpvect[1]);
+ (void) close(rpvect[0]);
+ fclose(mci->mci_out);
+ mci->mci_out = NULL;
+ rcode = EX_OSERR;
+ goto give_up;
+ }
}
else
{
@@ -1291,7 +1362,7 @@ tryhost:
if (tTd(11, 1))
{
printf("openmailer: ");
- mci_dump(mci);
+ mci_dump(mci, FALSE);
}
if (mci->mci_state != MCIS_OPEN)
@@ -1299,7 +1370,7 @@ tryhost:
/* couldn't open the mailer */
rcode = mci->mci_exitstat;
errno = mci->mci_errno;
-#ifdef NAMED_BIND
+#if NAMED_BIND
h_errno = mci->mci_herrno;
#endif
if (rcode == EX_OK)
@@ -1309,7 +1380,7 @@ tryhost:
rcode, mci->mci_state, firstsig);
rcode = EX_SOFTWARE;
}
- else if (rcode == EX_TEMPFAIL && *curhost != '\0')
+ else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0')
{
/* try next MX site */
goto tryhost;
@@ -1321,10 +1392,10 @@ tryhost:
** Format and send message.
*/
- putfromline(mci->mci_out, m, e);
- (*e->e_puthdr)(mci->mci_out, m, e);
- putline("\n", mci->mci_out, m);
- (*e->e_putbody)(mci->mci_out, m, e, NULL);
+ putfromline(mci, e);
+ (*e->e_puthdr)(mci, e);
+ putline("\n", mci);
+ (*e->e_putbody)(mci, e, NULL);
/* get the exit status */
rcode = endmailer(mci, e, pv);
@@ -1350,13 +1421,14 @@ tryhost:
if ((i = smtprcpt(to, m, mci, e)) != EX_OK)
{
markfailure(e, to, i);
- giveresponse(i, m, mci, e);
+ giveresponse(i, m, mci, ctladdr, e);
}
else
{
*t++ = ',';
for (p = to->q_paddr; *p; *t++ = *p++)
continue;
+ *t = '\0';
}
}
@@ -1378,7 +1450,7 @@ tryhost:
if (!bitset(MCIF_CACHED, mci->mci_flags))
smtpquit(m, mci, e);
}
- if (rcode != EX_OK && *curhost != '\0')
+ if (rcode != EX_OK && curhost != NULL && *curhost != '\0')
{
/* try next MX site */
goto tryhost;
@@ -1391,13 +1463,14 @@ tryhost:
goto give_up;
}
#endif /* SMTP */
-#ifdef NAMED_BIND
+#if NAMED_BIND
if (ConfigLevel < 2)
_res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */
#endif
/* arrange a return receipt if requested */
- if (e->e_receiptto != NULL && bitnset(M_LOCALMAILER, m->m_flags))
+ 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? */
@@ -1412,7 +1485,7 @@ tryhost:
give_up:
if (tobuf[0] != '\0')
- giveresponse(rcode, m, mci, e);
+ giveresponse(rcode, m, mci, ctladdr, e);
for (to = tochain; to != NULL; to = to->q_tchain)
{
if (rcode != EX_OK)
@@ -1421,6 +1494,12 @@ tryhost:
{
to->q_flags |= QSENT;
e->e_nsent++;
+ if (e->e_receiptto != NULL &&
+ bitnset(M_LOCALMAILER, m->m_flags))
+ {
+ fprintf(e->e_xfp, "%s... Successfully delivered\n",
+ to->q_paddr);
+ }
}
}
@@ -1428,6 +1507,18 @@ tryhost:
** Restore state and return.
*/
+#ifdef XDEBUG
+ {
+ char wbuf[MAXLINE];
+
+ /* make absolutely certain 0, 1, and 2 are in use */
+ sprintf(wbuf, "%s... end of deliver(%s)",
+ e->e_to == NULL ? "NO-TO-LIST" : e->e_to,
+ m->m_name);
+ checkfd012(wbuf);
+ }
+#endif
+
errno = 0;
define('g', (char *) NULL, e);
return (rcode);
@@ -1456,12 +1547,21 @@ markfailure(e, q, rcode)
{
char buf[MAXLINE];
- if (rcode == EX_OK)
- return;
- else if (rcode == EX_TEMPFAIL)
+ switch (rcode)
+ {
+ case EX_OK:
+ break;
+
+ case EX_TEMPFAIL:
+ case EX_IOERR:
+ case EX_OSERR:
q->q_flags |= QQUEUEUP;
- else if (rcode != EX_IOERR && rcode != EX_OSERR)
+ break;
+
+ default:
q->q_flags |= QBADADDR;
+ break;
+ }
}
/*
** ENDMAILER -- Wait for mailer to terminate.
@@ -1493,9 +1593,9 @@ endmailer(mci, e, pv)
/* close any connections */
if (mci->mci_in != NULL)
- (void) xfclose(mci->mci_in, pv[0], "mci_in");
+ (void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in");
if (mci->mci_out != NULL)
- (void) xfclose(mci->mci_out, pv[0], "mci_out");
+ (void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out");
mci->mci_in = mci->mci_out = NULL;
mci->mci_state = MCIS_CLOSED;
@@ -1511,29 +1611,29 @@ endmailer(mci, e, pv)
return (EX_SOFTWARE);
}
- /* see if it died a horrid death */
- if ((st & 0377) != 0)
+ if (WIFEXITED(st))
{
- syserr("mailer %s died with signal %o", pv[0], st);
+ /* normal death -- return status */
+ return (WEXITSTATUS(st));
+ }
- /* log the arguments */
- if (e->e_xfp != NULL)
- {
- register char **av;
+ /* it died a horrid death */
+ syserr("451 mailer %s died with signal %o",
+ mci->mci_mailer->m_name, st);
- fprintf(e->e_xfp, "Arguments:");
- for (av = pv; *av != NULL; av++)
- fprintf(e->e_xfp, " %s", *av);
- fprintf(e->e_xfp, "\n");
- }
+ /* log the arguments */
+ if (pv != NULL && e->e_xfp != NULL)
+ {
+ register char **av;
- ExitStat = EX_TEMPFAIL;
- return (EX_TEMPFAIL);
+ fprintf(e->e_xfp, "Arguments:");
+ for (av = pv; *av != NULL; av++)
+ fprintf(e->e_xfp, " %s", *av);
+ fprintf(e->e_xfp, "\n");
}
- /* normal death -- return status */
- st = (st >> 8) & 0377;
- return (st);
+ ExitStat = EX_TEMPFAIL;
+ return (EX_TEMPFAIL);
}
/*
** GIVERESPONSE -- Interpret an error response from a mailer
@@ -1545,6 +1645,8 @@ endmailer(mci, e, pv)
** m -- the mailer info for this mailer.
** mci -- the mailer connection info -- can be NULL if the
** response is given before the connection is made.
+** ctladdr -- the controlling address for the recipient
+** address(es).
** e -- the current envelope.
**
** Returns:
@@ -1555,10 +1657,11 @@ endmailer(mci, e, pv)
** ExitStat may be set.
*/
-giveresponse(stat, m, mci, e)
+giveresponse(stat, m, mci, ctladdr, e)
int stat;
register MAILER *m;
register MCI *mci;
+ ADDRESS *ctladdr;
ENVELOPE *e;
{
register const char *statmsg;
@@ -1590,9 +1693,9 @@ giveresponse(stat, m, mci, e)
else if (stat == EX_TEMPFAIL)
{
(void) strcpy(buf, SysExMsg[i] + 1);
-#ifdef NAMED_BIND
+#if NAMED_BIND
if (h_errno == TRY_AGAIN)
- statmsg = errstring(h_errno+MAX_ERRNO);
+ statmsg = errstring(h_errno+E_DNSBASE);
else
#endif
{
@@ -1601,8 +1704,6 @@ giveresponse(stat, m, mci, e)
else
{
#ifdef SMTP
- extern char SmtpError[];
-
statmsg = SmtpError;
#else /* SMTP */
statmsg = NULL;
@@ -1616,10 +1717,10 @@ giveresponse(stat, m, mci, e)
}
statmsg = buf;
}
-#ifdef NAMED_BIND
+#if NAMED_BIND
else if (stat == EX_NOHOST && h_errno != 0)
{
- statmsg = errstring(h_errno + MAX_ERRNO);
+ statmsg = errstring(h_errno + E_DNSBASE);
(void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg);
statmsg = buf;
}
@@ -1639,7 +1740,13 @@ giveresponse(stat, m, mci, e)
*/
if (stat == EX_OK || stat == EX_TEMPFAIL)
- message(&statmsg[4], errstring(errno));
+ {
+ extern char MsgBuf[];
+
+ message("%s", &statmsg[4]);
+ if (stat == EX_TEMPFAIL && e->e_xfp != NULL)
+ fprintf(e->e_xfp, "%s\n", &MsgBuf[4]);
+ }
else
{
Errors++;
@@ -1654,29 +1761,38 @@ giveresponse(stat, m, mci, e)
*/
if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6))
- logdelivery(m, mci, &statmsg[4], e);
+ logdelivery(m, mci, &statmsg[4], ctladdr, e);
+
+ if (tTd(11, 2))
+ printf("giveresponse: stat=%d, e->e_message=%s\n",
+ stat, e->e_message);
if (stat != EX_TEMPFAIL)
setstat(stat);
- if (stat != EX_OK)
+ if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL))
{
if (e->e_message != NULL)
free(e->e_message);
e->e_message = newstr(&statmsg[4]);
}
errno = 0;
-#ifdef NAMED_BIND
+#if NAMED_BIND
h_errno = 0;
#endif
}
/*
** LOGDELIVERY -- log the delivery in the system log
**
+** Care is taken to avoid logging lines that are too long, because
+** some versions of syslog have an unfortunate proclivity for core
+** dumping. This is a hack, to be sure, that is at best empirical.
+**
** Parameters:
** m -- the mailer info. Can be NULL for initial queue.
** mci -- the mailer connection info -- can be NULL if the
** log is occuring when no connection is active.
** stat -- the message to print for the status.
+** ctladdr -- the controlling address for the to list.
** e -- the current envelope.
**
** Returns:
@@ -1686,21 +1802,42 @@ giveresponse(stat, m, mci, e)
** none
*/
-logdelivery(m, mci, stat, e)
+logdelivery(m, mci, stat, ctladdr, e)
MAILER *m;
register MCI *mci;
char *stat;
+ ADDRESS *ctladdr;
register ENVELOPE *e;
{
# ifdef LOG
+ register char *bp;
+ register char *p;
+ int l;
char buf[512];
- (void) sprintf(buf, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+# if (SYSLOG_BUFSIZE) >= 256
+ bp = buf;
+ if (ctladdr != NULL)
+ {
+ strcpy(bp, ", ctladdr=");
+ strcat(bp, shortenstring(ctladdr->q_paddr, 83));
+ bp += strlen(bp);
+ if (bitset(QGOODUID, ctladdr->q_flags))
+ {
+ (void) sprintf(bp, " (%d/%d)",
+ ctladdr->q_uid, ctladdr->q_gid);
+ bp += strlen(bp);
+ }
+ }
+
+ (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+ bp += strlen(bp);
if (m != NULL)
{
- (void) strcat(buf, ", mailer=");
- (void) strcat(buf, m->m_name);
+ (void) strcpy(bp, ", mailer=");
+ (void) strcat(bp, m->m_name);
+ bp += strlen(bp);
}
if (mci != NULL && mci->mci_host != NULL)
@@ -1709,13 +1846,13 @@ logdelivery(m, mci, stat, e)
extern SOCKADDR CurHostAddr;
# endif
- (void) strcat(buf, ", relay=");
- (void) strcat(buf, mci->mci_host);
+ (void) strcpy(bp, ", relay=");
+ (void) strcat(bp, mci->mci_host);
# ifdef DAEMON
- (void) strcat(buf, " (");
- (void) strcat(buf, anynet_ntoa(&CurHostAddr));
- (void) strcat(buf, ")");
+ (void) strcat(bp, " [");
+ (void) strcat(bp, anynet_ntoa(&CurHostAddr));
+ (void) strcat(bp, "]");
# endif
}
else
@@ -1724,13 +1861,118 @@ logdelivery(m, mci, stat, e)
if (p != NULL && p[0] != '\0')
{
- (void) strcat(buf, ", relay=");
- (void) strcat(buf, p);
+ (void) strcpy(bp, ", relay=");
+ (void) strcat(bp, p);
}
}
+ bp += strlen(bp);
+
+#define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4)
+#if (STATLEN) < 63
+# undef STATLEN
+# define STATLEN 63
+#endif
+#if (STATLEN) > 203
+# undef STATLEN
+# define STATLEN 203
+#endif
+
+ if ((bp - buf) > (sizeof buf - ((STATLEN) + 20)))
+ {
+ /* desperation move -- truncate data */
+ bp = buf + sizeof buf - ((STATLEN) + 17);
+ strcpy(bp, "...");
+ bp += 3;
+ }
+
+ (void) strcpy(bp, ", stat=");
+ bp += strlen(bp);
+
+ (void) strcpy(bp, shortenstring(stat, (STATLEN)));
- syslog(LOG_INFO, "%s: to=%s, %s, stat=%s",
- e->e_id, e->e_to, buf, stat);
+ l = SYSLOG_BUFSIZE - 100 - strlen(buf);
+ p = e->e_to;
+ while (strlen(p) >= l)
+ {
+ register char *q = strchr(p + l, ',');
+
+ if (q == NULL)
+ break;
+ syslog(LOG_INFO, "%s: to=%.*s [more]%s",
+ e->e_id, ++q - p, p, buf);
+ p = q;
+ }
+ syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf);
+
+# else /* we have a very short log buffer size */
+
+ l = SYSLOG_BUFSIZE - 85;
+ p = e->e_to;
+ while (strlen(p) >= l)
+ {
+ register char *q = strchr(p + l, ',');
+
+ if (q == NULL)
+ break;
+ syslog(LOG_INFO, "%s: to=%.*s [more]",
+ e->e_id, ++q - p, p);
+ p = q;
+ }
+ syslog(LOG_INFO, "%s: to=%s", e->e_id, p);
+
+ if (ctladdr != NULL)
+ {
+ bp = buf;
+ strcpy(buf, "ctladdr=");
+ bp += strlen(buf);
+ strcpy(bp, shortenstring(ctladdr->q_paddr, 83));
+ bp += strlen(buf);
+ if (bitset(QGOODUID, ctladdr->q_flags))
+ {
+ (void) sprintf(bp, " (%d/%d)",
+ ctladdr->q_uid, ctladdr->q_gid);
+ bp += strlen(bp);
+ }
+ syslog(LOG_INFO, "%s: %s", e->e_id, buf);
+ }
+ bp = buf;
+ sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE));
+ bp += strlen(bp);
+
+ if (m != NULL)
+ {
+ sprintf(bp, ", mailer=%s", m->m_name);
+ bp += strlen(bp);
+ }
+ syslog(LOG_INFO, "%s: %s", e->e_id, buf);
+
+ buf[0] = '\0';
+ if (mci != NULL && mci->mci_host != NULL)
+ {
+# ifdef DAEMON
+ extern SOCKADDR CurHostAddr;
+# endif
+
+ sprintf(buf, "relay=%s", mci->mci_host);
+
+# ifdef DAEMON
+ (void) strcat(buf, " [");
+ (void) strcat(buf, anynet_ntoa(&CurHostAddr));
+ (void) strcat(buf, "]");
+# endif
+ }
+ else
+ {
+ char *p = macvalue('h', e);
+
+ if (p != NULL && p[0] != '\0')
+ sprintf(buf, "relay=%s", p);
+ }
+ if (buf[0] != '\0')
+ syslog(LOG_INFO, "%s: %s", e->e_id, buf);
+
+ syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63));
+# endif /* short log buffer */
# endif /* LOG */
}
/*
@@ -1744,8 +1986,8 @@ logdelivery(m, mci, stat, e)
** this kind of antique garbage????
**
** Parameters:
-** fp -- the file to output to.
-** m -- the mailer describing this entry.
+** mci -- the connection information.
+** e -- the envelope.
**
** Returns:
** none
@@ -1754,19 +1996,18 @@ logdelivery(m, mci, stat, e)
** outputs some text to fp.
*/
-putfromline(fp, m, e)
- register FILE *fp;
- register MAILER *m;
+putfromline(mci, e)
+ register MCI *mci;
ENVELOPE *e;
{
char *template = "\201l\n";
char buf[MAXLINE];
- if (bitnset(M_NHDR, m->m_flags))
+ if (bitnset(M_NHDR, mci->mci_mailer->m_flags))
return;
# ifdef UGLYUUCP
- if (bitnset(M_UGLYUUCP, m->m_flags))
+ if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags))
{
char *bang;
char xbuf[MAXLINE];
@@ -1774,7 +2015,10 @@ putfromline(fp, m, e)
expand("\201g", buf, &buf[sizeof buf - 1], e);
bang = strchr(buf, '!');
if (bang == NULL)
- syserr("554 No ! in UUCP! (%s)", buf);
+ {
+ errno = 0;
+ syserr("554 No ! in UUCP From address! (%s given)", buf);
+ }
else
{
*bang++ = '\0';
@@ -1784,14 +2028,13 @@ putfromline(fp, m, e)
}
# endif /* UGLYUUCP */
expand(template, buf, &buf[sizeof buf - 1], e);
- putline(buf, fp, m);
+ putline(buf, mci);
}
/*
** PUTBODY -- put the body of a message.
**
** Parameters:
-** fp -- file to output onto.
-** m -- a mailer descriptor to control output format.
+** mci -- the connection information.
** e -- the envelope to put out.
** separator -- if non-NULL, a message separator that must
** not be permitted in the resulting message.
@@ -1803,9 +2046,8 @@ putfromline(fp, m, e)
** The message is written onto fp.
*/
-putbody(fp, m, e, separator)
- FILE *fp;
- MAILER *m;
+putbody(mci, e, separator)
+ register MCI *mci;
register ENVELOPE *e;
char *separator;
{
@@ -1822,43 +2064,45 @@ putbody(fp, m, e, separator)
e->e_dfp = fopen(e->e_df, "r");
if (e->e_dfp == NULL)
syserr("putbody: Cannot open %s for %s from %s",
- e->e_df, e->e_to, e->e_from);
+ e->e_df, e->e_to, e->e_from.q_paddr);
}
else
- putline("<<< No Message Collected >>>", fp, m);
+ putline("<<< No Message Collected >>>", mci);
}
if (e->e_dfp != NULL)
{
rewind(e->e_dfp);
- while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL)
+ while (!ferror(mci->mci_out) && fgets(buf, sizeof buf, e->e_dfp) != NULL)
{
- if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
+ if (buf[0] == 'F' &&
+ bitnset(M_ESCFROM, mci->mci_mailer->m_flags) &&
strncmp(buf, "From ", 5) == 0)
- (void) putc('>', fp);
+ (void) putc('>', mci->mci_out);
if (buf[0] == '-' && buf[1] == '-' && separator != NULL)
{
/* possible separator */
int sl = strlen(separator);
if (strncmp(&buf[2], separator, sl) == 0)
- (void) putc(' ', fp);
+ (void) putc(' ', mci->mci_out);
}
- putline(buf, fp, m);
+ putline(buf, mci);
}
if (ferror(e->e_dfp))
{
- syserr("putbody: read error");
+ syserr("putbody: %s: read error", e->e_df);
ExitStat = EX_IOERR;
}
}
/* some mailers want extra blank line at end of message */
- if (bitnset(M_BLANKEND, m->m_flags) && buf[0] != '\0' && buf[0] != '\n')
- putline("", fp, m);
+ if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) &&
+ buf[0] != '\0' && buf[0] != '\n')
+ putline("", mci);
- (void) fflush(fp);
- if (ferror(fp) && errno != EPIPE)
+ (void) fflush(mci->mci_out);
+ if (ferror(mci->mci_out) && errno != EPIPE)
{
syserr("putbody: write error");
ExitStat = EX_IOERR;
@@ -1923,10 +2167,11 @@ mailfile(filename, ctladdr, e)
{
/* child -- actually write to file */
struct stat stb;
+ MCI mcibuf;
- (void) signal(SIGINT, SIG_DFL);
- (void) signal(SIGHUP, SIG_DFL);
- (void) signal(SIGTERM, SIG_DFL);
+ (void) setsignal(SIGINT, SIG_DFL);
+ (void) setsignal(SIGHUP, SIG_DFL);
+ (void) setsignal(SIGTERM, SIG_DFL);
(void) umask(OldUmask);
if (stat(filename, &stb) < 0)
@@ -1939,9 +2184,7 @@ mailfile(filename, ctladdr, e)
if (bitset(0111, stb.st_mode))
exit(EX_CANTCREAT);
- if (ctladdr == NULL)
- ctladdr = &e->e_from;
- else
+ if (ctladdr != NULL)
{
/* ignore setuid and setgid bits */
mode &= ~(S_ISGID|S_ISUID);
@@ -1954,20 +2197,18 @@ mailfile(filename, ctladdr, e)
if (e->e_dfp == NULL)
{
syserr("mailfile: Cannot open %s for %s from %s",
- e->e_df, e->e_to, e->e_from);
+ e->e_df, e->e_to, e->e_from.q_paddr);
}
}
if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0)
{
- if (ctladdr->q_uid == 0)
+ if (ctladdr == NULL || ctladdr->q_uid == 0)
{
- (void) setgid(DefGid);
(void) initgroups(DefUser, DefGid);
}
else
{
- (void) setgid(ctladdr->q_gid);
(void) initgroups(ctladdr->q_ruser ?
ctladdr->q_ruser : ctladdr->q_user,
ctladdr->q_gid);
@@ -1975,7 +2216,7 @@ mailfile(filename, ctladdr, e)
}
if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0)
{
- if (ctladdr->q_uid == 0)
+ if (ctladdr == NULL || ctladdr->q_uid == 0)
(void) setuid(DefUid);
else
(void) setuid(ctladdr->q_uid);
@@ -1985,18 +2226,24 @@ mailfile(filename, ctladdr, e)
f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode);
if (f == NULL)
{
- message("554 cannot open");
+ message("554 cannot open: %s", errstring(errno));
exit(EX_CANTCREAT);
}
- putfromline(f, FileMailer, e);
- (*e->e_puthdr)(f, FileMailer, e);
- putline("\n", f, FileMailer);
- (*e->e_putbody)(f, FileMailer, e, NULL);
- putline("\n", f, FileMailer);
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_mailer = FileMailer;
+ mcibuf.mci_out = f;
+ if (bitnset(M_7BITS, FileMailer->m_flags))
+ mcibuf.mci_flags |= MCIF_7BIT;
+
+ putfromline(&mcibuf, e);
+ (*e->e_puthdr)(&mcibuf, e);
+ putline("\n", &mcibuf);
+ (*e->e_putbody)(&mcibuf, e, NULL);
+ putline("\n", &mcibuf);
if (ferror(f))
{
- message("451 I/O error");
+ message("451 I/O error: %s", errstring(errno));
setstat(EX_IOERR);
}
(void) xfclose(f, "mailfile", filename);
@@ -2013,10 +2260,13 @@ mailfile(filename, ctladdr, e)
int st;
st = waitfor(pid);
- if ((st & 0377) != 0)
- return (EX_UNAVAILABLE);
+ if (WIFEXITED(st))
+ return (WEXITSTATUS(st));
else
- return ((st >> 8) & 0377);
+ {
+ syserr("child died on signal %d", st);
+ return (EX_UNAVAILABLE);
+ }
/*NOTREACHED*/
}
}
@@ -2049,7 +2299,7 @@ hostsignature(m, host, e)
register STAB *s;
int i;
int len;
-#ifdef NAMED_BIND
+#if NAMED_BIND
int nmx;
auto int rcode;
char *hp;
@@ -2070,13 +2320,6 @@ hostsignature(m, host, e)
}
/*
- ** If it is a numeric address, just return it.
- */
-
- if (host[0] == '[')
- return host;
-
- /*
** Look it up in the symbol table.
*/
@@ -2088,7 +2331,7 @@ hostsignature(m, host, e)
** Not already there -- create a signature.
*/
-#ifdef NAMED_BIND
+#if NAMED_BIND
if (ConfigLevel < 2)
{
oldoptions = _res.options;
@@ -2106,13 +2349,12 @@ hostsignature(m, host, e)
if (nmx <= 0)
{
register MCI *mci;
- extern int errno;
/* update the connection info for this host */
mci = mci_get(hp, m);
mci->mci_exitstat = rcode;
mci->mci_errno = errno;
-#ifdef NAMED_BIND
+#if NAMED_BIND
mci->mci_herrno = h_errno;
#endif
diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c
index fe977d29ed6a..48109fef9770 100644
--- a/usr.sbin/sendmail/src/domain.c
+++ b/usr.sbin/sendmail/src/domain.c
@@ -35,14 +35,14 @@
#include "sendmail.h"
#ifndef lint
-#ifdef NAMED_BIND
-static char sccsid[] = "@(#)domain.c 8.1 (Berkeley) 6/7/93 (with name server)";
+#if NAMED_BIND
+static char sccsid[] = "@(#)domain.c 8.19 (Berkeley) 3/11/94 (with name server)";
#else
-static char sccsid[] = "@(#)domain.c 8.1 (Berkeley) 6/7/93 (without name server)";
+static char sccsid[] = "@(#)domain.c 8.19 (Berkeley) 3/11/94 (without name server)";
#endif
#endif /* not lint */
-#ifdef NAMED_BIND
+#if NAMED_BIND
#include <errno.h>
#include <arpa/nameser.h>
@@ -65,6 +65,14 @@ static char MXHostBuf[MAXMXHOSTS*PACKETSZ];
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
+#ifndef NO_DATA
+# define NO_DATA NO_ADDRESS
+#endif
+
+#ifndef HEADERSZ
+# define HEADERSZ sizeof(HEADER)
+#endif
+
/* don't use sizeof because sizeof(long) is different on 64-bit machines */
#define SHORTSIZE 2 /* size of a short (really, must be 2) */
#define LONGSIZE 4 /* size of a long (really, must be 4) */
@@ -96,18 +104,24 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
{
extern int h_errno;
register u_char *eom, *cp;
- register int i, j, n, nmx;
+ register int i, j, n;
+ int nmx = 0;
register char *bp;
HEADER *hp;
querybuf answer;
int ancount, qdcount, buflen;
- bool seenlocal;
+ bool seenlocal = FALSE;
u_short pref, localpref, type;
char *fallbackMX = FallBackMX;
static bool firsttime = TRUE;
STAB *st;
+ bool trycanon = FALSE;
u_short prefer[MAXMXHOSTS];
int weight[MAXMXHOSTS];
+ extern bool getcanonname();
+
+ if (tTd(8, 2))
+ printf("getmxrr(%s, droplocalhost=%d)\n", host, droplocalhost);
if (fallbackMX != NULL)
{
@@ -127,6 +141,10 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
firsttime = FALSE;
}
+ /* efficiency hack -- numeric or non-MX lookups */
+ if (host[0] == '[')
+ goto punt;
+
errno = 0;
n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer));
if (n < 0)
@@ -137,13 +155,26 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
switch (h_errno)
{
case NO_DATA:
+ trycanon = TRUE;
+ /* fall through */
+
case NO_RECOVERY:
/* no MX data on this host */
goto punt;
case HOST_NOT_FOUND:
+#ifdef BROKEN_RES_SEARCH
+ /* Ultrix resolver returns failure w/ h_errno=0 */
+ case 0:
+#endif
/* the host just doesn't exist */
*rcode = EX_NOHOST;
+
+ if (!UseNameServer)
+ {
+ /* might exist in /etc/hosts */
+ goto punt;
+ }
break;
case TRY_AGAIN:
@@ -154,6 +185,12 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
/* it might come up later; better queue it up */
*rcode = EX_TEMPFAIL;
break;
+
+ default:
+ syserr("getmxrr: res_search (%s) failed with impossible h_errno (%d)\n",
+ host, h_errno);
+ *rcode = EX_OSERR;
+ break;
}
/* irreconcilable differences */
@@ -162,13 +199,11 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
/* find first satisfactory answer */
hp = (HEADER *)&answer;
- cp = (u_char *)&answer + sizeof(HEADER);
+ cp = (u_char *)&answer + HEADERSZ;
eom = (u_char *)&answer + n;
for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
if ((n = dn_skipname(cp, eom)) < 0)
goto punt;
- nmx = 0;
- seenlocal = FALSE;
buflen = sizeof(MXHostBuf) - 1;
bp = MXHostBuf;
ancount = ntohs(hp->ancount);
@@ -198,6 +233,9 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
(st = stab(bp, ST_CLASS, ST_FIND)) != NULL &&
bitnset('w', st->s_class))
{
+ if (tTd(8, 3))
+ printf("found localhost (%s) in MX list, pref=%d\n",
+ bp, pref);
if (!seenlocal || pref < localpref)
localpref = pref;
seenlocal = TRUE;
@@ -216,63 +254,95 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
*bp++ = '\0';
buflen -= n + 1;
}
- if (nmx == 0)
+
+ /* sort the records */
+ for (i = 0; i < nmx; i++)
{
-punt:
- mxhosts[0] = strcpy(MXHostBuf, host);
- bp = &MXHostBuf[strlen(MXHostBuf)];
- if (bp[-1] != '.')
+ for (j = i + 1; j < nmx; j++)
{
- *bp++ = '.';
- *bp = '\0';
+ if (prefer[i] > prefer[j] ||
+ (prefer[i] == prefer[j] && weight[i] > weight[j]))
+ {
+ register int temp;
+ register char *temp1;
+
+ temp = prefer[i];
+ prefer[i] = prefer[j];
+ prefer[j] = temp;
+ temp1 = mxhosts[i];
+ mxhosts[i] = mxhosts[j];
+ mxhosts[j] = temp1;
+ temp = weight[i];
+ weight[i] = weight[j];
+ weight[j] = temp;
+ }
+ }
+ if (seenlocal && prefer[i] >= localpref)
+ {
+ /* truncate higher preference part of list */
+ nmx = i;
}
- nmx = 1;
}
- else
+
+ if (nmx == 0)
{
- /* sort the records */
- for (i = 0; i < nmx; i++)
+punt:
+ if (seenlocal &&
+ (!TryNullMXList || gethostbyname(host) == NULL))
+ {
+ /*
+ ** If we have deleted all MX entries, this is
+ ** an error -- we should NEVER send to a host that
+ ** has an MX, and this should have been caught
+ ** earlier in the config file.
+ **
+ ** Some sites prefer to go ahead and try the
+ ** A record anyway; that case is handled by
+ ** setting TryNullMXList. I believe this is a
+ ** bad idea, but it's up to you....
+ */
+
+ *rcode = EX_CONFIG;
+ syserr("MX list for %s points back to %s",
+ host, MyHostName);
+ return -1;
+ }
+ strcpy(MXHostBuf, host);
+ mxhosts[0] = MXHostBuf;
+ if (host[0] == '[')
{
- for (j = i + 1; j < nmx; j++)
+ register char *p;
+
+ /* this may be an MX suppression-style address */
+ p = strchr(MXHostBuf, ']');
+ if (p != NULL)
{
- if (prefer[i] > prefer[j] ||
- (prefer[i] == prefer[j] && weight[i] > weight[j]))
+ *p = '\0';
+ if (inet_addr(&MXHostBuf[1]) != -1)
+ *p = ']';
+ else
{
- register int temp;
- register char *temp1;
-
- temp = prefer[i];
- prefer[i] = prefer[j];
- prefer[j] = temp;
- temp1 = mxhosts[i];
- mxhosts[i] = mxhosts[j];
- mxhosts[j] = temp1;
- temp = weight[i];
- weight[i] = weight[j];
- weight[j] = temp;
+ trycanon = TRUE;
+ mxhosts[0]++;
}
}
- if (seenlocal && prefer[i] >= localpref)
+ }
+ if (trycanon &&
+ getcanonname(mxhosts[0], sizeof MXHostBuf - 2, FALSE))
+ {
+ bp = &MXHostBuf[strlen(MXHostBuf)];
+ if (bp[-1] != '.')
{
- /*
- * truncate higher pref part of list; if we're
- * the best choice left, we should have realized
- * awhile ago that this was a local delivery.
- */
- if (i == 0)
- {
- *rcode = EX_CONFIG;
- return (-1);
- }
- nmx = i;
- break;
+ *bp++ = '.';
+ *bp = '\0';
}
}
+ nmx = 1;
}
/* if we have a default lowest preference, include that */
- if (FallBackMX != NULL && !seenlocal)
- mxhosts[nmx++] = FallBackMX;
+ if (fallbackMX != NULL && !seenlocal)
+ mxhosts[nmx++] = fallbackMX;
return (nmx);
}
@@ -317,7 +387,7 @@ mxrand(host)
if (isascii(c) && isupper(c))
c = tolower(c);
- hfunc = ((hfunc << 1) + c) % 2003;
+ hfunc = ((hfunc << 1) ^ c) % 2003;
}
hfunc &= 0xff;
@@ -348,6 +418,7 @@ mxrand(host)
** host -- a buffer containing the name of the host.
** This is a value-result parameter.
** hbsize -- the size of the host buffer.
+** trymx -- if set, try MX records as well as A and CNAME.
**
** Returns:
** TRUE -- if the host matched.
@@ -355,9 +426,10 @@ mxrand(host)
*/
bool
-getcanonname(host, hbsize)
+getcanonname(host, hbsize, trymx)
char *host;
int hbsize;
+ bool trymx;
{
extern int h_errno;
register u_char *eom, *ap;
@@ -375,8 +447,10 @@ getcanonname(host, hbsize)
bool gotmx;
int qtype;
int loopcnt;
+ char *xp;
char nbuf[MAX(PACKETSZ, MAXDNAME*2+2)];
char *searchlist[MAXDNSRCH+2];
+ extern char *gethostalias();
if (tTd(8, 2))
printf("getcanonname(%s)\n", host);
@@ -400,6 +474,20 @@ cnameloop:
if (*cp == '.')
n++;
+ if (n == 0 && (xp = gethostalias(host)) != NULL)
+ {
+ if (loopcnt++ > MAXCNAMEDEPTH)
+ {
+ syserr("loop in ${HOSTALIASES} file");
+ }
+ else
+ {
+ strncpy(host, xp, hbsize);
+ host[hbsize - 1] = '\0';
+ goto cnameloop;
+ }
+ }
+
dp = searchlist;
if (n > 0)
*dp++ = "";
@@ -412,6 +500,10 @@ cnameloop:
{
*dp++ = _res.defdname;
}
+ else if (*cp == '.')
+ {
+ *cp = '\0';
+ }
*dp = NULL;
/*
@@ -452,7 +544,7 @@ cnameloop:
qtype = T_A;
continue;
}
- else if (qtype == T_A && !gotmx)
+ else if (qtype == T_A && !gotmx && trymx)
{
qtype = T_MX;
continue;
@@ -480,7 +572,7 @@ cnameloop:
*/
hp = (HEADER *) &answer;
- ap = (u_char *) &answer + sizeof(HEADER);
+ ap = (u_char *) &answer + HEADERSZ;
eom = (u_char *) &answer + ret;
/* skip question part of response -- we know what we asked */
@@ -513,7 +605,7 @@ cnameloop:
if (**dp != '\0')
{
/* got a match -- save that info */
- if (mxmatch == NULL)
+ if (trymx && mxmatch == NULL)
mxmatch = *dp;
continue;
}
@@ -531,9 +623,19 @@ cnameloop:
case T_CNAME:
if (loopcnt++ > MAXCNAMEDEPTH)
{
- syserr("DNS failure: CNAME loop for %s",
+ /*XXX should notify postmaster XXX*/
+ message("DNS failure: CNAME loop for %s",
host);
- continue;
+ if (CurEnv->e_message == NULL)
+ {
+ char ebuf[MAXLINE];
+
+ sprintf(ebuf, "Deferred: DNS failure: CNAME loop for %s",
+ host);
+ CurEnv->e_message = newstr(ebuf);
+ }
+ h_errno = NO_RECOVERY;
+ return FALSE;
}
/* value points at name */
@@ -571,7 +673,7 @@ cnameloop:
if (qtype == T_ANY)
qtype = T_A;
- else if (qtype == T_A && !gotmx)
+ else if (qtype == T_A && !gotmx && trymx)
qtype = T_MX;
else
{
@@ -593,14 +695,63 @@ cnameloop:
return TRUE;
}
+
+char *
+gethostalias(host)
+ char *host;
+{
+ char *fname;
+ FILE *fp;
+ register char *p;
+ char buf[MAXLINE];
+ static char hbuf[MAXDNAME];
+
+ fname = getenv("HOSTALIASES");
+ if (fname == NULL || (fp = fopen(fname, "r")) == NULL)
+ return NULL;
+ while (fgets(buf, sizeof buf, fp) != NULL)
+ {
+ for (p = buf; p != '\0' && !(isascii(*p) && isspace(*p)); p++)
+ continue;
+ if (*p == 0)
+ {
+ /* syntax error */
+ continue;
+ }
+ *p++ = '\0';
+ if (strcasecmp(buf, host) == 0)
+ break;
+ }
+
+ if (feof(fp))
+ {
+ /* no match */
+ fclose(fp);
+ return NULL;
+ }
+
+ /* got a match; extract the equivalent name */
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ host = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ *p = '\0';
+ strncpy(hbuf, host, sizeof hbuf - 1);
+ hbuf[sizeof hbuf - 1] = '\0';
+ return hbuf;
+}
+
+
#else /* not NAMED_BIND */
#include <netdb.h>
bool
-getcanonname(host, hbsize)
+getcanonname(host, hbsize, trymx)
char *host;
int hbsize;
+ bool trymx;
{
struct hostent *hp;
diff --git a/usr.sbin/sendmail/src/envelope.c b/usr.sbin/sendmail/src/envelope.c
index 6818d8a59de4..14656f0d7ee1 100644
--- a/usr.sbin/sendmail/src/envelope.c
+++ b/usr.sbin/sendmail/src/envelope.c
@@ -33,11 +33,10 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)envelope.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)envelope.c 8.33 (Berkeley) 2/10/94";
#endif /* not lint */
#include "sendmail.h"
-#include <sys/time.h>
#include <pwd.h>
/*
@@ -101,6 +100,7 @@ dropenvelope(e)
register ENVELOPE *e;
{
bool queueit = FALSE;
+ bool saveit = bitset(EF_FATALERRS, e->e_flags);
register ADDRESS *q;
char *id = e->e_id;
char buf[MAXLINE];
@@ -109,7 +109,7 @@ dropenvelope(e)
{
printf("dropenvelope %x: id=", e);
xputs(e->e_id);
- printf(", flags=%o\n", e->e_flags);
+ printf(", flags=0x%x\n", e->e_flags);
if (tTd(50, 10))
{
printf("sendq=");
@@ -122,10 +122,13 @@ dropenvelope(e)
return;
#ifdef LOG
+ if (LogLevel > 4 && bitset(EF_LOGSENDER, e->e_flags))
+ logsender(e, NULL);
if (LogLevel > 84)
- syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
+ syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=0x%x, pid=%d",
id, e->e_flags, getpid());
#endif /* LOG */
+ e->e_flags &= ~EF_LOGSENDER;
/* post statistics */
poststats(StatFile);
@@ -134,10 +137,19 @@ dropenvelope(e)
** Extract state information from dregs of send list.
*/
+ e->e_flags &= ~EF_QUEUERUN;
for (q = e->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QQUEUEUP, q->q_flags))
queueit = TRUE;
+ if (!bitset(QDONTSEND, q->q_flags) &&
+ bitset(QBADADDR, q->q_flags))
+ {
+ if (q->q_owner == NULL &&
+ strcmp(e->e_from.q_paddr, "<>") != 0)
+ (void) sendtolist(e->e_from.q_paddr, NULL,
+ &e->e_errorqueue, e);
+ }
}
/*
@@ -148,16 +160,14 @@ dropenvelope(e)
/* nothing to do */ ;
else if (curtime() > e->e_ctime + TimeOuts.to_q_return)
{
- if (!bitset(EF_TIMEOUT, e->e_flags))
- {
- (void) sprintf(buf, "Cannot send message for %s",
- pintvl(TimeOuts.to_q_return, FALSE));
- if (e->e_message != NULL)
- free(e->e_message);
- e->e_message = newstr(buf);
- message(buf);
- }
- e->e_flags |= EF_TIMEOUT|EF_CLRQUEUE;
+ (void) sprintf(buf, "Cannot send message for %s",
+ pintvl(TimeOuts.to_q_return, FALSE));
+ if (e->e_message != NULL)
+ free(e->e_message);
+ e->e_message = newstr(buf);
+ message(buf);
+ e->e_flags |= EF_CLRQUEUE;
+ saveit = TRUE;
fprintf(e->e_xfp, "Message could not be delivered for %s\n",
pintvl(TimeOuts.to_q_return, FALSE));
fprintf(e->e_xfp, "Message will be deleted from queue\n");
@@ -181,7 +191,8 @@ dropenvelope(e)
free(e->e_message);
e->e_message = newstr(buf);
message(buf);
- e->e_flags |= EF_WARNING|EF_TIMEOUT;
+ e->e_flags |= EF_WARNING;
+ saveit = TRUE;
}
fprintf(e->e_xfp,
"Warning: message still undelivered after %s\n",
@@ -203,35 +214,53 @@ dropenvelope(e)
{
auto ADDRESS *rlist = NULL;
- (void) sendtolist(e->e_receiptto, (ADDRESS *) NULL, &rlist, e);
+ (void) sendtolist(e->e_receiptto, NULLADDR, &rlist, e);
(void) returntosender("Return receipt", rlist, FALSE, e);
+ e->e_flags &= ~EF_SENDRECEIPT;
}
/*
** Arrange to send error messages if there are fatal errors.
*/
- if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) &&
- e->e_errormode != EM_QUIET)
+ if (saveit && e->e_errormode != EM_QUIET)
savemail(e);
/*
+ ** Arrange to send warning messages to postmaster as requested.
+ */
+
+ if (bitset(EF_PM_NOTIFY, e->e_flags) && PostMasterCopy != NULL &&
+ !bitset(EF_RESPONSE, e->e_flags) && e->e_class >= 0)
+ {
+ auto ADDRESS *rlist = NULL;
+
+ (void) sendtolist(PostMasterCopy, NULLADDR, &rlist, e);
+ (void) returntosender(e->e_message, rlist, FALSE, e);
+ }
+
+ /*
** Instantiate or deinstantiate the queue.
*/
if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
bitset(EF_CLRQUEUE, e->e_flags))
{
- if (tTd(50, 2))
- printf("Dropping envelope\n");
+ if (tTd(50, 1))
+ printf("\n===== Dropping [dq]f%s =====\n\n", e->e_id);
if (e->e_df != NULL)
xunlink(e->e_df);
xunlink(queuename(e, 'q'));
+
+#ifdef LOG
+ if (LogLevel > 10)
+ syslog(LOG_INFO, "%s: done", id);
+#endif
}
else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
{
#ifdef QUEUE
- queueup(e, FALSE, FALSE);
+ queueup(e, bitset(EF_KEEPQUEUE, e->e_flags), FALSE);
#else /* QUEUE */
syserr("554 dropenvelope: queueup");
#endif /* QUEUE */
@@ -246,11 +275,6 @@ dropenvelope(e)
(void) xfclose(e->e_dfp, "dropenvelope", e->e_df);
e->e_dfp = NULL;
e->e_id = e->e_df = NULL;
-
-#ifdef LOG
- if (LogLevel > 74)
- syslog(LOG_INFO, "%s: done", id);
-#endif /* LOG */
}
/*
** CLEARENVELOPE -- clear an envelope without unlocking
@@ -326,8 +350,8 @@ void
initsys(e)
register ENVELOPE *e;
{
- static char cbuf[5]; /* holds hop count */
- static char pbuf[10]; /* holds pid */
+ char cbuf[5]; /* holds hop count */
+ char pbuf[10]; /* holds pid */
#ifdef TTYNAME
static char ybuf[60]; /* holds tty id */
register char *p;
@@ -351,7 +375,7 @@ initsys(e)
** tucked away in the transcript).
*/
- if (OpMode == MD_DAEMON && !bitset(EF_QUEUERUN, e->e_flags) &&
+ if (OpMode == MD_DAEMON && bitset(EF_QUEUERUN, e->e_flags) &&
e->e_xfp != NULL)
OutChannel = e->e_xfp;
@@ -361,11 +385,11 @@ initsys(e)
/* process id */
(void) sprintf(pbuf, "%d", getpid());
- define('p', pbuf, e);
+ define('p', newstr(pbuf), e);
/* hop count */
(void) sprintf(cbuf, "%d", e->e_hopcount);
- define('c', cbuf, e);
+ define('c', newstr(cbuf), e);
/* time as integer, unix time, arpa time */
settime(e);
@@ -404,8 +428,8 @@ settime(e)
{
register char *p;
auto time_t now;
- static char tbuf[20]; /* holds "current" time */
- static char dbuf[30]; /* holds ctime(tbuf) */
+ char tbuf[20]; /* holds "current" time */
+ char dbuf[30]; /* holds ctime(tbuf) */
register struct tm *tm;
extern char *arpadate();
extern struct tm *gmtime();
@@ -414,13 +438,14 @@ settime(e)
tm = gmtime(&now);
(void) sprintf(tbuf, "%04d%02d%02d%02d%02d", tm->tm_year + 1900,
tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
- define('t', tbuf, e);
+ define('t', newstr(tbuf), e);
(void) strcpy(dbuf, ctime(&now));
p = strchr(dbuf, '\n');
if (p != NULL)
*p = '\0';
- define('d', dbuf, e);
- p = newstr(arpadate(dbuf));
+ define('d', newstr(dbuf), e);
+ p = arpadate(dbuf);
+ p = newstr(p);
if (macvalue('a', e) == NULL)
define('a', p, e);
define('b', p, e);
@@ -464,6 +489,15 @@ openxscript(e)
syserr("!Can't open /dev/null");
}
e->e_xfp = fdopen(fd, "w");
+ if (e->e_xfp == NULL)
+ {
+ syserr("!Can't create transcript stream %s", p);
+ }
+ if (tTd(46, 9))
+ {
+ printf("openxscript(%s):\n ", p);
+ dumpfd(fileno(e->e_xfp), TRUE, FALSE);
+ }
}
/*
** CLOSEXSCRIPT -- close the transcript file.
@@ -535,7 +569,8 @@ setsender(from, e, delimptr, internal)
char *realname = NULL;
register struct passwd *pw;
char delimchar;
- char buf[MAXNAME];
+ char *bp;
+ char buf[MAXNAME + 2];
char pvpbuf[PSBUFSIZE];
extern struct passwd *getpwnam();
extern char *FullName;
@@ -548,7 +583,8 @@ setsender(from, e, delimptr, internal)
** Username can return errno != 0 on non-errors.
*/
- if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP)
+ if (bitset(EF_QUEUERUN, e->e_flags) || OpMode == MD_SMTP ||
+ OpMode == MD_ARPAFTP || OpMode == MD_DAEMON)
realname = from;
if (realname == NULL || realname[0] == '\0')
realname = username();
@@ -557,8 +593,14 @@ setsender(from, e, delimptr, internal)
SuprErrs = TRUE;
delimchar = internal ? '\0' : ' ';
+ e->e_from.q_flags = QBADADDR;
if (from == NULL ||
- parseaddr(from, &e->e_from, 1, delimchar, delimptr, e) == NULL)
+ parseaddr(from, &e->e_from, RF_COPYALL|RF_SENDERADDR,
+ delimchar, delimptr, e) == NULL ||
+ bitset(QBADADDR, e->e_from.q_flags) ||
+ e->e_from.q_mailer == ProgMailer ||
+ e->e_from.q_mailer == FileMailer ||
+ e->e_from.q_mailer == InclMailer)
{
/* log garbage addresses for traceback */
# ifdef LOG
@@ -577,17 +619,31 @@ setsender(from, e, delimptr, internal)
p = ebuf;
}
syslog(LOG_NOTICE,
- "from=%s unparseable, received from %s",
- from, p);
+ "setsender: %s: invalid or unparseable, received from %s",
+ shortenstring(from, 83), p);
}
# endif /* LOG */
if (from != NULL)
+ {
+ if (!bitset(QBADADDR, e->e_from.q_flags))
+ {
+ /* it was a bogus mailer in the from addr */
+ usrerr("553 Invalid sender address");
+ }
SuprErrs = TRUE;
+ }
if (from == realname ||
- parseaddr(from = newstr(realname), &e->e_from, 1, ' ', NULL, e) == NULL)
+ parseaddr(from = newstr(realname), &e->e_from,
+ RF_COPYALL|RF_SENDERADDR, ' ', NULL, e) == NULL)
{
+ char nbuf[100];
+
SuprErrs = TRUE;
- if (parseaddr("postmaster", &e->e_from, 1, ' ', NULL, e) == NULL)
+ expand("\201n", nbuf, &nbuf[sizeof nbuf], e);
+ if (parseaddr(from = newstr(nbuf), &e->e_from,
+ RF_COPYALL, ' ', NULL, e) == NULL &&
+ parseaddr(from = "postmaster", &e->e_from,
+ RF_COPYALL, ' ', NULL, e) == NULL)
syserr("553 setsender: can't even parse postmaster!");
}
}
@@ -618,7 +674,7 @@ setsender(from, e, delimptr, internal)
FullName = NULL;
# ifdef USERDB
- p = udbsender(from);
+ p = udbsender(e->e_from.q_user);
if (p != NULL)
{
@@ -626,7 +682,7 @@ setsender(from, e, delimptr, internal)
** We have an alternate address for the sender
*/
- pvp = prescan(p, '\0', pvpbuf, NULL);
+ pvp = prescan(p, '\0', pvpbuf, sizeof pvpbuf, NULL);
}
# endif /* USERDB */
}
@@ -637,14 +693,17 @@ setsender(from, e, delimptr, internal)
** Process passwd file entry.
*/
-
/* extract home directory */
- e->e_from.q_home = newstr(pw->pw_dir);
+ if (strcmp(pw->pw_dir, "/") == 0)
+ e->e_from.q_home = newstr("");
+ else
+ e->e_from.q_home = newstr(pw->pw_dir);
define('z', e->e_from.q_home, e);
/* extract user and group id */
e->e_from.q_uid = pw->pw_uid;
e->e_from.q_gid = pw->pw_gid;
+ e->e_from.q_flags |= QGOODUID;
/* extract full name from passwd file */
if (FullName == NULL && pw->pw_gecos != NULL &&
@@ -659,12 +718,18 @@ setsender(from, e, delimptr, internal)
if (FullName != NULL && !internal)
define('x', FullName, e);
}
- else if (!internal)
+ else if (!internal && OpMode != MD_DAEMON)
{
if (e->e_from.q_home == NULL)
+ {
e->e_from.q_home = getenv("HOME");
+ if (e->e_from.q_home != NULL &&
+ strcmp(e->e_from.q_home, "/") == 0)
+ e->e_from.q_home++;
+ }
e->e_from.q_uid = RealUid;
e->e_from.q_gid = RealGid;
+ e->e_from.q_flags |= QGOODUID;
}
/*
@@ -673,7 +738,7 @@ setsender(from, e, delimptr, internal)
*/
if (pvp == NULL)
- pvp = prescan(from, '\0', pvpbuf, NULL);
+ pvp = prescan(from, delimchar, pvpbuf, sizeof pvpbuf, NULL);
if (pvp == NULL)
{
/* don't need to give error -- prescan did that already */
@@ -683,15 +748,22 @@ setsender(from, e, delimptr, internal)
# endif
finis();
}
- (void) rewrite(pvp, 3, e);
- (void) rewrite(pvp, 1, e);
- (void) rewrite(pvp, 4, e);
- cataddr(pvp, NULL, buf, sizeof buf, '\0');
- e->e_sender = newstr(buf);
+ (void) rewrite(pvp, 3, 0, e);
+ (void) rewrite(pvp, 1, 0, e);
+ (void) rewrite(pvp, 4, 0, e);
+ bp = buf + 1;
+ cataddr(pvp, NULL, bp, sizeof buf - 2, '\0');
+ if (*bp == '@')
+ {
+ /* heuristic: route-addr: add angle brackets */
+ strcat(bp, ">");
+ *--bp = '<';
+ }
+ e->e_sender = newstr(bp);
define('f', e->e_sender, e);
/* save the domain spec if this mailer wants it */
- if (!internal && e->e_from.q_mailer != NULL &&
+ if (e->e_from.q_mailer != NULL &&
bitnset(M_CANONICAL, e->e_from.q_mailer->m_flags))
{
extern char **copyplist();
diff --git a/usr.sbin/sendmail/src/err.c b/usr.sbin/sendmail/src/err.c
index 9ee17becf456..fee36c4b42af 100644
--- a/usr.sbin/sendmail/src/err.c
+++ b/usr.sbin/sendmail/src/err.c
@@ -33,12 +33,13 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)err.c 8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)err.c 8.26 (Berkeley) 3/11/94";
#endif /* not lint */
# include "sendmail.h"
# include <errno.h>
# include <netdb.h>
+# include <pwd.h>
/*
** SYSERR -- Print error message.
@@ -64,13 +65,13 @@ static char sccsid[] = "@(#)err.c 8.2 (Berkeley) 7/11/93";
** sets ExitStat.
*/
-# ifdef lint
-int sys_nerr;
-char *sys_errlist[];
-# endif lint
char MsgBuf[BUFSIZ*2]; /* text of most recent message */
-static void fmtmsg();
+static void fmtmsg();
+
+#if NAMED_BIND && !defined(NO_DATA)
+# define NO_DATA NO_ADDRESS
+#endif
void
/*VARARGS1*/
@@ -85,6 +86,11 @@ syserr(fmt, va_alist)
register char *p;
int olderrno = errno;
bool panic;
+#ifdef LOG
+ char *uname;
+ struct passwd *pw;
+ char ubuf[80];
+#endif
VA_LOCAL_DECL
panic = *fmt == '!';
@@ -108,14 +114,30 @@ syserr(fmt, va_alist)
ExitStat = EX_SOFTWARE;
else
ExitStat = EX_OSERR;
+ if (tTd(54, 1))
+ printf("syserr: ExitStat = %d\n", ExitStat);
}
# ifdef LOG
+ pw = getpwuid(getuid());
+ if (pw != NULL)
+ uname = pw->pw_name;
+ else
+ {
+ uname = ubuf;
+ sprintf(ubuf, "UID%d", getuid());
+ }
+
if (LogLevel > 0)
- syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR: %s",
+ syslog(panic ? LOG_ALERT : LOG_CRIT, "%s: SYSERR(%s): %s",
CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
- &MsgBuf[4]);
+ uname, &MsgBuf[4]);
# endif /* LOG */
+ if (olderrno == EMFILE)
+ {
+ printopenfds(TRUE);
+ mci_dump_all(TRUE);
+ }
if (panic)
{
#ifdef XLA
@@ -154,8 +176,6 @@ usrerr(fmt, va_alist)
#endif
{
VA_LOCAL_DECL
- extern char SuprErrs;
- extern int errno;
if (SuprErrs)
return;
@@ -265,29 +285,45 @@ putoutmsg(msg, holdmsg)
char *msg;
bool holdmsg;
{
+ /* display for debugging */
+ if (tTd(54, 8))
+ printf("--- %s%s\n", msg, holdmsg ? " (held)" : "");
+
/* output to transcript if serious */
- if (CurEnv->e_xfp != NULL && (msg[0] == '4' || msg[0] == '5'))
+ if (CurEnv->e_xfp != NULL && strchr("456", msg[0]) != NULL)
fprintf(CurEnv->e_xfp, "%s\n", msg);
/* output to channel if appropriate */
if (holdmsg || (!Verbose && msg[0] == '0'))
return;
+ /* map warnings to something SMTP can handle */
+ if (msg[0] == '6')
+ msg[0] = '5';
+
(void) fflush(stdout);
- if (OpMode == MD_SMTP)
+
+ /* if DisConnected, OutChannel now points to the transcript */
+ if (!DisConnected &&
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON || OpMode == MD_ARPAFTP))
fprintf(OutChannel, "%s\r\n", msg);
else
fprintf(OutChannel, "%s\n", &msg[4]);
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%05d >>> %s\n", getpid(),
- OpMode == MD_SMTP ? msg : &msg[4]);
+ (OpMode == MD_SMTP || OpMode == MD_DAEMON) ? msg : &msg[4]);
if (msg[3] == ' ')
(void) fflush(OutChannel);
- if (!ferror(OutChannel))
+ if (!ferror(OutChannel) || DisConnected)
return;
- /* error on output -- if reporting lost channel, just ignore it */
- if (feof(InChannel) || ferror(InChannel))
+ /*
+ ** Error on output -- if reporting lost channel, just ignore it.
+ ** Also, ignore errors from QUIT response (221 message) -- some
+ ** rude servers don't read result.
+ */
+
+ if (feof(InChannel) || ferror(InChannel) || strncmp(msg, "221", 3) == 0)
return;
/* can't call syserr, 'cause we are using MsgBuf */
@@ -295,9 +331,10 @@ putoutmsg(msg, holdmsg)
#ifdef LOG
if (LogLevel > 0)
syslog(LOG_CRIT,
- "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\"",
+ "%s: SYSERR: putoutmsg (%s): error on output channel sending \"%s\": %m",
CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id,
- CurHostName, msg);
+ CurHostName == NULL ? "NO-HOST" : CurHostName,
+ msg);
#endif
}
/*
@@ -316,13 +353,23 @@ putoutmsg(msg, holdmsg)
puterrmsg(msg)
char *msg;
{
+ char msgcode = msg[0];
+
/* output the message as usual */
putoutmsg(msg, HoldErrs);
/* signal the error */
Errors++;
- if (msg[0] == '5')
+ if (msgcode == '6')
+ {
+ /* notify the postmaster */
+ CurEnv->e_flags |= EF_PM_NOTIFY;
+ }
+ else if (msgcode == '5' && bitset(EF_GLOBALERRS, CurEnv->e_flags))
+ {
+ /* mark long-term fatal errors */
CurEnv->e_flags |= EF_FATALERRS;
+ }
}
/*
** FMTMSG -- format a message into buffer.
@@ -377,7 +424,7 @@ fmtmsg(eb, to, num, eno, fmt, ap)
/* output the "to" person */
if (to != NULL && to[0] != '\0')
{
- (void) sprintf(eb, "%s... ", to);
+ (void) sprintf(eb, "%s... ", shortenstring(to, 203));
while (*eb != '\0')
*eb++ &= 0177;
}
@@ -396,46 +443,53 @@ fmtmsg(eb, to, num, eno, fmt, ap)
eb += strlen(eb);
}
- if (CurEnv->e_message == NULL && strchr("45", num[0]) != NULL)
+ if (num[0] == '5' || (CurEnv->e_message == NULL && num[0] == '4'))
+ {
+ if (CurEnv->e_message != NULL)
+ free(CurEnv->e_message);
CurEnv->e_message = newstr(meb);
+ }
}
/*
** ERRSTRING -- return string description of error code
**
** Parameters:
-** errno -- the error number to translate
+** errnum -- the error number to translate
**
** Returns:
-** A string description of errno.
+** A string description of errnum.
**
** Side Effects:
** none.
*/
const char *
-errstring(errno)
- int errno;
+errstring(errnum)
+ int errnum;
{
- extern const char *const sys_errlist[];
- extern int sys_nerr;
+ char *dnsmsg;
static char buf[MAXLINE];
+# ifndef ERRLIST_PREDEFINED
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+# endif
# ifdef SMTP
extern char *SmtpPhase;
# endif /* SMTP */
-# ifdef DAEMON
-# ifdef ETIMEDOUT
/*
** Handle special network error codes.
**
** These are 4.2/4.3bsd specific; they should be in daemon.c.
*/
- switch (errno)
+ dnsmsg = NULL;
+ switch (errnum)
{
+# if defined(DAEMON) && defined(ETIMEDOUT)
case ETIMEDOUT:
case ECONNRESET:
- (void) strcpy(buf, sys_errlist[errno]);
+ (void) strcpy(buf, sys_errlist[errnum]);
if (SmtpPhase != NULL)
{
(void) strcat(buf, " during ");
@@ -459,27 +513,49 @@ errstring(errno)
break;
(void) sprintf(buf, "Connection refused by %s", CurHostName);
return (buf);
+# endif
-# ifdef NAMED_BIND
- case HOST_NOT_FOUND + MAX_ERRNO:
- return ("Name server: host not found");
+ case EOPENTIMEOUT:
+ return "Timeout on file open";
- case TRY_AGAIN + MAX_ERRNO:
- return ("Name server: host name lookup failure");
+# if NAMED_BIND
+ case HOST_NOT_FOUND + E_DNSBASE:
+ dnsmsg = "host not found";
+ break;
- case NO_RECOVERY + MAX_ERRNO:
- return ("Name server: non-recoverable error");
+ case TRY_AGAIN + E_DNSBASE:
+ dnsmsg = "host name lookup failure";
+ break;
- case NO_DATA + MAX_ERRNO:
- return ("Name server: no data known for name");
+ case NO_RECOVERY + E_DNSBASE:
+ dnsmsg = "non-recoverable error";
+ break;
+
+ case NO_DATA + E_DNSBASE:
+ dnsmsg = "no data known";
+ break;
# endif
+
+ case EPERM:
+ /* SunOS gives "Not owner" -- this is the POSIX message */
+ return "Operation not permitted";
+ }
+
+ if (dnsmsg != NULL)
+ {
+ (void) strcpy(buf, "Name server: ");
+ if (CurHostName != NULL)
+ {
+ (void) strcat(buf, CurHostName);
+ (void) strcat(buf, ": ");
+ }
+ (void) strcat(buf, dnsmsg);
+ return buf;
}
-# endif
-# endif
- if (errno > 0 && errno < sys_nerr)
- return (sys_errlist[errno]);
+ if (errnum > 0 && errnum < sys_nerr)
+ return (sys_errlist[errnum]);
- (void) sprintf(buf, "Error %d", errno);
+ (void) sprintf(buf, "Error %d", errnum);
return (buf);
}
diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c
index 6679b50347d5..0d80b884b10f 100644
--- a/usr.sbin/sendmail/src/headers.c
+++ b/usr.sbin/sendmail/src/headers.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)headers.c 8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)headers.c 8.30 (Berkeley) 2/25/94";
#endif /* not lint */
# include <errno.h>
@@ -70,6 +70,7 @@ chompheader(line, def, e)
struct hdrinfo *hi;
bool cond = FALSE;
BITMAP mopts;
+ char buf[MAXNAME];
if (tTd(31, 6))
printf("chompheader: %s\n", line);
@@ -96,16 +97,18 @@ chompheader(line, def, e)
/* find canonical name */
fname = p;
- p = strchr(p, ':');
- if (p == NULL)
+ while (isascii(*p) && isgraph(*p) && *p != ':')
+ p++;
+ fvalue = p;
+ while (isascii(*p) && isspace(*p))
+ p++;
+ if (*p++ != ':' || fname == fvalue)
{
syserr("553 header syntax error, line \"%s\"", line);
return (0);
}
- fvalue = &p[1];
- while (isascii(*--p) && isspace(*p))
- continue;
- *++p = '\0';
+ *fvalue = '\0';
+ fvalue = p;
/* strip field value on front */
if (*fvalue == ' ')
@@ -118,6 +121,14 @@ chompheader(line, def, e)
break;
}
+ if (tTd(31, 9))
+ {
+ if (hi->hi_field == NULL)
+ printf("no header match\n");
+ else
+ printf("header match, hi_flags=%o\n", hi->hi_flags);
+ }
+
/* see if this is a resent message */
if (!def && bitset(H_RESENT, hi->hi_flags))
e->e_flags |= EF_RESENT;
@@ -126,7 +137,12 @@ chompheader(line, def, e)
if (bitset(H_EOH, hi->hi_flags))
return (hi->hi_flags);
- /* drop explicit From: if same as what we would generate -- for MH */
+ /*
+ ** Drop explicit From: if same as what we would generate.
+ ** This is to make MH (which doesn't always give a full name)
+ ** insert the full name information in all circumstances.
+ */
+
p = "resent-from";
if (!bitset(EF_RESENT, e->e_flags))
p += 7;
@@ -141,6 +157,46 @@ chompheader(line, def, 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 */
+#ifdef 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 &&
+ a.q_mailer == LocalMailer &&
+ (p = udbsender(a.q_user)) != NULL)
+ {
+ char *oldg = macvalue('g', e);
+
+ define('g', p, e);
+ expand(fancy, buf, &buf[sizeof buf], e);
+ define('g', oldg, e);
+ fvalue = buf;
+ }
+ SuprErrs = oldSuprErrs;
+ }
+#endif
+#endif
}
/* delete default value for this header */
@@ -155,7 +211,7 @@ chompheader(line, def, e)
/* create a new node */
h = (HDR *) xalloc(sizeof *h);
h->h_field = newstr(fname);
- h->h_value = NULL;
+ h->h_value = newstr(fvalue);
h->h_link = NULL;
bcopy((char *) mopts, (char *) h->h_mflags, sizeof mopts);
*hp = h;
@@ -164,9 +220,6 @@ chompheader(line, def, e)
h->h_flags |= H_DEFAULT;
if (cond)
h->h_flags |= H_CHECK;
- if (h->h_value != NULL)
- free((char *) h->h_value);
- h->h_value = newstr(fvalue);
/* hack to see if this is a new format message */
if (!def && bitset(H_RCPT|H_FROM, h->h_flags) &&
@@ -323,14 +376,30 @@ eatheader(e, full)
define('f', e->e_sender, e);
define('g', e->e_sender, e);
+ if (e->e_origrcpt != NULL && *e->e_origrcpt != '\0')
+ define('u', e->e_origrcpt, e);
+ else
+ define('u', NULL, e);
+
+ /* full name of from person */
+ p = hvalue("full-name", e);
+ if (p != NULL)
+ define('x', p, e);
if (tTd(32, 1))
printf("----- collected header -----\n");
msgid = "<none>";
for (h = e->e_header; h != NULL; h = h->h_link)
{
+ if (h->h_value == NULL)
+ {
+ if (tTd(32, 1))
+ printf("%s: <NULL>\n", h->h_field);
+ continue;
+ }
+
/* do early binding */
- if (bitset(H_DEFAULT, h->h_flags) && h->h_value != NULL)
+ if (bitset(H_DEFAULT, h->h_flags))
{
expand(h->h_value, buf, &buf[sizeof buf], e);
if (buf[0] != '\0')
@@ -341,7 +410,11 @@ eatheader(e, full)
}
if (tTd(32, 1))
- printf("%s: %s\n", h->h_field, h->h_value);
+ {
+ printf("%s: ", h->h_field);
+ xputs(h->h_value);
+ printf("\n");
+ }
/* count the number of times it has been processed */
if (bitset(H_TRACE, h->h_flags))
@@ -352,13 +425,18 @@ eatheader(e, full)
!bitset(H_DEFAULT, h->h_flags) &&
(!bitset(EF_RESENT, e->e_flags) || bitset(H_RESENT, h->h_flags)))
{
- (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+ int saveflags = e->e_flags;
+
+ (void) sendtolist(h->h_value, NULLADDR,
&e->e_sendqueue, e);
+
+ /* delete fatal errors generated by this address */
+ if (!GrabTo && !bitset(EF_FATALERRS, saveflags))
+ e->e_flags &= ~EF_FATALERRS;
}
/* save the message-id for logging */
- if (full && h->h_value != NULL &&
- strcasecmp(h->h_field, "message-id") == 0)
+ if (full && strcasecmp(h->h_field, "message-id") == 0)
{
msgid = h->h_value;
while (isascii(*msgid) && isspace(*msgid))
@@ -371,7 +449,7 @@ eatheader(e, full)
/* see if this is an errors-to header */
if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags))
- (void) sendtolist(h->h_value, (ADDRESS *) NULL,
+ (void) sendtolist(h->h_value, NULLADDR,
&e->e_errorqueue, e);
}
if (tTd(32, 1))
@@ -394,11 +472,6 @@ eatheader(e, full)
- e->e_class * WkClassFact
+ e->e_nrcpts * WkRecipFact;
- /* full name of from person */
- p = hvalue("full-name", e);
- if (p != NULL)
- define('x', p, e);
-
/* date message originated */
p = hvalue("posted-date", e);
if (p == NULL)
@@ -407,53 +480,130 @@ eatheader(e, full)
define('a', p, e);
/*
+ ** From person in antiquated ARPANET mode
+ ** required by UK Grey Book e-mail gateways (sigh)
+ */
+
+ if (OpMode == MD_ARPAFTP)
+ {
+ register struct hdrinfo *hi;
+
+ for (hi = HdrInfo; hi->hi_field != NULL; hi++)
+ {
+ if (bitset(H_FROM, hi->hi_flags) &&
+ (!bitset(H_RESENT, hi->hi_flags) ||
+ bitset(EF_RESENT, e->e_flags)) &&
+ (p = hvalue(hi->hi_field, e)) != NULL)
+ break;
+ }
+ if (hi->hi_field != NULL)
+ {
+ if (tTd(32, 2))
+ printf("eatheader: setsender(*%s == %s)\n",
+ hi->hi_field, p);
+ setsender(p, e, NULL, TRUE);
+ }
+ }
+
+ /*
** Log collection information.
*/
# ifdef LOG
if (full && LogLevel > 4)
+ logsender(e, msgid);
+# endif /* LOG */
+ e->e_flags &= ~EF_LOGSENDER;
+}
+ /*
+** LOGSENDER -- log sender information
+**
+** Parameters:
+** e -- the envelope to log
+** msgid -- the message id
+**
+** Returns:
+** none
+*/
+
+logsender(e, msgid)
+ register ENVELOPE *e;
+ char *msgid;
+{
+ char *name;
+ register char *sbp;
+ register char *p;
+ char hbuf[MAXNAME];
+ char sbuf[MAXLINE];
+
+ if (bitset(EF_RESPONSE, e->e_flags))
+ name = "[RESPONSE]";
+ else if ((name = macvalue('_', e)) != NULL)
+ ;
+ else if (RealHostName == NULL)
+ name = "localhost";
+ else if (RealHostName[0] == '[')
+ name = RealHostName;
+ else
{
- char *name;
- register char *sbp;
- char hbuf[MAXNAME];
- char sbuf[MAXLINE];
-
- if (bitset(EF_RESPONSE, e->e_flags))
- name = "[RESPONSE]";
- else if ((name = macvalue('_', e)) != NULL)
- ;
- else if (RealHostName[0] == '[')
- name = RealHostName;
- else
+ name = hbuf;
+ (void) sprintf(hbuf, "%.80s", RealHostName);
+ if (RealHostAddr.sa.sa_family != 0)
{
- name = hbuf;
- (void) sprintf(hbuf, "%.80s", RealHostName);
- if (RealHostAddr.sa.sa_family != 0)
- {
- p = &hbuf[strlen(hbuf)];
- (void) sprintf(p, " (%s)",
- anynet_ntoa(&RealHostAddr));
- }
+ p = &hbuf[strlen(hbuf)];
+ (void) sprintf(p, " (%s)",
+ anynet_ntoa(&RealHostAddr));
}
+ }
- /* some versions of syslog only take 5 printf args */
- sbp = sbuf;
- sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d, msgid=%.100s",
- e->e_from.q_paddr, e->e_msgsize, e->e_class,
- e->e_msgpriority, e->e_nrcpts, msgid);
+ /* some versions of syslog only take 5 printf args */
+# if (SYSLOG_BUFSIZE) >= 256
+ sbp = sbuf;
+ sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d",
+ e->e_from.q_paddr, e->e_msgsize, e->e_class,
+ e->e_msgpriority, e->e_nrcpts);
+ sbp += strlen(sbp);
+ if (msgid != NULL)
+ {
+ sprintf(sbp, ", msgid=%.100s", msgid);
sbp += strlen(sbp);
- if (e->e_bodytype != NULL)
- {
- (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
- sbp += strlen(sbp);
- }
- p = macvalue('r', e);
- if (p != NULL)
- (void) sprintf(sbp, ", proto=%.20s", p);
- syslog(LOG_INFO, "%s: %s, relay=%s",
- e->e_id, sbuf, name);
}
-# endif /* LOG */
+ if (e->e_bodytype != NULL)
+ {
+ (void) sprintf(sbp, ", bodytype=%.20s", e->e_bodytype);
+ sbp += strlen(sbp);
+ }
+ p = macvalue('r', e);
+ if (p != NULL)
+ (void) sprintf(sbp, ", proto=%.20s", p);
+ syslog(LOG_INFO, "%s: %s, relay=%s",
+ e->e_id, sbuf, name);
+
+# else /* short syslog buffer */
+
+ syslog(LOG_INFO, "%s: from=%s",
+ e->e_id, shortenstring(e->e_from.q_paddr, 83));
+ syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d",
+ e->e_id, e->e_msgsize, e->e_class,
+ e->e_msgpriority, e->e_nrcpts);
+ if (msgid != NULL)
+ syslog(LOG_INFO, "%s: msgid=%s", e->e_id, msgid);
+ sbp = sbuf;
+ sprintf(sbp, "%s:", e->e_id);
+ sbp += strlen(sbp);
+ if (e->e_bodytype != NULL)
+ {
+ sprintf(sbp, " bodytype=%s,", e->e_bodytype);
+ sbp += strlen(sbp);
+ }
+ p = macvalue('r', e);
+ if (p != NULL)
+ {
+ sprintf(sbp, " proto=%s,", p);
+ sbp += strlen(sbp);
+ }
+ syslog(LOG_INFO, "%s relay=%s", sbuf, name);
+# endif
}
/*
** PRIENCODE -- encode external priority names into internal values.
@@ -525,6 +675,7 @@ crackaddr(addr)
bool skipping;
bool putgmac = FALSE;
bool quoteit = FALSE;
+ bool gotangle = FALSE;
register char *bp;
char *buflim;
static char buf[MAXNAME];
@@ -579,7 +730,7 @@ crackaddr(addr)
}
/* check for quoted strings */
- if (c == '"')
+ if (c == '"' && cmtlev <= 0)
{
qmode = !qmode;
if (copylev > 0 && !skipping)
@@ -623,13 +774,12 @@ crackaddr(addr)
else if (c == ')')
{
/* syntax error: unmatched ) */
- if (!skipping)
+ if (copylev > 0 && !skipping)
bp--;
}
-
/* check for characters that may have to be quoted */
- if (strchr(".'@,;:\\()", c) != NULL)
+ if (strchr(".'@,;:\\()[]", c) != NULL)
{
/*
** If these occur as the phrase part of a <>
@@ -647,10 +797,15 @@ crackaddr(addr)
{
register char *q;
+ /* assume first of two angles is bogus */
+ if (gotangle)
+ quoteit = TRUE;
+ gotangle = TRUE;
+
/* oops -- have to change our mind */
- anglelev++;
+ anglelev = 1;
if (!skipping)
- realanglelev++;
+ realanglelev = 1;
bp = buf;
if (quoteit)
@@ -675,7 +830,10 @@ crackaddr(addr)
}
if (quoteit)
{
- *bp++ = '"';
+ if (bp == &buf[1])
+ bp--;
+ else
+ *bp++ = '"';
while ((c = *p++) != '<')
{
if (bp < buflim)
@@ -704,6 +862,7 @@ crackaddr(addr)
/* syntax error: unmatched > */
if (copylev > 0)
bp--;
+ quoteit = TRUE;
continue;
}
if (copylev++ <= 0)
@@ -739,8 +898,7 @@ crackaddr(addr)
** PUTHEADER -- put the header part of a message from the in-core copy
**
** Parameters:
-** fp -- file to put it on.
-** m -- mailer to use.
+** mci -- the connection information.
** e -- envelope to use.
**
** Returns:
@@ -757,9 +915,8 @@ crackaddr(addr)
# define MAX(a,b) (((a)>(b))?(a):(b))
#endif
-putheader(fp, m, e)
- register FILE *fp;
- register MAILER *m;
+putheader(mci, e)
+ register MCI *mci;
register ENVELOPE *e;
{
char buf[MAX(MAXLINE,BUFSIZ)];
@@ -767,7 +924,8 @@ putheader(fp, m, e)
char obuf[MAXLINE];
if (tTd(34, 1))
- printf("--- putheader, mailer = %s ---\n", m->m_name);
+ printf("--- putheader, mailer = %s ---\n",
+ mci->mci_mailer->m_name);
for (h = e->e_header; h != NULL; h = h->h_link)
{
@@ -781,7 +939,7 @@ putheader(fp, m, e)
}
if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
- !bitintersect(h->h_mflags, m->m_flags))
+ !bitintersect(h->h_mflags, mci->mci_mailer->m_flags))
{
if (tTd(34, 11))
printf(" (skipped)\n");
@@ -795,19 +953,24 @@ putheader(fp, m, e)
printf(" (skipped (resent))\n");
continue;
}
- if (tTd(34, 11))
- printf("\n");
+ /* macro expand value if generated internally */
p = h->h_value;
if (bitset(H_DEFAULT, h->h_flags))
{
- /* macro expand value if generated internally */
expand(p, buf, &buf[sizeof buf], e);
p = buf;
if (p == NULL || *p == '\0')
+ {
+ if (tTd(34, 11))
+ printf(" (skipped -- null value)\n");
continue;
+ }
}
+ if (tTd(34, 11))
+ printf("\n");
+
if (bitset(H_FROM|H_RCPT, h->h_flags))
{
/* address field */
@@ -815,7 +978,7 @@ putheader(fp, m, e)
if (bitset(H_FROM, h->h_flags))
oldstyle = FALSE;
- commaize(h, p, fp, oldstyle, m, e);
+ commaize(h, p, oldstyle, mci, e);
}
else
{
@@ -828,12 +991,12 @@ putheader(fp, m, e)
*nlp = '\0';
(void) strcat(obuf, p);
*nlp = '\n';
- putline(obuf, fp, m);
+ putline(obuf, mci);
p = ++nlp;
obuf[0] = '\0';
}
(void) strcat(obuf, p);
- putline(obuf, fp, m);
+ putline(obuf, mci);
}
}
}
@@ -843,10 +1006,8 @@ putheader(fp, m, e)
** Parameters:
** h -- the header field to output.
** p -- the value to put in it.
-** fp -- file to put it to.
** oldstyle -- TRUE if this is an old style header.
-** m -- a pointer to the mailer descriptor. If NULL,
-** don't transform the name at all.
+** mci -- the connection information.
** e -- the envelope containing the message.
**
** Returns:
@@ -856,16 +1017,17 @@ putheader(fp, m, e)
** outputs "p" to file "fp".
*/
-commaize(h, p, fp, oldstyle, m, e)
+void
+commaize(h, p, oldstyle, mci, e)
register HDR *h;
register char *p;
- FILE *fp;
bool oldstyle;
- register MAILER *m;
+ register MCI *mci;
register ENVELOPE *e;
{
register char *obp;
int opos;
+ int omax;
bool firstone = TRUE;
char obuf[MAXLINE + 3];
@@ -881,6 +1043,9 @@ commaize(h, p, fp, oldstyle, m, e)
(void) sprintf(obp, "%s: ", h->h_field);
opos = strlen(h->h_field) + 2;
obp += opos;
+ omax = mci->mci_mailer->m_linelimit - 2;
+ if (omax < 0 || omax > 78)
+ omax = 78;
/*
** Run through the list of values.
@@ -911,7 +1076,8 @@ commaize(h, p, fp, oldstyle, m, e)
auto char *oldp;
char pvpbuf[PSBUFSIZE];
- (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, &oldp);
+ (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf,
+ sizeof pvpbuf, &oldp);
p = oldp;
/* look to see if we have an at sign */
@@ -943,7 +1109,7 @@ commaize(h, p, fp, oldstyle, m, e)
if (bitset(H_FROM, h->h_flags))
flags |= RF_SENDERADDR;
stat = EX_OK;
- name = remotename(name, m, flags, &stat, e);
+ name = remotename(name, mci->mci_mailer, flags, &stat, e);
if (*name == '\0')
{
*p = savechar;
@@ -954,19 +1120,19 @@ commaize(h, p, fp, oldstyle, m, e)
opos += strlen(name);
if (!firstone)
opos += 2;
- if (opos > 78 && !firstone)
+ if (opos > omax && !firstone)
{
(void) strcpy(obp, ",\n");
- putline(obuf, fp, m);
+ putline(obuf, mci);
obp = obuf;
- (void) sprintf(obp, " ");
+ (void) strcpy(obp, " ");
opos = strlen(obp);
obp += opos;
opos += strlen(name);
}
else if (!firstone)
{
- (void) sprintf(obp, ", ");
+ (void) strcpy(obp, ", ");
obp += 2;
}
@@ -976,7 +1142,7 @@ commaize(h, p, fp, oldstyle, m, e)
*p = savechar;
}
(void) strcpy(obp, "\n");
- putline(obuf, fp, m);
+ putline(obuf, mci);
}
/*
** COPYHEADER -- copy header list
diff --git a/usr.sbin/sendmail/src/macro.c b/usr.sbin/sendmail/src/macro.c
index 877251debbb2..8a8a90b4f0f9 100644
--- a/usr.sbin/sendmail/src/macro.c
+++ b/usr.sbin/sendmail/src/macro.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)macro.c 8.1 (Berkeley) 6/7/93";
+static char sccsid[] = "@(#)macro.c 8.3 (Berkeley) 2/7/94";
#endif /* not lint */
# include "sendmail.h"
@@ -83,7 +83,7 @@ expand(s, buf, buflim, e)
s = "";
for (xp = xbuf; *s != '\0'; s++)
{
- char c;
+ int c;
/*
** Check for non-ordinary (special?) character.
@@ -115,8 +115,14 @@ expand(s, buf, buflim, e)
continue;
case MACROEXPAND: /* macro interpolation */
- c = *++s;
- q = macvalue(c & 0177, e);
+ c = *++s & 0177;
+ if (c != '\0')
+ q = macvalue(c, e);
+ else
+ {
+ s--;
+ q = NULL;
+ }
if (q == NULL)
continue;
break;
@@ -230,7 +236,7 @@ expand(s, buf, buflim, e)
void
define(n, v, e)
- char n;
+ int n;
char *v;
register ENVELOPE *e;
{
@@ -257,7 +263,7 @@ define(n, v, e)
char *
macvalue(n, e)
- char n;
+ int n;
register ENVELOPE *e;
{
n &= 0177;
diff --git a/usr.sbin/sendmail/src/mailq.1 b/usr.sbin/sendmail/src/mailq.1
new file mode 100644
index 000000000000..f7b9da43ed0f
--- /dev/null
+++ b/usr.sbin/sendmail/src/mailq.1
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1985, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mailq.1 8.4 (Berkeley) 2/22/94
+.\"
+.Dd February 22, 1994
+.Dt MAILQ 1
+.Os BSD 4
+.Sh NAME
+.Nm mailq
+.Nd print the mail queue
+.Sh SYNOPSIS
+.Nm mailq
+.Op Fl v
+.Sh DESCRIPTION
+.Nm Mailq
+prints a summary of the mail messages queued for future delivery.
+.Pp
+The first line printed for each message
+shows the internal identifier used on this host
+for the message,
+the size of the message in bytes,
+the date and time the message was accepted into the queue,
+and the envelope sender of the message.
+The second line shows the error message that caused this message
+to be retained in the queue;
+it will not be present if the message is being processed
+for the first time.
+The following lines show message recipients,
+one per line.
+.Pp
+.Nm Mailq
+is identical to
+.Dq Li "sendmail -bp" .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl v
+Print verbose information.
+This adds the priority of the message and
+a single character indicator (``+'' or blank)
+indicating whether a warning message has been sent
+on the first line of the message.
+Additionally, extra lines may be intermixed with the recipients
+indicating the ``controlling user'' information;
+this shows who will own any programs that are executed
+on behalf of this message
+and the name of the alias this command expanded from, if any.
+.El
+.Pp
+The
+.Nm mailq
+utility exits 0 on success, and >0 if an error occurs.
+.Sh SEE ALSO
+.Xr sendmail 8
+.Sh HISTORY
+The
+.Nm mailq
+command appeared in
+.Bx 4.0 .
diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c
index f4191ba61bff..cdd97c34a9a1 100644
--- a/usr.sbin/sendmail/src/main.c
+++ b/usr.sbin/sendmail/src/main.c
@@ -39,15 +39,13 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)main.c 8.52 (Berkeley) 3/11/94";
#endif /* not lint */
#define _DEFINE
#include "sendmail.h"
-#include <signal.h>
-#include <sgtty.h>
-#ifdef NAMED_BIND
+#if NAMED_BIND
#include <arpa/nameser.h>
#include <resolv.h>
#endif
@@ -55,7 +53,7 @@ static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 7/13/93";
# ifdef lint
char edata, end;
-# endif lint
+# endif /* lint */
/*
** SENDMAIL -- Post mail to a set of destinations.
@@ -96,15 +94,15 @@ ENVELOPE BlankEnvelope; /* a "blank" envelope */
ENVELOPE MainEnvelope; /* the envelope around the basic letter */
ADDRESS NullAddress = /* a null address */
{ "", "", NULL, "" };
-char *UserEnviron[MAXUSERENVIRON + 1];
+char *UserEnviron[MAXUSERENVIRON + 2];
/* saved user environment */
char RealUserName[256]; /* the actual user id on this host */
+char *CommandLineArgs; /* command line args for pid file */
+bool Warn_Q_option = FALSE; /* warn about Q option use */
/*
** Pointers for setproctitle.
** This allows "ps" listings to give more useful information.
-** These must be kept out of BSS for frozen configuration files
-** to work.
*/
# ifdef SETPROCTITLE
@@ -120,7 +118,7 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
#endif /* SMTP */
#endif /* DAEMON */
-#define MAXCONFIGLEVEL 4 /* highest config version level known */
+#define MAXCONFIGLEVEL 5 /* highest config version level known */
main(argc, argv, envp)
int argc;
@@ -128,7 +126,6 @@ main(argc, argv, envp)
char **envp;
{
register char *p;
- register char *q;
char **av;
extern int finis();
extern char Version[];
@@ -137,10 +134,10 @@ main(argc, argv, envp)
STAB *st;
register int i;
int j;
- bool readconfig = TRUE;
bool queuemode = FALSE; /* process queue requests */
- bool nothaw;
bool safecf = TRUE;
+ bool warn_C_flag = FALSE;
+ char warn_f_flag = '\0';
static bool reenter = FALSE;
char *argv0 = argv[0];
struct passwd *pw;
@@ -154,8 +151,10 @@ main(argc, argv, envp)
extern char **myhostname();
extern char *arpadate();
extern char *getauthinfo();
+ extern char *getcfname();
extern char *optarg;
extern char **environ;
+ extern void dumpstate();
/*
** Check to see if we reentered.
@@ -170,9 +169,12 @@ main(argc, argv, envp)
}
reenter = TRUE;
-#ifndef SYS5TZ
- /* enforce use of kernel-supplied time zone information */
- unsetenv("TZ");
+ /* do machine-dependent initializations */
+ init_md(argc, argv);
+
+ /* arrange to dump state on signal */
+#ifdef SIGUSR1
+ setsignal(SIGUSR1, dumpstate);
#endif
/* in 4.4BSD, the table can be huge; impose a reasonable limit */
@@ -186,13 +188,14 @@ main(argc, argv, envp)
*/
i = open("/dev/null", O_RDWR);
- if (fstat(STDIN_FILENO, &stb) < 0)
+ if (fstat(STDIN_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
(void) dup2(i, STDIN_FILENO);
- if (fstat(STDOUT_FILENO, &stb) < 0)
+ if (fstat(STDOUT_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
(void) dup2(i, STDOUT_FILENO);
- if (fstat(STDERR_FILENO, &stb) < 0)
+ if (fstat(STDERR_FILENO, &stb) < 0 && errno != EOPNOTSUPP)
(void) dup2(i, STDERR_FILENO);
- (void) close(i);
+ if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
+ (void) close(i);
i = DtableSize;
while (--i > 0)
@@ -232,42 +235,43 @@ main(argc, argv, envp)
else
(void) sprintf(RealUserName, "Unknown UID %d", RealUid);
- /* our real uid will have to be root -- we will trash this later */
- setuid((uid_t) 0);
+ /* save command line arguments */
+ i = 0;
+ for (av = argv; *av != NULL; )
+ i += strlen(*av++) + 1;
+ CommandLineArgs = xalloc(i);
+ p = CommandLineArgs;
+ for (av = argv; *av != NULL; )
+ {
+ if (av != argv)
+ *p++ = ' ';
+ strcpy(p, *av++);
+ p += strlen(p);
+ }
/* Handle any non-getoptable constructions. */
obsolete(argv);
/*
** Do a quick prescan of the argument list.
- ** We do this to find out if we can potentially thaw the
- ** configuration file. If not, we do the thaw now so that
- ** the argument processing applies to this run rather than
- ** to the run that froze the configuration.
*/
- nothaw = FALSE;
+
#if defined(__osf__) || defined(_AIX3)
-#define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x"
-#else
-#define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:"
+# define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x"
+#endif
+#if defined(ultrix)
+# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mno:p:q:r:sTtvX:"
+#endif
+#if defined(NeXT)
+# define OPTIONS "B:b:C:cd:e:F:f:h:IimnOo:p:q:r:sTtvX:"
+#endif
+#ifndef OPTIONS
+# define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:"
#endif
while ((j = getopt(argc, argv, OPTIONS)) != EOF)
{
switch (j)
{
- case 'b':
- if (optarg[0] == 'z' && optarg[1] == '\0')
- nothaw = TRUE;
- break;
-
- case 'C':
- ConfFile = optarg;
- (void) setgid(RealGid);
- (void) setuid(RealUid);
- safecf = FALSE;
- nothaw = TRUE;
- break;
-
case 'd':
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
tTflag(optarg);
@@ -280,14 +284,6 @@ main(argc, argv, envp)
InChannel = stdin;
OutChannel = stdout;
-# ifdef FROZENCONFIG
- if (!nothaw)
- readconfig = !thaw(FreezeFile, argv0);
-# else
- readconfig = TRUE;
-# endif
-
-# ifdef SETPROCTITLE
/*
** Move the environment so setproctitle can use the space at
** the top of memory.
@@ -302,6 +298,7 @@ main(argc, argv, envp)
UserEnviron[j] = NULL;
environ = UserEnviron;
+# ifdef SETPROCTITLE
/*
** Save start and extent of argv for setproctitle.
*/
@@ -313,17 +310,17 @@ main(argc, argv, envp)
LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
# endif /* SETPROCTITLE */
- if (signal(SIGINT, SIG_IGN) != SIG_IGN)
- (void) signal(SIGINT, intsig);
- if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
- (void) signal(SIGHUP, intsig);
- (void) signal(SIGTERM, intsig);
- (void) signal(SIGPIPE, SIG_IGN);
+ if (setsignal(SIGINT, SIG_IGN) != SIG_IGN)
+ (void) setsignal(SIGINT, intsig);
+ if (setsignal(SIGHUP, SIG_IGN) != SIG_IGN)
+ (void) setsignal(SIGHUP, intsig);
+ (void) setsignal(SIGTERM, intsig);
+ (void) setsignal(SIGPIPE, SIG_IGN);
OldUmask = umask(022);
OpMode = MD_DELIVER;
FullName = getenv("NAME");
-#ifdef NAMED_BIND
+#if NAMED_BIND
if (tTd(8, 8))
_res.options |= RES_DEBUG;
#endif
@@ -331,14 +328,11 @@ main(argc, argv, envp)
errno = 0;
from = NULL;
- if (readconfig)
- {
- /* initialize some macros, etc. */
- initmacros();
+ /* initialize some macros, etc. */
+ initmacros(CurEnv);
- /* version */
- define('v', Version, CurEnv);
- }
+ /* version */
+ define('v', Version, CurEnv);
/* hostname */
av = myhostname(jbuf, sizeof jbuf);
@@ -348,23 +342,33 @@ main(argc, argv, envp)
if (tTd(0, 4))
printf("canonical name: %s\n", jbuf);
- p = newstr(jbuf);
- define('w', p, CurEnv);
- setclass('w', p);
+ define('w', newstr(jbuf), CurEnv); /* must be new string */
+ define('j', newstr(jbuf), CurEnv);
+ setclass('w', jbuf);
- q = strchr(jbuf, '.');
- if (q != NULL)
+ p = strchr(jbuf, '.');
+ if (p != NULL)
{
- *q++ = '\0';
- define('m', q, CurEnv);
- p = newstr(jbuf);
- setclass('w', p);
+ if (p[1] != '\0')
+ {
+ define('m', newstr(&p[1]), CurEnv);
+ setclass('m', &p[1]);
+ }
+ while (p != NULL && strchr(&p[1], '.') != NULL)
+ {
+ *p = '\0';
+ setclass('w', jbuf);
+ *p++ = '.';
+ p = strchr(p, '.');
+ }
}
if (uname(&utsname) >= 0)
p = utsname.nodename;
else
{
+ if (tTd(0, 22))
+ printf("uname failed (%s)\n", errstring(errno));
makelower(jbuf);
p = jbuf;
}
@@ -372,6 +376,7 @@ main(argc, argv, envp)
printf("UUCP nodename: %s\n", p);
p = newstr(p);
define('k', p, CurEnv);
+ setclass('k', p);
setclass('w', p);
}
while (av != NULL && *av != NULL)
@@ -437,18 +442,16 @@ main(argc, argv, envp)
case MD_TEST:
case MD_INITALIAS:
case MD_PRINT:
-#ifdef FROZENCONFIG
- case MD_FREEZE:
+#ifdef MAYBE_NEXT_RELEASE
+ case MD_ARPAFTP:
#endif
OpMode = j;
break;
-#ifndef FROZENCONFIG
case MD_FREEZE:
usrerr("Frozen configurations unsupported");
ExitStat = EX_USAGE;
break;
-#endif
default:
usrerr("Invalid operation mode %c", j);
@@ -463,15 +466,14 @@ main(argc, argv, envp)
case 'C': /* select configuration file (already done) */
if (RealUid != 0)
- auth_warning(CurEnv,
- "Processed by %s with -C %s",
- RealUserName, optarg);
+ warn_C_flag = TRUE;
+ ConfFile = optarg;
+ (void) setgid(RealGid);
+ (void) setuid(RealUid);
+ safecf = FALSE;
break;
- case 'd': /* debugging -- redo in case frozen */
- tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
- tTflag(optarg);
- setbuf(stdout, (char *) NULL);
+ case 'd': /* debugging -- already done */
break;
case 'f': /* from address */
@@ -484,9 +486,7 @@ main(argc, argv, envp)
}
from = newstr(optarg);
if (strcmp(RealUserName, from) != 0)
- auth_warning(CurEnv,
- "%s set sender to %s using -%c",
- RealUserName, from, j);
+ warn_f_flag = j;
break;
case 'F': /* set full name */
@@ -512,13 +512,13 @@ main(argc, argv, envp)
break;
case 'p': /* set protocol */
- q = strchr(optarg, ':');
- if (q != NULL)
- *q++ = '\0';
+ p = strchr(optarg, ':');
+ if (p != NULL)
+ *p++ = '\0';
if (*optarg != '\0')
define('r', newstr(optarg), CurEnv);
- if (q != NULL && *q != '\0')
- define('s', newstr(q), CurEnv);
+ if (p != NULL && *p != '\0')
+ define('s', newstr(p), CurEnv);
break;
case 'q': /* run queue files at intervals */
@@ -563,7 +563,7 @@ main(argc, argv, envp)
break;
}
#ifdef HASSETVBUF
- setvbuf(TrafficLogFile, NULL, _IOLBF, BUFSIZ);
+ setvbuf(TrafficLogFile, NULL, _IOLBF, 0);
#else
setlinebuf(TrafficLogFile);
#endif
@@ -579,6 +579,9 @@ main(argc, argv, envp)
break;
case 'e': /* error message disposition */
+# if defined(ultrix)
+ case 'M': /* define macro */
+# endif
setoption(j, optarg, FALSE, TRUE, CurEnv);
break;
@@ -596,6 +599,10 @@ main(argc, argv, envp)
case 'x': /* random flag that OSF/1 & AIX mailx passes */
break;
# endif
+# if defined(NeXT)
+ case 'O': /* random flag that NeXT Mail.app passes */
+ break;
+# endif
default:
ExitStat = EX_USAGE;
@@ -611,21 +618,61 @@ main(argc, argv, envp)
** Extract special fields for local use.
*/
- if (OpMode == MD_FREEZE || readconfig)
- readcf(ConfFile, safecf, CurEnv);
+#ifdef XDEBUG
+ checkfd012("before readcf");
+#endif
+ readcf(getcfname(), safecf, CurEnv);
+
+ if (tTd(0, 1))
+ {
+ printf("SYSTEM IDENTITY (after readcf):");
+ printf("\n\t (short domain name) $w = ");
+ xputs(macvalue('w', CurEnv));
+ printf("\n\t(canonical domain name) $j = ");
+ xputs(macvalue('j', CurEnv));
+ printf("\n\t (subdomain name) $m = ");
+ xputs(macvalue('m', CurEnv));
+ printf("\n\t (node name) $k = ");
+ xputs(macvalue('k', CurEnv));
+ printf("\n");
+ }
+
+ /*
+ ** Process authorization warnings from command line.
+ */
+
+ if (warn_C_flag)
+ auth_warning(CurEnv, "Processed by %s with -C %s",
+ RealUserName, ConfFile);
+/*
+ if (warn_f_flag != '\0')
+ auth_warning(CurEnv, "%s set sender to %s using -%c",
+ RealUserName, from, warn_f_flag);
+*/
+ if (Warn_Q_option)
+ auth_warning(CurEnv, "Processed from queue %s", QueueDir);
-#ifdef SYS5TZ
/* Enforce use of local time (null string overrides this) */
if (TimeZoneSpec == NULL)
unsetenv("TZ");
else if (TimeZoneSpec[0] != '\0')
{
- p = xalloc(strlen(TimeZoneSpec) + 4);
- (void) strcpy(p, "TZ=");
- (void) strcat(p, TimeZoneSpec);
- putenv(p);
+ char **evp = UserEnviron;
+ char tzbuf[100];
+
+ strcpy(tzbuf, "TZ=");
+ strcpy(&tzbuf[3], TimeZoneSpec);
+
+ while (*evp != NULL && strncmp(*evp, "TZ=", 3) != 0)
+ evp++;
+ if (*evp == NULL)
+ {
+ *evp++ = newstr(tzbuf);
+ *evp = NULL;
+ }
+ else
+ *evp++ = newstr(tzbuf);
}
-#endif
if (ConfigLevel > MAXCONFIGLEVEL)
{
@@ -633,9 +680,11 @@ main(argc, argv, envp)
ConfigLevel, MAXCONFIGLEVEL);
}
+ if (MeToo)
+ BlankEnvelope.e_flags |= EF_METOO;
# ifdef QUEUE
- if (queuemode && RealUid != 0)
+ if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags))
{
struct stat stbuf;
@@ -645,7 +694,7 @@ main(argc, argv, envp)
if (stbuf.st_uid != RealUid)
{
/* nope, really a botch */
- usrerr("Permission denied");
+ usrerr("You do not have permission to process the queue");
exit (EX_NOPERM);
}
}
@@ -653,17 +702,6 @@ main(argc, argv, envp)
switch (OpMode)
{
-# ifdef FROZENCONFIG
- case MD_FREEZE:
- /* this is critical to avoid forgeries of the frozen config */
- (void) setgid(RealGid);
- (void) setuid(RealUid);
-
- /* freeze the configuration */
- freeze(FreezeFile);
- exit(EX_OK);
-# endif
-
case MD_INITALIAS:
Verbose = TRUE;
break;
@@ -672,13 +710,6 @@ main(argc, argv, envp)
/* remove things that don't make sense in daemon mode */
FullName = NULL;
break;
-
- case MD_SMTP:
- if (RealUid != 0)
- auth_warning(CurEnv,
- "%s owned process doing -bs",
- RealUserName);
- break;
}
/* do heuristic mode adjustment */
@@ -700,6 +731,9 @@ main(argc, argv, envp)
expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
MyHostName = jbuf;
+ /* make certain that this name is part of the $=w class */
+ setclass('w', MyHostName);
+
/* the indices of built-in mailers */
st = stab("local", ST_MAILER, ST_FIND);
if (st == NULL)
@@ -727,7 +761,7 @@ main(argc, argv, envp)
/* operate in queue directory */
- if (chdir(QueueDir) < 0)
+ if (OpMode != MD_TEST && chdir(QueueDir) < 0)
{
syserr("cannot chdir(%s)", QueueDir);
ExitStat = EX_SOFTWARE;
@@ -740,6 +774,10 @@ main(argc, argv, envp)
exit(ExitStat);
}
+#ifdef XDEBUG
+ checkfd012("before main() initmaps");
+#endif
+
/*
** Do operation-mode-dependent initialization.
*/
@@ -838,6 +876,7 @@ main(argc, argv, envp)
char *q;
auto char *delimptr;
extern bool invalidaddr();
+ extern char *crackaddr();
if (Verbose)
printf("> ");
@@ -846,8 +885,20 @@ main(argc, argv, envp)
finis();
if (!Verbose)
printf("> %s", buf);
- if (buf[0] == '#')
+ switch (buf[0])
+ {
+ case '#':
continue;
+
+#ifdef MAYBENEXTRELEASE
+ case 'C': /* try crackaddr */
+ q = crackaddr(&buf[1]);
+ xputs(q);
+ printf("\n");
+ continue;
+#endif
+ }
+
for (p = buf; isascii(*p) && isspace(*p); p++)
continue;
q = p;
@@ -859,13 +910,14 @@ main(argc, argv, envp)
continue;
}
*p = '\0';
- if (invalidaddr(p + 1))
+ if (invalidaddr(p + 1, NULL))
continue;
do
{
char pvpbuf[PSBUFSIZE];
- pvp = prescan(++p, ',', pvpbuf, &delimptr);
+ pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf,
+ &delimptr);
if (pvp == NULL)
continue;
p = q;
@@ -873,7 +925,7 @@ main(argc, argv, envp)
{
int stat;
- stat = rewrite(pvp, atoi(p), CurEnv);
+ stat = rewrite(pvp, atoi(p), 0, CurEnv);
if (stat != EX_OK)
printf("== Ruleset %s status %d\n",
p, stat);
@@ -919,7 +971,7 @@ main(argc, argv, envp)
exit(0);
/* disconnect from our controlling tty */
- disconnect(TRUE, CurEnv);
+ disconnect(2, CurEnv);
}
dtype[0] = '\0';
@@ -971,23 +1023,25 @@ main(argc, argv, envp)
** commands. This will never return.
*/
- if (OpMode == MD_SMTP)
+ if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
smtp(CurEnv);
# endif /* SMTP */
+ if (OpMode == MD_VERIFY)
+ {
+ CurEnv->e_sendmode = SM_VERIFY;
+ CurEnv->e_errormode = EM_QUIET;
+ }
+ else
+ {
+ /* interactive -- all errors are global */
+ CurEnv->e_flags |= EF_GLOBALERRS;
+ }
+
/*
** Do basic system initialization and set the sender
*/
- /* make sendmail immune from process group signals */
-# ifdef _POSIX_JOB_CONTROL
- (void) setpgid(0, getpid());
-# else
-# ifndef SYSTEM5
- (void) setpgrp(0, getpid());
-# endif
-# endif
-
initsys(CurEnv);
setsender(from, CurEnv, NULL, FALSE);
if (macvalue('s', CurEnv) == NULL)
@@ -995,6 +1049,7 @@ main(argc, argv, envp)
if (*av == NULL && !GrabTo)
{
+ CurEnv->e_flags |= EF_GLOBALERRS;
usrerr("Recipient names must be specified");
/* collect body for UUCP return */
@@ -1002,11 +1057,6 @@ main(argc, argv, envp)
collect(FALSE, FALSE, CurEnv);
finis();
}
- if (OpMode == MD_VERIFY)
- {
- CurEnv->e_sendmode = SM_VERIFY;
- CurEnv->e_errormode = EM_QUIET;
- }
/*
** Scan argv and deliver the message to everyone.
@@ -1024,13 +1074,12 @@ main(argc, argv, envp)
CurEnv->e_to = NULL;
if (OpMode != MD_VERIFY || GrabTo)
+ {
+ CurEnv->e_flags |= EF_GLOBALERRS;
collect(FALSE, FALSE, CurEnv);
+ }
errno = 0;
- /* collect statistics */
- if (OpMode != MD_VERIFY)
- markstats(CurEnv, (ADDRESS *) NULL);
-
if (tTd(1, 1))
printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);
@@ -1071,7 +1120,11 @@ main(argc, argv, envp)
finis()
{
if (tTd(2, 1))
- printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);
+ printf("\n====finis: stat %d e_flags %o, e_id=%s\n",
+ ExitStat, CurEnv->e_flags,
+ CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id);
+ if (tTd(2, 9))
+ printopenfds(FALSE);
/* clean up temp files */
CurEnv->e_to = NULL;
@@ -1167,7 +1220,8 @@ struct metamac MetaMacros[] =
'\0'
};
-initmacros()
+initmacros(e)
+ register ENVELOPE *e;
{
register struct metamac *m;
char buf[5];
@@ -1177,208 +1231,34 @@ initmacros()
{
buf[0] = m->metaval;
buf[1] = '\0';
- define(m->metaname, newstr(buf), CurEnv);
+ define(m->metaname, newstr(buf), e);
}
buf[0] = MATCHREPL;
buf[2] = '\0';
for (c = '0'; c <= '9'; c++)
{
buf[1] = c;
- define(c, newstr(buf), CurEnv);
- }
-}
- /*
-** FREEZE -- freeze BSS & allocated memory
-**
-** This will be used to efficiently load the configuration file.
-**
-** Parameters:
-** freezefile -- the name of the file to freeze to.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Writes BSS and malloc'ed memory to freezefile
-*/
-
-# ifdef FROZENCONFIG
-
-union frz
-{
- char frzpad[BUFSIZ]; /* insure we are on a BUFSIZ boundary */
- struct
- {
- time_t frzstamp; /* timestamp on this freeze */
- char *frzbrk; /* the current break */
- char *frzedata; /* address of edata */
- char *frzend; /* address of end */
- char frzver[252]; /* sendmail version */
- } frzinfo;
-};
-
-#if defined(__hpux) || defined(__alpha)
-#define BRK_TYPE int
-#define SBRK_TYPE void *
-#else
-#define BRK_TYPE char *
-#define SBRK_TYPE char *
-#endif
-
-freeze(freezefile)
- char *freezefile;
-{
- int f;
- union frz fhdr;
- extern SBRK_TYPE sbrk();
- extern char edata, end;
- extern char Version[];
-
- if (freezefile == NULL)
- return;
-
- /* try to open the freeze file */
- f = creat(freezefile, FileMode);
- if (f < 0)
- {
- syserr("Cannot freeze %s", freezefile);
- errno = 0;
- return;
- }
-
- /* build the freeze header */
- fhdr.frzinfo.frzstamp = curtime();
- fhdr.frzinfo.frzbrk = sbrk(0);
- fhdr.frzinfo.frzedata = &edata;
- fhdr.frzinfo.frzend = &end;
- (void) strcpy(fhdr.frzinfo.frzver, Version);
-
- /* write out the freeze header */
- if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
- write(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
- (int) (fhdr.frzinfo.frzbrk - &edata))
- {
- syserr("Cannot freeze %s", freezefile);
+ define(c, newstr(buf), e);
}
- /* fine, clean up */
- (void) close(f);
+ /* set defaults for some macros sendmail will use later */
+ define('e', "\201j Sendmail \201v ready at \201b", e);
+ define('l', "From \201g \201d", e);
+ define('n', "MAILER-DAEMON", e);
+ define('o', ".:@[]", e);
+ define('q', "<\201g>", e);
}
/*
-** THAW -- read in the frozen configuration file.
-**
-** Parameters:
-** freezefile -- the name of the file to thaw from.
-** binfile -- the name of the sendmail binary (ok to guess).
-**
-** Returns:
-** TRUE if it successfully read the freeze file.
-** FALSE otherwise.
-**
-** Side Effects:
-** reads freezefile in to BSS area.
-*/
-
-thaw(freezefile, binfile)
- char *freezefile;
- char *binfile;
-{
- int f;
- register char *p;
- union frz fhdr;
- char hbuf[60];
- struct stat fst, sst;
- extern char edata, end;
- extern char Version[];
- extern char **myhostname();
- extern BRK_TYPE brk();
-
- if (freezefile == NULL)
- return (FALSE);
-
- /* open the freeze file */
- f = open(freezefile, 0);
- if (f < 0)
- {
- errno = 0;
- return (FALSE);
- }
-
- if (fstat(f, &fst) < 0 || stat(ConfFile, &sst) < 0 ||
- fst.st_mtime < sst.st_mtime)
- {
- syslog(LOG_WARNING, "Freeze file older than config file");
- (void) close(f);
- return (FALSE);
- }
-
- if (strchr(binfile, '/') != NULL && stat(binfile, &sst) == 0 &&
- fst.st_mtime < sst.st_mtime)
- {
- syslog(LOG_WARNING, "Freeze file older than binary file");
- (void) close(f);
- return (FALSE);
- }
-
- /* read in the header */
- if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr)
- {
- syslog(LOG_WARNING, "Cannot read frozen config file");
- (void) close(f);
- return (FALSE);
- }
- if (fhdr.frzinfo.frzedata != &edata ||
- fhdr.frzinfo.frzend != &end ||
- strcmp(fhdr.frzinfo.frzver, Version) != 0)
- {
- fprintf(stderr, "Wrong version of frozen config file\n");
- syslog(LOG_WARNING, "Wrong version of frozen config file");
- (void) close(f);
- return (FALSE);
- }
-
- /* arrange to have enough space */
- if (brk(fhdr.frzinfo.frzbrk) == (BRK_TYPE) -1)
- {
- syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
- (void) close(f);
- return (FALSE);
- }
-
- /* now read in the freeze file */
- if (read(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
- (int) (fhdr.frzinfo.frzbrk - &edata))
- {
- syserr("Cannot read frozen config file");
- /* oops! we have trashed memory..... */
- (void) write(2, "Cannot read freeze file\n", 24);
- _exit(EX_SOFTWARE);
- }
-
- (void) close(f);
-
- /* verify that the host name was correct on the freeze */
- (void) myhostname(hbuf, sizeof hbuf);
- p = macvalue('w', CurEnv);
- if (p == NULL)
- p = "";
- if (strcmp(hbuf, macvalue('w', CurEnv)) == 0)
- return (TRUE);
- syslog(LOG_WARNING, "Hostname changed since freeze (%s => %s)",
- p, hbuf);
- return (FALSE);
-}
-
-# endif /* FROZENCONFIG */
- /*
** DISCONNECT -- remove our connection with any foreground process
**
** Parameters:
-** fulldrop -- if set, we should also drop the controlling
-** TTY if possible -- this should only be done when
-** setting up the daemon since otherwise UUCP can
-** leave us trying to open a dialin, and we will
-** wait for the carrier.
+** droplev -- how "deeply" we should drop the line.
+** 0 -- ignore signals, mail back errors, make sure
+** output goes to stdout.
+** 1 -- also, make stdout go to transcript.
+** 2 -- also, disconnect from controlling terminal
+** (only for daemon mode).
+** e -- the current envelope.
**
** Returns:
** none
@@ -1388,8 +1268,8 @@ thaw(freezefile, binfile)
** the controlling tty.
*/
-disconnect(fulldrop, e)
- bool fulldrop;
+disconnect(droplev, e)
+ int droplev;
register ENVELOPE *e;
{
int fd;
@@ -1404,14 +1284,15 @@ disconnect(fulldrop, e)
}
/* be sure we don't get nasty signals */
- (void) signal(SIGHUP, SIG_IGN);
- (void) signal(SIGINT, SIG_IGN);
- (void) signal(SIGQUIT, SIG_IGN);
+ (void) setsignal(SIGHUP, SIG_IGN);
+ (void) setsignal(SIGINT, SIG_IGN);
+ (void) setsignal(SIGQUIT, SIG_IGN);
/* we can't communicate with our caller, so.... */
HoldErrs = TRUE;
CurEnv->e_errormode = EM_MAIL;
Verbose = FALSE;
+ DisConnected = TRUE;
/* all input from /dev/null */
if (InChannel != stdin)
@@ -1427,32 +1308,30 @@ disconnect(fulldrop, e)
(void) fclose(OutChannel);
OutChannel = stdout;
}
- if (e->e_xfp == NULL)
- fd = open("/dev/null", O_WRONLY, 0666);
- else
- fd = fileno(e->e_xfp);
- (void) fflush(stdout);
- dup2(fd, STDOUT_FILENO);
- dup2(fd, STDERR_FILENO);
- if (e->e_xfp == NULL)
- close(fd);
+ if (droplev > 0)
+ {
+ if (e->e_xfp == NULL)
+ fd = open("/dev/null", O_WRONLY, 0666);
+ else
+ fd = fileno(e->e_xfp);
+ (void) fflush(stdout);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (e->e_xfp == NULL)
+ close(fd);
+ }
/* drop our controlling TTY completely if possible */
- if (fulldrop)
+ if (droplev > 1)
{
(void) setsid();
-#ifdef TIOCNOTTY
- fd = open("/dev/tty", 2);
- if (fd >= 0)
- {
- (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
- (void) close(fd);
- }
- (void) setpgrp(0, 0);
-#endif /* TIOCNOTTY */
errno = 0;
}
+#ifdef XDEBUG
+ checkfd012("disconnect");
+#endif
+
# ifdef LOG
if (LogLevel > 71)
syslog(LOG_DEBUG, "in background, pid=%d", getpid());
@@ -1465,7 +1344,8 @@ static void
obsolete(argv)
char *argv[];
{
- char *ap;
+ register char *ap;
+ register char *op;
while ((ap = *++argv) != NULL)
{
@@ -1473,10 +1353,18 @@ obsolete(argv)
if (ap[0] != '-' || ap[1] == '-')
return;
+ /* skip over options that do have a value */
+ op = strchr(OPTIONS, ap[1]);
+ if (op != NULL && *++op == ':' && ap[2] == '\0' &&
+ ap[1] != 'd' && argv[1] != NULL && argv[1][0] != '-')
+ {
+ argv++;
+ continue;
+ }
+
/* If -C doesn't have an argument, use sendmail.cf. */
#define __DEFPATH "sendmail.cf"
- if (ap[1] == 'C' && ap[2] == '\0' &&
- (argv[1] == NULL || argv[1][0] == '-'))
+ if (ap[1] == 'C' && ap[2] == '\0')
{
*argv = xalloc(sizeof(__DEFPATH) + 2);
argv[0][0] = '-';
@@ -1485,13 +1373,11 @@ obsolete(argv)
}
/* If -q doesn't have an argument, run it once. */
- if (ap[1] == 'q' && ap[2] == '\0' &&
- (argv[1] == NULL || argv[1][0] == '-'))
+ if (ap[1] == 'q' && ap[2] == '\0')
*argv = "-q0";
/* if -d doesn't have an argument, use 0-99.1 */
- if (ap[1] == 'd' && ap[2] == '\0' &&
- (argv[1] == NULL || !isdigit(argv[1][0])))
+ if (ap[1] == 'd' && ap[2] == '\0')
*argv = "-d0-99.1";
}
}
@@ -1537,3 +1423,40 @@ auth_warning(e, msg, va_alist)
addheader("X-Authentication-Warning", buf, e);
}
}
+ /*
+** DUMPSTATE -- dump state on user signal
+**
+** For debugging.
+*/
+
+void
+dumpstate()
+{
+#ifdef LOG
+ register char *j = macvalue('j', CurEnv);
+ register STAB *s;
+
+ syslog(LOG_DEBUG, "--- dumping state on user signal: $j = %s ---", j);
+ s = stab(j, ST_CLASS, ST_FIND);
+ if (s == NULL || !bitnset('w', s->s_class))
+ syslog(LOG_DEBUG, "*** $j not in $=w ***");
+ syslog(LOG_DEBUG, "--- open file descriptors: ---");
+ printopenfds(TRUE);
+ syslog(LOG_DEBUG, "--- connection cache: ---");
+ mci_dump_all(TRUE);
+ if (RewriteRules[89] != NULL)
+ {
+ int stat;
+ register char **pvp;
+ char *pv[MAXATOM + 1];
+
+ pv[0] = NULL;
+ stat = rewrite(pv, 89, 0, CurEnv);
+ syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
+ stat);
+ for (pvp = pv; *pvp != NULL; pvp++)
+ syslog(LOG_DEBUG, "%s", *pvp);
+ }
+ syslog(LOG_DEBUG, "--- end of state dump ---");
+#endif
+}
diff --git a/usr.sbin/sendmail/src/makesendmail b/usr.sbin/sendmail/src/makesendmail
new file mode 100755
index 000000000000..7c13db9fd9fc
--- /dev/null
+++ b/usr.sbin/sendmail/src/makesendmail
@@ -0,0 +1,113 @@
+#!/bin/sh
+
+# Copyright (c) 1993 Eric P. Allman
+# Copyright (c) 1993 The Regents of the University of California.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)makesendmail 8.5 (Berkeley) 2/27/94
+#
+
+#
+# A quick-and-dirty script to compile sendmail in the presence of
+# multiple architectures and Makefiles.
+#
+
+# determine machine architecture
+arch=`uname -m`
+case $arch
+in
+ sun4*) arch=sun4;;
+
+ 9000/*) arch=`echo $arch | sed -e 's/9000.//' -e 's/..$/xx/'`;;
+esac
+
+# determine operating system type
+os=`uname -s`
+
+# determine operating system release
+rel=`uname -r`
+rbase=`echo $rel | sed 's/\..*//''`
+
+# now try to find a reasonable object directory
+if [ -r obj.$os.$arch.$rel ]; then
+ obj=obj.$os.$arch.$rel
+elif [ -r obj.$os.$arch.$rbase.x ]; then
+ obj=obj.$os.$arch.$rbase.x
+elif [ -r obj.$os.$rel ]; then
+ obj=obj.$os.$rel
+elif [ -r obj.$os.$rbase.x ]; then
+ obj=obj.$os.$rbase.x
+elif [ -r obj.$os.$arch ]; then
+ obj=obj.$os.$arch
+elif [ -r obj.$arch.$rel ]; then
+ obj=obj.$arch.$rel
+elif [ -r obj.$arch.$rbase.x ]; then
+ obj=obj.$arch.$rbase.x
+elif [ -r obj.$os ]; then
+ obj=obj.$os
+elif [ -r obj.$arch ]; then
+ obj=obj.$arch
+elif [ -r obj.$rel ]; then
+ obj=obj.$rel
+else
+ # no existing obj directory -- try to create one if Makefile found
+ obj=obj.$os.$arch.$rel
+ if [ -r Makefile.$os.$arch.$rel ]; then
+ makefile=Makefile.$os.$arch.$rel
+ elif [ -r Makefile.$os.$arch.$rbase.x ]; then
+ makefile=Makefile.$os.$arch.$rbase.x
+ elif [ -r Makefile.$os.$rel ]; then
+ makefile=Makefile.$os.$rel
+ elif [ -r Makefile.$os.$rbase.x ]; then
+ makefile=Makefile.$os.$rbase.x
+ elif [ -r Makefile.$os.$arch ]; then
+ makefile=Makefile.$os.$arch
+ elif [ -r Makefile.$arch.$rel ]; then
+ makefile=Makefile.$arch.$rel
+ elif [ -r Makefile.$arch.$rbase.x ]; then
+ makefile=Makefile.$arch.$rbase.x
+ elif [ -r Makefile.$os ]; then
+ makefile=Makefile.$os
+ elif [ -r Makefile.$arch ]; then
+ makefile=Makefile.$arch
+ elif [ -r Makefile.$rel ]; then
+ makefile=Makefile.$rel
+ else
+ echo "Cannot determine how to support $arch.$os.$rel"
+ exit 1
+ fi
+ echo "Creating $obj using $makefile"
+ mkdir $obj
+ (cd $obj; ln -s ../*.[ch158] ../sendmail.hf .; ln -s ../$makefile Makefile)
+fi
+echo "Making in $obj"
+cd $obj
+exec make -f Makefile $*
diff --git a/usr.sbin/sendmail/src/map.c b/usr.sbin/sendmail/src/map.c
index bfa2dc03c264..7444cdab7378 100644
--- a/usr.sbin/sendmail/src/map.c
+++ b/usr.sbin/sendmail/src/map.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)map.c 8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)map.c 8.22 (Berkeley) 2/18/94";
#endif /* not lint */
#include "sendmail.h"
@@ -85,6 +85,8 @@ static char sccsid[] = "@(#)map.c 8.2 (Berkeley) 7/11/93";
*/
#define DBMMODE 0644
+
+extern bool aliaswait __P((MAP *, char *, int));
/*
** MAP_PARSEARGS -- parse config line arguments for database lookup
**
@@ -247,8 +249,7 @@ map_rewrite(map, s, slen, av)
c = *bp++;
if (!(isascii(c) && isdigit(c)))
continue;
- c -= 0;
- for (avp = av; --c >= 0 && *avp != NULL; avp++)
+ for (avp = av; --c >= '0' && *avp != NULL; avp++)
continue;
if (*avp == NULL)
continue;
@@ -291,8 +292,7 @@ map_rewrite(map, s, slen, av)
*bp++ = '%';
goto pushc;
}
- c -= '0';
- for (avp = av; --c >= 0 && *avp != NULL; avp++)
+ for (avp = av; --c >= '0' && *avp != NULL; avp++)
continue;
if (*avp == NULL)
continue;
@@ -332,8 +332,22 @@ initmaps(rebuild, e)
{
extern void map_init();
+#ifdef XDEBUG
+ checkfd012("entering initmaps");
+#endif
CurEnv = e;
- stabapply(map_init, rebuild);
+ if (rebuild)
+ {
+ stabapply(map_init, 1);
+ stabapply(map_init, 2);
+ }
+ else
+ {
+ stabapply(map_init, 0);
+ }
+#ifdef XDEBUG
+ checkfd012("exiting initmaps");
+#endif
}
void
@@ -352,8 +366,19 @@ map_init(s, rebuild)
return;
if (tTd(38, 2))
- printf("map_init(%s:%s)\n",
- map->map_class->map_cname, map->map_file);
+ printf("map_init(%s:%s, %d)\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_file == NULL ? "NULL" : map->map_file,
+ rebuild);
+
+ if (rebuild == (bitset(MF_ALIAS, map->map_mflags) &&
+ bitset(MCF_REBUILDABLE, map->map_class->map_cflags) ? 1 : 2))
+ {
+ if (tTd(38, 3))
+ printf("\twrong pass\n");
+ return;
+ }
/* if already open, close it (for nested open) */
if (bitset(MF_OPEN, map->map_mflags))
@@ -362,26 +387,28 @@ map_init(s, rebuild)
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE);
}
- if (rebuild)
+ if (rebuild == 2)
{
- if (bitset(MF_ALIAS, map->map_mflags) &&
- bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
- rebuildaliases(map, FALSE);
+ rebuildaliases(map, FALSE);
}
else
{
if (map->map_class->map_open(map, O_RDONLY))
{
if (tTd(38, 4))
- printf("%s:%s: valid\n",
- map->map_class->map_cname,
- map->map_file);
+ printf("\t%s:%s: valid\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_file == NULL ? "NULL" :
+ map->map_file);
map->map_mflags |= MF_OPEN;
}
else if (tTd(38, 4))
- printf("%s:%s: invalid: %s\n",
- map->map_class->map_cname,
- map->map_file,
+ printf("\t%s:%s: invalid: %s\n",
+ map->map_class->map_cname == NULL ? "NULL" :
+ map->map_class->map_cname,
+ map->map_file == NULL ? "NULL" :
+ map->map_file,
errstring(errno));
}
}
@@ -400,7 +427,8 @@ ndbm_map_open(map, mode)
MAP *map;
int mode;
{
- DBM *dbm;
+ register DBM *dbm;
+ struct stat st;
if (tTd(38, 2))
printf("ndbm_map_open(%s, %d)\n", map->map_file, mode);
@@ -412,13 +440,33 @@ ndbm_map_open(map, mode)
dbm = dbm_open(map->map_file, mode, DBMMODE);
if (dbm == NULL)
{
+#ifdef MAYBENEXTRELEASE
+ if (aliaswait(map, ".pag", FALSE))
+ return TRUE;
+#endif
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open DBM database %s", map->map_file);
return FALSE;
}
map->map_db1 = (void *) dbm;
- if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
- aliaswait(map, ".pag");
+ if (mode == O_RDONLY)
+ {
+ if (bitset(MF_ALIAS, map->map_mflags) &&
+ !aliaswait(map, ".pag", TRUE))
+ return FALSE;
+ }
+ else
+ {
+ int fd;
+
+ /* exclusive lock for duration of rebuild */
+ fd = dbm_dirfno((DBM *) map->map_db1);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags) &&
+ lockfile(fd, map->map_file, ".dir", LOCK_EX))
+ map->map_mflags |= MF_LOCKED;
+ }
+ if (fstat(dbm_dirfno((DBM *) map->map_db1), &st) >= 0)
+ map->map_mtime = st.st_mtime;
return TRUE;
}
@@ -435,6 +483,7 @@ ndbm_map_lookup(map, name, av, statp)
int *statp;
{
datum key, val;
+ int fd;
char keybuf[MAXNAME + 1];
if (tTd(38, 20))
@@ -450,7 +499,9 @@ ndbm_map_lookup(map, name, av, statp)
makelower(keybuf);
key.dptr = keybuf;
}
- (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_SH);
+ fd = dbm_dirfno((DBM *) map->map_db1);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".dir", LOCK_SH);
val.dptr = NULL;
if (bitset(MF_TRY0NULL, map->map_mflags))
{
@@ -465,7 +516,8 @@ ndbm_map_lookup(map, name, av, statp)
if (val.dptr != NULL)
map->map_mflags &= ~MF_TRY0NULL;
}
- (void) lockfile(dbm_dirfno((DBM *) map->map_db1), map->map_file, LOCK_UN);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".dir", LOCK_UN);
if (val.dptr == NULL)
return NULL;
if (bitset(MF_MATCHONLY, map->map_mflags))
@@ -525,14 +577,21 @@ ndbm_map_close(map)
{
if (bitset(MF_WRITABLE, map->map_mflags))
{
-#ifdef YPCOMPAT
+#ifdef NIS
+ bool inclnull;
char buf[200];
+ inclnull = bitset(MF_INCLNULL, map->map_mflags);
+ map->map_mflags &= ~MF_INCLNULL;
+
(void) sprintf(buf, "%010ld", curtime());
ndbm_map_store(map, "YP_LAST_MODIFIED", buf);
- (void) myhostname(buf, sizeof buf);
+ (void) gethostname(buf, sizeof buf);
ndbm_map_store(map, "YP_MASTER_NAME", buf);
+
+ if (inclnull)
+ map->map_mflags |= MF_INCLNULL;
#endif
/* write out the distinguished alias */
@@ -568,6 +627,8 @@ bt_map_open(map, mode)
DB *db;
int i;
int omode;
+ int fd;
+ struct stat st;
char buf[MAXNAME];
if (tTd(38, 2))
@@ -577,7 +638,7 @@ bt_map_open(map, mode)
if (omode == O_RDWR)
{
omode |= O_CREAT|O_TRUNC;
-#if defined(O_EXLOCK) && !defined(LOCKF)
+#if defined(O_EXLOCK) && HASFLOCK
omode |= O_EXLOCK;
# if !defined(OLD_NEWDB)
}
@@ -595,27 +656,45 @@ bt_map_open(map, mode)
db = dbopen(buf, omode, DBMMODE, DB_BTREE, NULL);
if (db == NULL)
{
+#ifdef MAYBENEXTRELEASE
+ if (aliaswait(map, ".db", FALSE))
+ return TRUE;
+#endif
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open BTREE database %s", map->map_file);
return FALSE;
}
-#if !defined(OLD_NEWDB) && !defined(LOCKF)
+#if !defined(OLD_NEWDB) && HASFLOCK
+ fd = db->fd(db);
# if !defined(O_EXLOCK)
- if (mode == O_RDWR)
- (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+ if (mode == O_RDWR && fd >= 0)
+ {
+ if (lockfile(fd, map->map_file, ".db", LOCK_EX))
+ map->map_mflags |= MF_LOCKED;
+ }
# else
- if (mode == O_RDONLY)
- (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+ if (mode == O_RDONLY && fd >= 0)
+ (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
+ else
+ map->map_mflags |= MF_LOCKED;
# endif
#endif
/* try to make sure that at least the database header is on disk */
if (mode == O_RDWR)
+#ifdef OLD_NEWDB
+ (void) db->sync(db);
+#else
(void) db->sync(db, 0);
+ if (fd >= 0 && fstat(fd, &st) >= 0)
+ map->map_mtime = st.st_mtime;
+#endif
+
map->map_db2 = (void *) db;
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
- aliaswait(map, ".db");
+ if (!aliaswait(map, ".db", TRUE))
+ return FALSE;
return TRUE;
}
@@ -632,6 +711,8 @@ hash_map_open(map, mode)
DB *db;
int i;
int omode;
+ int fd;
+ struct stat st;
char buf[MAXNAME];
if (tTd(38, 2))
@@ -641,7 +722,7 @@ hash_map_open(map, mode)
if (omode == O_RDWR)
{
omode |= O_CREAT|O_TRUNC;
-#if defined(O_EXLOCK) && !defined(LOCKF)
+#if defined(O_EXLOCK) && HASFLOCK
omode |= O_EXLOCK;
# if !defined(OLD_NEWDB)
}
@@ -659,27 +740,45 @@ hash_map_open(map, mode)
db = dbopen(buf, omode, DBMMODE, DB_HASH, NULL);
if (db == NULL)
{
+#ifdef MAYBENEXTRELEASE
+ if (aliaswait(map, ".db", FALSE))
+ return TRUE;
+#endif
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("Cannot open HASH database %s", map->map_file);
return FALSE;
}
-#if !defined(OLD_NEWDB) && !defined(LOCKF)
+#if !defined(OLD_NEWDB) && HASFLOCK
+ fd = db->fd(db);
# if !defined(O_EXLOCK)
- if (mode == O_RDWR)
- (void) lockfile(db->fd(db), map->map_file, LOCK_EX);
+ if (mode == O_RDWR && fd >= 0)
+ {
+ if (lockfile(fd, map->map_file, ".db", LOCK_EX))
+ map->map_mflags |= MF_LOCKED;
+ }
# else
- if (mode == O_RDONLY)
- (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+ if (mode == O_RDONLY && fd >= 0)
+ (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
+ else
+ map->map_mflags |= MF_LOCKED;
# endif
#endif
/* try to make sure that at least the database header is on disk */
if (mode == O_RDWR)
+#ifdef OLD_NEWDB
+ (void) db->sync(db);
+#else
(void) db->sync(db, 0);
+ if (fd >= 0 && fstat(fd, &st) >= 0)
+ map->map_mtime = st.st_mtime;
+#endif
+
map->map_db2 = (void *) db;
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags))
- aliaswait(map, ".db");
+ if (!aliaswait(map, ".db", TRUE))
+ return FALSE;
return TRUE;
}
@@ -699,6 +798,7 @@ db_map_lookup(map, name, av, statp)
register DB *db = (DB *) map->map_db2;
int st;
int saveerrno;
+ int fd;
char keybuf[MAXNAME + 1];
if (tTd(38, 20))
@@ -712,7 +812,9 @@ db_map_lookup(map, name, av, statp)
if (!bitset(MF_NOFOLDCASE, map->map_mflags))
makelower(keybuf);
#ifndef OLD_NEWDB
- (void) lockfile(db->fd(db), map->map_file, LOCK_SH);
+ fd = db->fd(db);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(db->fd(db), map->map_file, ".db", LOCK_SH);
#endif
st = 1;
if (bitset(MF_TRY0NULL, map->map_mflags))
@@ -730,7 +832,8 @@ db_map_lookup(map, name, av, statp)
}
saveerrno = errno;
#ifndef OLD_NEWDB
- (void) lockfile(db->fd(db), map->map_file, LOCK_UN);
+ if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
+ (void) lockfile(fd, map->map_file, ".db", LOCK_UN);
#endif
if (st != 0)
{
@@ -817,6 +920,10 @@ db_map_close(map)
# ifdef NIS
+# ifndef YPERR_BUSY
+# define YPERR_BUSY 16
+# endif
+
/*
** NIS_MAP_OPEN -- open DBM map
*/
@@ -837,7 +944,16 @@ nis_map_open(map, mode)
if (mode != O_RDONLY)
{
- errno = ENODEV;
+ /* issue a pseudo-error message */
+#ifdef ENOSYS
+ errno = ENOSYS;
+#else
+# ifdef EFTYPE
+ errno = EFTYPE;
+# else
+ errno = ENXIO;
+# endif
+#endif
return FALSE;
}
@@ -849,12 +965,20 @@ nis_map_open(map, mode)
map->map_domain = p;
}
- if (map->map_domain == NULL)
- yp_get_default_domain(&map->map_domain);
-
if (*map->map_file == '\0')
map->map_file = "mail.aliases";
+ if (map->map_domain == NULL)
+ {
+ yperr = yp_get_default_domain(&map->map_domain);
+ if (yperr != 0)
+ {
+ syserr("NIS map %s specified, but NIS not running\n",
+ map->map_file);
+ return FALSE;
+ }
+ }
+
/* check to see if this map actually exists */
yperr = yp_match(map->map_domain, map->map_file, "@", 1,
&vp, &vsize);
@@ -1012,6 +1136,9 @@ stab_map_open(map, mode)
register MAP *map;
int mode;
{
+ FILE *af;
+ struct stat st;
+
if (tTd(38, 2))
printf("stab_map_open(%s)\n", map->map_file);
@@ -1021,12 +1148,23 @@ stab_map_open(map, mode)
return FALSE;
}
+ af = fopen(map->map_file, "r");
+ if (af == NULL)
+ return FALSE;
+ readaliases(map, af, TRUE);
+
+ if (fstat(fileno(af), &st) >= 0)
+ map->map_mtime = st.st_mtime;
+ fclose(af);
+
return TRUE;
}
/*
-** STAB_MAP_CLOSE -- close symbol table (???)
+** STAB_MAP_CLOSE -- close symbol table.
+**
+** Since this is in memory, there is nothing to do.
*/
void
@@ -1100,11 +1238,13 @@ impl_map_open(map, mode)
struct stat stb;
if (tTd(38, 2))
- printf("impl_map_open(%s)\n", map->map_file);
+ printf("impl_map_open(%s, %d)\n", map->map_file, mode);
if (stat(map->map_file, &stb) < 0)
{
/* no alias file at all */
+ if (tTd(38, 3))
+ printf("no map file\n");
return FALSE;
}
@@ -1112,7 +1252,7 @@ impl_map_open(map, mode)
map->map_mflags |= MF_IMPL_HASH;
if (hash_map_open(map, mode))
{
-#if defined(NDBM) && defined(YPCOMPAT)
+#if defined(NDBM) && defined(NIS)
if (mode == O_RDONLY || access("/var/yp/Makefile", R_OK) != 0)
#endif
return TRUE;
@@ -1130,9 +1270,12 @@ impl_map_open(map, mode)
map->map_mflags &= ~MF_IMPL_NDBM;
#endif
-#if !defined(NEWDB) && !defined(NDBM)
+#if defined(NEWDB) || defined(NDBM)
if (Verbose)
message("WARNING: cannot open alias database %s", map->map_file);
+#else
+ if (mode != O_RDONLY)
+ usrerr("Cannot rebuild aliases: no database format defined");
#endif
return stab_map_open(map, mode);
diff --git a/usr.sbin/sendmail/src/mci.c b/usr.sbin/sendmail/src/mci.c
index 0d55a665a623..978b8c3cdbc0 100644
--- a/usr.sbin/sendmail/src/mci.c
+++ b/usr.sbin/sendmail/src/mci.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)mci.c 8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)mci.c 8.12 (Berkeley) 2/9/94";
#endif /* not lint */
#include "sendmail.h"
@@ -104,6 +104,16 @@ mci_cache(mci)
if (*mcislot != NULL)
mci_uncache(mcislot, TRUE);
+ if (tTd(42, 5))
+ printf("mci_cache: caching %x (%s) in slot %d\n",
+ mci, mci->mci_host, mcislot - MciCache);
+#ifdef LOG
+ if (tTd(91, 100))
+ syslog(LOG_DEBUG, "%s: mci_cache: caching %x (%s) in slot %d",
+ CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ mci, mci->mci_host, mcislot - MciCache);
+#endif
+
*mcislot = mci;
mci->mci_flags |= MCIF_CACHED;
}
@@ -185,6 +195,16 @@ mci_uncache(mcislot, doquit)
return;
*mcislot = NULL;
+ if (tTd(42, 5))
+ printf("mci_uncache: uncaching %x (%s) from slot %d (%d)\n",
+ mci, mci->mci_host, mcislot - MciCache, doquit);
+#ifdef LOG
+ if (tTd(91, 100))
+ syslog(LOG_DEBUG, "%s: mci_uncache: uncaching %x (%s) from slot %d (%d)",
+ CurEnv->e_id ? CurEnv->e_id : "NOQUEUE",
+ mci, mci->mci_host, mcislot - MciCache, doquit);
+#endif
+
if (doquit)
{
message("Closing connection to %s", mci->mci_host);
@@ -253,8 +273,13 @@ mci_get(host, m)
/* clear CurHostAddr so we don't get a bogus address with this name */
bzero(&CurHostAddr, sizeof CurHostAddr);
-#endif DAEMON
+#endif
+
+ /* clear out any expired connections */
+ mci_scan(NULL);
+ if (m->m_mno < 0)
+ syserr("negative mno %d (%s)", m->m_mno, m->m_name);
s = stab(host, ST_MCI + m->m_mno, ST_ENTER);
mci = &s->s_mci;
mci->mci_host = s->s_name;
@@ -278,6 +303,21 @@ mci_get(host, m)
mci->mci_exitstat = EX_OK;
mci->mci_state = MCIS_CLOSED;
}
+ else
+ {
+ /* get peer host address for logging reasons only */
+ /* (this should really be in the mci struct) */
+ int socksize = sizeof CurHostAddr;
+
+ (void) getpeername(fileno(mci->mci_in),
+ (struct sockaddr *) &CurHostAddr, &socksize);
+ }
+ }
+ if (mci->mci_state == MCIS_CLOSED)
+ {
+ /* copy out any mailer flags needed in connection state */
+ if (bitnset(M_7BITS, m->m_flags))
+ mci->mci_flags |= MCIF_7BIT;
}
return mci;
@@ -295,25 +335,62 @@ mci_get(host, m)
** none.
*/
-mci_dump(mci)
+mci_dump(mci, logit)
register MCI *mci;
+ bool logit;
{
+ register char *p;
+ char *sep;
+ char buf[1000];
extern char *ctime();
- printf("MCI@%x: ", mci);
+ sep = logit ? " " : "\n\t";
+ p = buf;
+ sprintf(p, "MCI@%x: ", mci);
+ p += strlen(p);
if (mci == NULL)
{
- printf("NULL\n");
- return;
+ sprintf(p, "NULL");
+ goto printit;
}
- printf("flags=%o, errno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,\n",
+ sprintf(p, "flags=%o, errno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
mci->mci_flags, mci->mci_errno, mci->mci_herrno,
- mci->mci_exitstat, mci->mci_state, mci->mci_pid);
- printf("\tmaxsize=%ld, phase=%s, mailer=%s,\n",
+ mci->mci_exitstat, mci->mci_state, mci->mci_pid, sep);
+ p += strlen(p);
+ sprintf(p, "maxsize=%ld, phase=%s, mailer=%s,%s",
mci->mci_maxsize,
mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
- mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name);
- printf("\thost=%s, lastuse=%s\n",
+ mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name,
+ sep);
+ p += strlen(p);
+ sprintf(p, "host=%s, lastuse=%s",
mci->mci_host == NULL ? "NULL" : mci->mci_host,
ctime(&mci->mci_lastuse));
+printit:
+ if (logit)
+ syslog(LOG_DEBUG, "%s", buf);
+ else
+ printf("%s\n", buf);
+}
+ /*
+** MCI_DUMP_ALL -- print the entire MCI cache
+**
+** Parameters:
+** logit -- if set, log the result instead of printing
+** to stdout.
+**
+** Returns:
+** none.
+*/
+
+mci_dump_all(logit)
+ bool logit;
+{
+ register int i;
+
+ if (MciCache == NULL)
+ return;
+
+ for (i = 0; i < MaxMciCache; i++)
+ mci_dump(MciCache[i], logit);
}
diff --git a/usr.sbin/sendmail/src/newaliases.1 b/usr.sbin/sendmail/src/newaliases.1
index 65cfc5f38e3c..c611b78b62b5 100644
--- a/usr.sbin/sendmail/src/newaliases.1
+++ b/usr.sbin/sendmail/src/newaliases.1
@@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)newaliases.1 8.1 (Berkeley) 6/7/93
+.\" @(#)newaliases.1 8.4 (Berkeley) 2/22/94
.\"
-.Dd June 7, 1993
+.Dd February 22, 1994
.Dt NEWALIASES 1
.Os BSD 4
.Sh NAME
@@ -43,12 +43,23 @@
.Nm Newaliases
rebuilds the random access data base for the mail aliases file
.Pa /etc/aliases .
-It must be run each time
-.Pa /etc/aliases
-is changed in order
+It must be run each time this file is changed in order
for the change to take effect.
+.Pp
+.Nm Newaliases
+is identical to
+.Dq Li "sendmail -bi" .
+.Pp
+The
+.Nm newaliases
+utility exits 0 on success, and >0 if an error occurs.
+.Sh FILES
+.Bl -tag -width /etc/aliases -compact
+.It Pa /etc/aliases
+The mail aliases file
+.El
.Sh SEE ALSO
-.\" .Xr aliases 5 ,
+.Xr aliases 5 ,
.Xr sendmail 8
.Sh HISTORY
The
diff --git a/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c
index 8951cac01cff..800a1372cdcd 100644
--- a/usr.sbin/sendmail/src/parseaddr.c
+++ b/usr.sbin/sendmail/src/parseaddr.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)parseaddr.c 8.3 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)parseaddr.c 8.30 (Berkeley) 2/9/94";
#endif /* not lint */
# include "sendmail.h"
@@ -56,14 +56,8 @@ static char sccsid[] = "@(#)parseaddr.c 8.3 (Berkeley) 7/11/93";
** addr -- the address to parse.
** a -- a pointer to the address descriptor buffer.
** If NULL, a header will be created.
-** copyf -- determines what shall be copied:
-** -1 -- don't copy anything. The printname
-** (q_paddr) is just addr, and the
-** user & host are allocated internally
-** to parse.
-** 0 -- copy out the parsed user & host, but
-** don't copy the printname.
-** +1 -- copy everything.
+** flags -- describe detail for parsing. See RF_ definitions
+** in sendmail.h.
** delim -- the character to terminate the address, passed
** to prescan.
** delimptr -- if non-NULL, set to the location of the
@@ -83,10 +77,10 @@ static char sccsid[] = "@(#)parseaddr.c 8.3 (Berkeley) 7/11/93";
# define DELIMCHARS "()<>,;\r\n" /* default word delimiters */
ADDRESS *
-parseaddr(addr, a, copyf, delim, delimptr, e)
+parseaddr(addr, a, flags, delim, delimptr, e)
char *addr;
register ADDRESS *a;
- int copyf;
+ int flags;
int delim;
char **delimptr;
register ENVELOPE *e;
@@ -106,17 +100,10 @@ parseaddr(addr, a, copyf, delim, delimptr, e)
if (tTd(20, 1))
printf("\n--parseaddr(%s)\n", addr);
- if (invalidaddr(addr))
- {
- if (tTd(20, 1))
- printf("parseaddr-->bad address\n");
- return NULL;
- }
-
if (delimptr == NULL)
delimptr = &delimptrbuf;
- pvp = prescan(addr, delim, pvpbuf, delimptr);
+ pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr);
if (pvp == NULL)
{
if (tTd(20, 1))
@@ -124,42 +111,58 @@ parseaddr(addr, a, copyf, delim, delimptr, e)
return (NULL);
}
+ if (invalidaddr(addr, delim == '\0' ? NULL : *delimptr))
+ {
+ if (tTd(20, 1))
+ printf("parseaddr-->bad address\n");
+ return NULL;
+ }
+
+ /*
+ ** Save addr if we are going to have to.
+ **
+ ** We have to do this early because there is a chance that
+ ** the map lookups in the rewriting rules could clobber
+ ** static memory somewhere.
+ */
+
+ if (bitset(RF_COPYPADDR, flags) && addr != NULL)
+ {
+ char savec = **delimptr;
+
+ if (savec != '\0')
+ **delimptr = '\0';
+ addr = newstr(addr);
+ if (savec != '\0')
+ **delimptr = savec;
+ }
+
/*
** Apply rewriting rules.
** Ruleset 0 does basic parsing. It must resolve.
*/
queueup = FALSE;
- if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
queueup = TRUE;
- if (rewrite(pvp, 0, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 0, 0, e) == EX_TEMPFAIL)
queueup = TRUE;
- /*
- ** See if we resolved to a real mailer.
- */
-
- if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
- {
- setstat(EX_USAGE);
- syserr("554 cannot resolve name %s", addr);
- return (NULL);
- }
/*
** Build canonical address from pvp.
*/
- a = buildaddr(pvp, a, e);
- if (a == NULL)
- return (NULL);
+ a = buildaddr(pvp, a, flags, e);
/*
** Make local copies of the host & user and then
** transport them out.
*/
- allocaddr(a, copyf, addr, *delimptr);
+ allocaddr(a, flags, addr);
+ if (bitset(QBADADDR, a->q_flags))
+ return a;
/*
** If there was a parsing failure, mark it for queueing.
@@ -201,18 +204,43 @@ parseaddr(addr, a, copyf, delim, delimptr, e)
*/
bool
-invalidaddr(addr)
+invalidaddr(addr, delimptr)
register char *addr;
+ char *delimptr;
{
+ char savedelim;
+
+ if (delimptr != NULL)
+ {
+ savedelim = *delimptr;
+ if (savedelim != '\0')
+ *delimptr = '\0';
+ }
+#if 0
+ /* for testing.... */
+ if (strcmp(addr, "INvalidADDR") == 0)
+ {
+ usrerr("553 INvalid ADDRess");
+ goto addrfailure;
+ }
+#endif
for (; *addr != '\0'; addr++)
{
- if ((*addr & 0340) != 0200)
- continue;
- setstat(EX_USAGE);
- usrerr("553 Address contained invalid control characters");
- return TRUE;
+ if ((*addr & 0340) == 0200)
+ break;
}
- return FALSE;
+ if (*addr == '\0')
+ {
+ if (savedelim != '\0' && delimptr != NULL)
+ *delimptr = savedelim;
+ return FALSE;
+ }
+ setstat(EX_USAGE);
+ usrerr("553 Address contained invalid control characters");
+ addrfailure:
+ if (savedelim != '\0' && delimptr != NULL)
+ *delimptr = savedelim;
+ return TRUE;
}
/*
** ALLOCADDR -- do local allocations of address on demand.
@@ -221,9 +249,9 @@ invalidaddr(addr)
**
** Parameters:
** a -- the address to reallocate.
-** copyf -- the copy flag (see parseaddr for description).
+** flags -- the copy flag (see RF_ definitions in sendmail.h
+** for a description).
** paddr -- the printname of the address.
-** delimptr -- a pointer to the address delimiter. Must be set.
**
** Returns:
** none.
@@ -232,34 +260,22 @@ invalidaddr(addr)
** Copies portions of a into local buffers as requested.
*/
-allocaddr(a, copyf, paddr, delimptr)
+allocaddr(a, flags, paddr)
register ADDRESS *a;
- int copyf;
+ int flags;
char *paddr;
- char *delimptr;
{
if (tTd(24, 4))
- printf("allocaddr(copyf=%d, paddr=%s)\n", copyf, paddr);
+ printf("allocaddr(flags=%o, paddr=%s)\n", flags, paddr);
- if (copyf > 0 && paddr != NULL)
- {
- char savec = *delimptr;
-
- if (savec != '\0')
- *delimptr = '\0';
- a->q_paddr = newstr(paddr);
- if (savec != '\0')
- *delimptr = savec;
- }
- else
- a->q_paddr = paddr;
+ a->q_paddr = paddr;
if (a->q_user == NULL)
a->q_user = "";
if (a->q_host == NULL)
a->q_host = "";
- if (copyf >= 0)
+ if (bitset(RF_COPYPARSE, flags))
{
a->q_host = newstr(a->q_host);
if (a->q_user != a->q_paddr)
@@ -292,6 +308,7 @@ allocaddr(a, copyf, paddr, delimptr)
** If '\t' then we are reading the .cf file.
** pvpbuf -- place to put the saved text -- note that
** the pointers are static.
+** pvpbsize -- size of pvpbuf.
** delimptr -- if non-NULL, set to the location of the
** terminating delimiter.
**
@@ -325,10 +342,34 @@ static short StateTab[NSTATES][NSTATES] =
/*ONE*/ OPR, OPR, OPR, OPR, OPR,
};
+/* token type table -- it gets modified with $o characters */
+static TokTypeTab[256] =
+{
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM,ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+ ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,
+};
+
+#define toktype(c) ((int) TokTypeTab[(c) & 0xff])
+
+
# define NOCHAR -1 /* signal nothing in lookahead token */
char **
-prescan(addr, delim, pvpbuf, delimptr)
+prescan(addr, delim, pvpbuf, pvpbsize, delimptr)
char *addr;
char delim;
char pvpbuf[];
@@ -346,8 +387,24 @@ prescan(addr, delim, pvpbuf, delimptr)
int newstate;
char *saveto = CurEnv->e_to;
static char *av[MAXATOM+1];
+ static char firsttime = TRUE;
extern int errno;
+ if (firsttime)
+ {
+ /* initialize the token type table */
+ char obuf[50];
+
+ firsttime = FALSE;
+ expand("\201o", obuf, &obuf[sizeof obuf - sizeof DELIMCHARS], CurEnv);
+ strcat(obuf, DELIMCHARS);
+ for (p = obuf; *p != '\0'; p++)
+ {
+ if (TokTypeTab[*p & 0xff] == ATM)
+ TokTypeTab[*p & 0xff] = OPR;
+ }
+ }
+
/* make sure error messages don't have garbage on them */
errno = 0;
@@ -377,9 +434,10 @@ prescan(addr, delim, pvpbuf, delimptr)
if (c != NOCHAR && !bslashmode)
{
/* see if there is room */
- if (q >= &pvpbuf[PSBUFSIZE - 5])
+ if (q >= &pvpbuf[pvpbsize - 5])
{
usrerr("553 Address too long");
+ returnnull:
if (delimptr != NULL)
*delimptr = p;
CurEnv->e_to = saveto;
@@ -397,18 +455,18 @@ prescan(addr, delim, pvpbuf, delimptr)
/* diagnose and patch up bad syntax */
if (state == QST)
{
- usrerr("553 Unbalanced '\"'");
+ usrerr("653 Unbalanced '\"'");
c = '"';
}
else if (cmntcnt > 0)
{
- usrerr("553 Unbalanced '('");
+ usrerr("653 Unbalanced '('");
c = ')';
}
else if (anglecnt > 0)
{
c = '>';
- usrerr("553 Unbalanced '<'");
+ usrerr("653 Unbalanced '<'");
}
else
break;
@@ -458,11 +516,8 @@ prescan(addr, delim, pvpbuf, delimptr)
{
if (cmntcnt <= 0)
{
- usrerr("553 Unbalanced ')'");
- if (delimptr != NULL)
- *delimptr = p;
- CurEnv->e_to = saveto;
- return (NULL);
+ usrerr("653 Unbalanced ')'");
+ c = NOCHAR;
}
else
cmntcnt--;
@@ -475,13 +530,11 @@ prescan(addr, delim, pvpbuf, delimptr)
{
if (anglecnt <= 0)
{
- usrerr("553 Unbalanced '>'");
- if (delimptr != NULL)
- *delimptr = p;
- CurEnv->e_to = saveto;
- return (NULL);
+ usrerr("653 Unbalanced '>'");
+ c = NOCHAR;
}
- anglecnt--;
+ else
+ anglecnt--;
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
@@ -516,10 +569,12 @@ prescan(addr, delim, pvpbuf, delimptr)
if (avp >= &av[MAXATOM])
{
syserr("553 prescan: too many tokens");
- if (delimptr != NULL)
- *delimptr = p;
- CurEnv->e_to = saveto;
- return (NULL);
+ goto returnnull;
+ }
+ if (q - tok > MAXNAME)
+ {
+ syserr("553 prescan: token too long");
+ goto returnnull;
}
*avp++ = tok;
}
@@ -535,50 +590,12 @@ prescan(addr, delim, pvpbuf, delimptr)
}
CurEnv->e_to = saveto;
if (av[0] == NULL)
- return (NULL);
- return (av);
-}
- /*
-** TOKTYPE -- return token type
-**
-** Parameters:
-** c -- the character in question.
-**
-** Returns:
-** Its type.
-**
-** Side Effects:
-** none.
-*/
-
-toktype(c)
- register int c;
-{
- static char buf[50];
- static bool firstime = TRUE;
-
- if (firstime)
{
- firstime = FALSE;
- expand("\201o", buf, &buf[sizeof buf - 1], CurEnv);
- (void) strcat(buf, DELIMCHARS);
+ if (tTd(22, 1))
+ printf("prescan: null leading token\n");
+ return (NULL);
}
- c &= 0377;
- if (c == MATCHCLASS || c == MATCHREPL || c == MATCHNCLASS)
- return (ONE);
- if (c == MACRODEXPAND)
- return (ONE);
- if (c == '"')
- return (QST);
- if ((c & 0340) == 0200)
- return (OPR);
- if (!isascii(c))
- return (ATM);
- if (isspace(c) || c == ')')
- return (SPC);
- if (strchr(buf, c) != NULL)
- return (OPR);
- return (ATM);
+ return (av);
}
/*
** REWRITE -- apply rewrite rules to token vector.
@@ -605,6 +622,7 @@ toktype(c)
** Parameters:
** pvp -- pointer to token vector.
** ruleset -- the ruleset to use for rewriting.
+** reclevel -- recursion level (to catch loops).
** e -- the current envelope.
**
** Returns:
@@ -624,11 +642,16 @@ struct match
# define MAXMATCH 9 /* max params per rewrite */
+# ifndef MAXRULERECURSION
+# define MAXRULERECURSION 50 /* max recursion depth */
+# endif
+
int
-rewrite(pvp, ruleset, e)
+rewrite(pvp, ruleset, reclevel, e)
char **pvp;
int ruleset;
+ int reclevel;
register ENVELOPE *e;
{
register char *ap; /* address pointer */
@@ -639,6 +662,7 @@ rewrite(pvp, ruleset, e)
register struct rewrite *rwr; /* pointer to current rewrite rule */
int ruleno; /* current rule number */
int rstat = EX_OK; /* return status */
+ int loopcount;
struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
@@ -652,6 +676,11 @@ rewrite(pvp, ruleset, e)
syserr("554 rewrite: illegal ruleset number %d", ruleset);
return EX_CONFIG;
}
+ if (reclevel++ > MAXRULERECURSION)
+ {
+ syserr("rewrite: infinite recursion, ruleset %d", ruleset);
+ return EX_CONFIG;
+ }
if (pvp == NULL)
return EX_USAGE;
@@ -661,10 +690,9 @@ rewrite(pvp, ruleset, e)
*/
ruleno = 1;
+ loopcount = 0;
for (rwr = RewriteRules[ruleset]; rwr != NULL; )
{
- int loopcount = 0;
-
if (tTd(21, 12))
{
printf("-----trying rule:");
@@ -874,6 +902,7 @@ rewrite(pvp, ruleset, e)
printf("----- rule fails\n");
rwr = rwr->r_next;
ruleno++;
+ loopcount = 0;
continue;
}
@@ -890,6 +919,7 @@ rewrite(pvp, ruleset, e)
rvp++;
rwr = rwr->r_next;
ruleno++;
+ loopcount = 0;
}
else if ((*rp & 0377) == CANONHOST)
{
@@ -984,6 +1014,7 @@ rewrite(pvp, ruleset, e)
char *pvpb1[MAXATOM + 1];
char *argvect[10];
char pvpbuf[PSBUFSIZE];
+ char *nullpvp[1];
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
@@ -1101,10 +1132,17 @@ rewrite(pvp, ruleset, e)
{
xpvp = key_rvp;
}
+ else if (*replac == '\0')
+ {
+ /* null replacement */
+ nullpvp[0] = NULL;
+ xpvp = nullpvp;
+ }
else
{
/* scan the new replacement */
- xpvp = prescan(replac, '\0', pvpbuf, NULL);
+ xpvp = prescan(replac, '\0', pvpbuf,
+ sizeof pvpbuf, NULL);
if (xpvp == NULL)
{
/* prescan already printed error */
@@ -1136,15 +1174,24 @@ rewrite(pvp, ruleset, e)
{
int stat;
- bcopy((char *) &npvp[2], (char *) pvp,
- (int) (avp - npvp - 2) * sizeof *avp);
- if (tTd(21, 3))
- printf("-----callsubr %s\n", npvp[1]);
- stat = rewrite(pvp, atoi(npvp[1]), e);
- if (rstat == EX_OK || stat == EX_TEMPFAIL)
- rstat = stat;
- if ((**pvp & 0377) == CANONNET)
+ if (npvp[1] == NULL)
+ {
+ syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
+ ruleset, ruleno);
+ *pvp = NULL;
+ }
+ else
+ {
+ bcopy((char *) &npvp[2], (char *) pvp,
+ (int) (avp - npvp - 2) * sizeof *avp);
+ if (tTd(21, 3))
+ printf("-----callsubr %s\n", npvp[1]);
+ stat = rewrite(pvp, atoi(npvp[1]), reclevel, e);
+ if (rstat == EX_OK || stat == EX_TEMPFAIL)
+ rstat = stat;
+ if (*pvp != NULL && (**pvp & 0377) == CANONNET)
rwr = NULL;
+ }
}
else
{
@@ -1173,6 +1220,8 @@ rewrite(pvp, ruleset, e)
** tv -- token vector.
** a -- pointer to address descriptor to fill.
** If NULL, one will be allocated.
+** flags -- info regarding whether this is a sender or
+** a recipient.
** e -- the current envelope.
**
** Returns:
@@ -1203,26 +1252,45 @@ struct errcodes
};
ADDRESS *
-buildaddr(tv, a, e)
+buildaddr(tv, a, flags, e)
register char **tv;
register ADDRESS *a;
+ int flags;
register ENVELOPE *e;
{
struct mailer **mp;
register struct mailer *m;
char *bp;
int spaceleft;
+ static MAILER errormailer;
+ static char *errorargv[] = { "ERROR", NULL };
static char buf[MAXNAME];
+ if (tTd(24, 5))
+ {
+ printf("buildaddr, flags=%o, tv=", flags);
+ printav(tv);
+ }
+
if (a == NULL)
a = (ADDRESS *) xalloc(sizeof *a);
bzero((char *) a, sizeof *a);
/* figure out what net/mailer to use */
- if ((**tv & 0377) != CANONNET)
+ if (*tv == NULL || (**tv & 0377) != CANONNET)
{
syserr("554 buildaddr: no net");
- return (NULL);
+badaddr:
+ a->q_flags |= QBADADDR;
+ a->q_mailer = &errormailer;
+ if (errormailer.m_name == NULL)
+ {
+ /* initialize the bogus mailer */
+ errormailer.m_name = "*error*";
+ errormailer.m_mailer = "ERROR";
+ errormailer.m_argv = errorargv;
+ }
+ return a;
}
tv++;
if (strcasecmp(*tv, "error") == 0)
@@ -1244,12 +1312,28 @@ buildaddr(tv, a, e)
}
tv++;
}
+ else
+ setstat(EX_UNAVAILABLE);
if ((**tv & 0377) != CANONUSER)
syserr("554 buildaddr: error: no user");
cataddr(++tv, NULL, buf, sizeof buf, ' ');
stripquotes(buf);
- usrerr(buf);
- return (NULL);
+ if (isascii(buf[0]) && isdigit(buf[0]) &&
+ isascii(buf[1]) && isdigit(buf[1]) &&
+ isascii(buf[2]) && isdigit(buf[2]) &&
+ buf[3] == ' ')
+ {
+ char fmt[10];
+
+ strncpy(fmt, buf, 3);
+ strcpy(&fmt[3], " %s");
+ usrerr(fmt, buf + 4);
+ }
+ else
+ {
+ usrerr("553 %s", buf);
+ }
+ goto badaddr;
}
for (mp = Mailer; (m = *mp++) != NULL; )
@@ -1260,7 +1344,7 @@ buildaddr(tv, a, e)
if (m == NULL)
{
syserr("554 buildaddr: unknown mailer %s", *tv);
- return (NULL);
+ goto badaddr;
}
a->q_mailer = m;
@@ -1297,7 +1381,7 @@ buildaddr(tv, a, e)
if (!bitnset(M_LOCALMAILER, m->m_flags))
{
syserr("554 buildaddr: no host");
- return (NULL);
+ goto badaddr;
}
a->q_host = NULL;
}
@@ -1306,7 +1390,7 @@ buildaddr(tv, a, e)
if (*tv == NULL || (**tv & 0377) != CANONUSER)
{
syserr("554 buildaddr: no user");
- return (NULL);
+ goto badaddr;
}
tv++;
@@ -1342,8 +1426,16 @@ buildaddr(tv, a, e)
a->q_flags |= QNOTREMOTE;
}
- /* do cleanup of final address */
- (void) rewrite(tv, 4, e);
+ /* rewrite according recipient mailer rewriting rules */
+ define('h', a->q_host, e);
+ if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
+ {
+ /* sender addresses done later */
+ (void) rewrite(tv, 2, 0, e);
+ if (m->m_re_rwset > 0)
+ (void) rewrite(tv, m->m_re_rwset, 0, e);
+ }
+ (void) rewrite(tv, 4, 0, e);
/* save the result for the command line/RCPT argument */
cataddr(tv, NULL, buf, sizeof buf, '\0');
@@ -1437,6 +1529,8 @@ sameaddr(a, b)
register ADDRESS *a;
register ADDRESS *b;
{
+ register ADDRESS *ca, *cb;
+
/* if they don't have the same mailer, forget it */
if (a->q_mailer != b->q_mailer)
return (FALSE);
@@ -1445,9 +1539,16 @@ sameaddr(a, b)
if (strcmp(a->q_user, b->q_user) != 0)
return (FALSE);
- /* if we have good uids for both but the differ, these are different */
- if (bitset(QGOODUID, a->q_flags & b->q_flags) && a->q_uid != b->q_uid)
- return (FALSE);
+ /* if we have good uids for both but they differ, these are different */
+ if (a->q_mailer == ProgMailer)
+ {
+ ca = getctladdr(a);
+ cb = getctladdr(b);
+ if (ca != NULL && cb != NULL &&
+ bitset(QGOODUID, ca->q_flags & cb->q_flags) &&
+ ca->q_uid != cb->q_uid)
+ return (FALSE);
+ }
/* otherwise compare hosts (but be careful for NULL ptrs) */
if (a->q_host == b->q_host)
@@ -1592,10 +1693,10 @@ remotename(name, m, flags, pstat, e)
** domain will be appended.
*/
- pvp = prescan(name, '\0', pvpbuf, NULL);
+ pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL);
if (pvp == NULL)
return (name);
- if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL)
{
@@ -1612,7 +1713,7 @@ remotename(name, m, flags, pstat, e)
while ((*pxp++ = *qxq++) != NULL)
continue;
- if (rewrite(pvp, 3, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
}
@@ -1626,17 +1727,17 @@ remotename(name, m, flags, pstat, e)
if (bitset(RF_SENDERADDR, flags))
{
- if (rewrite(pvp, 1, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
else
{
- if (rewrite(pvp, 2, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
if (rwset > 0)
{
- if (rewrite(pvp, rwset, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
}
@@ -1647,7 +1748,7 @@ remotename(name, m, flags, pstat, e)
** may be used as a default to the above rules.
*/
- if (rewrite(pvp, 4, e) == EX_TEMPFAIL)
+ if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL)
*pstat = EX_TEMPFAIL;
/*
@@ -1656,7 +1757,13 @@ remotename(name, m, flags, pstat, e)
cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0');
define('g', lbuf, e);
- expand(fancy, buf, &buf[sizeof buf - 1], e);
+
+ /* need to make sure route-addrs have <angle brackets> */
+ if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@')
+ expand("<\201g>", buf, &buf[sizeof buf - 1], e);
+ else
+ expand(fancy, buf, &buf[sizeof buf - 1], e);
+
define('g', oldg, e);
if (tTd(12, 1))
@@ -1690,16 +1797,16 @@ maplocaluser(a, sendq, e)
printf("maplocaluser: ");
printaddr(a, FALSE);
}
- pvp = prescan(a->q_user, '\0', pvpbuf, &delimptr);
+ pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr);
if (pvp == NULL)
return;
- (void) rewrite(pvp, 5, e);
+ (void) rewrite(pvp, 5, 0, e);
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
return;
/* if non-null, mailer destination specified -- has it changed? */
- a1 = buildaddr(pvp, NULL, e);
+ a1 = buildaddr(pvp, NULL, 0, e);
if (a1 == NULL || sameaddr(a, a1))
return;
@@ -1711,7 +1818,7 @@ maplocaluser(a, sendq, e)
printaddr(a, FALSE);
}
a1->q_alias = a;
- allocaddr(a1, 1, NULL, delimptr);
+ allocaddr(a1, RF_COPYALL, NULL);
(void) recipient(a1, sendq, e);
}
/*
diff --git a/usr.sbin/sendmail/src/pathnames.h b/usr.sbin/sendmail/src/pathnames.h
index be9a07261718..a611c0b0b2b0 100644
--- a/usr.sbin/sendmail/src/pathnames.h
+++ b/usr.sbin/sendmail/src/pathnames.h
@@ -30,17 +30,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)pathnames.h 8.1 (Berkeley) 6/7/93
+ * @(#)pathnames.h 8.2 (Berkeley) 8/20/93
*/
#ifndef _PATH_SENDMAILCF
# define _PATH_SENDMAILCF "/etc/sendmail.cf"
#endif
-#ifndef _PATH_SENDMAILFC
-# define _PATH_SENDMAILFC "/etc/sendmail.fc"
-#endif
-
#ifndef _PATH_SENDMAILPID
# ifdef BSD4_4
# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
diff --git a/usr.sbin/sendmail/src/queue.c b/usr.sbin/sendmail/src/queue.c
index 5b55217774ec..99e851efad7d 100644
--- a/usr.sbin/sendmail/src/queue.c
+++ b/usr.sbin/sendmail/src/queue.c
@@ -36,13 +36,12 @@
#ifndef lint
#ifdef QUEUE
-static char sccsid[] = "@(#)queue.c 8.3 (Berkeley) 7/13/93 (with queueing)";
+static char sccsid[] = "@(#)queue.c 8.40 (Berkeley) 3/6/94 (with queueing)";
#else
-static char sccsid[] = "@(#)queue.c 8.3 (Berkeley) 7/13/93 (without queueing)";
+static char sccsid[] = "@(#)queue.c 8.40 (Berkeley) 3/6/94 (without queueing)";
#endif
#endif /* not lint */
-# include <signal.h>
# include <errno.h>
# include <pwd.h>
# include <dirent.h>
@@ -95,49 +94,79 @@ queueup(e, queueall, announce)
bool newid;
register char *p;
MAILER nullmailer;
+ MCI mcibuf;
char buf[MAXLINE], tf[MAXLINE];
/*
** Create control file.
*/
- newid = (e->e_id == NULL);
+ newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
+
+ /* if newid, queuename will create a locked qf file in e->lockfp */
strcpy(tf, queuename(e, 't'));
tfp = e->e_lockfp;
if (tfp == NULL)
newid = FALSE;
- if (newid)
- {
- tfp = e->e_lockfp;
- }
- else
+
+ /* if newid, just write the qf file directly (instead of tf file) */
+ if (!newid)
{
/* get a locked tf file */
- for (i = 100; --i >= 0; )
+ for (i = 0; i < 128; i++)
{
fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
if (fd < 0)
{
- if (errno == EEXIST)
- continue;
-notemp:
- syserr("!queueup: cannot create temp file %s", tf);
+ if (errno != EEXIST)
+ break;
+#ifdef LOG
+ if (LogLevel > 0 && (i % 32) == 0)
+ syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s",
+ tf, geteuid(), errstring(errno));
+#endif
+ }
+ else
+ {
+ if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
+ break;
+#ifdef LOG
+ else if (LogLevel > 0 && (i % 32) == 0)
+ syslog(LOG_ALERT, "queueup: cannot lock %s: %s",
+ tf, errstring(errno));
+#endif
+ close(fd);
}
- if (lockfile(fd, tf, LOCK_EX|LOCK_NB))
- break;
-
- close(fd);
- sleep(i);
+ if ((i % 32) == 31)
+ {
+ /* save the old temp file away */
+ (void) rename(tf, queuename(e, 'T'));
+ }
+ else
+ sleep(i % 32);
+ }
+ if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL)
+ {
+ printopenfds(TRUE);
+ syserr("!queueup: cannot create queue temp file %s, uid=%d",
+ tf, geteuid());
}
- if (fd < 0)
- goto notemp;
-
- tfp = fdopen(fd, "w");
}
if (tTd(40, 1))
- printf("queueing %s\n", e->e_id);
+ printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id,
+ newid ? " (new id)" : "");
+ if (tTd(40, 9))
+ {
+ printf(" tfp=");
+ dumpfd(fileno(tfp), TRUE, FALSE);
+ printf(" lockfp=");
+ if (e->e_lockfp == NULL)
+ printf("NULL\n");
+ else
+ dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
+ }
/*
** If there is no data file yet, create one.
@@ -148,12 +177,16 @@ notemp:
register FILE *dfp;
extern putbody();
- e->e_df = newstr(queuename(e, 'd'));
+ e->e_df = queuename(e, 'd');
+ e->e_df = newstr(e->e_df);
fd = open(e->e_df, O_WRONLY|O_CREAT, FileMode);
- if (fd < 0)
- syserr("!queueup: cannot create %s", e->e_df);
- dfp = fdopen(fd, "w");
- (*e->e_putbody)(dfp, FileMailer, e, NULL);
+ if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL)
+ syserr("!queueup: cannot create data temp file %s, uid=%d",
+ e->e_df, geteuid());
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_out = dfp;
+ mcibuf.mci_mailer = FileMailer;
+ (*e->e_putbody)(&mcibuf, e, NULL);
(void) xfclose(dfp, "queueup dfp", e->e_id);
e->e_putbody = putbody;
}
@@ -224,7 +257,7 @@ notemp:
e->e_to = q->q_paddr;
message("queued");
if (LogLevel > 8)
- logdelivery(NULL, NULL, "queued", e);
+ logdelivery(NULL, NULL, "queued", NULL, e);
e->e_to = NULL;
}
if (tTd(40, 1))
@@ -249,6 +282,9 @@ notemp:
nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
nullmailer.m_eol = "\n";
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_mailer = &nullmailer;
+ mcibuf.mci_out = tfp;
define('g', "\201f", e);
for (h = e->e_header; h != NULL; h = h->h_link)
@@ -263,6 +299,14 @@ notemp:
if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
continue;
+ /* expand macros; if null, don't output header at all */
+ if (bitset(H_DEFAULT, h->h_flags))
+ {
+ (void) expand(h->h_value, buf, &buf[sizeof buf], e);
+ if (buf[0] == '\0')
+ continue;
+ }
+
/* output this header */
fprintf(tfp, "H");
@@ -281,7 +325,6 @@ notemp:
/* output the header: expand macros, convert addresses */
if (bitset(H_DEFAULT, h->h_flags))
{
- (void) expand(h->h_value, buf, &buf[sizeof buf], e);
fprintf(tfp, "%s: %s\n", h->h_field, buf);
}
else if (bitset(H_FROM|H_RCPT, h->h_flags))
@@ -294,8 +337,7 @@ notemp:
if (bitset(H_FROM, h->h_flags))
oldstyle = FALSE;
- commaize(h, h->h_value, tfp, oldstyle,
- &nullmailer, e);
+ commaize(h, h->h_value, oldstyle, &mcibuf, e);
TrafficLogFile = savetrace;
}
@@ -307,9 +349,7 @@ notemp:
** Clean up.
*/
- fflush(tfp);
- fsync(fileno(tfp));
- if (ferror(tfp))
+ if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp))
{
if (newid)
syserr("!552 Error writing control file %s", tf);
@@ -319,9 +359,13 @@ notemp:
if (!newid)
{
+ /* rename (locked) tf to be (locked) qf */
qf = queuename(e, 'q');
if (rename(tf, qf) < 0)
- syserr("cannot rename(%s, %s), df=%s", tf, qf, e->e_df);
+ syserr("cannot rename(%s, %s), df=%s, uid=%d",
+ tf, qf, e->e_df, geteuid());
+
+ /* close and unlock old (locked) qf */
if (e->e_lockfp != NULL)
(void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);
e->e_lockfp = tfp;
@@ -329,12 +373,16 @@ notemp:
else
qf = tf;
errno = 0;
+ e->e_flags |= EF_INQUEUE;
# ifdef LOG
/* save log info */
if (LogLevel > 79)
syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);
# endif /* LOG */
+
+ if (tTd(40, 1))
+ printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
return;
}
@@ -350,7 +398,7 @@ printctladdr(a, tfp)
static uid_t lastuid;
/* initialization */
- if (a == NULL || tfp == NULL)
+ if (a == NULL || a->q_alias == NULL || tfp == NULL)
{
if (lastctladdr != NULL && tfp != NULL)
fprintf(tfp, "C\n");
@@ -365,10 +413,7 @@ printctladdr(a, tfp)
uid = 0;
else
uid = q->q_uid;
-
- /* if a is an alias, use that for printing */
- if (a->q_alias != NULL)
- a = a->q_alias;
+ a = a->q_alias;
/* check to see if this is the same as last time */
if (lastctladdr != NULL && uid == lastuid &&
@@ -434,17 +479,18 @@ runqueue(forkflag)
if (forkflag)
{
int pid;
+#ifdef SIGCHLD
+ extern void reapchild();
+
+ (void) setsignal(SIGCHLD, reapchild);
+#endif
pid = dofork();
if (pid != 0)
{
- extern void reapchild();
-
/* parent -- pick up intermediate zombie */
#ifndef SIGCHLD
(void) waitfor(pid);
-#else /* SIGCHLD */
- (void) signal(SIGCHLD, reapchild);
#endif /* SIGCHLD */
if (QueueIntvl != 0)
(void) setevent(QueueIntvl, runqueue, TRUE);
@@ -455,7 +501,7 @@ runqueue(forkflag)
if (fork() != 0)
exit(EX_OK);
#else /* SIGCHLD */
- (void) signal(SIGCHLD, SIG_DFL);
+ (void) setsignal(SIGCHLD, SIG_DFL);
#endif /* SIGCHLD */
}
@@ -475,6 +521,9 @@ runqueue(forkflag)
clrdaemon();
# endif /* DAEMON */
+ /* force it to run expensive jobs */
+ NoConnect = FALSE;
+
/*
** Create ourselves an envelope
*/
@@ -517,7 +566,13 @@ runqueue(forkflag)
}
else
{
- dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
+ pid_t pid;
+ extern pid_t dowork();
+
+ pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
+ errno = 0;
+ if (pid != 0)
+ (void) waitfor(pid);
}
free(w->w_name);
free((char *) w);
@@ -597,6 +652,7 @@ orderq(doall)
while ((d = readdir(f)) != NULL)
{
FILE *cf;
+ register char *p;
char lbuf[MAXNAME];
extern bool strcontainedin();
@@ -613,8 +669,16 @@ orderq(doall)
** both old and new type ids.
*/
- i = strlen(d->d_name);
- if (i != 9 && i != 10)
+ p = d->d_name + 2;
+ if (isupper(p[0]) && isupper(p[2]))
+ p += 3;
+ else if (isupper(p[1]))
+ p += 2;
+ else
+ p = d->d_name;
+ for (i = 0; isdigit(*p); p++)
+ i++;
+ if (i < 5 || *p != '\0')
{
if (Verbose)
printf("orderq: bogus qf name %s\n", d->d_name);
@@ -775,19 +839,20 @@ workcmpf(a, b)
** e - the envelope in which to run it.
**
** Returns:
-** none.
+** process id of process that is running the queue job.
**
** Side Effects:
** The work request is satisfied if possible.
*/
+pid_t
dowork(id, forkflag, requeueflag, e)
char *id;
bool forkflag;
bool requeueflag;
register ENVELOPE *e;
{
- register int i;
+ register pid_t pid;
extern bool readqf();
if (tTd(40, 1))
@@ -799,19 +864,24 @@ dowork(id, forkflag, requeueflag, e)
if (forkflag)
{
- i = fork();
- if (i < 0)
+ pid = fork();
+ if (pid < 0)
{
syserr("dowork: cannot fork");
- return;
+ return 0;
+ }
+ else if (pid > 0)
+ {
+ /* parent -- clean out connection cache */
+ mci_flush(FALSE, NULL);
}
}
else
{
- i = 0;
+ pid = 0;
}
- if (i == 0)
+ if (pid == 0)
{
/*
** CHILD
@@ -824,9 +894,16 @@ dowork(id, forkflag, requeueflag, e)
/* set basic modes, etc. */
(void) alarm(0);
clearenvelope(e, FALSE);
- e->e_flags |= EF_QUEUERUN;
+ e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
e->e_errormode = EM_MAIL;
e->e_id = id;
+ GrabTo = UseErrorsTo = FALSE;
+ ExitStat = EX_OK;
+ if (forkflag)
+ {
+ disconnect(1, e);
+ OpMode = MD_DELIVER;
+ }
# ifdef LOG
if (LogLevel > 76)
syslog(LOG_DEBUG, "%s: dowork, pid=%d", e->e_id,
@@ -844,7 +921,7 @@ dowork(id, forkflag, requeueflag, e)
if (forkflag)
exit(EX_OK);
else
- return;
+ return 0;
}
e->e_flags |= EF_INQUEUE;
@@ -862,15 +939,8 @@ dowork(id, forkflag, requeueflag, e)
else
dropenvelope(e);
}
- else if (!requeueflag)
- {
- /*
- ** Parent -- pick up results.
- */
-
- errno = 0;
- (void) waitfor(i);
- }
+ e->e_id = NULL;
+ return pid;
}
/*
** READQF -- read queue file and set up environment.
@@ -915,6 +985,21 @@ readqf(e)
return FALSE;
}
+ if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
+ {
+ /* being processed by another queuer */
+ if (tTd(40, 8))
+ printf("readqf(%s): locked\n", qf);
+ if (Verbose)
+ printf("%s: locked\n", e->e_id);
+# ifdef LOG
+ if (LogLevel > 19)
+ syslog(LOG_DEBUG, "%s: locked", e->e_id);
+# endif /* LOG */
+ (void) fclose(qfp);
+ return FALSE;
+ }
+
/*
** Check the queue file for plausibility to avoid attacks.
*/
@@ -929,7 +1014,7 @@ readqf(e)
return FALSE;
}
- if (st.st_uid != geteuid() || (st.st_mode & 07777) != FileMode)
+ if (st.st_uid != geteuid())
{
# ifdef LOG
if (LogLevel > 0)
@@ -940,42 +1025,40 @@ readqf(e)
# endif /* LOG */
if (tTd(40, 8))
printf("readqf(%s): bogus file\n", qf);
- fclose(qfp);
rename(qf, queuename(e, 'Q'));
+ fclose(qfp);
return FALSE;
}
- if (!lockfile(fileno(qfp), qf, LOCK_EX|LOCK_NB))
+ if (st.st_size == 0)
{
- /* being processed by another queuer */
- if (tTd(40, 8))
- printf("readqf(%s): locked\n", qf);
- if (Verbose)
- printf("%s: locked\n", e->e_id);
-# ifdef LOG
- if (LogLevel > 19)
- syslog(LOG_DEBUG, "%s: locked", e->e_id);
-# endif /* LOG */
- (void) fclose(qfp);
+ /* must be a bogus file -- just remove it */
+ (void) unlink(qf);
+ fclose(qfp);
return FALSE;
}
- if (st.st_size == 0)
+ if (st.st_nlink == 0)
{
- /* must be a bogus file -- just remove it */
- (void) unlink(qf);
+ /*
+ ** Race condition -- we got a file just as it was being
+ ** unlinked. Just assume it is zero length.
+ */
+
fclose(qfp);
return FALSE;
}
- /* save this lock */
+ /* good file -- save this lock */
e->e_lockfp = qfp;
/* do basic system initialization */
initsys(e);
+ define('i', e->e_id, e);
- FileName = qf;
LineNumber = 0;
+ e->e_flags |= EF_GLOBALERRS;
+ OpMode = MD_DELIVER;
if (Verbose)
printf("\nRunning %s\n", e->e_id);
ctladdr = NULL;
@@ -1005,7 +1088,7 @@ readqf(e)
break;
case 'M': /* message */
- e->e_message = newstr(&bp[1]);
+ /* ignore this; we want a new message next time */
break;
case 'S': /* sender */
@@ -1060,8 +1143,8 @@ readqf(e)
break;
default:
- syserr("readqf: bad line \"%s\"", e->e_id,
- LineNumber, bp);
+ syserr("readqf: %s: line %d: bad line \"%s\"",
+ qf, LineNumber, bp);
fclose(qfp);
rename(qf, queuename(e, 'Q'));
return FALSE;
@@ -1071,8 +1154,6 @@ readqf(e)
free(bp);
}
- FileName = NULL;
-
/*
** If we haven't read any lines, this queue file is empty.
** Arrange to remove it without referencing any null pointers.
@@ -1109,12 +1190,12 @@ printqueue()
** Check for permission to print the queue
*/
- if (bitset(PRIV_RESTRMAILQ, PrivacyFlags) && RealUid != 0)
+ if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
{
struct stat st;
# ifdef NGROUPS
int n;
- int gidset[NGROUPS];
+ GIDSET_T gidset[NGROUPS];
# endif
if (stat(QueueDir, &st) < 0)
@@ -1175,14 +1256,15 @@ printqueue()
char message[MAXLINE];
char bodytype[MAXNAME];
+ printf("%8s", w->w_name + 2);
f = fopen(w->w_name, "r");
if (f == NULL)
{
+ printf(" (job completed)\n");
errno = 0;
continue;
}
- printf("%8s", w->w_name + 2);
- if (!lockfile(fileno(f), w->w_name, LOCK_SH|LOCK_NB))
+ if (!lockfile(fileno(f), w->w_name, NULL, LOCK_SH|LOCK_NB))
printf("*");
else if (shouldqueue(w->w_pri, w->w_ctime))
printf("X");
@@ -1344,11 +1426,11 @@ queuename(e, type)
{
if (errno == EEXIST)
continue;
- syserr("queuename: Cannot create \"%s\" in \"%s\"",
- qf, QueueDir);
+ syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
+ qf, QueueDir, geteuid());
exit(EX_UNAVAILABLE);
}
- if (lockfile(i, qf, LOCK_EX|LOCK_NB))
+ if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB))
{
e->e_lockfp = fdopen(i, "w");
break;
@@ -1359,14 +1441,19 @@ queuename(e, type)
}
if (c1 >= '~' && c2 >= 'Z')
{
- syserr("queuename: Cannot create \"%s\" in \"%s\"",
- qf, QueueDir);
+ syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
+ qf, QueueDir, geteuid());
exit(EX_OSERR);
}
e->e_id = newstr(&qf[2]);
define('i', e->e_id, e);
if (tTd(7, 1))
printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
+ if (tTd(7, 9))
+ {
+ printf(" lockfd=");
+ dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
+ }
# ifdef LOG
if (LogLevel > 93)
syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
@@ -1445,8 +1532,8 @@ setctluser(user)
** See if this clears our concept of controlling user.
*/
- if (user == NULL)
- user = "";
+ if (user == NULL || *user == '\0')
+ return NULL;
/*
** Set up addr fields for controlling user.
@@ -1460,7 +1547,10 @@ setctluser(user)
*p++ = '\0';
if (*user != '\0' && (pw = getpwnam(user)) != NULL)
{
- a->q_home = newstr(pw->pw_dir);
+ if (strcmp(pw->pw_dir, "/") == 0)
+ a->q_home = "";
+ else
+ a->q_home = newstr(pw->pw_dir);
a->q_uid = pw->pw_uid;
a->q_gid = pw->pw_gid;
a->q_user = newstr(user);
diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c
index 7af9d5a4c380..bd902c0cf66c 100644
--- a/usr.sbin/sendmail/src/readcf.c
+++ b/usr.sbin/sendmail/src/readcf.c
@@ -33,11 +33,13 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)readcf.c 8.2 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)readcf.c 8.23 (Berkeley) 3/18/94";
#endif /* not lint */
# include "sendmail.h"
-#ifdef NAMED_BIND
+# include <pwd.h>
+# include <grp.h>
+#if NAMED_BIND
# include <arpa/nameser.h>
# include <resolv.h>
#endif
@@ -68,7 +70,9 @@ static char sccsid[] = "@(#)readcf.c 8.2 (Berkeley) 7/13/93";
** Args specify mailer parameters.
** Oxvalue Set option x to value.
** Pname=value Set precedence name to value.
-** Vversioncode Version level of configuration syntax.
+** Vversioncode[/vendorcode]
+** Version level/vendor name of
+** configuration syntax.
** Kmapname mapclass arguments....
** Define keyed lookup of a given class.
** Arguments are class dependent.
@@ -96,13 +100,16 @@ readcf(cfname, safe, e)
char *q;
struct rewrite *rwp = NULL;
char *bp;
+ auto char *ep;
int nfuzzy;
+ char *file;
+ bool optional;
char buf[MAXLINE];
register char *p;
extern char **copyplist();
struct stat statb;
char exbuf[MAXLINE];
- char pvpbuf[PSBUFSIZE];
+ char pvpbuf[MAXLINE + MAXATOM];
extern char *munchstring();
extern void makemapentry();
@@ -201,6 +208,7 @@ readcf(cfname, safe, e)
}
/* interpret this line */
+ errno = 0;
switch (bp[0])
{
case '\0':
@@ -213,7 +221,7 @@ readcf(cfname, safe, e)
if (*p == '\0')
{
- syserr("invalid rewrite line \"%s\"", bp);
+ syserr("invalid rewrite line \"%s\" (tab expected)", bp);
break;
}
@@ -233,7 +241,8 @@ readcf(cfname, safe, e)
/* expand and save the LHS */
*p = '\0';
expand(&bp[1], exbuf, &exbuf[sizeof exbuf], e);
- rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, NULL);
+ rwp->r_lhs = prescan(exbuf, '\t', pvpbuf,
+ sizeof pvpbuf, NULL);
nfuzzy = 0;
if (rwp->r_lhs != NULL)
{
@@ -317,7 +326,8 @@ readcf(cfname, safe, e)
p++;
*p = '\0';
expand(q, exbuf, &exbuf[sizeof exbuf], e);
- rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, NULL);
+ rwp->r_rhs = prescan(exbuf, '\t', pvpbuf,
+ sizeof pvpbuf, NULL);
if (rwp->r_rhs != NULL)
{
register char **ap;
@@ -371,7 +381,15 @@ readcf(cfname, safe, e)
break;
case 'S': /* select rewriting set */
- ruleset = atoi(&bp[1]);
+ for (p = &bp[1]; isascii(*p) && isspace(*p); p++)
+ continue;
+ if (!isascii(*p) || !isdigit(*p))
+ {
+ syserr("invalid argument to S line: \"%.20s\"",
+ &bp[1]);
+ break;
+ }
+ ruleset = atoi(p);
if (ruleset >= MAXRWSETS || ruleset < 0)
{
syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS);
@@ -381,7 +399,8 @@ readcf(cfname, safe, e)
break;
case 'D': /* macro definition */
- define(bp[1], newstr(munchstring(&bp[2], NULL)), e);
+ p = munchstring(&bp[2], NULL);
+ define(bp[1], newstr(p), e);
break;
case 'H': /* required header line */
@@ -390,7 +409,8 @@ readcf(cfname, safe, e)
case 'C': /* word class */
/* scan the list of words and set class for all */
- for (p = &bp[2]; *p != '\0'; )
+ expand(&bp[2], exbuf, &exbuf[sizeof exbuf], e);
+ for (p = exbuf; *p != '\0'; )
{
register char *wd;
char delim;
@@ -403,23 +423,27 @@ readcf(cfname, safe, e)
delim = *p;
*p = '\0';
if (wd[0] != '\0')
- {
- if (tTd(37, 2))
- printf("setclass(%c, %s)\n",
- bp[1], wd);
setclass(bp[1], wd);
- }
*p = delim;
}
break;
case 'F': /* word class from file */
- /* read list of words from argument or file */
- /* read from file */
- for (p = &bp[2];
- *p != '\0' && !(isascii(*p) && isspace(*p));
- p++)
- continue;
+ for (p = &bp[2]; isascii(*p) && isspace(*p); )
+ p++;
+ if (p[0] == '-' && p[1] == 'o')
+ {
+ optional = TRUE;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
+ while (isascii(*p) && isspace(*p))
+ *p++;
+ }
+ else
+ optional = FALSE;
+ file = p;
+ while (*p != '\0' && !(isascii(*p) && isspace(*p)))
+ p++;
if (*p == '\0')
p = "%s";
else
@@ -428,7 +452,7 @@ readcf(cfname, safe, e)
while (isascii(*++p) && isspace(*p))
continue;
}
- fileclass(bp[1], &bp[2], p, safe);
+ fileclass(bp[1], file, p, safe, optional);
break;
#ifdef XLA
@@ -466,7 +490,33 @@ readcf(cfname, safe, e)
break;
case 'V': /* configuration syntax version */
- ConfigLevel = atoi(&bp[1]);
+ for (p = &bp[1]; isascii(*p) && isspace(*p); p++)
+ continue;
+ if (!isascii(*p) || !isdigit(*p))
+ {
+ syserr("invalid argument to V line: \"%.20s\"",
+ &bp[1]);
+ break;
+ }
+ ConfigLevel = strtol(p, &ep, 10);
+ if (ConfigLevel >= 5)
+ {
+ /* level 5 configs have short name in $w */
+ p = macvalue('w', e);
+ if (p != NULL && (p = strchr(p, '.')) != NULL)
+ *p = '\0';
+ }
+ if (*ep++ == '/')
+ {
+ /* extract vendor code */
+ for (p = ep; isascii(*p) && isalpha(*p); )
+ p++;
+ *p = '\0';
+
+ if (!setvendor(ep))
+ syserr("invalid V line vendor code: \"%s\"",
+ ep);
+ }
break;
case 'K':
@@ -492,8 +542,10 @@ readcf(cfname, safe, e)
{
/* user didn't initialize: set up host map */
strcpy(buf, "host host");
+#if NAMED_BIND
if (ConfigLevel >= 2)
strcat(buf, " -a.");
+#endif
makemapentry(buf);
}
}
@@ -524,6 +576,9 @@ toomany(id, maxcnt)
** class -- class to define.
** filename -- name of file to read.
** fmt -- scanf string to use for match.
+** safe -- if set, this is a safe read.
+** optional -- if set, it is not an error for the file to
+** not exist.
**
** Returns:
** none
@@ -534,19 +589,32 @@ toomany(id, maxcnt)
** the named class.
*/
-fileclass(class, filename, fmt, safe)
+fileclass(class, filename, fmt, safe, optional)
int class;
char *filename;
char *fmt;
bool safe;
+ bool optional;
{
FILE *f;
struct stat stbuf;
char buf[MAXLINE];
+ if (tTd(37, 2))
+ printf("fileclass(%s, fmt=%s)\n", filename, fmt);
+
+ if (filename[0] == '|')
+ {
+ syserr("fileclass: pipes (F%c%s) not supported due to security problems",
+ class, filename);
+ return;
+ }
if (stat(filename, &stbuf) < 0)
{
- syserr("fileclass: cannot stat %s", filename);
+ if (tTd(37, 2))
+ printf(" cannot stat (%s)\n", errstring(errno));
+ if (!optional)
+ syserr("fileclass: cannot stat %s", filename);
return;
}
if (!S_ISREG(stbuf.st_mode))
@@ -602,8 +670,7 @@ fileclass(class, filename, fmt, safe)
*p++ = '\0';
/* enter the word in the symbol table */
- s = stab(q, ST_CLASS, ST_ENTER);
- setbitn(class, s->s_class);
+ setclass(class, q);
}
}
@@ -950,7 +1017,7 @@ printrules()
static BITMAP StickyOpt; /* set if option is stuck */
-#ifdef NAMED_BIND
+#if NAMED_BIND
struct resolverflags
{
@@ -967,6 +1034,7 @@ struct resolverflags
"defnames", RES_DEFNAMES,
"stayopen", RES_STAYOPEN,
"dnsrch", RES_DNSRCH,
+ "true", 0, /* to avoid error on old syntax */
NULL, 0
};
@@ -984,6 +1052,7 @@ setoption(opt, val, safe, sticky, e)
extern time_t convtime();
extern int QueueLA;
extern int RefuseLA;
+ extern bool Warn_Q_option;
extern bool trusteduser();
if (tTd(37, 1))
@@ -1006,7 +1075,7 @@ setoption(opt, val, safe, sticky, e)
if (!safe && RealUid == 0)
safe = TRUE;
- if (!safe && strchr("bdeEijLmoprsvC7", opt) == NULL)
+ if (!safe && strchr("bCdeijLmoprsvw7", opt) == NULL)
{
if (opt != 'M' || (val[0] != 'r' && val[0] != 's'))
{
@@ -1039,9 +1108,9 @@ setoption(opt, val, safe, sticky, e)
case 'a': /* look N minutes for "@:@" in alias file */
if (val[0] == '\0')
- SafeAlias = 5;
+ SafeAlias = 5 * 60; /* five minutes */
else
- SafeAlias = atoi(val);
+ SafeAlias = convtime(val, 'm');
break;
case 'B': /* substitution for blank character */
@@ -1130,7 +1199,19 @@ setoption(opt, val, safe, sticky, e)
break;
case 'g': /* default gid */
- DefGid = atoi(val);
+ if (isascii(*val) && isdigit(*val))
+ DefGid = atoi(val);
+ else
+ {
+ register struct group *gr;
+
+ DefGid = -1;
+ gr = getgrnam(val);
+ if (gr == NULL)
+ syserr("readcf: option g: unknown group %s", val);
+ else
+ DefGid = gr->gr_gid;
+ }
break;
case 'H': /* help file */
@@ -1145,7 +1226,7 @@ setoption(opt, val, safe, sticky, e)
break;
case 'I': /* use internet domain name server */
-#ifdef NAMED_BIND
+#if NAMED_BIND
UseNameServer = TRUE;
for (p = val; *p != 0; )
{
@@ -1173,7 +1254,9 @@ setoption(opt, val, safe, sticky, e)
if (strcasecmp(q, rfp->rf_name) == 0)
break;
}
- if (clearmode)
+ if (rfp->rf_name == NULL)
+ syserr("readcf: I option value %s unrecognized", q);
+ else if (clearmode)
_res.options &= ~rfp->rf_bits;
else
_res.options |= rfp->rf_bits;
@@ -1212,7 +1295,8 @@ setoption(opt, val, safe, sticky, e)
break;
case 'L': /* log level */
- LogLevel = atoi(val);
+ if (safe || LogLevel < atoi(val))
+ LogLevel = atoi(val);
break;
case 'M': /* define macro */
@@ -1283,7 +1367,7 @@ setoption(opt, val, safe, sticky, e)
else
QueueDir = newstr(val);
if (RealUid != 0 && !safe)
- auth_warning(e, "Processed from queue %s", QueueDir);
+ Warn_Q_option = TRUE;
break;
case 'R': /* don't prune routes */
@@ -1324,7 +1408,19 @@ setoption(opt, val, safe, sticky, e)
break;
case 'u': /* set default uid */
- DefUid = atoi(val);
+ if (isascii(*val) && isdigit(*val))
+ DefUid = atoi(val);
+ else
+ {
+ register struct passwd *pw;
+
+ DefUid = -1;
+ pw = getpwnam(val);
+ if (pw == NULL)
+ syserr("readcf: option u: unknown user %s", val);
+ else
+ DefUid = pw->pw_uid;
+ }
setdefuser();
break;
@@ -1336,7 +1432,9 @@ setoption(opt, val, safe, sticky, e)
Verbose = atobool(val);
break;
- /* 'w' available -- was "no wildcard MX matching" */
+ case 'w': /* if we are best MX, try host directly */
+ TryNullMXList = atobool(val);
+ break;
/* 'W' available -- was wizard password */
@@ -1392,7 +1490,7 @@ setclass(class, word)
register STAB *s;
if (tTd(37, 8))
- printf("%s added to class %c\n", word, class);
+ printf("setclass(%c, %s)\n", class, word);
s = stab(word, ST_CLASS, ST_ENTER);
setbitn(class, s->s_class);
}
@@ -1417,7 +1515,7 @@ makemapentry(line)
register char *p;
char *mapname;
char *classname;
- register STAB *map;
+ register STAB *s;
STAB *class;
for (p = line; isascii(*p) && isspace(*p); p++)
@@ -1457,12 +1555,24 @@ makemapentry(line)
}
/* enter the map */
- map = stab(mapname, ST_MAP, ST_ENTER);
- map->s_map.map_class = &class->s_mapclass;
- map->s_map.map_mname = newstr(mapname);
+ s = stab(mapname, ST_MAP, ST_ENTER);
+ s->s_map.map_class = &class->s_mapclass;
+ s->s_map.map_mname = newstr(mapname);
- if (class->s_mapclass.map_parse(&map->s_map, p))
- map->s_map.map_mflags |= MF_VALID;
+ if (class->s_mapclass.map_parse(&s->s_map, p))
+ s->s_map.map_mflags |= MF_VALID;
+
+ if (tTd(37, 5))
+ {
+ printf("map %s, class %s, flags %x, file %s,\n",
+ s->s_map.map_mname, s->s_map.map_class->map_cname,
+ s->s_map.map_mflags,
+ s->s_map.map_file == NULL ? "(null)" : s->s_map.map_file);
+ printf("\tapp %s, domain %s, rebuild %s\n",
+ s->s_map.map_app == NULL ? "(null)" : s->s_map.map_app,
+ s->s_map.map_domain == NULL ? "(null)" : s->s_map.map_domain,
+ s->s_map.map_rebuild == NULL ? "(null)" : s->s_map.map_rebuild);
+ }
}
/*
** SETTIMEOUTS -- parse and set timeout values
@@ -1478,6 +1588,7 @@ makemapentry(line)
** Initializes the TimeOuts structure
*/
+#define SECONDS
#define MINUTES * 60
#define HOUR * 3600
@@ -1500,6 +1611,7 @@ settimeouts(val)
TimeOuts.to_quit = (time_t) 2 MINUTES;
TimeOuts.to_nextcommand = (time_t) 1 HOUR;
TimeOuts.to_miscshort = (time_t) 2 MINUTES;
+ TimeOuts.to_ident = (time_t) 30 SECONDS;
return;
}
@@ -1560,6 +1672,8 @@ settimeouts(val)
TimeOuts.to_quit = to;
else if (strcasecmp(val, "misc") == 0)
TimeOuts.to_miscshort = to;
+ else if (strcasecmp(val, "ident") == 0)
+ TimeOuts.to_ident = to;
else
syserr("settimeouts: invalid timeout %s", val);
}
diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c
index bcdf5bfb3bfc..98d800d006ab 100644
--- a/usr.sbin/sendmail/src/recipient.c
+++ b/usr.sbin/sendmail/src/recipient.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)recipient.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)recipient.c 8.44 (Berkeley) 2/28/94";
#endif /* not lint */
# include "sendmail.h"
@@ -75,6 +75,13 @@ sendtolist(list, ctladdr, sendq, e)
bool firstone; /* set on first address sent */
char delimiter; /* the address delimiter */
int naddrs;
+ char *oldto = e->e_to;
+
+ if (list == NULL)
+ {
+ syserr("sendtolist: null list");
+ return 0;
+ }
if (tTd(25, 1))
{
@@ -103,7 +110,7 @@ sendtolist(list, ctladdr, sendq, e)
/* parse the address */
while ((isascii(*p) && isspace(*p)) || *p == ',')
p++;
- a = parseaddr(p, (ADDRESS *) NULL, 1, delimiter, &delimptr, e);
+ a = parseaddr(p, NULLADDR, RF_COPYALL, delimiter, &delimptr, e);
p = delimptr;
if (a == NULL)
continue;
@@ -135,7 +142,7 @@ sendtolist(list, ctladdr, sendq, e)
naddrs++;
}
- e->e_to = NULL;
+ e->e_to = oldto;
return (naddrs);
}
/*
@@ -182,6 +189,15 @@ recipient(a, sendq, e)
printaddr(a, FALSE);
}
+ /* if this is primary, add it to the original recipient list */
+ if (a->q_alias == NULL)
+ {
+ if (e->e_origrcpt == NULL)
+ e->e_origrcpt = a->q_paddr;
+ else if (e->e_origrcpt != a->q_paddr)
+ e->e_origrcpt = "";
+ }
+
/* break aliasing loops */
if (AliasLevel > MAXRCRSN)
{
@@ -206,11 +222,25 @@ recipient(a, sendq, e)
stripquotes(buf);
/* check for direct mailing to restricted mailers */
- if (a->q_alias == NULL && m == ProgMailer &&
- !bitset(EF_QUEUERUN, e->e_flags))
+ if (m == ProgMailer)
{
- a->q_flags |= QBADADDR;
- usrerr("550 Cannot mail directly to programs", m->m_name);
+ if (a->q_alias == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ usrerr("550 Cannot mail directly to programs");
+ }
+ else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs",
+ a->q_alias->q_ruser, MyHostName);
+ }
+ else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ usrerr("550 Address %s is unsafe for mailing to programs",
+ a->q_alias->q_paddr);
+ }
}
/*
@@ -237,7 +267,10 @@ recipient(a, sendq, e)
message("duplicate suppressed");
q->q_flags |= a->q_flags;
}
- return (q);
+ else if (bitset(QSELFREF, q->q_flags))
+ q->q_flags |= a->q_flags & ~QDONTSEND;
+ a = q;
+ goto testselfdestruct;
}
}
@@ -254,12 +287,12 @@ recipient(a, sendq, e)
printf("at trylocaluser %s\n", a->q_user);
if (bitset(QDONTSEND|QBADADDR|QVERIFIED, a->q_flags))
- return (a);
+ goto testselfdestruct;
if (m == InclMailer)
{
a->q_flags |= QDONTSEND;
- if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
+ if (a->q_alias == NULL)
{
a->q_flags |= QBADADDR;
usrerr("550 Cannot mail directly to :include:s");
@@ -274,38 +307,49 @@ recipient(a, sendq, e)
{
#ifdef LOG
if (LogLevel > 2)
- syslog(LOG_ERR, "%s: include %s: transient error: %e",
- e->e_id, a->q_user, errstring(ret));
+ syslog(LOG_ERR, "%s: include %s: transient error: %s",
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ a->q_user, errstring(ret));
#endif
- a->q_flags |= QQUEUEUP|QDONTSEND;
+ a->q_flags |= QQUEUEUP;
+ a->q_flags &= ~QDONTSEND;
usrerr("451 Cannot open %s: %s",
a->q_user, errstring(ret));
}
else if (ret != 0)
{
+ a->q_flags |= QBADADDR;
usrerr("550 Cannot open %s: %s",
a->q_user, errstring(ret));
- a->q_flags |= QBADADDR;
}
}
}
else if (m == FileMailer)
{
- struct stat stb;
extern bool writable();
- p = strrchr(buf, '/');
/* check if writable or creatable */
- if (a->q_alias == NULL && !bitset(EF_QUEUERUN, e->e_flags))
+ if (a->q_alias == NULL)
{
a->q_flags |= QBADADDR;
usrerr("550 Cannot mail directly to files");
}
- else if ((stat(buf, &stb) >= 0) ? (!writable(&stb)) :
- (*p = '\0', safefile(buf, RealUid, TRUE, S_IWRITE|S_IEXEC) != 0))
+ else if (bitset(QBOGUSSHELL, a->q_alias->q_flags))
+ {
+ a->q_flags |= QBADADDR;
+ usrerr("550 User %s@%s doesn't have a valid shell for mailing to files",
+ a->q_alias->q_ruser, MyHostName);
+ }
+ else if (bitset(QUNSAFEADDR, a->q_alias->q_flags))
{
a->q_flags |= QBADADDR;
- giveresponse(EX_CANTCREAT, m, NULL, e);
+ usrerr("550 Address %s is unsafe for mailing to files",
+ a->q_alias->q_paddr);
+ }
+ else if (!writable(buf, getctladdr(a), SFF_ANYFILE))
+ {
+ a->q_flags |= QBADADDR;
+ giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, e);
}
}
@@ -313,7 +357,7 @@ recipient(a, sendq, e)
{
if (!bitset(QDONTSEND, a->q_flags))
e->e_nrcpts++;
- return (a);
+ goto testselfdestruct;
}
/* try aliasing */
@@ -324,29 +368,29 @@ recipient(a, sendq, e)
if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags))
{
extern int udbexpand();
- extern int errno;
if (udbexpand(a, sendq, e) == EX_TEMPFAIL)
{
- a->q_flags |= QQUEUEUP|QDONTSEND;
+ a->q_flags |= QQUEUEUP;
if (e->e_message == NULL)
e->e_message = newstr("Deferred: user database error");
# ifdef LOG
if (LogLevel > 8)
syslog(LOG_INFO, "%s: deferred: udbexpand: %s",
- e->e_id, errstring(errno));
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ errstring(errno));
# endif
message("queued (user database error): %s",
errstring(errno));
e->e_nrcpts++;
- return (a);
+ goto testselfdestruct;
}
}
# endif
/* if it was an alias or a UDB expansion, just return now */
if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags))
- return (a);
+ goto testselfdestruct;
/*
** If we have a level two config file, then pass the name through
@@ -383,7 +427,7 @@ recipient(a, sendq, e)
if (pw == NULL)
{
a->q_flags |= QBADADDR;
- giveresponse(EX_NOUSER, m, NULL, e);
+ giveresponse(EX_NOUSER, m, NULL, a->q_alias, e);
}
else
{
@@ -405,7 +449,10 @@ recipient(a, sendq, e)
(void) strcpy(buf, pw->pw_name);
goto trylocaluser;
}
- a->q_home = newstr(pw->pw_dir);
+ if (strcmp(pw->pw_dir, "/") == 0)
+ a->q_home = "";
+ else
+ a->q_home = newstr(pw->pw_dir);
a->q_uid = pw->pw_uid;
a->q_gid = pw->pw_gid;
a->q_ruser = newstr(pw->pw_name);
@@ -413,12 +460,36 @@ recipient(a, sendq, e)
buildfname(pw->pw_gecos, pw->pw_name, nbuf);
if (nbuf[0] != '\0')
a->q_fullname = newstr(nbuf);
+ if (pw->pw_shell != NULL && pw->pw_shell[0] != '\0' &&
+ !usershellok(pw->pw_shell))
+ {
+ a->q_flags |= QBOGUSSHELL;
+ }
if (!quoted)
forward(a, sendq, e);
}
}
if (!bitset(QDONTSEND, a->q_flags))
e->e_nrcpts++;
+
+ testselfdestruct:
+ if (tTd(26, 8))
+ {
+ printf("testselfdestruct: ");
+ printaddr(a, TRUE);
+ }
+ if (a->q_alias == NULL && a != &e->e_from &&
+ bitset(QDONTSEND, a->q_flags))
+ {
+ q = *sendq;
+ while (q != NULL && bitset(QDONTSEND, q->q_flags))
+ q = q->q_next;
+ if (q == NULL)
+ {
+ a->q_flags |= QBADADDR;
+ usrerr("554 aliasing/forwarding loop broken");
+ }
+ }
return (a);
}
/*
@@ -459,6 +530,17 @@ finduser(name, fuzzyp)
*fuzzyp = FALSE;
+ /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */
+ for (p = name; *p != '\0'; p++)
+ if (!isascii(*p) || !isdigit(*p))
+ break;
+ if (*p == '\0')
+ {
+ if (tTd(29, 4))
+ printf("failed (numeric input)\n");
+ return NULL;
+ }
+
/* look up this login name using fast path */
if ((pw = getpwnam(name)) != NULL)
{
@@ -517,7 +599,9 @@ finduser(name, fuzzyp)
** not writable. This is also enforced by mailfile.
**
** Parameters:
-** s -- pointer to a stat struct for the file.
+** filename -- the file name to check.
+** ctladdr -- the controlling address for this file.
+** flags -- SFF_* flags to control the function.
**
** Returns:
** TRUE -- if we will be able to write this file.
@@ -528,35 +612,98 @@ finduser(name, fuzzyp)
*/
bool
-writable(s)
- register struct stat *s;
+writable(filename, ctladdr, flags)
+ char *filename;
+ ADDRESS *ctladdr;
+ int flags;
{
uid_t euid;
gid_t egid;
int bits;
+ register char *p;
+ char *uname;
+ struct stat stb;
+ extern char RealUserName[];
- if (bitset(0111, s->st_mode))
- return (FALSE);
- euid = RealUid;
- egid = RealGid;
- if (geteuid() == 0)
+ if (tTd(29, 5))
+ printf("writable(%s, %x)\n", filename, flags);
+
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(filename, &stb)
+ : stat(filename, &stb)) < 0)
+#else
+ if (stat(filename, &stb) < 0)
+#endif
+ {
+ /* file does not exist -- see if directory is safe */
+ p = strrchr(filename, '/');
+ if (p == NULL)
+ {
+ errno = ENOTDIR;
+ return FALSE;
+ }
+ *p = '\0';
+ errno = safefile(filename, RealUid, RealGid, RealUserName,
+ SFF_MUSTOWN, S_IWRITE|S_IEXEC);
+ *p = '/';
+ return errno == 0;
+ }
+
+#ifdef SUID_ROOT_FILES_OK
+ /* really ought to be passed down -- and not a good idea */
+ flags |= SFF_ROOTOK;
+#endif
+
+ /*
+ ** File does exist -- check that it is writable.
+ */
+
+ if (bitset(0111, stb.st_mode))
{
- if (bitset(S_ISUID, s->st_mode))
- euid = s->st_uid;
- if (bitset(S_ISGID, s->st_mode))
- egid = s->st_gid;
+ if (tTd(29, 5))
+ printf("failed (mode %o: x bits)\n", stb.st_mode);
+ errno = EPERM;
+ return (FALSE);
}
+ if (ctladdr != NULL && geteuid() == 0)
+ {
+ euid = ctladdr->q_uid;
+ egid = ctladdr->q_gid;
+ uname = ctladdr->q_user;
+ }
+ else
+ {
+ euid = RealUid;
+ egid = RealGid;
+ uname = RealUserName;
+ }
if (euid == 0)
- return (TRUE);
- bits = S_IWRITE;
- if (euid != s->st_uid)
{
- bits >>= 3;
- if (egid != s->st_gid)
- bits >>= 3;
+ euid = DefUid;
+ uname = DefUser;
+ }
+ if (egid == 0)
+ egid = DefGid;
+ if (geteuid() == 0)
+ {
+ if (bitset(S_ISUID, stb.st_mode) &&
+ (stb.st_uid != 0 || bitset(SFF_ROOTOK, flags)))
+ {
+ euid = stb.st_uid;
+ uname = NULL;
+ }
+ if (bitset(S_ISGID, stb.st_mode) &&
+ (stb.st_gid != 0 || bitset(SFF_ROOTOK, flags)))
+ egid = stb.st_gid;
}
- return ((s->st_mode & bits) != 0);
+
+ if (tTd(29, 5))
+ printf("\teu/gid=%d/%d, st_u/gid=%d/%d\n",
+ euid, egid, stb.st_uid, stb.st_gid);
+
+ errno = safefile(filename, euid, egid, uname, flags, S_IWRITE);
+ return errno == 0;
}
/*
** INCLUDE -- handle :include: specification.
@@ -577,9 +724,32 @@ writable(s)
** Side Effects:
** reads the :include: file and sends to everyone
** listed in that file.
+**
+** Security Note:
+** If you have restricted chown (that is, you can't
+** give a file away), it is reasonable to allow programs
+** and files called from this :include: file to be to be
+** run as the owner of the :include: file. This is bogus
+** if there is any chance of someone giving away a file.
+** We assume that pre-POSIX systems can give away files.
+**
+** There is an additional restriction that if you
+** forward to a :include: file, it will not take on
+** the ownership of the :include: file. This may not
+** be necessary, but shouldn't hurt.
*/
static jmp_buf CtxIncludeTimeout;
+static int includetimeout();
+
+#ifndef S_IWOTH
+# define S_IWOTH (S_IWRITE >> 6)
+#endif
+
+#if defined(__FreeBSD__) && defined(_POSIX_CHOWN_RESTRICTED)
+# undef _POSIX_CHOWN_RESTRICTED
+# define _POSIX_CHOWN_RESTRICTED 1
+#endif
int
include(fname, forwarding, ctladdr, sendq, e)
@@ -589,84 +759,184 @@ include(fname, forwarding, ctladdr, sendq, e)
ADDRESS **sendq;
ENVELOPE *e;
{
- register FILE *fp;
+ register FILE *fp = NULL;
char *oldto = e->e_to;
char *oldfilename = FileName;
int oldlinenumber = LineNumber;
register EVENT *ev = NULL;
int nincludes;
- int ret;
- ADDRESS *ca;
- uid_t uid;
+ register ADDRESS *ca;
+ uid_t saveduid, uid;
+ gid_t savedgid, gid;
+ char *uname;
+ int rval = 0;
+ int sfflags = forwarding ? SFF_MUSTOWN : SFF_ANYFILE;
+ struct stat st;
char buf[MAXLINE];
- static int includetimeout();
+#ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED == -1
+# define safechown FALSE
+# else
+# define safechown TRUE
+# endif
+#else
+# ifdef _PC_CHOWN_RESTRICTED
+ bool safechown;
+# else
+# ifdef BSD
+# define safechown TRUE
+# else
+# define safechown FALSE
+# endif
+# endif
+#endif
+ extern bool chownsafe();
if (tTd(27, 2))
printf("include(%s)\n", fname);
+ if (tTd(27, 4))
+ printf(" ruid=%d euid=%d\n", getuid(), geteuid());
if (tTd(27, 14))
{
printf("ctladdr ");
printaddr(ctladdr, FALSE);
}
- /*
- ** If home directory is remote mounted but server is down,
- ** this can hang or give errors; use a timeout to avoid this
- */
+ if (tTd(27, 9))
+ printf("include: old uid = %d/%d\n", getuid(), geteuid());
ca = getctladdr(ctladdr);
if (ca == NULL)
- uid = 0;
+ {
+ uid = DefUid;
+ gid = DefGid;
+ uname = DefUser;
+ saveduid = -1;
+ }
else
+ {
uid = ca->q_uid;
+ gid = ca->q_gid;
+ uname = ca->q_user;
+#ifdef HASSETREUID
+ saveduid = geteuid();
+ savedgid = getegid();
+ if (saveduid == 0)
+ {
+ initgroups(uname, gid);
+ if (uid != 0)
+ (void) setreuid(0, uid);
+ }
+#endif
+ }
+
+ if (tTd(27, 9))
+ printf("include: new uid = %d/%d\n", getuid(), geteuid());
+
+ /*
+ ** If home directory is remote mounted but server is down,
+ ** this can hang or give errors; use a timeout to avoid this
+ */
if (setjmp(CtxIncludeTimeout) != 0)
{
- ctladdr->q_flags |= QQUEUEUP|QDONTSEND;
+ ctladdr->q_flags |= QQUEUEUP;
errno = 0;
- usrerr("451 open timeout on %s", fname);
- return ETIMEDOUT;
+
+ /* return pseudo-error code */
+ rval = EOPENTIMEOUT;
+ goto resetuid;
}
ev = setevent((time_t) 60, includetimeout, 0);
/* the input file must be marked safe */
- if ((ret = safefile(fname, uid, forwarding, S_IREAD)) != 0)
+ rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD);
+ if (rval != 0)
{
- /* don't use this .forward file */
- clrevent(ev);
+ /* don't use this :include: file */
if (tTd(27, 4))
printf("include: not safe (uid=%d): %s\n",
- uid, errstring(ret));
- return ret;
+ uid, errstring(rval));
}
-
- fp = fopen(fname, "r");
- if (fp == NULL)
+ else
{
- int ret = errno;
-
- clrevent(ev);
- return ret;
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ {
+ rval = errno;
+ if (tTd(27, 4))
+ printf("include: open: %s\n", errstring(rval));
+ }
}
+ clrevent(ev);
- if (ca == NULL)
+resetuid:
+
+#ifdef HASSETREUID
+ if (saveduid == 0)
{
- struct stat st;
+ if (uid != 0)
+ if (setreuid(-1, 0) < 0 || setreuid(RealUid, 0) < 0)
+ syserr("setreuid(%d, 0) failure (real=%d, eff=%d)",
+ RealUid, getuid(), geteuid());
+ setgid(savedgid);
+ }
+#endif
- if (fstat(fileno(fp), &st) < 0)
- {
- int ret = errno;
+ if (tTd(27, 9))
+ printf("include: reset uid = %d/%d\n", getuid(), geteuid());
- clrevent(ev);
- syserr("Cannot fstat %s!", fname);
- return ret;
- }
+ if (rval == EOPENTIMEOUT)
+ usrerr("451 open timeout on %s", fname);
+
+ if (fp == NULL)
+ return rval;
+
+ if (fstat(fileno(fp), &st) < 0)
+ {
+ rval = errno;
+ syserr("Cannot fstat %s!", fname);
+ return rval;
+ }
+
+#ifndef safechown
+ safechown = chownsafe(fileno(fp));
+#endif
+ if (ca == NULL && safechown)
+ {
ctladdr->q_uid = st.st_uid;
ctladdr->q_gid = st.st_gid;
ctladdr->q_flags |= QGOODUID;
}
+ if (ca != NULL && ca->q_uid == st.st_uid)
+ {
+ /* optimization -- avoid getpwuid if we already have info */
+ ctladdr->q_flags |= ca->q_flags & QBOGUSSHELL;
+ ctladdr->q_ruser = ca->q_ruser;
+ }
+ else
+ {
+ char *sh;
+ register struct passwd *pw;
- clrevent(ev);
+ sh = "/SENDMAIL/ANY/SHELL/";
+ pw = getpwuid(st.st_uid);
+ if (pw != NULL)
+ {
+ ctladdr->q_ruser = newstr(pw->pw_name);
+ if (safechown)
+ sh = pw->pw_shell;
+ }
+ if (pw == NULL)
+ ctladdr->q_flags |= QBOGUSSHELL;
+ else if(!usershellok(sh))
+ {
+ if (safechown)
+ ctladdr->q_flags |= QBOGUSSHELL;
+ else
+ ctladdr->q_flags |= QUNSAFEADDR;
+ }
+ }
if (bitset(EF_VRFYONLY, e->e_flags))
{
@@ -674,9 +944,22 @@ include(fname, forwarding, ctladdr, sendq, e)
ctladdr->q_flags |= QVERIFIED;
e->e_nrcpts++;
xfclose(fp, "include", fname);
- return 0;
+ return rval;
}
+ /*
+ ** Check to see if some bad guy can write this file
+ **
+ ** This should really do something clever with group
+ ** permissions; currently we just view world writable
+ ** as unsafe. Also, we don't check for writable
+ ** directories in the path. We've got to leave
+ ** something for the local sysad to do.
+ */
+
+ if (bitset(S_IWOTH, st.st_mode))
+ ctladdr->q_flags |= QUNSAFEADDR;
+
/* read the file -- each line is a comma-separated list. */
FileName = fname;
LineNumber = 0;
@@ -697,13 +980,17 @@ include(fname, forwarding, ctladdr, sendq, e)
#ifdef LOG
if (forwarding && LogLevel > 9)
syslog(LOG_INFO, "%s: forward %s => %s",
- e->e_id, oldto, buf);
+ e->e_id == NULL ? "NOQUEUE" : e->e_id,
+ oldto, buf);
#endif
AliasLevel++;
nincludes += sendtolist(buf, ctladdr, sendq, e);
AliasLevel--;
}
+
+ if (ferror(fp) && tTd(27, 3))
+ printf("include: read error: %s\n", errstring(errno));
if (nincludes > 0 && !bitset(QSELFREF, ctladdr->q_flags))
{
if (tTd(27, 5))
@@ -717,7 +1004,8 @@ include(fname, forwarding, ctladdr, sendq, e)
(void) xfclose(fp, "include", fname);
FileName = oldfilename;
LineNumber = oldlinenumber;
- return 0;
+ e->e_to = oldto;
+ return rval;
}
static
@@ -748,7 +1036,7 @@ sendtoargv(argv, e)
while ((p = *argv++) != NULL)
{
- (void) sendtolist(p, (ADDRESS *) NULL, &e->e_sendqueue, e);
+ (void) sendtolist(p, NULLADDR, &e->e_sendqueue, e);
}
}
/*
diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c
index f47fc4e0e8cd..6467defcfdbf 100644
--- a/usr.sbin/sendmail/src/savemail.c
+++ b/usr.sbin/sendmail/src/savemail.c
@@ -33,11 +33,11 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)savemail.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)savemail.c 8.28 (Berkeley) 3/11/94";
#endif /* not lint */
-# include <pwd.h>
# include "sendmail.h"
+# include <pwd.h>
/*
** SAVEMAIL -- Save mail on error
@@ -69,6 +69,10 @@ static char sccsid[] = "@(#)savemail.c 8.3 (Berkeley) 7/13/93";
# define ESM_PANIC 6 /* leave the locked queue/transcript files */
# define ESM_DONE 7 /* the message is successfully delivered */
+# ifndef _PATH_VARTMP
+# define _PATH_VARTMP "/usr/tmp/"
+# endif
+
savemail(e)
register ENVELOPE *e;
@@ -77,16 +81,19 @@ savemail(e)
register FILE *fp;
int state;
auto ADDRESS *q = NULL;
+ register char *p;
+ MCI mcibuf;
char buf[MAXLINE+1];
extern struct passwd *getpwnam();
- register char *p;
extern char *ttypath();
typedef int (*fnptr)();
+ extern bool writable();
if (tTd(6, 1))
{
- printf("\nsavemail, errormode = %c, id = %s\n e_from=",
- e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id);
+ printf("\nsavemail, errormode = %c, id = %s, ExitStat = %d\n e_from=",
+ e->e_errormode, e->e_id == NULL ? "NONE" : e->e_id,
+ ExitStat);
printaddr(&e->e_from, FALSE);
}
@@ -96,8 +103,6 @@ savemail(e)
return;
}
- e->e_flags &= ~EF_FATALERRS;
-
/*
** In the unhappy event we don't know who to return the mail
** to, make someone up.
@@ -106,7 +111,8 @@ savemail(e)
if (e->e_from.q_paddr == NULL)
{
e->e_sender = "Postmaster";
- if (parseaddr(e->e_sender, &e->e_from, 0, '\0', NULL, e) == NULL)
+ if (parseaddr(e->e_sender, &e->e_from,
+ RF_COPYPARSE|RF_SENDERADDR, '\0', NULL, e) == NULL)
{
syserr("553 Cannot parse Postmaster!");
ExitStat = EX_SOFTWARE;
@@ -238,33 +244,48 @@ savemail(e)
** joe@x, which gives a response, etc. Also force
** the mail to be delivered even if a version of
** it has already been sent to the sender.
+ **
+ ** If this is a configuration or local software
+ ** error, send to the local postmaster as well,
+ ** since the originator can't do anything
+ ** about it anyway. Note that this is a full
+ ** copy of the message (intentionally) so that
+ ** the Postmaster can forward things along.
*/
+ if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE)
+ {
+ (void) sendtolist("postmaster",
+ NULLADDR, &e->e_errorqueue, e);
+ }
if (strcmp(e->e_from.q_paddr, "<>") != 0)
+ {
(void) sendtolist(e->e_from.q_paddr,
- (ADDRESS *) NULL,
- &e->e_errorqueue, e);
+ NULLADDR, &e->e_errorqueue, e);
+ }
- /* deliver a cc: to the postmaster if desired */
- if (PostMasterCopy != NULL)
- {
- auto ADDRESS *rlist = NULL;
+ /*
+ ** Deliver a non-delivery report to the
+ ** Postmaster-designate (not necessarily
+ ** Postmaster). This does not include the
+ ** body of the message, for privacy reasons.
+ ** You really shouldn't need this.
+ */
- (void) sendtolist(PostMasterCopy,
- (ADDRESS *) NULL,
- &rlist, e);
- (void) returntosender(e->e_message,
- rlist, FALSE, e);
- }
- q = e->e_errorqueue;
+ e->e_flags |= EF_PM_NOTIFY;
+
+ /* check to see if there are any good addresses */
+ for (q = e->e_errorqueue; q != NULL; q = q->q_next)
+ if (!bitset(QBADADDR|QDONTSEND, q->q_flags))
+ break;
if (q == NULL)
{
/* this is an error-error */
state = ESM_POSTMASTER;
break;
}
- if (returntosender(e->e_message,
- q, (e->e_class >= 0), e) == 0)
+ if (returntosender(e->e_message, e->e_errorqueue,
+ (e->e_class >= 0), e) == 0)
{
state = ESM_DONE;
break;
@@ -335,7 +356,9 @@ savemail(e)
e->e_to = buf;
q = NULL;
(void) sendtolist(buf, &e->e_from, &q, e);
- if (deliver(e, q) == 0)
+ if (q != NULL &&
+ !bitset(QBADADDR, q->q_flags) &&
+ deliver(e, q) == 0)
state = ESM_DONE;
else
state = ESM_MAIL;
@@ -358,19 +381,31 @@ savemail(e)
break;
}
- fp = dfopen("/usr/tmp/dead.letter",
- O_WRONLY|O_CREAT|O_APPEND, FileMode);
+ strcpy(buf, _PATH_VARTMP);
+ strcat(buf, "dead.letter");
+ if (!writable(buf, NULLADDR, SFF_NOSLINK))
+ {
+ state = ESM_PANIC;
+ break;
+ }
+ fp = dfopen(buf, O_WRONLY|O_CREAT|O_APPEND, FileMode);
if (fp == NULL)
{
state = ESM_PANIC;
break;
}
- putfromline(fp, FileMailer, e);
- (*e->e_puthdr)(fp, FileMailer, e);
- putline("\n", fp, FileMailer);
- (*e->e_putbody)(fp, FileMailer, e, NULL);
- putline("\n", fp, FileMailer);
+ bzero(&mcibuf, sizeof mcibuf);
+ mcibuf.mci_out = fp;
+ mcibuf.mci_mailer = FileMailer;
+ if (bitnset(M_7BITS, FileMailer->m_flags))
+ mcibuf.mci_flags |= MCIF_7BIT;
+
+ putfromline(&mcibuf, e);
+ (*e->e_puthdr)(&mcibuf, e);
+ putline("\n", &mcibuf);
+ (*e->e_putbody)(&mcibuf, e, NULL);
+ putline("\n", &mcibuf);
(void) fflush(fp);
state = ferror(fp) ? ESM_PANIC : ESM_DONE;
(void) xfclose(fp, "savemail", "/usr/tmp/dead.letter");
@@ -383,8 +418,7 @@ savemail(e)
case ESM_PANIC:
/* leave the locked queue & transcript files around */
- syserr("554 savemail: cannot save rejected email anywhere");
- exit(EX_SOFTWARE);
+ syserr("!554 savemail: cannot save rejected email anywhere");
}
}
}
@@ -450,6 +484,7 @@ returntosender(msg, returnq, sendbody, e)
SendBody = sendbody;
define('g', e->e_from.q_paddr, e);
+ define('u', NULL, e);
ee = newenvelope(&errenvelope, e);
define('a', "\201b", ee);
define('r', "internal", ee);
@@ -457,12 +492,14 @@ returntosender(msg, returnq, sendbody, e)
define('_', "localhost", ee);
ee->e_puthdr = putheader;
ee->e_putbody = errbody;
- ee->e_flags |= EF_RESPONSE;
+ ee->e_flags |= EF_RESPONSE|EF_METOO;
if (!bitset(EF_OLDSTYLE, e->e_flags))
ee->e_flags &= ~EF_OLDSTYLE;
ee->e_sendqueue = returnq;
- ee->e_msgsize = e->e_msgsize + ERRORFUDGE;
- openxscript(ee);
+ ee->e_msgsize = ERRORFUDGE;
+ if (!NoReturn)
+ ee->e_msgsize += e->e_msgsize;
+ initsys(ee);
for (q = returnq; q != NULL; q = q->q_next)
{
if (bitset(QBADADDR, q->q_flags))
@@ -472,7 +509,7 @@ returntosender(msg, returnq, sendbody, e)
ee->e_nrcpts++;
if (!DontPruneRoutes && pruneroute(q->q_paddr))
- parseaddr(q->q_paddr, q, 0, '\0', NULL, e);
+ parseaddr(q->q_paddr, q, RF_COPYPARSE, '\0', NULL, e);
if (q->q_alias == NULL)
addheader("To", q->q_paddr, ee);
@@ -499,7 +536,7 @@ returntosender(msg, returnq, sendbody, e)
/* fake up an address header for the from person */
expand("\201n", buf, &buf[sizeof buf - 1], e);
- if (parseaddr(buf, &ee->e_from, 1, '\0', NULL, e) == NULL)
+ if (parseaddr(buf, &ee->e_from, RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL)
{
syserr("553 Can't parse myself!");
ExitStat = EX_SOFTWARE;
@@ -515,7 +552,7 @@ returntosender(msg, returnq, sendbody, e)
eatheader(ee, TRUE);
/* mark statistics */
- markstats(ee, (ADDRESS *) NULL);
+ markstats(ee, NULLADDR);
/* actually deliver the error message */
sendall(ee, SM_DEFAULT);
@@ -535,8 +572,7 @@ returntosender(msg, returnq, sendbody, e)
** original offending message.
**
** Parameters:
-** fp -- the output file.
-** m -- the mailer to output to.
+** mci -- the mailer connection information.
** e -- the envelope we are working in.
**
** Returns:
@@ -546,9 +582,8 @@ returntosender(msg, returnq, sendbody, e)
** Outputs the body of an error message.
*/
-errbody(fp, m, e)
- register FILE *fp;
- register struct mailer *m;
+errbody(mci, e)
+ register MCI *mci;
register ENVELOPE *e;
{
register FILE *xfile;
@@ -560,7 +595,7 @@ errbody(fp, m, e)
if (e->e_parent == NULL)
{
syserr("errbody: null parent");
- putline(" ----- Original message lost -----\n", fp, m);
+ putline(" ----- Original message lost -----\n", mci);
return;
}
@@ -570,12 +605,39 @@ errbody(fp, m, e)
if (e->e_msgboundary != NULL)
{
- putline("This is a MIME-encapsulated message", fp, m);
- putline("", fp, m);
+ putline("This is a MIME-encapsulated message", mci);
+ putline("", mci);
(void) sprintf(buf, "--%s", e->e_msgboundary);
- putline(buf, fp, m);
- putline("", fp, m);
+ putline(buf, mci);
+ putline("", mci);
+ }
+
+ /*
+ ** Output introductory information.
+ */
+
+ for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
+ if (bitset(QBADADDR, q->q_flags))
+ break;
+ if (q == NULL &&
+ !bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
+ {
+ putline(" **********************************************",
+ mci);
+ putline(" ** THIS IS A WARNING MESSAGE ONLY **",
+ mci);
+ putline(" ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **",
+ mci);
+ putline(" **********************************************",
+ mci);
+ putline("", mci);
}
+ sprintf(buf, "The original message was received at %s",
+ arpadate(ctime(&e->e_parent->e_ctime)));
+ putline(buf, mci);
+ expand("from \201_", buf, &buf[sizeof buf - 1], e->e_parent);
+ putline(buf, mci);
+ putline("", mci);
/*
** Output error message header (if specified and available).
@@ -591,17 +653,17 @@ errbody(fp, m, e)
while (fgets(buf, sizeof buf, xfile) != NULL)
{
expand(buf, buf, &buf[sizeof buf - 1], e);
- putline(buf, fp, m);
+ putline(buf, mci);
}
(void) fclose(xfile);
- putline("\n", fp, m);
+ putline("\n", mci);
}
}
else
{
expand(ErrMsgFile, buf, &buf[sizeof buf - 1], e);
- putline(buf, fp, m);
- putline("", fp, m);
+ putline(buf, mci);
+ putline("", mci);
}
}
@@ -617,22 +679,26 @@ errbody(fp, m, e)
if (printheader)
{
putline(" ----- The following addresses had delivery problems -----",
- fp, m);
+ mci);
printheader = FALSE;
}
- if (q->q_alias != NULL)
- strcpy(buf, q->q_alias->q_paddr);
- else
- strcpy(buf, q->q_paddr);
+ strcpy(buf, q->q_paddr);
if (bitset(QBADADDR, q->q_flags))
- strcat(buf, " (hard error -- address deleted)");
+ strcat(buf, " (unrecoverable error)");
else
- strcat(buf, " (temporary failure -- will retry)");
- putline(buf, fp, m);
+ strcat(buf, " (transient failure)");
+ putline(buf, mci);
+ if (q->q_alias != NULL)
+ {
+ strcpy(buf, " (expanded from: ");
+ strcat(buf, q->q_alias->q_paddr);
+ strcat(buf, ")");
+ putline(buf, mci);
+ }
}
}
if (!printheader)
- putline("\n", fp, m);
+ putline("\n", mci);
/*
** Output transcript of errors
@@ -643,15 +709,15 @@ errbody(fp, m, e)
if ((xfile = fopen(p, "r")) == NULL)
{
syserr("Cannot open %s", p);
- putline(" ----- Transcript of session is unavailable -----\n", fp, m);
+ putline(" ----- Transcript of session is unavailable -----\n", mci);
}
else
{
- putline(" ----- Transcript of session follows -----\n", fp, m);
+ putline(" ----- Transcript of session follows -----\n", mci);
if (e->e_xfp != NULL)
(void) fflush(e->e_xfp);
while (fgets(buf, sizeof buf, xfile) != NULL)
- putline(buf, fp, m);
+ putline(buf, mci);
(void) xfclose(xfile, "errbody xscript", p);
}
errno = 0;
@@ -662,42 +728,42 @@ errbody(fp, m, e)
if (NoReturn)
SendBody = FALSE;
- putline("", fp, m);
+ putline("", mci);
if (e->e_parent->e_df != NULL)
{
if (SendBody)
- putline(" ----- Unsent message follows -----\n", fp, m);
+ putline(" ----- Original message follows -----\n", mci);
else
- putline(" ----- Message header follows -----\n", fp, m);
- (void) fflush(fp);
+ putline(" ----- Message header follows -----\n", mci);
+ (void) fflush(mci->mci_out);
if (e->e_msgboundary != NULL)
{
- putline("", fp, m);
+ putline("", mci);
(void) sprintf(buf, "--%s", e->e_msgboundary);
- putline(buf, fp, m);
- putline("Content-Type: message/rfc822", fp, m);
- putline("", fp, m);
+ putline(buf, mci);
+ putline("Content-Type: message/rfc822", mci);
+ putline("", mci);
}
- putheader(fp, m, e->e_parent);
- putline("", fp, m);
+ putheader(mci, e->e_parent);
+ putline("", mci);
if (SendBody)
- putbody(fp, m, e->e_parent, e->e_msgboundary);
+ putbody(mci, e->e_parent, e->e_msgboundary);
else
- putline(" ----- Message body suppressed -----", fp, m);
+ putline(" ----- Message body suppressed -----", mci);
}
else
{
- putline(" ----- No message was collected -----\n", fp, m);
+ putline(" ----- No message was collected -----\n", mci);
}
if (e->e_msgboundary != NULL)
{
- putline("", fp, m);
+ putline("", mci);
(void) sprintf(buf, "--%s--", e->e_msgboundary);
- putline(buf, fp, m);
+ putline(buf, mci);
}
- putline("", fp, m);
+ putline("", mci);
/*
** Cleanup and exit
@@ -726,7 +792,7 @@ errbody(fp, m, e)
pruneroute(addr)
char *addr;
{
-#ifdef NAMED_BIND
+#if NAMED_BIND
char *start, *at, *comma;
char c;
int rcode;
diff --git a/usr.sbin/sendmail/src/sendmail.8 b/usr.sbin/sendmail/src/sendmail.8
index c2e067885990..ee0f700d83a0 100644
--- a/usr.sbin/sendmail/src/sendmail.8
+++ b/usr.sbin/sendmail/src/sendmail.8
@@ -29,9 +29,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)sendmail.8 8.2 (Berkeley) 7/11/93
+.\" @(#)sendmail.8 8.4 (Berkeley) 12/11/93
.\"
-.Dd July 11, 1993
+.Dd December 11, 1993
.Dt SENDMAIL 8
.Os BSD 4
.Sh NAME
@@ -132,16 +132,14 @@ it is used for debugging configuration tables.
Verify names only \- do not try to collect or deliver a message.
Verify mode is normally used for validating
users or mailing lists.
-.It Fl bz
-Create the configuration freeze file.
.It Fl C Ns Ar file
Use alternate configuration file.
.Nm Sendmail
refuses to run as root if an alternate configuration file is specified.
-The frozen configuration file is bypassed.
.It Fl d Ns Ar X
Set debugging value to
.Ar X .
+.ne 1i
.It Fl F Ns Ar fullname
Set the full name of the sender.
.It Fl f Ns Ar name
@@ -463,8 +461,6 @@ raw data for alias names
data base of alias names
.It Pa /etc/sendmail.cf
configuration file
-.It Pa /etc/sendmail.fc
-frozen configuration
.It Pa /etc/sendmail.hf
help file
.It Pa /var/log/sendmail.st
@@ -491,12 +487,12 @@ Internet Request For Comments
.Rs
.%T "Sendmail \- An Internetwork Mail Router"
.%V SMM
-.%N \&No. 16
+.%N \&No. 9
.Re
.Rs
.%T "Sendmail Installation and Operation Guide"
.%V SMM
-.%N \&No. 7
+.%N \&No. 8
.Re
.Sh HISTORY
The
diff --git a/usr.sbin/sendmail/src/sendmail.h b/usr.sbin/sendmail/src/sendmail.h
index ef9107eae781..ca6af5fef143 100644
--- a/usr.sbin/sendmail/src/sendmail.h
+++ b/usr.sbin/sendmail/src/sendmail.h
@@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)sendmail.h 8.3 (Berkeley) 7/13/93
+ * @(#)sendmail.h 8.41 (Berkeley) 2/6/94
*/
/*
@@ -41,7 +41,7 @@
# ifdef _DEFINE
# define EXTERN
# ifndef lint
-static char SmailSccsId[] = "@(#)sendmail.h 8.3 7/13/93";
+static char SmailSccsId[] = "@(#)sendmail.h 8.41 2/6/94";
# endif
# else /* _DEFINE */
# define EXTERN extern
@@ -68,6 +68,9 @@ static char SmailSccsId[] = "@(#)sendmail.h 8.3 7/13/93";
# ifdef DAEMON
# include <sys/socket.h>
# endif
+# ifdef NETUNIX
+# include <sys/un.h>
+# endif
# ifdef NETINET
# include <netinet/in.h>
# endif
@@ -147,6 +150,10 @@ typedef struct address ADDRESS;
# define QSELFREF 000200 /* this address references itself */
# define QVERIFIED 000400 /* verified, but not expanded */
# define QREPORT 001000 /* report this address in return message */
+# define QBOGUSSHELL 002000 /* this entry has an invalid shell listed */
+# define QUNSAFEADDR 004000 /* address aquired through an unsafe path */
+
+# define NULLADDR ((ADDRESS *) NULL)
/*
** Mailer definition structure.
** Every mailer known to the system is declared in this
@@ -190,14 +197,14 @@ typedef struct mailer MAILER;
/* 'F' /* CF: include From: or Resent-From: */
# define M_NO_NULL_FROM 'g' /* sender of errors should be $g */
# define M_HST_UPPER 'h' /* preserve host case distinction */
- /* 'H' /* UIUC: MAIL11V3: preview headers */
+# define M_PREHEAD 'H' /* MAIL11V3: preview headers */
# define M_INTERNAL 'I' /* SMTP to another sendmail site */
# define M_LOCALMAILER 'l' /* delivery is to this host */
# define M_LIMITS 'L' /* must enforce SMTP line limits */
# define M_MUSER 'm' /* can handle multiple users at once */
/* 'M' /* CF: include Message-Id: */
# define M_NHDR 'n' /* don't insert From line */
- /* 'N' /* UIUC: MAIL11V3: DATA returns multi-status */
+# define M_MANYSTATUS 'N' /* MAIL11V3: DATA returns multi-status */
# define M_FROMPATH 'p' /* use reverse-path in MAIL FROM: */
/* 'P' /* CF: include Return-Path: */
# define M_ROPT 'r' /* mailer takes picky -r flag */
@@ -261,6 +268,50 @@ extern struct hdrinfo HdrInfo[];
# define H_RECEIPTTO 02000 /* this field has return receipt info */
# define H_ERRORSTO 04000 /* this field has error address info */
/*
+** Information about currently open connections to mailers, or to
+** hosts that we have looked up recently.
+*/
+
+# define MCI struct mailer_con_info
+
+MCI
+{
+ short mci_flags; /* flag bits, see below */
+ short mci_errno; /* error number on last connection */
+ short mci_herrno; /* h_errno from last DNS lookup */
+ short mci_exitstat; /* exit status from last connection */
+ short mci_state; /* SMTP state */
+ long mci_maxsize; /* max size this server will accept */
+ FILE *mci_in; /* input side of connection */
+ FILE *mci_out; /* output side of connection */
+ int mci_pid; /* process id of subordinate proc */
+ char *mci_phase; /* SMTP phase string */
+ struct mailer *mci_mailer; /* ptr to the mailer for this conn */
+ char *mci_host; /* host name */
+ time_t mci_lastuse; /* last usage time */
+};
+
+
+/* flag bits */
+#define MCIF_VALID 000001 /* this entry is valid */
+#define MCIF_TEMP 000002 /* don't cache this connection */
+#define MCIF_CACHED 000004 /* currently in open cache */
+#define MCIF_ESMTP 000010 /* this host speaks ESMTP */
+#define MCIF_EXPN 000020 /* EXPN command supported */
+#define MCIF_SIZE 000040 /* SIZE option supported */
+#define MCIF_8BITMIME 000100 /* BODY=8BITMIME supported */
+#define MCIF_7BIT 000200 /* strip this message to 7 bits */
+#define MCIF_MULTSTAT 000400 /* MAIL11V3: handles MULT status */
+
+/* states */
+#define MCIS_CLOSED 0 /* no traffic on this connection */
+#define MCIS_OPENING 1 /* sending initial protocol */
+#define MCIS_OPEN 2 /* open, initial protocol sent */
+#define MCIS_ACTIVE 3 /* message being sent */
+#define MCIS_QUITING 4 /* running quit protocol */
+#define MCIS_SSD 5 /* service shutting down */
+#define MCIS_ERROR 6 /* I/O error on connection */
+ /*
** Envelope structure.
** This structure defines the message itself. There is usually
** only one of these -- for the message that we originally read
@@ -284,16 +335,16 @@ ENVELOPE
ADDRESS *e_sendqueue; /* list of message recipients */
ADDRESS *e_errorqueue; /* the queue for error responses */
long e_msgsize; /* size of the message in bytes */
+ long e_flags; /* flags, see below */
int e_nrcpts; /* number of recipients */
short e_class; /* msg class (priority, junk, etc.) */
- short e_flags; /* flags, see below */
short e_hopcount; /* number of times processed */
short e_nsent; /* number of sends since checkpoint */
short e_sendmode; /* message send mode */
short e_errormode; /* error return mode */
- int (*e_puthdr)__P((FILE *, MAILER *, ENVELOPE *));
+ int (*e_puthdr)__P((MCI *, ENVELOPE *));
/* function to put header of message */
- int (*e_putbody)__P((FILE *, MAILER *, ENVELOPE *, char *));
+ int (*e_putbody)__P((MCI *, ENVELOPE *, char *));
/* function to put body of message */
struct envelope *e_parent; /* the message this one encloses */
struct envelope *e_sibling; /* the next envelope of interest */
@@ -306,22 +357,26 @@ ENVELOPE
char *e_message; /* error message */
char *e_statmsg; /* stat msg (changes per delivery) */
char *e_msgboundary; /* MIME-style message part boundary */
+ char *e_origrcpt; /* original recipient (one only) */
char *e_macro[128]; /* macro definitions */
};
/* values for e_flags */
-#define EF_OLDSTYLE 000001 /* use spaces (not commas) in hdrs */
-#define EF_INQUEUE 000002 /* this message is fully queued */
-#define EF_TIMEOUT 000004 /* this message is too old */
-#define EF_CLRQUEUE 000010 /* disk copy is no longer needed */
-#define EF_SENDRECEIPT 000020 /* send a return receipt */
-#define EF_FATALERRS 000040 /* fatal errors occured */
-#define EF_KEEPQUEUE 000100 /* keep queue files always */
-#define EF_RESPONSE 000200 /* this is an error or return receipt */
-#define EF_RESENT 000400 /* this message is being forwarded */
-#define EF_VRFYONLY 001000 /* verify only (don't expand aliases) */
-#define EF_WARNING 002000 /* warning message has been sent */
-#define EF_QUEUERUN 004000 /* this envelope is from queue */
+#define EF_OLDSTYLE 0x0000001 /* use spaces (not commas) in hdrs */
+#define EF_INQUEUE 0x0000002 /* this message is fully queued */
+#define EF_CLRQUEUE 0x0000008 /* disk copy is no longer needed */
+#define EF_SENDRECEIPT 0x0000010 /* send a return receipt */
+#define EF_FATALERRS 0x0000020 /* fatal errors occured */
+#define EF_KEEPQUEUE 0x0000040 /* keep queue files always */
+#define EF_RESPONSE 0x0000080 /* this is an error or return receipt */
+#define EF_RESENT 0x0000100 /* this message is being forwarded */
+#define EF_VRFYONLY 0x0000200 /* verify only (don't expand aliases) */
+#define EF_WARNING 0x0000400 /* warning message has been sent */
+#define EF_QUEUERUN 0x0000800 /* this envelope is from queue */
+#define EF_GLOBALERRS 0x0001000 /* treat errors as global */
+#define EF_PM_NOTIFY 0x0002000 /* send return mail to postmaster */
+#define EF_METOO 0x0004000 /* send to me too */
+#define EF_LOGSENDER 0x0008000 /* need to log the sender */
EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */
/*
@@ -415,51 +470,9 @@ EXTERN struct rewrite *RewriteRules[MAXRWSETS];
struct metamac
{
char metaname; /* external code (after $) */
- char metaval; /* internal code (as above) */
+ u_char metaval; /* internal code (as above) */
};
/*
-** Information about currently open connections to mailers, or to
-** hosts that we have looked up recently.
-*/
-
-# define MCI struct mailer_con_info
-
-MCI
-{
- short mci_flags; /* flag bits, see below */
- short mci_errno; /* error number on last connection */
- short mci_herrno; /* h_errno from last DNS lookup */
- short mci_exitstat; /* exit status from last connection */
- short mci_state; /* SMTP state */
- long mci_maxsize; /* max size this server will accept */
- FILE *mci_in; /* input side of connection */
- FILE *mci_out; /* output side of connection */
- int mci_pid; /* process id of subordinate proc */
- char *mci_phase; /* SMTP phase string */
- struct mailer *mci_mailer; /* ptr to the mailer for this conn */
- char *mci_host; /* host name */
- time_t mci_lastuse; /* last usage time */
-};
-
-
-/* flag bits */
-#define MCIF_VALID 000001 /* this entry is valid */
-#define MCIF_TEMP 000002 /* don't cache this connection */
-#define MCIF_CACHED 000004 /* currently in open cache */
-#define MCIF_ESMTP 000010 /* this host speaks ESMTP */
-#define MCIF_EXPN 000020 /* EXPN command supported */
-#define MCIF_SIZE 000040 /* SIZE option supported */
-#define MCIF_8BITMIME 000100 /* BODY=8BITMIME supported */
-
-/* states */
-#define MCIS_CLOSED 0 /* no traffic on this connection */
-#define MCIS_OPENING 1 /* sending initial protocol */
-#define MCIS_OPEN 2 /* open, initial protocol sent */
-#define MCIS_ACTIVE 3 /* message being sent */
-#define MCIS_QUITING 4 /* running quit protocol */
-#define MCIS_SSD 5 /* service shutting down */
-#define MCIS_ERROR 6 /* I/O error on connection */
- /*
** Name canonification short circuit.
**
** If the name server for a host is down, the process of trying to
@@ -503,11 +516,12 @@ MAP
char *map_mname; /* name of this map */
int map_mflags; /* flags, see below */
char *map_file; /* the (nominal) filename */
- void *map_db1; /* the open database ptr */
- void *map_db2; /* an "extra" database pointer */
+ ARBPTR_T map_db1; /* the open database ptr */
+ ARBPTR_T map_db2; /* an "extra" database pointer */
char *map_app; /* to append to successful matches */
char *map_domain; /* the (nominal) NIS domain */
char *map_rebuild; /* program to run to do auto-rebuild */
+ time_t map_mtime; /* last database modification time */
};
/* bit values for map_flags */
@@ -521,6 +535,8 @@ MAP
# define MF_ALIAS 0x0080 /* this is an alias file */
# define MF_TRY0NULL 0x0100 /* try with no null byte */
# define MF_TRY1NULL 0x0200 /* try with the null byte */
+# define MF_LOCKED 0x0400 /* this map is currently locked */
+# define MF_ALIASWAIT 0x0800 /* alias map in aliaswait state */
# define MF_IMPL_HASH 0x1000 /* implicit: underlying hash database */
# define MF_IMPL_NDBM 0x2000 /* implicit: underlying NDBM database */
@@ -645,6 +661,7 @@ EXTERN char OpMode; /* operation mode, see below */
#define MD_DELIVER 'm' /* be a mail sender */
#define MD_SMTP 's' /* run SMTP on standard input */
+#define MD_ARPAFTP 'a' /* obsolete ARPANET mode (Grey Book) */
#define MD_DAEMON 'd' /* run as a daemon */
#define MD_VERIFY 'v' /* verify: don't collect or deliver */
#define MD_TEST 't' /* test mode: resolve addrs only */
@@ -675,10 +692,6 @@ EXTERN char OpMode; /* operation mode, see below */
*/
-/* Offset used to ensure that name server error * codes are unique */
-#define MAX_ERRNO 100
-
-
/*
** Privacy flags
** These are bit values for the PrivacyFlags word.
@@ -691,7 +704,8 @@ EXTERN char OpMode; /* operation mode, see below */
#define PRIV_NOEXPN 00010 /* disallow EXPN command entirely */
#define PRIV_NOVRFY 00020 /* disallow VRFY command entirely */
#define PRIV_AUTHWARNINGS 00040 /* flag possible authorization probs */
-#define PRIV_RESTRMAILQ 01000 /* restrict mailq command */
+#define PRIV_RESTRICTMAILQ 01000 /* restrict mailq command */
+#define PRIV_RESTRICTQRUN 02000 /* restrict queue run */
#define PRIV_GOAWAY 00777 /* don't give no info, anyway, anyhow */
/* struct defining such things */
@@ -703,13 +717,27 @@ struct prival
/*
-** Flags passed to remotename
+** Flags passed to remotename, parseaddr, allocaddr, and buildaddr.
*/
#define RF_SENDERADDR 0001 /* this is a sender address */
#define RF_HEADERADDR 0002 /* this is a header address */
#define RF_CANONICAL 0004 /* strip comment information */
#define RF_ADDDOMAIN 0010 /* OK to do domain extension */
+#define RF_COPYPARSE 0020 /* copy parsed user & host */
+#define RF_COPYPADDR 0040 /* copy print address */
+#define RF_COPYALL (RF_COPYPARSE|RF_COPYPADDR)
+#define RF_COPYNONE 0
+
+
+/*
+** Flags passed to safefile.
+*/
+
+#define SFF_ANYFILE 0 /* no special restrictions */
+#define SFF_MUSTOWN 0x0001 /* user must own this file */
+#define SFF_NOSLINK 0x0002 /* file cannot be a symbolic link */
+#define SFF_ROOTOK 0x0004 /* ok for root to own this file */
/*
@@ -720,6 +748,9 @@ struct prival
union bigsockaddr
{
struct sockaddr sa; /* general version */
+#ifdef NETUNIX
+ struct sockaddr_un sunix; /* UNIX family */
+#endif
#ifdef NETINET
struct sockaddr_in sin; /* INET family */
#endif
@@ -735,7 +766,6 @@ union bigsockaddr
};
#define SOCKADDR union bigsockaddr
-
/*
** Global variables.
*/
@@ -757,7 +787,7 @@ EXTERN bool CheckAliases; /* parse addresses during newaliases */
EXTERN bool NoAlias; /* suppress aliasing */
EXTERN bool UseNameServer; /* use internet domain name server */
EXTERN bool SevenBit; /* force 7-bit data */
-EXTERN int SafeAlias; /* minutes to wait until @:@ in alias file */
+EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */
EXTERN FILE *InChannel; /* input connection */
EXTERN FILE *OutChannel; /* output connection */
EXTERN uid_t RealUid; /* when Daemon, real uid of caller */
@@ -793,10 +823,13 @@ EXTERN bool LogUsrErrs; /* syslog user errors (e.g., SMTP RCPT cmd) */
EXTERN bool SendMIMEErrors; /* send error messages in MIME format */
EXTERN bool MatchGecos; /* look for user names in gecos field */
EXTERN bool UseErrorsTo; /* use Errors-To: header (back compat) */
+EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */
+extern bool CheckLoopBack; /* check for loopback on HELO packet */
+EXTERN bool InChild; /* true if running in an SMTP subprocess */
+EXTERN bool DisConnected; /* running with OutChannel redirected to xf */
EXTERN char SpaceSub; /* substitution for <lwsp> */
EXTERN int PrivacyFlags; /* privacy flags */
-extern char *ConfFile; /* location of configuration file [conf.c] */
-extern char *FreezeFile; /* location of frozen memory image [conf.c] */
+EXTERN char *ConfFile; /* location of configuration file [conf.c] */
extern char *PidFile; /* location of proc id file [conf.c] */
extern ADDRESS NullAddress; /* a null (template) address [main.c] */
EXTERN long WkClassFact; /* multiplier for message class -> priority */
@@ -813,12 +846,14 @@ EXTERN long MaxMessageSize; /* advertised max size we will accept */
EXTERN char *PostMasterCopy; /* address to get errs cc's */
EXTERN int CheckpointInterval; /* queue file checkpoint interval */
EXTERN bool DontPruneRoutes; /* don't prune source routes */
+extern bool BrokenSmtpPeers; /* peers can't handle 2-line greeting */
EXTERN int MaxMciCache; /* maximum entries in MCI cache */
EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */
EXTERN char *QueueLimitRecipient; /* limit queue runs to this recipient */
EXTERN char *QueueLimitSender; /* limit queue runs to this sender */
EXTERN char *QueueLimitId; /* limit queue runs to this id */
EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
+extern int errno;
/*
@@ -829,6 +864,7 @@ EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
EXTERN struct
{
+ /* RFC 1123-specified timeouts [minimum value] */
time_t to_initial; /* initial greeting timeout [5m] */
time_t to_mail; /* MAIL command [5m] */
time_t to_rcpt; /* RCPT command [5m] */
@@ -841,6 +877,7 @@ EXTERN struct
time_t to_helo; /* HELO command */
time_t to_quit; /* QUIT command */
time_t to_miscshort; /* misc short commands (NOOP, VERB, etc) */
+ time_t to_ident; /* IDENT protocol requests */
/* following are per message */
time_t to_q_return; /* queue return timeout */
time_t to_q_warning; /* queue warning timeout */
@@ -894,7 +931,8 @@ extern const char *errstring __P((int));
extern void expand __P((char *, char *, char *, ENVELOPE *));
extern void define __P((int, char *, ENVELOPE *));
extern char *macvalue __P((int, ENVELOPE *));
-extern char **prescan __P((char *, int, char[], char **));
+extern char **prescan __P((char *, int, char[], int, char **));
+extern int rewrite __P((char **, int, int, ENVELOPE *));
extern char *fgetfolded __P((char *, int, FILE *));
extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, ENVELOPE *));
extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *));
@@ -908,10 +946,14 @@ extern ADDRESS *getctladdr __P((ADDRESS *));
extern char *anynet_ntoa __P((SOCKADDR *));
extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *));
extern bool shouldqueue __P((long, time_t));
-extern bool lockfile __P((int, char *, int));
+extern bool lockfile __P((int, char *, char *, int));
extern char *hostsignature __P((MAILER *, char *, ENVELOPE *));
extern void openxscript __P((ENVELOPE *));
extern void closexscript __P((ENVELOPE *));
+extern sigfunc_t setsignal __P((int, sigfunc_t));
+extern char *shortenstring __P((char *, int));
+extern bool usershellok __P((char *));
+extern void commaize __P((HDR *, char *, int, MCI *, ENVELOPE *));
/* ellipsis is a different case though */
#ifdef __STDC__
diff --git a/usr.sbin/sendmail/src/sendmail.hf b/usr.sbin/sendmail/src/sendmail.hf
index ff208bad7d99..142a7f577054 100644
--- a/usr.sbin/sendmail/src/sendmail.hf
+++ b/usr.sbin/sendmail/src/sendmail.hf
@@ -3,7 +3,7 @@ cpyr Copyright (c) 1983 Eric P. Allman
cpyr Copyright (c) 1988, 1993
cpyr The Regents of the University of California. All rights reserved.
cpyr
-cpyr @(#)sendmail.hf 8.1 (Berkeley) 6/7/93
+cpyr @(#)sendmail.hf 8.2 (Berkeley) 7/16/93
cpyr
smtp Commands:
smtp HELO EHLO MAIL RCPT DATA
@@ -16,8 +16,7 @@ smtp For local information send email to Postmaster at your site.
help HELP [ <topic> ]
help The HELP command gives help info.
helo HELO <hostname>
-helo Introduce yourself. I am a boor, so I really don't
-helo care if you do.
+helo Introduce yourself.
ehlo EHLO <hostname>
ehlo Introduce yourself, and request extended SMTP mode.
mail MAIL FROM: <sender>
diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c
index 39dabe0a49e7..e049de3ff174 100644
--- a/usr.sbin/sendmail/src/srvrsmtp.c
+++ b/usr.sbin/sendmail/src/srvrsmtp.c
@@ -36,14 +36,13 @@
#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)srvrsmtp.c 8.3 (Berkeley) 7/13/93 (with SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.32 (Berkeley) 3/8/94 (with SMTP)";
#else
-static char sccsid[] = "@(#)srvrsmtp.c 8.3 (Berkeley) 7/13/93 (without SMTP)";
+static char sccsid[] = "@(#)srvrsmtp.c 8.32 (Berkeley) 3/8/94 (without SMTP)";
#endif
#endif /* not lint */
# include <errno.h>
-# include <signal.h>
# ifdef SMTP
@@ -83,6 +82,8 @@ struct cmd
/* non-standard commands */
# define CMDONEX 16 /* onex -- sending one transaction only */
# define CMDVERB 17 /* verb -- go into verbose mode */
+/* use this to catch and log "door handle" attempts on your system */
+# define CMDLOGBOGUS 23 /* bogus command that should be logged */
/* debugging-only commands, only enabled if SMTPDEBUG is defined */
# define CMDDBGQSHOW 24 /* showq -- show send queue */
# define CMDDBGDEBUG 25 /* debug -- set debug mode */
@@ -108,13 +109,18 @@ static struct cmd CmdTab[] =
*/
"showq", CMDDBGQSHOW,
"debug", CMDDBGDEBUG,
+ "wiz", CMDLOGBOGUS,
NULL, CMDERROR,
};
-bool InChild = FALSE; /* true if running in a subprocess */
bool OneXact = FALSE; /* one xaction only this run */
+char *CurSmtpClient; /* who's at the other end of channel */
-#define EX_QUIT 22 /* special code for QUIT command */
+static char *skipword();
+extern char RealUserName[];
+
+
+#define MAXBADCOMMANDS 25 /* maximum number of bad commands */
smtp(e)
register ENVELOPE *e;
@@ -122,7 +128,6 @@ smtp(e)
register char *p;
register struct cmd *c;
char *cmd;
- static char *skipword();
auto ADDRESS *vrfyqueue;
ADDRESS *a;
bool gotmail; /* mail command received */
@@ -131,10 +136,12 @@ smtp(e)
char *protocol; /* sending protocol */
char *sendinghost; /* sending hostname */
long msize; /* approximate maximum message size */
+ char *peerhostname; /* name of SMTP peer or "localhost" */
auto char *delimptr;
char *id;
int nrcpts; /* number of RCPT commands */
bool doublequeue;
+ int badcommands = 0; /* count of bad commands */
char inp[MAXLINE];
char cmdbuf[MAXLINE];
extern char Version[];
@@ -146,11 +153,25 @@ smtp(e)
(void) dup2(fileno(OutChannel), fileno(stdout));
}
settime(e);
- CurHostName = RealHostName;
- setproctitle("server %s startup", CurHostName);
+ peerhostname = RealHostName;
+ if (peerhostname == NULL)
+ peerhostname = "localhost";
+ CurHostName = peerhostname;
+ CurSmtpClient = macvalue('_', e);
+ if (CurSmtpClient == NULL)
+ CurSmtpClient = CurHostName;
+
+ setproctitle("server %s startup", CurSmtpClient);
expand("\201e", inp, &inp[sizeof inp], e);
- message("220-%s", inp);
- message("220 ESMTP spoken here");
+ if (BrokenSmtpPeers)
+ {
+ message("220 %s", inp);
+ }
+ else
+ {
+ message("220-%s", inp);
+ message("220 ESMTP spoken here");
+ }
protocol = NULL;
sendinghost = macvalue('s', e);
gothello = FALSE;
@@ -158,16 +179,20 @@ smtp(e)
for (;;)
{
/* arrange for backout */
- if (setjmp(TopFrame) > 0 && InChild)
+ if (setjmp(TopFrame) > 0)
{
- QuickAbort = FALSE;
- SuprErrs = TRUE;
- finis();
+ /* if() nesting is necessary for Cray UNICOS */
+ if (InChild)
+ {
+ QuickAbort = FALSE;
+ SuprErrs = TRUE;
+ finis();
+ }
}
QuickAbort = FALSE;
HoldErrs = FALSE;
LogUsrErrs = FALSE;
- e->e_flags &= ~EF_VRFYONLY;
+ e->e_flags &= ~(EF_VRFYONLY|EF_GLOBALERRS);
/* setup for the read */
e->e_to = NULL;
@@ -184,12 +209,13 @@ smtp(e)
if (p == NULL)
{
/* end of file, just die */
+ disconnect(1, e);
message("421 %s Lost input channel from %s",
- MyHostName, CurHostName);
+ MyHostName, CurSmtpClient);
#ifdef LOG
- if (LogLevel > 1)
+ if (LogLevel > (gotmail ? 1 : 19))
syslog(LOG_NOTICE, "lost input channel from %s",
- CurHostName);
+ CurSmtpClient);
#endif
if (InChild)
ExitStat = EX_QUIT;
@@ -204,9 +230,9 @@ smtp(e)
fprintf(e->e_xfp, "<<< %s\n", inp);
if (e->e_id == NULL)
- setproctitle("%s: %s", CurHostName, inp);
+ setproctitle("%s: %.80s", CurSmtpClient, inp);
else
- setproctitle("%s %s: %s", e->e_id, CurHostName, inp);
+ setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
/* break off command */
for (p = inp; isascii(*p) && isspace(*p); p++)
@@ -248,21 +274,12 @@ smtp(e)
SmtpPhase = "server HELO";
}
sendinghost = newstr(p);
- if (strcasecmp(p, RealHostName) != 0)
- {
- auth_warning(e, "Host %s claimed to be %s",
- RealHostName, p);
- }
- p = macvalue('_', e);
- if (p == NULL)
- p = RealHostName;
-
gothello = TRUE;
if (c->cmdcode != CMDEHLO)
{
/* print old message and be done with it */
message("250 %s Hello %s, pleased to meet you",
- MyHostName, p);
+ MyHostName, CurSmtpClient);
break;
}
@@ -286,7 +303,7 @@ smtp(e)
{
/* set sending host to our known value */
if (sendinghost == NULL)
- sendinghost = RealHostName;
+ sendinghost = peerhostname;
if (bitset(PRIV_NEEDMAILHELO, PrivacyFlags))
{
@@ -297,6 +314,8 @@ smtp(e)
if (gotmail)
{
message("503 Sender already specified");
+ if (InChild)
+ finis();
break;
}
if (InChild)
@@ -313,15 +332,26 @@ smtp(e)
{
auth_warning(e,
"Host %s didn't use HELO protocol",
- RealHostName);
+ peerhostname);
+ }
+#ifdef PICKY_HELO_CHECK
+ if (strcasecmp(sendinghost, peerhostname) != 0 &&
+ (strcasecmp(peerhostname, "localhost") != 0 ||
+ strcasecmp(sendinghost, MyHostName) != 0))
+ {
+ auth_warning(e, "Host %s claimed to be %s",
+ peerhostname, sendinghost);
}
+#endif
+
if (protocol == NULL)
protocol = "SMTP";
define('r', protocol, e);
define('s', sendinghost, e);
initsys(e);
nrcpts = 0;
- setproctitle("%s %s: %s", e->e_id, CurHostName, inp);
+ e->e_flags |= EF_LOGSENDER;
+ setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
/* child -- go do the processing */
p = skipword(p, "from");
@@ -348,12 +378,21 @@ smtp(e)
if (p != NULL && *p != '\0')
*p++ = '\0';
+ /* check for possible spoofing */
+ if (RealUid != 0 && OpMode == MD_SMTP &&
+ (e->e_from.q_mailer != LocalMailer &&
+ strcmp(e->e_from.q_user, RealUserName) != 0))
+ {
+ auth_warning(e, "%s owned process doing -bs",
+ RealUserName);
+ }
+
/* now parse ESMTP arguments */
msize = 0;
for (; p != NULL && *p != '\0'; p++)
{
char *kp;
- char *vp;
+ char *vp = NULL;
/* locate the beginning of the keyword */
while (isascii(*p) && isspace(*p))
@@ -462,7 +501,7 @@ smtp(e)
p = skipword(p, "to");
if (p == NULL)
break;
- a = parseaddr(p, (ADDRESS *) NULL, 1, ' ', NULL, e);
+ a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', NULL, e);
if (a == NULL)
break;
a->q_flags |= QPRIMARY;
@@ -474,7 +513,9 @@ smtp(e)
e->e_to = p;
if (!bitset(QBADADDR, a->q_flags))
{
- message("250 Recipient ok");
+ message("250 Recipient ok%s",
+ bitset(QQUEUEUP, a->q_flags) ?
+ " (will queue)" : "");
nrcpts++;
}
else
@@ -492,7 +533,7 @@ smtp(e)
message("503 Need MAIL command");
break;
}
- else if (e->e_nrcpts <= 0)
+ else if (nrcpts <= 0)
{
message("503 Need RCPT (recipient)");
break;
@@ -519,9 +560,9 @@ smtp(e)
/* collect the text of the message */
SmtpPhase = "collect";
collect(TRUE, doublequeue, e);
- e->e_flags &= ~EF_FATALERRS;
if (Errors != 0)
goto abortmessage;
+ HoldErrs = TRUE;
/*
** Arrange to send to everyone.
@@ -554,9 +595,6 @@ smtp(e)
sendall(e, doublequeue ? SM_QUEUE : SM_DEFAULT);
e->e_to = NULL;
- /* save statistics */
- markstats(e, (ADDRESS *) NULL);
-
/* issue success if appropriate and reset */
if (Errors == 0 || HoldErrs)
message("250 %s Message accepted for delivery", id);
@@ -576,9 +614,10 @@ smtp(e)
/* if we just queued, poke it */
if (doublequeue && e->e_sendmode != SM_QUEUE)
{
+ extern pid_t dowork();
+
unlockqueue(e);
- dowork(id, TRUE, TRUE, e);
- e->e_id = NULL;
+ (void) dowork(id, TRUE, TRUE, e);
}
}
@@ -596,6 +635,7 @@ smtp(e)
case CMDRSET: /* rset -- reset state */
message("250 Reset state");
+ e->e_flags |= EF_CLRQUEUE;
if (InChild)
finis();
@@ -614,7 +654,12 @@ smtp(e)
if (vrfy)
message("252 Who's to say?");
else
- message("502 That's none of your business");
+ message("502 Sorry, we do not allow this operation");
+#ifdef LOG
+ if (LogLevel > 5)
+ syslog(LOG_INFO, "%s: %s [rejected]",
+ CurSmtpClient, inp);
+#endif
break;
}
else if (!gothello &&
@@ -628,7 +673,7 @@ smtp(e)
break;
#ifdef LOG
if (LogLevel > 5)
- syslog(LOG_INFO, "%s: %s", CurHostName, inp);
+ syslog(LOG_INFO, "%s: %s", CurSmtpClient, inp);
#endif
vrfyqueue = NULL;
QuickAbort = TRUE;
@@ -643,8 +688,7 @@ smtp(e)
}
else
{
- (void) sendtolist(p, (ADDRESS *) NULL,
- &vrfyqueue, e);
+ (void) sendtolist(p, NULLADDR, &vrfyqueue, e);
}
if (Errors != 0)
{
@@ -658,16 +702,13 @@ smtp(e)
}
while (vrfyqueue != NULL)
{
- register ADDRESS *a = vrfyqueue->q_next;
-
- while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags))
- a = a->q_next;
-
+ 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);
- else if (a == NULL)
- message("554 Self destructive alias loop");
- vrfyqueue = a;
+ vrfyqueue = vrfyqueue->q_next;
}
if (InChild)
finis();
@@ -678,14 +719,15 @@ smtp(e)
break;
case CMDNOOP: /* noop -- do nothing */
- message("200 OK");
+ message("250 OK");
break;
case CMDQUIT: /* quit -- leave mail */
message("221 %s closing connection", MyHostName);
+doquit:
/* avoid future 050 messages */
- Verbose = FALSE;
+ disconnect(1, e);
if (InChild)
ExitStat = EX_QUIT;
@@ -721,20 +763,27 @@ smtp(e)
break;
# else /* not SMTPDEBUG */
-
case CMDDBGQSHOW: /* show queues */
case CMDDBGDEBUG: /* set debug mode */
+# endif /* SMTPDEBUG */
+ case CMDLOGBOGUS: /* bogus command */
# ifdef LOG
if (LogLevel > 0)
- syslog(LOG_NOTICE,
+ syslog(LOG_CRIT,
"\"%s\" command from %s (%s)",
- c->cmdname, RealHostName,
+ c->cmdname, peerhostname,
anynet_ntoa(&RealHostAddr));
# endif
/* FALL THROUGH */
-# endif /* SMTPDEBUG */
case CMDERROR: /* unknown command */
+ if (++badcommands > MAXBADCOMMANDS)
+ {
+ message("421 %s Too many bad commands; closing connection",
+ MyHostName);
+ goto doquit;
+ }
+
message("500 Command unrecognized");
break;
@@ -766,6 +815,7 @@ skipword(p, w)
char *w;
{
register char *q;
+ char *firstp = p;
/* find beginning of word */
while (isascii(*p) && isspace(*p))
@@ -780,7 +830,8 @@ skipword(p, w)
if (*p != ':')
{
syntax:
- message("501 Syntax error in parameters");
+ message("501 Syntax error in parameters scanning \"%s\"",
+ firstp);
Errors++;
return (NULL);
}
@@ -934,10 +985,16 @@ runinchild(label, e)
st = waitfor(childpid);
if (st == -1)
syserr("%s: lost child", label);
+ else if (!WIFEXITED(st))
+ syserr("%s: died on signal %d",
+ label, st & 0177);
/* if we exited on a QUIT command, complete the process */
- if (st == (EX_QUIT << 8))
+ if (WEXITSTATUS(st) == EX_QUIT)
+ {
+ disconnect(1, e);
finis();
+ }
return (1);
}
diff --git a/usr.sbin/sendmail/src/stats.c b/usr.sbin/sendmail/src/stats.c
index 94bead6d343a..2dc68272fbc1 100644
--- a/usr.sbin/sendmail/src/stats.c
+++ b/usr.sbin/sendmail/src/stats.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)stats.c 8.2 (Berkeley) 7/11/93";
+static char sccsid[] = "@(#)stats.c 8.3 (Berkeley) 8/28/93";
#endif /* not lint */
# include "sendmail.h"
@@ -95,12 +95,13 @@ poststats(sfile)
(void) time(&Stat.stat_itime);
Stat.stat_size = sizeof Stat;
- fd = open(sfile, 2);
+ fd = open(sfile, O_RDWR);
if (fd < 0)
{
errno = 0;
return;
}
+ (void) lockfile(fd, sfile, NULL, LOCK_EX);
if (read(fd, (char *) &stat, sizeof stat) == sizeof stat &&
stat.stat_size == sizeof stat)
{
diff --git a/usr.sbin/sendmail/src/trace.c b/usr.sbin/sendmail/src/trace.c
index f27d70b318ed..29421eee3c6b 100644
--- a/usr.sbin/sendmail/src/trace.c
+++ b/usr.sbin/sendmail/src/trace.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/7/93";
+static char sccsid[] = "@(#)trace.c 8.2 (Berkeley) 3/14/94";
#endif /* not lint */
# include "sendmail.h"
@@ -82,8 +82,8 @@ tTsetup(vect, size, defflags)
tTflag(s)
register char *s;
{
- int first, last;
- register int i;
+ unsigned int first, last;
+ register unsigned int i;
if (*s == '\0')
s = DefFlags;
diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c
index d0987d407f51..dbd1d046c190 100644
--- a/usr.sbin/sendmail/src/udb.c
+++ b/usr.sbin/sendmail/src/udb.c
@@ -36,15 +36,14 @@
#ifndef lint
#ifdef USERDB
-static char sccsid [] = "@(#)udb.c 8.1 (Berkeley) 6/7/93 (with USERDB)";
+static char sccsid [] = "@(#)udb.c 8.6 (Berkeley) 3/11/94 (with USERDB)";
#else
-static char sccsid [] = "@(#)udb.c 8.1 (Berkeley) 6/7/93 (without USERDB)";
+static char sccsid [] = "@(#)udb.c 8.6 (Berkeley) 3/11/94 (without USERDB)";
#endif
#endif
#ifdef USERDB
-#include <sys/time.h>
#include <errno.h>
#include <netdb.h>
#include <db.h>
@@ -197,12 +196,14 @@ udbexpand(a, sendq, e)
key.data = keybuf;
key.size = keylen;
if (tTd(28, 80))
- printf("udbexpand: trying %s\n", keybuf);
+ printf("udbexpand: trying %s (%d)\n",
+ keybuf, keylen);
i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_CURSOR);
if (i > 0 || info.size <= 0)
{
if (tTd(28, 2))
- printf("udbexpand: no match on %s\n", keybuf);
+ printf("udbexpand: no match on %s (%d)\n",
+ keybuf, keylen);
continue;
}
if (tTd(28, 80))
@@ -346,6 +347,17 @@ char *
udbsender(sender)
char *sender;
{
+ extern char *udbmatch();
+
+ return udbmatch(sender, "mailname");
+}
+
+
+char *
+udbmatch(user, field)
+ char *user;
+ char *field;
+{
register char *p;
register struct udbent *up;
int i;
@@ -354,7 +366,7 @@ udbsender(sender)
char keybuf[MAXKEY];
if (tTd(28, 1))
- printf("udbsender(%s)\n", sender);
+ printf("udbmatch(%s, %s)\n", user, field);
if (!UdbInitialized)
{
@@ -367,16 +379,17 @@ udbsender(sender)
return NULL;
/* long names can never match and are a pain to deal with */
- if (strlen(sender) > sizeof keybuf - 12)
+ if ((strlen(user) + strlen(field)) > sizeof keybuf - 4)
return NULL;
/* names beginning with colons indicate metadata */
- if (sender[0] == ':')
+ if (user[0] == ':')
return NULL;
/* build database key */
- (void) strcpy(keybuf, sender);
- (void) strcat(keybuf, ":mailname");
+ (void) strcpy(keybuf, user);
+ (void) strcat(keybuf, ":");
+ (void) strcat(keybuf, field);
keylen = strlen(keybuf);
for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++)
@@ -394,8 +407,8 @@ udbsender(sender)
if (i != 0 || info.size <= 0)
{
if (tTd(28, 2))
- printf("udbsender: no match on %s\n",
- keybuf);
+ printf("udbmatch: no match on %s (%d)\n",
+ keybuf, keylen);
continue;
}
@@ -403,11 +416,14 @@ udbsender(sender)
bcopy(info.data, p, info.size);
p[info.size] = '\0';
if (tTd(28, 1))
- printf("udbsender ==> %s\n", p);
+ printf("udbmatch ==> %s\n", p);
return p;
}
}
+ if (strcmp(field, "mailname") != 0)
+ return NULL;
+
/*
** Nothing yet. Search again for a default case. But only
** use it if we also have a forward (:maildrop) pointer already
@@ -415,7 +431,7 @@ udbsender(sender)
*/
/* build database key */
- (void) strcpy(keybuf, sender);
+ (void) strcpy(keybuf, user);
(void) strcat(keybuf, ":maildrop");
keylen = strlen(keybuf);
@@ -456,12 +472,12 @@ udbsender(sender)
}
/* they exist -- build the actual address */
- p = xalloc(strlen(sender) + strlen(up->udb_default) + 2);
- (void) strcpy(p, sender);
+ p = xalloc(strlen(user) + strlen(up->udb_default) + 2);
+ (void) strcpy(p, user);
(void) strcat(p, "@");
(void) strcat(p, up->udb_default);
if (tTd(28, 1))
- printf("udbsender ==> %s\n", p);
+ printf("udbmatch ==> %s\n", p);
return p;
}
}
@@ -554,7 +570,7 @@ _udbx_init()
case '*': /* search remote database (expand MX) */
if (*spec == '*')
{
-#ifdef NAMED_BIND
+#if NAMED_BIND
nmx = getmxrr(spec + 1, mxhosts, FALSE, &rcode);
#else
mxhosts[0] = spec + 1;
@@ -586,7 +602,7 @@ _udbx_init()
up->udb_addr.sin_family = h->h_addrtype;
bcopy(h->h_addr_list[0],
(char *) &up->udb_addr.sin_addr,
- h->h_length);
+ sizeof up->udb_addr.sin_addr);
up->udb_addr.sin_port = UdbPort;
up->udb_timeout = UdbTimeout;
up++;
diff --git a/usr.sbin/sendmail/src/useful.h b/usr.sbin/sendmail/src/useful.h
index 944eb5c96292..ba33a792db08 100644
--- a/usr.sbin/sendmail/src/useful.h
+++ b/usr.sbin/sendmail/src/useful.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)useful.h 8.1 (Berkeley) 6/7/93
+ * @(#)useful.h 8.2 (Berkeley) 9/24/93
*/
# include <sys/types.h>
@@ -67,7 +67,11 @@ typedef char bool;
/* sccs id's */
# ifndef lint
-# define SCCSID(arg) static char SccsId[] = "arg";
+# ifdef __STDC__
+# define SCCSID(arg) static char SccsId[] = #arg;
+# else
+# define SCCSID(arg) static char SccsId[] = "arg";
+# endif
# else
-# define SCCSID(arg)
+# define SCCSID(arg)
# endif
diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c
index eb6271160504..06acd3f2fc8e 100644
--- a/usr.sbin/sendmail/src/usersmtp.c
+++ b/usr.sbin/sendmail/src/usersmtp.c
@@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
-static char sccsid[] = "@(#)usersmtp.c 8.4 (Berkeley) 7/13/93 (with SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.18 (Berkeley) 1/24/94 (with SMTP)";
#else
-static char sccsid[] = "@(#)usersmtp.c 8.4 (Berkeley) 7/13/93 (without SMTP)";
+static char sccsid[] = "@(#)usersmtp.c 8.18 (Berkeley) 1/24/94 (without SMTP)";
#endif
#endif /* not lint */
@@ -61,6 +61,7 @@ char SmtpMsgBuffer[MAXLINE]; /* buffer for commands */
char SmtpReplyBuffer[MAXLINE]; /* buffer for replies */
char SmtpError[MAXLINE] = ""; /* save failure error messages */
int SmtpPid; /* pid of mailer */
+bool SmtpNeedIntro; /* need "while talking" in transcript */
#ifdef __STDC__
extern smtpmessage(char *f, MAILER *m, MCI *mci, ...);
@@ -95,7 +96,7 @@ smtpinit(m, mci, e)
if (tTd(18, 1))
{
printf("smtpinit ");
- mci_dump(mci);
+ mci_dump(mci, FALSE);
}
/*
@@ -104,6 +105,7 @@ smtpinit(m, mci, e)
SmtpError[0] = '\0';
CurHostName = mci->mci_host; /* XXX UGLY XXX */
+ SmtpNeedIntro = TRUE;
switch (mci->mci_state)
{
case MCIS_ACTIVE:
@@ -139,8 +141,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) != 2)
+ if (r < 0 || REPLYTYPE(r) == 4)
goto tempfail1;
+ if (REPLYTYPE(r) != 2)
+ goto unavailable;
/*
** Send the HELO command.
@@ -182,12 +186,15 @@ tryhelo:
** Check to see if we actually ended up talking to ourself.
** This means we didn't know about an alias or MX, or we managed
** to connect to an echo server.
+ **
+ ** If this code remains at all, "CheckLoopBack" should be
+ ** a mailer flag. This is a MAYBENEXTRELEASE feature.
*/
p = strchr(&SmtpReplyBuffer[4], ' ');
if (p != NULL)
*p = '\0';
- if (strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
+ if (CheckLoopBack && strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0)
{
syserr("553 %s config error: mail loops back to myself",
MyHostName);
@@ -211,8 +218,13 @@ tryhelo:
goto tempfail2;
}
- mci->mci_state = MCIS_OPEN;
- return;
+ if (mci->mci_state != MCIS_CLOSED)
+ {
+ mci->mci_state = MCIS_OPEN;
+ return;
+ }
+
+ /* got a 421 error code during startup */
tempfail1:
tempfail2:
@@ -291,7 +303,10 @@ helo_options(line, m, mci, e)
mci->mci_maxsize = atol(p);
}
else if (strcasecmp(line, "8bitmime") == 0)
+ {
mci->mci_flags |= MCIF_8BITMIME;
+ mci->mci_flags &= ~MCIF_7BIT;
+ }
else if (strcasecmp(line, "expn") == 0)
mci->mci_flags |= MCIF_EXPN;
}
@@ -310,6 +325,7 @@ smtpmailfrom(m, mci, e)
ENVELOPE *e;
{
int r;
+ char *bufp;
char buf[MAXNAME];
char optbuf[MAXLINE];
@@ -317,7 +333,7 @@ smtpmailfrom(m, mci, e)
printf("smtpmailfrom: CurHost=%s\n", CurHostName);
/* set up appropriate options to include */
- if (bitset(MCIF_SIZE, mci->mci_flags))
+ if (bitset(MCIF_SIZE, mci->mci_flags) && e->e_msgsize > 0)
sprintf(optbuf, " SIZE=%ld", e->e_msgsize);
else
strcpy(optbuf, "");
@@ -334,15 +350,25 @@ smtpmailfrom(m, mci, e)
(void) strcpy(buf, "");
else
expand("\201g", buf, &buf[sizeof buf - 1], e);
+ if (buf[0] == '<')
+ {
+ /* strip off <angle brackets> (put back on below) */
+ bufp = &buf[strlen(buf) - 1];
+ if (*bufp == '>')
+ *bufp = '\0';
+ bufp = &buf[1];
+ }
+ else
+ bufp = buf;
if (e->e_from.q_mailer == LocalMailer ||
!bitnset(M_FROMPATH, m->m_flags))
{
- smtpmessage("MAIL From:<%s>%s", m, mci, buf, optbuf);
+ smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf);
}
else
{
smtpmessage("MAIL From:<@%s%c%s>%s", m, mci, MyHostName,
- buf[0] == '@' ? ',' : ':', buf, optbuf);
+ *bufp == '@' ? ',' : ':', bufp, optbuf);
}
SmtpPhase = mci->mci_phase = "client MAIL";
setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase);
@@ -443,6 +469,7 @@ smtprcpt(to, m, mci, e)
*/
static jmp_buf CtxDataTimeout;
+static int datatimeout();
smtpdata(m, mci, e)
struct mailer *m;
@@ -452,7 +479,6 @@ smtpdata(m, mci, e)
register int r;
register EVENT *ev;
time_t timeout;
- static int datatimeout();
/*
** Send the data.
@@ -513,12 +539,22 @@ smtpdata(m, mci, e)
ev = setevent(timeout, datatimeout, 0);
/* now output the actual message */
- (*e->e_puthdr)(mci->mci_out, m, e);
- putline("\n", mci->mci_out, m);
- (*e->e_putbody)(mci->mci_out, m, e, NULL);
+ (*e->e_puthdr)(mci, e);
+ putline("\n", mci);
+ (*e->e_putbody)(mci, e, NULL);
clrevent(ev);
+ if (ferror(mci->mci_out))
+ {
+ /* error during processing -- don't send the dot */
+ mci->mci_errno = EIO;
+ mci->mci_exitstat = EX_IOERR;
+ mci->mci_state = MCIS_ERROR;
+ smtpquit(m, mci, e);
+ return EX_IOERR;
+ }
+
/* terminate the message */
fprintf(mci->mci_out, ".%s", m->m_eol);
if (TrafficLogFile != NULL)
@@ -577,7 +613,16 @@ smtpquit(m, mci, e)
register MCI *mci;
ENVELOPE *e;
{
- int i;
+ bool oldSuprErrs = SuprErrs;
+
+ /*
+ ** Suppress errors here -- we may be processing a different
+ ** job when we do the quit connection, and we don't want the
+ ** new job to be penalized for something that isn't it's
+ ** problem.
+ */
+
+ SuprErrs = TRUE;
/* send the quit message if we haven't gotten I/O error */
if (mci->mci_state != MCIS_ERROR)
@@ -585,14 +630,18 @@ smtpquit(m, mci, e)
SmtpPhase = "client QUIT";
smtpmessage("QUIT", m, mci);
(void) reply(m, mci, e, TimeOuts.to_quit, NULL);
+ SuprErrs = oldSuprErrs;
if (mci->mci_state == MCIS_CLOSED)
+ {
+ SuprErrs = oldSuprErrs;
return;
+ }
}
/* now actually close the connection and pick up the zombie */
- i = endmailer(mci, e, m->m_argv);
- if (i != EX_OK)
- syserr("451 smtpquit %s: stat %d", m->m_argv[0], i);
+ (void) endmailer(mci, e, NULL);
+
+ SuprErrs = oldSuprErrs;
}
/*
** SMTPRSET -- send a RSET (reset) command
@@ -724,8 +773,14 @@ reply(m, mci, e, timeout, pfunc)
#ifdef XDEBUG
{
char wbuf[MAXLINE];
- sprintf(wbuf, "%s... reply(%s) during %s",
- e->e_to, mci->mci_host, SmtpPhase);
+ char *p = wbuf;
+ if (e->e_to != NULL)
+ {
+ sprintf(p, "%s... ", e->e_to);
+ p += strlen(p);
+ }
+ sprintf(p, "reply(%s) during %s",
+ mci->mci_host, SmtpPhase);
checkfd012(wbuf);
}
#endif
@@ -739,6 +794,14 @@ reply(m, mci, e, timeout, pfunc)
(bufp[0] == '5' && strncmp(SmtpMsgBuffer, "EHLO", 4) != 0)))
{
/* serious error -- log the previous command */
+ if (SmtpNeedIntro)
+ {
+ /* inform user who we are chatting with */
+ fprintf(CurEnv->e_xfp,
+ "... while talking to %s:\n",
+ CurHostName);
+ SmtpNeedIntro = FALSE;
+ }
if (SmtpMsgBuffer[0] != '\0')
fprintf(e->e_xfp, ">>> %s\n", SmtpMsgBuffer);
SmtpMsgBuffer[0] = '\0';
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c
index 453a1adc0d7f..ca7612d7673b 100644
--- a/usr.sbin/sendmail/src/util.c
+++ b/usr.sbin/sendmail/src/util.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)util.c 8.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)util.c 8.34 (Berkeley) 3/11/94";
#endif /* not lint */
# include "sendmail.h"
@@ -403,8 +403,13 @@ buildfname(gecos, login, buf)
**
** Parameters:
** fn -- filename to check.
-** uid -- uid to compare against.
-** mustown -- to be safe, this uid must own the file.
+** uid -- user id to compare against.
+** gid -- group id to compare against.
+** uname -- user name to compare against (used for group
+** sets).
+** flags -- modifiers:
+** SFF_MUSTOWN -- "uid" must own this file.
+** SFF_NOSLINK -- file cannot be a symbolic link.
** mode -- mode bits that must match.
**
** Returns:
@@ -415,69 +420,144 @@ buildfname(gecos, login, buf)
** none.
*/
+#include <grp.h>
+
#ifndef S_IXOTH
# define S_IXOTH (S_IEXEC >> 6)
#endif
+#ifndef S_IXGRP
+# define S_IXGRP (S_IEXEC >> 3)
+#endif
+
#ifndef S_IXUSR
# define S_IXUSR (S_IEXEC)
#endif
int
-safefile(fn, uid, mustown, mode)
+safefile(fn, uid, gid, uname, flags, mode)
char *fn;
uid_t uid;
- bool mustown;
+ gid_t gid;
+ char *uname;
+ int flags;
int mode;
{
register char *p;
+ register struct group *gr = NULL;
struct stat stbuf;
if (tTd(54, 4))
- printf("safefile(%s, %d, %d, %o): ", fn, uid, mustown, mode);
+ printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
+ fn, uid, gid, flags, mode);
errno = 0;
for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
{
*p = '\0';
- if (stat(fn, &stbuf) < 0 ||
- !bitset(stbuf.st_uid == uid ? S_IXUSR : S_IXOTH,
- stbuf.st_mode))
+ if (stat(fn, &stbuf) < 0)
+ break;
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
+ {
+ if (bitset(S_IXOTH, stbuf.st_mode))
+ continue;
+ break;
+ }
+ if (stbuf.st_uid == uid && bitset(S_IXUSR, stbuf.st_mode))
+ continue;
+ if (stbuf.st_gid == gid && bitset(S_IXGRP, stbuf.st_mode))
+ continue;
+#ifndef NO_GROUP_SET
+ if (uname != NULL &&
+ ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
+ (gr = getgrgid(stbuf.st_gid)) != NULL))
{
- int ret = errno;
-
- if (ret == 0)
- ret = EACCES;
- if (tTd(54, 4))
- printf("[dir %s] %s\n", fn, errstring(ret));
- *p = '/';
- return ret;
+ register char **gp;
+
+ for (gp = gr->gr_mem; *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (*gp != NULL && bitset(S_IXGRP, stbuf.st_mode))
+ continue;
}
+#endif
+ if (!bitset(S_IXOTH, stbuf.st_mode))
+ break;
+ }
+ if (p != NULL)
+ {
+ int ret = errno;
+
+ if (ret == 0)
+ ret = EACCES;
+ if (tTd(54, 4))
+ printf("\t[dir %s] %s\n", fn, errstring(ret));
+ *p = '/';
+ return ret;
}
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, &stbuf)
+ : stat(fn, &stbuf)) < 0)
+#else
if (stat(fn, &stbuf) < 0)
+#endif
{
int ret = errno;
if (tTd(54, 4))
- printf("%s\n", errstring(ret));
+ printf("\t%s\n", errstring(ret));
errno = 0;
return ret;
}
- if (stbuf.st_uid != uid || uid == 0 || !mustown)
+
+#ifdef S_ISLNK
+ if (bitset(SFF_NOSLINK, flags) && S_ISLNK(stbuf.st_mode))
+ {
+ if (tTd(54, 4))
+ printf("\t[slink mode %o]\tEPERM\n", stbuf.st_mode);
+ return EPERM;
+ }
+#endif
+
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
mode >>= 6;
+ else if (stbuf.st_uid != uid)
+ {
+ mode >>= 3;
+ if (stbuf.st_gid == gid)
+ ;
+#ifndef NO_GROUP_SET
+ else if (uname != NULL &&
+ ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
+ (gr = getgrgid(stbuf.st_gid)) != NULL))
+ {
+ register char **gp;
+
+ for (gp = gr->gr_mem; *gp != NULL; gp++)
+ if (strcmp(*gp, uname) == 0)
+ break;
+ if (*gp == NULL)
+ mode >>= 3;
+ }
+#endif
+ else
+ mode >>= 3;
+ }
if (tTd(54, 4))
- printf("[uid %d, stat %o] ", stbuf.st_uid, stbuf.st_mode);
- if ((stbuf.st_uid == uid || uid == 0 || !mustown) &&
+ printf("\t[uid %d, stat %o, mode %o] ",
+ stbuf.st_uid, stbuf.st_mode, mode);
+ if ((stbuf.st_uid == uid || stbuf.st_uid == 0 ||
+ !bitset(SFF_MUSTOWN, flags)) &&
(stbuf.st_mode & mode) == mode)
{
if (tTd(54, 4))
- printf("OK\n");
+ printf("\tOK\n");
return 0;
}
if (tTd(54, 4))
- printf("EACCES\n");
+ printf("\tEACCES\n");
return EACCES;
}
/*
@@ -564,8 +644,16 @@ dfopen(filename, omode, cmode)
fd = open(filename, omode, cmode);
if (fd >= 0)
break;
- if (errno != ENFILE && errno != EINTR)
- break;
+ switch (errno)
+ {
+ case ENFILE: /* system file table full */
+ case EINTR: /* interrupted syscall */
+#ifdef ETXTBSY
+ case ETXTBSY: /* Apollo: net file locked */
+#endif
+ continue;
+ }
+ break;
}
if (fd >= 0 && fstat(fd, &st) >= 0 && S_ISREG(st.st_mode))
{
@@ -576,7 +664,7 @@ dfopen(filename, omode, cmode)
locktype = LOCK_EX;
else
locktype = LOCK_SH;
- (void) lockfile(fd, filename, locktype);
+ (void) lockfile(fd, filename, NULL, locktype);
errno = 0;
}
if (fd < 0)
@@ -592,8 +680,7 @@ dfopen(filename, omode, cmode)
**
** Parameters:
** l -- line to put.
-** fp -- file to put it onto.
-** m -- the mailer used to control output.
+** mci -- the mailer connection information.
**
** Returns:
** none
@@ -602,16 +689,16 @@ dfopen(filename, omode, cmode)
** output of l to fp.
*/
-putline(l, fp, m)
+putline(l, mci)
register char *l;
- FILE *fp;
- MAILER *m;
+ register MCI *mci;
{
register char *p;
register char svchar;
+ int slop = 0;
/* strip out 0200 bits -- these can look like TELNET protocol */
- if (bitnset(M_7BITS, m->m_flags))
+ if (bitset(MCIF_7BIT, mci->mci_flags))
{
for (p = l; (svchar = *p) != '\0'; ++p)
if (bitset(0200, svchar))
@@ -629,40 +716,45 @@ putline(l, fp, m)
fprintf(TrafficLogFile, "%05d >>> ", getpid());
/* check for line overflow */
- while (m->m_linelimit > 0 && (p - l) > m->m_linelimit)
+ while (mci->mci_mailer->m_linelimit > 0 &&
+ (p - l + slop) > mci->mci_mailer->m_linelimit)
{
- register char *q = &l[m->m_linelimit - 1];
+ register char *q = &l[mci->mci_mailer->m_linelimit - slop - 1];
svchar = *q;
*q = '\0';
- if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
+ if (l[0] == '.' && slop == 0 &&
+ bitnset(M_XDOT, mci->mci_mailer->m_flags))
{
- (void) putc('.', fp);
+ (void) putc('.', mci->mci_out);
if (TrafficLogFile != NULL)
(void) putc('.', TrafficLogFile);
}
- fputs(l, fp);
- (void) putc('!', fp);
- fputs(m->m_eol, fp);
+ fputs(l, mci->mci_out);
+ (void) putc('!', mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
+ (void) putc(' ', mci->mci_out);
if (TrafficLogFile != NULL)
- fprintf(TrafficLogFile, "%s!\n%05d >>> ",
+ fprintf(TrafficLogFile, "%s!\n%05d >>> ",
l, getpid());
*q = svchar;
l = q;
+ slop = 1;
}
/* output last part */
- if (l[0] == '.' && bitnset(M_XDOT, m->m_flags))
+ if (l[0] == '.' && slop == 0 &&
+ bitnset(M_XDOT, mci->mci_mailer->m_flags))
{
- (void) putc('.', fp);
+ (void) putc('.', mci->mci_out);
if (TrafficLogFile != NULL)
(void) putc('.', TrafficLogFile);
}
if (TrafficLogFile != NULL)
fprintf(TrafficLogFile, "%.*s\n", p - l, l);
for ( ; l < p; ++l)
- (void) putc(*l, fp);
- fputs(m->m_eol, fp);
+ (void) putc(*l, mci->mci_out);
+ fputs(mci->mci_mailer->m_eol, mci->mci_out);
if (*l == '\n')
++l;
} while (l[0] != '\0');
@@ -716,6 +808,10 @@ xfclose(fp, a, b)
{
if (tTd(53, 99))
printf("xfclose(%x) %s %s\n", fp, a, b);
+#ifdef XDEBUG
+ if (fileno(fp) == 1)
+ syserr("xfclose(%s %s): fd = 1", a, b);
+#endif
if (fclose(fp) < 0 && tTd(53, 99))
printf("xfclose FAILURE: %s\n", errstring(errno));
}
@@ -739,6 +835,7 @@ xfclose(fp, a, b)
*/
static jmp_buf CtxReadTimeout;
+static int readtimeout();
char *
sfgets(buf, siz, fp, timeout, during)
@@ -750,7 +847,12 @@ sfgets(buf, siz, fp, timeout, during)
{
register EVENT *ev = NULL;
register char *p;
- static int readtimeout();
+
+ if (fp == NULL)
+ {
+ buf[0] = '\0';
+ return NULL;
+ }
/* set the timeout */
if (timeout != 0)
@@ -776,12 +878,13 @@ sfgets(buf, siz, fp, timeout, during)
/* try to read */
p = NULL;
- while (p == NULL && !feof(fp) && !ferror(fp))
+ while (!feof(fp) && !ferror(fp))
{
errno = 0;
p = fgets(buf, siz, fp);
- if (errno == EINTR)
- clearerr(fp);
+ if (p != NULL || errno != EINTR)
+ break;
+ clearerr(fp);
}
/* clear the event if it has not sprung */
@@ -927,7 +1030,7 @@ bool
atobool(s)
register char *s;
{
- if (*s == '\0' || strchr("tTyY", *s) != NULL)
+ if (s == NULL || *s == '\0' || strchr("tTyY", *s) != NULL)
return (TRUE);
return (FALSE);
}
@@ -968,10 +1071,15 @@ atooct(s)
** none.
*/
+int
waitfor(pid)
int pid;
{
+#ifdef WAITUNION
+ union wait st;
+#else
auto int st;
+#endif
int i;
do
@@ -980,8 +1088,12 @@ waitfor(pid)
i = wait(&st);
} while ((i >= 0 || errno == EINTR) && i != pid);
if (i < 0)
- st = -1;
- return (st);
+ return -1;
+#ifdef WAITUNION
+ return st.w_status;
+#else
+ return st;
+#endif
}
/*
** BITINTERSECT -- tell if two bitmaps intersect
@@ -1051,18 +1163,23 @@ strcontainedin(a, b)
register char *a;
register char *b;
{
- int l;
-
- l = strlen(a);
- for (;;)
+ int la;
+ int lb;
+ int c;
+
+ la = strlen(a);
+ lb = strlen(b);
+ c = *a;
+ if (isascii(c) && isupper(c))
+ c = tolower(c);
+ for (; lb-- >= la; b++)
{
- b = strchr(b, a[0]);
- if (b == NULL)
- return FALSE;
- if (strncmp(a, b, l) == 0)
+ if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
+ continue;
+ if (strncasecmp(a, b, la) == 0)
return TRUE;
- b++;
}
+ return FALSE;
}
/*
** CHECKFD012 -- check low numbered file descriptors
@@ -1086,7 +1203,7 @@ checkfd012(where)
for (i = 0; i < 3; i++)
{
- if (fstat(i, &stbuf) < 0)
+ if (fstat(i, &stbuf) < 0 && errno != EOPNOTSUPP)
{
/* oops.... */
int fd;
@@ -1100,5 +1217,197 @@ checkfd012(where)
}
}
}
-#endif XDEBUG
+#endif /* XDEBUG */
+}
+ /*
+** PRINTOPENFDS -- print the open file descriptors (for debugging)
+**
+** Parameters:
+** logit -- if set, send output to syslog; otherwise
+** print for debugging.
+**
+** Returns:
+** none.
+*/
+
+#include <netdb.h>
+#include <arpa/inet.h>
+
+printopenfds(logit)
+ bool logit;
+{
+ register int fd;
+ extern int DtableSize;
+
+ for (fd = 0; fd < DtableSize; fd++)
+ dumpfd(fd, FALSE, logit);
+}
+ /*
+** DUMPFD -- dump a file descriptor
+**
+** Parameters:
+** fd -- the file descriptor to dump.
+** printclosed -- if set, print a notification even if
+** it is closed; otherwise print nothing.
+** logit -- if set, send output to syslog instead of stdout.
+*/
+
+dumpfd(fd, printclosed, logit)
+ int fd;
+ bool printclosed;
+ bool logit;
+{
+ register struct hostent *hp;
+ register char *p;
+ struct sockaddr_in sin;
+ auto int slen;
+ struct stat st;
+ char buf[200];
+
+ p = buf;
+ sprintf(p, "%3d: ", fd);
+ p += strlen(p);
+
+ if (fstat(fd, &st) < 0)
+ {
+ if (printclosed || errno != EBADF)
+ {
+ sprintf(p, "CANNOT STAT (%s)", errstring(errno));
+ goto printit;
+ }
+ return;
+ }
+
+ slen = fcntl(fd, F_GETFL, NULL);
+ if (slen != -1)
+ {
+ sprintf(p, "fl=0x%x, ", slen);
+ p += strlen(p);
+ }
+
+ sprintf(p, "mode=%o: ", st.st_mode);
+ p += strlen(p);
+ switch (st.st_mode & S_IFMT)
+ {
+#ifdef S_IFSOCK
+ case S_IFSOCK:
+ sprintf(p, "SOCK ");
+ p += strlen(p);
+ slen = sizeof sin;
+ if (getsockname(fd, (struct sockaddr *) &sin, &slen) < 0)
+ sprintf(p, "(badsock)");
+ else
+ {
+ hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET);
+ sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr)
+ : hp->h_name, ntohs(sin.sin_port));
+ }
+ p += strlen(p);
+ sprintf(p, "->");
+ p += strlen(p);
+ slen = sizeof sin;
+ if (getpeername(fd, (struct sockaddr *) &sin, &slen) < 0)
+ sprintf(p, "(badsock)");
+ else
+ {
+ hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET);
+ sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr)
+ : hp->h_name, ntohs(sin.sin_port));
+ }
+ break;
+#endif
+
+ case S_IFCHR:
+ sprintf(p, "CHR: ");
+ p += strlen(p);
+ goto defprint;
+
+ case S_IFBLK:
+ sprintf(p, "BLK: ");
+ p += strlen(p);
+ goto defprint;
+
+#if defined(S_IFIFO) && (!defined(S_IFSOCK) || S_IFIFO != S_IFSOCK)
+ case S_IFIFO:
+ sprintf(p, "FIFO: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFDIR
+ case S_IFDIR:
+ sprintf(p, "DIR: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFLNK
+ case S_IFLNK:
+ sprintf(p, "LNK: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+ default:
+defprint:
+ sprintf(p, "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%ld",
+ major(st.st_dev), minor(st.st_dev), st.st_ino,
+ st.st_nlink, st.st_uid, st.st_gid, st.st_size);
+ break;
+ }
+
+printit:
+ if (logit)
+ syslog(LOG_DEBUG, "%s", buf);
+ else
+ printf("%s\n", buf);
+}
+ /*
+** SHORTENSTRING -- return short version of a string
+**
+** If the string is already short, just return it. If it is too
+** long, return the head and tail of the string.
+**
+** Parameters:
+** s -- the string to shorten.
+** m -- the max length of the string.
+**
+** Returns:
+** Either s or a short version of s.
+*/
+
+#ifndef MAXSHORTSTR
+# define MAXSHORTSTR 203
+#endif
+
+char *
+shortenstring(s, m)
+ register char *s;
+ int m;
+{
+ int l;
+ static char buf[MAXSHORTSTR + 1];
+
+ l = strlen(s);
+ if (l < m)
+ return s;
+ if (m > MAXSHORTSTR)
+ m = MAXSHORTSTR;
+ else if (m < 10)
+ {
+ if (m < 5)
+ {
+ strncpy(buf, s, m);
+ buf[m] = '\0';
+ return buf;
+ }
+ strncpy(buf, s, m - 3);
+ strcpy(buf + m - 3, "...");
+ return buf;
+ }
+ m = (m - 3) / 2;
+ strncpy(buf, s, m);
+ strcpy(buf + m, "...");
+ strcpy(buf + m + 3, s + l - m);
+ return buf;
}
diff --git a/usr.sbin/sendmail/src/version.c b/usr.sbin/sendmail/src/version.c
index b3cb8a5f6426..1ff28a958b9c 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.3 (Berkeley) 7/13/93";
+static char sccsid[] = "@(#)version.c 8.6.8.1 (Berkeley) 3/18/94";
#endif /* not lint */
-char Version[] = "8.3";
+char Version[] = "8.6.8";