Fold sendmail-8.8.2 changes into files that have been touched.

(^!&@$#&^! delete !!@^@^ trailing !@^&#$!& whitespace!!!)
This commit is contained in:
Peter Wemm 1996-10-24 05:07:25 +00:00
parent 3b50ea913d
commit 82c2534fd0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=19149
25 changed files with 3797 additions and 1260 deletions

View File

@ -1,4 +1,4 @@
# @(#)Makefile 8.12 (Berkeley) 5/29/95
# @(#)Makefile 8.15 (Berkeley) 9/21/96
VER= XX
SUBDIR= src mailstats makemap praliases smrsh cf/cf
@ -12,6 +12,11 @@ tar: sccs-check compile-world run-pax
sccs-check:
sccs check
(cd src; sccs check)
(cd mail.local; sccs check)
(cd mailstats; sccs check)
(cd makemap; sccs check)
(cd praliases; sccs check)
(cd smrsh; sccs check)
(cd doc/op; sccs check)
(cd doc/intro; sccs check)
(cd doc/usenix; sccs check)
@ -24,7 +29,12 @@ sccs-check:
(cd cf/domain; sccs check)
compile-world:
(cd src; ${MAKE})
(cd src; sh makesendmail)
(cd mail.local; ${MAKE})
(cd mailstats; ${MAKE})
(cd makemap; ${MAKE})
(cd praliases; ${MAKE})
(cd smrsh; ${MAKE})
(cd doc; PRINTER=ps ${MAKE})
(cd doc; chmod 444 op/op.ps intro/intro.ps usenix/usenix.ps)
(cd cf/cf; ${MAKE})

View File

@ -1,4 +1,4 @@
# @(#)Makefile 8.12 (Berkeley) 5/29/95
# @(#)Makefile 8.15 (Berkeley) 9/21/96
VER= XX
SUBDIR= src mailstats makemap praliases smrsh cf/cf
@ -12,6 +12,11 @@ tar: sccs-check compile-world run-pax
sccs-check:
sccs check
(cd src; sccs check)
(cd mail.local; sccs check)
(cd mailstats; sccs check)
(cd makemap; sccs check)
(cd praliases; sccs check)
(cd smrsh; sccs check)
(cd doc/op; sccs check)
(cd doc/intro; sccs check)
(cd doc/usenix; sccs check)
@ -24,7 +29,12 @@ sccs-check:
(cd cf/domain; sccs check)
compile-world:
(cd src; ${MAKE})
(cd src; sh makesendmail)
(cd mail.local; ${MAKE})
(cd mailstats; ${MAKE})
(cd makemap; ${MAKE})
(cd praliases; ${MAKE})
(cd smrsh; ${MAKE})
(cd doc; PRINTER=ps ${MAKE})
(cd doc; chmod 444 op/op.ps intro/intro.ps usenix/usenix.ps)
(cd cf/cf; ${MAKE})

View File

@ -44,7 +44,7 @@ POPDIVERT
### SMTP Mailer specification ###
#####################################
VERSIONID(`@(#)smtp.m4 8.32 (Berkeley) 11/20/95')
VERSIONID(`@(#)smtp.m4 8.33 (Berkeley) 7/9/96')
Msmtp, P=[IPC], F=CONCAT(mDFMuX8, SMTP_MAILER_FLAGS), S=11/31, R=ifdef(`_ALL_MASQUERADE_', `21/31', `21'), E=\r\n, L=990,
_OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP,
@ -114,7 +114,9 @@ R$+ < @ $* > $* $@ $1 < @ $2 > $3 not UUCP form
R< $&h ! > $- ! $+ $@ $2 < @ $1 .UUCP. >
R< $&h ! > $-.$+ ! $+ $@ $3 < @ $1.$2 >
R< $&h ! > $+ $@ $1 < @ $&h .UUCP. >
R< $+ ! > $+ $: $1 ! $2 < @ *LOCAL* >')
R< $+ ! > $+ $: $1 ! $2 < @ $Y > use UUCP_RELAY
R$+ < @ $+ : $+ > $@ $1 < @ $3 > strip mailer: part
R$+ < @ > $: $1 < @ *LOCAL* > if no UUCP_RELAY')
#

View File

@ -1,8 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/7/93
# @(#)Makefile 8.2 (Berkeley) 9/21/96
PROG= mailstats
CFLAGS+=-I${.CURDIR}/../src
MAN8= mailstats.8
CFLAGS+=-I${.CURDIR}/../src
.include "../../Makefile.inc"
.include <bsd.prog.mk>

View File

@ -40,9 +40,10 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)mailstats.c 8.4 (Berkeley) 8/14/94";
static char sccsid[] = "@(#)mailstats.c 8.8 (Berkeley) 9/25/96";
#endif /* not lint */
#define NOT_SENDMAIL
#include <sendmail.h>
#include <mailstats.h>
#include <pathnames.h>
@ -91,7 +92,8 @@ main(argc, argv)
case '?':
default:
usage:
fputs("usage: mailstats [-o] [-C cffile] [-f stfile]\n", stderr);
fputs("usage: mailstats [-o] [-C cffile] [-f stfile]\n",
stderr);
exit(EX_USAGE);
}
}
@ -189,13 +191,24 @@ main(argc, argv)
exit (EX_OSFILE);
}
if ((fd = open(sfile, O_RDONLY)) < 0) {
if ((fd = open(sfile, O_RDONLY)) < 0 ||
(i = read(fd, &stat, sizeof stat)) < 0)
{
fputs("mailstats: ", stderr);
perror(sfile);
exit(EX_NOINPUT);
}
if (read(fd, &stat, sizeof(stat)) != sizeof(stat) ||
stat.stat_size != sizeof(stat))
if (i == 0)
{
sleep(1);
i = read(fd, &stat, sizeof stat);
if (i == 0)
{
bzero((ARBPTR_T) &stat, sizeof stat);
(void) time(&stat.stat_itime);
}
}
else if (i != sizeof stat || stat.stat_size != sizeof(stat))
{
fputs("mailstats: file size changed.\n", stderr);
exit(EX_OSERR);

View File

@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)makemap.c 8.14 (Berkeley) 11/5/95";
static char sccsid[] = "@(#)makemap.c 8.17 (Berkeley) 9/25/96";
#endif /* not lint */
#include <stdio.h>
@ -45,6 +45,7 @@ static char sccsid[] = "@(#)makemap.c 8.14 (Berkeley) 11/5/95";
#ifndef ISC_UNIX
# include <sys/file.h>
#endif
#define NOT_SENDMAIL
#include "useful.h"
#include "conf.h"
@ -95,6 +96,7 @@ main(argc, argv)
int lineno;
int st;
int mode;
int putflags;
enum type type;
int fd;
union
@ -211,20 +213,33 @@ main(argc, argv)
bzero(&bti, sizeof bti);
if (allowdups)
bti.flags |= R_DUP;
if (allowdups || allowreplace)
putflags = 0;
else
putflags = R_NOOVERWRITE;
break;
case T_HASH:
if (allowreplace)
putflags = 0;
else
putflags = R_NOOVERWRITE;
break;
#endif
#ifdef NDBM
case T_DBM:
#endif
if (allowdups)
{
fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n",
progname, typename);
exit(EX_UNAVAILABLE);
}
if (allowreplace)
putflags = DBM_REPLACE;
else
putflags = DBM_INSERT;
break;
#endif
}
/*
@ -386,16 +401,14 @@ main(argc, argv)
{
#ifdef NDBM
case T_DBM:
st = dbm_store(dbp.dbm, key.dbm, val.dbm,
allowreplace ? DBM_REPLACE : DBM_INSERT);
st = dbm_store(dbp.dbm, key.dbm, val.dbm, putflags);
break;
#endif
#ifdef NEWDB
case T_BTREE:
case T_HASH:
st = (*dbp.db->put)(dbp.db, &key.db, &val.db,
allowreplace ? 0 : R_NOOVERWRITE);
st = (*dbp.db->put)(dbp.db, &key.db, &val.db, putflags);
break;
#endif
}

View File

@ -30,7 +30,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)smrsh.8 8.1 (Berkeley) 11/13/94
.\" @(#)smrsh.8 8.2 (Berkeley) 1/9/96
.\"
.TH SMRSH 8 11/02/93
.SH NAME
@ -62,8 +62,8 @@ limits programs to be in the directory
/usr/libexec/sm.bin,
allowing the system administrator to choose the set of acceptable commands.
It also rejects any commands with the characters
`\`', `<', `>', `|', `;', `&', `$', `(', `)', `\r' (carriage return),
or `\n' (newline)
`\`', `<', `>', `|', `;', `&', `$', `(', `)', `\er' (carriage return),
or `\en' (newline)
on the command line to prevent ``end run'' attacks.
.PP
Initial pathnames on programs are stripped,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)collect.c 8.49 (Berkeley) 10/29/95";
static char sccsid[] = "@(#)collect.c 8.58 (Berkeley) 9/18/96";
#endif /* not lint */
# include <errno.h>
@ -101,8 +101,8 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
int buflen;
int istate;
int mstate;
char *pbp;
char peekbuf[8];
u_char *pbp;
u_char peekbuf[8];
char dfname[20];
char bufbuf[MAXLINE];
extern bool isheader();
@ -170,9 +170,10 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
if (setjmp(CtxCollectTimeout) != 0)
{
#ifdef LOG
syslog(LOG_NOTICE,
"timeout waiting for input from %s during message collect",
CurHostName ? CurHostName : "<local machine>");
if (LogLevel > 2)
syslog(LOG_NOTICE,
"timeout waiting for input from %s during message collect",
CurHostName ? CurHostName : "<local machine>");
#endif
errno = 0;
usrerr("451 timeout waiting for input during message collect");
@ -216,8 +217,6 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
c &= 0x7f;
else
HasEightBits |= bitset(0x80, c);
if (!headeronly)
e->e_msgsize++;
}
if (tTd(30, 94))
printf("istate=%d, c=%c (0x%x)\n",
@ -253,7 +252,7 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
break;
case IS_DOTCR:
if (c == '\n')
if (c == '\n' && !ignrdot)
goto readerr;
else
{
@ -287,6 +286,8 @@ collect(fp, smtpmode, requeueflag, hdrp, e)
istate = IS_NORM;
bufferchar:
if (!headeronly)
e->e_msgsize++;
if (mstate == MS_BODY)
{
/* just put the character out */
@ -316,7 +317,13 @@ bufferchar:
if (obuf != bufbuf)
free(obuf);
}
if (c != '\0')
if (c >= 0200 && c <= 0237)
{
#if 0 /* causes complaints -- figure out something for 8.9 */
usrerr("Illegal character 0x%x in header", c);
#endif
}
else if (c != '\0')
*bp++ = c;
if (istate == IS_BOL)
break;
@ -564,7 +571,8 @@ readerr:
if (HasEightBits)
{
e->e_flags |= EF_HAS8BIT;
if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode))
if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode) &&
!bitset(EF_IS_MIME, e->e_flags))
{
e->e_status = "5.6.1";
usrerr("554 Eight bit data not allowed");
@ -625,6 +633,7 @@ tferror(tf, e)
struct stat st;
long avail;
long bsize;
extern long freediskspace __P((char *, long *));
e->e_flags |= EF_NO_BODY_RETN;
if (fstat(fileno(tf), &st) < 0)
@ -729,7 +738,6 @@ eatfrom(fm, e)
if (*p != '\0')
{
char *q;
extern char *arpadate();
/* we have found a date */
q = xalloc(25);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)conf.h 8.220 (Berkeley) 11/29/95
* @(#)conf.h 8.267 (Berkeley) 10/17/96
*/
/*
@ -66,7 +66,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define MAXMAILERS 25 /* maximum mailers known to system */
# define MAXRWSETS 200 /* max # of sets of rewriting rules */
# define MAXPRIORITIES 25 /* max values for Precedence: field */
# define MAXMXHOSTS 20 /* max # of MX records */
# define MAXMXHOSTS 100 /* max # of MX records for one host */
# define SMTPLINELIM 990 /* maximum SMTP line length */
# define MAXKEY 128 /* maximum size of a database key */
# define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */
@ -183,9 +183,6 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
# endif
# define syslog hard_syslog
# ifdef __STDC__
extern void hard_syslog(int, char *, ...);
# endif
# ifdef V4FS
/* HP-UX 10.x */
@ -205,11 +202,24 @@ extern void hard_syslog(int, char *, ...);
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
# ifdef __STDC__
extern void hard_syslog(int, char *, ...);
# endif
# endif
#endif
/*
** IBM AIX 4.x
*/
#ifdef _AIX4
# define _AIX3 1 /* pull in AIX3 stuff */
# define HASSETREUID 1 /* setreuid(2) works */
#endif
/*
** IBM AIX 3.x -- actually tested for 3.2.3
*/
@ -222,15 +232,58 @@ extern void hard_syslog(int, char *, ...);
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
# define FORK fork /* no vfork primitive available */
# define GIDSET_T gid_t
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# define SPT_PADCHAR '\0' /* pad process title with nulls */
# define LA_TYPE LA_INT
# define FSHIFT 16
# define LA_AVENRUN "avenrun"
#endif
/*
** IBM AIX 2.2.1 -- actually tested for osupdate level 2706+1773
**
** From Mark Whetzel <markw@wg.waii.com>.
*/
#ifdef AIX /* AIX/RT compiler pre-defines this */
# include <paths.h>
# include <sys/time.h> /* AIX/RT resource.h does NOT include this */
# define HASINITGROUPS 1 /* has initgroups(3) call */
# define HASUNAME 1 /* use System V uname(2) system call */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define HASFCHMOD 0 /* does not have fchmod(2) syscall */
# define HASSETREUID 1 /* use setreuid(2) -lbsd system call */
# define HASSETVBUF 1 /* use setvbuf(2) system call */
# define HASSETRLIMIT 0 /* does not have setrlimit call */
# define HASFLOCK 0 /* does not have flock call - use fcntl */
# define HASULIMIT 1 /* use ulimit instead of setrlimit call */
# define NEEDGETOPT 1 /* Do we need theirs or ours */
# define SYS5SETPGRP 1 /* don't have setpgid on AIX/RT */
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
# define BSD4_3 1 /* NOT bsd 4.4 or posix signals */
# define GIDSET_T int
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# define SPT_PADCHAR '\0' /* pad process title with nulls */
# define LA_TYPE LA_SUBR /* use our ported loadavgd daemon */
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# define ARBPTR_T int *
# define void int
typedef int pid_t;
/* RTisms for BSD compatibility, specified in the Makefile
define BSD 1
define BSD_INCLUDES 1
define BSD_REMAP_SIGNAL_TO_SIGVEC
RTisms needed above */
/* make this sendmail in a completely different place */
# define _PATH_VENDORCF "/usr/local/newmail/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/usr/local/newmail/sendmail.pid"
# endif
#endif
/*
** Silicon Graphics IRIX
**
@ -238,13 +291,30 @@ extern void hard_syslog(int, char *, ...);
**
** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0).
** Use IRIX5 instead of IRIX for IRIX 5.x.
**
** This version tries to be adaptive using _MIPS_SIM:
** _MIPS_SIM == _ABIO32 (= 1) Abi: -32 on IRIX 6.2
** _MIPS_SIM == _ABIN32 (= 2) Abi: -n32 on IRIX 6.2
** _MIPS_SIM == _ABI64 (= 3) Abi: -64 on IRIX 6.2
**
** _MIPS_SIM is 1 also on IRIX 5.3
**
** IRIX64 changes from Mark R. Levinson <ml@cvdev.rochester.edu>.
** IRIX5 changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>.
** Adaptive changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>.
*/
#if defined(IRIX64) || defined(IRIX5)
# define IRIX
#if defined(__sgi)
# ifndef IRIX
# define IRIX
# endif
# if _MIPS_SIM > 0 && !defined(IRIX5)
# define IRIX5 /* IRIX5 or IRIX6 */
# endif
# if _MIPS_SIM > 1 && !defined(IRIX6) && !defined(IRIX64)
# define IRIX6 /* IRIX6 */
# endif
#endif
#ifdef IRIX
@ -254,18 +324,24 @@ extern void hard_syslog(int, char *, ...);
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define IP_SRCROUTE 1 /* can check IP source routing */
# define FORK fork /* no vfork primitive available */
# define setpgid BSDsetpgrp
# define GIDSET_T gid_t
# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
# define SFS_BAVAIL f_bfree /* alternate field name */
# define LA_TYPE LA_INT
# ifdef IRIX64
# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */
# ifdef IRIX6
# define LA_TYPE LA_IRIX6 /* figure out at run time */
# else
# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
# define LA_TYPE LA_INT
# ifdef IRIX64
# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */
# else
# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */
# endif
# endif
# if defined(IRIX64) || defined(IRIX5)
# if defined(IRIX64) || defined(IRIX5)
# include <sys/cdefs.h>
# include <paths.h>
# define ARGV_T char *const *
# define HASSETRLIMIT 1 /* has setrlimit(2) syscall */
# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */
@ -290,10 +366,16 @@ extern void hard_syslog(int, char *, ...);
# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
# define IP_SRCROUTE 1 /* can check IP source routing */
# define LA_TYPE LA_INT
# ifndef LA_TYPE
# define LA_TYPE LA_INT
# endif
# ifdef SOLARIS_2_3
# define SOLARIS 203 /* for back compat only -- use -DSOLARIS=203 */
# define SOLARIS 20300 /* for back compat only -- use -DSOLARIS=20300 */
# endif
# if defined(NOT_SENDMAIL) && !defined(SOLARIS) && defined(sun) && (defined(__svr4__) || defined(__SVR4))
# define SOLARIS 1 /* unknown Solaris version */
# endif
# ifdef SOLARIS
@ -303,6 +385,7 @@ extern void hard_syslog(int, char *, ...);
# endif
# include <sys/time.h>
# define GIDSET_T gid_t
# define USE_SA_SIGACTION 1 /* use sa_sigaction field */
# ifndef _PATH_UNIX
# define _PATH_UNIX "/dev/ksyms"
# endif
@ -316,6 +399,20 @@ extern void hard_syslog(int, char *, ...);
# ifndef SYSLOG_BUFSIZE
# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */
# endif
# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203)
# define USESETEUID 1 /* seteuid works as of 2.3 */
# endif
# if SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205)
# define HASSNPRINTF 1 /* has snprintf starting in 2.5 */
# define HASSETREUID 1 /* setreuid works as of 2.5 */
# if SOLARIS == 20500 || SOLARIS == 205
# define snprintf __snprintf /* but names it oddly in 2.5 */
# define vsnprintf __vsnprintf
# endif
# endif
# ifndef HASGETUSERSHELL
# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */
# endif
# else
/* SunOS 4.0.3 or 4.1.x */
@ -432,8 +529,6 @@ extern long dgux_inet_addr();
#ifdef __ksr__
# define __osf__ 1 /* get OSF/1 defines below */
# define FORK fork /* no vfork primitive available */
# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
# ifndef TZ_TYPE
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# endif
@ -449,12 +544,16 @@ extern long dgux_inet_addr();
#ifdef __PARAGON__
# define __osf__ 1 /* get OSF/1 defines below */
# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
# ifndef TZ_TYPE
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# endif
#endif
/*
** OSF/1 (tested on Alpha)
** OSF/1 (tested on Alpha) -- now known as Digital UNIX.
**
** Tested for 3.2 and 4.0.
*/
#ifdef __osf__
@ -468,6 +567,7 @@ extern long dgux_inet_addr();
# endif
# define LA_TYPE LA_INT
# define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */
# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/var/run/sendmail.pid"
# endif
@ -487,6 +587,7 @@ extern long dgux_inet_addr();
# define NEEDGETOPT 1 /* need a replacement for getopt(3) */
# define WAITUNION 1 /* use "union wait" as wait argument type */
# define UID_T int /* compiler gripes on uid_t */
# define GID_T int /* ditto for gid_t */
# define sleep sleepX
# define setpgid setpgrp
# ifndef LA_TYPE
@ -512,6 +613,7 @@ typedef int pid_t;
*/
#if defined(BSD4_4) && !defined(__bsdi__)
# include <paths.h>
# define HASUNSETENV 1 /* has unsetenv(3) call */
# define USESETEUID 1 /* has useable seteuid(2) call */
# define HASFCHMOD 1 /* has fchmod(2) syscall */
@ -529,11 +631,12 @@ typedef int pid_t;
/*
** BSD/386 (all versions)
** BSD/OS (was BSD/386) (all versions)
** From Tony Sanders, BSDI
*/
#ifdef __bsdi__
# include <paths.h>
# define HASUNSETENV 1 /* has the unsetenv(3) call */
# define HASSETSID 1 /* has the setsid(2) POSIX syscall */
# define USESETEUID 1 /* has useable seteuid(2) call */
@ -592,25 +695,25 @@ typedef int pid_t;
# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1)
# undef SPT_TYPE
# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */
# define setreuid __setreuid
# endif
# if defined(__FreeBSD__)
# undef SPT_TYPE
# if __FreeBSD__ == 2
# include <osreldate.h> /* and this works */
# if __FreeBSD_version >= 199512 /* 2.2-current right now */
# define SPT_TYPE SPT_BUILTIN
# include <libutil.h>
# define SPT_TYPE SPT_BUILTIN
# endif
# endif
# ifndef SPT_TYPE
# define SPT_TYPE SPT_REUSEARGV
# define SPT_PADCHAR '\0' /* pad process title with nulls */
# define SPT_PADCHAR '\0' /* pad process title with nulls */
# endif
# endif
#endif
/*
** Mach386
**
@ -672,36 +775,63 @@ extern int errno;
/*
** SCO Unix
**
** This includes two parts -- the first is for SCO Open Server 3.2v4
** (contributed by Philippe Brand <phb@colombo.telesys-innov.fr>).
** The second is, I believe, for an older version.
** This includes three parts:
**
** The first is for SCO OpenServer 5.
** (Contributed by Keith Reynolds <keithr@sco.COM>).
**
** SCO OpenServer 5 has a compiler version number macro,
** which we can use to figure out what version we're on.
** This may have to change in future releases.
**
** The second is for SCO UNIX 3.2v4.2/Open Desktop 3.0.
** (Contributed by Philippe Brand <phb@colombo.telesys-innov.fr>).
**
** The third is for SCO UNIX 3.2v4.0/Open Desktop 2.0 and earlier.
*/
#if _SCO_DS >= 1
# include <paths.h>
# define _SCO_unix_4_2
# define HASSNPRINTF 1 /* has snprintf() call */
# define HASFCHMOD 1 /* has fchmod() call */
# define HASSETRLIMIT 1 /* has setrlimit() call */
# define RLIMIT_NEEDS_SYS_TIME_H 1
#endif
#ifdef _SCO_unix_4_2
# define _SCO_unix_
# define HASSETREUID 1 /* has setreuid(2) call */
# define _PATH_UNIX "/unix"
# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/etc/sendmail.pid"
# endif
#endif
#ifdef _SCO_unix_
# include <sys/stream.h> /* needed for IP_SRCROUTE */
# define SYSTEM5 1 /* include all the System V defines */
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define NOFTRUNCATE 0 /* does not have ftruncate(3) call */
# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
# define FORK fork
# define MAXPATHLEN PATHSIZE
# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_4ARGS /* use <sys/statfs.h> 4-arg impl */
# define SFS_BAVAIL f_bfree /* alternate field name */
# define SPT_TYPE SPT_SCO /* write kernel u. area */
# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
# define NETUNIX 0 /* no unix domain socket support */
# define _PATH_UNIX "/unix"
# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/etc/sendmail.pid"
# endif
/* stuff fixed in later releases */
# ifndef _SCO_unix_4_2
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# endif
# ifndef _SCO_DS
# define NOFTRUNCATE 0 /* does not have ftruncate(3) call */
# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
# define NETUNIX 0 /* no unix domain socket support */
# endif
#endif
@ -721,7 +851,6 @@ extern int errno;
# define HASSETREUID 1 /* has setreuid(2) call */
# define NEEDFSYNC 1 /* needs the fsync(2) call stub */
# define NETUNIX 0 /* no unix domain socket support */
# define FORK fork
# define MAXPATHLEN 1024
# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
@ -736,22 +865,24 @@ extern int errno;
/*
** Altos System V.
** Contributed by Tim Rice <timr@crl.com>.
** Altos System V (5.3.1)
** Contributed by Tim Rice <tim@trr.metro.net>.
*/
#ifdef ALTOS_SYS_V
#ifdef ALTOS_SYSTEM_V
# include <sys/stream.h>
# include <limits.h>
# define SYSTEM5 1 /* include all the System V defines */
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define WAITUNION 1 /* use "union wait" as wait argument type */
# define NEEDFSYNC 1 /* no fsync(2) in system library */
# define FORK fork
# define MAXPATHLEN PATHSIZE
# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */
# define MAXPATHLEN PATH_MAX
# define LA_TYPE LA_SHORT
# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */
# define SFS_BAVAIL f_bfree /* alternate field name */
# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */
# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */
# define NETUNIX 0 /* no unix domain socket support */
# undef WIFEXITED
# undef WEXITSTATUS
@ -760,6 +891,17 @@ extern int errno;
typedef unsigned short uid_t;
typedef unsigned short gid_t;
typedef short pid_t;
/* some stuff that should have been in the include files */
# include <grp.h>
extern char *malloc();
extern struct passwd *getpwent();
extern struct passwd *getpwnam();
extern struct passwd *getpwuid();
extern char *getenv();
extern struct group *getgrgid();
extern struct group *getgrnam();
#endif
@ -768,13 +910,26 @@ typedef short pid_t;
**
** "Todd C. Miller" <millert@mroe.cs.colorado.edu> claims this
** works on 9.1 as well.
**
** ConvexOS 11.5 and later, should work on 11.0 as defined.
** For pre-ConvexOOS 11.0, define NEEDGETOPT, undef IDENTPROTO
**
** Eric Schnoebelen (eric@cirr.com) For CONVEX Computer Corp.
** (now the CONVEX Technologies Center of Hewlett Packard)
*/
#ifdef _CONVEX_SOURCE
# define BSD 1 /* include all the BSD defines */
# define HASGETDTABLESIZE 1 /* has getdtablesize(2) */
# define HASINITGROUPS 1 /* has initgroups(3) */
# define HASUNAME 1 /* use System V uname(2) system call */
# define HASSETSID 1 /* has POSIX setsid(2) call */
# define NEEDGETOPT 1 /* need replacement for getopt(3) */
# define HASUNSETENV 1 /* has unsetenv(3) */
# define HASFLOCK 1 /* has flock(2) */
# define HASSETRLIMIT 1 /* has setrlimit(2) */
# define HASSETREUID 1 /* has setreuid(2) */
# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_error=0 */
# define NEEDPUTENV 1 /* needs putenv (written in terms of setenv) */
# define NEEDGETOPT 0 /* need replacement for getopt(3) */
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
# define LA_TYPE LA_FLOAT
# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */
@ -787,8 +942,23 @@ typedef short pid_t;
# define S_IFCHR _S_IFCHR
# define S_IFBLK _S_IFBLK
# endif
# ifndef TZ_TYPE
# define TZ_TYPE TZ_TIMEZONE
# endif
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# define IDENTPROTO 1
# endif
# ifndef SHARE_V1
# define SHARE_V1 1 /* version 1 of the fair share scheduler */
# endif
# if !defined(__GNUC__ )
# define UID_T int /* GNUC gets it right, ConvexC botches */
# define GID_T int /* GNUC gets it right, ConvexC botches */
# endif
# if SECUREWARE
# define FORK fork /* SecureWare wants the real fork! */
# else
# define FORK vfork /* the rest of the OS versions don't care */
# endif
#endif
@ -839,9 +1009,14 @@ extern void *malloc();
** Florian La Roche <rzsfl@rz.uni-sb.de>
** Karl London <karl@borg.demon.co.uk>
**
** Last compiled against: [09/06/95 @ 10:20:58 AM (Wednesday)]
** sendmail 8.7-b14 named 4.9.3-beta17 db-1.85
** gcc 2.7.0 libc-5.2.7 linux 1.2.13
** Last compiled against: [06/10/96 @ 09:21:40 PM (Monday)]
** sendmail 8.8-a4 named bind-4.9.4-T4B db-1.85
** gcc 2.7.2 libc-5.3.12 linux 2.0.0
**
** NOTE: Override HASFLOCK as you will but, as of 1.99.6, mixed-style
** file locking is no longer allowed. In particular, make sure
** your DBM library and sendmail are both using either flock(2)
** *or* fcntl(2) file locking, but not both.
*/
#ifdef __linux__
@ -857,7 +1032,12 @@ extern void *malloc();
# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */
# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */
# ifndef HASFLOCK
# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */
# include <linux/version.h>
# if LINUX_VERSION_CODE < 66399
# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */
# else
# define HASFLOCK 1 /* flock(2) fixed after 1.3.95 */
# endif
# endif
# ifndef LA_TYPE
# define LA_TYPE LA_PROCSTR
@ -907,7 +1087,6 @@ extern void *malloc();
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
# define FORK fork
# ifndef LA_TYPE
# define LA_TYPE LA_INT
# define FSHIFT 16
@ -937,7 +1116,6 @@ extern void *malloc();
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */
# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */
# define FORK fork /* no vfork(2) primitive available */
# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */
# define MAXPATHLEN PATH_MAX
extern struct passwd *getpwent(), *getpwnam(), *getpwuid();
@ -1010,9 +1188,12 @@ typedef int pid_t;
** For DYNIX/ptx v1.x, undefine HASSETREUID.
**
** From Tim Wright <timw@sequent.com>.
** Update from Jack Woolley <jwoolley@sctcorp.com>, 26 Dec 1995,
** for DYNIX/ptx 4.0.2.
*/
#ifdef _SEQUENT_
# include <sys/stream.h>
# define SYSTEM5 1 /* include all the System V defines */
# define HASSETSID 1 /* has POSIX setsid(2) call */
# define HASINITGROUPS 1 /* has initgroups(3) call */
@ -1076,6 +1257,7 @@ typedef int pid_t;
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
# define RLIMIT_NEEDS_SYS_TIME_H 1
#endif
@ -1138,18 +1320,30 @@ typedef int pid_t;
/*
** NCR 3000 Series (SysVr4)
** NCR MP-RAS 2.x (SysVr4) with Wollongong TCP/IP
**
** From Kevin Darcy <kevin@tech.mis.cfc.com>.
*/
#ifdef NCR3000
#ifdef NCR_MP_RAS2
# include <sys/sockio.h>
# define __svr4__
# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */
# undef BSD
# define LA_AVENRUN "avenrun"
# define SYSLOG_BUFSIZE 1024
# define SPT_TYPE SPT_NONE
#endif
/*
** NCR MP-RAS 3.x (SysVr4) with STREAMware TCP/IP
**
** From Tom Moore <Tom.Moore@DaytonOH.NCR.COM>
*/
#ifdef NCR_MP_RAS3
# define __svr4__
# define SYSLOG_BUFSIZE 1024
# define SPT_TYPE SPT_NONE
#endif
@ -1372,20 +1566,75 @@ extern int errno;
** Fujitsu/ICL UXP/DS (For the DS/90 Series)
**
** From Diego R. Lopez <drlopez@cica.es>.
** Additional changes from Fumio Moriya and Toshiaki Nomura of the
** Fujitsu Fresoftware gruop <dsfrsoft@oai6.yk.fujitsu.co.jp>.
*/
#ifdef UXPDS
#ifdef __uxp__
# include <arpa/nameser.h>
# include <sys/sysmacros.h>
# include <sys/mkdev.h>
# define __svr4__
# define HASGETUSERSHELL 1
# define HASGETUSERSHELL 0
# define HASFLOCK 0
# if UXPDS == 10
# define HASSNPRINTF 0 /* no snprintf(3) or vsnprintf(3) */
# else
# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */
# endif
# define _PATH_UNIX "/stand/unix"
# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf"
# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf"
# ifndef _PATH_SENDMAILPID
# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid"
# define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid"
# endif
#endif
/*
** Pyramid DC/OSx
**
** From Earle Ake <akee@wpdis01.wpafb.af.mil>.
*/
#ifdef DCOSx
# define GIDSET_T gid_t
# ifndef IDENTPROTO
# define IDENTPROTO 0 /* TCP/IP implementation is broken */
# endif
#endif
/*
** Concurrent Computer Corporation Maxion
**
** From Donald R. Laster Jr. <laster@access.digex.net>.
*/
#ifdef __MAXION__
# include <sys/stream.h>
# define __svr4__ 1 /* SVR4.2MP */
# define HASSETREUID 1 /* have setreuid(2) */
# define HASLSTAT 1 /* have lstat(2) */
# define HASSETRLIMIT 1 /* have setrlimit(2) */
# define HASGETDTABLESIZE 1 /* have getdtablesize(2) */
# define HASSNPRINTF 1 /* have snprintf(3) */
# define HASGETUSERSHELL 1 /* have getusershell(3) */
# define NOFTRUNCATE 1 /* do not have ftruncate(2) */
# define SLEEP_T unsigned
# define SFS_TYPE SFS_STATVFS
# define SFS_BAVAIL f_bavail
# ifndef SYSLOG_BUFSIZE
# define SYSLOG_BUFSIZE 256 /* Use 256 bytes */
# endif
# undef WUNTRACED
# undef WIFEXITED
# undef WIFSIGNALED
# undef WIFSTOPPED
# undef WEXITSTATUS
# undef WTERMSIG
# undef WSTOPSIG
#endif
/**********************************************************************
** End of Per-Operating System defines
@ -1418,13 +1667,16 @@ extern int errno;
# define SYSTEM5 1
# define USESETEUID 1 /* has useable seteuid(2) call */
# define HASINITGROUPS 1 /* has initgroups(3) call */
# define BSD_COMP 1 /* get BSD ioctl calls */
# define BSD_COMP 1 /* get BSD ioctl calls */
# ifndef HASSETRLIMIT
# define HASSETRLIMIT 1 /* has setrlimit(2) call */
# endif
# ifndef HASGETUSERSHELL
# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */
# endif
# ifndef HASFCHMOD
# define HASFCHMOD 1 /* most (all?) SVr4s seem to have fchmod(2) */
# endif
# ifndef _PATH_UNIX
# define _PATH_UNIX "/unix"
@ -1442,6 +1694,7 @@ extern int errno;
# define SFS_TYPE SFS_STATVFS
# endif
/* SVr4 uses different routines for setjmp/longjmp with signal support */
# define jmp_buf sigjmp_buf
# define setjmp(env) sigsetjmp(env, 1)
# define longjmp(env, val) siglongjmp(env, val)
@ -1499,7 +1752,7 @@ extern int errno;
# undef bcopy /* despite SystemV claim, uses BSD bcopy */
#endif
#ifdef ALTOS_SYS_V
#ifdef ALTOS_SYSTEM_V
# undef bcopy /* despite SystemV claim, uses BSD bcopy */
# undef bzero /* despite SystemV claim, uses BSD bzero */
# undef bcmp /* despite SystemV claim, uses BSD bcmp */
@ -1561,6 +1814,10 @@ extern int errno;
# define OLD_NEWDB 0 /* assume newer version of newdb */
#endif
#ifndef SECUREWARE
# define SECUREWARE 0 /* assume no SecureWare C2 auditing hooks */
#endif
/* heuristic setting of HASSETSIGMASK; can override above */
#ifndef HASSIGSETMASK
# ifdef SIGVTALRM
@ -1584,6 +1841,10 @@ extern int errno;
# define UID_T uid_t
#endif
#ifndef GID_T
# define GID_T gid_t
#endif
#ifndef SIZE_T
# define SIZE_T size_t
#endif
@ -1601,6 +1862,9 @@ extern int errno;
#ifndef S_ISREG
# define S_ISREG(foo) ((foo & S_IFMT) == S_IFREG)
#endif
#ifndef S_ISDIR
# define S_ISDIR(foo) ((foo & S_IFMT) == S_IFDIR)
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
# define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK)
#endif
@ -1729,7 +1993,7 @@ struct utsname
};
#endif /* HASUNAME */
#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYS_V)
#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYSTEM_V)
# define MAXHOSTNAMELEN 256
#endif
@ -1809,9 +2073,10 @@ typedef void (*sigfunc_t) __P((int));
*/
# define PSBUFSIZE (MAXNAME + MAXATOM) /* size of prescan buffer */
/* fork routine -- set above using #ifdef _osname_ or in Makefile */
# ifndef FORK
# define FORK vfork /* function to call to fork mailer */
# define FORK fork /* function to call to fork mailer */
# endif
/*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -37,9 +37,9 @@
#ifndef lint
#ifdef DAEMON
static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (with daemon mode)";
static char sccsid[] = "@(#)daemon.c 8.145 (Berkeley) 10/12/96 (with daemon mode)";
#else
static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemon mode)";
static char sccsid[] = "@(#)daemon.c 8.145 (Berkeley) 10/12/96 (without daemon mode)";
#endif
#endif /* not lint */
@ -70,7 +70,7 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** thing yourself, I recommend chucking the entire file
** and starting from scratch. Basic semantics are:
**
** getrequests()
** getrequests(e)
** Opens a port and initiates a connection.
** Returns in a child. Must set InChannel and
** OutChannel appropriately.
@ -80,7 +80,7 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** etc., to avoid having extra file descriptors during
** the queue run and to avoid confusing the network
** code (if it cares).
** makeconnection(host, port, outfile, infile, usesecureport)
** makeconnection(host, port, outfile, infile, e)
** Make a connection to the named host on the given
** port. Set *outfile and *infile to the files
** appropriate for communication. Returns zero on
@ -93,10 +93,12 @@ static char sccsid[] = "@(#)daemon.c 8.119.1.2 (Berkeley) 9/16/96 (without daemo
** GETREQUESTS -- open mail IPC port and get requests.
**
** Parameters:
** none.
** e -- the current envelope.
**
** Returns:
** none.
** TRUE -- if a "null server" should be used -- that is, one
** that rejects all commands.
** FALSE -- to use a normal server.
**
** Side Effects:
** Waits until some interesting activity occurs. When
@ -113,8 +115,9 @@ int ListenQueueSize = 10; /* size of listen queue */
int TcpRcvBufferSize = 0; /* size of TCP receive buffer */
int TcpSndBufferSize = 0; /* size of TCP send buffer */
void
getrequests()
bool
getrequests(e)
ENVELOPE *e;
{
int t;
bool refusingconnections = TRUE;
@ -124,6 +127,7 @@ getrequests()
bool j_has_dot;
#endif
extern void reapchild();
extern int opendaemonsocket __P((bool));
/*
** Set up the address for the mailer.
@ -166,7 +170,7 @@ getrequests()
extern char *CommandLineArgs;
/* write the process id on line 1 */
fprintf(pidf, "%d\n", getpid());
fprintf(pidf, "%ld\n", (long) getpid());
/* line 2 contains all command line flags */
fprintf(pidf, "%s\n", CommandLineArgs);
@ -179,7 +183,7 @@ getrequests()
{
char jbuf[MAXHOSTNAMELEN];
expand("\201j", jbuf, sizeof jbuf, CurEnv);
expand("\201j", jbuf, sizeof jbuf, e);
j_has_dot = strchr(jbuf, '.') != NULL;
}
#endif
@ -195,8 +199,7 @@ getrequests()
extern int getla();
/* see if we are rejecting connections */
CurrentLA = getla();
if (refuseconnections())
if (refuseconnections(ntohs(DaemonAddr.sin.sin_port)))
{
if (DaemonSocket >= 0)
{
@ -220,8 +223,9 @@ getrequests()
/* check for disaster */
{
char jbuf[MAXHOSTNAMELEN];
extern void dumpstate __P((char *));
expand("\201j", jbuf, sizeof jbuf, CurEnv);
expand("\201j", jbuf, sizeof jbuf, e);
if (!wordinclass(jbuf, 'w'))
{
dumpstate("daemon lost $j");
@ -238,7 +242,8 @@ getrequests()
#endif
/* wait for a connection */
setproctitle("accepting connections");
setproctitle("accepting connections on port %d",
ntohs(DaemonAddr.sin.sin_port));
do
{
errno = 0;
@ -277,9 +282,9 @@ getrequests()
if (pid == 0)
{
char *p;
extern char *hostnamebyanyaddr();
extern void intsig();
FILE *inchannel, *outchannel;
bool nullconn;
/*
** CHILD -- return to caller.
@ -296,7 +301,7 @@ getrequests()
/* determine host name */
p = hostnamebyanyaddr(&RealHostAddr);
if (strlen(p) > MAXNAME)
if (strlen(p) > (SIZE_T) MAXNAME)
p[MAXNAME] = '\0';
RealHostName = newstr(p);
setproctitle("startup with %s", p);
@ -313,7 +318,13 @@ getrequests()
OutChannel = outchannel;
DisConnected = FALSE;
/* should we check for illegal connection here? XXX */
/* validate the connection */
HoldErrs = TRUE;
nullconn = !validate_connection(&RealHostAddr, RealHostName, e);
HoldErrs = FALSE;
if (nullconn)
break;
#ifdef XLA
if (!xla_host_ok(RealHostName))
{
@ -323,16 +334,19 @@ getrequests()
#endif
if (tTd(15, 2))
printf("getreq: returning\n");
return;
printf("getreq: returning (normal server)\n");
return FALSE;
}
CurChildren++;
/* parent -- keep track of children */
proc_list_add(pid);
/* close the port so that others will hang (for a while) */
(void) close(t);
}
/*NOTREACHED*/
if (tTd(15, 2))
printf("getreq: returning (null server)\n");
return TRUE;
}
/*
** OPENDAEMONSOCKET -- open the SMTP socket
@ -446,6 +460,7 @@ opendaemonsocket(firsttime)
} while (ntries++ < MAXOPENTRIES && transienterror(saveerrno));
syserr("!opendaemonsocket: server SMTP socket wedged: exiting");
finis();
return -1; /* avoid compiler warning on IRIX */
}
/*
** CLRDAEMON -- reset the daemon connection
@ -536,16 +551,16 @@ setdaemonoptions(p)
#if NETINET
case AF_INET:
if (isascii(*v) && isdigit(*v))
DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v));
DaemonAddr.sin.sin_addr.s_addr = inet_addr(v);
else
{
register struct netent *np;
register struct hostent *hp;
np = getnetbyname(v);
if (np == NULL)
syserr("554 network \"%s\" unknown", v);
hp = sm_gethostbyname(v);
if (hp == NULL)
syserr("554 host \"%s\" unknown", v);
else
DaemonAddr.sin.sin_addr.s_addr = np->n_net;
bcopy(hp->h_addr, &DaemonAddr.sin.sin_addr, INADDRSZ);
}
break;
#endif
@ -630,8 +645,7 @@ setdaemonoptions(p)
** port -- the port number to connect to.
** mci -- a pointer to the mail connection information
** structure to be filled in.
** usesecureport -- if set, use a low numbered (reserved)
** port to provide some rudimentary authentication.
** e -- the current envelope.
**
** Returns:
** An exit code telling whether the connection could be
@ -653,11 +667,11 @@ connecttimeout()
SOCKADDR CurHostAddr; /* address of current host */
int
makeconnection(host, port, mci, usesecureport)
makeconnection(host, port, mci, e)
char *host;
u_short port;
register MCI *mci;
bool usesecureport;
ENVELOPE *e;
{
register int i = 0;
register int s;
@ -691,7 +705,7 @@ makeconnection(host, port, mci, usesecureport)
*p = '\0';
#if NETINET
hid = inet_addr(&host[1]);
if (hid == -1)
if (hid == INADDR_NONE)
#endif
{
/* try it as a host name (avoid MX lookup) */
@ -717,8 +731,11 @@ makeconnection(host, port, mci, usesecureport)
}
if (p == NULL)
{
extern char MsgBuf[];
usrerr("553 Invalid numeric domain spec \"%s\"", host);
mci->mci_status = "5.1.2";
mci->mci_rstatus = newstr(MsgBuf);
return (EX_NOHOST);
}
#if NETINET
@ -728,22 +745,25 @@ makeconnection(host, port, mci, usesecureport)
}
else
{
register char *p = &host[strlen(host) - 1];
hp = sm_gethostbyname(host);
if (hp == NULL && *p == '.')
/* contortion to get around SGI cc complaints */
{
#if NAMED_BIND
int oldopts = _res.options;
register char *p = &host[strlen(host) - 1];
_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
#endif
*p = '\0';
hp = sm_gethostbyname(host);
*p = '.';
if (hp == NULL && *p == '.')
{
#if NAMED_BIND
_res.options = oldopts;
int oldopts = _res.options;
_res.options &= ~(RES_DEFNAMES|RES_DNSRCH);
#endif
*p = '\0';
hp = sm_gethostbyname(host);
*p = '.';
#if NAMED_BIND
_res.options = oldopts;
#endif
}
}
gothostent:
if (hp == NULL)
@ -754,6 +774,7 @@ gothostent:
(errno == ECONNREFUSED && UseNameServer))
{
mci->mci_status = "4.4.3";
mci->mci_rstatus = NULL;
return (EX_TEMPFAIL);
}
#endif
@ -841,7 +862,7 @@ gothostent:
/* save for logging */
CurHostAddr = addr;
if (usesecureport)
if (bitnset(M_SECURE_PORT, mci->mci_mailer->m_flags))
{
int rport = IPPORT_RESERVED - 1;
@ -878,8 +899,8 @@ gothostent:
(void) setsockopt(s, SOL_SOCKET, SO_DEBUG,
(char *)&on, sizeof on);
}
if (CurEnv->e_xfp != NULL)
(void) fflush(CurEnv->e_xfp); /* for debugging */
if (e->e_xfp != NULL)
(void) fflush(e->e_xfp); /* for debugging */
errno = 0; /* for debugging */
/*
@ -889,10 +910,12 @@ gothostent:
if (setjmp(CtxConnectTimeout) == 0)
{
if (TimeOuts.to_connect == 0)
ev = NULL;
else
if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0);
else if (TimeOuts.to_connect != 0)
ev = setevent(TimeOuts.to_connect, connecttimeout, 0);
else
ev = NULL;
if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0)
{
if (ev != NULL)
@ -986,7 +1009,6 @@ myhostname(hostbuf, size)
int size;
{
register struct hostent *hp;
extern bool getcanonname();
if (gethostname(hostbuf, size) < 0)
{
@ -1087,7 +1109,6 @@ getauthinfo(fd)
int nleft;
char ibuf[MAXNAME + 1];
static char hbuf[MAXNAME * 2 + 2];
extern char *hostnamebyanyaddr();
falen = sizeof RealHostAddr;
if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 ||
@ -1104,6 +1125,8 @@ getauthinfo(fd)
{
/* translate that to a host name */
RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr));
if (strlen(RealHostName) > MAXNAME)
RealHostName[MAXNAME - 1] = '\0';
}
if (TimeOuts.to_ident == 0)
@ -1170,6 +1193,9 @@ getauthinfo(fd)
{
p += i;
nleft -= i;
*p = '\0';
if (strchr(ibuf, '\n') != NULL)
break;
}
(void) close(s);
clrevent(ev);
@ -1207,14 +1233,6 @@ getauthinfo(fd)
}
/* p now points to the OSTYPE field */
while (isascii(*p) && isspace(*p))
p++;
if (strncasecmp(p, "other", 5) == 0 &&
(p[5] == ':' || p[5] == ' ' || p[5] == ',' || p[5] == '\0'))
{
/* not useful information */
goto noident;
}
p = strchr(p, ':');
if (p == NULL)
{
@ -1432,25 +1450,28 @@ host_map_lookup(map, name, av, statp)
if (*name != '[')
{
extern bool getcanonname();
if (tTd(9, 1))
printf("host_map_lookup(%s) => ", name);
s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */
if (strlen(name) < sizeof hbuf)
snprintf(hbuf, sizeof hbuf, "%s", name);
if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX))
{
if (tTd(9, 1))
printf("%s\n", hbuf);
cp = map_rewrite(map, hbuf, strlen(hbuf), av);
s->s_namecanon.nc_cname = newstr(cp);
if (bitset(MF_MATCHONLY, map->map_mflags))
{
cp = map_rewrite(map, name, strlen(name), av);
s->s_namecanon.nc_cname = newstr(hbuf);
}
else
{
cp = map_rewrite(map, hbuf, strlen(hbuf), av);
s->s_namecanon.nc_cname = newstr(cp);
}
return cp;
}
else
{
register struct hostent *hp;
s->s_namecanon.nc_errno = errno;
#if NAMED_BIND
s->s_namecanon.nc_herrno = h_errno;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1986, 1995 Eric P. Allman
* Copyright (c) 1986, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -36,9 +36,9 @@
#ifndef lint
#if NAMED_BIND
static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (with name server)";
static char sccsid[] = "@(#)domain.c 8.63 (Berkeley) 9/15/96 (with name server)";
#else
static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (without name server)";
static char sccsid[] = "@(#)domain.c 8.63 (Berkeley) 9/15/96 (without name server)";
#endif
#endif /* not lint */
@ -46,6 +46,7 @@ static char sccsid[] = "@(#)domain.c 8.54.1.2 (Berkeley) 9/16/96 (without name s
#include <errno.h>
#include <resolv.h>
#include <arpa/inet.h>
typedef union
{
@ -53,14 +54,18 @@ typedef union
u_char qb2[PACKETSZ];
} querybuf;
static char MXHostBuf[MAXMXHOSTS*PACKETSZ];
#ifndef MXHOSTBUFSIZE
# define MXHOSTBUFSIZE (128 * MAXMXHOSTS)
#endif
static char MXHostBuf[MXHOSTBUFSIZE];
#ifndef MAXDNSRCH
#define MAXDNSRCH 6 /* number of possible domains to search */
# define MAXDNSRCH 6 /* number of possible domains to search */
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
# define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef NO_DATA
@ -114,32 +119,21 @@ getmxrr(host, mxhosts, droplocalhost, rcode)
u_short pref, type;
u_short localpref = 256;
char *fallbackMX = FallBackMX;
static bool firsttime = TRUE;
bool trycanon = FALSE;
int (*resfunc)();
extern int res_query(), res_search();
u_short prefer[MAXMXHOSTS];
int weight[MAXMXHOSTS];
extern bool getcanonname();
extern int mxrand __P((char *));
if (tTd(8, 2))
printf("getmxrr(%s, droplocalhost=%d)\n", host, droplocalhost);
if (fallbackMX != NULL)
if (fallbackMX != NULL && droplocalhost &&
wordinclass(fallbackMX, 'w'))
{
if (firsttime &&
res_query(FallBackMX, C_IN, T_A,
(u_char *) &answer, sizeof answer) < 0)
{
/* this entry is bogus */
fallbackMX = FallBackMX = NULL;
}
else if (droplocalhost && wordinclass(fallbackMX, 'w'))
{
/* don't use fallback for this pass */
fallbackMX = NULL;
}
firsttime = FALSE;
/* don't use fallback for this pass */
fallbackMX = NULL;
}
*rcode = EX_OK;
@ -356,8 +350,11 @@ punt:
if (p != NULL)
{
*p = '\0';
if (inet_addr(&MXHostBuf[1]) != -1)
if (inet_addr(&MXHostBuf[1]) != INADDR_NONE)
{
nmx++;
*p = ']';
}
else
{
trycanon = TRUE;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)headers.c 8.82.1.2 (Berkeley) 9/16/96";
static char sccsid[] = "@(#)headers.c 8.100 (Berkeley) 9/15/96";
#endif /* not lint */
# include <errno.h>
@ -74,7 +74,6 @@ chompheader(line, def, hdrp, e)
bool cond = FALSE;
bool headeronly;
BITMAP mopts;
char buf[MAXNAME + 1];
if (tTd(31, 6))
{
@ -158,7 +157,6 @@ chompheader(line, def, hdrp, e)
if (bitset(H_EOH, hi->hi_flags))
return (hi->hi_flags);
#ifdef LOTUS_NOTES_HACK
/*
** Horrible hack to work around problem with Lotus Notes SMTP
** mail gateway, which generates From: headers with newlines in
@ -172,7 +170,6 @@ chompheader(line, def, hdrp, e)
while ((p = strchr(fvalue, '\n')) != NULL)
*p = ' ';
}
#endif
/*
** Drop explicit From: if same as what we would generate.
@ -195,46 +192,6 @@ chompheader(line, def, hdrp, e)
(strcmp(fvalue, e->e_from.q_paddr) == 0 ||
strcmp(fvalue, e->e_from.q_user) == 0))
return (hi->hi_flags);
#ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */
#if USERDB
else
{
auto ADDRESS a;
char *fancy;
bool oldSuprErrs = SuprErrs;
extern char *crackaddr();
extern char *udbsender();
/*
** Try doing USERDB rewriting even on fully commented
** names; this saves the "comment" information (such
** as full name) and rewrites the electronic part.
**
** XXX This code doesn't belong here -- parsing should
** XXX not be done during collect() phase because
** XXX error messages can confuse the SMTP phase.
** XXX Setting SuprErrs is a crude hack around this
** XXX problem.
*/
if (OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
SuprErrs = TRUE;
fancy = crackaddr(fvalue);
if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL &&
bitnset(M_CHECKUDB, a.q_mailer->m_flags) &&
(p = udbsender(a.q_user)) != NULL)
{
char *oldg = macvalue('g', e);
define('g', p, e);
expand(fancy, buf, sizeof buf, e);
define('g', oldg, e);
fvalue = buf;
}
SuprErrs = oldSuprErrs;
}
#endif
#endif
}
/* delete default value for this header */
@ -433,6 +390,7 @@ eatheader(e, full)
int hopcnt = 0;
char *msgid;
char buf[MAXLINE];
extern int priencode __P((char *));
/*
** Set up macros for possible expansion in headers.
@ -522,10 +480,6 @@ eatheader(e, full)
while (isascii(*msgid) && isspace(*msgid))
msgid++;
}
/* see if this is a return-receipt header */
if (bitset(H_RECEIPTTO, h->h_flags))
e->e_receiptto = h->h_value;
}
if (tTd(32, 1))
printf("----------------------------\n");
@ -558,11 +512,11 @@ eatheader(e, full)
if (p != NULL)
{
/* (this should be in the configuration file) */
if (strcasecmp(p, "urgent"))
if (strcasecmp(p, "urgent") == 0)
e->e_timeoutclass = TOC_URGENT;
else if (strcasecmp(p, "normal"))
else if (strcasecmp(p, "normal") == 0)
e->e_timeoutclass = TOC_NORMAL;
else if (strcasecmp(p, "non-urgent"))
else if (strcasecmp(p, "non-urgent") == 0)
e->e_timeoutclass = TOC_NONURGENT;
}
@ -807,6 +761,7 @@ crackaddr(addr)
int realcmtlev;
int anglelev, realanglelev;
int copylev;
int bracklev;
bool qmode;
bool realqmode;
bool skipping;
@ -833,9 +788,10 @@ crackaddr(addr)
*/
bp = bufhead = buf;
buflim = &buf[sizeof buf - 5];
buflim = &buf[sizeof buf - 6];
p = addrhead = addr;
copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0;
bracklev = 0;
qmode = realqmode = FALSE;
while ((c = *p++) != '\0')
@ -892,7 +848,8 @@ crackaddr(addr)
realcmtlev++;
if (copylev++ <= 0)
{
*bp++ = ' ';
if (bp != bufhead)
*bp++ = ' ';
*bp++ = c;
}
}
@ -918,20 +875,33 @@ crackaddr(addr)
bp--;
}
/* count nesting on [ ... ] (for IPv6 domain literals) */
if (c == '[')
bracklev++;
else if (c == ']')
bracklev--;
/* check for group: list; syntax */
if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr)
if (c == ':' && anglelev <= 0 && bracklev <= 0 &&
!gotcolon && !ColonOkInAddr)
{
register char *q;
if (*p == ':')
/*
** Check for DECnet phase IV ``::'' (host::user)
** or ** DECnet phase V ``:.'' syntaxes. The latter
** covers ``user@DEC:.tay.myhost'' and
** ``DEC:.tay.myhost::user'' syntaxes (bletch).
*/
if (*p == ':' || *p == '.')
{
/* special case -- :: syntax */
if (cmtlev <= 0 && !qmode)
quoteit = TRUE;
if (copylev > 0 && !skipping)
{
*bp++ = c;
*bp++ = c;
*bp++ = *p;
}
p++;
goto putg;
@ -1086,6 +1056,8 @@ crackaddr(addr)
putg:
if (copylev <= 0 && !putgmac)
{
if (bp > bufhead && bp[-1] == ')')
*bp++ = ' ';
*bp++ = MACROEXPAND;
*bp++ = 'g';
putgmac = TRUE;
@ -1102,7 +1074,11 @@ crackaddr(addr)
*bp++ = '\0';
if (tTd(33, 1))
printf("crackaddr=>`%s'\n", buf);
{
printf("crackaddr=>`");
xputs(buf);
printf("'\n");
}
return (buf);
}
@ -1129,11 +1105,12 @@ crackaddr(addr)
#endif
void
putheader(mci, h, e)
putheader(mci, hdr, e)
register MCI *mci;
register HDR *h;
HDR *hdr;
register ENVELOPE *e;
{
register HDR *h;
char buf[MAX(MAXLINE,BUFSIZ)];
char obuf[MAXLINE];
@ -1142,7 +1119,7 @@ putheader(mci, h, e)
mci->mci_mailer->m_name);
mci->mci_flags |= MCIF_INHEADER;
for (; h != NULL; h = h->h_link)
for (h = hdr; h != NULL; h = h->h_link)
{
register char *p = h->h_value;
extern bool bitintersect();
@ -1155,7 +1132,7 @@ putheader(mci, h, e)
/* suppress Content-Transfer-Encoding: if we are MIMEing */
if (bitset(H_CTE, h->h_flags) &&
bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags))
bitset(MCIF_CVT8TO7|MCIF_CVT7TO8|MCIF_INMIME, mci->mci_flags))
{
if (tTd(34, 11))
printf(" (skipped (content-transfer-encoding))\n");
@ -1166,7 +1143,8 @@ putheader(mci, h, e)
{
if (tTd(34, 11))
printf("\n");
goto vanilla;
put_vanilla_header(h, p, mci);
continue;
}
if (bitset(H_CHECK|H_ACHECK, h->h_flags) &&
@ -1239,31 +1217,7 @@ putheader(mci, h, e)
}
else
{
/* vanilla header line */
register char *nlp;
register char *obp;
vanilla:
obp = obuf;
(void) snprintf(obp, SPACELEFT(obuf, obp), "%.200s: ",
h->h_field);
obp = obuf + strlen(obuf);
while ((nlp = strchr(p, '\n')) != NULL)
{
*nlp = '\0';
snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
sizeof obuf - (obp - obuf) - 1, p);
*nlp = '\n';
putline(obuf, mci);
p = ++nlp;
obp = obuf;
if (*p != ' ' && *p != '\t')
*obp++ = ' ';
}
snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
sizeof obuf - (obp - obuf) - 1, p);
putline(obuf, mci);
put_vanilla_header(h, p, mci);
}
}
@ -1277,7 +1231,7 @@ vanilla:
bitset(EF_HAS8BIT, e->e_flags) &&
!bitset(EF_DONT_MIME, e->e_flags) &&
!bitnset(M_8BITS, mci->mci_mailer->m_flags) &&
!bitset(MCIF_CVT8TO7, mci->mci_flags))
!bitset(MCIF_CVT8TO7|MCIF_CVT7TO8, mci->mci_flags))
{
if (hvalue("MIME-Version", e->e_header) == NULL)
putline("MIME-Version: 1.0", mci);
@ -1294,6 +1248,49 @@ vanilla:
#endif
}
/*
** PUT_VANILLA_HEADER -- output a fairly ordinary header
**
** Parameters:
** h -- the structure describing this header
** v -- the value of this header
** mci -- the connection info for output
**
** Returns:
** none.
*/
void
put_vanilla_header(h, v, mci)
HDR *h;
char *v;
MCI *mci;
{
register char *nlp;
register char *obp;
char obuf[MAXLINE];
(void) snprintf(obuf, sizeof obuf, "%.200s: ", h->h_field);
obp = obuf + strlen(obuf);
while ((nlp = strchr(v, '\n')) != NULL)
{
int l;
l = nlp - v;
if (sizeof obuf - (obp - obuf) < l)
l = sizeof obuf - (obp - obuf);
snprintf(obp, SPACELEFT(obuf, obp), "%.*s", l, v);
putline(obuf, mci);
v += l + 1;
obp = obuf;
if (*v != ' ' && *v != '\t')
*obp++ = ' ';
}
snprintf(obp, SPACELEFT(obuf, obp), "%.*s",
sizeof obuf - (obp - obuf) - 1, v);
putline(obuf, mci);
}
/*
** COMMAIZE -- output a header field, making a comma-translated list.
**
** Parameters:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -39,12 +39,13 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
static char sccsid[] = "@(#)main.c 8.162.1.3 (Berkeley) 9/16/96";
static char sccsid[] = "@(#)main.c 8.211 (Berkeley) 10/12/96";
#endif /* not lint */
#define _DEFINE
#include "sendmail.h"
#include <arpa/inet.h>
#if NAMED_BIND
#include <resolv.h>
#endif
@ -75,14 +76,16 @@ char edata, end;
** See the associated documentation for details.
**
** Author:
** Eric Allman, UCB/INGRES (until 10/81)
** Eric Allman, UCB/INGRES (until 10/81).
** Britton-Lee, Inc., purveyors of fine
** database computers (from 11/81)
** Now back at UCB at the Mammoth project.
** The support of the INGRES Project and Britton-Lee is
** gratefully acknowledged. Britton-Lee in
** particular had absolutely nothing to gain from
** my involvement in this project.
** database computers (11/81 - 10/88).
** International Computer Science Institute
** (11/88 - 9/89).
** UCB/Mammoth Project (10/89 - 7/95).
** InReference, Inc. (8/95 - present).
** The support of the my employers is gratefully acknowledged.
** Few of them (Britton-Lee in particular) have had
** anything to gain from my involvement in this project.
*/
@ -97,6 +100,8 @@ bool Warn_Q_option = FALSE; /* warn about Q option use */
char **SaveArgv; /* argument vector for re-execing */
static void obsolete();
extern void printmailer __P((MAILER *));
extern void tTflag __P((char *));
#ifdef DAEMON
#ifndef SMTP
@ -104,7 +109,7 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR
#endif /* SMTP */
#endif /* DAEMON */
#define MAXCONFIGLEVEL 6 /* highest config version level known */
#define MAXCONFIGLEVEL 7 /* highest config version level known */
int
main(argc, argv, envp)
@ -124,26 +129,40 @@ main(argc, argv, envp)
bool safecf = TRUE;
bool warn_C_flag = FALSE;
char warn_f_flag = '\0';
bool run_in_foreground = FALSE; /* -bD mode */
static bool reenter = FALSE;
struct passwd *pw;
struct stat stb;
struct hostent *hp;
bool nullserver;
char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */
static char rnamebuf[MAXNAME]; /* holds RealUserName */
char *emptyenviron[1];
extern int DtableSize;
extern int optind;
extern int opterr;
extern char *optarg;
extern char **environ;
extern time_t convtime();
extern void intsig();
extern struct hostent *myhostname();
extern char *arpadate();
extern char *getauthinfo();
extern char *getcfname();
extern char *optarg;
extern char **environ;
extern void sigusr1();
extern void sighup();
extern void initmacros __P((ENVELOPE *));
extern void init_md __P((int, char **));
extern int getdtsize __P((void));
extern void tTsetup __P((u_char *, int, char *));
extern void setdefaults __P((ENVELOPE *));
extern void initsetproctitle __P((int, char **, char **));
extern void init_vendor_macros __P((ENVELOPE *));
extern void load_if_names __P((void));
extern void vendor_pre_defaults __P((ENVELOPE *));
extern void vendor_post_defaults __P((ENVELOPE *));
extern void readcf __P((char *, bool, ENVELOPE *));
extern void printqueue __P((void));
extern void sendtoargv __P((char **, ENVELOPE *));
extern void resetlimits __P((void));
/*
@ -159,6 +178,9 @@ main(argc, argv, envp)
}
reenter = TRUE;
/* avoid null pointer dereferences */
TermEscape.te_rv_on = TermEscape.te_rv_off = "";
/* do machine-dependent initializations */
init_md(argc, argv);
@ -205,6 +227,42 @@ main(argc, argv, envp)
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
/* Handle any non-getoptable constructions. */
obsolete(argv);
/*
** Do a quick prescan of the argument list.
*/
#if defined(__osf__) || defined(_AIX3)
# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:x"
#endif
#if defined(sony_news)
# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mN:nO:o:p:q:R:r:sTtUV:vX:"
#endif
#ifndef OPTIONS
# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mN:nO:o:p:q:R:r:sTtUV:vX:"
#endif
opterr = 0;
while ((j = getopt(argc, argv, OPTIONS)) != EOF)
{
switch (j)
{
case 'd':
/* hack attack -- see if should use ANSI mode */
if (strcmp(optarg, "ANSI") == 0)
{
TermEscape.te_rv_on = "\033[7m";
TermEscape.te_rv_off = "\033[0m";
break;
}
tTflag(optarg);
setbuf(stdout, (char *) NULL);
break;
}
}
opterr = 1;
/* set up the blank envelope */
BlankEnvelope.e_puthdr = putheader;
BlankEnvelope.e_putbody = putbody;
@ -247,35 +305,6 @@ main(argc, argv, envp)
}
SaveArgv[i] = NULL;
/* Handle any non-getoptable constructions. */
obsolete(argv);
/*
** Do a quick prescan of the argument list.
*/
#if defined(__osf__) || defined(_AIX3)
# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x"
#endif
#if defined(sony_news)
# define OPTIONS "B:b:C:cd:E:e:F:f:h:IiJ:M:mnO:o:p:q:r:sTtvX:"
#endif
#ifndef OPTIONS
# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:"
#endif
opterr = 0;
while ((j = getopt(argc, argv, OPTIONS)) != EOF)
{
switch (j)
{
case 'd':
tTflag(optarg);
setbuf(stdout, (char *) NULL);
break;
}
}
opterr = 1;
if (tTd(0, 1))
{
int ll;
@ -308,7 +337,7 @@ main(argc, argv, envp)
int ll;
extern char *OsCompileOptions[];
printf(" OS Defines:", Version);
printf(" OS Defines:");
av = OsCompileOptions;
ll = 7;
while (*av != NULL)
@ -332,7 +361,7 @@ main(argc, argv, envp)
#ifdef _PATH_UNIX
printf("Kernel symbols:\t%s\n", _PATH_UNIX);
#endif
printf(" Config file:\t%s\n", getcfname());
printf(" Def Conf file:\t%s\n", getcfname());
printf(" Pid file:\t%s\n", PidFile);
}
@ -342,6 +371,11 @@ main(argc, argv, envp)
/* initialize for setproctitle */
initsetproctitle(argc, argv, envp);
/* clear sendmail's environment */
ExternalEnviron = environ;
emptyenviron[0] = NULL;
environ = emptyenviron;
/* prime the child environment */
setuserenv("AGENT", "sendmail");
@ -351,7 +385,7 @@ main(argc, argv, envp)
(void) setsignal(SIGPIPE, SIG_IGN);
OldUmask = umask(022);
OpMode = MD_DELIVER;
FullName = getenv("NAME");
FullName = getextenv("NAME");
#if NAMED_BIND
if (tTd(8, 8))
@ -393,6 +427,8 @@ main(argc, argv, envp)
while (p != NULL && strchr(&p[1], '.') != NULL)
{
*p = '\0';
if (tTd(0, 4))
printf("\ta.k.a.: %s\n", jbuf);
setclass('w', jbuf);
*p++ = '.';
p = strchr(p, '.');
@ -448,13 +484,6 @@ main(argc, argv, envp)
/* current time */
define('b', arpadate((char *) NULL), CurEnv);
/*
** Find our real host name for future logging.
*/
p = getauthinfo(STDIN_FILENO);
define('_', p, CurEnv);
/*
** Crack argv.
*/
@ -469,6 +498,10 @@ main(argc, argv, envp)
OpMode = MD_PRINT;
else if (strcmp(p, "smtpd") == 0)
OpMode = MD_DAEMON;
else if (strcmp(p, "hoststat") == 0)
OpMode = MD_HOSTSTAT;
else if (strcmp(p, "purgestat") == 0)
OpMode = MD_PURGESTAT;
optind = 1;
while ((j = getopt(argc, argv, OPTIONS)) != EOF)
@ -479,12 +512,15 @@ main(argc, argv, envp)
switch (j = *optarg)
{
case MD_DAEMON:
case MD_FGDAEMON:
# ifdef DAEMON
if (RealUid != 0) {
if (RealUid != 0)
{
usrerr("Permission denied");
exit (EX_USAGE);
exit(EX_USAGE);
}
(void) unsetenv("HOSTALIASES");
vendor_daemon_setup(CurEnv);
/* fall through ... */
# else
usrerr("Daemon mode not implemented");
ExitStat = EX_USAGE;
@ -496,11 +532,16 @@ main(argc, argv, envp)
ExitStat = EX_USAGE;
break;
# endif /* SMTP */
case MD_INITALIAS:
/* fall through ... */
case MD_DELIVER:
case MD_VERIFY:
case MD_TEST:
case MD_INITALIAS:
case MD_PRINT:
case MD_HOSTSTAT:
case MD_PURGESTAT:
case MD_ARPAFTP:
OpMode = j;
break;
@ -557,7 +598,6 @@ main(argc, argv, envp)
{
usrerr("Bad hop count (%s)", optarg);
ExitStat = EX_USAGE;
break;
}
break;
@ -565,6 +605,29 @@ main(argc, argv, envp)
NoAlias = TRUE;
break;
case 'N': /* delivery status notifications */
DefaultNotify |= QHASNOTIFY;
if (strcasecmp(optarg, "never") == 0)
break;
for (p = optarg; p != NULL; optarg = p)
{
p = strchr(p, ',');
if (p != NULL)
*p++ = '\0';
if (strcasecmp(optarg, "success") == 0)
DefaultNotify |= QPINGONSUCCESS;
else if (strcasecmp(optarg, "failure") == 0)
DefaultNotify |= QPINGONFAILURE;
else if (strcasecmp(optarg, "delay") == 0)
DefaultNotify |= QPINGONDELAY;
else
{
usrerr("Invalid -N argument");
ExitStat = EX_USAGE;
}
}
break;
case 'o': /* set option */
setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
break;
@ -595,7 +658,6 @@ main(argc, argv, envp)
case 'q': /* run queue files at intervals */
# ifdef QUEUE
(void) unsetenv("HOSTALIASES");
FullName = NULL;
queuemode = TRUE;
switch (optarg[0])
@ -622,10 +684,41 @@ main(argc, argv, envp)
# endif /* QUEUE */
break;
case 'R': /* DSN RET: what to return */
if (bitset(EF_RET_PARAM, CurEnv->e_flags))
{
usrerr("Duplicate -R flag");
ExitStat = EX_USAGE;
break;
}
CurEnv->e_flags |= EF_RET_PARAM;
if (strcasecmp(optarg, "hdrs") == 0)
CurEnv->e_flags |= EF_NO_BODY_RETN;
else if (strcasecmp(optarg, "full") != 0)
{
usrerr("Invalid -R value");
ExitStat = EX_USAGE;
}
break;
case 't': /* read recipients from message */
GrabTo = TRUE;
break;
case 'U': /* initial (user) submission */
UserSubmission = TRUE;
break;
case 'V': /* DSN ENVID: set "original" envelope id */
if (!xtextok(optarg))
{
usrerr("Invalid syntax in -V flag");
ExitStat = EX_USAGE;
}
else
CurEnv->e_envid = newstr(optarg);
break;
case 'X': /* traffic log file */
endpwent();
setgid(RealGid);
@ -634,6 +727,7 @@ main(argc, argv, envp)
if (TrafficLogFile == NULL)
{
syserr("cannot open %s", optarg);
ExitStat = EX_CANTCREAT;
break;
}
#ifdef HASSETVBUF
@ -706,11 +800,28 @@ main(argc, argv, envp)
#endif
vendor_pre_defaults(CurEnv);
readcf(getcfname(), safecf, CurEnv);
ConfigFileRead = TRUE;
vendor_post_defaults(CurEnv);
/* avoid denial-of-service attacks */
resetlimits();
if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
{
/* drop privileges -- daemon mode done after socket/bind */
if (RunAsGid != 0)
(void) setgid(RunAsGid);
if (RunAsUid != 0)
(void) setuid(RunAsUid);
}
/*
** Find our real host name for future logging.
*/
p = getauthinfo(STDIN_FILENO);
define('_', p, CurEnv);
/* suppress error printing if errors mailed back or whatever */
if (CurEnv->e_errormode != EM_PRINT)
HoldErrs = TRUE;
@ -770,6 +881,10 @@ main(argc, argv, envp)
CurEnv->e_bodytype = NULL;
}
/* tweak default DSN notifications */
if (DefaultNotify == 0)
DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
/* Enforce use of local time (null string overrides this) */
if (TimeZoneSpec == NULL)
unsetenv("TZ");
@ -786,18 +901,49 @@ main(argc, argv, envp)
ConfigLevel, MAXCONFIGLEVEL);
}
/* need MCI cache to have persistence */
if (HostStatDir != NULL && MaxMciCache == 0)
{
HostStatDir = NULL;
printf("Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n");
}
/* need HostStatusDir in order to have SingleThreadDelivery */
if (SingleThreadDelivery && HostStatDir == NULL)
{
SingleThreadDelivery = FALSE;
printf("Warning: HostStatusDirectory required for SingleThreadDelivery\n");
}
if (MeToo)
BlankEnvelope.e_flags |= EF_METOO;
switch (OpMode)
{
case MD_TEST:
/* don't have persistent host status in test mode */
HostStatDir = NULL;
break;
case MD_FGDAEMON:
run_in_foreground = TRUE;
OpMode = MD_DAEMON;
/* fall through ... */
case MD_DAEMON:
/* remove things that don't make sense in daemon mode */
FullName = NULL;
GrabTo = FALSE;
/* arrange to restart on hangup signal */
#ifdef LOG
if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/')
syslog(LOG_WARNING, "daemon invoked without full pathname; kill -1 won't work");
#endif
setsignal(SIGHUP, sighup);
/* workaround: can't seem to release the signal in the parent */
releasesignal(SIGHUP);
break;
case MD_INITALIAS:
@ -908,11 +1054,20 @@ main(argc, argv, envp)
setuserenv("ISP", NULL);
setuserenv("SYSTYPE", NULL);
}
if (ConfigLevel < 7)
{
if (LocalMailer != NULL)
setbitn(M_VRFY250, LocalMailer->m_flags);
if (ProgMailer != NULL)
setbitn(M_VRFY250, ProgMailer->m_flags);
if (FileMailer != NULL)
setbitn(M_VRFY250, FileMailer->m_flags);
}
/* MIME Content-Types that cannot be transfer encoded */
setclass('n', "multipart/signed");
/* MIME message/* subtypes that can be treated as messages */
/* MIME message/xxx subtypes that can be treated as messages */
setclass('s', "rfc822");
/* MIME Content-Transfer-Encodings that can be encoded */
@ -920,11 +1075,36 @@ main(argc, argv, envp)
setclass('e', "8bit");
setclass('e', "binary");
#ifdef USE_B_CLASS
/* MIME Content-Types that should be treated as binary */
setclass('b', "image");
setclass('b', "audio");
setclass('b', "video");
setclass('b', "application/octet-stream");
#endif
/* operate in queue directory */
if (OpMode != MD_TEST && chdir(QueueDir) < 0)
if (OpMode == MD_TEST)
/* nothing -- just avoid further if clauses */ ;
else if (QueueDir == NULL)
{
syserr("QueueDirectory (Q) option must be set");
ExitStat = EX_CONFIG;
}
else if (chdir(QueueDir) < 0)
{
syserr("cannot chdir(%s)", QueueDir);
ExitStat = EX_SOFTWARE;
ExitStat = EX_CONFIG;
}
/* check host status directory for validity */
if (HostStatDir != NULL && !path_is_dir(HostStatDir, FALSE))
{
/* cannot use this value */
if (tTd(0, 2))
printf("Cannot use HostStatusDirectory = %s: %s\n",
HostStatDir, errstring(errno));
HostStatDir = NULL;
}
# ifdef QUEUE
@ -965,7 +1145,7 @@ main(argc, argv, envp)
case MD_PRINT:
/* print the queue */
#ifdef QUEUE
dropenvelope(CurEnv);
dropenvelope(CurEnv, TRUE);
printqueue();
endpwent();
setuid(RealUid);
@ -975,15 +1155,33 @@ main(argc, argv, envp)
finis();
#endif /* QUEUE */
case MD_HOSTSTAT:
mci_traverse_persistent(mci_print_persistent, NULL);
exit(EX_OK);
break;
case MD_PURGESTAT:
mci_traverse_persistent(mci_purge_persistent, NULL);
exit(EX_OK);
break;
case MD_INITALIAS:
/* initialize alias database */
initmaps(TRUE, CurEnv);
endpwent();
setuid(RealUid);
exit(EX_OK);
exit(ExitStat);
case MD_SMTP:
nullserver = FALSE;
/* fall through... */
case MD_DAEMON:
case MD_SMTP:
/* reset DSN parameters */
DefaultNotify = QPINGONFAILURE|QPINGONDELAY;
CurEnv->e_envid = NULL;
CurEnv->e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN);
/* don't open alias database -- done in srvrsmtp */
break;
@ -995,6 +1193,8 @@ main(argc, argv, envp)
if (tTd(0, 15))
{
extern void printrules __P((void));
/* print configuration table (or at least part of it) */
if (tTd(0, 90))
printrules();
@ -1075,8 +1275,9 @@ main(argc, argv, envp)
if (OpMode == MD_DAEMON || QueueIntvl != 0)
{
char dtype[200];
extern bool getrequests __P((ENVELOPE *));
if (!tTd(99, 100))
if (!run_in_foreground && !tTd(99, 100))
{
/* put us in background */
i = fork();
@ -1116,10 +1317,16 @@ main(argc, argv, envp)
pause();
}
# endif /* QUEUE */
dropenvelope(CurEnv);
dropenvelope(CurEnv, TRUE);
#ifdef DAEMON
getrequests();
nullserver = getrequests(CurEnv);
/* drop privileges */
if (RunAsGid != 0)
(void) setgid(RunAsGid);
if (RunAsUid != 0)
(void) setuid(RunAsUid);
/* at this point we are in a child: reset state */
(void) newenvelope(CurEnv, CurEnv);
@ -1129,8 +1336,7 @@ main(argc, argv, envp)
*/
p = getauthinfo(fileno(InChannel));
define('_', p, CurEnv);
define('_', p, &BlankEnvelope);
#endif /* DAEMON */
}
@ -1141,14 +1347,34 @@ main(argc, argv, envp)
*/
if (OpMode == MD_SMTP || OpMode == MD_DAEMON)
smtp(CurEnv);
{
char pbuf[20];
extern void smtp __P((bool, ENVELOPE *));
/*
** Save some macros for check_* rulesets.
*/
define(macid("{client_name}", NULL), RealHostName, &BlankEnvelope);
define(macid("{client_addr}", NULL),
newstr(anynet_ntoa(&RealHostAddr)), &BlankEnvelope);
if (RealHostAddr.sa.sa_family == AF_INET)
snprintf(pbuf, sizeof pbuf, "%d", RealHostAddr.sin.sin_port);
else
snprintf(pbuf, sizeof pbuf, "0");
define(macid("{client_port}", NULL), newstr(pbuf), &BlankEnvelope);
smtp(nullserver, CurEnv);
}
# endif /* SMTP */
clearenvelope(CurEnv, FALSE);
if (OpMode == MD_VERIFY)
{
CurEnv->e_sendmode = SM_VERIFY;
CurEnv->e_errormode = EM_QUIET;
CurEnv->e_errormode = EM_PRINT;
PostMasterCopy = NULL;
HoldErrs = FALSE;
}
else
{
@ -1224,6 +1450,8 @@ main(argc, argv, envp)
*/
finis();
/*NOTREACHED*/
return -1;
}
@ -1264,7 +1492,8 @@ finis()
/* clean up temp files */
CurEnv->e_to = NULL;
dropenvelope(CurEnv);
if (CurEnv->e_id != NULL)
dropenvelope(CurEnv, TRUE);
/* flush any cached connections */
mci_flush(TRUE, NULL);
@ -1307,6 +1536,11 @@ finis()
void
intsig()
{
#ifdef LOG
if (LogLevel > 79)
syslog(LOG_DEBUG, "%s: interrupt",
CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id);
#endif
FileName = NULL;
unlockqueue(CurEnv);
#ifdef XLA
@ -1338,24 +1572,24 @@ intsig()
struct metamac MetaMacros[] =
{
/* LHS pattern matching characters */
'*', MATCHZANY, '+', MATCHANY, '-', MATCHONE,
'=', MATCHCLASS, '~', MATCHNCLASS,
{ '*', MATCHZANY }, { '+', MATCHANY }, { '-', MATCHONE },
{ '=', MATCHCLASS }, { '~', MATCHNCLASS },
/* these are RHS metasymbols */
'#', CANONNET, '@', CANONHOST, ':', CANONUSER,
'>', CALLSUBR,
{ '#', CANONNET }, { '@', CANONHOST }, { ':', CANONUSER },
{ '>', CALLSUBR },
/* the conditional operations */
'?', CONDIF, '|', CONDELSE, '.', CONDFI,
{ '?', CONDIF }, { '|', CONDELSE }, { '.', CONDFI },
/* the hostname lookup characters */
'[', HOSTBEGIN, ']', HOSTEND,
'(', LOOKUPBEGIN, ')', LOOKUPEND,
{ '[', HOSTBEGIN }, { ']', HOSTEND },
{ '(', LOOKUPBEGIN }, { ')', LOOKUPEND },
/* miscellaneous control characters */
'&', MACRODEXPAND,
{ '&', MACRODEXPAND },
'\0'
{ '\0' }
};
#define MACBINDING(name, mid) \
@ -1427,6 +1661,11 @@ disconnect(droplev, e)
printf("don't\n");
return;
}
#ifdef LOG
if (LogLevel > 93)
syslog(LOG_DEBUG, "%s: disconnect level %d",
e->e_id == NULL ? "[NOQUEUE]" : e->e_id, droplev);
#endif
/* be sure we don't get nasty signals */
(void) setsignal(SIGINT, SIG_IGN);
@ -1576,7 +1815,7 @@ auth_warning(e, msg, va_alist)
(void) snprintf(buf, sizeof buf, "%s: ", hostbuf);
p = &buf[strlen(buf)];
VA_START(msg);
vsnprintf(p, sizeof buf - (p - buf), msg, ap);
vsnprintf(p, SPACELEFT(buf, p), msg, ap);
VA_END;
addheader("X-Authentication-Warning", buf, &e->e_header);
#ifdef LOG
@ -1587,6 +1826,31 @@ auth_warning(e, msg, va_alist)
}
}
/*
** GETEXTENV -- get from external environment
**
** Parameters:
** envar -- the name of the variable to retrieve
**
** Returns:
** The value, if any.
*/
char *
getextenv(envar)
const char *envar;
{
char **envp;
int l;
l = strlen(envar);
for (envp = ExternalEnviron; *envp != NULL; envp++)
{
if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
return &(*envp)[l + 1];
}
return NULL;
}
/*
** SETUSERENV -- set an environment in the propogated environment
**
** Parameters:
@ -1611,7 +1875,7 @@ setuserenv(envar, value)
if (value == NULL)
{
value = getenv(envar);
value = getextenv(envar);
if (value == NULL)
return;
}
@ -1650,6 +1914,7 @@ dumpstate(when)
{
#ifdef LOG
register char *j = macvalue('j', CurEnv);
int rs;
syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---",
when,
@ -1664,16 +1929,18 @@ dumpstate(when)
printopenfds(TRUE);
syslog(LOG_DEBUG, "--- connection cache: ---");
mci_dump_all(TRUE);
if (RewriteRules[89] != NULL)
rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
if (rs > 0)
{
int stat;
register char **pvp;
char *pv[MAXATOM + 1];
pv[0] = NULL;
stat = rewrite(pv, 89, 0, CurEnv);
syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---",
stat);
stat = rewrite(pv, rs, 0, CurEnv);
syslog(LOG_DEBUG,
"--- ruleset debug_dumpstate returns stat %d, pv: ---",
stat);
for (pvp = pv; *pvp != NULL; pvp++)
syslog(LOG_DEBUG, "%s", *pvp);
}
@ -1739,6 +2006,7 @@ testmodeline(line, e)
extern char *crackaddr __P((char *));
extern void dump_class __P((STAB *, int));
extern void translate_dollars __P((char *));
extern void help __P((char *));
switch (line[0])
{
@ -1805,7 +2073,10 @@ testmodeline(line, e)
case 'S': /* dump rule set */
rs = strtorwset(&line[2], NULL, ST_FIND);
if (rs < 0)
{
printf("Undefined ruleset %s\n", &line[2]);
return;
}
rw = RewriteRules[rs];
if (rw == NULL)
return;
@ -1827,7 +2098,7 @@ testmodeline(line, e)
putchar(' ');
}
putchar('\n');
} while (rw = rw->r_next);
} while ((rw = rw->r_next) != NULL);
break;
case 'M':
@ -1926,7 +2197,6 @@ testmodeline(line, e)
}
else if (strcasecmp(&line[1], "canon") == 0)
{
auto int rcode = EX_OK;
char host[MAXHOSTNAMELEN];
if (*p == '\0')
@ -1940,9 +2210,8 @@ testmodeline(line, e)
return;
}
strcpy(host, p);
getcanonname(host, sizeof(host), HasWildcardMX, &rcode);
printf("getcanonname(%s) returns %s (%d)\n",
p, host, rcode);
(void) getcanonname(host, sizeof(host), HasWildcardMX);
printf("getcanonname(%s) returns %s\n", p, host);
}
else if (strcasecmp(&line[1], "map") == 0)
{
@ -2006,6 +2275,7 @@ testmodeline(line, e)
p = remotename(q, m, tryflags, &rcode, CurEnv);
printf("Rcode = %d, addr = %s\n",
rcode, p == NULL ? "<NULL>" : p);
e->e_to = NULL;
}
else if (strcasecmp(&line[1], "tryflags") == 0)
{
@ -2061,6 +2331,7 @@ testmodeline(line, e)
else
printf("mailer %s, user %s\n",
a.q_mailer->m_name, a.q_user);
e->e_to = NULL;
}
else
{
@ -2098,7 +2369,10 @@ testmodeline(line, e)
int rs = strtorwset(p, NULL, ST_FIND);
if (rs < 0)
{
printf("Undefined ruleset %s\n", p);
break;
}
stat = rewrite(pvp, rs, 0, e);
if (stat != EX_OK)
printf("== Ruleset %s (%d) status %d\n",

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)parseaddr.c 8.87.1.1 (Berkeley) 9/16/96";
static char sccsid[] = "@(#)parseaddr.c 8.114 (Berkeley) 9/20/96";
#endif /* not lint */
# include "sendmail.h"
@ -169,7 +169,7 @@ parseaddr(addr, a, flags, delim, delimptr, e)
** If there was a parsing failure, mark it for queueing.
*/
if (queueup)
if (queueup && OpMode != MD_INITALIAS)
{
char *msg = "Transient parse error -- message queued for future delivery";
@ -220,14 +220,6 @@ invalidaddr(addr, delimptr)
if (savedelim != '\0')
*delimptr = '\0';
}
#if 0
/* for testing.... */
if (strcmp(addr, "INvalidADDR") == 0)
{
usrerr("553 INvalid ADDRess");
goto addrfailure;
}
#endif
for (; *addr != '\0'; addr++)
{
if ((*addr & 0340) == 0200)
@ -241,7 +233,6 @@ invalidaddr(addr, delimptr)
}
setstat(EX_USAGE);
usrerr("553 Address contained invalid control characters");
addrfailure:
if (delimptr != NULL && savedelim != '\0')
*delimptr = savedelim;
return TRUE;
@ -343,12 +334,12 @@ allocaddr(a, flags, paddr)
static short StateTab[NSTATES][NSTATES] =
{
/* oldst chtype> OPR ATM QST SPC ONE ILL */
/*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB,
/*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB,
/*QST*/ QST, QST, OPR, QST, QST, QST,
/*SPC*/ OPR, ATM, QST, SPC|M, ONE, ILL|MB,
/*ONE*/ OPR, OPR, OPR, OPR, OPR, ILL|MB,
/*ILL*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M,
/*OPR*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB },
/*ATM*/ { OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB },
/*QST*/ { QST, QST, OPR, QST, QST, QST },
/*SPC*/ { OPR, ATM, QST, SPC|M, ONE, ILL|MB },
/*ONE*/ { OPR, OPR, OPR, OPR, OPR, ILL|MB },
/*ILL*/ { OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M },
};
/* token type table -- it gets modified with $o characters */
@ -444,6 +435,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
register int c;
char **avp;
bool bslashmode;
bool route_syntax;
int cmntcnt;
int anglecnt;
char *tok;
@ -483,6 +475,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
q = pvpbuf;
bslashmode = FALSE;
route_syntax = FALSE;
cmntcnt = 0;
anglecnt = 0;
avp = av;
@ -510,7 +503,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
if (q >= &pvpbuf[pvpbsize - 5])
{
usrerr("553 Address too long");
if (strlen(addr) > MAXNAME)
if (strlen(addr) > (SIZE_T) MAXNAME)
addr[MAXNAME] = '\0';
returnnull:
if (delimptr != NULL)
@ -548,9 +541,19 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
p--;
}
else if (c == delim && anglecnt <= 0 &&
cmntcnt <= 0 && state != QST)
break;
else if (c == delim && cmntcnt <= 0 && state != QST)
{
if (anglecnt <= 0)
break;
/* special case for better error management */
if (delim == ',' && !route_syntax)
{
usrerr("653 Unbalanced '<'");
c = '>';
p--;
}
}
if (tTd(22, 101))
printf("c=%c, s=%d; ", c, state);
@ -600,7 +603,15 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
else if (cmntcnt > 0)
c = NOCHAR;
else if (c == '<')
{
char *q = p;
anglecnt++;
while (isascii(*q) && isspace(*q))
q++;
if (*q == '@')
route_syntax = TRUE;
}
else if (c == '>')
{
if (anglecnt <= 0)
@ -610,6 +621,7 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab)
}
else
anglecnt--;
route_syntax = FALSE;
}
else if (delim == ' ' && isascii(c) && isspace(c))
c = ' ';
@ -743,10 +755,11 @@ rewrite(pvp, ruleset, reclevel, e)
int loopcount;
struct match mlist[MAXMATCH]; /* stores match on LHS */
char *npvp[MAXATOM+1]; /* temporary space for rebuild */
extern int callsubr __P((char**, int, ENVELOPE *));
if (OpMode == MD_TEST || tTd(21, 1))
{
printf("rewrite: ruleset %2d input:", ruleset);
printf("rewrite: ruleset %3d input:", ruleset);
printav(pvp);
}
if (ruleset < 0 || ruleset >= MAXRWSETS)
@ -772,6 +785,12 @@ rewrite(pvp, ruleset, reclevel, e)
loopcount = 0;
for (rwr = RewriteRules[ruleset]; rwr != NULL; )
{
int stat;
/* if already canonical, quit now */
if (pvp[0] != NULL && (pvp[0][0] & 0377) == CANONNET)
break;
if (tTd(21, 12))
{
printf("-----trying rule:");
@ -1002,8 +1021,6 @@ rewrite(pvp, ruleset, reclevel, e)
rvp++;
rwr = NULL;
}
else if ((*rp & 0377) == CANONNET)
rwr = NULL;
/* substitute */
for (avp = npvp; *rvp != NULL; rvp++)
@ -1091,6 +1108,7 @@ rewrite(pvp, ruleset, reclevel, e)
char *argvect[10];
char pvpbuf[PSBUFSIZE];
char *nullpvp[1];
extern char *map_lookup __P((STAB *, char *, char **, int *, ENVELOPE *));
if ((**rvp & 0377) != HOSTBEGIN &&
(**rvp & 0377) != LOOKUPBEGIN)
@ -1173,55 +1191,7 @@ rewrite(pvp, ruleset, reclevel, e)
/* look it up */
cataddr(key_rvp, NULL, buf, sizeof buf, '\0');
argvect[0] = buf;
if (e->e_sendmode == SM_DEFER)
{
/* don't do any map lookups */
if (tTd(60, 1))
printf("map_lookup(%s, %s) => DEFERRED\n",
mapname, buf);
replac = NULL;
rstat = EX_TEMPFAIL;
}
else if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags))
{
auto int stat = EX_OK;
if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
stripquotes(buf);
/* XXX should try to auto-open the map here */
if (tTd(60, 1))
printf("map_lookup(%s, %s) => ",
mapname, buf);
replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
buf, argvect, &stat);
if (tTd(60, 1))
printf("%s (%d)\n",
replac ? replac : "NOT FOUND",
stat);
/* should recover if stat == EX_TEMPFAIL */
if (stat == EX_TEMPFAIL)
{
rstat = EX_TEMPFAIL;
if (tTd(60, 1))
printf("map_lookup(%s, %s) tempfail: errno=%d\n",
mapname, buf, errno);
if (e->e_message == NULL)
{
char mbuf[300];
snprintf(mbuf, sizeof mbuf,
"%.80s map: lookup (%s): deferred",
mapname,
shortenstring(buf, 203));
e->e_message = newstr(mbuf);
}
}
}
else
replac = NULL;
replac = map_lookup(map, buf, argvect, &rstat, e);
/* if no replacement, use default */
if (replac == NULL && default_rvp != NULL)
@ -1273,38 +1243,16 @@ rewrite(pvp, ruleset, reclevel, e)
** Check for subroutine calls.
*/
if (*npvp != NULL && (**npvp & 0377) == CALLSUBR)
{
int stat;
stat = callsubr(npvp, reclevel, e);
if (rstat == EX_OK || stat == EX_TEMPFAIL)
rstat = stat;
if (npvp[1] == NULL)
{
syserr("parseaddr: NULL subroutine call in ruleset %d, rule %d",
ruleset, ruleno);
*pvp = NULL;
}
else
{
int ruleset;
STAB *s;
bcopy((char *) &npvp[2], (char *) pvp,
(int) (avp - npvp - 2) * sizeof *avp);
if (tTd(21, 3))
printf("-----callsubr %s\n", npvp[1]);
ruleset = strtorwset(npvp[1], NULL, ST_FIND);
stat = rewrite(pvp, ruleset, reclevel, e);
if (rstat == EX_OK || stat == EX_TEMPFAIL)
rstat = stat;
if (*pvp != NULL && (**pvp & 0377) == CANONNET)
rwr = NULL;
}
}
else
{
bcopy((char *) npvp, (char *) pvp,
(int) (avp - npvp) * sizeof *avp);
}
/* copy vector back into original space. */
for (avp = npvp; *avp++ != NULL;)
continue;
bcopy((char *) npvp, (char *) pvp,
(int) (avp - npvp) * sizeof *avp);
if (tTd(21, 4))
{
printf("rewritten as:");
@ -1314,13 +1262,192 @@ rewrite(pvp, ruleset, reclevel, e)
if (OpMode == MD_TEST || tTd(21, 1))
{
printf("rewrite: ruleset %2d returns:", ruleset);
printf("rewrite: ruleset %3d returns:", ruleset);
printav(pvp);
}
return rstat;
}
/*
** CALLSUBR -- call subroutines in rewrite vector
**
** Parameters:
** pvp -- pointer to token vector.
** reclevel -- the current recursion level.
** e -- the current envelope.
**
** Returns:
** The status from the subroutine call.
**
** Side Effects:
** pvp is modified.
*/
int
callsubr(pvp, reclevel, e)
char **pvp;
int reclevel;
ENVELOPE *e;
{
char **avp;
char **rvp;
register int i;
int subr;
int stat;
int rstat = EX_OK;
char *tpvp[MAXATOM + 1];
for (avp = pvp; *avp != NULL; avp++)
{
if ((**avp & 0377) == CALLSUBR && avp[1] != NULL)
{
subr = strtorwset(avp[1], NULL, ST_FIND);
if (subr < 0)
{
syserr("Unknown ruleset %s", avp[1]);
return EX_CONFIG;
}
if (tTd(21, 3))
printf("-----callsubr %s (%d)\n", avp[1], subr);
/*
** Take care of possible inner calls first.
** use a full size temporary buffer to avoid
** overflows in rewrite, but strip off the
** subroutine call.
*/
for (i = 2; avp[i] != NULL; i++)
tpvp[i - 2] = avp[i];
tpvp[i - 2] = NULL;
stat = callsubr(tpvp, reclevel, e);
if (rstat == EX_OK || stat == EX_TEMPFAIL)
rstat = stat;
/*
** Now we need to call the ruleset specified for
** the subroutine. we can do this with the
** temporary buffer that we set up earlier,
** since it has all the data we want to rewrite.
*/
stat = rewrite(tpvp, subr, reclevel, e);
if (rstat == EX_OK || stat == EX_TEMPFAIL)
rstat = stat;
/*
** Find length of tpvp and current offset into
** pvp, if the total is greater than MAXATOM,
** then it would overflow the buffer if we copied
** it back in to pvp, in which case we throw a
** fit.
*/
for (rvp = tpvp; *rvp != NULL; rvp++)
continue;
if (((rvp - tpvp) + (avp - pvp)) > MAXATOM)
{
syserr("554 callsubr: expansion too long");
return EX_DATAERR;
}
/*
** Now we can copy the rewritten code over
** the initial subroutine call in the buffer.
*/
for (i = 0; tpvp[i] != NULL; i++)
avp[i] = tpvp[i];
avp[i] = NULL;
/*
** If we got this far, we've processed the left
** most subroutine, and recursively called ourselves
** to handle any other subroutines. We're done.
*/
break;
}
}
return rstat;
}
/*
** MAP_LOOKUP -- do lookup in map
**
** Parameters:
** map -- the map to use for the lookup.
** key -- the key to look up.
** argvect -- arguments to pass to the map lookup.
** pstat -- a pointer to an integer in which to store the
** status from the lookup.
** e -- the current envelope.
**
** Returns:
** The result of the lookup.
** NULL -- if there was no data for the given key.
*/
char *
map_lookup(map, key, argvect, pstat, e)
STAB *map;
char key[];
char **argvect;
int *pstat;
ENVELOPE *e;
{
auto int stat = EX_OK;
char *replac;
if (e->e_sendmode == SM_DEFER)
{
/* don't do any map lookups */
if (tTd(60, 1))
printf("map_lookup(%s, %s) => DEFERRED\n",
map->s_name, key);
*pstat = EX_TEMPFAIL;
return NULL;
}
if (map == NULL || !bitset(MF_OPEN, map->s_map.map_mflags))
return NULL;
if (!bitset(MF_KEEPQUOTES, map->s_map.map_mflags))
stripquotes(key);
/* XXX should try to auto-open the map here */
if (tTd(60, 1))
printf("map_lookup(%s, %s) => ",
map->s_name, key);
replac = (*map->s_map.map_class->map_lookup)(&map->s_map,
key, argvect, &stat);
if (tTd(60, 1))
printf("%s (%d)\n",
replac != NULL ? replac : "NOT FOUND",
stat);
/* should recover if stat == EX_TEMPFAIL */
if (stat == EX_TEMPFAIL && !bitset(MF_NODEFER, map->s_map.map_mflags))
{
*pstat = EX_TEMPFAIL;
if (tTd(60, 1))
printf("map_lookup(%s, %s) tempfail: errno=%d\n",
map->s_name, key, errno);
if (e->e_message == NULL)
{
char mbuf[300];
snprintf(mbuf, sizeof mbuf,
"%.80s map: lookup (%s): deferred",
map->s_name,
shortenstring(key, 203));
e->e_message = newstr(mbuf);
}
}
return replac;
}
/*
** BUILDADDR -- build address from token vector.
**
** Parameters:
@ -1345,17 +1472,17 @@ struct errcodes
int ec_code; /* numeric code */
} ErrorCodes[] =
{
"usage", EX_USAGE,
"nouser", EX_NOUSER,
"nohost", EX_NOHOST,
"unavailable", EX_UNAVAILABLE,
"software", EX_SOFTWARE,
"tempfail", EX_TEMPFAIL,
"protocol", EX_PROTOCOL,
{ "usage", EX_USAGE },
{ "nouser", EX_NOUSER },
{ "nohost", EX_NOHOST },
{ "unavailable", EX_UNAVAILABLE },
{ "software", EX_SOFTWARE },
{ "tempfail", EX_TEMPFAIL },
{ "protocol", EX_PROTOCOL },
#ifdef EX_CONFIG
"config", EX_CONFIG,
{ "config", EX_CONFIG },
#endif
NULL, EX_UNAVAILABLE,
{ NULL, EX_UNAVAILABLE }
};
ADDRESS *
@ -1386,7 +1513,7 @@ buildaddr(tv, a, flags, e)
bzero((char *) a, sizeof *a);
/* set up default error return flags */
a->q_flags |= QPINGONFAILURE|QPINGONDELAY;
a->q_flags |= DefaultNotify;
/* figure out what net/mailer to use */
if (*tv == NULL || (**tv & 0377) != CANONNET)
@ -1407,7 +1534,7 @@ badaddr:
mname = *++tv;
/* extract host and user portions */
if ((**++tv & 0377) == CANONHOST)
if (*++tv != NULL && (**tv & 0377) == CANONHOST)
hostp = ++tv;
else
hostp = NULL;
@ -1433,6 +1560,8 @@ badaddr:
if (strchr(hbuf, '.') != NULL)
{
extern int dsntoexitstat __P((char *));
a->q_status = newstr(hbuf);
setstat(dsntoexitstat(hbuf));
}
@ -1703,27 +1832,27 @@ struct qflags
struct qflags AddressFlags[] =
{
"QDONTSEND", QDONTSEND,
"QBADADDR", QBADADDR,
"QGOODUID", QGOODUID,
"QPRIMARY", QPRIMARY,
"QQUEUEUP", QQUEUEUP,
"QSENT", QSENT,
"QNOTREMOTE", QNOTREMOTE,
"QSELFREF", QSELFREF,
"QVERIFIED", QVERIFIED,
"QBOGUSSHELL", QBOGUSSHELL,
"QUNSAFEADDR", QUNSAFEADDR,
"QPINGONSUCCESS", QPINGONSUCCESS,
"QPINGONFAILURE", QPINGONFAILURE,
"QPINGONDELAY", QPINGONDELAY,
"QHASNOTIFY", QHASNOTIFY,
"QRELAYED", QRELAYED,
"QEXPANDED", QEXPANDED,
"QDELIVERED", QDELIVERED,
"QDELAYED", QDELAYED,
"QTHISPASS", QTHISPASS,
NULL
{ "QDONTSEND", QDONTSEND },
{ "QBADADDR", QBADADDR },
{ "QGOODUID", QGOODUID },
{ "QPRIMARY", QPRIMARY },
{ "QQUEUEUP", QQUEUEUP },
{ "QSENT", QSENT },
{ "QNOTREMOTE", QNOTREMOTE },
{ "QSELFREF", QSELFREF },
{ "QVERIFIED", QVERIFIED },
{ "QBOGUSSHELL", QBOGUSSHELL },
{ "QUNSAFEADDR", QUNSAFEADDR },
{ "QPINGONSUCCESS", QPINGONSUCCESS },
{ "QPINGONFAILURE", QPINGONFAILURE },
{ "QPINGONDELAY", QPINGONDELAY },
{ "QHASNOTIFY", QHASNOTIFY },
{ "QRELAYED", QRELAYED },
{ "QEXPANDED", QEXPANDED },
{ "QDELIVERED", QDELIVERED },
{ "QDELAYED", QDELAYED },
{ "QTHISPASS", QTHISPASS },
{ NULL }
};
void
@ -1781,10 +1910,14 @@ printaddr(a, follow)
a->q_owner == NULL ? "(none)" : a->q_owner,
a->q_home == NULL ? "(none)" : a->q_home,
a->q_fullname == NULL ? "(none)" : a->q_fullname);
printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n",
printf("\torcpt=\"%s\", statmta=%s, status=%s\n",
a->q_orcpt == NULL ? "(none)" : a->q_orcpt,
a->q_statmta == NULL ? "(none)" : a->q_statmta,
a->q_status == NULL ? "(none)" : a->q_status);
printf("\trstatus=\"%s\"\n",
a->q_rstatus == NULL ? "(none)" : a->q_rstatus);
printf("\tspecificity=%d, statdate=%s\n",
a->q_specificity, ctime(&a->q_statdate));
if (!follow)
return;
@ -1993,7 +2126,12 @@ maplocaluser(a, sendq, aliaslevel, e)
if (pvp == NULL)
return;
(void) rewrite(pvp, 5, 0, e);
if (rewrite(pvp, 5, 0, e) == EX_TEMPFAIL)
{
a->q_flags |= QQUEUEUP;
a->q_status = "4.4.3";
return;
}
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET)
return;
@ -2154,5 +2292,111 @@ dequote_map(map, name, av, statp)
quotemode || quotecnt <= 0 || spacecnt != 0)
return NULL;
*q++ = '\0';
return name;
return map_rewrite(map, name, strlen(name), NULL);
}
/*
** RSCHECK -- check string(s) for validity using rewriting sets
**
** Parameters:
** rwset -- the rewriting set to use.
** p1 -- the first string to check.
** p2 -- the second string to check -- may be null.
** e -- the current envelope.
**
** Returns:
** EX_OK -- if the rwset doesn't resolve to $#error
** else -- the failure status (message printed)
*/
int
rscheck(rwset, p1, p2, e)
char *rwset;
char *p1;
char *p2;
ENVELOPE *e;
{
char *buf;
int bufsize;
int saveexitstat;
int rstat;
char **pvp;
int rsno;
auto ADDRESS a1;
bool saveQuickAbort = QuickAbort;
char buf0[MAXLINE];
char pvpbuf[PSBUFSIZE];
extern char MsgBuf[];
if (tTd(48, 2))
printf("rscheck(%s, %s, %s)\n", rwset, p1,
p2 == NULL ? "(NULL)" : p2);
rsno = strtorwset(rwset, NULL, ST_FIND);
if (rsno < 0)
return EX_OK;
if (p2 != NULL)
{
bufsize = strlen(p1) + strlen(p2) + 2;
if (bufsize > sizeof buf0)
buf = xalloc(bufsize);
else
{
buf = buf0;
bufsize = sizeof buf0;
}
(void) snprintf(buf, bufsize, "%s%c%s", p1, CONDELSE, p2);
}
else
{
bufsize = strlen(p1) + 1;
if (bufsize > sizeof buf0)
buf = xalloc(bufsize);
else
{
buf = buf0;
bufsize = sizeof buf0;
}
(void) snprintf(buf, bufsize, "%s", p1);
}
pvp = prescan(buf, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL);
if (pvp == NULL)
{
rstat = EX_DATAERR;
goto finis;
}
(void) rewrite(pvp, rsno, 0, e);
if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET ||
pvp[1] == NULL || strcmp(pvp[1], "error") != 0)
return EX_OK;
/* got an error -- process it */
saveexitstat = ExitStat;
QuickAbort = FALSE;
(void) buildaddr(pvp, &a1, 0, e);
QuickAbort = saveQuickAbort;
rstat = ExitStat;
ExitStat = saveexitstat;
#ifdef LOG
if (LogLevel >= 4)
{
if (p2 == NULL)
syslog(LOG_NOTICE, "Ruleset %s (%s) rejection: %s",
rwset, p1, MsgBuf);
else
syslog(LOG_NOTICE, "Ruleset %s (%s, %s) rejection: %s",
rwset, p1, p2, MsgBuf);
}
#endif
if (QuickAbort)
longjmp(TopFrame, 2);
/* clean up */
finis:
setstat(rstat);
if (buf != buf0)
free(buf);
return rstat;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)readcf.c 8.139 (Berkeley) 11/29/95";
static char sccsid[] = "@(#)readcf.c 8.174 (Berkeley) 10/9/96";
#endif /* not lint */
# include "sendmail.h"
@ -112,10 +112,11 @@ readcf(cfname, safe, e)
char exbuf[MAXLINE];
char pvpbuf[MAXLINE + MAXATOM];
static char *null_list[1] = { NULL };
extern char *munchstring __P((char *, char **));
extern char *munchstring __P((char *, char **, int));
extern void fileclass __P((int, char *, char *, bool, bool));
extern void toomany __P((int, int));
extern void translate_dollars __P((char *));
extern void inithostmaps __P((void));
FileName = cfname;
LineNumber = 0;
@ -246,10 +247,6 @@ readcf(cfname, safe, e)
botch = "$?";
break;
case CONDELSE:
botch = "$|";
break;
case CONDFI:
botch = "$.";
break;
@ -354,16 +351,17 @@ readcf(cfname, safe, e)
rwp = RewriteRules[ruleset];
if (rwp != NULL)
{
if (OpMode == MD_TEST || tTd(37, 1))
printf("WARNING: Ruleset %s has multiple definitions\n",
&bp[1]);
while (rwp->r_next != NULL)
rwp = rwp->r_next;
fprintf(stderr, "WARNING: Ruleset %s redefined\n",
&bp[1]);
}
break;
case 'D': /* macro definition */
mid = macid(&bp[1], &ep);
p = munchstring(ep, NULL);
p = munchstring(ep, NULL, '\0');
define(mid, newstr(p), e);
break;
@ -441,6 +439,13 @@ readcf(cfname, safe, e)
break;
#endif
#ifdef SUN_EXTENSIONS
case 'L': /* lookup macro */
case 'G': /* lookup class */
/* reserved for Sun -- NIS+ database lookup */
goto badline;
#endif
case 'M': /* define mailer */
makemailer(&bp[1]);
break;
@ -499,6 +504,8 @@ readcf(cfname, safe, e)
if (*ep++ == '/')
{
extern bool setvendor __P((char *));
/* extract vendor code */
for (p = ep; isascii(*p) && isalpha(*p); )
p++;
@ -837,13 +844,11 @@ makemailer(line)
auto char *endp;
extern int NextMailer;
extern char **makeargv();
extern char *munchstring();
extern char *munchstring __P((char *, char **, int));
/* allocate a mailer and set up defaults */
m = (struct mailer *) xalloc(sizeof *m);
bzero((char *) m, sizeof *m);
m->m_eol = "\n";
m->m_uid = m->m_gid = 0;
/* collect the mailer name */
for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++)
@ -875,7 +880,7 @@ makemailer(line)
p++;
/* p now points to the field body */
p = munchstring(p, &delimptr);
p = munchstring(p, &delimptr, ',');
/* install the field into the mailer struct */
switch (fcode)
@ -1089,6 +1094,29 @@ makemailer(line)
m->m_diagtype = "smtp";
}
if (m->m_eol == NULL)
{
char **pp;
/* default for SMTP is \r\n; use \n for local delivery */
for (pp = m->m_argv; *pp != NULL; pp++)
{
char *p;
for (p = *pp; *p != '\0'; )
{
if ((*p++ & 0377) == MACROEXPAND && *p == 'u')
break;
}
if (*p != '\0')
break;
}
if (*pp == NULL)
m->m_eol = "\r\n";
else
m->m_eol = "\n";
}
/* enter the mailer into the symbol table */
s = stab(m->m_name, ST_MAILER, ST_ENTER);
if (s->s_mailer != NULL)
@ -1110,15 +1138,17 @@ makemailer(line)
** p -- the string to munch.
** delimptr -- if non-NULL, set to the pointer of the
** field delimiter character.
** delim -- the delimiter for the field.
**
** Returns:
** the munched string.
*/
char *
munchstring(p, delimptr)
munchstring(p, delimptr, delim)
register char *p;
char **delimptr;
int delim;
{
register char *q;
bool backslash = FALSE;
@ -1157,7 +1187,7 @@ munchstring(p, delimptr)
backslash = TRUE;
else if (*p == '"')
quotemode = !quotemode;
else if (quotemode || *p != ',')
else if (quotemode || *p != delim)
*q++ = *p;
else
break;
@ -1322,17 +1352,17 @@ struct resolverflags
long rf_bits; /* bits to set/clear */
} ResolverFlags[] =
{
"debug", RES_DEBUG,
"aaonly", RES_AAONLY,
"usevc", RES_USEVC,
"primary", RES_PRIMARY,
"igntc", RES_IGNTC,
"recurse", RES_RECURSE,
"defnames", RES_DEFNAMES,
"stayopen", RES_STAYOPEN,
"dnsrch", RES_DNSRCH,
"true", 0, /* to avoid error on old syntax */
NULL, 0
{ "debug", RES_DEBUG },
{ "aaonly", RES_AAONLY },
{ "usevc", RES_USEVC },
{ "primary", RES_PRIMARY },
{ "igntc", RES_IGNTC },
{ "recurse", RES_RECURSE },
{ "defnames", RES_DEFNAMES },
{ "stayopen", RES_STAYOPEN },
{ "dnsrch", RES_DNSRCH },
{ "true", 0 }, /* avoid error on old syntax */
{ NULL, 0 }
};
#endif
@ -1344,108 +1374,112 @@ struct optioninfo
bool o_safe; /* safe for random people to use */
} OptionTab[] =
{
"SevenBitInput", '7', TRUE,
{ "SevenBitInput", '7', TRUE },
#if MIME8TO7
"EightBitMode", '8', TRUE,
{ "EightBitMode", '8', TRUE },
#endif
"AliasFile", 'A', FALSE,
"AliasWait", 'a', FALSE,
"BlankSub", 'B', FALSE,
"MinFreeBlocks", 'b', TRUE,
"CheckpointInterval", 'C', TRUE,
"HoldExpensive", 'c', FALSE,
"AutoRebuildAliases", 'D', FALSE,
"DeliveryMode", 'd', TRUE,
"ErrorHeader", 'E', FALSE,
"ErrorMode", 'e', TRUE,
"TempFileMode", 'F', FALSE,
"SaveFromLine", 'f', FALSE,
"MatchGECOS", 'G', FALSE,
"HelpFile", 'H', FALSE,
"MaxHopCount", 'h', FALSE,
"ResolverOptions", 'I', FALSE,
"IgnoreDots", 'i', TRUE,
"ForwardPath", 'J', FALSE,
"SendMimeErrors", 'j', TRUE,
"ConnectionCacheSize", 'k', FALSE,
"ConnectionCacheTimeout", 'K', FALSE,
"UseErrorsTo", 'l', FALSE,
"LogLevel", 'L', FALSE,
"MeToo", 'm', TRUE,
"CheckAliases", 'n', FALSE,
"OldStyleHeaders", 'o', TRUE,
"DaemonPortOptions", 'O', FALSE,
"PrivacyOptions", 'p', TRUE,
"PostmasterCopy", 'P', FALSE,
"QueueFactor", 'q', FALSE,
"QueueDirectory", 'Q', FALSE,
"DontPruneRoutes", 'R', FALSE,
"Timeout", 'r', TRUE,
"StatusFile", 'S', FALSE,
"SuperSafe", 's', TRUE,
"QueueTimeout", 'T', FALSE,
"TimeZoneSpec", 't', FALSE,
"UserDatabaseSpec", 'U', FALSE,
"DefaultUser", 'u', FALSE,
"FallbackMXhost", 'V', FALSE,
"Verbose", 'v', TRUE,
"TryNullMXList", 'w', TRUE,
"QueueLA", 'x', FALSE,
"RefuseLA", 'X', FALSE,
"RecipientFactor", 'y', FALSE,
"ForkEachJob", 'Y', FALSE,
"ClassFactor", 'z', FALSE,
"RetryFactor", 'Z', FALSE,
{ "AliasFile", 'A', FALSE },
{ "AliasWait", 'a', FALSE },
{ "BlankSub", 'B', FALSE },
{ "MinFreeBlocks", 'b', TRUE },
{ "CheckpointInterval", 'C', TRUE },
{ "HoldExpensive", 'c', FALSE },
{ "AutoRebuildAliases", 'D', FALSE },
{ "DeliveryMode", 'd', TRUE },
{ "ErrorHeader", 'E', FALSE },
{ "ErrorMode", 'e', TRUE },
{ "TempFileMode", 'F', FALSE },
{ "SaveFromLine", 'f', FALSE },
{ "MatchGECOS", 'G', FALSE },
{ "HelpFile", 'H', FALSE },
{ "MaxHopCount", 'h', FALSE },
{ "ResolverOptions", 'I', FALSE },
{ "IgnoreDots", 'i', TRUE },
{ "ForwardPath", 'J', FALSE },
{ "SendMimeErrors", 'j', TRUE },
{ "ConnectionCacheSize", 'k', FALSE },
{ "ConnectionCacheTimeout", 'K', FALSE },
{ "UseErrorsTo", 'l', FALSE },
{ "LogLevel", 'L', TRUE },
{ "MeToo", 'm', TRUE },
{ "CheckAliases", 'n', FALSE },
{ "OldStyleHeaders", 'o', TRUE },
{ "DaemonPortOptions", 'O', FALSE },
{ "PrivacyOptions", 'p', TRUE },
{ "PostmasterCopy", 'P', FALSE },
{ "QueueFactor", 'q', FALSE },
{ "QueueDirectory", 'Q', FALSE },
{ "DontPruneRoutes", 'R', FALSE },
{ "Timeout", 'r', FALSE },
{ "StatusFile", 'S', FALSE },
{ "SuperSafe", 's', TRUE },
{ "QueueTimeout", 'T', FALSE },
{ "TimeZoneSpec", 't', FALSE },
{ "UserDatabaseSpec", 'U', FALSE },
{ "DefaultUser", 'u', FALSE },
{ "FallbackMXhost", 'V', FALSE },
{ "Verbose", 'v', TRUE },
{ "TryNullMXList", 'w', TRUE },
{ "QueueLA", 'x', FALSE },
{ "RefuseLA", 'X', FALSE },
{ "RecipientFactor", 'y', FALSE },
{ "ForkEachJob", 'Y', FALSE },
{ "ClassFactor", 'z', FALSE },
{ "RetryFactor", 'Z', FALSE },
#define O_QUEUESORTORD 0x81
"QueueSortOrder", O_QUEUESORTORD, TRUE,
{ "QueueSortOrder", O_QUEUESORTORD, TRUE },
#define O_HOSTSFILE 0x82
"HostsFile", O_HOSTSFILE, FALSE,
{ "HostsFile", O_HOSTSFILE, FALSE },
#define O_MQA 0x83
"MinQueueAge", O_MQA, TRUE,
#define O_MHSA 0x84
/*
"MaxHostStatAge", O_MHSA, TRUE,
*/
{ "MinQueueAge", O_MQA, TRUE },
#define O_DEFCHARSET 0x85
"DefaultCharSet", O_DEFCHARSET, TRUE,
{ "DefaultCharSet", O_DEFCHARSET, TRUE },
#define O_SSFILE 0x86
"ServiceSwitchFile", O_SSFILE, FALSE,
{ "ServiceSwitchFile", O_SSFILE, FALSE },
#define O_DIALDELAY 0x87
"DialDelay", O_DIALDELAY, TRUE,
{ "DialDelay", O_DIALDELAY, TRUE },
#define O_NORCPTACTION 0x88
"NoRecipientAction", O_NORCPTACTION, TRUE,
{ "NoRecipientAction", O_NORCPTACTION, TRUE },
#define O_SAFEFILEENV 0x89
"SafeFileEnvironment", O_SAFEFILEENV, FALSE,
{ "SafeFileEnvironment", O_SAFEFILEENV, FALSE },
#define O_MAXMSGSIZE 0x8a
"MaxMessageSize", O_MAXMSGSIZE, FALSE,
{ "MaxMessageSize", O_MAXMSGSIZE, FALSE },
#define O_COLONOKINADDR 0x8b
"ColonOkInAddr", O_COLONOKINADDR, TRUE,
{ "ColonOkInAddr", O_COLONOKINADDR, TRUE },
#define O_MAXQUEUERUN 0x8c
"MaxQueueRunSize", O_MAXQUEUERUN, TRUE,
{ "MaxQueueRunSize", O_MAXQUEUERUN, TRUE },
#define O_MAXCHILDREN 0x8d
/*
"MaxDaemonChildren", O_MAXCHILDREN, FALSE,
*/
{ "MaxDaemonChildren", O_MAXCHILDREN, FALSE },
#define O_KEEPCNAMES 0x8e
"DontExpandCnames", O_KEEPCNAMES, FALSE,
{ "DontExpandCnames", O_KEEPCNAMES, FALSE },
#define O_MUSTQUOTE 0x8f
/*
"MustQuoteChars", O_MUSTQUOTE, FALSE,
*/
{ "MustQuoteChars", O_MUSTQUOTE, FALSE },
#define O_SMTPGREETING 0x90
"SmtpGreetingMessage", O_SMTPGREETING, FALSE,
{ "SmtpGreetingMessage", O_SMTPGREETING, FALSE },
#define O_UNIXFROM 0x91
"UnixFromLine", O_UNIXFROM, FALSE,
{ "UnixFromLine", O_UNIXFROM, FALSE },
#define O_OPCHARS 0x92
"OperatorChars", O_OPCHARS, FALSE,
{ "OperatorChars", O_OPCHARS, FALSE },
#define O_DONTINITGRPS 0x93
"DontInitGroups", O_DONTINITGRPS, TRUE,
{ "DontInitGroups", O_DONTINITGRPS, TRUE },
#define O_SLFH 0x94
#ifdef LOTUS_NOTES_HACK
"SingleLineFromHeader", O_SLFH, TRUE,
#endif
{ "SingleLineFromHeader", O_SLFH, TRUE },
#define O_ABH 0x95
{ "AllowBogusHELO", O_ABH, TRUE },
#define O_CONNTHROT 0x97
{ "ConnectionRateThrottle", O_CONNTHROT, FALSE },
#define O_UGW 0x99
{ "UnsafeGroupWrites", O_UGW, FALSE },
#define O_DBLBOUNCE 0x9a
{ "DoubleBounceAddress", O_DBLBOUNCE, FALSE },
#define O_HSDIR 0x9b
{ "HostStatusDirectory", O_HSDIR, FALSE },
#define O_SINGTHREAD 0x9c
{ "SingleThreadDelivery", O_SINGTHREAD, FALSE },
#define O_RUNASUSER 0x9d
{ "RunAsUser", O_RUNASUSER, FALSE },
NULL, '\0', FALSE,
{ NULL, '\0', FALSE }
};
@ -1461,12 +1495,18 @@ setoption(opt, val, safe, sticky, e)
register char *p;
register struct optioninfo *o;
char *subopt;
int mid;
auto char *ep;
char buf[50];
extern bool atobool();
extern time_t convtime();
extern int QueueLA;
extern int RefuseLA;
extern bool Warn_Q_option;
extern void setalias __P((char *));
extern int atooct __P((char *));
extern void setdefuser __P((void));
extern void setdaemonoptions __P((char *));
errno = 0;
if (opt == ' ')
@ -1843,10 +1883,11 @@ setoption(opt, val, safe, sticky, e)
break;
case 'M': /* define macro */
p = newstr(&val[1]);
mid = macid(val, &ep);
p = newstr(ep);
if (!safe)
cleanstrcpy(p, p, MAXNAME);
define(val[0], p, CurEnv);
define(mid, p, CurEnv);
sticky = FALSE;
break;
@ -1986,6 +2027,14 @@ setoption(opt, val, safe, sticky, e)
DefGid = pw->pw_gid;
}
}
#ifdef UID_MAX
if (DefUid > UID_MAX)
{
syserr("readcf: option u: uid value (%ld) > UID_MAX (%ld); ignored",
DefUid, UID_MAX);
}
#endif
setdefuser();
/* handle the group if it is there */
@ -1995,7 +2044,8 @@ setoption(opt, val, safe, sticky, e)
goto g_opt;
case 'V': /* fallback MX host */
FallBackMX = newstr(val);
if (val[0] != '\0')
FallBackMX = newstr(val);
break;
case 'v': /* run in verbose mode */
@ -2045,6 +2095,11 @@ setoption(opt, val, safe, sticky, e)
QueueSortOrder = QS_BYPRIORITY;
break;
case 't': /* Submission time */
case 'T':
QueueSortOrder = QS_BYTIME;
break;
default:
syserr("Invalid queue sort order \"%s\"", val);
}
@ -2058,10 +2113,6 @@ setoption(opt, val, safe, sticky, e)
MinQueueAge = convtime(val, 'm');
break;
case O_MHSA: /* maximum age of cached host status */
MaxHostStatAge = convtime(val, 'm');
break;
case O_DEFCHARSET: /* default character set for mimefying */
DefaultCharSet = newstr(denlstring(val, TRUE, TRUE));
break;
@ -2115,21 +2166,21 @@ setoption(opt, val, safe, sticky, e)
case O_MUSTQUOTE: /* must quote these characters in phrases */
strcpy(buf, "@,;:\\()[]");
if (strlen(val) < sizeof buf - 10)
if (strlen(val) < (SIZE_T) sizeof buf - 10)
strcat(buf, val);
MustQuoteChars = newstr(buf);
break;
case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */
SmtpGreeting = newstr(munchstring(val, NULL));
SmtpGreeting = newstr(munchstring(val, NULL, '\0'));
break;
case O_UNIXFROM: /* UNIX From_ line (old $l macro) */
UnixFromLine = newstr(munchstring(val, NULL));
UnixFromLine = newstr(munchstring(val, NULL, '\0'));
break;
case O_OPCHARS: /* operator characters (old $o macro) */
OperatorChars = newstr(munchstring(val, NULL));
OperatorChars = newstr(munchstring(val, NULL, '\0'));
break;
case O_DONTINITGRPS: /* don't call initgroups(3) */
@ -2140,6 +2191,75 @@ setoption(opt, val, safe, sticky, e)
SingleLineFromHeader = atobool(val);
break;
case O_ABH: /* allow HELO commands with syntax errors */
AllowBogusHELO = atobool(val);
break;
case O_CONNTHROT: /* connection rate throttle */
ConnRateThrottle = atoi(val);
break;
case O_UGW: /* group writable files are unsafe */
UnsafeGroupWrites = atobool(val);
break;
case O_DBLBOUNCE: /* address to which to send double bounces */
if (val[0] != '\0')
DoubleBounceAddr = newstr(val);
else
syserr("readcf: option DoubleBounceAddress: value required");
break;
case O_HSDIR: /* persistent host status directory */
if (val[0] != '\0')
HostStatDir = newstr(val);
break;
case O_SINGTHREAD: /* single thread deliveries (requires hsdir) */
SingleThreadDelivery = atobool(val);
break;
case O_RUNASUSER: /* run bulk of code as this user */
for (p = val; *p != '\0'; p++)
{
if (*p == '.' || *p == '/' || *p == ':')
{
*p++ = '\0';
break;
}
}
if (isascii(*val) && isdigit(*val))
RunAsUid = atoi(val);
else
{
register struct passwd *pw;
pw = sm_getpwnam(val);
if (pw == NULL)
syserr("readcf: option RunAsUser: unknown user %s", val);
else
{
RunAsUid = pw->pw_uid;
RunAsGid = pw->pw_gid;
}
}
if (*p == '\0')
break;
if (isascii(*p) && isdigit(*p))
DefGid = atoi(p);
else
{
register struct group *gr;
gr = getgrnam(p);
if (gr == NULL)
syserr("readcf: option RunAsUser: unknown group %s",
p);
else
RunAsGid = gr->gr_gid;
}
break;
default:
if (tTd(37, 1))
{
@ -2249,7 +2369,7 @@ makemapentry(line)
if (tTd(37, 5))
{
printf("map %s, class %s, flags %x, file %s,\n",
printf("map %s, class %s, flags %lx, file %s,\n",
s->s_map.map_mname, s->s_map.map_class->map_cname,
s->s_map.map_mflags,
s->s_map.map_file == NULL ? "(null)" : s->s_map.map_file);
@ -2327,10 +2447,7 @@ strtorwset(p, endp, stabmode)
*p = delim;
if (s == NULL)
{
syserr("unknown ruleset %s", q);
return -1;
}
if (stabmode == ST_ENTER && delim == '=')
{
@ -2368,7 +2485,7 @@ strtorwset(p, endp, stabmode)
if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset)
{
syserr("%s: ruleset changed value (old %d, new %d)",
q, ruleset, s->s_ruleset);
q, s->s_ruleset, ruleset);
ruleset = s->s_ruleset;
}
else if (ruleset > 0)
@ -2403,6 +2520,8 @@ inittimeouts(val)
register char *p;
extern time_t convtime();
if (tTd(37, 2))
printf("inittimeouts(%s)\n", val == NULL ? "<NULL>" : val);
if (val == NULL)
{
TimeOuts.to_connect = (time_t) 0 SECONDS;
@ -2423,6 +2542,24 @@ inittimeouts(val)
TimeOuts.to_ident = (time_t) 0 SECONDS;
#endif
TimeOuts.to_fileopen = (time_t) 60 SECONDS;
if (tTd(37, 5))
{
printf("Timeouts:\n");
printf(" connect = %ld\n", TimeOuts.to_connect);
printf(" initial = %ld\n", TimeOuts.to_initial);
printf(" helo = %ld\n", TimeOuts.to_helo);
printf(" mail = %ld\n", TimeOuts.to_mail);
printf(" rcpt = %ld\n", TimeOuts.to_rcpt);
printf(" datainit = %ld\n", TimeOuts.to_datainit);
printf(" datablock = %ld\n", TimeOuts.to_datablock);
printf(" datafinal = %ld\n", TimeOuts.to_datafinal);
printf(" rset = %ld\n", TimeOuts.to_rset);
printf(" quit = %ld\n", TimeOuts.to_quit);
printf(" nextcommand = %ld\n", TimeOuts.to_nextcommand);
printf(" miscshort = %ld\n", TimeOuts.to_miscshort);
printf(" ident = %ld\n", TimeOuts.to_ident);
printf(" fileopen = %ld\n", TimeOuts.to_fileopen);
}
return;
}
@ -2482,6 +2619,9 @@ settimeout(name, val)
time_t to;
extern time_t convtime();
if (tTd(37, 2))
printf("settimeout(%s = %s)\n", name, val);
to = convtime(val, 'm');
p = strchr(name, '.');
if (p != NULL)
@ -2515,6 +2655,8 @@ settimeout(name, val)
TimeOuts.to_fileopen = to;
else if (strcasecmp(name, "connect") == 0)
TimeOuts.to_connect = to;
else if (strcasecmp(name, "iconnect") == 0)
TimeOuts.to_iconnect = to;
else if (strcasecmp(name, "queuewarn") == 0)
{
to = convtime(val, 'h');
@ -2551,6 +2693,8 @@ settimeout(name, val)
else
syserr("settimeout: invalid queuereturn subtimeout %s", p);
}
else if (strcasecmp(name, "hoststatus") == 0)
MciInfoTimeout = convtime(val, 'm');
else
syserr("settimeout: invalid timeout %s", name);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)recipient.c 8.108.1.1 (Berkeley) 9/12/96";
static char sccsid[] = "@(#)recipient.c 8.116 (Berkeley) 8/17/96";
#endif /* not lint */
# include "sendmail.h"
@ -241,7 +241,7 @@ recipient(a, sendq, aliaslevel, e)
int i;
char *buf;
char buf0[MAXNAME + 1]; /* unquoted image of the user name */
extern int safefile();
extern void alias __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
e->e_to = a->q_paddr;
m = a->q_mailer;
@ -267,7 +267,7 @@ recipient(a, sendq, aliaslevel, e)
if (aliaslevel > MaxAliasRecursion)
{
a->q_status = "5.4.6";
usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max",
usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max)",
aliaslevel, MaxAliasRecursion);
return (a);
}
@ -482,6 +482,8 @@ recipient(a, sendq, aliaslevel, e)
ConfigLevel >= 2 && RewriteRules[5] != NULL &&
bitnset(M_TRYRULESET5, m->m_flags))
{
extern void maplocaluser __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
maplocaluser(a, sendq, aliaslevel + 1, e);
}
@ -495,7 +497,7 @@ recipient(a, sendq, aliaslevel, e)
{
auto bool fuzzy;
register struct passwd *pw;
extern struct passwd *finduser();
extern void forward __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
/* warning -- finduser may trash buf */
pw = finduser(buf, &fuzzy);
@ -738,8 +740,7 @@ finduser(name, fuzzyp)
{
if (tTd(29, 4))
printf("found (case wrapped)\n");
*fuzzyp = TRUE;
return pw;
break;
}
# endif
@ -749,17 +750,22 @@ finduser(name, fuzzyp)
if (tTd(29, 4))
printf("fuzzy matches %s\n", pw->pw_name);
message("sending to login name %s", pw->pw_name);
*fuzzyp = TRUE;
return (pw);
break;
}
}
if (tTd(29, 4))
if (pw != NULL)
*fuzzyp = TRUE;
else if (tTd(29, 4))
printf("no fuzzy match found\n");
# if DEC_OSF_BROKEN_GETPWENT /* DEC OSF/1 3.2 or earlier */
endpwent();
# endif
return pw;
#else
if (tTd(29, 4))
printf("not found (fuzzy disabled)\n");
return NULL;
#endif
return (NULL);
}
/*
** WRITABLE -- predicate returning if the file is writable.
@ -1122,19 +1128,21 @@ resetuid:
/*
** Check to see if some bad guy can write this file
**
** This should really do something clever with group
** permissions; currently we just view world writable
** as unsafe. Also, we don't check for writable
** Group write checking could be more clever, e.g.,
** guessing as to which groups are actually safe ("sys"
** may be; "user" probably is not).
** Also, we don't check for writable
** directories in the path. We've got to leave
** something for the local sysad to do.
*/
if (bitset(S_IWOTH, st.st_mode))
if (bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st.st_mode))
{
#ifdef LOG
if (LogLevel >= 12)
syslog(LOG_INFO, "%s: world writable %s file, marked unsafe",
syslog(LOG_INFO, "%s: %s writable %s file, marked unsafe",
shortenstring(fname, 203),
bitset(S_IWOTH, st.st_mode) ? "world" : "group",
forwarding ? "forward" : ":include:");
#endif
ctladdr->q_flags |= QUNSAFEADDR;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)savemail.c 8.87.1.2 (Berkeley) 9/16/96";
static char sccsid[] = "@(#)savemail.c 8.100 (Berkeley) 9/27/96";
#endif /* not lint */
# include "sendmail.h"
@ -86,7 +86,7 @@ savemail(e, sendbody)
auto ADDRESS *q = NULL;
register char *p;
MCI mcibuf;
int sfflags;
int flags;
char buf[MAXLINE+1];
extern char *ttypath();
typedef int (*fnptr)();
@ -283,7 +283,9 @@ savemail(e, sendbody)
break;
}
if (returntosender(e->e_message, e->e_errorqueue,
sendbody, e) == 0)
sendbody ? RTSF_SEND_BODY
: RTSF_NO_BODY,
e) == 0)
{
state = ESM_DONE;
break;
@ -299,14 +301,17 @@ savemail(e, sendbody)
*/
q = NULL;
if (sendtolist("postmaster", NULL, &q, 0, e) <= 0)
if (sendtolist(DoubleBounceAddr, NULL, &q, 0, e) <= 0)
{
syserr("553 cannot parse postmaster!");
syserr("553 cannot parse %s!", DoubleBounceAddr);
ExitStat = EX_SOFTWARE;
state = ESM_USRTMP;
break;
}
if (returntosender(e->e_message, q, sendbody, e) == 0)
flags = RTSF_PM_BOUNCE;
if (sendbody)
flags |= RTSF_SEND_BODY;
if (returntosender(e->e_message, q, flags, e) == 0)
{
state = ESM_DONE;
break;
@ -344,9 +349,9 @@ savemail(e, sendbody)
/* we have a home directory; write dead.letter */
define('z', p, e);
expand("\201z/dead.letter", buf, sizeof buf, e);
sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID;
e->e_to = buf;
if (mailfile(buf, NULL, sfflags, e) == EX_OK)
if (mailfile(buf, NULL, flags, e) == EX_OK)
{
bool oldverb = Verbose;
@ -378,10 +383,10 @@ savemail(e, sendbody)
snprintf(buf, sizeof buf, "%sdead.letter", _PATH_VARTMP);
sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
if (!writable(buf, NULL, sfflags) ||
flags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT;
if (!writable(buf, NULL, flags) ||
(fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND,
FileMode, sfflags)) == NULL)
FileMode, flags)) == NULL)
{
state = ESM_PANIC;
break;
@ -398,7 +403,9 @@ savemail(e, sendbody)
(*e->e_putbody)(&mcibuf, e, NULL);
putline("\n", &mcibuf);
(void) fflush(fp);
if (!ferror(fp))
if (ferror(fp))
state = ESM_PANIC;
else
{
bool oldverb = Verbose;
@ -410,9 +417,7 @@ savemail(e, sendbody)
syslog(LOG_NOTICE, "Saved message in %s", buf);
#endif
state = ESM_DONE;
break;
}
state = ESM_PANIC;
(void) xfclose(fp, "savemail", buf);
break;
@ -434,8 +439,10 @@ savemail(e, sendbody)
** Parameters:
** msg -- the explanatory message.
** returnq -- the queue of people to send the message to.
** sendbody -- if TRUE, also send back the body of the
** message; otherwise just send the header.
** flags -- flags tweaking the operation:
** RTSF_SENDBODY -- include body of message (otherwise
** just send the header).
** RTSF_PMBOUNCE -- this is a postmaster bounce.
** e -- the current envelope.
**
** Returns:
@ -451,10 +458,10 @@ savemail(e, sendbody)
#define ERRORFUDGE 100 /* nominal size of error message text */
int
returntosender(msg, returnq, sendbody, e)
returntosender(msg, returnq, flags, e)
char *msg;
ADDRESS *returnq;
bool sendbody;
int flags;
register ENVELOPE *e;
{
register ENVELOPE *ee;
@ -509,16 +516,21 @@ returntosender(msg, returnq, sendbody, e)
ee->e_flags &= ~EF_OLDSTYLE;
ee->e_sendqueue = returnq;
ee->e_msgsize = ERRORFUDGE;
if (sendbody)
if (bitset(RTSF_SEND_BODY, flags))
ee->e_msgsize += e->e_msgsize;
else
ee->e_flags |= EF_NO_BODY_RETN;
initsys(ee);
for (q = returnq; q != NULL; q = q->q_next)
{
extern bool pruneroute __P((char *));
if (bitset(QBADADDR, q->q_flags))
continue;
q->q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS);
q->q_flags |= QPINGONFAILURE;
if (!DontPruneRoutes && pruneroute(q->q_paddr))
{
register ADDRESS *p;
@ -543,8 +555,10 @@ returntosender(msg, returnq, sendbody, e)
{
if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags))
p = "return to sender";
else
else if (bitset(RTSF_PM_BOUNCE, flags))
p = "postmaster notify";
else
p = "DSN";
syslog(LOG_INFO, "%s: %s: %s: %s",
e->e_id, ee->e_id, p, shortenstring(msg, 203));
}
@ -589,6 +603,13 @@ returntosender(msg, returnq, sendbody, e)
addheader("Subject", msg, &ee->e_header);
p = "return-receipt";
}
else if (bitset(RTSF_PM_BOUNCE, flags))
{
snprintf(buf, sizeof buf, "Postmaster notify: %.*s",
sizeof buf - 20, msg);
addheader("Subject", buf, &ee->e_header);
p = "postmaster-notification";
}
else
{
snprintf(buf, sizeof buf, "Returned mail: %.*s",
@ -608,6 +629,8 @@ returntosender(msg, returnq, sendbody, e)
returndepth--;
return (-1);
}
ee->e_from.q_flags &= ~(QHASNOTIFY|Q_PINGFLAGS);
ee->e_from.q_flags |= QPINGONFAILURE;
ee->e_sender = ee->e_from.q_paddr;
/* push state into submessage */
@ -623,7 +646,7 @@ returntosender(msg, returnq, sendbody, e)
sendall(ee, SM_DEFAULT);
/* restore state */
dropenvelope(ee);
dropenvelope(ee, TRUE);
CurEnv = oldcur;
returndepth--;
@ -647,7 +670,6 @@ returntosender(msg, returnq, sendbody, e)
** mci -- the mailer connection information.
** e -- the envelope we are working in.
** separator -- any possible MIME separator.
** flags -- to modify the behaviour.
**
** Returns:
** none
@ -667,8 +689,8 @@ errbody(mci, e, separator)
register ADDRESS *q;
bool printheader;
bool sendbody;
bool pm_notify;
char buf[MAXLINE];
extern char *xuntextify();
if (bitset(MCIF_INHEADER, mci->mci_flags))
{
@ -699,10 +721,17 @@ errbody(mci, e, separator)
** Output introductory information.
*/
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
if (bitset(QBADADDR, q->q_flags))
break;
if (q == NULL &&
pm_notify = FALSE;
p = hvalue("subject", e->e_header);
if (p != NULL && strncmp(p, "Postmaster ", 11) == 0)
pm_notify = TRUE;
else
{
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
if (bitset(QBADADDR, q->q_flags))
break;
}
if (!pm_notify && q == NULL &&
!bitset(EF_FATALERRS|EF_SENDRECEIPT, e->e_parent->e_flags))
{
putline(" **********************************************",
@ -757,16 +786,63 @@ errbody(mci, e, separator)
printheader = TRUE;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QBADADDR, q->q_flags))
{
if (!bitset(QPINGONFAILURE, q->q_flags))
continue;
p = "unrecoverable error";
}
else if (!bitset(QPRIMARY, q->q_flags))
if (!bitset(QBADADDR, q->q_flags) ||
!bitset(QPINGONFAILURE, q->q_flags))
continue;
if (printheader)
{
putline(" ----- The following addresses had permanent fatal errors -----",
mci);
printheader = FALSE;
}
snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, 203));
putline(buf, mci);
if (q->q_alias != NULL)
{
snprintf(buf, sizeof buf, " (expanded from: %s)",
shortenstring(q->q_alias->q_paddr, 203));
putline(buf, mci);
}
}
if (!printheader)
putline("", mci);
printheader = TRUE;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QBADADDR, q->q_flags) ||
!bitset(QPRIMARY, q->q_flags) ||
!bitset(QDELAYED, q->q_flags))
continue;
if (printheader)
{
putline(" ----- The following addresses had transient non-fatal errors -----",
mci);
printheader = FALSE;
}
snprintf(buf, sizeof buf, "%s", shortenstring(q->q_paddr, 203));
putline(buf, mci);
if (q->q_alias != NULL)
{
snprintf(buf, sizeof buf, " (expanded from: %s)",
shortenstring(q->q_alias->q_paddr, 203));
putline(buf, mci);
}
}
if (!printheader)
putline("", mci);
printheader = TRUE;
for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next)
{
if (bitset(QBADADDR, q->q_flags) ||
!bitset(QPRIMARY, q->q_flags) ||
bitset(QDELAYED, q->q_flags))
continue;
else if (bitset(QDELAYED, q->q_flags))
p = "transient failure";
else if (!bitset(QPINGONSUCCESS, q->q_flags))
continue;
else if (bitset(QRELAYED, q->q_flags))
@ -785,7 +861,7 @@ errbody(mci, e, separator)
if (printheader)
{
putline(" ----- The following addresses have delivery notifications -----",
putline(" ----- The following addresses had successful delivery notifications -----",
mci);
printheader = FALSE;
}
@ -801,7 +877,7 @@ errbody(mci, e, separator)
}
}
if (!printheader)
putline("\n", mci);
putline("", mci);
/*
** Output transcript of errors
@ -1164,14 +1240,16 @@ smtptodsn(smtpstat)
**
** Parameters:
** t -- the text to convert.
** taboo -- additional characters that must be encoded.
**
** Returns:
** The xtext-ified version of the same string.
*/
char *
xtextify(t)
xtextify(t, taboo)
register char *t;
char *taboo;
{
register char *p;
int l;
@ -1179,6 +1257,9 @@ xtextify(t)
static char *bp = NULL;
static int bplen = 0;
if (taboo == NULL)
taboo = "";
/* figure out how long this xtext will have to be */
nbogus = l = 0;
for (p = t; *p != '\0'; p++)
@ -1186,7 +1267,8 @@ xtextify(t)
register int c = (*p & 0xff);
/* ASCII dependence here -- this is the way the spec words it */
if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
strchr(taboo, c) != NULL)
nbogus++;
l++;
}
@ -1209,7 +1291,8 @@ xtextify(t)
register int c = (*t++ & 0xff);
/* ASCII dependence here -- this is the way the spec words it */
if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(')
if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(' ||
strchr(taboo, c) != NULL)
{
*p++ = '+';
*p++ = "0123456789abcdef"[c >> 4];
@ -1298,6 +1381,7 @@ xuntextify(t)
c -= 'a' - 10;
*p++ |= c;
}
*p = '\0';
return bp;
}
/*

View File

@ -29,14 +29,14 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)sendmail.8 8.6 (Berkeley) 5/27/95
.\" @(#)sendmail.8 8.10 (Berkeley) 9/20/96
.\"
.Dd May 27, 1995
.Dd September 20, 1996
.Dt SENDMAIL 8
.Os BSD 4
.Sh NAME
.Nm sendmail
.Nd send mail over the internet
.Nd an electronic mail transport agent
.Sh SYNOPSIS
.Nm sendmail
.Op Ar flags
@ -108,6 +108,14 @@ listening on socket 25 for incoming
connections.
This is normally run from
.Pa /etc/rc .
.It Fl bD
Same as
.Fl bd
except runs in foreground.
.It Fl bh
Print the persistent host status database.
.It Fl bH
Purge the persistent host status database.
.It Fl bi
Initialize the alias database.
.It Fl bm
@ -165,14 +173,41 @@ the mail is returned with an error message,
the victim of an aliasing loop.
If not specified,
``Received:'' lines in the message are counted.
.It Fl i
Ignore dots alone on lines by themselves in incoming messages.
This should be set if you are reading data from a file.
.It Fl N Ar dsn
Set delivery status notification conditions to
.Ar dsn,
which can be
.Ql never
for no notifications
or a comma separated list of the values
.Ql failure
to be notified if delivery failed,
.Ql delay
to be notified if delivery is delayed, and
.Ql success
to be notified when the message is successfully delivered.
.It Fl n
Don't do aliasing.
.It Fl O Ar option Ns = Ns Em value
Set option
.Ar option
to the specified
.Em value .
This form uses long names.
See below for more details.
.It Fl o Ns Ar x Em value
Set option
.Ar x
to the specified
.Em value .
Options are described below.
This form uses single character names only.
The short names are not described in this manual page;
see the
.%T "Sendmail Installation and Operation Guide"
for details.
.It Fl p Ns Ar protocol
Set the name of the protocol used to receive the message.
This can be a simple protocol name such as ``UUCP''
@ -221,6 +256,16 @@ as a substring of one of the recipients.
Limit processed jobs to those containing
.Ar substr
as a substring of the sender.
.It Fl R Ar return
Set the amount of the message to be returned
if the message bounces.
The
.Ar return
parameter can be
.Ql full
to return the entire message or
.Ql hdrs
to return only the headers.
.It Fl r Ns Ar name
An alternate and obsolete form of the
.Fl f
@ -234,6 +279,22 @@ that is,
they will
.Em not
receive copies even if listed in the message header.
.It Fl U
Initial (user) submission.
This should
.Em always
be set when called from a user agent such as
.Nm Mail
or
.Nm exmh
and
.Em never
be set when called by a network delivery agent such as
.Nm rmail .
.It Fl V Ar envid
Set the original envelope id.
This is propogated across SMTP to servers that support DSNs
and is returned in DSN-compliant error messages.
.It Fl v
Go into verbose mode.
Alias expansions will be announced, etc.
@ -249,22 +310,25 @@ Normally these will only be used by a system administrator.
Options may be set either on the command line
using the
.Fl o
flag
flag (for short names),
the
.Fl O
flag (for long names),
or in the configuration file.
This is a partial list;
This is a partial list limited to those options that are likely to be useful
on the command line
and only shows the long names;
for a complete list (and details), consult the
.%T "Sendmail Installation and Operation Guide" .
The options are:
.Bl -tag -width Fl
.It Li A Ns Ar file
.It Li AliasFile= Ns Ar file
Use alternate alias file.
.It Li b Ns Ar nblocks
The minimum number of free blocks needed on the spool filesystem.
.It Li c
.It Li HoldExpensive
On mailers that are considered ``expensive'' to connect to,
don't initiate immediate connection.
This requires queueing.
.It Li C Ar N
.It Li CheckpointInterval= Ns Ar N
Checkpoint the queue file after every
.Ar N
successful deliveries (default 10).
@ -272,7 +336,7 @@ This avoids excessive duplicate deliveries
when sending to long mailing lists
interrupted by system crashes.
.ne 1i
.It Li d Ns Ar x
.It Li DeliveryMode= Ns Ar x
Set the delivery mode to
.Ar x .
Delivery modes are
@ -280,14 +344,14 @@ Delivery modes are
for interactive (synchronous) delivery,
.Ql b
for background (asynchronous) delivery,
and
.Ql q
for queue only \- i.e.,
actual delivery is done the next time the queue is run.
.It Li D
Try to automatically rebuild the alias database
if necessary.
.It Li e Ns Ar x
actual delivery is done the next time the queue is run, and
.Ql d
for deferred \- the same as
.Ql q
except that database lookups (notably DNS and NIS lookups) are avoided.
.It Li ErrorMode= Ns Ar x
Set error processing to mode
.Ar x .
Valid modes are
@ -315,41 +379,33 @@ and if the sender is local to this machine,
a copy of the message is appended to the file
.Pa dead.letter
in the sender's home directory.
.It Li f
.It Li SaveFromLine
Save
.Tn UNIX Ns \-style
From lines at the front of messages.
.It Li G
Match local mail names against the GECOS portion of the password file.
.It Li g Ar N
The default group id to use when calling mailers.
.It Li H Ns Ar file
The
.Tn SMTP
help file.
.It Li h Ar N
.It Li MaxHopCount= Ar N
The maximum number of times a message is allowed to ``hop''
before we decide it is in a loop.
.It Li i
.It Li IgnoreDots
Do not take dots on a line by themselves
as a message terminator.
.It Li j
.It Li SendMimeErrors
Send error messages in MIME format.
.It Li K Ns Ar timeout
If not set, the DSN (Delivery Status Notification) SMTP extension
is disabled.
.It Li ConnectionCacheTimeout= Ns Ar timeout
Set connection cache timeout.
.It Li k Ns Ar N
.It Li ConnectionCacheSize= Ns Ar N
Set connection cache size.
.It Li L Ns Ar n
.It Li LogLevel= Ns Ar n
The log level.
.It Li l
Pay attention to the Errors-To: header.
.It Li m
.It Li MeToo
Send to ``me'' (the sender) also if I am in an alias expansion.
.It Li n
.It Li CheckAliases
Validate the right hand side of aliases during a
.Xr newaliases 1
command.
.It Li o
.It Li OldStyleHeaders
If set, this message may have
old style headers.
If not set,
@ -357,24 +413,18 @@ this message is guaranteed to have new style headers
(i.e., commas instead of spaces between addresses).
If set, an adaptive algorithm is used that will correctly
determine the header format in most cases.
.It Li Q Ns Ar queuedir
.It Li QueueDirectory= Ns Ar queuedir
Select the directory in which to queue messages.
.It Li S Ns Ar file
.It Li StatusFile= Ns Ar file
Save statistics in the named file.
.It Li s
Always instantiate the queue file,
even under circumstances where it is not strictly necessary.
This provides safety against system crashes during delivery.
.It Li T Ns Ar time
.It Li Timeout.queuereturn= Ns Ar time
Set the timeout on undelivered messages in the queue to the specified time.
After delivery has failed
(e.g., because of a host being down)
for this amount of time,
failed messages will be returned to the sender.
The default is three days.
.It Li t Ns Ar stz , Ar dtz
Set the name of the time zone.
.It Li U Ns Ar userdatabase
The default is five days.
.It Li UserDatabaseSpec= Ns Ar userdatabase
If set, a user database is consulted to get forwarding information.
You can consider this an adjunct to the aliasing mechanism,
except that the database is intended to be distributed;
@ -382,13 +432,54 @@ aliases are local to a particular host.
This may not be available if your sendmail does not have the
.Dv USERDB
option compiled in.
.It Li u Ns Ar N
Set the default user id for mailers.
.It Li Y
.It Li ForkEachJob
Fork each job during queue runs.
May be convenient on memory-poor machines.
.It Li 7
.It Li SevenBitInput
Strip incoming messages to seven bits.
.It Li EightBitMode= Ns Ar mode
Set the handling of eight bit input to seven bit destinations to
.Ar mode :
.Li m
(mimefy) will convert to seven-bit MIME format,
.Li p
(pass) will pass it as eight bits (but violates protocols),
and
.Li s
(strict) will bounce the message.
.It Li MinQueueAge= Ns Ar timeout
Sets how long a job must ferment in the queue between attempts to send it.
.It Li DefaultCharSet= Ns Ar charset
Sets the default character set used to label 8-bit data
that is not otherwise labelled.
.It Li DialDelay= Ns Ar sleeptime
If opening a connection fails,
sleep for
.Ar sleeptime
seconds and try again.
Useful on dial-on-demand sites.
.It Li NoRecipientAction= Ns Ar action
Set the behaviour when there are no recipient headers (To:, Cc: or Bcc:)
in the message to
.Ar action :
.Li none
leaves the message unchanged,
.Li add-to
adds a To: header with the envelope recipients,
.Li add-apparently-to
adds an Apparently-To: header with the envelope recipients,
.Li add-bcc
adds an empty Bcc: header, and
.Li add-to-undisclosed
adds a header reading
.Ql "To: undisclosed-recipients:;" .
.It Li MaxDaemonChildren= Ns Ar N
Sets the maximum number of children that an incoming SMTP daemon
will allow to spawn at any time to
.Ar N .
.It Li ConnectionRateThrottle= Ns Ar N
Sets the maximum number of connections per second to the SMTP port to
.Ar N .
.El
.Pp
In aliases,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)sendmail.h 8.159.1.3 (Berkeley) 9/16/96
* @(#)sendmail.h 8.206 (Berkeley) 10/17/96
*/
/*
@ -41,7 +41,7 @@
# ifdef _DEFINE
# define EXTERN
# ifndef lint
static char SmailSccsId[] = "@(#)sendmail.h 8.159.1.3 9/16/96";
static char SmailSccsId[] = "@(#)sendmail.h 8.206 10/17/96";
# endif
# else /* _DEFINE */
# define EXTERN extern
@ -179,12 +179,15 @@ typedef struct address ADDRESS;
# define QEXPANDED 0x00020000 /* DSN: undergone list expansion */
# define QDELIVERED 0x00040000 /* DSN: successful final delivery */
# define QDELAYED 0x00080000 /* DSN: message delayed */
# define QTHISPASS 0x80000000 /* temp: address set this pass */
# define QTHISPASS 0x40000000 /* temp: address set this pass */
# define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY)
# define NULLADDR ((ADDRESS *) NULL)
/* functions */
extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *));
extern ADDRESS *buildaddr __P((char **, ADDRESS *, int, ENVELOPE *));
extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern char **prescan __P((char *, int, char[], int, char **, u_char *));
extern int rewrite __P((char **, int, int, ENVELOPE *));
@ -250,6 +253,7 @@ struct mailer
# define M_INTERNAL 'I' /* SMTP to another sendmail site */
# define M_UDBRECIPIENT 'j' /* do udbsender rewriting on recipient lines */
# define M_NOLOOPCHECK 'k' /* don't check for loops in HELO command */
# define M_CHUNKING 'K' /* CHUNKING: reserved for future use */
# define M_LOCALMAILER 'l' /* delivery is to this host */
# define M_LIMITS 'L' /* must enforce SMTP line limits */
# define M_MUSER 'm' /* can handle multiple users at once */
@ -259,6 +263,7 @@ struct mailer
# define M_RUNASRCPT 'o' /* always run mailer as recipient */
# define M_FROMPATH 'p' /* use reverse-path in MAIL FROM: */
/* 'P' CF: include Return-Path: */
# define M_VRFY250 'q' /* VRFY command returns 250 instead of 252 */
# define M_ROPT 'r' /* mailer takes picky -r flag */
# define M_SECURE_PORT 'R' /* try to send on a reserved TCP port */
# define M_STRIPQ 's' /* strip quote chars from user/host */
@ -270,6 +275,7 @@ struct mailer
# define M_HASPWENT 'w' /* check for /etc/passwd entry */
/* 'x' CF: include Full-Name: */
# define M_XDOT 'X' /* use hidden-dot algorithm */
# define M_NOMX '0' /* turn off MX lookups */
# define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */
# define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */
# define M_7BITS '7' /* use 7-bit path */
@ -279,6 +285,7 @@ struct mailer
# define M_CHECKPROG '|' /* check for |program addresses */
# define M_CHECKFILE '/' /* check for /file addresses */
# define M_CHECKUDB '@' /* user can be user database key */
# define M_CHECKHDIR '~' /* SGI: check for valid home directory */
EXTERN MAILER *Mailer[MAXMAILERS+1];
@ -287,6 +294,75 @@ EXTERN MAILER *ProgMailer; /* ptr to program mailer */
EXTERN MAILER *FileMailer; /* ptr to *file* mailer */
EXTERN MAILER *InclMailer; /* ptr to *include* mailer */
/*
** Information about currently open connections to mailers, or to
** hosts that we have looked up recently.
*/
# define MCI struct mailer_con_info
MCI
{
short mci_flags; /* flag bits, see below */
short mci_errno; /* error number on last connection */
short mci_herrno; /* h_errno from last DNS lookup */
short mci_exitstat; /* exit status from last connection */
short mci_state; /* SMTP state */
long mci_maxsize; /* max size this server will accept */
FILE *mci_in; /* input side of connection */
FILE *mci_out; /* output side of connection */
int mci_pid; /* process id of subordinate proc */
char *mci_phase; /* SMTP phase string */
struct mailer *mci_mailer; /* ptr to the mailer for this conn */
char *mci_host; /* host name */
char *mci_status; /* DSN status to be copied to addrs */
char *mci_rstatus; /* SMTP status to be copied to addrs */
time_t mci_lastuse; /* last usage time */
FILE *mci_statfile; /* long term status file */
};
/* flag bits */
#define MCIF_VALID 0x0001 /* this entry is valid */
#define MCIF_TEMP 0x0002 /* don't cache this connection */
#define MCIF_CACHED 0x0004 /* currently in open cache */
#define MCIF_ESMTP 0x0008 /* this host speaks ESMTP */
#define MCIF_EXPN 0x0010 /* EXPN command supported */
#define MCIF_SIZE 0x0020 /* SIZE option supported */
#define MCIF_8BITMIME 0x0040 /* BODY=8BITMIME supported */
#define MCIF_7BIT 0x0080 /* strip this message to 7 bits */
#define MCIF_MULTSTAT 0x0100 /* MAIL11V3: handles MULT status */
#define MCIF_INHEADER 0x0200 /* currently outputing header */
#define MCIF_CVT8TO7 0x0400 /* convert from 8 to 7 bits */
#define MCIF_DSN 0x0800 /* DSN extension supported */
#define MCIF_8BITOK 0x1000 /* OK to send 8 bit characters */
#define MCIF_CVT7TO8 0x2000 /* convert from 7 to 8 bits */
#define MCIF_INMIME 0x4000 /* currently reading MIME header */
/* states */
#define MCIS_CLOSED 0 /* no traffic on this connection */
#define MCIS_OPENING 1 /* sending initial protocol */
#define MCIS_OPEN 2 /* open, initial protocol sent */
#define MCIS_ACTIVE 3 /* message being sent */
#define MCIS_QUITING 4 /* running quit protocol */
#define MCIS_SSD 5 /* service shutting down */
#define MCIS_ERROR 6 /* I/O error on connection */
/* functions */
extern MCI *mci_get __P((char *, MAILER *));
extern void mci_cache __P((MCI *));
extern void mci_flush __P((bool, MCI *));
extern void mci_dump __P((MCI *, bool));
extern void mci_dump_all __P((bool));
extern MCI **mci_scan __P((MCI *));
extern int mci_traverse_persistent __P((int (), char *));
extern int mci_print_persistent __P((char *, char *));
extern int mci_purge_persistent __P((char *, char *));
extern int mci_lock_host __P((MCI *));
extern void mci_unlock_host __P((MCI *));
extern int mci_lock_host_statfile __P((MCI *));
extern void mci_store_persistent __P((MCI *));
extern int mci_read_persistent __P((FILE *, MCI *));
/*
** Header structure.
** This structure is used internally to store header items.
*/
@ -332,62 +408,15 @@ extern struct hdrinfo HdrInfo[];
# define H_CTE 0x1000 /* this field is a content-transfer-encoding */
# define H_CTYPE 0x2000 /* this is a content-type field */
# define H_BCC 0x4000 /* Bcc: header: strip value or delete */
/*
** Information about currently open connections to mailers, or to
** hosts that we have looked up recently.
*/
# define MCI struct mailer_con_info
MCI
{
short mci_flags; /* flag bits, see below */
short mci_errno; /* error number on last connection */
short mci_herrno; /* h_errno from last DNS lookup */
short mci_exitstat; /* exit status from last connection */
short mci_state; /* SMTP state */
long mci_maxsize; /* max size this server will accept */
FILE *mci_in; /* input side of connection */
FILE *mci_out; /* output side of connection */
int mci_pid; /* process id of subordinate proc */
char *mci_phase; /* SMTP phase string */
struct mailer *mci_mailer; /* ptr to the mailer for this conn */
char *mci_host; /* host name */
char *mci_status; /* DSN status to be copied to addrs */
time_t mci_lastuse; /* last usage time */
};
/* flag bits */
#define MCIF_VALID 0x0001 /* this entry is valid */
#define MCIF_TEMP 0x0002 /* don't cache this connection */
#define MCIF_CACHED 0x0004 /* currently in open cache */
#define MCIF_ESMTP 0x0008 /* this host speaks ESMTP */
#define MCIF_EXPN 0x0010 /* EXPN command supported */
#define MCIF_SIZE 0x0020 /* SIZE option supported */
#define MCIF_8BITMIME 0x0040 /* BODY=8BITMIME supported */
#define MCIF_7BIT 0x0080 /* strip this message to 7 bits */
#define MCIF_MULTSTAT 0x0100 /* MAIL11V3: handles MULT status */
#define MCIF_INHEADER 0x0200 /* currently outputing header */
#define MCIF_CVT8TO7 0x0400 /* convert from 8 to 7 bits */
#define MCIF_DSN 0x0800 /* DSN extension supported */
#define MCIF_8BITOK 0x1000 /* OK to send 8 bit characters */
#define MCIF_CVT7TO8 0x2000 /* convert from 7 to 8 bits */
#define MCIF_INMIME 0x4000 /* currently reading MIME header */
/* states */
#define MCIS_CLOSED 0 /* no traffic on this connection */
#define MCIS_OPENING 1 /* sending initial protocol */
#define MCIS_OPEN 2 /* open, initial protocol sent */
#define MCIS_ACTIVE 3 /* message being sent */
#define MCIS_QUITING 4 /* running quit protocol */
#define MCIS_SSD 5 /* service shutting down */
#define MCIS_ERROR 6 /* I/O error on connection */
# define H_ENCODABLE 0x8000 /* field can be RFC 1522 encoded */
/* functions */
extern MCI *mci_get __P((char *, MAILER *));
extern void mci_cache __P((MCI *));
extern void mci_flush __P((bool, MCI *));
extern void addheader __P((char *, char *, HDR **));
extern char *hvalue __P((char *, HDR *));
extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern void put_vanilla_header __P((HDR *, char *, MCI *));
extern void eatheader __P((ENVELOPE *e, bool));
extern int chompheader __P((char *, bool, HDR **, ENVELOPE *));
/*
** Envelope structure.
** This structure defines the message itself. There is usually
@ -403,7 +432,6 @@ struct envelope
long e_msgpriority; /* adjusted priority of this message */
time_t e_ctime; /* time message appeared in the queue */
char *e_to; /* the target person */
char *e_receiptto; /* return receipt address */
ADDRESS e_from; /* the person it is from */
char *e_sender; /* e_from.q_paddr w comments stripped */
char **e_fromdomain; /* the domain part of the sender */
@ -472,7 +500,7 @@ EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */
/* functions */
extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *));
extern void dropenvelope __P((ENVELOPE *));
extern void dropenvelope __P((ENVELOPE *, bool));
extern void clearenvelope __P((ENVELOPE *, bool));
extern void putheader __P((MCI *, HDR *, ENVELOPE *));
@ -636,7 +664,8 @@ MAP
char *map_domain; /* the (nominal) NIS domain */
char *map_rebuild; /* program to run to do auto-rebuild */
time_t map_mtime; /* last database modification time */
short map_specificity; /* specificity of alaases */
int map_lockfd; /* auxiliary lock file descriptor */
short map_specificity; /* specificity of aliases */
MAP *map_stack[MAXMAPSTACK]; /* list for stacked maps */
short map_return[MAXMAPACTIONS]; /* return bitmaps for stacked maps */
};
@ -659,6 +688,7 @@ MAP
# define MF_UNSAFEDB 0x00004000 /* this map is world writable */
# define MF_APPEND 0x00008000 /* append new entry on rebuiled */
# define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */
# define MF_NODEFER 0x00020000 /* don't defer if map lookup fails */
/* indices for map_actions */
# define MA_NOTFOUND 0 /* member map returned "not found" */
@ -695,6 +725,7 @@ MAPCLASS
/* functions */
extern char *map_rewrite __P((MAP *, char *, int, char **));
extern MAP *makemapentry __P((char *));
extern void initmaps __P((bool, ENVELOPE *));
/*
** Symbol table definitions
*/
@ -702,7 +733,8 @@ extern MAP *makemapentry __P((char *));
struct symtab
{
char *s_name; /* name to be entered */
char s_type; /* general type (see below) */
short s_type; /* general type (see below) */
short s_len; /* length of this entry */
struct symtab *s_next; /* pointer to next in chain */
union
{
@ -717,6 +749,7 @@ struct symtab
NAMECANON sv_namecanon; /* canonical name cache */
int sv_macro; /* macro name => id mapping */
int sv_ruleset; /* ruleset index */
char *sv_service[MAXMAPSTACK]; /* service switch */
} s_value;
};
@ -734,6 +767,7 @@ typedef struct symtab STAB;
# define ST_NAMECANON 8 /* cached canonical name */
# define ST_MACRO 9 /* macro name to id mapping */
# define ST_RULESET 10 /* ruleset index */
# define ST_SERVICE 11 /* service switch entry */
# define ST_MCI 16 /* mailer connection info (offset) */
# define s_class s_value.sv_class
@ -747,6 +781,7 @@ typedef struct symtab STAB;
# define s_namecanon s_value.sv_namecanon
# define s_macro s_value.sv_macro
# define s_ruleset s_value.sv_ruleset
# define s_service s_value.sv_service
extern STAB *stab __P((char *, int, int));
extern void stabapply __P((void (*)(STAB *, int), int));
@ -802,12 +837,14 @@ EXTERN char OpMode; /* operation mode, see below */
#define MD_SMTP 's' /* run SMTP on standard input */
#define MD_ARPAFTP 'a' /* obsolete ARPANET mode (Grey Book) */
#define MD_DAEMON 'd' /* run as a daemon */
#define MD_FGDAEMON 'D' /* run daemon in foreground */
#define MD_VERIFY 'v' /* verify: don't collect or deliver */
#define MD_TEST 't' /* test mode: resolve addrs only */
#define MD_INITALIAS 'i' /* initialize alias database */
#define MD_PRINT 'p' /* print the queue */
#define MD_FREEZE 'z' /* freeze the configuration file */
#define MD_HOSTSTAT 'h' /* print persistent host stat info */
#define MD_PURGESTAT 'H' /* purge persistent host stat info */
/* values for e_sendmode -- send modes */
#define SM_DELIVER 'i' /* interactive delivery */
@ -841,6 +878,7 @@ EXTERN int QueueSortOrder;
#define QS_BYPRIORITY 0 /* sort by message priority */
#define QS_BYHOST 1 /* sort by first host name */
#define QS_BYTIME 2 /* sort by submission time */
/* how to handle messages without any recipient addresses */
@ -856,7 +894,7 @@ EXTERN int NoRecipientAction;
/* flags to putxline */
#define PXLF_NOTHINGSPECIAL 0 /* no special mapping */
#define PXLF_MAPFROM 0x0001 /* map From_ to >From_ */
#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit *e
#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit */
/*
** Additional definitions
*/
@ -918,6 +956,9 @@ struct prival
/* flags that are actually specific to safefopen */
#define SFF_OPENASROOT 0x1000 /* open as root instead of real user */
/* functions */
extern int safefile __P((char *, UID_T, GID_T, char *, int, int, struct stat *));
/*
** Flags passed to mime8to7.
@ -928,6 +969,15 @@ struct prival
#define M87F_DIGEST 0x0002 /* processing multipart/digest */
/*
** Flags passed to returntosender.
*/
#define RTSF_NO_BODY 0 /* send headers only */
#define RTSF_SEND_BODY 0x0001 /* include body of message in return */
#define RTSF_PM_BOUNCE 0x0002 /* this is a postmaster bounce */
/*
** Regular UNIX sockaddrs are too small to handle ISO addresses, so
** we are forced to declare a supertype here.
@ -957,6 +1007,8 @@ union bigsockaddr
#define SOCKADDR union bigsockaddr
EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */
extern char *hostnamebyanyaddr __P((SOCKADDR *));
extern char *anynet_ntoa __P((SOCKADDR *));
#endif
@ -983,6 +1035,34 @@ extern char *anynet_ntoa __P((SOCKADDR *));
#define VENDOR_IBM 4 /* IBM specific config syntax */
EXTERN int VendorCode; /* vendor-specific operation enhancements */
/* prototypes for vendor-specific hook routines */
extern void vendor_set_uid __P((UID_T));
extern void vendor_daemon_setup __P((ENVELOPE *));
/*
** Terminal escape codes.
**
** To make debugging output clearer.
*/
struct termescape
{
char *te_rv_on; /* turn reverse-video on */
char *te_rv_off; /* turn reverse-video off */
};
EXTERN struct termescape TermEscape;
/*
** Error return from inet_addr(3), in case not defined in /usr/include.
*/
#ifndef INADDR_NONE
# define INADDR_NONE 0xffffffff
#endif
/*
** Global variables.
*/
@ -1005,6 +1085,7 @@ EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */
EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */
EXTERN bool SevenBitInput; /* force 7-bit data on input */
EXTERN bool HasEightBits; /* has at least one eight bit input byte */
EXTERN bool ConfigFileRead; /* configuration file has been read */
EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */
EXTERN FILE *InChannel; /* input connection */
EXTERN FILE *OutChannel; /* output connection */
@ -1061,11 +1142,11 @@ EXTERN char *ForwardPath; /* path to search for .forward files */
EXTERN long MinBlocksFree; /* min # of blocks free on queue fs */
EXTERN char *FallBackMX; /* fall back MX host */
EXTERN long MaxMessageSize; /* advertised max size we will accept */
EXTERN time_t MaxHostStatAge; /* max age of cached host status info */
EXTERN time_t MinQueueAge; /* min delivery interval */
EXTERN time_t DialDelay; /* delay between dial-on-demand tries */
EXTERN char *SafeFileEnv; /* chroot location for file delivery */
EXTERN char *HostsFile; /* path to /etc/hosts file */
EXTERN char *HostStatDir; /* location of host status information */
EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */
EXTERN int MaxChildren; /* maximum number of daemonic children */
EXTERN int CurChildren; /* current number of daemonic children */
@ -1073,8 +1154,17 @@ EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */
EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */
EXTERN char *OperatorChars; /* operators (old $o macro) */
EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */
EXTERN int DefaultNotify; /* default DSN notification flags */
EXTERN bool AllowBogusHELO; /* allow syntax errors on HELO command */
EXTERN bool UserSubmission; /* initial (user) mail submission */
EXTERN uid_t RunAsUid; /* UID to become for bulk of run */
EXTERN gid_t RunAsGid; /* GID to become for bulk of run */
EXTERN bool SingleThreadDelivery; /* single thread hosts on delivery */
EXTERN bool UnsafeGroupWrites; /* group-writable files are unsafe */
EXTERN bool SingleLineFromHeader; /* force From: header to be one line */
EXTERN int ConnRateThrottle; /* throttle for SMTP connection rate */
EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */
EXTERN int MaxMacroRecursion; /* maximum depth of macro recursion */
EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */
EXTERN char *MustQuoteChars; /* quote these characters in phrases */
EXTERN char *ServiceSwitchFile; /* backup service switch */
@ -1085,12 +1175,16 @@ EXTERN int CheckpointInterval; /* queue file checkpoint interval */
EXTERN bool DontPruneRoutes; /* don't prune source routes */
EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */
EXTERN int MaxMciCache; /* maximum entries in MCI cache */
EXTERN time_t ServiceCacheTime; /* time service switch was cached */
EXTERN time_t ServiceCacheMaxAge; /* refresh interval for cache */
EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */
EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */
EXTERN char *QueueLimitRecipient; /* limit queue runs to this recipient */
EXTERN char *QueueLimitSender; /* limit queue runs to this sender */
EXTERN char *QueueLimitId; /* limit queue runs to this id */
EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */
EXTERN char *DoubleBounceAddr; /* where to send double bounces */
EXTERN char **ExternalEnviron; /* input environment */
EXTERN char *UserEnviron[MAXUSERENVIRON + 1];
/* saved user environment */
extern int errno;
@ -1113,7 +1207,8 @@ EXTERN struct
time_t to_datafinal; /* DATA completion [10m] */
time_t to_nextcommand; /* next command [5m] */
/* following timeouts are not mentioned in RFC 1123 */
time_t to_connect; /* initial connection timeout */
time_t to_iconnect; /* initial connection timeout (first try) */
time_t to_connect; /* initial connection timeout (later tries) */
time_t to_rset; /* RSET command */
time_t to_helo; /* HELO command */
time_t to_quit; /* QUIT command */
@ -1161,6 +1256,7 @@ EXTERN u_char tTdvect[100];
#define STRUCTCOPY(s, d) d = s
/*
** Declarations of useful functions
*/
@ -1181,8 +1277,6 @@ extern void openxscript __P((ENVELOPE *));
extern void closexscript __P((ENVELOPE *));
extern char *shortenstring __P((const char *, int));
extern bool usershellok __P((char *, char *));
extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *));
extern char *hvalue __P((char *, HDR *));
extern char *defcharset __P((ENVELOPE *));
extern bool wordinclass __P((char *, int));
extern char *denlstring __P((char *, bool, bool));
@ -1197,6 +1291,7 @@ extern void logsender __P((ENVELOPE *, char *));
extern void smtprset __P((MAILER *, MCI *, ENVELOPE *));
extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *));
extern void setuserenv __P((const char *, const char *));
extern char *getextenv __P((const char *));
extern void disconnect __P((int, ENVELOPE *));
extern void putxline __P((char *, MCI *, int));
extern void dumpfd __P((int, bool, bool));
@ -1208,15 +1303,66 @@ extern void inittimeouts __P((char *));
extern void logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *));
extern void giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *));
extern void buildfname __P((char *, char *, char *, int));
extern void mci_setstat __P((MCI *, char *, char *));
extern char *smtptodsn __P((int));
extern int rscheck __P((char *, char *, char *, ENVELOPE *e));
extern void mime7to8 __P((MCI *, HDR *, ENVELOPE *));
extern int mime8to7 __P((MCI *, HDR *, ENVELOPE *, char **, int));
extern void xfclose __P((FILE *, char *, char *));
extern int switch_map_find __P((char *, char *[], short []));
extern void shorten_hostname __P((char []));
extern int waitfor __P((pid_t));
extern void proc_list_add __P((pid_t));
extern void proc_list_drop __P((pid_t));
extern void buffer_errors __P((void));
extern void flush_errors __P((bool));
extern void putline __P((char *, MCI *));
extern void putxline __P((char *, MCI *, int));
extern bool xtextok __P((char *));
extern char *xtextify __P((char *, char *));
extern char *xuntextify __P((char *));
extern void cleanstrcpy __P((char *, char *, int));
extern int getmxrr __P((char *, char **, bool, int *));
extern int strtorwset __P((char *, char **, int));
extern void printav __P((char **));
extern void printopenfds __P((bool));
extern int endmailer __P((MCI *, ENVELOPE *, char **));
extern void fixcrlf __P((char *, bool));
extern int dofork __P((void));
extern void initsys __P((ENVELOPE *));
extern void collect __P((FILE *, bool, bool, HDR **, ENVELOPE *));
extern void stripquotes __P((char *));
extern int include __P((char *, bool, ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern void unlockqueue __P((ENVELOPE *));
extern void xunlink __P((char *));
extern void runqueue __P((bool));
extern int getla __P((void));
extern void sendall __P((ENVELOPE *, int));
extern void queueup __P((ENVELOPE *, bool));
extern void checkfds __P((char *));
extern int returntosender __P((char *, ADDRESS *, int, ENVELOPE *));
extern void markstats __P((ENVELOPE *, ADDRESS *));
extern void poststats __P((char *));
extern char *arpadate __P((char *));
extern int mailfile __P((char *, ADDRESS *, int, ENVELOPE *));
extern void loseqfile __P((ENVELOPE *, char *));
extern int prog_open __P((char **, int *, ENVELOPE *));
extern bool getcanonname __P((char *, int, bool));
extern bool validate_connection __P((SOCKADDR *, char *, ENVELOPE *));
extern bool path_is_dir __P((char *, bool));
extern pid_t dowork __P((char *, bool, bool, ENVELOPE *));
extern const char *errstring __P((int));
extern sigfunc_t setsignal __P((int, sigfunc_t));
extern int releasesignal __P((int));
extern struct hostent *sm_gethostbyname __P((char *));
extern struct hostent *sm_gethostbyaddr __P((char *, int, int));
extern struct passwd *sm_getpwnam __P((char *));
extern struct passwd *sm_getpwuid __P((UID_T));
extern struct passwd *finduser __P((char *, bool *));
#ifdef XDEBUG
extern void checkfdopen __P((int, char *));
extern void checkfd012 __P((char *));
#endif
@ -1227,12 +1373,14 @@ extern void syserr(const char *, ...);
extern void usrerr(const char *, ...);
extern void message(const char *, ...);
extern void nmessage(const char *, ...);
extern void setproctitle(const char *fmt, ...);
#else
extern void auth_warning();
extern void syserr();
extern void usrerr();
extern void message();
extern void nmessage();
extern void setproctitle();
#endif
#if !HASSNPRINTF

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (with SMTP)";
static char sccsid[] = "@(#)srvrsmtp.c 8.123 (Berkeley) 10/12/96 (with SMTP)";
#else
static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (without SMTP)";
static char sccsid[] = "@(#)srvrsmtp.c 8.123 (Berkeley) 10/12/96 (without SMTP)";
#endif
#endif /* not lint */
@ -79,9 +79,11 @@ struct cmd
# define CMDHELO 9 /* helo -- be polite */
# define CMDHELP 10 /* help -- give usage info */
# define CMDEHLO 11 /* ehlo -- extended helo (RFC 1425) */
# define CMDETRN 12 /* etrn -- flush queue */
/* non-standard commands */
# define CMDONEX 16 /* onex -- sending one transaction only */
# define CMDVERB 17 /* verb -- go into verbose mode */
# define CMDXUSR 18 /* xusr -- initial (user) submission */
/* use this to catch and log "door handle" attempts on your system */
# define CMDLOGBOGUS 23 /* bogus command that should be logged */
/* debugging-only commands, only enabled if SMTPDEBUG is defined */
@ -90,27 +92,27 @@ struct cmd
static struct cmd CmdTab[] =
{
"mail", CMDMAIL,
"rcpt", CMDRCPT,
"data", CMDDATA,
"rset", CMDRSET,
"vrfy", CMDVRFY,
"expn", CMDEXPN,
"help", CMDHELP,
"noop", CMDNOOP,
"quit", CMDQUIT,
"helo", CMDHELO,
"ehlo", CMDEHLO,
"verb", CMDVERB,
"onex", CMDONEX,
/*
* remaining commands are here only
* to trap and log attempts to use them
*/
"showq", CMDDBGQSHOW,
"debug", CMDDBGDEBUG,
"wiz", CMDLOGBOGUS,
NULL, CMDERROR,
{ "mail", CMDMAIL },
{ "rcpt", CMDRCPT },
{ "data", CMDDATA },
{ "rset", CMDRSET },
{ "vrfy", CMDVRFY },
{ "expn", CMDEXPN },
{ "help", CMDHELP },
{ "noop", CMDNOOP },
{ "quit", CMDQUIT },
{ "helo", CMDHELO },
{ "ehlo", CMDEHLO },
{ "etrn", CMDETRN },
{ "verb", CMDVERB },
{ "onex", CMDONEX },
{ "xusr", CMDXUSR },
/* remaining commands are here only to trap and log attempts to use them */
{ "showq", CMDDBGQSHOW },
{ "debug", CMDDBGDEBUG },
{ "wiz", CMDLOGBOGUS },
{ NULL, CMDERROR }
};
bool OneXact = FALSE; /* one xaction only this run */
@ -122,7 +124,8 @@ static char *skipword();
#define MAXBADCOMMANDS 25 /* maximum number of bad commands */
void
smtp(e)
smtp(nullserver, e)
bool nullserver;
register ENVELOPE *volatile e;
{
register char *p;
@ -141,10 +144,15 @@ smtp(e)
volatile int nrcpts = 0; /* number of RCPT commands */
bool doublequeue;
volatile int badcommands = 0; /* count of bad commands */
volatile int nverifies = 0; /* count of VRFY/EXPN commands */
volatile int n_etrn = 0; /* count of ETRN commands */
char inp[MAXLINE];
char cmdbuf[MAXLINE];
extern ENVELOPE BlankEnvelope;
extern void help __P((char *));
extern void settime __P((ENVELOPE *));
extern bool enoughdiskspace __P((long));
extern int runinchild __P((char *, ENVELOPE *));
if (fileno(OutChannel) != fileno(stdout))
{
@ -253,6 +261,11 @@ smtp(e)
if (e->e_xfp != NULL)
fprintf(e->e_xfp, "<<< %s\n", inp);
#ifdef LOG
if (LogLevel >= 15)
syslog(LOG_INFO, "<-- %s", inp);
#endif
if (e->e_id == NULL)
setproctitle("%s: %.80s", CurSmtpClient, inp);
else
@ -282,7 +295,20 @@ smtp(e)
/* reset errors */
errno = 0;
/* process command */
/*
** Process command.
**
** If we are running as a null server, return 550
** to everything.
*/
if (nullserver && c->cmdcode != CMDQUIT)
{
message("550 Access denied");
continue;
}
/* non-null server */
switch (c->cmdcode)
{
case CMDHELO: /* hello -- introduce yourself */
@ -299,7 +325,7 @@ smtp(e)
}
/* check for valid domain name (re 1123 5.2.5) */
if (*p == '\0')
if (*p == '\0' && !AllowBogusHELO)
{
message("501 %s requires domain address",
cmdbuf);
@ -325,11 +351,23 @@ smtp(e)
}
if (*q != '\0')
{
message("501 Invalid domain name");
if (!AllowBogusHELO)
message("501 Invalid domain name");
else
message("250 %s Invalid domain name, accepting anyway",
MyHostName);
break;
}
}
/* check for duplicate HELO/EHLO per RFC 1651 4.2 */
if (gothello)
{
message("503 %s Duplicate HELO/EHLO",
MyHostName);
break;
}
sendinghost = newstr(p);
gothello = TRUE;
if (c->cmdcode != CMDEHLO)
@ -344,7 +382,10 @@ smtp(e)
message("250-%s Hello %s, pleased to meet you",
MyHostName, CurSmtpClient);
if (!bitset(PRIV_NOEXPN, PrivacyFlags))
{
message("250-EXPN");
message("250-VERB");
}
#if MIME8TO7
message("250-8BITMIME");
#endif
@ -356,8 +397,9 @@ smtp(e)
if (SendMIMEErrors)
message("250-DSN");
#endif
message("250-VERB");
message("250-ONEX");
message("250-ETRN");
message("250-XUSR");
message("250 HELP");
break;
@ -391,13 +433,17 @@ smtp(e)
finis();
}
p = skipword(p, "from");
if (p == NULL)
break;
/* fork a subprocess to process this command */
if (runinchild("SMTP-MAIL", e) > 0)
break;
if (!gothello)
{
auth_warning(e,
"Host %s didn't use HELO protocol",
"%s didn't use HELO protocol",
CurSmtpClient);
}
#ifdef PICKY_HELO_CHECK
@ -420,12 +466,10 @@ smtp(e)
setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp);
/* child -- go do the processing */
p = skipword(p, "from");
if (p == NULL)
break;
if (setjmp(TopFrame) > 0)
{
/* this failed -- undo work */
undo_subproc:
if (InChild)
{
QuickAbort = FALSE;
@ -440,9 +484,12 @@ smtp(e)
/* must parse sender first */
delimptr = NULL;
setsender(p, e, &delimptr, FALSE);
p = delimptr;
if (p != NULL && *p != '\0')
*p++ = '\0';
if (delimptr != NULL && *delimptr != '\0')
*delimptr++ = '\0';
/* do config file checking of the sender */
if (rscheck("check_mail", p, NULL, e) != EX_OK)
goto undo_subproc;
/* check for possible spoofing */
if (RealUid != 0 && OpMode == MD_SMTP &&
@ -456,6 +503,7 @@ smtp(e)
/* now parse ESMTP arguments */
e->e_msgsize = 0;
p = delimptr;
while (p != NULL && *p != '\0')
{
char *kp;
@ -470,7 +518,7 @@ smtp(e)
kp = p;
/* skip to the value portion */
while (isascii(*p) && isalnum(*p) || *p == '-')
while ((isascii(*p) && isalnum(*p)) || *p == '-')
p++;
if (*p == '=')
{
@ -534,9 +582,15 @@ smtp(e)
a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e);
if (a == NULL)
break;
p = delimptr;
if (delimptr != NULL && *delimptr != '\0')
*delimptr++ = '\0';
/* do config file checking of the recipient */
if (rscheck("check_rcpt", p, NULL, e) != EX_OK)
break;
/* now parse ESMTP arguments */
p = delimptr;
while (p != NULL && *p != '\0')
{
char *kp;
@ -551,7 +605,7 @@ smtp(e)
kp = p;
/* skip to the value portion */
while (isascii(*p) && isalnum(*p) || *p == '-')
while ((isascii(*p) && isalnum(*p)) || *p == '-')
p++;
if (*p == '=')
{
@ -582,7 +636,7 @@ smtp(e)
break;
/* no errors during parsing, but might be a duplicate */
e->e_to = p;
e->e_to = a->q_paddr;
if (!bitset(QBADADDR, a->q_flags))
{
message("250 Recipient ok%s",
@ -698,7 +752,7 @@ smtp(e)
/* clean up a bit */
gotmail = FALSE;
dropenvelope(e);
dropenvelope(e, TRUE);
CurEnv = e = newenvelope(e, CurEnv);
e->e_flags = BlankEnvelope.e_flags;
break;
@ -714,12 +768,24 @@ smtp(e)
/* clean up a bit */
gotmail = FALSE;
dropenvelope(e);
dropenvelope(e, TRUE);
CurEnv = e = newenvelope(e, CurEnv);
break;
case CMDVRFY: /* vrfy -- verify address */
case CMDEXPN: /* expn -- expand address */
if (++nverifies >= MAXBADCOMMANDS)
{
#ifdef LOG
if (nverifies == MAXBADCOMMANDS &&
LogLevel > 5)
{
syslog(LOG_INFO, "%.100s: VRFY attack?",
CurSmtpClient);
}
#endif
sleep(1);
}
vrfy = c->cmdcode == CMDVRFY;
if (bitset(vrfy ? PRIV_NOVRFY : PRIV_NOEXPN,
PrivacyFlags))
@ -778,20 +844,47 @@ smtp(e)
}
while (vrfyqueue != NULL)
{
extern void printvrfyaddr __P((ADDRESS *, bool));
extern void printvrfyaddr __P((ADDRESS *, bool, bool));
a = vrfyqueue;
while ((a = a->q_next) != NULL &&
bitset(QDONTSEND|QBADADDR, a->q_flags))
continue;
if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags))
printvrfyaddr(vrfyqueue, a == NULL);
printvrfyaddr(vrfyqueue, a == NULL, vrfy);
vrfyqueue = vrfyqueue->q_next;
}
if (InChild)
finis();
break;
case CMDETRN: /* etrn -- force queue flush */
if (strlen(p) <= 0)
{
message("500 Parameter required");
break;
}
/* crude way to avoid denial-of-service attacks */
if (n_etrn++ >= 3)
sleep(3);
id = p;
if (*id == '@')
id++;
else
*--id = '@';
#ifdef LOG
if (LogLevel > 5)
syslog(LOG_INFO, "%.100s: ETRN %s",
CurSmtpClient,
shortenstring(id, 203));
#endif
QueueLimitRecipient = id;
runqueue(TRUE);
QueueLimitRecipient = NULL;
message("250 Queuing for node %s started", p);
break;
case CMDHELP: /* help -- give user info */
help(p);
break;
@ -831,6 +924,11 @@ doquit:
message("250 Only one transaction");
break;
case CMDXUSR: /* initial (user) submission */
UserSubmission = TRUE;
message("250 Initial submission");
break;
# ifdef SMTPDEBUG
case CMDDBGQSHOW: /* show queues */
printf("Send Queue=");
@ -1112,6 +1210,7 @@ rcpt_esmtp_args(a, kp, vp, e)
** Parameters:
** a -- the address to print
** last -- set if this is the last one.
** vrfy -- set if this is a VRFY command.
**
** Returns:
** none.
@ -1121,13 +1220,18 @@ rcpt_esmtp_args(a, kp, vp, e)
*/
void
printvrfyaddr(a, last)
printvrfyaddr(a, last, vrfy)
register ADDRESS *a;
bool last;
bool vrfy;
{
char fmtbuf[20];
strcpy(fmtbuf, "250");
if (vrfy && a->q_mailer != NULL &&
!bitnset(M_VRFY250, a->q_mailer->m_flags))
strcpy(fmtbuf, "252");
else
strcpy(fmtbuf, "250");
fmtbuf[3] = last ? ' ' : '-';
if (a->q_fullname == NULL)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -36,9 +36,9 @@
#ifndef lint
#if USERDB
static char sccsid [] = "@(#)udb.c 8.33.1.2 (Berkeley) 9/16/96 (with USERDB)";
static char sccsid [] = "@(#)udb.c 8.42 (Berkeley) 9/18/96 (with USERDB)";
#else
static char sccsid [] = "@(#)udb.c 8.33.1.2 (Berkeley) 9/16/96 (without USERDB)";
static char sccsid [] = "@(#)udb.c 8.42 (Berkeley) 9/18/96 (without USERDB)";
#endif
#endif
@ -119,6 +119,8 @@ struct option
char *name;
char *val;
};
extern int _udbx_init __P((void));
/*
** UDBEXPAND -- look up user in database and expand
**
@ -159,7 +161,6 @@ udbexpand(a, sendq, aliaslevel, e)
int keylen;
int naddrs;
char keybuf[MAXKEY];
char buf[BUFSIZ];
if (tTd(28, 1))
printf("udbexpand(%s)\n", a->q_paddr);
@ -172,8 +173,6 @@ udbexpand(a, sendq, aliaslevel, e)
/* on first call, locate the database */
if (!UdbInitialized)
{
extern int _udbx_init();
if (_udbx_init() == EX_TEMPFAIL)
return EX_TEMPFAIL;
}
@ -187,7 +186,7 @@ udbexpand(a, sendq, aliaslevel, e)
return EX_OK;
/* if name is too long, assume it won't match */
if (strlen(a->q_user) > sizeof keybuf - 12)
if (strlen(a->q_user) > (SIZE_T) sizeof keybuf - 12)
return EX_OK;
/* if name begins with a colon, it indicates our metadata */
@ -203,6 +202,16 @@ udbexpand(a, sendq, aliaslevel, e)
for (up = UdbEnts; !breakout; up++)
{
char *user;
int usersize;
int userleft;
char userbuf[MEMCHUNKSIZE];
#if defined(HESIOD) && defined(HES_GETMAILHOST)
char pobuf[MAXNAME];
#endif
user = userbuf;
usersize = sizeof userbuf;
userleft = sizeof userbuf - 1;
/*
** Select action based on entry type.
@ -227,17 +236,18 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 2))
printf("udbexpand: no match on %s (%d)\n",
keybuf, keylen);
continue;
break;
}
if (tTd(28, 80))
printf("udbexpand: match %.*s: %.*s\n",
key.size, key.data, info.size, info.data);
naddrs = 0;
a->q_flags &= ~QSELFREF;
while (i == 0 && key.size == keylen &&
bcmp(key.data, keybuf, keylen) == 0)
{
char *p;
if (bitset(EF_VRFYONLY, e->e_flags))
{
a->q_flags |= QVERIFIED;
@ -245,24 +255,26 @@ udbexpand(a, sendq, aliaslevel, e)
}
breakout = TRUE;
if (info.size < sizeof buf)
user = buf;
else
user = xalloc(info.size + 1);
if (info.size >= userleft - 1)
{
char *nuser = xalloc(usersize + MEMCHUNKSIZE);
bcopy(user, nuser, usersize);
if (user != userbuf)
free(user);
user = nuser;
usersize += MEMCHUNKSIZE;
userleft += MEMCHUNKSIZE;
}
p = &user[strlen(user)];
if (p != user)
{
*p++ = ',';
userleft--;
}
bcopy(info.data, user, info.size);
user[info.size] = '\0';
message("expanded to %s", user);
#ifdef LOG
if (LogLevel >= 10)
syslog(LOG_INFO, "%s: expand %.100s => %s",
e->e_id, e->e_to,
shortenstring(user, 203));
#endif
naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e);
if (user != buf)
free(user);
userleft -= info.size;
/* get the next record */
i = (*up->udb_dbp->seq)(up->udb_dbp, &key, &info, R_NEXT);
@ -270,8 +282,16 @@ udbexpand(a, sendq, aliaslevel, e)
/* if nothing ever matched, try next database */
if (!breakout)
continue;
break;
message("expanded to %s", user);
#ifdef LOG
if (LogLevel >= 10)
syslog(LOG_INFO, "%s: expand %.100s => %s",
e->e_id, e->e_to,
shortenstring(user, 203));
#endif
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
@ -357,13 +377,24 @@ udbexpand(a, sendq, aliaslevel, e)
if (tTd(28, 2))
printf("hes_getmailhost(%s): %d\n",
a->q_user, hes_error());
continue;
break;
}
if (strlen(hp->po_name) + strlen(hp->po_host) >
sizeof pobuf - 2)
{
if (tTd(28, 2))
printf("hes_getmailhost(%s): expansion too long: %.30s@%.30s\n",
a->q_user,
hp->po_name,
hp->po_host);
break;
}
info.data = pobuf;
snprintf(pobuf, sizeof pobuf, "%s@%s",
hp->po_name, hp->po_host);
info.size = strlen(info.data);
#else
continue;
break;
#endif
}
if (tTd(28, 80))
@ -378,9 +409,7 @@ udbexpand(a, sendq, aliaslevel, e)
}
breakout = TRUE;
if (info.size < sizeof buf)
user = buf;
else
if (info.size >= usersize)
user = xalloc(info.size + 1);
bcopy(info.data, user, info.size);
user[info.size] = '\0';
@ -394,9 +423,6 @@ udbexpand(a, sendq, aliaslevel, e)
#endif
naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e);
if (user != buf)
free(user);
if (naddrs > 0 && !bitset(QSELFREF, a->q_flags))
{
if (tTd(28, 5))
@ -428,17 +454,18 @@ udbexpand(a, sendq, aliaslevel, e)
case UDB_REMOTE:
/* not yet implemented */
continue;
break;
case UDB_FORWARD:
if (bitset(EF_VRFYONLY, e->e_flags))
return EX_OK;
i = strlen(up->udb_fwdhost) + strlen(a->q_user) + 1;
if (i < sizeof buf)
user = buf;
else
user = xalloc(i + 1);
(void) snprintf(user, i, "%s@%s",
if (i >= usersize)
{
usersize = i + 1;
user = xalloc(usersize);
}
(void) snprintf(user, usersize, "%s@%s",
a->q_user, up->udb_fwdhost);
message("expanded to %s", user);
a->q_flags &= ~QSELFREF;
@ -452,19 +479,19 @@ udbexpand(a, sendq, aliaslevel, e)
}
a->q_flags |= QDONTSEND;
}
if (user != buf)
free(user);
breakout = TRUE;
break;
case UDB_EOLIST:
breakout = TRUE;
continue;
break;
default:
/* unknown entry type */
continue;
break;
}
if (user != userbuf)
free(user);
}
return EX_OK;
}
@ -798,6 +825,7 @@ _udbx_init()
char *mxhosts[MAXMXHOSTS + 1];
# endif
struct option opts[MAXUDBOPTS + 1];
extern int _udb_parsespec __P((char *, struct option [], int));
while (*p == ' ' || *p == '\t' || *p == ',')
p++;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -36,9 +36,9 @@
#ifndef lint
#ifdef SMTP
static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (with SMTP)";
static char sccsid[] = "@(#)usersmtp.c 8.72 (Berkeley) 9/15/96 (with SMTP)";
#else
static char sccsid[] = "@(#)usersmtp.c 8.65.1.2 (Berkeley) 9/16/96 (without SMTP)";
static char sccsid[] = "@(#)usersmtp.c 8.72 (Berkeley) 9/15/96 (without SMTP)";
#endif
#endif /* not lint */
@ -64,6 +64,7 @@ int SmtpPid; /* pid of mailer */
bool SmtpNeedIntro; /* need "while talking" in transcript */
extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)()));
/*
** SMTPINIT -- initialize SMTP.
**
@ -83,7 +84,7 @@ extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...));
void
smtpinit(m, mci, e)
struct mailer *m;
MAILER *m;
register MCI *mci;
ENVELOPE *e;
{
@ -327,7 +328,7 @@ helo_options(line, firstline, m, mci, e)
int
smtpmailfrom(m, mci, e)
struct mailer *m;
MAILER *m;
MCI *mci;
ENVELOPE *e;
{
@ -383,14 +384,16 @@ smtpmailfrom(m, mci, e)
else if (!bitset(MM_PASS8BIT, MimeMode))
{
/* cannot just send a 8-bit version */
extern char MsgBuf[];
usrerr("%s does not support 8BITMIME", mci->mci_host);
mci->mci_status = "5.6.3";
mci_setstat(mci, "5.6.3", MsgBuf);
return EX_DATAERR;
}
if (bitset(MCIF_DSN, mci->mci_flags))
{
if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) l)
if (e->e_envid != NULL && strlen(e->e_envid) < (SIZE_T) (l - 7))
{
strcat(optbuf, " ENVID=");
strcat(optbuf, e->e_envid);
@ -454,6 +457,7 @@ smtpmailfrom(m, mci, e)
}
else if (REPLYTYPE(r) == 4)
{
mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
return EX_TEMPFAIL;
}
else if (REPLYTYPE(r) == 2)
@ -463,24 +467,25 @@ smtpmailfrom(m, mci, e)
else if (r == 501)
{
/* syntax error in arguments */
mci->mci_status = "5.5.2";
mci_setstat(mci, "5.5.2", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 553)
{
/* mailbox name not allowed */
mci->mci_status = "5.1.3";
mci_setstat(mci, "5.1.3", SmtpReplyBuffer);
return EX_DATAERR;
}
else if (r == 552)
{
/* exceeded storage allocation */
mci->mci_status = "5.2.2";
mci_setstat(mci, "5.2.2", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
else if (REPLYTYPE(r) == 5)
{
/* unknown error */
mci_setstat(mci, "5.0.0", SmtpReplyBuffer);
return EX_UNAVAILABLE;
}
@ -494,6 +499,7 @@ smtpmailfrom(m, mci, e)
#endif
/* protocol error -- close up */
mci_setstat(mci, "5.5.1", SmtpReplyBuffer);
smtpquit(m, mci, e);
return EX_PROTOCOL;
}
@ -523,7 +529,6 @@ smtprcpt(to, m, mci, e)
register int r;
int l;
char optbuf[MAXLINE];
extern char *smtptodsn();
strcpy(optbuf, "");
l = sizeof optbuf - 1;
@ -581,10 +586,25 @@ smtprcpt(to, m, mci, e)
return EX_TEMPFAIL;
else if (REPLYTYPE(r) == 2)
return EX_OK;
else if (r == 550 || r == 551 || r == 553)
else if (r == 550)
{
to->q_status = "5.1.1";
return EX_NOUSER;
}
else if (r == 551)
{
to->q_status = "5.1.6";
return EX_NOUSER;
}
else if (r == 553)
{
to->q_status = "5.1.3";
return EX_NOUSER;
}
else if (REPLYTYPE(r) == 5)
{
return EX_UNAVAILABLE;
}
#ifdef LOG
if (LogLevel > 1)
@ -616,7 +636,7 @@ static void datatimeout();
int
smtpdata(m, mci, e)
struct mailer *m;
MAILER *m;
register MCI *mci;
register ENVELOPE *e;
{
@ -723,6 +743,7 @@ smtpdata(m, mci, e)
return EX_TEMPFAIL;
}
mci->mci_state = MCIS_OPEN;
mci_setstat(mci, smtptodsn(r), SmtpReplyBuffer);
e->e_statmsg = newstr(&SmtpReplyBuffer[4]);
if (REPLYTYPE(r) == 4)
return EX_TEMPFAIL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1983, 1995 Eric P. Allman
* Copyright (c) 1983, 1995, 1996 Eric P. Allman
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
*
@ -33,7 +33,7 @@
*/
#ifndef lint
static char sccsid[] = "@(#)util.c 8.84.1.4 (Berkeley) 9/16/96";
static char sccsid[] = "@(#)util.c 8.105 (Berkeley) 10/12/96";
#endif /* not lint */
# include "sendmail.h"
@ -260,50 +260,71 @@ xputs(s)
{
register int c;
register struct metamac *mp;
bool shiftout = FALSE;
extern struct metamac MetaMacros[];
if (s == NULL)
{
printf("<null>");
printf("%s<null>%s", TermEscape.te_rv_on, TermEscape.te_rv_off);
return;
}
while ((c = (*s++ & 0377)) != '\0')
{
if (shiftout)
{
printf("%s", TermEscape.te_rv_off);
shiftout = FALSE;
}
if (!isascii(c))
{
if (c == MATCHREPL)
{
putchar('$');
continue;
printf("%s$", TermEscape.te_rv_on);
shiftout = TRUE;
if (*s == '\0')
continue;
c = *s++ & 0377;
goto printchar;
}
if (c == MACROEXPAND)
{
putchar('$');
printf("%s$", TermEscape.te_rv_on);
shiftout = TRUE;
if (strchr("=~&?", *s) != NULL)
putchar(*s++);
if (bitset(0200, *s))
printf("{%s}", macname(*s++ & 0377));
else
printf("%c", *s++);
continue;
}
for (mp = MetaMacros; mp->metaname != '\0'; mp++)
{
if ((mp->metaval & 0377) == c)
{
printf("$%c", mp->metaname);
printf("%s$%c",
TermEscape.te_rv_on,
mp->metaname);
shiftout = TRUE;
break;
}
}
if (c == MATCHCLASS || c == MATCHNCLASS)
{
if (!bitset(0200, *s))
continue;
printf("{%s}", macname(*s++ & 0377));
if (bitset(0200, *s))
printf("{%s}", macname(*s++ & 0377));
else
printf("%c", *s++);
}
if (mp->metaname != '\0')
continue;
(void) putchar('\\');
/* unrecognized meta character */
printf("%sM-", TermEscape.te_rv_on);
shiftout = TRUE;
c &= 0177;
}
printchar:
if (isprint(c))
{
putchar(c);
@ -324,15 +345,25 @@ xputs(s)
case '\t':
c = 't';
break;
default:
}
if (!shiftout)
{
printf("%s", TermEscape.te_rv_on);
shiftout = TRUE;
}
if (isprint(c))
{
(void) putchar('\\');
(void) putchar(c);
}
else
{
(void) putchar('^');
(void) putchar(c ^ 0100);
continue;
}
(void) putchar('\\');
(void) putchar(c);
}
if (shiftout)
printf("%s", TermEscape.te_rv_off);
(void) fflush(stdout);
}
/*
@ -397,27 +428,18 @@ buildfname(gecos, login, buf, buflen)
if (*gecos == '*')
gecos++;
/* find length of final string */
l = 0;
for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
{
if (*p == '&')
l += strlen(login);
else
l++;
}
if (l > buflen - 1)
{
/* not a good sign */
snprintf(buf, buflen, "%s", gecos);
return;
}
/* now fill in buf */
/* copy gecos, interpolating & to be full name */
for (p = gecos; *p != '\0' && *p != ',' && *p != ';' && *p != '%'; p++)
{
if (bp >= &buf[buflen - 1])
{
/* buffer overflow -- just use login name */
snprintf(buf, buflen, "%s", login);
return;
}
if (*p == '&')
{
/* interpolate full name */
snprintf(bp, buflen - (bp - buf), "%s", login);
*bp = toupper(*bp);
bp += strlen(bp);
@ -470,8 +492,8 @@ buildfname(gecos, login, buf, buflen)
int
safefile(fn, uid, gid, uname, flags, mode, st)
char *fn;
uid_t uid;
gid_t gid;
UID_T uid;
GID_T gid;
char *uname;
int flags;
int mode;
@ -552,7 +574,7 @@ safefile(fn, uid, gid, uname, flags, mode, st)
bitset(S_IXGRP, stbuf.st_mode))
continue;
#ifndef NO_GROUP_SET
if (uname != NULL &&
if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
(gr = getgrgid(stbuf.st_gid)) != NULL))
{
@ -651,7 +673,7 @@ safefile(fn, uid, gid, uname, flags, mode, st)
if (st->st_gid == gid)
;
#ifndef NO_GROUP_SET
else if (uname != NULL &&
else if (uname != NULL && !DontInitGroups &&
((gr != NULL && gr->gr_gid == st->st_gid) ||
(gr = getgrgid(st->st_gid)) != NULL))
{
@ -815,12 +837,12 @@ struct omodes
char *farg;
} OpenModes[] =
{
O_ACCMODE, O_RDONLY, "r",
O_ACCMODE|O_APPEND, O_WRONLY, "w",
O_ACCMODE|O_APPEND, O_WRONLY|O_APPEND, "a",
O_TRUNC, 0, "w+",
O_APPEND, O_APPEND, "a+",
0, 0, "r+",
{ O_ACCMODE, O_RDONLY, "r" },
{ O_ACCMODE|O_APPEND, O_WRONLY, "w" },
{ O_ACCMODE|O_APPEND, O_WRONLY|O_APPEND, "a" },
{ O_TRUNC, 0, "w+" },
{ O_APPEND, O_APPEND, "a+" },
{ 0, 0, "r+" },
};
FILE *
@ -1109,9 +1131,11 @@ sfgets(buf, siz, fp, timeout, during)
if (setjmp(CtxReadTimeout) != 0)
{
# ifdef LOG
syslog(LOG_NOTICE,
"timeout waiting for input from %.100s during %s",
CurHostName? CurHostName: "local", during);
if (LogLevel > 1)
syslog(LOG_NOTICE,
"timeout waiting for input from %.100s during %s",
CurHostName ? CurHostName : "local",
during);
# endif
errno = 0;
usrerr("451 timeout waiting for input during %s",
@ -1339,19 +1363,21 @@ atooct(s)
int
waitfor(pid)
int pid;
pid_t pid;
{
#ifdef WAITUNION
union wait st;
#else
auto int st;
#endif
int i;
pid_t i;
do
{
errno = 0;
i = wait(&st);
if (i > 0)
proc_list_drop(i);
} while ((i >= 0 || errno == EINTR) && i != pid);
if (i < 0)
return -1;
@ -1470,7 +1496,7 @@ checkfd012(where)
for (i = 0; i < 3; i++)
{
if (fstat(i, &stbuf) < 0 && errno != EOPNOTSUPP)
if (fstat(i, &stbuf) < 0 && errno == EBADF)
{
/* oops.... */
int fd;
@ -1487,6 +1513,90 @@ checkfd012(where)
#endif /* XDEBUG */
}
/*
** CHECKFDOPEN -- make sure file descriptor is open -- for extended debugging
**
** Parameters:
** fd -- file descriptor to check.
** where -- tag to print on failure.
**
** Returns:
** none.
*/
void
checkfdopen(fd, where)
int fd;
char *where;
{
#if XDEBUG
struct stat st;
if (fstat(fd, &st) < 0 && errno == EBADF)
{
syserr("checkfdopen(%d): %s not open as expected!", fd, where);
printopenfds(TRUE);
}
#endif
}
/*
** CHECKFDS -- check for new or missing file descriptors
**
** Parameters:
** where -- tag for printing. If null, take a base line.
**
** Returns:
** none
**
** Side Effects:
** If where is set, shows changes since the last call.
*/
void
checkfds(where)
char *where;
{
int maxfd;
register int fd;
bool printhdr = TRUE;
int save_errno = errno;
static BITMAP baseline;
extern int DtableSize;
if (DtableSize > 256)
maxfd = 256;
else
maxfd = DtableSize;
if (where == NULL)
clrbitmap(baseline);
for (fd = 0; fd < maxfd; fd++)
{
struct stat stbuf;
if (fstat(fd, &stbuf) < 0 && errno != EOPNOTSUPP)
{
if (!bitnset(fd, baseline))
continue;
clrbitn(fd, baseline);
}
else if (!bitnset(fd, baseline))
setbitn(fd, baseline);
else
continue;
/* file state has changed */
if (where == NULL)
continue;
if (printhdr)
{
syslog(LOG_DEBUG, "%s: changed fds:", where);
printhdr = FALSE;
}
dumpfd(fd, TRUE, TRUE);
}
errno = save_errno;
}
/*
** PRINTOPENFDS -- print the open file descriptors (for debugging)
**
** Parameters:
@ -1542,12 +1652,17 @@ dumpfd(fd, printclosed, logit)
if (fstat(fd, &st) < 0)
{
if (printclosed || errno != EBADF)
if (errno != EBADF)
{
snprintf(p, SPACELEFT(buf, p), "CANNOT STAT (%s)",
errstring(errno));
goto printit;
}
else if (printclosed)
{
snprintf(p, SPACELEFT(buf, p), "CLOSED");
goto printit;
}
return;
}
@ -1812,8 +1927,10 @@ prog_open(argv, pfd, e)
/* run as default user */
endpwent();
setgid(DefGid);
setuid(DefUid);
if (setgid(DefGid) < 0)
syserr("prog_open: setgid(%ld) failed", (long) DefGid);
if (setuid(DefUid) < 0)
syserr("prog_open: setuid(%ld) failed", (long) DefUid);
/* run in some directory */
if (ProgMailer != NULL)
@ -1856,6 +1973,7 @@ prog_open(argv, pfd, e)
if (transienterror(saveerrno))
_exit(EX_OSERR);
_exit(EX_CONFIG);
return -1; /* avoid compiler warning on IRIX */
}
/*
** GET_COLUMN -- look up a Column in a line buffer
@ -1904,7 +2022,7 @@ get_column(line, col, delim, buf, buflen)
if (col == 0 && delim == '\0')
{
while (*begin && isspace(*begin))
while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
@ -1915,14 +2033,14 @@ get_column(line, col, delim, buf, buflen)
begin++;
if (delim == '\0')
{
while (*begin && isspace(*begin))
while (*begin != '\0' && isascii(*begin) && isspace(*begin))
begin++;
}
}
end = strpbrk(begin, delimbuf);
if (end == NULL)
i = strlen(buf);
i = strlen(begin);
else
i = end - begin;
if (i >= buflen)
@ -2022,3 +2140,112 @@ denlstring(s, strict, logattacks)
return bp;
}
/*
** PATH_IS_DIR -- check to see if file exists and is a directory.
**
** Parameters:
** pathname -- pathname to check for directory-ness.
** createflag -- if set, create directory if needed.
**
** Returns:
** TRUE -- if the indicated pathname is a directory
** FALSE -- otherwise
*/
int
path_is_dir(pathname, createflag)
char *pathname;
bool createflag;
{
struct stat statbuf;
if (stat(pathname, &statbuf) < 0)
{
if (errno != ENOENT || !createflag)
return FALSE;
if (mkdir(pathname, 0755) < 0)
return FALSE;
return TRUE;
}
if (!S_ISDIR(statbuf.st_mode))
{
errno = ENOTDIR;
return FALSE;
}
return TRUE;
}
/*
** PROC_LIST_ADD -- add process id to list of our children
**
** Parameters:
** pid -- pid to add to list.
**
** Returns:
** none
*/
static pid_t *ProcListVec = NULL;
static int ProcListSize = 0;
#define NO_PID ((pid_t) 0)
#ifndef PROC_LIST_SEG
# define PROC_LIST_SEG 32 /* number of pids to alloc at a time */
#endif
void
proc_list_add(pid)
pid_t pid;
{
int i;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i] == NO_PID)
break;
}
if (i >= ProcListSize)
{
/* grow process list */
pid_t *npv;
npv = (pid_t *) xalloc(sizeof (pid_t) * (ProcListSize + PROC_LIST_SEG));
if (ProcListSize > 0)
{
bcopy(ProcListVec, npv, ProcListSize * sizeof (pid_t));
free(ProcListVec);
}
for (i = ProcListSize; i < ProcListSize + PROC_LIST_SEG; i++)
npv[i] = NO_PID;
i = ProcListSize;
ProcListSize += PROC_LIST_SEG;
ProcListVec = npv;
}
ProcListVec[i] = pid;
CurChildren++;
}
/*
** PROC_LIST_DROP -- drop pid from process list
**
** Parameters:
** pid -- pid to drop
**
** Returns:
** none.
*/
void
proc_list_drop(pid)
pid_t pid;
{
int i;
for (i = 0; i < ProcListSize; i++)
{
if (ProcListVec[i] == pid)
{
ProcListVec[i] = NO_PID;
CurChildren--;
break;
}
}
}