diff options
58 files changed, 10213 insertions, 6713 deletions
diff --git a/usr.sbin/sendmail/cf/cf/Makefile b/usr.sbin/sendmail/cf/cf/Makefile index 3d0ab69..90372b7 100644 --- a/usr.sbin/sendmail/cf/cf/Makefile +++ b/usr.sbin/sendmail/cf/cf/Makefile @@ -1,7 +1,18 @@ -# @(#)Makefile 8.5 (Berkeley) 12/1/93 +# @(#)Makefile 8.17 (Berkeley) 9/12/95 + +# +# This Makefile uses the new Berkeley "make" program. See Makefile.dist +# for a more vanilla version. +# +# Configuration files are created using "m4 file.mc > file.cf"; +# this may be easier than tweaking the Makefile. You do need to +# have a fairly modern M4 available (GNU m4 works). On SunOS, use +# /usr/5bin/m4. +# M4= m4 #M4= /usr/src/usr.bin/m4/obj/m4 +CFDIR= .. CHMOD= chmod ROMODE= 444 RM= rm -f @@ -10,73 +21,87 @@ RM= rm -f .mc.cf: $(RM) $@ - (cd ${.CURDIR} && $(M4) ${@:R}.mc ) > $@ + (cd ${.CURDIR} && $(M4) ${CFDIR}/m4/cf.m4 ${@:R}.mc > $@) $(CHMOD) $(ROMODE) $@ -CLEANFILES= cs-hidden.cf cs-exposed.cf \ - hpux-cs-exposed.cf hpux-cs-hidden.cf \ - riscos-cs-exposed.cf \ - sunos3.5-cs-exposed.cf sunos3.5-cs-hidden.cf \ - sunos4.1-cs-exposed.cf sunos4.1-cs-hidden.cf \ - ultrix4.1-cs-exposed.cf ultrix4.1-cs-hidden.cf \ - osf1-cs-exposed.cf osf1-cs-hidden.cf \ - mail.cs.cf mail.eecs.cf ucbvax.cf vangogh.cf \ - chez.cf knecht.cf cogsci.cf alpha.cf s2k.cf auspex.cf \ - python.cf \ - clientproto.cf tcpproto.cf uucpproto.cf +ALL= generic-bsd4.4.cf generic-hpux9.cf generic-hpux10.cf \ + generic-osf1.cf generic-solaris2.cf \ + generic-sunos4.1.cf generic-ultrix4.cf \ + cs-hpux9.cf cs-osf1.cf cs-solaris2.cf \ + cs-sunos4.1.cf cs-ultrix4.cf \ + s2k-osf1.cf s2k-ultrix4.cf \ + chez.cs.cf huginn.cs.cf mail.cs.cf mail.eecs.cf mailspool.cs.cf \ + python.cs.cf ucbarpa.cf ucbvax.cf vangogh.cs.cf -all: $(CLEANFILES) +all: $(ALL) depend install: # this is overkill, but.... M4FILES=\ - ../domain/Berkeley.m4 \ - ../domain/cs.exposed.m4 \ - ../domain/cs.hidden.m4 \ - ../domain/eecs.hidden.m4 \ - ../domain/s2k.m4 \ - ../feature/allmasquerade.m4 \ - ../feature/always_add_domain.m4 \ - ../feature/bitdomain.m4 \ - ../feature/domaintable.m4 \ - ../feature/mailertable.m4 \ - ../feature/nocanonify.m4 \ - ../feature/nodns.m4 \ - ../feature/notsticky.m4 \ - ../feature/nouucp.m4 \ - ../feature/nullclient.m4 \ - ../feature/redirect.m4 \ - ../feature/use_cw_file.m4 \ - ../feature/uucpdomain.m4 \ - ../hack/cssubdomain.m4 \ - ../m4/cf.m4 \ - ../m4/nullrelay.m4 \ - ../m4/proto.m4 \ - ../m4/version.m4 \ - ../mailer/fax.m4 \ - ../mailer/local.m4 \ - ../mailer/smtp.m4 \ - ../mailer/usenet.m4 \ - ../mailer/uucp.m4 \ - ../ostype/aix3.m4 \ - ../ostype/bsd4.3.m4 \ - ../ostype/bsd4.4.m4 \ - ../ostype/hpux.m4 \ - ../ostype/irix.m4 \ - ../ostype/linux.m4 \ - ../ostype/nextstep.m4 \ - ../ostype/osf1.m4 \ - ../ostype/riscos4.5.m4 \ - ../ostype/solaris2.m4 \ - ../ostype/sunos3.5.m4 \ - ../ostype/sunos4.1.m4 \ - ../ostype/svr4.m4 \ - ../ostype/ultrix4.1.m4 \ - ../siteconfig/uucp.cogsci.m4 \ - ../siteconfig/uucp.old.arpa.m4 \ - ../siteconfig/uucp.ucbarpa.m4 \ - ../siteconfig/uucp.ucbvax.m4 \ + ${CFDIR}/domain/Berkeley.EDU.m4 \ + ${CFDIR}/domain/CS.Berkeley.EDU.m4 \ + ${CFDIR}/domain/EECS.Berkeley.EDU.m4 \ + ${CFDIR}/domain/S2K.Berkeley.EDU.m4 \ + ${CFDIR}/feature/allmasquerade.m4 \ + ${CFDIR}/feature/always_add_domain.m4 \ + ${CFDIR}/feature/bestmx_is_local.m4 \ + ${CFDIR}/feature/bitdomain.m4 \ + ${CFDIR}/feature/domaintable.m4 \ + ${CFDIR}/feature/local_procmail.m4 \ + ${CFDIR}/feature/mailertable.m4 \ + ${CFDIR}/feature/nocanonify.m4 \ + ${CFDIR}/feature/nodns.m4 \ + ${CFDIR}/feature/notsticky.m4 \ + ${CFDIR}/feature/nouucp.m4 \ + ${CFDIR}/feature/nullclient.m4 \ + ${CFDIR}/feature/redirect.m4 \ + ${CFDIR}/feature/smrsh.m4 \ + ${CFDIR}/feature/stickyhost.m4 \ + ${CFDIR}/feature/use_cw_file.m4 \ + ${CFDIR}/feature/uucpdomain.m4 \ + ${CFDIR}/hack/cssubdomain.m4 \ + ${CFDIR}/m4/cf.m4 \ + ${CFDIR}/m4/cfhead.m4 \ + ${CFDIR}/m4/nullrelay.m4 \ + ${CFDIR}/m4/proto.m4 \ + ${CFDIR}/m4/version.m4 \ + ${CFDIR}/mailer/cyrus.m4 \ + ${CFDIR}/mailer/fax.m4 \ + ${CFDIR}/mailer/local.m4 \ + ${CFDIR}/mailer/mail11.m4 \ + ${CFDIR}/mailer/pop.m4 \ + ${CFDIR}/mailer/procmail.m4 \ + ${CFDIR}/mailer/smtp.m4 \ + ${CFDIR}/mailer/usenet.m4 \ + ${CFDIR}/mailer/uucp.m4 \ + ${CFDIR}/ostype/aix3.m4 \ + ${CFDIR}/ostype/amdahl-uts.m4 \ + ${CFDIR}/ostype/aux.m4 \ + ${CFDIR}/ostype/bsd4.3.m4 \ + ${CFDIR}/ostype/bsd4.4.m4 \ + ${CFDIR}/ostype/bsdi1.0.m4 \ + ${CFDIR}/ostype/dgux.m4 \ + ${CFDIR}/ostype/domainos.m4 \ + ${CFDIR}/ostype/dynix3.2.m4 \ + ${CFDIR}/ostype/hpux9.m4 \ + ${CFDIR}/ostype/irix4.m4 \ + ${CFDIR}/ostype/irix5.m4 \ + ${CFDIR}/ostype/linux.m4 \ + ${CFDIR}/ostype/nextstep.m4 \ + ${CFDIR}/ostype/osf1.m4 \ + ${CFDIR}/ostype/ptx2.m4 \ + ${CFDIR}/ostype/riscos4.5.m4 \ + ${CFDIR}/ostype/sco3.2.m4 \ + ${CFDIR}/ostype/solaris2.m4 \ + ${CFDIR}/ostype/sunos3.5.m4 \ + ${CFDIR}/ostype/sunos4.1.m4 \ + ${CFDIR}/ostype/svr4.m4 \ + ${CFDIR}/ostype/ultrix4.m4 \ + ${CFDIR}/siteconfig/uucp.cogsci.m4 \ + ${CFDIR}/siteconfig/uucp.old.arpa.m4 \ + ${CFDIR}/siteconfig/uucp.ucbarpa.m4 \ + ${CFDIR}/siteconfig/uucp.ucbvax.m4 \ $(ALL): $(M4FILES) diff --git a/usr.sbin/sendmail/contrib/bitdomain.c b/usr.sbin/sendmail/contrib/bitdomain.c index d5e8549..720b9a1 100644 --- a/usr.sbin/sendmail/contrib/bitdomain.c +++ b/usr.sbin/sendmail/contrib/bitdomain.c @@ -1,6 +1,6 @@ /* * By John G. Myers, jgm+@cmu.edu - * Version 1.1 + * Version 1.2 * * Process a BITNET "internet.listing" file, producing output * suitable for input to makemap. @@ -154,7 +154,7 @@ char *domainlen; * if "domain" doesn't have a domain expansion already. */ p = lookup(domain); - if (!p || !index(p, '.')) remember(domain, otherdomain); + if (!p || !strchr(p, '.')) remember(domain, otherdomain); } } else { @@ -167,7 +167,7 @@ char *domainlen; * have a domain expansion, give it the expansion "domain". */ p = lookup(otherdomain); - if (!p || !index(p, '.')) remember(otherdomain, domain); + if (!p || !strchr(p, '.')) remember(otherdomain, domain); } } else { diff --git a/usr.sbin/sendmail/makemap/makemap.c b/usr.sbin/sendmail/makemap/makemap.c index 14548bd..c48a1c9 100644 --- a/usr.sbin/sendmail/makemap/makemap.c +++ b/usr.sbin/sendmail/makemap/makemap.c @@ -33,15 +33,18 @@ */ #ifndef lint -static char sccsid[] = "@(#)makemap.c 8.6.1.1 (Berkeley) 3/6/95"; +static char sccsid[] = "@(#)makemap.c 8.14 (Berkeley) 11/5/95"; #endif /* not lint */ #include <stdio.h> #include <sysexits.h> #include <sys/types.h> -#include <sys/file.h> #include <ctype.h> #include <string.h> +#include <sys/errno.h> +#ifndef ISC_UNIX +# include <sys/file.h> +#endif #include "useful.h" #include "conf.h" @@ -80,6 +83,7 @@ main(argc, argv) bool inclnull = FALSE; bool notrunc = FALSE; bool allowreplace = FALSE; + bool allowdups = FALSE; bool verbose = FALSE; bool foldcase = TRUE; int exitstat; @@ -87,10 +91,12 @@ main(argc, argv) char *typename; char *mapname; char *ext; + char *lext; int lineno; int st; int mode; enum type type; + int fd; union { #ifdef NDBM @@ -102,14 +108,19 @@ main(argc, argv) void *dbx; } dbp; union dbent key, val; +#ifdef NEWDB + BTREEINFO bti; +#endif char ibuf[BUFSIZE]; char fbuf[MAXNAME]; + char lbuf[MAXNAME]; extern char *optarg; extern int optind; + extern bool lockfile(); progname = argv[0]; - while ((opt = getopt(argc, argv, "Nforv")) != EOF) + while ((opt = getopt(argc, argv, "Ndforv")) != EOF) { switch (opt) { @@ -117,6 +128,10 @@ main(argc, argv) inclnull = TRUE; break; + case 'd': + allowdups = TRUE; + break; + case 'f': foldcase = FALSE; break; @@ -148,10 +163,12 @@ main(argc, argv) typename = argv[0]; mapname = argv[1]; ext = NULL; + lext = NULL; if (strcmp(typename, "dbm") == 0) { type = T_DBM; + lext = ".dir"; } else if (strcmp(typename, "btree") == 0) { @@ -170,7 +187,7 @@ main(argc, argv) switch (type) { case T_ERR: - fprintf(stderr, "Usage: %s [-N] [-o] [-v] type mapname\n", progname); + fprintf(stderr, "Usage: %s [-N] [-d] [-f] [-o] [-r] [-v] type mapname\n", progname); exit(EX_USAGE); case T_UNKNOWN: @@ -188,6 +205,26 @@ main(argc, argv) fprintf(stderr, "%s: Type %s not supported in this version\n", progname, typename); exit(EX_UNAVAILABLE); + +#ifdef NEWDB + case T_BTREE: + bzero(&bti, sizeof bti); + if (allowdups) + bti.flags |= R_DUP; + break; + + case T_HASH: +#endif +#ifdef NDBM + case T_DBM: +#endif + if (allowdups) + { + fprintf(stderr, "%s: Type %s does not support -d (allow dups)\n", + progname, typename); + exit(EX_UNAVAILABLE); + } + break; } /* @@ -208,6 +245,10 @@ main(argc, argv) } } + strcpy(lbuf, mapname); + if (lext != NULL) + strcat(lbuf, lext); + /* ** Create the database. */ @@ -215,6 +256,19 @@ main(argc, argv) mode = O_RDWR; if (!notrunc) mode |= O_CREAT|O_TRUNC; +#ifdef O_EXLOCK + mode |= O_EXLOCK; +#else + /* pre-lock the database */ + fd = open(lbuf, mode & ~O_TRUNC, 0644); + if (fd < 0) + { + fprintf(stderr, "%s: cannot create type %s map %s\n", + progname, typename, mapname); + exit(EX_CANTCREAT); + } + (void) lockfile(fd); +#endif switch (type) { #ifdef NDBM @@ -227,13 +281,25 @@ main(argc, argv) case T_HASH: dbp.db = dbopen(mapname, mode, 0644, DB_HASH, NULL); if (dbp.db != NULL) + { +# if OLD_NEWDB + (void) (*dbp.db->sync)(dbp.db); +# else (void) (*dbp.db->sync)(dbp.db, 0); +# endif + } break; case T_BTREE: - dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, NULL); + dbp.db = dbopen(mapname, mode, 0644, DB_BTREE, &bti); if (dbp.db != NULL) + { +# if OLD_NEWDB + (void) (*dbp.db->sync)(dbp.db); +# else (void) (*dbp.db->sync)(dbp.db, 0); +# endif + } break; #endif @@ -244,7 +310,7 @@ main(argc, argv) if (dbp.dbx == NULL) { - fprintf(stderr, "%s: cannot create type %s map %s\n", + fprintf(stderr, "%s: cannot open type %s map %s\n", progname, typename, mapname); exit(EX_CANTCREAT); } @@ -373,5 +439,58 @@ main(argc, argv) #endif } +#ifndef O_EXLOCK + /* release locks */ + close(fd); +#endif + exit (exitstat); } +/* +** LOCKFILE -- lock a file using flock or (shudder) fcntl locking +** +** Parameters: +** fd -- the file descriptor of the file. +** +** Returns: +** TRUE if the lock was acquired. +** FALSE otherwise. +*/ + +bool +lockfile(fd) + int fd; +{ +# if !HASFLOCK + int action; + struct flock lfd; + extern int errno; + + bzero(&lfd, sizeof lfd); + lfd.l_type = F_WRLCK; + action = F_SETLKW; + + if (fcntl(fd, action, &lfd) >= 0) + return TRUE; + + /* + ** On SunOS, if you are testing using -oQ/tmp/mqueue or + ** -oA/tmp/aliases or anything like that, and /tmp is mounted + ** as type "tmp" (that is, served from swap space), the + ** previous fcntl will fail with "Invalid argument" errors. + ** Since this is fairly common during testing, we will assume + ** that this indicates that the lock is successfully grabbed. + */ + + if (errno == EINVAL) + return TRUE; + +# else /* HASFLOCK */ + + if (flock(fd, LOCK_EX) >= 0) + return TRUE; + +# endif + + return FALSE; +} diff --git a/usr.sbin/sendmail/src/Makefile b/usr.sbin/sendmail/src/Makefile index 6295846..c3919d2 100644 --- a/usr.sbin/sendmail/src/Makefile +++ b/usr.sbin/sendmail/src/Makefile @@ -1,4 +1,9 @@ -# @(#)Makefile 8.4 (Berkeley) 2/3/94 +# @(#)Makefile 8.7 (Berkeley) 10/31/95 + +######################################################################### +# This Makefile is for 4.4BSD only!!! For all other systems, use # +# the "makesendmail" script. # +######################################################################### PROG= sendmail @@ -10,14 +15,14 @@ PROG= sendmail # databases are read, but the new format will be used on any rebuilds. On # really gnarly systems, you can set this to null; it will crawl like a high # spiral snail, but it will work. -DBMDEF= -DNEWDB -DNDBM +DBMDEF= -DNEWDB CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ + mci.c mime.c parseaddr.c queue.c readcf.c recipient.c savemail.c \ + srvrsmtp.c stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ util.c version.c DPADD= LDADD= diff --git a/usr.sbin/sendmail/src/Makefile.386BSD b/usr.sbin/sendmail/src/Makefile.386BSD deleted file mode 100644 index 397ce8b..0000000 --- a/usr.sbin/sendmail/src/Makefile.386BSD +++ /dev/null @@ -1,42 +0,0 @@ -# @(#)Makefile.386BSD 8.1 (Berkeley) 2/26/94 - -PROG= sendmail - -# define the database format to use for aliases et al. Can be -DNEWDB (for -# the new BSD database package -- this is preferred) or -DNDBM for the NDBM -# database package. The old putrescent V7 DBM package is no longer -# supported. -# You can define both NEWDB and NDBM during a transition period; old -# databases are read, but the new format will be used on any rebuilds. On -# really gnarly systems, you can set this to null; it will crawl like a high -# spiral snail, but it will work. -DBMDEF= -DNEWDB - -CFLAGS+=-I${.CURDIR} ${DBMDEF} -DMIME - -SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ - deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ - util.c version.c -DPADD= -LDADD= $(LIBUTIL) -MAN1= newaliases.0 mailq.0 -MAN5= aliases.0 -MAN8= sendmail.0 -LINKS= /usr/sbin/sendmail /usr/bin/newaliases \ - /usr/sbin/sendmail /usr/bin/mailq -BINDIR= /usr/sbin -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -beforeinstall: -# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ -# ${DESTDIR}/etc/sendmail.fc - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/log/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \ - ${DESTDIR}/usr/share/misc - -.include <bsd.prog.mk> diff --git a/usr.sbin/sendmail/src/Makefile.AIX b/usr.sbin/sendmail/src/Makefile.AIX deleted file mode 100644 index 5d3041d..0000000 --- a/usr.sbin/sendmail/src/Makefile.AIX +++ /dev/null @@ -1,113 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on AIX 3.1.5 and 3.2.3e. -# -# @(#)Makefile.AIX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -# you can use -O3 on AIX 3.2.4 or greater ONLY! -O= -g - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB -DNIS -# -# If you did not install the NEWDB on your AIX platform, use: -#DBMDEF=-DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -D_AIX3 - -# see also conf.h for additional compilation flags - -# include directories -#INCDIRS=-I/usr/sww/include/db - -# library directories -#LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldbm -ldb -# -# If you did not install the NEWDB on your AIX platform, use: -#LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/sbin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -INSTALL=/usr/ucb/install - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/sbin/newaliases ${DESTDIR}/usr/sbin/mailq -BINOWN= root -BINGRP= system -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.AUX b/usr.sbin/sendmail/src/Makefile.AUX deleted file mode 100644 index dc84b21..0000000 --- a/usr.sbin/sendmail/src/Makefile.AUX +++ /dev/null @@ -1,105 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# @(#)Makefile.AUX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldbm -lposix - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/sbin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/share/misc - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do ; rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.BSD43 b/usr.sbin/sendmail/src/Makefile.BSD43 deleted file mode 100644 index 4177c3b..0000000 --- a/usr.sbin/sendmail/src/Makefile.BSD43 +++ /dev/null @@ -1,123 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This is based on work from Jim Oldroyd -- I believe he was -# using a fairly old Mt Xinu port. -# -# It should also work on UMIPS-BSD from MIPS, if you still have -# any lying around. -# -# @(#)Makefile.BSD43 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DoldBSD43 - -# see also conf.h for additional compilation flags - -# include directories -#INCDIRS=-I/usr/sww/include/db - -# library directories -#LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldbm -lresolv -ll - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= unistd.h stddef.h stdlib.h dirent.h sys/time.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -unistd.h stddef.h stdlib.h sys/time.h: - cp /dev/null $@ - -sys/time.h: sys - -sys: - mkdir sys - -dirent.h: - echo "#include <sys/dir.h>" > dirent.h - echo "#define dirent direct" >> dirent.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.BSDI b/usr.sbin/sendmail/src/Makefile.BSDI deleted file mode 100644 index a45016d..0000000 --- a/usr.sbin/sendmail/src/Makefile.BSDI +++ /dev/null @@ -1,32 +0,0 @@ -# @(#)Makefile.BSDI 8.1 (Berkeley) 2/26/94 - -PROG= sendmail -DBMDEF= -DNEWDB -CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO - -SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ - deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ - util.c version.c -DPADD= ${LIBUTIL} ${LIBKVM} -LDADD= -lutil -lkvm -MAN1= mailq.0 newaliases.0 -MAN5= aliases.0 -MAN8= sendmail.0 -LINKS= /usr/sbin/sendmail /usr/bin/newaliases \ - /usr/sbin/sendmail /usr/bin/mailq -BINDIR= /usr/sbin -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -beforeinstall: -# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ -# ${DESTDIR}/etc/sendmail.fc - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/log/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \ - ${DESTDIR}/usr/share/misc - -.include <bsd.prog.mk> diff --git a/usr.sbin/sendmail/src/Makefile.CLIX b/usr.sbin/sendmail/src/Makefile.CLIX deleted file mode 100644 index 7e54e36..0000000 --- a/usr.sbin/sendmail/src/Makefile.CLIX +++ /dev/null @@ -1,115 +0,0 @@ -# -# This makefile is for clipper-based Intergraph systems running CLIX. -# It and the defines supporting it in the source tree should be considered -# alpha-quality and used at own risk. -# -# Porting done for CICNet, Inc., on behalf the Michigan State Department -# of Natural Resources. -# -# --Paul Southworth <pauls@cic.net> -# -# @(#)Makefile.CLIX 8.1 (Berkeley) 4/12/94 -# - -# make sure the shell constructs below use the right shell -SHELL= /bin/sh - -# use O=-O (usual) or O=-g (debugging) -O= -O - -CC= gcc - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DCLIX - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= -I/usr/include - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -lnsl -lbsd - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= getusershell.o - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq -BINOWN= root -BINGRP= mail -BINMODE=6555 -INSTALL=cp - -ALL= sendmail # aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail #install-docs - -install-sendmail: sendmail - #${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - ${INSTALL} sendmail ${BINDIR} - chmod ${BINMODE} ${BINDIR}/sendmail - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - #${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - # ${STDIR}/sendmail.st - ${INSTALL} /dev/null ${STDIR}/sendmail.st - #${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - ${INSTALL} sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail #aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.ConvexOS b/usr.sbin/sendmail/src/Makefile.ConvexOS deleted file mode 100644 index 82a77d5..0000000 --- a/usr.sbin/sendmail/src/Makefile.ConvexOS +++ /dev/null @@ -1,105 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on CxOS 11.0 beta 1 and 10.x. -# -# @(#)Makefile.ConvexOS 8.3 (Berkeley) 4/11/94 -# - - -# use O=-O (usual) or O=-g (debugging) -O= -g -tm c1 -D__STDC__ -d non_int_bit_field - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DYPCOMPAT -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -#INCDIRS=-I/usr/sww/include/db - -# library directories -#LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.DGUX b/usr.sbin/sendmail/src/Makefile.DGUX deleted file mode 100644 index d7f63af..0000000 --- a/usr.sbin/sendmail/src/Makefile.DGUX +++ /dev/null @@ -1,101 +0,0 @@ -# -# Tested on DG/UX 5.4.2 by A. Bryan Curnutt <bryan@Stoner.COM>. -# -# @(#)Makefile.DGUX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF=-DDGUX - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/bin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/etc - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= bin -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Dell b/usr.sbin/sendmail/src/Makefile.Dell deleted file mode 100644 index 39bc1e8..0000000 --- a/usr.sbin/sendmail/src/Makefile.Dell +++ /dev/null @@ -1,113 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# Based on a Makefile for Dell SVR4 Issue 2.2 from Kimmo Suominen -# <kim@grendel.lut.fi> -- I haven't tested this myself. It may -# work on other SVR4 ports. -# -# @(#)Makefile.Dell 8.3 (Berkeley) 4/11/94 -# - -# make sure the shell constructs below use the right shell -SHELL= /bin/sh - -# use O=-O (usual) or O=-g (debugging) -O= -O2 - -CC= gcc -#DESTDIR=/usr/local/sendmail - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNEWDB -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -D__svr4__ - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -ldb -ldbm -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/ucblib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/ucblib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/ucblib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= mail -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.DomainOS b/usr.sbin/sendmail/src/Makefile.DomainOS deleted file mode 100644 index 5564ecb..0000000 --- a/usr.sbin/sendmail/src/Makefile.DomainOS +++ /dev/null @@ -1,123 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on DomainOS 10.3.5 -# -# @(#)Makefile.DomainOS 8.5 (Berkeley) 4/12/94 -# -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNDBM -DNEWDB -DYPCOMPAT -- use both plus YP compatility -# -DNIS -- include client NIS support -# The really old (V7) DBM library is no longer supported. -# If YPCOMPAT is defined and /var/yp/Makefile exists, sendmail will build -# both the NEWDB and DBM libraries (the DBM just for YP). -# - -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# loader options -LDOPTS= - -# library directories -LIBDIRS= - -# libraries required on your system -# You might want to use the BIND 4.9 resolver library here -#LIBS= -ldb -ldbm -LIBS= -ldbm -lresolv - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= unistd.h dirent.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. -A nansi $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -unistd.h: - cp /dev/null unistd.h - -dirent.h: - echo "#include <sys/dir.h>" > dirent.h - echo "#define dirent direct" >> dirent.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Dynix b/usr.sbin/sendmail/src/Makefile.Dynix deleted file mode 100644 index 344a9b7..0000000 --- a/usr.sbin/sendmail/src/Makefile.Dynix +++ /dev/null @@ -1,113 +0,0 @@ -# -# Tested on Dynix 3.2.0. -# -# From Jim Davis <jdavis@cs.arizona.edu>. -# -# ``There is no strtol in libc (well there is in the 'att universe' -# libc, but I couldn't figure out how to link that in), so I -# got the Chris Torek strtol.c from bsd-sources on uunet and -# compiled that. There is no native ndbm either; I couldn't -# get db 1.72 to pass it's regression test, so I used gdbm-1.7 -# instead. I compiled it with gcc 1.40a. The -lseq is to pick -# up getopt.'' -# -# @(#)Makefile.Dynix 8.3 (Berkeley) 4/11/94 -# - -CC= gcc - -# use O=-O (usual) or O=-g (debugging) -O= -O -g - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# loader options -LDOPTS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -lseq -lgdbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD=strtol.o - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= staff # no kmem group, -BINMODE=4555 # so not setgid - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.FreeBSD b/usr.sbin/sendmail/src/Makefile.FreeBSD deleted file mode 100644 index 242c805..0000000 --- a/usr.sbin/sendmail/src/Makefile.FreeBSD +++ /dev/null @@ -1,50 +0,0 @@ -# -# Makefile for FreeBSD -# -# @(#)Makefile.FreeBSD 8.1 (Berkeley) 2/26/94 - -PROG= sendmail - -# define the database format to use for aliases et al. Can be -DNEWDB (for -# the new BSD database package -- this is preferred) or -DNDBM for the NDBM -# database package. The old putrescent V7 DBM package is no longer -# supported. -# You can define both NEWDB and NDBM during a transition period; old -# databases are read, but the new format will be used on any rebuilds. On -# really gnarly systems, you can set this to null; it will crawl like a high -# spiral snail, but it will work. -DBMDEF= -DNEWDB - -# FreeBSD 1.0 RELEASE has uname(2) now. Use -DUSEUNAME in order to use it. -CFLAGS+=-I${.CURDIR} ${DBMDEF} -DMIME -DUSEUNAME - -SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ - deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ - util.c version.c -DPADD= -LDADD= $(LIBUTIL) -# -# FreeBSD 1.0 RELEASE has GNU man and doesn't need preformatted man pages anymore -# (assuming you consider a slower "man" command a feature) -# -MAN1= mailq.1 newaliases.1 -MAN5= aliases.5 -MAN8= sendmail.8 -LINKS= /usr/sbin/sendmail /usr/bin/newaliases \ - /usr/sbin/sendmail /usr/bin/mailq -BINDIR= /usr/sbin -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -beforeinstall: -# ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ -# ${DESTDIR}/etc/sendmail.fc - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/log/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \ - ${DESTDIR}/usr/share/misc - -.include <bsd.prog.mk> diff --git a/usr.sbin/sendmail/src/Makefile.HP-UX b/usr.sbin/sendmail/src/Makefile.HP-UX deleted file mode 100644 index c1b51ec..0000000 --- a/usr.sbin/sendmail/src/Makefile.HP-UX +++ /dev/null @@ -1,105 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on HP-UX 8.07 on 7xx series. -# -# @(#)Makefile.HP-UX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -# +O is OK on 7xx, and 300xx at 9.0 -O= +O1 - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldb -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq -BINOWN= root -BINGRP= mail -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - cpset sendmail ${BINDIR} ${BINMODE} ${BINOWN} ${BINGRP} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - cpset /dev/null ${STDIR}/sendmail.st 644 ${BINOWN} ${BINGRP} - cpset sendmail.hf ${HFDIR} 444 ${BINOWN} ${BINGRP} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.IRIX b/usr.sbin/sendmail/src/Makefile.IRIX deleted file mode 100644 index 30e8f1c..0000000 --- a/usr.sbin/sendmail/src/Makefile.IRIX +++ /dev/null @@ -1,109 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on IRIX 4.0.4. -# -# @(#)Makefile.IRIX 8.4 (Berkeley) 4/11/94 -# -SHELL= /bin/sh - -# use O=-O (usual) or O=-g (debugging) -O= -O -CC=gcc - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB (requires -ldb) -# -DNIS -- include NIS support (requires -lsun) -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DIRIX - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -lmld -#LIBS= -lsun -ldb -lmld - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/bsd/newaliases ${DESTDIR}/usr/bsd/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -u ${BINOWN} -g ${BINGRP} -m ${BINMODE} -f ${BINDIR} sendmail - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - cp /dev/null ${STDIR}/sendmail.st - chmod 644 ${STDIR}/sendmail.st - chown ${BINOWN} ${STDIR}/sendmail.st - chgrp ${BINGRP} ${STDIR}/sendmail.st - install -u ${BINOWN} -g ${BINGRP} -m 444 -f ${HFDIR} sendmail.hf - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Linux b/usr.sbin/sendmail/src/Makefile.Linux deleted file mode 100644 index 3c8f3e5..0000000 --- a/usr.sbin/sendmail/src/Makefile.Linux +++ /dev/null @@ -1,120 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Linux 0.99p10. -# -# Linux doesn't really have standard places to install things, so this -# Makefile is likely to require a lot of customization. Read it over -# carefully before proceeding. -# -# @(#)Makefile.Linux 8.7 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/local/include - -# library directories -LIBDIRS=-L/usr/local/lib - -# libraries required on your system -LIBS= -lndbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/sbin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -unistd.h: - cp /dev/null unistd.h - -dirent.h: - echo "#include <sys/dir.h>" > dirent.h - echo "#define dirent direct" >> dirent.h - -NROFF= nroff - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - cp /dev/null ${STDIR}/sendmail.st - chmod 644 ${STDIR}/sendmail.st - chown ${BINOWN} ${STDIR}/sendmail.st - chgrp ${BINGRP} ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Mach386 b/usr.sbin/sendmail/src/Makefile.Mach386 deleted file mode 100644 index eaed6ca..0000000 --- a/usr.sbin/sendmail/src/Makefile.Mach386 +++ /dev/null @@ -1,107 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# @(#)Makefile.Mach386 8.3 (Berkeley) 4/11/94 -# - -CC= gcc - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# loader options -LDOPTS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.NCR3000 b/usr.sbin/sendmail/src/Makefile.NCR3000 deleted file mode 100644 index a556951..0000000 --- a/usr.sbin/sendmail/src/Makefile.NCR3000 +++ /dev/null @@ -1,109 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# NCR 3000 support from Kevin Darcy <kevin@tech.mis.cfc.com>. -# -# @(#)Makefile.NCR3000 8.2 (Berkeley) 4/16/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DNCR3000 - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/ucbinclude - -# loader options -LDOPTS= - -# library directories -LIBDIRS=-L/usr/ucblib - -# libraries required on your system -LIBS= -lsocket -lc -lelf -lucb -ldbm -lnet -lnsl - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/ucblib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/ucblib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/ucblib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -INSTALL=install - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.NeXT b/usr.sbin/sendmail/src/Makefile.NeXT deleted file mode 100644 index de0dc7f..0000000 --- a/usr.sbin/sendmail/src/Makefile.NeXT +++ /dev/null @@ -1,114 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on NeXT 2.1. -# -# @(#)Makefile.NeXT 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DNeXT -DNETINFO - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# library directories -LIBDIRS=-L/usr/local/lib - -# libraries required on your system -LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc/sendmail - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= unistd.h dirent.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -unistd.h: - cp /dev/null unistd.h - -dirent.h: - echo "#include <sys/dir.h>" > dirent.h - echo "#define dirent direct" >> dirent.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.NetBSD b/usr.sbin/sendmail/src/Makefile.NetBSD deleted file mode 100644 index b253c0b..0000000 --- a/usr.sbin/sendmail/src/Makefile.NetBSD +++ /dev/null @@ -1,46 +0,0 @@ -# -# NetBSD Makefile -# -# @(#)Makefile.NetBSD 8.1 (Berkeley) 2/26/94 -# @Id: Makefile.NetBSD,v 1.3 1994/02/01 05:33:44 glass Exp $ -# - -PROG= sendmail - -# define the database format to use for aliases et al. Can be -DNEWDB (for -# the new BSD database package -- this is preferred) or -DNDBM for the NDBM -# database package. The old putrescent V7 DBM package is no longer -# supported. -# You can define both NEWDB and NDBM during a transition period; old -# databases are read, but the new format will be used on any rebuilds. On -# really gnarly systems, you can set this to null; it will crawl like a high -# spiral snail, but it will work. -DBMDEF= -DNEWDB -DNIS - -#nasty warning about gcc 2.4.x caused bugs -CFLAGS=-I${.CURDIR} ${DBMDEF} -DNETISO -#CFLAGS+=-I${.CURDIR} ${DBMDEF} -DNETISO - -SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ - deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ - util.c version.c -MAN1= mailq.0 newaliases.0 -MAN5= aliases.0 -MAN8= sendmail.0 -LINKS= /usr/sbin/sendmail /usr/bin/newaliases \ - /usr/sbin/sendmail /usr/bin/mailq -BINDIR= /usr/sbin -BINOWN= root -BINMODE=4555 - -beforeinstall: -# install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ -# ${DESTDIR}/etc/sendmail.fc - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/log/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \ - ${DESTDIR}/usr/share/misc - -.include <bsd.prog.mk> diff --git a/usr.sbin/sendmail/src/Makefile.OSF1 b/usr.sbin/sendmail/src/Makefile.OSF1 deleted file mode 100644 index c79b2bb..0000000 --- a/usr.sbin/sendmail/src/Makefile.OSF1 +++ /dev/null @@ -1,109 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on OSF/1 1.3 -# -# @(#)Makefile.OSF1 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -Olimit 1000 - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib -L/usr/shlib -L/usr/lib - -# libraries required on your system -LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/sbin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/adm/sendmail - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/share/lib - -# additional .o files needed -OBJADD= - -# additional link flags -#LDADD= -non_shared - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${BINDIR}/newaliases ${BINDIR}/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDADD} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - installbsd -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - cp /dev/null ${STDIR}/sendmail.st - chmod 644 ${STDIR}/sendmail.st - chown ${BINOWN}.${BINGRP} ${STDIR}/sendmail.st - installbsd -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - rm -f /usr/sbin/smtpd - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.PTX b/usr.sbin/sendmail/src/Makefile.PTX deleted file mode 100644 index f27238b..0000000 --- a/usr.sbin/sendmail/src/Makefile.PTX +++ /dev/null @@ -1,114 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# For Sequent DYNIX/ptx. -# -# From Tim "Pinball Wizard" Wright <timw@sequent.com>. -# -# @(#)Makefile.PTX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -g - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -#INCDIRS=-I/usr/sww/include/db -INCDIRS= - -# loader options -LDOPTS= - -# library directories -#LIBDIRS=-L/usr/sww/lib -LIBDIRS= - -# libraries required on your system -#LIBS= -ldb -ldbm -LIBS= -lsocket -linet -lnsl -lseq - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/bin/newaliases ${DESTDIR}/usr/bin/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 - -ALL= sendmail aliases.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: $& ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -INSTALL=install - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.RISCos b/usr.sbin/sendmail/src/Makefile.RISCos deleted file mode 100644 index b4c4b36..0000000 --- a/usr.sbin/sendmail/src/Makefile.RISCos +++ /dev/null @@ -1,117 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# For Mips RISC/os 4.52. -# -# @(#)Makefile.RISCos 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# be sure we are compiling in BSD mode -CC= cc -systype bsd43 - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DRISCOS -Olimit 800 - -# see also conf.h for additional compilation flags - -# include directories -#INCDIRS=-I/usr/sww/include/db - -# library directories -#LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -lmld - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= stdlib.h dirent.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -stdlib.h: - cp /dev/null $@ - -dirent.h: - echo "#include <sys/dir.h>" > dirent.h - echo "#define dirent direct" >> dirent.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SCO b/usr.sbin/sendmail/src/Makefile.SCO deleted file mode 100644 index 0eccdab..0000000 --- a/usr.sbin/sendmail/src/Makefile.SCO +++ /dev/null @@ -1,104 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on SCO. -# -# @(#)Makefile.SCO 8.4 (Berkeley) 4/12/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -D_SCO_unix_ - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -lsocket - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/lib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SVR4 b/usr.sbin/sendmail/src/Makefile.SVR4 deleted file mode 100644 index 92de6dd..0000000 --- a/usr.sbin/sendmail/src/Makefile.SVR4 +++ /dev/null @@ -1,113 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# Based on a Makefile for Dell SVR4 Issue 2.2 from Kimmo Suominen -# <kim@grendel.lut.fi> -- I haven't tested this myself. It may -# work on other SVR4 ports. -# -# @(#)Makefile.SVR4 8.3 (Berkeley) 4/11/94 -# - -# make sure the shell constructs below use the right shell -SHELL= /bin/sh - -# use O=-O (usual) or O=-g (debugging) -O= -O - -CC= gcc -#DESTDIR=/usr/local/sendmail - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNEWDB -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -D__svr4__ - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -ldb -ldbm -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/ucblib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/usr/ucblib - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/ucblib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= mail -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Solaris b/usr.sbin/sendmail/src/Makefile.Solaris deleted file mode 100644 index 8256a3e..0000000 --- a/usr.sbin/sendmail/src/Makefile.Solaris +++ /dev/null @@ -1,115 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Solaris 2.1 and 2.2. -# -# @(#)Makefile.Solaris 8.5 (Berkeley) 4/12/94 -# - -# use O=-O (usual) or O=-g (debugging) -# warning: do not use -O with gcc -O= - -CC= gcc - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNIS - -# environment definitions (e.g., -D_AIX3) -# include -DSOLARIS_2_3 for version 2.3 and higher -ENVDEF= -DSOLARIS - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/etc/mail - -# additional .o files needed -OBJADD= - -# things to be made before compilation begins -BEFORE= sysexits.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -sysexits.h: /usr/ucbinclude/sysexits.h - ln -s /usr/ucbinclude/sysexits.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SunOS b/usr.sbin/sendmail/src/Makefile.SunOS deleted file mode 100644 index ee3025f..0000000 --- a/usr.sbin/sendmail/src/Makefile.SunOS +++ /dev/null @@ -1,111 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on SunOS 4.1.[12]. -# For SunOS 4.0.3, add -DSUNOS403 to the ENVDEF macro, and -# create empty files stdlib.h and stddef.h in your -# compile directory. -# -# @(#)Makefile.SunOS 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB -DNIS - -# environment definitions (e.g., -D_AIX3) -# need to add -DSUNOS403 if you are on a SunOS 4.0.3 system -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= -Bstatic - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldb -ldbm -lresolv - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3 b/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3 deleted file mode 100644 index 126ac64..0000000 --- a/usr.sbin/sendmail/src/Makefile.SunOS.4.0.3 +++ /dev/null @@ -1,113 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# You may find you need to find versions of some routines -# such as strcasecmp in order to link this on SunOS 4.0.3. -# -# @(#)Makefile.SunOS.4.0.3 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DSUNOS403 - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= -Bstatic - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldb -ldbm -lresolv - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/etc - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -BEFORE= stdlib.h stddef.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -stddef.h stdlib.h: - cp /dev/null $@ - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.5.1 b/usr.sbin/sendmail/src/Makefile.SunOS.5.1 deleted file mode 100644 index 8256a3e..0000000 --- a/usr.sbin/sendmail/src/Makefile.SunOS.5.1 +++ /dev/null @@ -1,115 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Solaris 2.1 and 2.2. -# -# @(#)Makefile.Solaris 8.5 (Berkeley) 4/12/94 -# - -# use O=-O (usual) or O=-g (debugging) -# warning: do not use -O with gcc -O= - -CC= gcc - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNIS - -# environment definitions (e.g., -D_AIX3) -# include -DSOLARIS_2_3 for version 2.3 and higher -ENVDEF= -DSOLARIS - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/etc/mail - -# additional .o files needed -OBJADD= - -# things to be made before compilation begins -BEFORE= sysexits.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -sysexits.h: /usr/ucbinclude/sysexits.h - ln -s /usr/ucbinclude/sysexits.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.5.2 b/usr.sbin/sendmail/src/Makefile.SunOS.5.2 deleted file mode 100644 index 8256a3e..0000000 --- a/usr.sbin/sendmail/src/Makefile.SunOS.5.2 +++ /dev/null @@ -1,115 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Solaris 2.1 and 2.2. -# -# @(#)Makefile.Solaris 8.5 (Berkeley) 4/12/94 -# - -# use O=-O (usual) or O=-g (debugging) -# warning: do not use -O with gcc -O= - -CC= gcc - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNIS - -# environment definitions (e.g., -D_AIX3) -# include -DSOLARIS_2_3 for version 2.3 and higher -ENVDEF= -DSOLARIS - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/etc/mail - -# additional .o files needed -OBJADD= - -# things to be made before compilation begins -BEFORE= sysexits.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -sysexits.h: /usr/ucbinclude/sysexits.h - ln -s /usr/ucbinclude/sysexits.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.SunOS.5.x b/usr.sbin/sendmail/src/Makefile.SunOS.5.x deleted file mode 100644 index 1b7d268..0000000 --- a/usr.sbin/sendmail/src/Makefile.SunOS.5.x +++ /dev/null @@ -1,115 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Solaris 2.3. -# -# @(#)Makefile.SunOS.5.x 8.5 (Berkeley) 4/12/94 -# - -# use O=-O (usual) or O=-g (debugging) -# warning: do not use -O with gcc -O= - -CC= gcc - -# define the database mechanism used for alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNIS - -# environment definitions (e.g., -D_AIX3) -# include -DSOLARIS_2_3 for version 2.3 and higher -ENVDEF= -DSOLARIS_2_3 - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -lresolv -lsocket -lnsl -lelf - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/etc/mail - -# additional .o files needed -OBJADD= - -# things to be made before compilation begins -BEFORE= sysexits.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= sys -BINMODE=6555 -INSTALL=/usr/ucb/install - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${OBJS} ${LIBDIRS} ${LIBS} - -sysexits.h: /usr/ucbinclude/sysexits.h - ln -s /usr/ucbinclude/sysexits.h - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Titan b/usr.sbin/sendmail/src/Makefile.Titan deleted file mode 100644 index 89b156a..0000000 --- a/usr.sbin/sendmail/src/Makefile.Titan +++ /dev/null @@ -1,114 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# @(#)Makefile.Titan 8.3 (Berkeley) 4/11/94 -# - -# put the compiler in BSD mode -CC= cc -43 - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# loader options -LDOPTS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/share/misc - -# additional .o files needed -OBJADD= - -# additional pseudo-sources needed -BEFORE= stddef.h stdlib.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -stddef.h stdlib.h: - cp /dev/null $@ - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.ULTRIX b/usr.sbin/sendmail/src/Makefile.ULTRIX deleted file mode 100644 index a3f222e..0000000 --- a/usr.sbin/sendmail/src/Makefile.ULTRIX +++ /dev/null @@ -1,107 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Ultrix 4.2A and 4.3A. -# -# @(#)Makefile.ULTRIX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -Olimit 800 - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldb - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.UMAX b/usr.sbin/sendmail/src/Makefile.UMAX deleted file mode 100644 index c69e2b6..0000000 --- a/usr.sbin/sendmail/src/Makefile.UMAX +++ /dev/null @@ -1,114 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# This has been tested on Encore UMAX V -# -# @(#)Makefile.UMAX 8.3 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNIS - -# environment definitions (e.g., -D_AIX3) -ENVDEF= -DUMAXV - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS= - -# loader options -LDOPTS= - -# library directories -LIBDIRS= - -# libraries required on your system -LIBS= -lyp -lrpc - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/lib - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/lib - -# additional .o files needed -OBJADD= - -# things to do before compilation -BEFORE= stddef.h - -stddef.h: - echo "#define _STDDEF_H" > stddef.h - chmod 444 stddef.h - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -install: install-sendmail install-docs - -install-sendmail: sendmail - install -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/Makefile.Utah b/usr.sbin/sendmail/src/Makefile.Utah deleted file mode 100644 index 84f2403..0000000 --- a/usr.sbin/sendmail/src/Makefile.Utah +++ /dev/null @@ -1,40 +0,0 @@ -# @(#)Makefile.Utah 8.1 (Berkeley) 2/26/94 - -PROG= sendmail - -# define the database format to use for aliases et al. Can be -DNEWDB (for -# the new BSD database package -- this is preferred) or -DNDBM for the NDBM -# database package. The old putrescent V7 DBM package is no longer -# supported. -# You can define both NEWDB and NDBM during a transition period; old -# databases are read, but the new format will be used on any rebuilds. On -# really gnarly systems, you can set this to null; it will crawl like a high -# spiral snail, but it will work. -DBMDEF= -DNEWDB -DNDBM -DOLD_NEWDB - -CFLAGS+=-I${.CURDIR} ${DBMDEF} -Dsetpgid=setpgrp - -SRCS= alias.c arpadate.c clock.c collect.c conf.c convtime.c daemon.c \ - deliver.c domain.c envelope.c err.c headers.c macro.c main.c map.c \ - mci.c parseaddr.c queue.c readcf.c recipient.c savemail.c srvrsmtp.c \ - stab.c stats.c sysexits.c trace.c udb.c usersmtp.c \ - util.c version.c -DPADD= ${LIBDBM} ${LIBCOMPAT} -LDADD= -MAN1= mailq.0 newaliases.0 -MAN5= aliases.0 -MAN8= sendmail.0 -LINKS= ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/newaliases \ - ${DESTDIR}/usr/sbin/sendmail ${DESTDIR}/usr/bin/mailq -BINDIR= /usr/sbin -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -beforeinstall: - install -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${DESTDIR}/var/log/sendmail.st - install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${.CURDIR}/sendmail.hf \ - ${DESTDIR}/usr/share/misc - -.include <bsd.prog.mk> diff --git a/usr.sbin/sendmail/src/Makefile.dist b/usr.sbin/sendmail/src/Makefile.dist deleted file mode 100644 index 5fab596..0000000 --- a/usr.sbin/sendmail/src/Makefile.dist +++ /dev/null @@ -1,107 +0,0 @@ -# -# This Makefile is designed to work on the old "make" program. It does -# not use the obj subdirectory. It also does not install documentation -# automatically -- think of it as a quick start for sites that have the -# old make program (I recommend that you get and port the new make if you -# are going to be doing any signficant work on sendmail). -# -# @(#)Makefile.dist 8.12 (Berkeley) 4/11/94 -# - -# use O=-O (usual) or O=-g (debugging) -O= -O - -# define the database mechanisms available for map & alias lookups: -# -DNDBM -- use new DBM -# -DNEWDB -- use new Berkeley DB -# -DNIS -- include NIS support -# The really old (V7) DBM library is no longer supported. -# See READ_ME for a description of how these flags interact. -# -DBMDEF= -DNDBM -DNEWDB - -# environment definitions (e.g., -D_AIX3) -ENVDEF= - -# see also conf.h for additional compilation flags - -# include directories -INCDIRS=-I/usr/sww/include/db - -# loader options -LDOPTS= - -# library directories -LIBDIRS=-L/usr/sww/lib - -# libraries required on your system -LIBS= -ldb -ldbm - -# location of sendmail binary (usually /usr/sbin or /usr/lib) -BINDIR= ${DESTDIR}/usr/sbin - -# location of sendmail.st file (usually /var/log or /usr/lib) -STDIR= ${DESTDIR}/var/log - -# location of sendmail.hf file (usually /usr/share/misc or /usr/lib) -HFDIR= ${DESTDIR}/usr/share/misc - -# additional .o files needed -OBJADD= - -################### end of user configuration flags ###################### - -CFLAGS= -I. $O ${INCDIRS} ${DBMDEF} ${ENVDEF} - -OBJS= alias.o arpadate.o clock.o collect.o conf.o convtime.o daemon.o \ - deliver.o domain.o envelope.o err.o headers.o macro.o main.o \ - map.o mci.o parseaddr.o queue.o readcf.o recipient.o \ - savemail.o srvrsmtp.o stab.o stats.o sysexits.o \ - trace.o udb.o usersmtp.o util.o version.o ${OBJADD} - -LINKS= ${DESTDIR}/usr/ucb/newaliases ${DESTDIR}/usr/ucb/mailq -BINOWN= root -BINGRP= kmem -BINMODE=6555 - -ALL= sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -all: ${ALL} - -sendmail: ${BEFORE} ${OBJS} - ${CC} -o sendmail ${LDOPTS} ${OBJS} ${LIBDIRS} ${LIBS} - -NROFF= nroff -h - -aliases.0: aliases.5 - ${NROFF} -mandoc aliases.5 > aliases.0 - -mailq.0: mailq.1 - ${NROFF} -mandoc mailq.1 > mailq.0 - -newaliases.0: newaliases.1 - ${NROFF} -mandoc newaliases.1 > newaliases.0 - -sendmail.0: sendmail.8 - ${NROFF} -mandoc sendmail.8 > sendmail.0 - -INSTALL=install - -install: install-sendmail install-docs - -install-sendmail: sendmail - ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} sendmail ${BINDIR} - for i in ${LINKS}; do rm -f $$i; ln -s ${BINDIR}/sendmail $$i; done - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 644 /dev/null \ - ${STDIR}/sendmail.st - ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 sendmail.hf ${HFDIR} - -# doesn't actually install them -- you may want to install pre-nroff versions -install-docs: aliases.0 mailq.0 newaliases.0 sendmail.0 - -clean: - rm -f ${OBJS} sendmail aliases.0 mailq.0 newaliases.0 sendmail.0 - -# dependencies -# gross overkill, and yet still not quite enough.... -${OBJS}: sendmail.h conf.h diff --git a/usr.sbin/sendmail/src/collect.c b/usr.sbin/sendmail/src/collect.c index 29546ce..7e43c5f 100644 --- a/usr.sbin/sendmail/src/collect.c +++ b/usr.sbin/sendmail/src/collect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.14 (Berkeley) 4/18/94"; +static char sccsid[] = "@(#)collect.c 8.49 (Berkeley) 10/29/95"; #endif /* not lint */ # include <errno.h> @@ -47,12 +47,14 @@ static char sccsid[] = "@(#)collect.c 8.14 (Berkeley) 4/18/94"; ** stripped off (after important information is extracted). ** ** Parameters: +** fp -- file to read. ** smtpmode -- if set, we are running SMTP: give an RFC821 ** style message to say we are ready to collect ** input, and never ignore a single dot to mean ** end of message. ** requeueflag -- this message will be requeued later, so ** don't do final processing on it. +** hdrp -- the location to stash the header. ** e -- the current envelope. ** ** Returns: @@ -63,37 +65,77 @@ static char sccsid[] = "@(#)collect.c 8.14 (Berkeley) 4/18/94"; ** The from person may be set. */ -char *CollectErrorMessage; -bool CollectErrno; - -collect(smtpmode, requeueflag, e) +static jmp_buf CtxCollectTimeout; +static void collecttimeout(); +static bool CollectProgress; +static EVENT *CollectTimeout; + +/* values for input state machine */ +#define IS_NORM 0 /* middle of line */ +#define IS_BOL 1 /* beginning of line */ +#define IS_DOT 2 /* read a dot at beginning of line */ +#define IS_DOTCR 3 /* read ".\r" at beginning of line */ +#define IS_CR 4 /* read a carriage return */ + +/* values for message state machine */ +#define MS_UFROM 0 /* reading Unix from line */ +#define MS_HEADER 1 /* reading message header */ +#define MS_BODY 2 /* reading message body */ + +void +collect(fp, smtpmode, requeueflag, hdrp, e) + FILE *fp; bool smtpmode; bool requeueflag; + HDR **hdrp; register ENVELOPE *e; { register FILE *tf; bool ignrdot = smtpmode ? FALSE : IgnrDot; time_t dbto = smtpmode ? TimeOuts.to_datablock : 0; - char buf[MAXLINE], buf2[MAXLINE]; - register char *workbuf, *freebuf; + register char *bp; + int c = '\0'; bool inputerr = FALSE; - extern char *hvalue(); - extern bool isheader(), flusheol(); - - CollectErrorMessage = NULL; - CollectErrno = 0; + bool headeronly; + char *buf; + int buflen; + int istate; + int mstate; + char *pbp; + char peekbuf[8]; + char dfname[20]; + char bufbuf[MAXLINE]; + extern bool isheader(); + extern void eatheader(); + extern void tferror(); + + headeronly = hdrp != NULL; /* ** Create the temp file name and create the file. */ - e->e_df = queuename(e, 'd'); - e->e_df = newstr(e->e_df); - if ((tf = dfopen(e->e_df, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL) + if (!headeronly) { - syserr("Cannot create %s", e->e_df); - NoReturn = TRUE; - finis(); + struct stat stbuf; + + strcpy(dfname, queuename(e, 'd')); + if ((tf = dfopen(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode)) == NULL) + { + syserr("Cannot create %s", dfname); + e->e_flags |= EF_NO_BODY_RETN; + finis(); + } + if (fstat(fileno(tf), &stbuf) < 0) + e->e_dfino = -1; + else + { + e->e_dfdev = stbuf.st_dev; + e->e_dfino = stbuf.st_ino; + } + HasEightBits = FALSE; + e->e_msgsize = 0; + e->e_flags |= EF_HAS_DF; } /* @@ -103,223 +145,296 @@ collect(smtpmode, requeueflag, e) if (smtpmode) message("354 Enter mail, end with \".\" on a line by itself"); - /* set global timer to monitor progress */ - sfgetset(dbto); + if (tTd(30, 2)) + printf("collect\n"); /* - ** Try to read a UNIX-style From line + ** Read the message. + ** + ** This is done using two interleaved state machines. + ** The input state machine is looking for things like + ** hidden dots; the message state machine is handling + ** the larger picture (e.g., header versus body). */ - if (sfgets(buf, MAXLINE, InChannel, dbto, - "initial message read") == NULL) - goto readerr; - fixcrlf(buf, FALSE); -# ifndef NOTUNIX - if (!SaveFrom && strncmp(buf, "From ", 5) == 0) + buf = bp = bufbuf; + buflen = sizeof bufbuf; + pbp = peekbuf; + istate = IS_BOL; + mstate = SaveFrom ? MS_HEADER : MS_UFROM; + CollectProgress = FALSE; + + if (dbto != 0) { - if (!flusheol(buf, InChannel)) - goto readerr; - eatfrom(buf, e); - if (sfgets(buf, MAXLINE, InChannel, dbto, - "message header read") == NULL) + /* handle possible input timeout */ + if (setjmp(CtxCollectTimeout) != 0) + { +#ifdef LOG + syslog(LOG_NOTICE, + "timeout waiting for input from %s during message collect", + CurHostName ? CurHostName : "<local machine>"); +#endif + errno = 0; + usrerr("451 timeout waiting for input during message collect"); goto readerr; - fixcrlf(buf, FALSE); + } + CollectTimeout = setevent(dbto, collecttimeout, dbto); } -# endif /* NOTUNIX */ - /* - ** Copy InChannel to temp file & do message editing. - ** To keep certain mailers from getting confused, - ** and to keep the output clean, lines that look - ** like UNIX "From" lines are deleted in the header. - */ - - workbuf = buf; /* `workbuf' contains a header field */ - freebuf = buf2; /* `freebuf' can be used for read-ahead */ for (;;) { - char *curbuf; - int curbuffree; - register int curbuflen; - char *p; - - /* first, see if the header is over */ - if (!isheader(workbuf)) - { - fixcrlf(workbuf, TRUE); - break; - } - - /* if the line is too long, throw the rest away */ - if (!flusheol(workbuf, InChannel)) - goto readerr; - - /* it's okay to toss '\n' now (flusheol() needed it) */ - fixcrlf(workbuf, TRUE); - - curbuf = workbuf; - curbuflen = strlen(curbuf); - curbuffree = MAXLINE - curbuflen; - p = curbuf + curbuflen; - - /* get the rest of this field */ + if (tTd(30, 35)) + printf("top, istate=%d, mstate=%d\n", istate, mstate); for (;;) { - int clen; - - if (sfgets(freebuf, MAXLINE, InChannel, dbto, - "message header read") == NULL) + if (pbp > peekbuf) + c = *--pbp; + else { - freebuf[0] = '\0'; - break; + while (!feof(fp) && !ferror(fp)) + { + errno = 0; + c = getc(fp); + if (errno != EINTR) + break; + clearerr(fp); + } + CollectProgress = TRUE; + if (TrafficLogFile != NULL && !headeronly) + { + if (istate == IS_BOL) + fprintf(TrafficLogFile, "%05d <<< ", + getpid()); + if (c == EOF) + fprintf(TrafficLogFile, "[EOF]\n"); + else + putc(c, TrafficLogFile); + } + if (c == EOF) + goto readerr; + if (SevenBitInput) + c &= 0x7f; + else + HasEightBits |= bitset(0x80, c); + if (!headeronly) + e->e_msgsize++; } + if (tTd(30, 94)) + printf("istate=%d, c=%c (0x%x)\n", + istate, c, c); + switch (istate) + { + case IS_BOL: + if (c == '.') + { + istate = IS_DOT; + continue; + } + break; - /* is this a continuation line? */ - if (*freebuf != ' ' && *freebuf != '\t') + case IS_DOT: + if (c == '\n' && !ignrdot && + !bitset(EF_NL_NOT_EOL, e->e_flags)) + goto readerr; + else if (c == '\r' && + !bitset(EF_CRLF_NOT_EOL, e->e_flags)) + { + istate = IS_DOTCR; + continue; + } + else if (c != '.' || + (OpMode != MD_SMTP && + OpMode != MD_DAEMON && + OpMode != MD_ARPAFTP)) + { + *pbp++ = c; + c = '.'; + } break; - if (!flusheol(freebuf, InChannel)) - goto readerr; + case IS_DOTCR: + if (c == '\n') + goto readerr; + else + { + /* push back the ".\rx" */ + *pbp++ = c; + *pbp++ = '\r'; + c = '.'; + } + break; - fixcrlf(freebuf, TRUE); - clen = strlen(freebuf) + 1; + case IS_CR: + if (c == '\n') + istate = IS_BOL; + else + { + ungetc(c, fp); + c = '\r'; + istate = IS_NORM; + } + goto bufferchar; + } - /* if insufficient room, dynamically allocate buffer */ - if (clen >= curbuffree) + if (c == '\r' && !bitset(EF_CRLF_NOT_EOL, e->e_flags)) { - /* reallocate buffer */ - int nbuflen = ((p - curbuf) + clen) * 2; - char *nbuf = xalloc(nbuflen); - - p = nbuf + curbuflen; - curbuffree = nbuflen - curbuflen; - bcopy(curbuf, nbuf, curbuflen); - if (curbuf != buf && curbuf != buf2) - free(curbuf); - curbuf = nbuf; + istate = IS_CR; + continue; } - *p++ = '\n'; - bcopy(freebuf, p, clen - 1); - p += clen - 1; - curbuffree -= clen; - curbuflen += clen; - } - *p++ = '\0'; - - e->e_msgsize += curbuflen; - - /* - ** The working buffer now becomes the free buffer, since - ** the free buffer contains a new header field. - ** - ** This is premature, since we still havent called - ** chompheader() to process the field we just created - ** (so the call to chompheader() will use `freebuf'). - ** This convolution is necessary so that if we break out - ** of the loop due to H_EOH, `workbuf' will always be - ** the next unprocessed buffer. - */ + else if (c == '\n' && !bitset(EF_NL_NOT_EOL, e->e_flags)) + istate = IS_BOL; + else + istate = IS_NORM; - { - register char *tmp = workbuf; - workbuf = freebuf; - freebuf = tmp; - } +bufferchar: + if (mstate == MS_BODY) + { + /* just put the character out */ + if (MaxMessageSize <= 0 || + e->e_msgsize <= MaxMessageSize) + putc(c, tf); + continue; + } - /* - ** Snarf header away. - */ + /* header -- buffer up */ + if (bp >= &buf[buflen - 2]) + { + char *obuf; + + if (mstate != MS_HEADER) + break; + + /* out of space for header */ + obuf = buf; + if (buflen < MEMCHUNKSIZE) + buflen *= 2; + else + buflen += MEMCHUNKSIZE; + buf = xalloc(buflen); + bcopy(obuf, buf, bp - obuf); + bp = &buf[bp - obuf]; + if (obuf != bufbuf) + free(obuf); + } + if (c != '\0') + *bp++ = c; + if (istate == IS_BOL) + break; + } + *bp = '\0'; - if (bitset(H_EOH, chompheader(curbuf, FALSE, e))) - break; +nextstate: + if (tTd(30, 35)) + printf("nextstate, istate=%d, mstate=%d, line = \"%s\"\n", + istate, mstate, buf); + switch (mstate) + { + extern int chompheader(); - /* - ** If the buffer was dynamically allocated, free it. - */ + case MS_UFROM: + mstate = MS_HEADER; +#ifndef NOTUNIX + if (strncmp(buf, "From ", 5) == 0) + { + extern void eatfrom(); - if (curbuf != buf && curbuf != buf2) - free(curbuf); - } + bp = buf; + eatfrom(buf, e); + continue; + } +#endif + /* fall through */ - if (tTd(30, 1)) - printf("EOH\n"); + case MS_HEADER: + if (!isheader(buf)) + { + mstate = MS_BODY; + goto nextstate; + } - if (*workbuf == '\0') - { - /* throw away a blank line */ - if (sfgets(buf, MAXLINE, InChannel, dbto, - "message separator read") == NULL) - goto readerr; - } - else if (workbuf == buf2) /* guarantee `buf' contains data */ - (void) strcpy(buf, buf2); + /* check for possible continuation line */ + do + { + clearerr(fp); + errno = 0; + c = getc(fp); + } while (errno == EINTR); + if (c != EOF) + ungetc(c, fp); + if (c == ' ' || c == '\t') + { + /* yep -- defer this */ + continue; + } - /* - ** Collect the body of the message. - */ + /* trim off trailing CRLF or NL */ + if (*--bp != '\n' || *--bp != '\r') + bp++; + *bp = '\0'; + if (bitset(H_EOH, chompheader(buf, FALSE, hdrp, e))) + mstate = MS_BODY; + break; - for (;;) - { - register char *bp = buf; + case MS_BODY: + if (tTd(30, 1)) + printf("EOH\n"); + if (headeronly) + goto readerr; + bp = buf; - fixcrlf(buf, TRUE); + /* toss blank line */ + if ((!bitset(EF_CRLF_NOT_EOL, e->e_flags) && + bp[0] == '\r' && bp[1] == '\n') || + (!bitset(EF_NL_NOT_EOL, e->e_flags) && + bp[0] == '\n')) + { + break; + } - /* check for end-of-message */ - if (!ignrdot && buf[0] == '.' && (buf[1] == '\n' || buf[1] == '\0')) + /* if not a blank separator, write it out */ + if (MaxMessageSize <= 0 || + e->e_msgsize <= MaxMessageSize) + { + while (*bp != '\0') + putc(*bp++, tf); + } break; - - /* check for transparent dot */ - if ((OpMode == MD_SMTP || OpMode == MD_DAEMON) && - bp[0] == '.' && bp[1] == '.') - bp++; - - /* - ** Figure message length, output the line to the temp - ** file, and insert a newline if missing. - */ - - e->e_msgsize += strlen(bp) + 1; - fputs(bp, tf); - fputs("\n", tf); - if (ferror(tf)) - tferror(tf, e); - if (sfgets(buf, MAXLINE, InChannel, dbto, - "message body read") == NULL) - goto readerr; + } + bp = buf; } - if (feof(InChannel) || ferror(InChannel)) - { readerr: + if ((feof(fp) && smtpmode) || ferror(fp)) + { + const char *errmsg = errstring(errno); + if (tTd(30, 1)) - printf("collect: read error\n"); + printf("collect: premature EOM: %s\n", errmsg); +#ifdef LOG + if (LogLevel >= 2) + syslog(LOG_WARNING, "collect: premature EOM: %s", errmsg); +#endif inputerr = TRUE; } /* reset global timer */ - sfgetset((time_t) 0); + clrevent(CollectTimeout); - if (fflush(tf) != 0) - tferror(tf, e); - if (fsync(fileno(tf)) < 0 || fclose(tf) < 0) + if (headeronly) + return; + + if (tf != NULL && + (fflush(tf) != 0 || ferror(tf) || fsync(fileno(tf)) < 0 || + fclose(tf) < 0)) { tferror(tf, e); + flush_errors(TRUE); finis(); } - if (CollectErrorMessage != NULL && Errors <= 0) - { - if (CollectErrno != 0) - { - errno = CollectErrno; - syserr(CollectErrorMessage, e->e_df); - finis(); - } - usrerr(CollectErrorMessage); - } - else if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) + /* An EOF when running SMTP is an error */ + if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON)) { - /* An EOF when running SMTP is an error */ char *host; char *problem; @@ -327,24 +442,28 @@ readerr: if (host == NULL) host = "localhost"; - if (feof(InChannel)) + if (feof(fp)) problem = "unexpected close"; - else if (ferror(InChannel)) + else if (ferror(fp)) problem = "I/O error"; else problem = "read timeout"; # ifdef LOG - if (LogLevel > 0 && feof(InChannel)) + if (LogLevel > 0 && feof(fp)) syslog(LOG_NOTICE, - "collect: %s on connection from %s, sender=%s: %s\n", - problem, host, e->e_from.q_paddr, errstring(errno)); + "collect: %s on connection from %.100s, sender=%s: %s", + problem, host, + shortenstring(e->e_from.q_paddr, 203), + errstring(errno)); # endif - if (feof(InChannel)) + if (feof(fp)) usrerr("451 collect: %s on connection from %s, from=%s", - problem, host, e->e_from.q_paddr); + problem, host, + shortenstring(e->e_from.q_paddr, 203)); else syserr("451 collect: %s on connection from %s, from=%s", - problem, host, e->e_from.q_paddr); + problem, host, + shortenstring(e->e_from.q_paddr, 203)); /* don't return an error indication */ e->e_to = NULL; @@ -364,84 +483,128 @@ readerr: eatheader(e, !requeueflag); + if (GrabTo && e->e_sendqueue == NULL) + usrerr("No recipient addresses found in header"); + /* collect statistics */ if (OpMode != MD_VERIFY) + { + extern void markstats(); + markstats(e, (ADDRESS *) NULL); + } /* ** Add an Apparently-To: line if we have no recipient lines. */ - if (hvalue("to", e) == NULL && hvalue("cc", e) == NULL && - hvalue("bcc", e) == NULL && hvalue("apparently-to", e) == NULL) + if (hvalue("to", e->e_header) != NULL || + hvalue("cc", e->e_header) != NULL || + hvalue("apparently-to", e->e_header) != NULL) { + /* have a valid recipient header -- delete Bcc: headers */ + e->e_flags |= EF_DELETE_BCC; + } + else if (hvalue("bcc", e->e_header) == NULL) + { + /* no valid recipient headers */ register ADDRESS *q; + char *hdr = NULL; + extern void addheader(); /* create an Apparently-To: field */ /* that or reject the message.... */ - for (q = e->e_sendqueue; q != NULL; q = q->q_next) + switch (NoRecipientAction) { - if (q->q_alias != NULL) - continue; - if (tTd(30, 3)) - printf("Adding Apparently-To: %s\n", q->q_paddr); - addheader("Apparently-To", q->q_paddr, e); + case NRA_ADD_APPARENTLY_TO: + hdr = "Apparently-To"; + break; + + case NRA_ADD_TO: + hdr = "To"; + break; + + case NRA_ADD_BCC: + addheader("Bcc", "", &e->e_header); + break; + + case NRA_ADD_TO_UNDISCLOSED: + addheader("To", "undisclosed-recipients:;", &e->e_header); + break; + } + + if (hdr != NULL) + { + for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { + if (q->q_alias != NULL) + continue; + if (tTd(30, 3)) + printf("Adding %s: %s\n", + hdr, q->q_paddr); + addheader(hdr, q->q_paddr, &e->e_header); + } } } /* check for message too large */ if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) { + e->e_status = "5.2.3"; usrerr("552 Message exceeds maximum fixed size (%ld)", MaxMessageSize); +# ifdef LOG + if (LogLevel > 6) + syslog(LOG_NOTICE, "%s: message size (%ld) exceeds maximum (%ld)", + e->e_id, e->e_msgsize, MaxMessageSize); +# endif } - if ((e->e_dfp = fopen(e->e_df, "r")) == NULL) + /* check for illegal 8-bit data */ + if (HasEightBits) + { + e->e_flags |= EF_HAS8BIT; + if (!bitset(MM_PASS8BIT|MM_MIME8BIT, MimeMode)) + { + e->e_status = "5.6.1"; + usrerr("554 Eight bit data not allowed"); + } + } + else + { + /* if it claimed to be 8 bits, well, it lied.... */ + if (e->e_bodytype != NULL && + strcasecmp(e->e_bodytype, "8BITMIME") == 0) + e->e_bodytype = "7BIT"; + } + + if ((e->e_dfp = fopen(dfname, "r")) == NULL) { /* we haven't acked receipt yet, so just chuck this */ - syserr("Cannot reopen %s", e->e_df); + syserr("Cannot reopen %s", dfname); finis(); } } -/* -** FLUSHEOL -- if not at EOL, throw away rest of input line. -** -** Parameters: -** buf -- last line read in (checked for '\n'), -** fp -- file to be read from. -** -** Returns: -** FALSE on error from sfgets(), TRUE otherwise. -** -** Side Effects: -** none. -*/ -bool -flusheol(buf, fp) - char *buf; - FILE *fp; -{ - register char *p = buf; - char junkbuf[MAXLINE]; - while (strchr(p, '\n') == NULL) - { - CollectErrorMessage = "553 header line too long"; - CollectErrno = 0; - if (sfgets(junkbuf, MAXLINE, fp, TimeOuts.to_datablock, - "long line flush") == NULL) - return (FALSE); - p = junkbuf; - } +static void +collecttimeout(timeout) + time_t timeout; +{ + /* if no progress was made, die now */ + if (!CollectProgress) + longjmp(CtxCollectTimeout, 1); - return (TRUE); + /* otherwise reset the timeout */ + CollectTimeout = setevent(timeout, collecttimeout, timeout); + CollectProgress = FALSE; } /* ** TFERROR -- signal error on writing the temporary file. ** ** Parameters: ** tf -- the file pointer for the temporary file. +** e -- the current envelope. ** ** Returns: ** none. @@ -451,21 +614,22 @@ flusheol(buf, fp) ** Arranges for following output to go elsewhere. */ +void tferror(tf, e) FILE *tf; register ENVELOPE *e; { - CollectErrno = errno; + setstat(EX_IOERR); if (errno == ENOSPC) { struct stat st; long avail; long bsize; - NoReturn = TRUE; + e->e_flags |= EF_NO_BODY_RETN; if (fstat(fileno(tf), &st) < 0) st.st_size = 0; - (void) freopen(e->e_df, "w", tf); + (void) freopen(queuename(e, 'd'), "w", tf); if (st.st_size <= 0) fprintf(tf, "\n*** Mail could not be accepted"); else if (sizeof st.st_size > sizeof (long)) @@ -476,7 +640,7 @@ tferror(tf, e) st.st_size); fprintf(tf, "*** at %s due to lack of disk space for temp file.\n", MyHostName); - avail = freespace(QueueDir, &bsize); + avail = freediskspace(QueueDir, &bsize); if (avail > 0) { if (bsize > 1024) @@ -486,12 +650,11 @@ tferror(tf, e) fprintf(tf, "*** Currently, %ld kilobytes are available for mail temp files.\n", avail); } - CollectErrorMessage = "452 Out of disk space for temp file"; + e->e_status = "4.3.1"; + usrerr("452 Out of disk space for temp file"); } else - { - CollectErrorMessage = "cannot write message body to disk (%s)"; - } + syserr("collect: Cannot write tf%s", e->e_id); (void) freopen("/dev/null", "w", tf); } /* @@ -525,6 +688,7 @@ char *MonthList[] = NULL }; +void eatfrom(fm, e) char *fm; register ENVELOPE *e; diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c index de71851..ee47763 100644 --- a/usr.sbin/sendmail/src/conf.c +++ b/usr.sbin/sendmail/src/conf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,15 +33,13 @@ */ #ifndef lint -static char sccsid[] = "@(#)conf.c 8.89.1.3 (Berkeley) 3/7/95"; +static char sccsid[] = "@(#)conf.c 8.243 (Berkeley) 11/20/95"; #endif /* not lint */ # include "sendmail.h" # include "pathnames.h" # include <sys/ioctl.h> # include <sys/param.h> -# include <netdb.h> -# include <pwd.h> /* ** CONF.C -- Sendmail Configuration Tables. @@ -80,44 +78,47 @@ static char sccsid[] = "@(#)conf.c 8.89.1.3 (Berkeley) 3/7/95"; struct hdrinfo HdrInfo[] = { /* originator fields, most to least significant */ - "resent-sender", H_FROM|H_RESENT, - "resent-from", H_FROM|H_RESENT, - "resent-reply-to", H_FROM|H_RESENT, - "sender", H_FROM, - "from", H_FROM, - "reply-to", H_FROM, - "full-name", H_ACHECK, - "return-receipt-to", H_FROM|H_RECEIPTTO, - "errors-to", H_FROM|H_ERRORSTO, + "resent-sender", H_FROM|H_RESENT, + "resent-from", H_FROM|H_RESENT, + "resent-reply-to", H_FROM|H_RESENT, + "sender", H_FROM, + "from", H_FROM, + "reply-to", H_FROM, + "full-name", H_ACHECK, + "return-receipt-to", H_FROM|H_RECEIPTTO, + "errors-to", H_FROM|H_ERRORSTO, /* destination fields */ - "to", H_RCPT, - "resent-to", H_RCPT|H_RESENT, - "cc", H_RCPT, - "resent-cc", H_RCPT|H_RESENT, - "bcc", H_RCPT|H_ACHECK, - "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, - "apparently-to", H_RCPT, + "to", H_RCPT, + "resent-to", H_RCPT|H_RESENT, + "cc", H_RCPT, + "resent-cc", H_RCPT|H_RESENT, + "bcc", H_RCPT|H_BCC, + "resent-bcc", H_RCPT|H_BCC|H_RESENT, + "apparently-to", H_RCPT, /* message identification and control */ - "message-id", 0, - "resent-message-id", H_RESENT, - "message", H_EOH, - "text", H_EOH, + "message-id", 0, + "resent-message-id", H_RESENT, + "message", H_EOH, + "text", H_EOH, /* date fields */ - "date", 0, - "resent-date", H_RESENT, + "date", 0, + "resent-date", H_RESENT, /* trace fields */ - "received", H_TRACE|H_FORCE, - "x400-received", H_TRACE|H_FORCE, - "via", H_TRACE|H_FORCE, - "mail-from", H_TRACE|H_FORCE, + "received", H_TRACE|H_FORCE, + "x400-received", H_TRACE|H_FORCE, + "via", H_TRACE|H_FORCE, + "mail-from", H_TRACE|H_FORCE, /* miscellaneous fields */ - "comments", H_FORCE, - "return-path", H_FORCE|H_ACHECK, + "comments", H_FORCE, + "return-path", H_FORCE|H_ACHECK, + "content-transfer-encoding", H_CTE, + "content-type", H_CTYPE, + "content-length", H_ACHECK, NULL, 0, }; @@ -159,25 +160,6 @@ struct prival PrivacyValues[] = */ int DtableSize = 50; /* max open files; reset in 4.2bsd */ - - -/* -** Following should be config parameters (and probably will be in -** future releases). In the meantime, setting these is considered -** unsupported, and is intentionally undocumented. -*/ - -#ifdef BROKENSMTPPEERS -bool BrokenSmtpPeers = TRUE; /* set if you have broken SMTP peers */ -#else -bool BrokenSmtpPeers = FALSE; /* set if you have broken SMTP peers */ -#endif -#ifdef NOLOOPBACKCHECK -bool CheckLoopBack = FALSE; /* set to check HELO loopback */ -#else -bool CheckLoopBack = TRUE; /* set to check HELO loopback */ -#endif - /* ** SETDEFAULTS -- set default values ** @@ -195,11 +177,24 @@ bool CheckLoopBack = TRUE; /* set to check HELO loopback */ ** default values. */ -#define DAYS * 24 * 60 * 60 +#define MINUTES * 60 +#define HOURS * 60 MINUTES +#define DAYS * 24 HOURS + +#ifndef MAXRULERECURSION +# define MAXRULERECURSION 50 /* max ruleset recursion depth */ +#endif +void setdefaults(e) register ENVELOPE *e; { + int i; + extern void inittimeouts(); + extern void setdefuser(); + extern void setupmaps(); + extern void setupmailers(); + SpaceSub = ' '; /* option B */ QueueLA = 8; /* option x */ RefuseLA = 12; /* option X */ @@ -215,14 +210,29 @@ setdefaults(e) MaxHopCount = 25; /* option h */ e->e_sendmode = SM_FORK; /* option d */ e->e_errormode = EM_PRINT; /* option e */ - SevenBit = FALSE; /* option 7 */ + SevenBitInput = FALSE; /* option 7 */ MaxMciCache = 1; /* option k */ - MciCacheTimeout = 300; /* option K */ + MciCacheTimeout = 5 MINUTES; /* option K */ LogLevel = 9; /* option L */ - settimeouts(NULL); /* option r */ - TimeOuts.to_q_return = 5 DAYS; /* option T */ - TimeOuts.to_q_warning = 0; /* option T */ + inittimeouts(NULL); /* option r */ PrivacyFlags = 0; /* option p */ +#if MIME8TO7 + MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ +#else + MimeMode = MM_PASS8BIT; +#endif + for (i = 0; i < MAXTOCLASS; i++) + { + TimeOuts.to_q_return[i] = 5 DAYS; /* option T */ + TimeOuts.to_q_warning[i] = 0; /* option T */ + } + ServiceSwitchFile = "/etc/service.switch"; + HostsFile = _PATH_HOSTS; + MustQuoteChars = "@,;:\\()[].'"; + MciInfoTimeout = 30 MINUTES; + MaxRuleRecursion = MAXRULERECURSION; + MaxAliasRecursion = 10; + ColonOkInAddr = TRUE; setdefuser(); setupmaps(); setupmailers(); @@ -233,13 +243,14 @@ setdefaults(e) ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) */ +void setdefuser() { struct passwd *defpwent; static char defuserbuf[40]; DefUser = defuserbuf; - if ((defpwent = getpwuid(DefUid)) != NULL) + if ((defpwent = sm_getpwuid(DefUid)) != NULL) strcpy(defuserbuf, defpwent->pw_name); else strcpy(defuserbuf, "nobody"); @@ -248,6 +259,8 @@ setdefuser() ** HOST_MAP_INIT -- initialize host class structures */ +bool host_map_init __P((MAP *map, char *args)); + bool host_map_init(MAP *map, char *args) { @@ -278,14 +291,16 @@ host_map_init(MAP *map, char *args) ** SETUPMAILERS -- initialize default mailers */ +void setupmailers() { char buf[100]; + extern void makemailer(); - strcpy(buf, "prog, P=/bin/sh, F=lsD, A=sh -c $u"); + strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=DNS/RFC822/X-Unix, A=sh -c \201u"); makemailer(buf); - strcpy(buf, "*file*, P=/dev/null, F=lsDFMPEu, A=FILE"); + strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=DNS/RFC822/X-Unix, A=FILE"); makemailer(buf); strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE"); @@ -313,6 +328,7 @@ setupmailers() s->s_mapclass.map_store = store; \ } +void setupmaps() { register STAB *s; @@ -321,6 +337,7 @@ setupmaps() MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE, map_parseargs, hash_map_open, db_map_close, db_map_lookup, db_map_store); + MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, map_parseargs, bt_map_open, db_map_close, db_map_lookup, db_map_store); @@ -334,40 +351,490 @@ setupmaps() #ifdef NIS MAPDEF("nis", NULL, MCF_ALIASOK, - map_parseargs, nis_map_open, nis_map_close, - nis_map_lookup, nis_map_store); + map_parseargs, nis_map_open, null_map_close, + nis_map_lookup, null_map_store); #endif +#ifdef NISPLUS + MAPDEF("nisplus", NULL, MCF_ALIASOK, + map_parseargs, nisplus_map_open, null_map_close, + nisplus_map_lookup, null_map_store); +#endif + +#ifdef HESIOD + MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, + map_parseargs, hes_map_open, null_map_close, + hes_map_lookup, null_map_store); +#endif + +#if NETINFO + MAPDEF("netinfo", NULL, MCF_ALIASOK, + map_parseargs, ni_map_open, null_map_close, + ni_map_lookup, null_map_store); +#endif + +#if 0 + MAPDEF("dns", NULL, 0, + dns_map_init, null_map_open, null_map_close, + dns_map_lookup, null_map_store); +#endif + +#if NAMED_BIND + /* best MX DNS lookup */ + MAPDEF("bestmx", NULL, MCF_OPTFILE, + map_parseargs, null_map_open, null_map_close, + bestmx_map_lookup, null_map_store); +#endif + + MAPDEF("host", NULL, 0, + host_map_init, null_map_open, null_map_close, + host_map_lookup, null_map_store); + + MAPDEF("text", NULL, MCF_ALIASOK, + map_parseargs, text_map_open, null_map_close, + text_map_lookup, null_map_store); + MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, - map_parseargs, stab_map_open, stab_map_close, + map_parseargs, stab_map_open, null_map_close, stab_map_lookup, stab_map_store); MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE, map_parseargs, impl_map_open, impl_map_close, impl_map_lookup, impl_map_store); - /* host DNS lookup */ - MAPDEF("host", NULL, 0, - host_map_init, null_map_open, null_map_close, - host_map_lookup, null_map_store); + /* access to system passwd file */ + MAPDEF("user", NULL, MCF_OPTFILE, + map_parseargs, user_map_open, null_map_close, + user_map_lookup, null_map_store); /* dequote map */ MAPDEF("dequote", NULL, 0, dequote_init, null_map_open, null_map_close, dequote_map, null_map_store); -#if 0 -# ifdef USERDB +#if USERDB /* user database */ - MAPDEF("udb", ".db", 0, - udb_map_parse, null_map_open, null_map_close, + MAPDEF("userdb", ".db", 0, + map_parseargs, null_map_open, null_map_close, udb_map_lookup, null_map_store); -# endif #endif + + /* arbitrary programs */ + MAPDEF("program", NULL, MCF_ALIASOK, + map_parseargs, null_map_open, null_map_close, + prog_map_lookup, null_map_store); + + /* sequenced maps */ + MAPDEF("sequence", NULL, MCF_ALIASOK, + seq_map_parse, null_map_open, null_map_close, + seq_map_lookup, seq_map_store); + + /* switched interface to sequenced maps */ + MAPDEF("switch", NULL, MCF_ALIASOK, + map_parseargs, switch_map_open, null_map_close, + seq_map_lookup, seq_map_store); + + /* null map lookup -- really for internal use only */ + MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE, + map_parseargs, null_map_open, null_map_close, + null_map_lookup, null_map_store); } #undef MAPDEF /* +** INITHOSTMAPS -- initial host-dependent maps +** +** This should act as an interface to any local service switch +** provided by the host operating system. +** +** Parameters: +** none +** +** Returns: +** none +** +** Side Effects: +** Should define maps "host" and "users" as necessary +** for this OS. If they are not defined, they will get +** a default value later. It should check to make sure +** they are not defined first, since it's possible that +** the config file has provided an override. +*/ + +void +inithostmaps() +{ + register int i; + int nmaps; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; + char buf[MAXLINE]; + + /* + ** Set up default hosts maps. + */ + +#if 0 + nmaps = switch_map_find("hosts", maptype, mapreturn); + for (i = 0; i < nmaps; i++) + { + if (strcmp(maptype[i], "files") == 0 && + stab("hosts.files", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts"); + (void) makemapentry(buf); + } +#if NAMED_BIND + else if (strcmp(maptype[i], "dns") == 0 && + stab("hosts.dns", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "hosts.dns dns A"); + (void) makemapentry(buf); + } +#endif +#ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir"); + (void) makemapentry(buf); + } +#endif +#ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("hosts.nis", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname"); + (void) makemapentry(buf); + } +#endif +#if NETINFO + else if (strcmp(maptype[i], "netinfo") == 0) && + stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "hosts.netinfo netinfo -v name /machines"); + (void) makemapentry(buf); + } +#endif + } +#endif + + /* + ** Make sure we have a host map. + */ + + if (stab("host", ST_MAP, ST_FIND) == NULL) + { + /* user didn't initialize: set up host map */ + strcpy(buf, "host host"); +#if NAMED_BIND + if (ConfigLevel >= 2) + strcat(buf, " -a."); +#endif + (void) makemapentry(buf); + } + + /* + ** Set up default aliases maps + */ + + nmaps = switch_map_find("aliases", maptype, mapreturn); + for (i = 0; i < nmaps; i++) + { + if (strcmp(maptype[i], "files") == 0 && + stab("aliases.files", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases.files null"); + (void) makemapentry(buf); + } +#ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir"); + (void) makemapentry(buf); + } +#endif +#ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("aliases.nis", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases.nis nis -d mail.aliases"); + (void) makemapentry(buf); + } +#endif +#ifdef NETINFO + else if (strcmp(maptype[i], "netinfo") == 0 && + stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases.netinfo netinfo /aliases"); + (void) makemapentry(buf); + } +#endif +#ifdef HESIOD + else if (strcmp(maptype[i], "hesiod") == 0 && + stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases.hesiod hesiod aliases"); + (void) makemapentry(buf); + } +#endif + } + if (stab("aliases", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "aliases switch aliases"); + (void) makemapentry(buf); + } + +#if 0 /* "user" map class is a better choice */ + /* + ** Set up default users maps. + */ + + nmaps = switch_map_find("passwd", maptype, mapreturn); + for (i = 0; i < nmaps; i++) + { + if (strcmp(maptype[i], "files") == 0 && + stab("users.files", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd"); + (void) makemapentry(buf); + } +#ifdef NISPLUS + else if (strcmp(maptype[i], "nisplus") == 0 && + stab("users.nisplus", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir"); + (void) makemapentry(buf); + } +#endif +#ifdef NIS + else if (strcmp(maptype[i], "nis") == 0 && + stab("users.nis", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "users.nis nis -m -d passwd.byname"); + (void) makemapentry(buf); + } +#endif +#ifdef HESIOD + else if (strcmp(maptype[i], "hesiod") == 0) && + stab("users.hesiod", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "users.hesiod hesiod"); + (void) makemapentry(buf); + } +#endif + } + if (stab("users", ST_MAP, ST_FIND) == NULL) + { + strcpy(buf, "users switch -m passwd"); + (void) makemapentry(buf); + } +#endif +} +/* +** SWITCH_MAP_FIND -- find the list of types associated with a map +** +** This is the system-dependent interface to the service switch. +** +** Parameters: +** service -- the name of the service of interest. +** maptype -- an out-array of strings containing the types +** of access to use for this service. There can +** be at most MAXMAPSTACK types for a single service. +** mapreturn -- an out-array of return information bitmaps +** for the map. +** +** Returns: +** The number of map types filled in, or -1 for failure. +*/ + +#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) +# define _USE_SUN_NSSWITCH_ +#endif + +#ifdef _USE_SUN_NSSWITCH_ +# include <nsswitch.h> +#endif + +#if defined(ultrix) || (defined(__osf__) && defined(__alpha)) +# define _USE_DEC_SVC_CONF_ +#endif + +#ifdef _USE_DEC_SVC_CONF_ +# include <sys/svcinfo.h> +#endif + +int +switch_map_find(service, maptype, mapreturn) + char *service; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; +{ + register FILE *fp; + int svcno; + static char buf[MAXLINE]; + +#ifdef _USE_SUN_NSSWITCH_ + struct __nsw_switchconfig *nsw_conf; + enum __nsw_parse_err pserr; + struct __nsw_lookup *lk; + int nsw_rc; + static struct __nsw_lookup lkp0 = + { "files", {1, 0, 0, 0}, NULL, NULL }; + static struct __nsw_switchconfig lkp_default = + { 0, "sendmail", 3, &lkp0 }; + + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + + if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL) + lk = lkp_default.lookups; + else + lk = nsw_conf->lookups; + svcno = 0; + while (lk != NULL) + { + maptype[svcno] = lk->service_name; + if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN) + mapreturn[MA_NOTFOUND] |= 1 << svcno; + if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN) + mapreturn[MA_TRYAGAIN] |= 1 << svcno; + if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN) + mapreturn[MA_TRYAGAIN] |= 1 << svcno; + svcno++; + lk = lk->next; + } + return svcno; +#endif + +#ifdef _USE_DEC_SVC_CONF_ + struct svcinfo *svcinfo; + int svc; + + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + + svcinfo = getsvc(); + if (svcinfo == NULL) + goto punt; + if (strcmp(service, "hosts") == 0) + svc = SVC_HOSTS; + else if (strcmp(service, "aliases") == 0) + svc = SVC_ALIASES; + else if (strcmp(service, "passwd") == 0) + svc = SVC_PASSWD; + else + return -1; + for (svcno = 0; svcno < SVC_PATHSIZE; svcno++) + { + switch (svcinfo->svcpath[svc][svcno]) + { + case SVC_LOCAL: + maptype[svcno] = "files"; + break; + + case SVC_YP: + maptype[svcno] = "nis"; + break; + + case SVC_BIND: + maptype[svcno] = "dns"; + break; + +#ifdef SVC_HESIOD + case SVC_HESIOD: + maptype[svcno] = "hesiod"; + break; +#endif + + case SVC_LAST: + return svcno; + } + } + return svcno; +#endif + +#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) + /* + ** Fall-back mechanism. + */ + + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + + svcno = 0; + fp = fopen(ServiceSwitchFile, "r"); + if (fp != NULL) + { + while (fgets(buf, sizeof buf, fp) != NULL) + { + register char *p; + + p = strpbrk(buf, "#\n"); + if (p != NULL) + *p = '\0'; + p = strpbrk(buf, " \t"); + if (p != NULL) + *p++ = '\0'; + if (strcmp(buf, service) != 0) + continue; + + /* got the right service -- extract data */ + do + { + while (isspace(*p)) + p++; + if (*p == '\0') + break; + maptype[svcno++] = p; + p = strpbrk(p, " \t"); + if (p != NULL) + *p++ = '\0'; + } while (p != NULL); + fclose(fp); + return svcno; + } + + /* service was not found -- use compiled in default */ + fclose(fp); + } +#endif + + /* if the service file doesn't work, use an absolute fallback */ + punt: + for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) + mapreturn[svcno] = 0; + svcno = 0; + if (strcmp(service, "aliases") == 0) + { + maptype[svcno++] = "files"; +#ifdef AUTO_NIS_ALIASES +# ifdef NISPLUS + maptype[svcno++] = "nisplus"; +# endif +# ifdef NIS + maptype[svcno++] = "nis"; +# endif +#endif + return svcno; + } + if (strcmp(service, "hosts") == 0) + { +# if NAMED_BIND + maptype[svcno++] = "dns"; +# else +# if defined(sun) && !defined(BSD) && !defined(_USE_SUN_NSSWITCH_) + /* SunOS */ + maptype[svcno++] = "nis"; +# endif +# endif + maptype[svcno++] = "files"; + return svcno; + } + return -1; +} +/* ** USERNAME -- return the user id of the logged in user. ** ** Parameters: @@ -396,7 +863,7 @@ username() myname = getlogin(); if (myname == NULL || myname[0] == '\0') { - pw = getpwuid(RealUid); + pw = sm_getpwuid(RealUid); if (pw != NULL) myname = newstr(pw->pw_name); } @@ -405,10 +872,10 @@ username() uid_t uid = RealUid; myname = newstr(myname); - if ((pw = getpwnam(myname)) == NULL || + if ((pw = sm_getpwnam(myname)) == NULL || (uid != 0 && uid != pw->pw_uid)) { - pw = getpwuid(uid); + pw = sm_getpwuid(uid); if (pw != NULL) myname = newstr(pw->pw_name); } @@ -485,11 +952,14 @@ ttypath() ** forwarding or registration of users. ** ** If the hosts are found to be incompatible, an error -** message should be given using "usrerr" and 0 should -** be returned. +** message should be given using "usrerr" and an EX_ code +** should be returned. You can also set to->q_status to +** a DSN-style status code. ** -** 'NoReturn' can be set to suppress the return-to-sender -** function; this should be done on huge messages. +** EF_NO_BODY_RETN can be set in e->e_flags to suppress the +** body during the return-to-sender function; this should be done +** on huge messages. This bit may already be set by the ESMTP +** protocol. ** ** Parameters: ** to -- the person being sent to. @@ -501,6 +971,7 @@ ttypath() ** none (unless you include the usrerr stuff) */ +int checkcompat(to, e) register ADDRESS *to; register ENVELOPE *e; @@ -519,11 +990,12 @@ checkcompat(to, e) register STAB *s; s = stab("arpa", ST_MAILER, ST_FIND); - if (s != NULL && e->e_from.q_mailer != LocalMailer && + if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 && to->q_mailer == s->s_mailer) { usrerr("553 No ARPA mail through this machine: see your system administration"); - /* NoReturn = TRUE; to supress return copy */ + /* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */ + to->q_status = "5.7.1"; return (EX_UNAVAILABLE); } # endif /* EXAMPLE_CODE */ @@ -540,19 +1012,47 @@ setsignal(sig, handler) int sig; sigfunc_t handler; { -#if defined(SYS5SIGNALS) || defined(BSD4_3) || defined(_AUX_SOURCE) +#if defined(SYS5SIGNALS) || defined(BSD4_3) return signal(sig, handler); #else struct sigaction n, o; bzero(&n, sizeof n); n.sa_handler = handler; +# ifdef SA_RESTART + n.sa_flags = SA_RESTART; +# endif if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; #endif } /* +** RELEASESIGNAL -- release a held signal +** +** Parameters: +** sig -- the signal to release. +** +** Returns: +** 0 on success. +** -1 on failure. +*/ + +int +releasesignal(sig) + int sig; +{ +#ifdef BSD4_3 + return sigsetmask(sigblock(0) & ~(1 << sig)); +#else + sigset_t sset; + + sigemptyset(&sset); + sigaddset(&sset, sig); + return sigprocmask(SIG_UNBLOCK, &sset, NULL); +#endif +} +/* ** HOLDSIGS -- arrange to hold all signals ** ** Parameters: @@ -565,6 +1065,7 @@ setsignal(sig, handler) ** Arranges that signals are held. */ +void holdsigs() { } @@ -583,6 +1084,7 @@ holdsigs() ** Arranges that signals are released. */ +void rlsesigs() { } @@ -597,6 +1099,7 @@ rlsesigs() # include <compat.h> #endif +void init_md(argc, argv) int argc; char **argv; @@ -604,6 +1107,32 @@ init_md(argc, argv) #ifdef _AUX_SOURCE setcompat(getcompat() | COMPAT_BSDPROT); #endif + +#ifdef VENDOR_DEFAULT + VendorCode = VENDOR_DEFAULT; +#else + VendorCode = VENDOR_BERKELEY; +#endif +} +/* +** INIT_VENDOR_MACROS -- vendor-dependent macro initializations +** +** Called once, on startup. +** +** Parameters: +** e -- the global envelope. +** +** Returns: +** none. +** +** Side Effects: +** vendor-dependent. +*/ + +void +init_vendor_macros(e) + register ENVELOPE *e; +{ } /* ** GETLA -- get the current load average @@ -628,15 +1157,36 @@ init_md(argc, argv) #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */ #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */ #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */ +#define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */ +#define LA_DGUX 9 /* special DGUX implementation */ +#define LA_HPUX 10 /* special HPUX implementation */ /* do guesses based on general OS type */ #ifndef LA_TYPE # define LA_TYPE LA_ZERO #endif -#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) +#ifndef FSHIFT +# if defined(unixpc) +# define FSHIFT 5 +# endif -#include <nlist.h> +# if defined(__alpha) || defined(IRIX) +# define FSHIFT 10 +# endif + +# if defined(_AIX3) +# define FSHIFT 16 +# endif +#endif + +#ifndef FSHIFT +# define FSHIFT 8 +#endif + +#ifndef FSCALE +# define FSCALE (1 << FSHIFT) +#endif #ifndef LA_AVENRUN # ifdef SYSTEM5 @@ -646,39 +1196,38 @@ init_md(argc, argv) # endif #endif +/* _PATH_KMEM should be defined in <paths.h> */ +#ifndef _PATH_KMEM +# define _PATH_KMEM "/dev/kmem" +#endif + +#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) + +#include <nlist.h> + +#ifdef IRIX64 +# define nlist nlist64 +#endif + /* _PATH_UNIX should be defined in <paths.h> */ #ifndef _PATH_UNIX # if defined(SYSTEM5) # define _PATH_UNIX "/unix" # else -# define _PATH_UNIX "/kernel" +# define _PATH_UNIX "/vmunix" # endif #endif -struct nlist Nl[] = +#ifdef _AUX_SOURCE +struct nlist Nl[2]; +#else +struct nlist Nl[] = { { LA_AVENRUN }, -#define X_AVENRUN 0 { 0 }, }; - -#ifndef FSHIFT -# if defined(unixpc) -# define FSHIFT 5 -# endif - -# if defined(__alpha) || defined(IRIX) -# define FSHIFT 10 -# endif -#endif - -#ifndef FSHIFT -# define FSHIFT 8 -#endif - -#ifndef FSCALE -# define FSCALE (1 << FSHIFT) #endif +#define X_AVENRUN 0 getla() { @@ -692,12 +1241,12 @@ getla() double avenrun[3]; # endif #endif - extern off_t lseek(); extern int errno; + extern off_t lseek(); if (kmem < 0) { - kmem = open("/dev/kmem", 0, 0); + kmem = open(_PATH_KMEM, 0, 0); if (kmem < 0) { if (tTd(3, 1)) @@ -706,7 +1255,17 @@ getla() return (-1); } (void) fcntl(kmem, F_SETFD, 1); + +#ifdef _AUX_SOURCE + strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN); + Nl[1].n_name[0] = '\0'; +#endif + +#ifdef _AIX3 + if (knlist(Nl, 1, sizeof Nl[0]) < 0) +#else if (nlist(_PATH_UNIX, Nl) < 0) +#endif { if (tTd(3, 1)) printf("getla: nlist(%s): %s\n", _PATH_UNIX, @@ -720,13 +1279,13 @@ getla() _PATH_UNIX, LA_AVENRUN); return (-1); } -#ifdef IRIX - Nl[X_AVENRUN].n_value &= 0x7fffffff; +#ifdef NAMELISTMASK + Nl[X_AVENRUN].n_value &= NAMELISTMASK; #endif } if (tTd(3, 20)) printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value); - if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || + if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) { /* thank you Ian */ @@ -734,7 +1293,7 @@ getla() printf("getla: lseek or read: %s\n", errstring(errno)); return (-1); } -#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) +# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) if (tTd(3, 5)) { printf("getla: avenrun = %d", avenrun[0]); @@ -745,7 +1304,7 @@ getla() if (tTd(3, 1)) printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); -#else +# else /* LA_TYPE == LA_FLOAT */ if (tTd(3, 5)) { printf("getla: avenrun = %g", avenrun[0]); @@ -756,28 +1315,113 @@ getla() if (tTd(3, 1)) printf("getla: %d\n", (int) (avenrun[0] +0.5)); return ((int) (avenrun[0] + 0.5)); -#endif +# endif } -#else -#if LA_TYPE == LA_SUBR +#endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */ + +#if LA_TYPE == LA_READKSYM + +# include <sys/ksym.h> + +getla() +{ + static int kmem = -1; + long avenrun[3]; + extern int errno; + struct mioc_rksym mirk; + + if (kmem < 0) + { + kmem = open("/dev/kmem", 0, 0); + if (kmem < 0) + { + if (tTd(3, 1)) + printf("getla: open(/dev/kmem): %s\n", + errstring(errno)); + return (-1); + } + (void) fcntl(kmem, F_SETFD, 1); + } + mirk.mirk_symname = LA_AVENRUN; + mirk.mirk_buf = avenrun; + mirk.mirk_buflen = sizeof(avenrun); + if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) + { + if (tTd(3, 1)) + printf("getla: ioctl(MIOC_READKSYM) failed: %s\n", + errstring(errno)); + return -1; + } + if (tTd(3, 5)) + { + printf("getla: avenrun = %d", avenrun[0]); + if (tTd(3, 15)) + printf(", %d, %d", avenrun[1], avenrun[2]); + printf("\n"); + } + if (tTd(3, 1)) + printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT); + return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); +} -#ifdef DGUX +#endif /* LA_TYPE == LA_READKSYM */ -#include <sys/dg_sys_info.h> +#if LA_TYPE == LA_DGUX -int getla() +# include <sys/dg_sys_info.h> + +int +getla() { struct dg_sys_info_load_info load_info; dg_sys_info((long *)&load_info, DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); + if (tTd(3, 1)) + printf("getla: %d\n", (int) (load_info.one_minute + 0.5)); + return((int) (load_info.one_minute + 0.5)); } -#else +#endif /* LA_TYPE == LA_DGUX */ + +#if LA_TYPE == LA_HPUX + +/* forward declarations to keep gcc from complaining */ +struct pst_dynamic; +struct pst_status; +struct pst_static; +struct pst_vminfo; +struct pst_diskinfo; +struct pst_processor; +struct pst_lv; +struct pst_swapinfo; + +# include <sys/param.h> +# include <sys/pstat.h> + +int +getla() +{ + struct pst_dynamic pstd; + + if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic), + (size_t) 1, 0) == -1) + return 0; + + if (tTd(3, 1)) + printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); + + return (int) (pstd.psd_avg_1_min + 0.5); +} + +#endif /* LA_TYPE == LA_HPUX */ +#if LA_TYPE == LA_SUBR + +int getla() { double avenrun[3]; @@ -793,8 +1437,8 @@ getla() return ((int) (avenrun[0] + 0.5)); } -#endif /* DGUX */ -#else +#endif /* LA_TYPE == LA_SUBR */ + #if LA_TYPE == LA_MACH /* @@ -828,8 +1472,8 @@ getla() return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; } +#endif /* LA_TYPE == LA_MACH */ -#else #if LA_TYPE == LA_PROCSTR /* @@ -875,7 +1519,9 @@ getla() return ((int) (avenrun + 0.5)); } -#else +#endif /* LA_TYPE == LA_PROCSTR */ + +#if LA_TYPE == LA_ZERO getla() { @@ -884,10 +1530,7 @@ getla() return (0); } -#endif -#endif -#endif -#endif +#endif /* LA_TYPE == LA_ZERO */ /* @@ -915,7 +1558,7 @@ getla() /* Non Apollo stuff removed by Don Lewis 11/15/93 */ #ifndef lint -static char rcsid[] = "@(#)$Id: conf.c,v 1.6 1995/03/10 05:08:13 pst Exp $"; +static char rcsid[] = "@(#)$Id: conf.c,v 1.7 1995/05/30 03:52:08 rgrimes Exp $"; #endif /* !lint */ #ifdef apollo @@ -958,11 +1601,28 @@ shouldqueue(pri, ctime) long pri; time_t ctime; { + bool rval; + + if (tTd(3, 30)) + printf("shouldqueue: CurrentLA=%d, pri=%d: ", CurrentLA, pri); if (CurrentLA < QueueLA) + { + if (tTd(3, 30)) + printf("FALSE (CurrentLA < QueueLA)\n"); return (FALSE); - if (CurrentLA >= RefuseLA) + } +#if 0 /* this code is reported to cause oscillation around RefuseLA */ + if (CurrentLA >= RefuseLA && QueueLA < RefuseLA) + { + if (tTd(3, 30)) + printf("TRUE (CurrentLA >= RefuseLA)\n"); return (TRUE); - return (pri > (QueueFactor / (CurrentLA - QueueLA + 1))); + } +#endif + rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); + if (tTd(3, 30)) + printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE"); + return rval; } /* ** REFUSECONNECTIONS -- decide if connections should be refused @@ -976,19 +1636,38 @@ shouldqueue(pri, ctime) ** FALSE if we should accept new work. ** ** Side Effects: -** none. +** Sets process title when it is rejecting connections. */ bool refuseconnections() { + extern bool enoughdiskspace(); + extern void setproctitle __P((const char *, ...)); + #ifdef XLA if (!xla_smtp_ok()) return TRUE; #endif - /* this is probably too simplistic */ - return (CurrentLA >= RefuseLA); + if (CurrentLA >= RefuseLA) + { + setproctitle("rejecting connections: load average: %d", + CurrentLA); + } + else if (!enoughdiskspace(MinBlocksFree + 1)) + { + setproctitle("rejecting connections: min free: %d", + MinBlocksFree); + } + else if (MaxChildren > 0 && CurChildren >= MaxChildren) + { + setproctitle("rejecting connections: maximum children: %d", + CurChildren); + } + else + return FALSE; + return TRUE; } /* ** SETPROCTITLE -- set process title for ps @@ -1005,58 +1684,139 @@ refuseconnections() ** display the title. */ -#ifdef SETPROCTITLE -# ifdef HASSETPROCTITLE - *** ERROR *** Cannot have both SETPROCTITLE and HASSETPROCTITLE defined -# endif -# ifdef __hpux +#define SPT_NONE 0 /* don't use it at all */ +#define SPT_REUSEARGV 1 /* cover argv with title information */ +#define SPT_BUILTIN 2 /* use libc builtin */ +#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ +#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ +#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ +#define SPT_SCO 6 /* write kernel u. area */ + +#ifndef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +#endif + +#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN + +# if SPT_TYPE == SPT_PSTAT # include <sys/pstat.h> # endif -# ifdef BSD4_4 +# if SPT_TYPE == SPT_PSSTRINGS # include <machine/vmparam.h> # include <sys/exec.h> -# ifdef __bsdi__ -# undef PS_STRINGS /* BSDI 1.0 doesn't do PS_STRINGS as we expect */ -# define PROCTITLEPAD '\0' -# endif # ifdef __FreeBSD__ # undef PS_STRINGS /* XXX This is broken due to needing<machine/pmap.h> */ # define PROCTITLEPAD '\0' # endif -# ifdef PS_STRINGS -# define SETPROC_STATIC static +# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ +# undef SPT_TYPE +# define SPT_TYPE SPT_REUSEARGV +# else +# ifndef NKPDE /* FreeBSD 2.0 */ +# define NKPDE 63 +typedef unsigned int *pt_entry_t; +# endif # endif # endif -# ifndef SETPROC_STATIC + +# if SPT_TYPE == SPT_PSSTRINGS +# define SETPROC_STATIC static +# else # define SETPROC_STATIC # endif -#endif -#ifndef PROCTITLEPAD -# define PROCTITLEPAD ' ' -#endif +# if SPT_TYPE == SPT_SYSMIPS +# include <sys/sysmips.h> +# include <sys/sysnews.h> +# endif + +# if SPT_TYPE == SPT_SCO +# include <sys/immu.h> +# include <sys/dir.h> +# include <sys/user.h> +# include <sys/fs/s5param.h> +# if PSARGSZ > MAXLINE +# define SPT_BUFSIZE PSARGSZ +# endif +# endif + +# ifndef SPT_PADCHAR +# define SPT_PADCHAR ' ' +# endif + +# ifndef SPT_BUFSIZE +# define SPT_BUFSIZE MAXLINE +# endif + +#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ + +/* +** Pointers for setproctitle. +** This allows "ps" listings to give more useful information. +*/ + +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ + +void +initsetproctitle(argc, argv, envp) + int argc; + char **argv; + char **envp; +{ + register int i; + extern char **environ; + + /* + ** Move the environment so setproctitle can use the space at + ** the top of memory. + */ + + for (i = 0; envp[i] != NULL; i++) + continue; + environ = (char **) xalloc(sizeof (char *) * (i + 1)); + for (i = 0; envp[i] != NULL; i++) + environ[i] = newstr(envp[i]); + environ[i] = NULL; + + /* + ** Save start and extent of argv for setproctitle. + */ + + Argv = argv; + if (i > 0) + LastArgv = envp[i - 1] + strlen(envp[i - 1]); + else + LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); +} + +#if SPT_TYPE != SPT_BUILTIN -#ifndef HASSETPROCTITLE /*VARARGS1*/ -#ifdef __STDC__ -setproctitle(char *fmt, ...) -#else +void +# ifdef __STDC__ +setproctitle(const char *fmt, ...) +# else setproctitle(fmt, va_alist) - char *fmt; + const char *fmt; va_dcl -#endif +# endif { -# ifdef SETPROCTITLE +# if SPT_TYPE != SPT_NONE register char *p; register int i; - SETPROC_STATIC char buf[MAXLINE]; + SETPROC_STATIC char buf[SPT_BUFSIZE]; VA_LOCAL_DECL -# ifdef __hpux +# if SPT_TYPE == SPT_PSTAT union pstun pst; # endif - extern char **Argv; - extern char *LastArgv; +# if SPT_TYPE == SPT_SCO + off_t seek_off; + static int kmem = -1; + static int kmempid = -1; + struct user u; +# endif p = buf; @@ -1066,19 +1826,39 @@ setproctitle(fmt, va_alist) /* print the argument string */ VA_START(fmt); - (void) vsprintf(p, fmt, ap); + (void) vsnprintf(p, sizeof buf - (p - buf), fmt, ap); VA_END; i = strlen(buf); -# ifdef __hpux +# if SPT_TYPE == SPT_PSTAT pst.pst_command = buf; pstat(PSTAT_SETCMD, pst, i, 0, 0); -# else -# ifdef PS_STRINGS +# endif +# if SPT_TYPE == SPT_PSSTRINGS PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = buf; -# else +# endif +# if SPT_TYPE == SPT_SYSMIPS + sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); +# endif +# if SPT_TYPE == SPT_SCO + if (kmem < 0 || kmempid != getpid()) + { + if (kmem >= 0) + close(kmem); + kmem = open(_PATH_KMEM, O_RDWR, 0); + if (kmem < 0) + return; + (void) fcntl(kmem, F_SETFD, 1); + kmempid = getpid(); + } + buf[PSARGSZ - 1] = '\0'; + seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; + if (lseek(kmem, (char *) seek_off, SEEK_SET) == seek_off) + (void) write(kmem, buf, PSARGSZ); +# endif +# if SPT_TYPE == SPT_REUSEARGV if (i > LastArgv - Argv[0] - 2) { i = LastArgv - Argv[0] - 2; @@ -1087,18 +1867,18 @@ setproctitle(fmt, va_alist) (void) strcpy(Argv[0], buf); p = &Argv[0][i]; while (p < LastArgv) - *p++ = PROCTITLEPAD; -# endif + *p++ = SPT_PADCHAR; + Argv[1] = NULL; # endif -# endif /* SETPROCTITLE */ +# endif /* SPT_TYPE != SPT_NONE */ } -#endif +#endif /* SPT_TYPE != SPT_BUILTIN */ /* ** REAPCHILD -- pick up the body of my child, lest it become a zombie ** ** Parameters: -** none. +** sig -- the signal that got us here (unused). ** ** Returns: ** none. @@ -1108,7 +1888,8 @@ setproctitle(fmt, va_alist) */ void -reapchild() +reapchild(sig) + int sig; { int olderrno = errno; # ifdef HASWAITPID @@ -1127,18 +1908,19 @@ reapchild() #endif break; } + CurChildren--; } # else # ifdef WNOHANG union wait status; while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) - continue; + CurChildren--; # else /* WNOHANG */ auto int status; while (wait(&status) > 0) - continue; + CurChildren--; # endif /* WNOHANG */ # endif # ifdef SYS5SIGNALS @@ -1147,6 +1929,107 @@ reapchild() errno = olderrno; } /* +** PUTENV -- emulation of putenv() in terms of setenv() +** +** Not needed on Posix-compliant systems. +** This doesn't have full Posix semantics, but it's good enough +** for sendmail. +** +** Parameter: +** env -- the environment to put. +** +** Returns: +** none. +*/ + +#ifdef NEEDPUTENV + +# if NEEDPUTENV == 2 /* no setenv(3) call available */ + +int +putenv(str) + char *str; +{ + char **current; + int matchlen, envlen=0; + char *tmp; + char **newenv; + static int first=1; + extern char **environ; + + /* + * find out how much of str to match when searching + * for a string to replace. + */ + if ((tmp = index(str, '=')) == NULL || tmp == str) + matchlen = strlen(str); + else + matchlen = (int) (tmp - str); + ++matchlen; + + /* + * Search for an existing string in the environment and find the + * length of environ. If found, replace and exit. + */ + for (current=environ; *current; current++) { + ++envlen; + + if (strncmp(str, *current, matchlen) == 0) { + /* found it, now insert the new version */ + *current = (char *)str; + return(0); + } + } + + /* + * There wasn't already a slot so add space for a new slot. + * If this is our first time through, use malloc(), else realloc(). + */ + if (first) { + newenv = (char **) malloc(sizeof(char *) * (envlen + 2)); + if (newenv == NULL) + return(-1); + + first=0; + (void) memcpy(newenv, environ, sizeof(char *) * envlen); + } else { + newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2)); + if (newenv == NULL) + return(-1); + } + + /* actually add in the new entry */ + environ = newenv; + environ[envlen] = (char *)str; + environ[envlen+1] = NULL; + + return(0); +} + +#else /* implement putenv() in terms of setenv() */ + +int +putenv(env) + char *env; +{ + char *p; + int l; + char nbuf[100]; + + p = strchr(env, '='); + if (p == NULL) + return 0; + l = p - env; + if (l > sizeof nbuf - 1) + l = sizeof nbuf - 1; + bcopy(env, nbuf, l); + nbuf[l] = '\0'; + return setenv(nbuf, ++p, 1); +} + +# endif +#endif +/* ** UNSETENV -- remove a variable from the environment ** ** Not needed on newer systems. @@ -1353,10 +2236,11 @@ fsync(fd) ** DGUX_INET_ADDR -- inet_addr for DG/UX ** ** Data General DG/UX version of inet_addr returns a struct in_addr -** instead of a long. This patches things. +** instead of a long. This patches things. Only needed on versions +** prior to 5.4.3. */ -#ifdef DGUX +#ifdef DGUX_5_4_2 #undef inet_addr @@ -1399,13 +2283,14 @@ static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86"; * get option letter from argument vector */ #ifdef _CONVEX_SOURCE -extern int optind, opterr; +extern int optind, opterr, optopt; +extern char *optarg; #else int opterr = 1; /* if error message should be printed */ int optind = 1; /* index into parent argv vector */ -#endif int optopt = 0; /* character checked for validity */ char *optarg = NULL; /* argument associated with option */ +#endif #define BADCH (int)'?' #define EMSG "" @@ -1467,12 +2352,12 @@ getopt(nargc,nargv,ostr) #define MAXARG 16 vfprintf(fp, fmt, ap) - FILE * fp; - char * fmt; - char ** ap; + FILE *fp; + char *fmt; + char **ap; { - char * bp[MAXARG]; - int i = 0; + char *bp[MAXARG]; + int i = 0; while (*ap && i < MAXARG) bp[i++] = *ap++; @@ -1483,12 +2368,12 @@ vfprintf(fp, fmt, ap) } vsprintf(s, fmt, ap) - char * s; - char * fmt; - char ** ap; + char *s; + char *fmt; + char **ap; { - char * bp[MAXARG]; - int i = 0; + char *bp[MAXARG]; + int i = 0; while (*ap && i < MAXARG) bp[i++] = *ap++; @@ -1500,9 +2385,60 @@ vsprintf(s, fmt, ap) #endif /* +** SNPRINTF, VSNPRINT -- counted versions of printf +** +** These are at best crude emulations. +*/ + +#if !HASSNPRINTF + +void +# ifdef __STDC__ +snprintf(char *buf, size_t bufsize, const char *fmt, ...) +# else +snprintf(buf, bufsize, fmt, va_alist) + char *buf; + size_t bufsize; + const char *fmt; + va_dcl +# endif +{ + VA_LOCAL_DECL + + VA_START(fmt); + vsprintf(buf, fmt, ap); + VA_END; +# if defined(XDEBUG) && defined(LOG) + if (strlen(buf) > bufsize) + syslog(LOG_ALERT, "INTERNAL ERROR: snprintf overflow: %s", + shortenstring(buf, 200)); +# endif +} + + +#ifndef luna2 +void +vsnprintf(buf, bufsize, fmt, ap) + char *buf; + size_t bufsize; + const char *fmt; + va_list ap; +{ + vsprintf(buf, fmt, ap); +# if defined(XDEBUG) && defined(LOG) + if (strlen(buf) > bufsize) + syslog(LOG_ALERT, "INTERNAL ERROR: vsnprintf overflow: %s", + shortenstring(buf, 200)); +# endif +} +#endif + +#endif +/* ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use ** ** Parameters: +** user -- the name of the user we are checking. ** shell -- the user's shell from /etc/passwd ** ** Returns: @@ -1516,19 +2452,45 @@ vsprintf(s, fmt, ap) # define _PATH_SHELLS "/etc/shells" # endif +# ifdef _AIX3 +# include <userconf.h> +# include <usersec.h> +# endif + char *DefaultUserShells[] = { - "/bin/sh", + "/bin/sh", /* standard shell */ "/usr/bin/sh", - "/bin/csh", + "/bin/csh", /* C shell */ "/usr/bin/csh", #ifdef __hpux - "/bin/rsh", - "/bin/ksh", - "/bin/rksh", +# ifdef V4FS + "/usr/bin/rsh", /* restricted Bourne shell */ + "/usr/bin/ksh", /* Korn shell */ + "/usr/bin/rksh", /* restricted Korn shell */ + "/usr/bin/pam", + "/usr/bin/keysh", /* key shell (extended Korn shell) */ + "/usr/bin/posix/sh", +# else + "/bin/rsh", /* restricted Bourne shell */ + "/bin/ksh", /* Korn shell */ + "/bin/rksh", /* restricted Korn shell */ "/bin/pam", - "/usr/bin/keysh", + "/usr/bin/keysh", /* key shell (extended Korn shell) */ "/bin/posix/sh", +# endif +#endif +#ifdef _AIX3 + "/bin/ksh", /* Korn shell */ + "/usr/bin/ksh", + "/bin/tsh", /* trusted shell */ + "/usr/bin/tsh", + "/bin/bsh", /* Bourne shell */ + "/usr/bin/bsh", +#endif +#ifdef __svr4__ + "/bin/ksh", /* Korn shell */ + "/usr/bin/ksh", #endif NULL }; @@ -1538,14 +2500,16 @@ char *DefaultUserShells[] = #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/" bool -usershellok(shell) +usershellok(user, shell) + char *user; char *shell; { #if HASGETUSERSHELL register char *p; extern char *getusershell(); - if (shell == NULL || shell[0] == '\0') + if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || + ConfigLevel <= 1) return TRUE; setusershell(); @@ -1555,12 +2519,41 @@ usershellok(shell) endusershell(); return p != NULL; #else +# if USEGETCONFATTR + auto char *v; +# endif register FILE *shellf; char buf[MAXLINE]; - if (shell == NULL || shell[0] == '\0') + if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't')) return TRUE; +# if USEGETCONFATTR + /* + ** Naturally IBM has a "better" idea..... + ** + ** What a crock. This interface isn't documented, it is + ** considered part of the security library (-ls), and it + ** only works if you are running as root (since the list + ** of valid shells is obviously a source of great concern). + ** I recommend that you do NOT define USEGETCONFATTR, + ** especially since you are going to have to set up an + ** /etc/shells anyhow to handle the cases where getconfattr + ** fails. + */ + + if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL) + { + while (*v != '\0') + { + if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0) + return TRUE; + v += strlen(v) + 1; + } + return FALSE; + } +# endif + shellf = fopen(_PATH_SHELLS, "r"); if (shellf == NULL) { @@ -1599,7 +2592,7 @@ usershellok(shell) #endif } /* -** FREESPACE -- see how much free space is on the queue filesystem +** FREEDISKSPACE -- see how much free space is on the queue filesystem ** ** Only implemented if you have statfs. ** @@ -1646,7 +2639,7 @@ usershellok(shell) #endif long -freespace(dir, bsize) +freediskspace(dir, bsize) char *dir; long *bsize; { @@ -1655,26 +2648,25 @@ freespace(dir, bsize) struct ustat fs; struct stat statbuf; # define FSBLOCKSIZE DEV_BSIZE -# define f_bavail f_tfree +# define SFS_BAVAIL f_tfree # else # if defined(ultrix) struct fs_data fs; -# define f_bavail fd_bfreen -# define FSBLOCKSIZE fs.fd_bsize +# define SFS_BAVAIL fd_bfreen +# define FSBLOCKSIZE 1024L # else # if SFS_TYPE == SFS_STATVFS struct statvfs fs; -# define FSBLOCKSIZE fs.f_bsize +# define FSBLOCKSIZE fs.f_frsize # else struct statfs fs; # define FSBLOCKSIZE fs.f_bsize -# if defined(_SCO_unix_) || defined(IRIX) || defined(apollo) -# define f_bavail f_bfree -# endif # endif # endif # endif - extern int errno; +# ifndef SFS_BAVAIL +# define SFS_BAVAIL f_bavail +# endif # if SFS_TYPE == SFS_USTAT if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) @@ -1682,23 +2674,30 @@ freespace(dir, bsize) # if SFS_TYPE == SFS_4ARGS if (statfs(dir, &fs, sizeof fs, 0) == 0) # else -# if defined(ultrix) - if (statfs(dir, &fs) > 0) +# if SFS_TYPE == SFS_STATVFS + if (statvfs(dir, &fs) == 0) # else +# if defined(ultrix) + if (statfs(dir, &fs) > 0) +# else if (statfs(dir, &fs) == 0) +# endif # endif # endif # endif { if (bsize != NULL) *bsize = FSBLOCKSIZE; - return (fs.f_bavail); + if (fs.SFS_BAVAIL < 0) + return 0; + else + return fs.SFS_BAVAIL; } #endif return (-1); } /* -** ENOUGHSPACE -- check to see if there is enough free space on the queue fs +** ENOUGHDISKSPACE -- is there enough free space on the queue fs? ** ** Only implemented if you have statfs. ** @@ -1713,7 +2712,7 @@ freespace(dir, bsize) */ bool -enoughspace(msize) +enoughdiskspace(msize) long msize; { long bfree, bsize; @@ -1721,14 +2720,14 @@ enoughspace(msize) if (MinBlocksFree <= 0 && msize <= 0) { if (tTd(4, 80)) - printf("enoughspace: no threshold\n"); + printf("enoughdiskspace: no threshold\n"); return TRUE; } - if ((bfree = freespace(QueueDir, &bsize)) >= 0) + if ((bfree = freediskspace(QueueDir, &bsize)) >= 0) { if (tTd(4, 80)) - printf("enoughspace: bavail=%ld, need=%ld\n", + printf("enoughdiskspace: bavail=%ld, need=%ld\n", bfree, msize); /* convert msize to block count */ @@ -1742,14 +2741,16 @@ enoughspace(msize) if (LogLevel > 0) syslog(LOG_ALERT, "%s: low on space (have %ld, %s needs %ld in %s)", - CurEnv->e_id, bfree, - CurHostName, msize, QueueDir); + CurEnv->e_id == NULL ? "[NOQUEUE]" : CurEnv->e_id, + bfree, + CurHostName == NULL ? "SMTP-DAEMON" : CurHostName, + msize, QueueDir); #endif return FALSE; } } else if (tTd(4, 80)) - printf("enoughspace failure: min=%ld, need=%ld: %s\n", + printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n", MinBlocksFree, msize, errstring(errno)); return TRUE; } @@ -1850,6 +2851,7 @@ transienterror(err) #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) case ENOSR: /* Out of streams resources */ #endif + case EOPENTIMEOUT: /* PSEUDO: open timed out */ return TRUE; } @@ -2011,7 +3013,7 @@ chownsafe(fd) rval = fchown(tfd, DefUid, DefGid) != 0; close(tfd); unlink(s); - setreuid(o_uid, o_euid); + setresuid(o_uid, o_euid, -1); setresgid(o_gid, o_egid, -1); return rval; #else @@ -2023,18 +3025,62 @@ chownsafe(fd) # endif # else # ifdef _PC_CHOWN_RESTRICTED - return fpathconf(fd, _PC_CHOWN_RESTRICTED) > 0; -# else -# ifdef BSD + int rval; + + /* + ** Some systems (e.g., SunOS) seem to have the call and the + ** #define _PC_CHOWN_RESTRICTED, but don't actually implement + ** the call. This heuristic checks for that. + */ + + errno = 0; + rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); + if (errno == 0) + return rval > 0; +# endif +# ifdef BSD return TRUE; -# else +# else return FALSE; -# endif # endif # endif #endif } /* +** RESETLIMITS -- reset system controlled resource limits +** +** This is to avoid denial-of-service attacks +** +** Parameters: +** none +** +** Returns: +** none +*/ + +#if HASSETRLIMIT +# ifdef apollo +# include <sys/time.h> +# endif +# include <sys/resource.h> +#endif + +void +resetlimits() +{ +#if HASSETRLIMIT + struct rlimit lim; + + lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; + (void) setrlimit(RLIMIT_CPU, &lim); + (void) setrlimit(RLIMIT_FSIZE, &lim); +#else +# if HASULIMIT + (void) ulimit(2, 0x3fffff); +# endif +#endif +} +/* ** GETCFNAME -- return the name of the .cf file. ** ** Some systems (e.g., NeXT) determine this dynamically. @@ -2043,18 +3089,21 @@ chownsafe(fd) char * getcfname() { + if (ConfFile != NULL) return ConfFile; -#ifdef NETINFO +#if NETINFO { extern char *ni_propval(); char *cflocation; - cflocation = ni_propval("/locations/sendmail", "sendmail.cf"); + cflocation = ni_propval("/locations", NULL, "sendmail", + "sendmail.cf", '\0'); if (cflocation != NULL) return cflocation; } #endif + return _PATH_SENDMAILCF; } /* @@ -2079,13 +3128,49 @@ setvendor(vendor) char *vendor; { if (strcasecmp(vendor, "Berkeley") == 0) + { + VendorCode = VENDOR_BERKELEY; return TRUE; + } /* add vendor extensions here */ +#ifdef SUN_EXTENSIONS + if (strcasecmp(vendor, "Sun") == 0) + { + VendorCode = VENDOR_SUN; + return TRUE; + } +#endif + return FALSE; } /* +** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults +** +** Vendor_pre_defaults is called before reading the configuration +** file; vendor_post_defaults is called immediately after. +** +** Parameters: +** e -- the global environment to initialize. +** +** Returns: +** none. +*/ + +void +vendor_pre_defaults(e) + ENVELOPE *e; +{ +} + + +void +vendor_post_defaults(e) + ENVELOPE *e; +{ +} +/* ** STRTOL -- convert string to long integer ** ** For systems that don't have it in the C library. @@ -2191,40 +3276,127 @@ strtol(nptr, endptr, base) #endif /* -** SOLARIS_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX +** STRSTR -- find first substring in string +** +** Parameters: +** big -- the big (full) string. +** little -- the little (sub) string. ** -** Solaris versions prior through 2.3 don't properly deliver a -** canonical h_name field. This tries to work around it. +** Returns: +** A pointer to the first instance of little in big. +** big if little is the null string. +** NULL if little is not contained in big. */ -#ifdef SOLARIS +#ifdef NEEDSTRSTR + +char * +strstr(big, little) + char *big; + char *little; +{ + register char *p = big; + int l; -extern int h_errno; + if (*little == '\0') + return big; + l = strlen(little); + + while ((p = strchr(p, *little)) != NULL) + { + if (strncmp(p, little, l) == 0) + return p; + p++; + } + return NULL; +} + +#endif +/* +** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX +** +** Some operating systems have wierd problems with the gethostbyXXX +** routines. For example, Solaris versions at least through 2.3 +** don't properly deliver a canonical h_name field. This tries to +** work around these problems. +*/ struct hostent * -solaris_gethostbyname(name) - const char *name; +sm_gethostbyname(name) + char *name; { -# ifdef SOLARIS_2_3 + struct hostent *h; +#if defined(SOLARIS) && SOLARIS < 204 || defined(sony_news) && defined(__svr4) +# if SOLARIS == 203 static struct hostent hp; static char buf[1000]; extern struct hostent *_switch_gethostbyname_r(); - return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); + if (tTd(61, 10)) + printf("_switch_gethostbyname_r(%s)... ", name); + h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); # else extern struct hostent *__switch_gethostbyname(); - return __switch_gethostbyname(name); + if (tTd(61, 10)) + printf("__switch_gethostbyname(%s)... ", name); + h = __switch_gethostbyname(name); # endif +#else + int nmaps; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; + char hbuf[MAXNAME]; + + if (tTd(61, 10)) + printf("gethostbyname(%s)... ", name); + h = gethostbyname(name); + if (h == NULL) + { + if (tTd(61, 10)) + printf("failure\n"); + + nmaps = switch_map_find("hosts", maptype, mapreturn); + while (--nmaps >= 0) + if (strcmp(maptype[nmaps], "nis") == 0 || + strcmp(maptype[nmaps], "files") == 0) + break; + if (nmaps >= 0) + { + /* try short name */ + if (strlen(name) > sizeof hbuf - 1) + return NULL; + strcpy(hbuf, name); + shorten_hostname(hbuf); + + /* if it hasn't been shortened, there's no point */ + if (strcmp(hbuf, name) != 0) + { + if (tTd(61, 10)) + printf("gethostbyname(%s)... ", hbuf); + h = gethostbyname(hbuf); + } + } + } +#endif + if (tTd(61, 10)) + { + if (h == NULL) + printf("failure\n"); + else + printf("%s\n", h->h_name); + } + return h; } struct hostent * -solaris_gethostbyaddr(addr, len, type) - const char *addr; +sm_gethostbyaddr(addr, len, type) + char *addr; int len; int type; { -# ifdef SOLARIS_2_3 +#if defined(SOLARIS) && SOLARIS < 204 +# if SOLARIS == 203 static struct hostent hp; static char buf[1000]; extern struct hostent *_switch_gethostbyaddr_r(); @@ -2235,122 +3407,155 @@ solaris_gethostbyaddr(addr, len, type) return __switch_gethostbyaddr(addr, len, type); # endif +#else + return gethostbyaddr(addr, len, type); +#endif } +/* +** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid +*/ -#endif +struct passwd * +sm_getpwnam(user) + char *user; +{ + return getpwnam(user); +} + +struct passwd * +sm_getpwuid(uid) + UID_T uid; +{ + return getpwuid(uid); +} /* -** NI_PROPVAL -- netinfo property value lookup routine +** LOAD_IF_NAMES -- load interface-specific names into $=w ** ** Parameters: -** directory -- the Netinfo directory name. -** propname -- the Netinfo property name. +** none. ** ** Returns: -** NULL -- if: -** 1. the directory is not found -** 2. the property name is not found -** 3. the property contains multiple values -** 4. some error occured -** else -- the location of the config file. +** none. ** -** Notes: -** Caller should free the return value of ni_proval +** Side Effects: +** Loads $=w with the names of all the interfaces. */ -#ifdef NETINFO - -# include <netinfo/ni.h> - -# define LOCAL_NETINFO_DOMAIN "." -# define PARENT_NETINFO_DOMAIN ".." -# define MAX_NI_LEVELS 256 +#ifdef SIOCGIFCONF +struct rtentry; +struct mbuf; +# include <arpa/inet.h> +# ifndef SUNOS403 +# include <sys/time.h> +# endif +# include <net/if.h> +#endif -char * -ni_propval(directory, propname) - char *directory; - char *propname; +void +load_if_names() { - char *propval = NULL; +#ifdef SIOCGIFCONF + int s; int i; - void *ni = NULL; - void *lastni = NULL; - ni_status nis; - ni_id nid; - ni_namelist ninl; + struct ifconf ifc; + char interfacebuf[1024]; - /* - ** If the passed directory and property name are found - ** in one of netinfo domains we need to search (starting - ** from the local domain moving all the way back to the - ** root domain) set propval to the property's value - ** and return it. - */ + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s == -1) + return; - for (i = 0; i < MAX_NI_LEVELS; ++i) + /* get the list of known IP address from the kernel */ + ifc.ifc_buf = interfacebuf; + ifc.ifc_len = sizeof interfacebuf; + if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { - if (i == 0) - { - nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); - } - else - { - if (lastni != NULL) - ni_free(lastni); - lastni = ni; - nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); - } + if (tTd(0, 4)) + printf("SIOGIFCONF failed: %s\n", errstring(errno)); + close(s); + return; + } + close(s); - /* - ** Don't bother if we didn't get a handle on a - ** proper domain. This is not necessarily an error. - ** We would get a positive ni_status if, for instance - ** we never found the directory or property and tried - ** to open the parent of the root domain! - */ + /* scan the list of IP address */ + if (tTd(0, 40)) + printf("scanning for interface specific names, ifc_len=%d\n", + ifc.ifc_len); - if (nis != 0) - break; + for (i = 0; i < ifc.ifc_len; ) + { + struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; + struct sockaddr *sa = &ifr->ifr_addr; + struct in_addr ia; + struct hostent *hp; + char ip_addr[256]; + extern char *inet_ntoa(); + extern struct hostent *gethostbyaddr(); + +#ifdef BSD4_4_SOCKADDR + if (sa->sa_len > sizeof ifr->ifr_addr) + i += sizeof ifr->ifr_name + sa->sa_len; + else +#endif + i += sizeof *ifr; - /* - ** Find the path to the server information. - */ + if (tTd(0, 20)) + printf("%s\n", anynet_ntoa((SOCKADDR *) sa)); - if (ni_pathsearch(ni, &nid, directory) != 0) + /* for some reason gcc 2.3 pukes on || here */ + if (!bitset(IFF_UP, ifr->ifr_flags)) continue; - - /* - ** Find "host" information. - */ - - if (ni_lookupprop(ni, &nid, propname, &ninl) != 0) + if (ifr->ifr_addr.sa_family != AF_INET) continue; - /* - ** If there's only one name in - ** the list, assume we've got - ** what we want. - */ + /* extract IP address from the list*/ + ia = (((struct sockaddr_in *) sa)->sin_addr); - if (ninl.ni_namelist_len == 1) + /* save IP address in text from */ + (void) sprintf(ip_addr, "[%.*s]", + sizeof ip_addr - 3, + inet_ntoa(((struct sockaddr_in *) sa)->sin_addr)); + if (!wordinclass(ip_addr, 'w')) { - propval = ni_name_dup(ninl.ni_namelist_val[0]); - break; + setclass('w', ip_addr); + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", ip_addr); } - } - /* - ** Clean up. - */ + /* skip "loopback" interface "lo" */ + if (strcmp("lo0", ifr->ifr_name) == 0) + continue; - if (ni != NULL) - ni_free(ni); - if (lastni != NULL && ni != lastni) - ni_free(lastni); + /* lookup name with IP address */ + hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET); + if (hp == NULL) + { + syslog(LOG_CRIT, "gethostbyaddr() failed for %.100s\n", + inet_ntoa(ia)); + continue; + } - return propval; -} + /* save its cname */ + if (!wordinclass((char *) hp->h_name, 'w')) + { + setclass('w', (char *) hp->h_name); + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", hp->h_name); + } -#endif /* NETINFO */ + /* save all it aliases name */ + while (*hp->h_aliases) + { + if (!wordinclass(*hp->h_aliases, 'w')) + { + setclass('w', *hp->h_aliases); + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", *hp->h_aliases); + } + hp->h_aliases++; + } + } +#endif +} /* ** HARD_SYSLOG -- call syslog repeatedly until it works ** @@ -2364,6 +3569,7 @@ ni_propval(directory, propname) # undef syslog # ifdef __STDC__ +void hard_syslog(int pri, char *msg, ...) # else hard_syslog(pri, msg, va_alist) @@ -2377,7 +3583,7 @@ hard_syslog(pri, msg, va_alist) VA_LOCAL_DECL; VA_START(msg); - vsprintf(buf, msg, ap); + vsnprintf(buf, sizeof buf, msg, ap); VA_END; for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; ) @@ -2385,3 +3591,167 @@ hard_syslog(pri, msg, va_alist) } #endif +/* +** LOCAL_HOSTNAME_LENGTH +** +** This is required to get sendmail to compile against BIND 4.9.x +** on Ultrix. +*/ + +#if defined(ultrix) && NAMED_BIND + +# include <resolv.h> +# if __RES >= 19931104 && __RES < 19950621 + +int +local_hostname_length(hostname) + char *hostname; +{ + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) && + hostname[len_host - len_domain - 1] == '.') + return len_host - len_domain - 1; + else + return 0; +} + +# endif +#endif +/* +** Compile-Time options +*/ + +char *CompileOptions[] = +{ +#if HESIOD + "HESIOD", +#endif +#if HES_GETMAILHOST + "HES_GETMAILHOST", +#endif +#ifdef LOG + "LOG", +#endif +#if MATCHGECOS + "MATCHGECOS", +#endif +#if MIME8TO7 + "MIME8TO7", +#endif +#if NAMED_BIND + "NAMED_BIND", +#endif +#if NDBM + "NDBM", +#endif +#if NETINET + "NETINET", +#endif +#if NETINFO + "NETINFO", +#endif +#if NETISO + "NETISO", +#endif +#if NETNS + "NETNS", +#endif +#if NETUNIX + "NETUNIX", +#endif +#if NETX25 + "NETX25", +#endif +#if NEWDB + "NEWDB", +#endif +#if NIS + "NIS", +#endif +#if NISPLUS + "NISPLUS", +#endif +#if SCANF + "SCANF", +#endif +#if SUID_ROOT_FILES_OK + "SUID_ROOT_FILES_OK", +#endif +#if USERDB + "USERDB", +#endif +#if XDEBUG + "XDEBUG", +#endif +#if XLA + "XLA", +#endif + NULL +}; + + +/* +** OS compile options. +*/ + +char *OsCompileOptions[] = +{ +#if HASFCHMOD + "HASFCHMOD", +#endif +#if HASFLOCK + "HASFLOCK", +#endif +#if HASGETUSERSHELL + "HASGETUSERSHELL", +#endif +#if HASINITGROUPS + "HASINITGROUPS", +#endif +#if HASLSTAT + "HASLSTAT", +#endif +#if HASSETREUID + "HASSETREUID", +#endif +#if HASSETSID + "HASSETSID", +#endif +#if HASSETVBUF + "HASSETVBUF", +#endif +#if HASSNPRINTF + "HASSNPRINTF", +#endif +#if HASUNAME + "HASUNAME", +#endif +#if IDENTPROTO + "IDENTPROTO", +#endif +#if IP_SRCROUTE + "IP_SRCROUTE", +#endif +#if NEEDFSYNC + "NEEDFSYNC", +#endif +#if NOFTRUNCATE + "NOFTRUNCATE", +#endif +#if SYS5SETPGRP + "SYS5SETPGRP", +#endif +#if SYSTEM5 + "SYSTEM5", +#endif +#if USESETEUID + "USESETEUID", +#endif + NULL +}; diff --git a/usr.sbin/sendmail/src/conf.h b/usr.sbin/sendmail/src/conf.h index 10a8d3d..30bb9d1 100644 --- a/usr.sbin/sendmail/src/conf.h +++ b/usr.sbin/sendmail/src/conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -31,20 +31,28 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)conf.h 8.104 (Berkeley) 4/17/94 + * @(#)conf.h 8.219 (Berkeley) 11/11/95 */ /* ** CONF.H -- All user-configurable parameters for sendmail +** +** Send updates to sendmail@Sendmail.ORG so they will be +** included in the next release. */ +struct rusage; /* forward declaration to get gcc to shut up in wait.h */ + # include <sys/param.h> # include <sys/types.h> # include <sys/stat.h> # include <sys/file.h> # include <sys/wait.h> +# include <limits.h> # include <fcntl.h> # include <signal.h> +# include <netdb.h> +# include <pwd.h> /********************************************************************** ** Table sizes, etc.... @@ -56,7 +64,7 @@ # define MAXPV 40 /* max # of parms to mailers */ # define MAXATOM 200 /* max atoms per address */ # define MAXMAILERS 25 /* maximum mailers known to system */ -# define MAXRWSETS 100 /* max # of sets of rewriting rules */ +# define MAXRWSETS 200 /* max # of sets of rewriting rules */ # define MAXPRIORITIES 25 /* max values for Precedence: field */ # define MAXMXHOSTS 20 /* max # of MX records */ # define SMTPLINELIM 990 /* maximum SMTP line length */ @@ -64,46 +72,68 @@ # define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */ # define MAXUSERENVIRON 100 /* max envars saved, must be >= 3 */ # define MAXALIASDB 12 /* max # of alias databases */ - -# ifndef QUEUESIZE -# define QUEUESIZE 1000 /* max # of jobs per queue run */ -# endif +# define MAXMAPSTACK 12 /* max # of stacked or sequenced maps */ +# define MAXTOCLASS 8 /* max # of message timeout classes */ +# define MAXMIMEARGS 20 /* max args in Content-Type: */ +# define MAXMIMENESTING 20 /* max MIME multipart nesting */ +# define QUEUESEGSIZE 1000 /* increment for queue size */ /********************************************************************** ** Compilation options. -** -** #define these if they are available; comment them out otherwise. +** #define these to 1 if they are available; +** #define them to 0 otherwise. +** All can be overridden from Makefile. **********************************************************************/ -# define LOG 1 /* enable logging */ -# define UGLYUUCP 1 /* output ugly UUCP From lines */ -# define NETUNIX 1 /* include unix domain support */ -# define NETINET 1 /* include internet support */ -# define SETPROCTITLE 1 /* munge argv to display current status */ -# define MATCHGECOS 1 /* match user names from gecos field */ -# define XDEBUG 1 /* enable extended debugging */ -# ifdef NEWDB -# define USERDB 1 /* look in user database (requires NEWDB) */ +# ifndef NETINET +# define NETINET 1 /* include internet support */ # endif -/********************************************************************** -** 0/1 Compilation options. -** #define these to 1 if they are available; -** #define them to 0 otherwise. -**********************************************************************/ +# ifndef NETISO +# define NETISO 0 /* do not include ISO socket support */ +# endif # ifndef NAMED_BIND # define NAMED_BIND 1 /* use Berkeley Internet Domain Server */ # endif -/* -** Most systems have symbolic links today, so default them on. You -** can turn them off by #undef'ing this below. -*/ +# ifndef XDEBUG +# define XDEBUG 1 /* enable extended debugging */ +# endif -# define HASLSTAT 1 /* has lstat(2) call */ +# ifndef MATCHGECOS +# define MATCHGECOS 1 /* match user names from gecos field */ +# endif -/* +# ifndef DSN +# define DSN 1 /* include delivery status notification code */ +# endif + +# if !defined(USERDB) && (defined(NEWDB) || defined(HESIOD)) +# define USERDB 1 /* look in user database */ +# endif + +# ifndef MIME8TO7 +# define MIME8TO7 1 /* 8->7 bit MIME conversions */ +# endif + +# ifndef MIME7TO8 +# define MIME7TO8 1 /* 7->8 bit MIME conversions */ +# endif + +/********************************************************************** +** "Hard" compilation options. +** #define these if they are available; comment them out otherwise. +** These cannot be overridden from the Makefile, and should really not +** be turned off unless absolutely necessary. +**********************************************************************/ + +# define LOG /* enable logging -- don't turn off */ + +/********************************************************************** +** End of site-specific configuration. +**********************************************************************/ +/* ** General "standard C" defines. ** ** These may be undone later, to cope with systems that claim to @@ -118,7 +148,12 @@ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ #endif -/********************************************************************** +/* +** Assume you have standard calls; can be #undefed below if necessary. +*/ + +# define HASLSTAT 1 /* has lstat(2) call */ +/********************************************************************** ** Operating system configuration. ** ** Unless you are porting to a new OS, you shouldn't have to @@ -126,80 +161,125 @@ **********************************************************************/ /* -** Per-Operating System defines -*/ - - -/* ** HP-UX -- tested for 8.07, 9.00, and 9.01. +** +** If V4FS is defined, compile for HP-UX 10.0. */ -# ifdef __hpux -/* avoid m_flags conflict between db.h & sys/sysmacros.h on HP 300 */ -# undef m_flags +#ifdef __hpux + /* common definitions for HP-UX 9.x and 10.x */ +# undef m_flags /* conflict between db.h & sys/sysmacros.h on HP 300 */ # define SYSTEM5 1 /* include all the System V defines */ # define HASINITGROUPS 1 /* has initgroups(3) call */ -# define HASSETREUID 1 /* has setreuid(2) call */ -# define setreuid(r, e) setresuid(r, e, -1) -# define LA_TYPE LA_FLOAT +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define USESETEUID 1 /* has useable seteuid(2) call */ +# define seteuid(e) setresuid(-1, e, -1) +# define IP_SRCROUTE 1 /* can check IP source routing */ +# define LA_TYPE LA_HPUX +# define SPT_TYPE SPT_PSTAT # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # define GIDSET_T gid_t -# define _PATH_UNIX "/hp-ux" -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif -# ifndef IDENTPROTO -# define IDENTPROTO 0 /* TCP/IP implementation is broken */ -# endif # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ # endif # define syslog hard_syslog # ifdef __STDC__ -extern int syslog(int, char *, ...); +extern void hard_syslog(int, char *, ...); # endif + +# ifdef V4FS + /* HP-UX 10.x */ +# define _PATH_UNIX "/stand/vmunix" +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif +# ifndef IDENTPROTO +# define IDENTPROTO 1 /* TCP/IP implementation fixed in 10.0 */ +# endif + +# else + /* HP-UX 9.x */ +# define _PATH_UNIX "/hp-ux" +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif # endif +#endif + /* ** IBM AIX 3.x -- actually tested for 3.2.3 */ -# ifdef _AIX3 +#ifdef _AIX3 +# include <paths.h> # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define FORK fork /* no vfork primitive available */ -# undef SETPROCTITLE /* setproctitle confuses AIX */ +# define GIDSET_T gid_t # define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */ -# endif +# define SPT_PADCHAR '\0' /* pad process title with nulls */ +# define LA_TYPE LA_INT +# define LA_AVENRUN "avenrun" +#endif /* ** Silicon Graphics IRIX ** ** Compiles on 4.0.1. +** +** Use IRIX64 instead of IRIX for 64-bit IRIX (6.0). +** Use IRIX5 instead of IRIX for IRIX 5.x. +** +** IRIX64 changes from Mark R. Levinson <ml@cvdev.rochester.edu>. +** IRIX5 changes from Kari E. Hurtta <Kari.Hurtta@fmi.fi>. */ -# ifdef IRIX +#if defined(IRIX64) || defined(IRIX5) +# define IRIX +#endif + +#ifdef IRIX # define SYSTEM5 1 /* this is a System-V derived system */ # define HASSETREUID 1 /* has setreuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define IP_SRCROUTE 1 /* can check IP source routing */ # define FORK fork /* no vfork primitive available */ -# define WAITUNION 1 /* use "union wait" as wait argument type */ # define setpgid BSDsetpgrp # define GIDSET_T gid_t # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ # define LA_TYPE LA_INT +# ifdef IRIX64 +# define NAMELISTMASK 0x7fffffffffffffff /* mask for nlist() values */ +# else +# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ # endif +# if defined(IRIX64) || defined(IRIX5) +# define ARGV_T char *const * +# define HASSETRLIMIT 1 /* has setrlimit(2) syscall */ +# define HASGETDTABLESIZE 1 /* has getdtablesize(2) syscall */ +# else +# define ARGV_T const char ** +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# endif +#endif /* ** SunOS and Solaris ** ** Tested on SunOS 4.1.x (a.k.a. Solaris 1.1.x) and -** Solaris 2.2 (a.k.a. SunOS 5.2). +** Solaris 2.4 (a.k.a. SunOS 5.4). */ #if defined(sun) && !defined(BSD) @@ -207,10 +287,12 @@ extern int syslog(int, char *, ...); # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define IP_SRCROUTE 1 /* can check IP source routing */ # define LA_TYPE LA_INT # ifdef SOLARIS_2_3 -# define SOLARIS +# define SOLARIS 203 /* for back compat only -- use -DSOLARIS=203 */ # endif # ifdef SOLARIS @@ -219,18 +301,17 @@ extern int syslog(int, char *, ...); # define __svr4__ /* use all System V Releae 4 defines below */ # endif # include <sys/time.h> -# define gethostbyname solaris_gethostbyname /* get working version */ -# define gethostbyaddr solaris_gethostbyaddr /* get working version */ # define GIDSET_T gid_t # ifndef _PATH_UNIX -# define _PATH_UNIX "/kernel/unix" -# endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/etc/mail/sendmail.cf" +# define _PATH_UNIX "/dev/ksyms" # endif +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" # endif +# ifndef _PATH_HOSTS +# define _PATH_HOSTS "/etc/inet/hosts" +# endif # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ # endif @@ -242,12 +323,14 @@ extern int syslog(int, char *, ...); # define HASFLOCK 1 /* has flock(2) call */ # endif # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ # include <vfork.h> # ifdef SUNOS403 /* special tweaking for SunOS 4.0.3 */ # include <malloc.h> -# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define BSD4_3 1 /* 4.3 BSD-based */ +# define NEEDSTRSTR 1 /* need emulation of strstr(3) routine */ # define WAITUNION 1 /* use "union wait" as wait argument type */ # undef WIFEXITED # undef WEXITSTATUS @@ -268,29 +351,41 @@ extern char *getenv(); /* ** DG/UX ** -** Tested on 5.4.2 +** Tested on 5.4.2 and 5.4.3. Use DGUX_5_4_2 to get the +** older support. +** 5.4.3 changes from Mark T. Robinson <mtr@ornl.gov>. */ +#ifdef DGUX_5_4_2 +# define DGUX 1 +#endif + #ifdef DGUX # define SYSTEM5 1 -# define LA_TYPE LA_SUBR +# define LA_TYPE LA_DGUX # define HASSETREUID 1 /* has setreuid(2) call */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETSID 1 /* has Posix setsid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ +# define IP_SRCROUTE 0 /* does not have <netinet/ip_var.h> */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif -# undef SETPROCTITLE +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ /* these include files must be included early on DG/UX */ # include <netinet/in.h> # include <arpa/inet.h> -# define inet_addr dgux_inet_addr +/* compiler doesn't understand const? */ +# define const + +# ifdef DGUX_5_4_2 +# define inet_addr dgux_inet_addr extern long dgux_inet_addr(); +# endif #endif @@ -307,11 +402,14 @@ extern long dgux_inet_addr(); # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASUNAME 1 /* use System V uname(2) system call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ -# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ +# ifndef BROKEN_RES_SEARCH +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ +# endif # ifdef vax # define LA_TYPE LA_FLOAT # else @@ -320,19 +418,50 @@ extern long dgux_inet_addr(); # endif # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # ifndef IDENTPROTO -# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# define IDENTPROTO 0 /* pre-4.4 TCP/IP implementation is broken */ # endif #endif /* +** OSF/1 for KSR. +** +** Contributed by Todd C. Miller <Todd.Miller@cs.colorado.edu> +*/ + +#ifdef __ksr__ +# define __osf__ 1 /* get OSF/1 defines below */ +# define FORK fork /* no vfork primitive available */ +# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif +#endif + + +/* +** OSF/1 for Intel Paragon. +** +** Contributed by Jeff A. Earickson <jeff@ssd.intel.com> +** of Intel Scalable Systems Divison. +*/ + +#ifdef __PARAGON__ +# define __osf__ 1 /* get OSF/1 defines below */ +# define _PATH_VENDOR_CF "/var/adm/sendmail/sendmail.cf" +#endif + + +/* ** OSF/1 (tested on Alpha) */ #ifdef __osf__ # define HASUNSETENV 1 /* has unsetenv(3) call */ -# define HASSETREUID 1 /* has setreuid(2) call */ +# define USESETEUID 1 /* has useable seteuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(3) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define IP_SRCROUTE 1 /* can check IP source routing */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif @@ -350,11 +479,13 @@ extern long dgux_inet_addr(); #ifdef NeXT # define HASINITGROUPS 1 /* has initgroups(3) call */ +# define NEEDPUTENV 2 /* need putenv(3) call; no setenv(3) call */ # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ # define WAITUNION 1 /* use "union wait" as wait argument type */ +# define UID_T int /* compiler gripes on uid_t */ # define sleep sleepX # define setpgid setpgrp # ifndef LA_TYPE @@ -366,9 +497,7 @@ typedef int pid_t; # undef WEXITSTATUS # undef WIFEXITED # endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/etc/sendmail/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/etc/sendmail/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail/sendmail.pid" # endif @@ -381,14 +510,20 @@ typedef int pid_t; ** See also BSD defines. */ -#ifdef BSD4_4 +#if defined(BSD4_4) && !defined(__bsdi__) # define HASUNSETENV 1 /* has unsetenv(3) call */ +# define USESETEUID 1 /* has useable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ +# define SPT_TYPE SPT_PSSTRINGS /* use PS_STRINGS pointer */ #endif @@ -400,31 +535,39 @@ typedef int pid_t; #ifdef __bsdi__ # define HASUNSETENV 1 /* has the unsetenv(3) call */ # define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has useable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define HASUNAME 1 /* has uname(2) syscall */ # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif +# define GIDSET_T gid_t # if defined(_BSDI_VERSION) && _BSDI_VERSION >= 199312 /* version 1.1 or later */ -# define HASSETPROCTITLE 1 /* setproctitle is in libc */ -# undef SETPROCTITLE /* so don't redefine it in conf.c */ +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # else /* version 1.0 or earlier */ # ifndef OLD_NEWDB # define OLD_NEWDB 1 /* old version of newdb library */ # endif +# define SPT_PADCHAR '\0' /* pad process title with nulls */ # endif #endif /* -** 386BSD / FreeBSD 1.0E / NetBSD (all architectures, all versions) +** FreeBSD / NetBSD (all architectures, all versions) ** -** Were 4.3BSD clone, closer to 4.4BSD -** Now real 4.4BSD. +** 4.3BSD clone, closer to 4.4BSD for FreeBSD 1.x and NetBSD 0.9x +** 4.4BSD-Lite based for FreeBSD 2.x and NetBSD 1.x ** ** See also BSD defines. */ @@ -432,14 +575,24 @@ typedef int pid_t; #if defined(__FreeBSD__) || defined(__NetBSD__) # define HASUNSETENV 1 /* has unsetenv(3) call */ # define HASSETSID 1 /* has the setsid(2) POSIX syscall */ +# define USESETEUID 1 /* has useable seteuid(2) call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ # define HASUNAME 1 /* has uname(2) syscall */ -# define GIDSET_T gid_t # include <sys/cdefs.h> # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ +# define BSD4_4_SOCKADDR /* has sa_len */ +# define NETLINK 1 /* supports AF_LINK */ +# define GIDSET_T gid_t # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif # define SFS_TYPE SFS_MOUNT /* use <sys/mount.h> statfs() impl */ +# if defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) +# undef SPT_TYPE +# define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ +# define setreuid __setreuid +# endif #endif @@ -466,9 +619,7 @@ typedef int pid_t; # undef HASSETVBUF /* don't actually have setvbuf(3) */ # undef WEXITSTATUS # undef WIFEXITED -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif @@ -492,9 +643,7 @@ typedef int pid_t; # ifndef LA_TYPE # define LA_TYPE LA_FLOAT # endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif @@ -516,25 +665,85 @@ extern int errno; #ifdef _SCO_unix_4_2 # define _SCO_unix_ # define HASSETREUID 1 /* has setreuid(2) call */ -# define NEEDFSYNC 1 /* needs the fsync(2) call stub */ -# define _PATH_UNIX "/unix" -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define _PATH_UNIX "/unix" +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif #endif #ifdef _SCO_unix_ +# include <sys/stream.h> /* needed for IP_SRCROUTE */ +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define NEEDFSYNC 1 /* needs the fsync(2) call stub */ +# define FORK fork +# define MAXPATHLEN PATHSIZE +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_4ARGS /* use <sys/statfs.h> 4-arg impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define SPT_TYPE SPT_SCO /* write kernel u. area */ +# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */ +# define NETUNIX 0 /* no unix domain socket support */ +#endif + + +/* +** ISC (SunSoft) Unix. +** +** Contributed by J.J. Bailey <jjb@jagware.bcc.com> +*/ + +#ifdef ISC_UNIX +# include <net/errno.h> +# include <sys/stream.h> /* needed for IP_SRCROUTE */ +# include <sys/bsdtypes.h> # define SYSTEM5 1 /* include all the System V defines */ # define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define HASSETREUID 1 /* has setreuid(2) call */ +# define NEEDFSYNC 1 /* needs the fsync(2) call stub */ +# define NETUNIX 0 /* no unix domain socket support */ +# define FORK fork +# define MAXPATHLEN 1024 +# define LA_TYPE LA_SHORT +# define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _PATH_UNIX "/unix" +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/sendmail.pid" +# endif + +#endif + + +/* +** Altos System V. +** Contributed by Tim Rice <timr@crl.com>. +*/ + +#ifdef ALTOS_SYS_V +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# define NEEDFSYNC 1 /* no fsync(2) in system library */ # define FORK fork # define MAXPATHLEN PATHSIZE # define LA_TYPE LA_SHORT # define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */ -# undef NETUNIX /* no unix domain socket support */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define TZ_TYPE TZ_TM_NAME /* use tm->tm_name */ +# define NETUNIX 0 /* no unix domain socket support */ +# undef WIFEXITED +# undef WEXITSTATUS +# define strtoul strtol /* gcc library bogosity */ + +typedef unsigned short uid_t; +typedef unsigned short gid_t; +typedef short pid_t; #endif @@ -550,11 +759,10 @@ extern int errno; # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETSID 1 /* has POSIX setsid(2) call */ # define NEEDGETOPT 1 /* need replacement for getopt(3) */ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # define LA_TYPE LA_FLOAT # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef S_IREAD # define S_IREAD _S_IREAD # define S_IWRITE _S_IWRITE @@ -583,6 +791,9 @@ extern int errno; # endif # define WAITUNION 1 /* use "union wait" as wait argument type */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ +# define NEEDPUTENV 1 /* need putenv(3) call */ +# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ # define LA_TYPE LA_INT # define LA_AVENRUN "avenrun" # define _PATH_UNIX "/unix" @@ -597,6 +808,8 @@ typedef int (*sigfunc_t)(); extern char *getenv(); extern void *malloc(); +# include <sys/time.h> + #endif @@ -606,13 +819,13 @@ extern void *malloc(); ** Thanks to, in reverse order of contact: ** ** John Kennedy <warlock@csuchico.edu> +** Andrew Pam <avatar@aus.xanadu.com> ** Florian La Roche <rzsfl@rz.uni-sb.de> ** Karl London <karl@borg.demon.co.uk> ** -** Last compiled against: [03/02/94 @ 05:34 PM (Wednesday)] -** sendmail 8.6.6.b9 named 4.9.2-931205-p1 db-1.73 -** gcc 2.5.8 libc.so.4.5.19 -** slackware 1.1.2 linux 0.99.15 +** Last compiled against: [09/06/95 @ 10:20:58 AM (Wednesday)] +** sendmail 8.7-b14 named 4.9.3-beta17 db-1.85 +** gcc 2.7.0 libc-5.2.7 linux 1.2.13 */ #ifdef __linux__ @@ -620,12 +833,24 @@ extern void *malloc(); # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ # define HASUNAME 1 /* use System V uname(2) system call */ # define HASUNSETENV 1 /* has unsetenv(3) call */ +# ifndef HASSNPRINTF +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# endif # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ # define GIDSET_T gid_t /* from <linux/types.h> */ +# define HASGETUSERSHELL 0 /* getusershell(3) broken in Slackware 2.0 */ +# define IP_SRCROUTE 0 /* linux <= 1.2.8 doesn't support IP_OPTIONS */ +# ifndef HASFLOCK +# define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ +# endif # ifndef LA_TYPE # define LA_TYPE LA_PROCSTR # endif # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() impl */ +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# endif +# define TZ_TYPE TZ_TNAME # include <sys/sysmacros.h> # undef atol /* wounded in <stdlib.h> */ #endif @@ -656,20 +881,28 @@ extern void *malloc(); #ifdef _AUX_SOURCE # include <sys/sysmacros.h> # define BSD /* has BSD routines */ +# define HASSETRLIMIT 0 /* ... but not setrlimit(2) */ +# define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ # define HASUNAME 1 /* use System V uname(2) system call */ +# define HASFCHMOD 1 /* has fchmod(2) syscall */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # define SIGFUNC_DEFINED /* sigfunc_t already defined */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif # define FORK fork -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif # ifndef LA_TYPE -# define LA_TYPE LA_ZERO +# define LA_TYPE LA_INT +# define FSHIFT 16 # endif +# define LA_AVENRUN "avenrun" # define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ +# define TZ_TYPE TZ_TZNAME +# ifndef _PATH_UNIX +# define _PATH_UNIX "/unix" /* should be in <paths.h> */ +# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # undef WIFEXITED # undef WEXITSTATUS #endif @@ -682,7 +915,6 @@ extern void *malloc(); */ #ifdef UMAXV -# include <limits.h> # define HASUNAME 1 /* use System V uname(2) system call */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ # define HASINITGROUPS 1 /* has initgroups(3) call */ @@ -749,11 +981,9 @@ typedef int pid_t; # endif # ifndef _PATH_UNIX -# define _PATH_UNIX "/dynix" -# endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" +# define _PATH_UNIX "/dynix" # endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" #endif @@ -775,13 +1005,11 @@ typedef int pid_t; # define GIDSET_T gid_t # define LA_TYPE LA_INT # define SFS_TYPE SFS_STATFS /* use <sys/statfs.h> statfs() impl */ -# undef SETPROCTITLE +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ # ifndef IDENTPROTO # define IDENTPROTO 0 /* TCP/IP implementation is broken */ # endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif @@ -800,6 +1028,7 @@ typedef int pid_t; # define MAXPATHLEN PATHSIZE # define LA_TYPE LA_ZERO # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ #endif @@ -808,19 +1037,20 @@ typedef int pid_t; ** ** From Todd Martin <tmartint@tus.ssi1.com> & Don Lewis <gdonl@gv.ssi1.com> ** -** 15 Jan 1994 +** 15 Jan 1994; updated 2 Aug 1995 ** */ #ifdef apollo # define HASSETREUID 1 /* has setreuid(2) call */ # define HASINITGROUPS 1 /* has initgroups(2) call */ -# undef SETPROCTITLE +# define IP_SRCROUTE 0 /* does not have <netinet/ip_var.h> */ +# define SPT_TYPE SPT_NONE /* don't use setproctitle */ # define LA_TYPE LA_SUBR /* use getloadavg.c */ # define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/lib/sendmail.cf" -# endif +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define TZ_TYPE TZ_TZNAME +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif @@ -834,26 +1064,37 @@ typedef int pid_t; /* -** UnixWare +** UnixWare 2.x +*/ + +#ifdef UNIXWARE2 +# define UNIXWARE 1 +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +#endif + + +/* +** UnixWare 1.1.2. ** +** Updated by Petr Lampa <lampa@fee.vutbr.cz>. ** From Evan Champion <evanc@spatial.synapse.org>. */ #ifdef UNIXWARE +# include <sys/mkdev.h> # define SYSTEM5 1 -# ifndef HASGETUSERSHELL -# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ -# endif -# define GIDSET_T int -# define SLEEP_T int +# define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ +# define HASSETREUID 1 +# define HASSETSID 1 +# define HASINITGROUPS 1 +# define GIDSET_T gid_t +# define SLEEP_T unsigned # define SFS_TYPE SFS_STATVFS # define LA_TYPE LA_ZERO # undef WIFEXITED # undef WEXITSTATUS # define _PATH_UNIX "/unix" -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/ucblib/sendmail.cf" -# endif +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" # endif @@ -883,24 +1124,257 @@ typedef int pid_t; /* ** NCR 3000 Series (SysVr4) ** -** From From: Kevin Darcy <kevin@tech.mis.cfc.com>. +** From Kevin Darcy <kevin@tech.mis.cfc.com>. */ #ifdef NCR3000 +# include <sys/sockio.h> # define __svr4__ +# define IP_SRCROUTE 0 /* Something is broken with getsockopt() */ # undef BSD # define LA_AVENRUN "avenrun" +# define SYSLOG_BUFSIZE 1024 +#endif + + +/* +** Tandem NonStop-UX SVR4 +** +** From Rick McCarty <mccarty@mpd.tandem.com>. +*/ + +#ifdef NonStop_UX_BXX +# define __svr4__ +#endif + + +/* +** Hitachi 3050R & 3050RX Workstations running HI-UX/WE2. +** +** Tested for 1.04 and 1.03 +** From Akihiro Hashimoto ("Hash") <hash@dominic.ipc.chiba-u.ac.jp>. +*/ + +#ifdef __H3050R +# define SYSTEM5 1 /* include all the System V defines */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define setreuid(r, e) setresuid(r, e, -1) +# define LA_TYPE LA_FLOAT +# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ +# define HASSETVBUF /* HI-UX has no setlinebuf */ +# ifndef GIDSET_T +# define GIDSET_T gid_t +# endif +# ifndef _PATH_UNIX +# define _PATH_UNIX "/HI-UX" +# endif +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ +# endif + +/* avoid m_flags conflict between db.h & sys/sysmacros.h on HIUX 3050 */ +# undef m_flags + +# ifdef __STDC__ +extern int syslog(int, char *, ...); +# endif + +#endif + + +/* +** Amdahl UTS System V 2.1.5 (SVr3-based) +** +** From: Janet Jackson <janet@dialix.oz.au>. +*/ + +#ifdef _UTS +# include <sys/sysmacros.h> +# undef HASLSTAT /* has symlinks, but they cause problems */ +# define NEEDFSYNC 1 /* system fsync(2) fails on non-EFS filesys */ +# define SYS5SIGNALS 1 /* System V signal semantics */ +# define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ +# define HASUNAME 1 /* use System V uname(2) system call */ +# define HASINITGROUPS 1 /* has initgroups(3) function */ +# define HASSETVBUF 1 /* has setvbuf(3) function */ +# define HASSIGSETMASK 0 /* does not have sigsetmask(2) function */ +# ifndef HASGETUSERSHELL +# define HASGETUSERSHELL 0 /* does not have getusershell(3) function */ +# endif +# define GIDSET_T gid_t /* type of 2nd arg to getgroups(2) isn't int */ +# define LA_TYPE LA_ZERO /* doesn't have load average */ +# define SFS_TYPE SFS_4ARGS /* use 4-arg statfs() */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _PATH_UNIX "/unix" +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +#endif + +/* +** Cray Computer Corporation's CSOS +** +** From Scott Bolte <scott@craycos.com>. +*/ + +#ifdef _CRAYCOM +# define SYSTEM5 1 /* include all the System V defines */ +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define NEEDFSYNC 1 /* no fsync in system library */ +# define MAXPATHLEN PATHSIZE +# define LA_TYPE LA_ZERO +# define SFS_TYPE SFS_4ARGS /* four argument statfs() call */ +# define SFS_BAVAIL f_bfree /* alternate field name */ +# define _POSIX_CHOWN_RESTRICTED -1 +extern struct group *getgrent(), *getgrnam(), *getgrgid(); +#endif + + +/* +** Sony NEWS-OS 4.2.1R and 6.0.3 +** +** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>. +*/ + +#ifdef sony_news +# ifndef __svr4 + /* NEWS-OS 4.2.1R */ +# ifndef BSD +# define BSD /* has BSD routines */ +# endif +# define HASUNSETENV 1 /* has unsetenv(2) call */ +# undef HASSETVBUF /* don't actually have setvbuf(3) */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# define LA_TYPE LA_INT +# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ +# ifndef HASFLOCK +# define HASFLOCK 1 /* has flock(2) call */ +# endif +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED + +# else + /* NEWS-OS 6.0.3 with /bin/cc */ +# ifndef __svr4__ +# define __svr4__ /* use all System V Releae 4 defines below */ +# endif +# define HASSETSID 1 /* has Posix setsid(2) call */ +# define HASGETUSERSHELL 1 /* DOES have getusershell(3) call in libc */ +# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ +# ifndef SPT_TYPE +# define SPT_TYPE SPT_SYSMIPS /* use sysmips() (OS 6.0.2 or later) */ +# endif +# define GIDSET_T gid_t +# undef WIFEXITED +# undef WEXITSTATUS +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 +# endif +# define _PATH_UNIX "/stand/unix" +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif + +# endif +#endif + + +/* +** Omron LUNA/UNIOS-B 3.0, LUNA2/Mach and LUNA88K Mach +** +** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>. +*/ + +#ifdef luna +# ifndef IDENTPROTO +# define IDENTPROTO 0 /* TCP/IP implementation is broken */ +# endif +# define HASUNSETENV 1 /* has unsetenv(2) call */ +# define NEEDPUTENV 1 /* need putenv(3) call */ +# define NEEDGETOPT 1 /* need a replacement for getopt(3) */ +# define NEEDSTRSTR 1 /* need emulation of the strstr(3) call */ +# define WAITUNION 1 /* use "union wait" as wait argument type */ +# ifdef uniosb +# include <sys/time.h> +# define NEEDVPRINTF 1 /* need a replacement for vprintf(3) */ +# define LA_TYPE LA_INT +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# endif +# ifdef luna2 +# define LA_TYPE LA_SUBR +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone */ +# endif +# ifdef luna88k +# define HASSNPRINTF 1 /* has snprintf(3) and vsnprintf(3) */ +# define LA_TYPE LA_INT +# endif +# define SFS_TYPE SFS_VFS /* use <sys/vfs.h> statfs() implementation */ +# define setpgid setpgrp +# undef WIFEXITED +# undef WEXITSTATUS +typedef int pid_t; +typedef int (*sigfunc_t)(); +# define SIGFUNC_DEFINED +extern char *getenv(); +extern int errno; +# define _PATH_VENDOR_CF "/usr/lib/sendmail.cf" +#endif + + +/* +** NEC EWS-UX/V 4.2 (with /usr/ucb/cc) +** +** From Motonori NAKAMURA <motonori@cs.ritsumei.ac.jp>. +*/ + +#if defined(nec_ews_svr4) || defined(_nec_ews_svr4) +# ifndef __svr4__ +# define __svr4__ /* use all System V Releae 4 defines below */ +# endif +# define SYS5SIGNALS 1 /* SysV signal semantics -- reset on each sig */ +# define HASSETSID 1 /* has Posix setsid(2) call */ +# define LA_TYPE LA_READKSYM /* use MIOC_READSYM ioctl */ +# define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ +# define GIDSET_T gid_t +# undef WIFEXITED +# undef WEXITSTATUS +# define NAMELISTMASK 0x7fffffff /* mask for nlist() values */ +# ifndef SYSLOG_BUFSIZE +# define SYSLOG_BUFSIZE 1024 /* allow full size syslog buffer */ +# endif #endif +/* +** Fujitsu/ICL UXP/DS (For the DS/90 Series) +** +** From Diego R. Lopez <drlopez@cica.es>. +*/ + +#ifdef UXPDS +# define __svr4__ +# define HASGETUSERSHELL 1 +# define HASFLOCK 0 +# define _PATH_UNIX "/stand/unix" +# define _PATH_VENDOR_CF "/etc/mail/sendmail.cf" +# ifndef _PATH_SENDMAILPID +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif +#endif /********************************************************************** ** End of Per-Operating System defines **********************************************************************/ - -/********************************************************************** +/********************************************************************** ** More general defines **********************************************************************/ @@ -908,26 +1382,39 @@ typedef int pid_t; #ifdef BSD # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ # define HASSETREUID 1 /* has setreuid(2) call */ -# define HASINITGROUPS 1 /* has initgroups(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# ifndef IP_SRCROUTE +# define IP_SRCROUTE 1 /* can check IP source routing */ +# endif +# ifndef HASSETRLIMIT +# define HASSETRLIMIT 1 /* has setrlimit(2) call */ +# endif # ifndef HASFLOCK # define HASFLOCK 1 /* has flock(2) call */ # endif +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TM_ZONE /* use tm->tm_zone variable */ +# endif #endif /* general System V Release 4 defines */ #ifdef __svr4__ # define SYSTEM5 1 -# define HASSETREUID 1 /* has seteuid(2) call & working saved uids */ +# define USESETEUID 1 /* has useable seteuid(2) call */ +# define HASINITGROUPS 1 /* has initgroups(3) call */ +# define BSD_COMP 1 /* get BSD ioctl calls */ +# ifndef HASSETRLIMIT +# define HASSETRLIMIT 1 /* has setrlimit(2) call */ +# endif # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* does not have getusershell(3) call */ # endif -# define setreuid(r, e) seteuid(e) # ifndef _PATH_UNIX # define _PATH_UNIX "/unix" # endif -# ifndef _PATH_SENDMAILCF -# define _PATH_SENDMAILCF "/usr/ucblib/sendmail.cf" +# ifndef _PATH_VENDOR_CF +# define _PATH_VENDOR_CF "/usr/ucblib/sendmail.cf" # endif # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/usr/ucblib/sendmail.pid" @@ -935,6 +1422,13 @@ typedef int pid_t; # ifndef SYSLOG_BUFSIZE # define SYSLOG_BUFSIZE 128 # endif +# ifndef SFS_TYPE +# define SFS_TYPE SFS_STATVFS +# endif + +# define jmp_buf sigjmp_buf +# define setjmp(env) sigsetjmp(env, 1) +# define longjmp(env, val) siglongjmp(env, val) #endif /* general System V defines */ @@ -943,12 +1437,22 @@ typedef int pid_t; # define HASUNAME 1 /* use System V uname(2) system call */ # define SYS5SETPGRP 1 /* use System V setpgrp(2) syscall */ # define HASSETVBUF 1 /* we have setvbuf(3) in libc */ +# ifndef HASULIMIT +# define HASULIMIT 1 /* has the ulimit(2) syscall */ +# endif # ifndef LA_TYPE -# define LA_TYPE LA_INT /* assume integer load average */ +# ifdef MIOC_READKSYM +# define LA_TYPE LA_READKSYM /* use MIOC_READKSYM ioctl */ +# else +# define LA_TYPE LA_INT /* assume integer load average */ +# endif # endif # ifndef SFS_TYPE # define SFS_TYPE SFS_USTAT /* use System V ustat(2) syscall */ # endif +# ifndef TZ_TYPE +# define TZ_TYPE TZ_TZNAME /* use tzname[] vector */ +# endif # define bcopy(s, d, l) (memmove((d), (s), (l))) # define bzero(d, l) (memset((d), '\0', (l))) # define bcmp(s, d, l) (memcmp((s), (d), (l))) @@ -958,25 +1462,31 @@ typedef int pid_t; #ifdef _POSIX_VERSION # define HASSETSID 1 /* has Posix setsid(2) call */ # define HASWAITPID 1 /* has Posix waitpid(2) call */ +# if _POSIX_VERSION >= 199500 && !defined(USESETEUID) +# define USESETEUID 1 /* has useable seteuid(2) call */ +# endif #endif - -/* -** If no type for argument two of getgroups call is defined, assume -** it's an integer -- unfortunately, there seem to be several choices -** here. +/* +** Tweaking for systems that (for example) claim to be BSD or POSIX +** but don't have all the standard BSD or POSIX routines (boo hiss). */ -#ifndef GIDSET_T -# define GIDSET_T int +#ifdef titan +# undef HASINITGROUPS /* doesn't have initgroups(3) call */ #endif -/* -** Tweaking for systems that (for example) claim to be BSD but -** don't have all the standard BSD routines (boo hiss). -*/ +#ifdef _CRAYCOM +# undef HASSETSID /* despite POSIX claim, doesn't have setsid */ +#endif -#ifdef titan -# undef HASINITGROUPS /* doesn't have initgroups(3) call */ +#ifdef ISC_UNIX +# undef bcopy /* despite SystemV claim, uses BSD bcopy */ +#endif + +#ifdef ALTOS_SYS_V +# undef bcopy /* despite SystemV claim, uses BSD bcopy */ +# undef bzero /* despite SystemV claim, uses BSD bzero */ +# undef bcmp /* despite SystemV claim, uses BSD bcmp */ #endif @@ -995,20 +1505,77 @@ typedef int pid_t; # define IDENTPROTO 1 /* use IDENT proto (RFC 1413) */ #endif +#ifndef IP_SRCROUTE +# define IP_SRCROUTE 1 /* Detect IP source routing */ +#endif + #ifndef HASGETUSERSHELL # define HASGETUSERSHELL 1 /* libc has getusershell(3) call */ #endif +#ifndef NETUNIX +# define NETUNIX 1 /* include unix domain support */ +#endif + #ifndef HASFLOCK # define HASFLOCK 0 /* assume no flock(2) support */ #endif +#ifndef HASSETREUID +# define HASSETREUID 0 /* assume no setreuid(2) call */ +#endif + +#ifndef HASFCHMOD +# define HASFCHMOD 0 /* assume no fchmod(2) syscall */ +#endif + +#ifndef USESETEUID +# define USESETEUID 0 /* assume no seteuid(2) call or no saved ids */ +#endif + +#ifndef HASSETRLIMIT +# define HASSETRLIMIT 0 /* assume no setrlimit(2) support */ +#endif + +#ifndef HASULIMIT +# define HASULIMIT 0 /* assume no ulimit(2) support */ +#endif + #ifndef OLD_NEWDB # define OLD_NEWDB 0 /* assume newer version of newdb */ #endif +/* heuristic setting of HASSETSIGMASK; can override above */ +#ifndef HASSIGSETMASK +# ifdef SIGVTALRM +# define HASSETSIGMASK 1 +# else +# define HASSETSIGMASK 0 +# endif +#endif + +/* +** If no type for argument two of getgroups call is defined, assume +** it's an integer -- unfortunately, there seem to be several choices +** here. +*/ -/********************************************************************** +#ifndef GIDSET_T +# define GIDSET_T int +#endif + +#ifndef UID_T +# define UID_T uid_t +#endif + +#ifndef SIZE_T +# define SIZE_T size_t +#endif + +#ifndef ARGV_T +# define ARGV_T char ** +#endif +/********************************************************************** ** Remaining definitions should never have to be changed. They are ** primarily to provide back compatibility for older systems -- for ** example, it includes some POSIX compatibility definitions @@ -1021,11 +1588,14 @@ typedef int pid_t; #if !defined(S_ISLNK) && defined(S_IFLNK) # define S_ISLNK(foo) ((foo & S_IFMT) == S_IFLNK) #endif +#ifndef S_IWUSR +# define S_IWUSR 0200 +#endif #ifndef S_IWGRP -#define S_IWGRP 020 +# define S_IWGRP 0020 #endif #ifndef S_IWOTH -#define S_IWOTH 002 +# define S_IWOTH 0002 #endif /* @@ -1063,11 +1633,45 @@ typedef int pid_t; # include "cdefs.h" #endif +#if NAMED_BIND +# include <arpa/nameser.h> +# ifdef __svr4__ +# ifdef NOERROR +# undef NOERROR /* avoid compiler conflict with stream.h */ +# endif +# endif +# ifndef __ksr__ +extern int h_errno; +# endif +#endif + +/* +** The size of an IP address -- can't use sizeof because of problems +** on Crays, where everything is 64 bits. This will break if/when +** IP addresses are expanded to eight bytes. +*/ + +#ifndef INADDRSZ +# define INADDRSZ 4 +#endif + +/* +** The size of various known types -- for reading network protocols. +** Again, we can't use sizeof because of compiler randomness. +*/ + +#ifndef INT16SZ +# define INT16SZ 2 +#endif +#ifndef INT32SZ +# define INT32SZ 4 +#endif + /* ** Do some required dependencies */ -#if defined(NETINET) || defined(NETISO) +#if NETINET || NETISO # define SMTP 1 /* enable user and server SMTP */ # define QUEUE 1 /* enable queueing */ # define DAEMON 1 /* include the daemon (requires IPC & SMTP) */ @@ -1109,7 +1713,7 @@ struct utsname }; #endif /* HASUNAME */ -#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) +#if !defined(MAXHOSTNAMELEN) && !defined(_SCO_unix_) && !defined(NonStop_UX_BXX) && !defined(ALTOS_SYS_V) # define MAXHOSTNAMELEN 256 #endif @@ -1118,15 +1722,15 @@ struct utsname #endif #ifndef STDIN_FILENO -#define STDIN_FILENO 0 +# define STDIN_FILENO 0 #endif #ifndef STDOUT_FILENO -#define STDOUT_FILENO 1 +# define STDOUT_FILENO 1 #endif #ifndef STDERR_FILENO -#define STDERR_FILENO 2 +# define STDERR_FILENO 2 #endif #ifndef LOCK_SH @@ -1136,6 +1740,12 @@ struct utsname # define LOCK_UN 0x08 /* unlock */ #endif +#ifndef SEEK_SET +# define SEEK_SET 0 +# define SEEK_CUR 1 +# define SEEK_END 2 +#endif + #ifndef SIG_ERR # define SIG_ERR ((void (*)()) -1) #endif @@ -1163,13 +1773,19 @@ typedef void (*sigfunc_t) __P((int)); */ #ifndef TOBUFSIZE -# if (SYSLOG_BUFSIZE) > 512 -# define TOBUFSIZE (SYSLOG_BUFSIZE - 256) +# if (SYSLOG_BUFSIZE) > 768 +# define TOBUFSIZE (SYSLOG_BUFSIZE - 512) # else # define TOBUFSIZE 256 # endif #endif +/* TOBUFSIZE must never be permitted to exceed MAXLINE - 128 */ +#if TOBUFSIZE > (MAXLINE - 128) +# undef TOBUFSIZE +# define TOBUFSIZE (MAXLINE - 128) +#endif + /* ** Size of prescan buffer. ** Despite comments in the _sendmail_ book, this probably should @@ -1183,9 +1799,9 @@ typedef void (*sigfunc_t) __P((int)); # endif /* -** If we are going to link scanf anyway, use it in readcf +** Default to using scanf in readcf. */ -#if !defined(HASUNAME) && !defined(SCANF) +#ifndef SCANF # define SCANF 1 #endif diff --git a/usr.sbin/sendmail/src/daemon.c b/usr.sbin/sendmail/src/daemon.c index b4b4e8b..c2f5327 100644 --- a/usr.sbin/sendmail/src/daemon.c +++ b/usr.sbin/sendmail/src/daemon.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -37,20 +37,27 @@ #ifndef lint #ifdef DAEMON -static char sccsid[] = "@(#)daemon.c 8.48.1.5 (Berkeley) 3/28/95 (with daemon mode)"; +static char sccsid[] = "@(#)daemon.c 8.118 (Berkeley) 10/8/95 (with daemon mode)"; #else -static char sccsid[] = "@(#)daemon.c 8.48.1.5 (Berkeley) 3/28/95 (without daemon mode)"; +static char sccsid[] = "@(#)daemon.c 8.118 (Berkeley) 10/8/95 (without daemon mode)"; #endif #endif /* not lint */ #ifdef DAEMON -# include <netdb.h> # include <arpa/inet.h> #if NAMED_BIND -# include <arpa/nameser.h> # include <resolv.h> +# ifndef NO_DATA +# define NO_DATA NO_ADDRESS +# endif +#endif + +#if IP_SRCROUTE +# include <netinet/in_systm.h> +# include <netinet/ip.h> +# include <netinet/ip_var.h> #endif /* @@ -106,13 +113,14 @@ int ListenQueueSize = 10; /* size of listen queue */ int TcpRcvBufferSize = 0; /* size of TCP receive buffer */ int TcpSndBufferSize = 0; /* size of TCP send buffer */ +void getrequests() { int t; bool refusingconnections = TRUE; FILE *pidf; int socksize; -#ifdef XDEBUG +#if XDEBUG bool j_has_dot; #endif extern void reapchild(); @@ -167,11 +175,11 @@ getrequests() fclose(pidf); } -#ifdef XDEBUG +#if XDEBUG { char jbuf[MAXHOSTNAMELEN]; - expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); + expand("\201j", jbuf, sizeof jbuf, CurEnv); j_has_dot = strchr(jbuf, '.') != NULL; } #endif @@ -184,6 +192,7 @@ getrequests() register int pid; auto int lotherend; extern bool refuseconnections(); + extern int getla(); /* see if we are rejecting connections */ CurrentLA = getla(); @@ -196,29 +205,24 @@ getrequests() DaemonSocket = -1; } refusingconnections = TRUE; - setproctitle("rejecting connections: load average: %d", - CurrentLA); sleep(15); continue; } + /* arrange to (re)open the socket if necessary */ if (refusingconnections) { - /* start listening again */ (void) opendaemonsocket(FALSE); - setproctitle("accepting connections"); refusingconnections = FALSE; } -#ifdef XDEBUG +#if XDEBUG /* check for disaster */ { - register STAB *s; char jbuf[MAXHOSTNAMELEN]; - expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); - if ((s = stab(jbuf, ST_CLASS, ST_FIND)) == NULL || - !bitnset('w', s->s_class)) + expand("\201j", jbuf, sizeof jbuf, CurEnv); + if (!wordinclass(jbuf, 'w')) { dumpstate("daemon lost $j"); syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog"); @@ -234,6 +238,7 @@ getrequests() #endif /* wait for a connection */ + setproctitle("accepting connections"); do { errno = 0; @@ -244,6 +249,11 @@ getrequests() if (t < 0) { syserr("getrequests: accept"); + + /* arrange to re-open the socket next time around */ + (void) close(DaemonSocket); + DaemonSocket = -1; + refusingconnections = TRUE; sleep(5); continue; } @@ -268,6 +278,8 @@ getrequests() { char *p; extern char *hostnamebyanyaddr(); + extern void intsig(); + FILE *inchannel, *outchannel; /* ** CHILD -- return to caller. @@ -276,34 +288,31 @@ getrequests() */ (void) setsignal(SIGCHLD, SIG_DFL); - DisConnected = FALSE; + (void) setsignal(SIGHUP, intsig); + (void) close(DaemonSocket); setproctitle("startup with %s", anynet_ntoa(&RealHostAddr)); /* determine host name */ p = hostnamebyanyaddr(&RealHostAddr); + if (strlen(p) > MAXNAME) + p[MAXNAME] = '\0'; RealHostName = newstr(p); setproctitle("startup with %s", p); -#ifdef LOG - if (LogLevel > 11) - { - /* log connection information */ - syslog(LOG_INFO, "connect from %s (%s)", - RealHostName, anynet_ntoa(&RealHostAddr)); - } -#endif - - (void) close(DaemonSocket); - if ((InChannel = fdopen(t, "r")) == NULL || + if ((inchannel = fdopen(t, "r")) == NULL || (t = dup(t)) < 0 || - (OutChannel = fdopen(t, "w")) == NULL) + (outchannel = fdopen(t, "w")) == NULL) { syserr("cannot open SMTP server channel, fd=%d", t); exit(0); } + InChannel = inchannel; + OutChannel = outchannel; + DisConnected = FALSE; + /* should we check for illegal connection here? XXX */ #ifdef XLA if (!xla_host_ok(RealHostName)) @@ -318,6 +327,8 @@ getrequests() return; } + CurChildren++; + /* close the port so that others will hang (for a while) */ (void) close(t); } @@ -347,7 +358,7 @@ opendaemonsocket(firsttime) bool firsttime; { int on = 1; - int socksize; + int socksize = 0; int ntries = 0; int saveerrno; @@ -363,7 +374,6 @@ opendaemonsocket(firsttime) DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0); if (DaemonSocket < 0) { - /* probably another daemon already */ saveerrno = errno; syserr("opendaemonsocket: can't create server SMTP socket"); severe: @@ -393,19 +403,19 @@ opendaemonsocket(firsttime) SO_RCVBUF, (char *) &TcpRcvBufferSize, sizeof(TcpRcvBufferSize)) < 0) - syserr("getrequests: setsockopt(SO_RCVBUF)"); + syserr("opendaemonsocket: setsockopt(SO_RCVBUF)"); } #endif switch (DaemonAddr.sa.sa_family) { -# ifdef NETINET +# if NETINET case AF_INET: socksize = sizeof DaemonAddr.sin; break; # endif -# ifdef NETISO +# if NETISO case AF_ISO: socksize = sizeof DaemonAddr.siso; break; @@ -418,8 +428,9 @@ opendaemonsocket(firsttime) if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0) { + /* probably another daemon already */ saveerrno = errno; - syserr("getrequests: cannot bind"); + syserr("opendaemonsocket: cannot bind"); (void) close(DaemonSocket); goto severe; } @@ -427,12 +438,13 @@ opendaemonsocket(firsttime) if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0) { saveerrno = errno; - syserr("getrequests: cannot listen"); + syserr("opendaemonsocket: cannot listen"); (void) close(DaemonSocket); goto severe; } return socksize; } while (ntries++ < MAXOPENTRIES && transienterror(saveerrno)); + syserr("!opendaemonsocket: server SMTP socket wedged: exiting"); finis(); } /* @@ -448,6 +460,7 @@ opendaemonsocket(firsttime) ** releases any resources used by the passive daemon. */ +void clrdaemon() { if (DaemonSocket >= 0) @@ -464,6 +477,7 @@ clrdaemon() ** none. */ +void setdaemonoptions(p) register char *p; { @@ -488,25 +502,27 @@ setdaemonoptions(p) continue; while (isascii(*++v) && isspace(*v)) continue; + if (isascii(*f) && islower(*f)) + *f = toupper(*f); switch (*f) { case 'F': /* address family */ if (isascii(*v) && isdigit(*v)) DaemonAddr.sa.sa_family = atoi(v); -#ifdef NETINET +#if NETINET else if (strcasecmp(v, "inet") == 0) DaemonAddr.sa.sa_family = AF_INET; #endif -#ifdef NETISO +#if NETISO else if (strcasecmp(v, "iso") == 0) DaemonAddr.sa.sa_family = AF_ISO; #endif -#ifdef NETNS +#if NETNS else if (strcasecmp(v, "ns") == 0) DaemonAddr.sa.sa_family = AF_NS; #endif -#ifdef NETX25 +#if NETX25 else if (strcasecmp(v, "x.25") == 0) DaemonAddr.sa.sa_family = AF_CCITT; #endif @@ -517,10 +533,10 @@ setdaemonoptions(p) case 'A': /* address */ switch (DaemonAddr.sa.sa_family) { -#ifdef NETINET +#if NETINET case AF_INET: if (isascii(*v) && isdigit(*v)) - DaemonAddr.sin.sin_addr.s_addr = inet_network(v); + DaemonAddr.sin.sin_addr.s_addr = htonl(inet_network(v)); else { register struct netent *np; @@ -546,7 +562,7 @@ setdaemonoptions(p) { short port; -#ifdef NETINET +#if NETINET case AF_INET: if (isascii(*v) && isdigit(*v)) DaemonAddr.sin.sin_port = htons(atoi(v)); @@ -563,7 +579,7 @@ setdaemonoptions(p) break; #endif -#ifdef NETISO +#if NETISO case AF_ISO: /* assume two byte transport selector */ if (isascii(*v) && isdigit(*v)) @@ -600,6 +616,9 @@ setdaemonoptions(p) case 'R': /* receive buffer size */ TcpRcvBufferSize = atoi(v); break; + + default: + syserr("554 DaemonPortOptions parameter \"%s\" unknown", f); } } } @@ -622,6 +641,15 @@ setdaemonoptions(p) ** none. */ +static jmp_buf CtxConnectTimeout; + +static void +connecttimeout() +{ + errno = ETIMEDOUT; + longjmp(CtxConnectTimeout, 1); +} + SOCKADDR CurHostAddr; /* address of current host */ int @@ -631,14 +659,14 @@ makeconnection(host, port, mci, usesecureport) register MCI *mci; bool usesecureport; { - register int i, s; + register int i = 0; + register int s; register struct hostent *hp = (struct hostent *)NULL; SOCKADDR addr; int sav_errno; int addrlen; -#if NAMED_BIND - extern int h_errno; -#endif + bool firstconnect; + EVENT *ev; /* ** Set up the address for the mailer. @@ -661,18 +689,26 @@ makeconnection(host, port, mci, usesecureport) if (p != NULL) { *p = '\0'; -#ifdef NETINET +#if NETINET hid = inet_addr(&host[1]); if (hid == -1) #endif { /* try it as a host name (avoid MX lookup) */ - hp = gethostbyname(&host[1]); + hp = sm_gethostbyname(&host[1]); if (hp == NULL && p[-1] == '.') { +#if NAMED_BIND + int oldopts = _res.options; + + _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); +#endif p[-1] = '\0'; - hp = gethostbyname(&host[1]); + hp = sm_gethostbyname(&host[1]); p[-1] = '.'; +#if NAMED_BIND + _res.options = oldopts; +#endif } *p = ']'; goto gothostent; @@ -682,9 +718,10 @@ makeconnection(host, port, mci, usesecureport) if (p == NULL) { usrerr("553 Invalid numeric domain spec \"%s\"", host); + mci->mci_status = "5.1.2"; return (EX_NOHOST); } -#ifdef NETINET +#if NETINET addr.sin.sin_family = AF_INET; /*XXX*/ addr.sin.sin_addr.s_addr = hid; #endif @@ -693,34 +730,43 @@ makeconnection(host, port, mci, usesecureport) { register char *p = &host[strlen(host) - 1]; - hp = gethostbyname(host); + hp = sm_gethostbyname(host); if (hp == NULL && *p == '.') { +#if NAMED_BIND + int oldopts = _res.options; + + _res.options &= ~(RES_DEFNAMES|RES_DNSRCH); +#endif *p = '\0'; - hp = gethostbyname(host); + hp = sm_gethostbyname(host); *p = '.'; +#if NAMED_BIND + _res.options = oldopts; +#endif } gothostent: if (hp == NULL) { #if NAMED_BIND - if (errno == ETIMEDOUT || h_errno == TRY_AGAIN) - return (EX_TEMPFAIL); - - /* if name server is specified, assume temp fail */ - if (errno == ECONNREFUSED && UseNameServer) + /* check for name server timeouts */ + if (errno == ETIMEDOUT || h_errno == TRY_AGAIN || + (errno == ECONNREFUSED && UseNameServer)) + { + mci->mci_status = "4.4.3"; return (EX_TEMPFAIL); + } #endif return (EX_NOHOST); } addr.sa.sa_family = hp->h_addrtype; switch (hp->h_addrtype) { -#ifdef NETINET +#if NETINET case AF_INET: bcopy(hp->h_addr, &addr.sin.sin_addr, - sizeof addr.sin.sin_addr); + INADDRSZ); break; #endif @@ -737,15 +783,16 @@ gothostent: ** Determine the port number. */ - if (port != 0) - port = htons(port); - else + if (port == 0) { register struct servent *sp = getservbyname("smtp", "tcp"); if (sp == NULL) { - syserr("554 makeconnection: service \"smtp\" unknown"); +#ifdef LOG + if (LogLevel > 2) + syslog(LOG_ERR, "makeconnection: service \"smtp\" unknown"); +#endif port = htons(25); } else @@ -754,14 +801,14 @@ gothostent: switch (addr.sa.sa_family) { -#ifdef NETINET +#if NETINET case AF_INET: addr.sin.sin_port = port; addrlen = sizeof (struct sockaddr_in); break; #endif -#ifdef NETISO +#if NETISO case AF_ISO: /* assume two byte transport selector */ bcopy((char *) &port, TSEL((struct sockaddr_iso *) &addr), 2); @@ -784,6 +831,7 @@ gothostent: return EX_TEMPFAIL; #endif + firstconnect = TRUE; for (;;) { if (tTd(16, 1)) @@ -806,7 +854,7 @@ gothostent: if (s < 0) { sav_errno = errno; - syserr("makeconnection: no socket"); + syserr("makeconnection: cannot create socket"); goto failure; } @@ -833,24 +881,54 @@ gothostent: if (CurEnv->e_xfp != NULL) (void) fflush(CurEnv->e_xfp); /* for debugging */ errno = 0; /* for debugging */ - if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) - break; - /* couldn't connect.... figure out why */ + /* + ** Linux seems to hang in connect for 90 minutes (!!!). + ** Time out the connect to avoid this problem. + */ + + if (setjmp(CtxConnectTimeout) == 0) + { + if (TimeOuts.to_connect == 0) + ev = NULL; + else + ev = setevent(TimeOuts.to_connect, connecttimeout, 0); + if (connect(s, (struct sockaddr *) &addr, addrlen) >= 0) + { + if (ev != NULL) + clrevent(ev); + break; + } + } sav_errno = errno; + if (ev != NULL) + clrevent(ev); + + /* if running demand-dialed connection, try again */ + if (DialDelay > 0 && firstconnect) + { + if (tTd(16, 1)) + printf("Connect failed (%s); trying again...\n", + errstring(sav_errno)); + firstconnect = FALSE; + sleep(DialDelay); + continue; + } + + /* couldn't connect.... figure out why */ (void) close(s); - if (hp && hp->h_addr_list[i]) + if (hp != NULL && hp->h_addr_list[i]) { if (tTd(16, 1)) printf("Connect failed (%s); trying new address....\n", errstring(sav_errno)); switch (addr.sa.sa_family) { -#ifdef NETINET +#if NETINET case AF_INET: bcopy(hp->h_addr_list[i++], &addr.sin.sin_addr, - sizeof addr.sin.sin_addr); + INADDRSZ); break; #endif @@ -902,61 +980,77 @@ gothostent: ** Adds numeric codes to $=w. */ -char ** +struct hostent * myhostname(hostbuf, size) char hostbuf[]; int size; { register struct hostent *hp; - extern struct hostent *gethostbyname(); + extern bool getcanonname(); if (gethostname(hostbuf, size) < 0) { (void) strcpy(hostbuf, "localhost"); } - hp = gethostbyname(hostbuf); + hp = sm_gethostbyname(hostbuf); if (hp == NULL) + return NULL; + if (strchr(hp->h_name, '.') != NULL || strchr(hostbuf, '.') == NULL) { - syserr("!My host name (%s) does not seem to exist!", hostbuf); + (void) strncpy(hostbuf, hp->h_name, size - 1); + hostbuf[size - 1] = '\0'; } - (void) strncpy(hostbuf, hp->h_name, size - 1); - hostbuf[size - 1] = '\0'; -#if NAMED_BIND - /* if still no dot, try DNS directly (i.e., avoid NIS problems) */ + /* + ** If there is still no dot in the name, try looking for a + ** dotted alias. + */ + if (strchr(hostbuf, '.') == NULL) { - extern bool getcanonname(); - extern int h_errno; + char **ha; - /* try twice in case name server not yet started up */ - if (!getcanonname(hostbuf, size, TRUE) && - UseNameServer && - (h_errno != TRY_AGAIN || - (sleep(30), !getcanonname(hostbuf, size, TRUE)))) + for (ha = hp->h_aliases; *ha != NULL; ha++) { - errno = h_errno + E_DNSBASE; - syserr("!My host name (%s) not known to DNS", - hostbuf); + if (strchr(*ha, '.') != NULL) + { + (void) strncpy(hostbuf, *ha, size - 1); + hostbuf[size - 1] = '\0'; + break; + } } } -#endif - if (hp->h_addrtype == AF_INET && hp->h_length == 4) - { - register int i; + /* + ** If _still_ no dot, wait for a while and try again -- it is + ** possible that some service is starting up. This can result + ** in excessive delays if the system is badly configured, but + ** there really isn't a way around that, particularly given that + ** the config file hasn't been read at this point. + ** All in all, a bit of a mess. + */ - for (i = 0; hp->h_addr_list[i] != NULL; i++) + if (strchr(hostbuf, '.') == NULL && + !getcanonname(hostbuf, size, TRUE)) + { +#ifdef LOG + syslog(LOG_CRIT, "My unqualifed host name (%s) unknown; sleeping for retry", + hostbuf); +#endif + message("My unqualifed host name (%s) unknown; sleeping for retry", + hostbuf); + sleep(60); + if (!getcanonname(hostbuf, size, TRUE)) { - char ipbuf[100]; - - sprintf(ipbuf, "[%s]", - inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); - setclass('w', ipbuf); +#ifdef LOG + syslog(LOG_ALERT, "unable to qualify my own domain name (%s) -- using short name", + hostbuf); +#endif + message("WARNING: unable to qualify my own domain name (%s) -- using short name", + hostbuf); } } - - return (hp->h_aliases); + return (hp); } /* ** GETAUTHINFO -- get the real host name asociated with a file descriptor @@ -970,41 +1064,34 @@ myhostname(hostbuf, size) ** The user@host information associated with this descriptor. */ -#if IDENTPROTO - static jmp_buf CtxAuthTimeout; -static +static void authtimeout() { longjmp(CtxAuthTimeout, 1); } -#endif - char * getauthinfo(fd) int fd; { int falen; register char *p; -#if IDENTPROTO SOCKADDR la; int lalen; register struct servent *sp; - int s; + volatile int s; int i; EVENT *ev; int nleft; char ibuf[MAXNAME + 1]; -#endif static char hbuf[MAXNAME * 2 + 2]; extern char *hostnamebyanyaddr(); - extern char RealUserName[]; /* main.c */ falen = sizeof RealHostAddr; - if (getpeername(fd, &RealHostAddr.sa, &falen) < 0 || falen <= 0 || - RealHostAddr.sa.sa_family == 0) + if (isatty(fd) || getpeername(fd, &RealHostAddr.sa, &falen) < 0 || + falen <= 0 || RealHostAddr.sa.sa_family == 0) { (void) sprintf(hbuf, "%s@localhost", RealUserName); if (tTd(9, 1)) @@ -1018,7 +1105,6 @@ getauthinfo(fd) RealHostName = newstr(hostnamebyanyaddr(&RealHostAddr)); } -#if IDENTPROTO if (TimeOuts.to_ident == 0) goto noident; @@ -1120,6 +1206,14 @@ 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) { @@ -1136,14 +1230,12 @@ getauthinfo(fd) i = strlen(hbuf); hbuf[i++] = '@'; strcpy(&hbuf[i], RealHostName == NULL ? "localhost" : RealHostName); - goto finish; + goto postident; closeident: (void) close(s); clrevent(ev); -#endif /* IDENTPROTO */ - noident: if (RealHostName == NULL) { @@ -1153,12 +1245,92 @@ noident: } (void) strcpy(hbuf, RealHostName); -finish: +postident: +#if IP_SRCROUTE + /* + ** Extract IP source routing information. + ** + ** Format of output for a connection from site a through b + ** through c to d: + ** loose: @site-c@site-b:site-a + ** strict: !@site-c@site-b:site-a + ** + ** o - pointer within ipopt_list structure. + ** q - pointer within ls/ss rr route data + ** p - pointer to hbuf + */ + + if (RealHostAddr.sa.sa_family == AF_INET) + { + int ipoptlen, j; + u_char *q; + u_char *o; + struct in_addr addr; + struct ipoption ipopt; + + ipoptlen = sizeof ipopt; + if (getsockopt(fd, IPPROTO_IP, IP_OPTIONS, + (char *) &ipopt, &ipoptlen) < 0) + goto noipsr; + if (ipoptlen == 0) + goto noipsr; + o = (u_char *) ipopt.ipopt_list; + while (o != NULL && o < (u_char *) &ipopt + ipoptlen) + { + switch (*o) + { + case IPOPT_EOL: + o = NULL; + break; + + case IPOPT_NOP: + o++; + break; + + case IPOPT_SSRR: + case IPOPT_LSRR: + p = &hbuf[strlen(hbuf)]; + sprintf(p, " [%s@%.120s", + *o == IPOPT_SSRR ? "!" : "", + inet_ntoa(ipopt.ipopt_dst)); + p += strlen(p); + + /* o[1] is option length */ + j = *++o / sizeof(struct in_addr) - 1; + + /* q skips length and router pointer to data */ + q = o + 2; + for ( ; j >= 0; j--) + { + memcpy(&addr, q, sizeof(addr)); + sprintf(p, "%c%.120s", + j ? '@' : ':', + inet_ntoa(addr)); + p += strlen(p); + q += sizeof(struct in_addr); + } + o += *o; + break; + + default: + /* Skip over option */ + o += o[1]; + break; + } + } + strcat(hbuf,"]"); + goto postipsr; + } +#endif + +noipsr: if (RealHostName != NULL && RealHostName[0] != '[') { p = &hbuf[strlen(hbuf)]; - (void) sprintf(p, " [%s]", anynet_ntoa(&RealHostAddr)); + (void) sprintf(p, " [%.100s]", anynet_ntoa(&RealHostAddr)); } + +postipsr: if (tTd(9, 1)) printf("getauthinfo: %s\n", hbuf); return hbuf; @@ -1192,15 +1364,10 @@ host_map_lookup(map, name, av, statp) int *statp; { register struct hostent *hp; - u_long in_addr; + struct in_addr in_addr; char *cp; - int i; register STAB *s; - char hbuf[MAXNAME]; - extern struct hostent *gethostbyaddr(); -#if NAMED_BIND - extern int h_errno; -#endif + char hbuf[MAXNAME + 1]; /* ** See if we have already looked up this name. If so, just @@ -1212,22 +1379,39 @@ host_map_lookup(map, name, av, statp) { if (tTd(9, 1)) printf("host_map_lookup(%s) => CACHE %s\n", - name, s->s_namecanon.nc_cname); + name, + s->s_namecanon.nc_cname == NULL + ? "NULL" + : s->s_namecanon.nc_cname); errno = s->s_namecanon.nc_errno; #if NAMED_BIND h_errno = s->s_namecanon.nc_herrno; #endif *statp = s->s_namecanon.nc_stat; - if (CurEnv->e_message == NULL && *statp == EX_TEMPFAIL) + if (*statp == EX_TEMPFAIL) { - sprintf(hbuf, "%s: Name server timeout", + CurEnv->e_status = "4.4.3"; + message("851 %s: Name server timeout", shortenstring(name, 33)); - CurEnv->e_message = newstr(hbuf); } return s->s_namecanon.nc_cname; } /* + ** If we are running without a regular network connection (usually + ** dial-on-demand) and we are just queueing, we want to avoid DNS + ** lookups because those could try to connect to a server. + */ + + if (CurEnv->e_sendmode == SM_DEFER) + { + if (tTd(9, 1)) + printf("host_map_lookup(%s) => DEFERRED\n", name); + *statp = EX_TEMPFAIL; + return NULL; + } + + /* ** If first character is a bracket, then it is an address ** lookup. Address is copied into a temporary buffer to ** strip the brackets and to preserve name if address is @@ -1241,8 +1425,14 @@ host_map_lookup(map, name, av, statp) if (tTd(9, 1)) printf("host_map_lookup(%s) => ", name); s->s_namecanon.nc_flags |= NCF_VALID; /* will be soon */ - (void) strcpy(hbuf, name); - if (getcanonname(hbuf, sizeof hbuf - 1, TRUE)) + if (strlen(name) < sizeof hbuf) + (void) strcpy(hbuf, name); + else + { + bcopy(name, hbuf, sizeof hbuf - 1); + hbuf[sizeof hbuf - 1] = '\0'; + } + if (getcanonname(hbuf, sizeof hbuf - 1, !HasWildcardMX)) { if (tTd(9, 1)) printf("%s\n", hbuf); @@ -1264,16 +1454,15 @@ host_map_lookup(map, name, av, statp) case TRY_AGAIN: if (UseNameServer) { - sprintf(hbuf, "%s: Name server timeout", + CurEnv->e_status = "4.4.3"; + message("851 %s: Name server timeout", shortenstring(name, 33)); - message("%s", hbuf); - if (CurEnv->e_message == NULL) - CurEnv->e_message = newstr(hbuf); } *statp = EX_TEMPFAIL; break; case HOST_NOT_FOUND: + case NO_DATA: *statp = EX_NOHOST; break; @@ -1291,34 +1480,16 @@ host_map_lookup(map, name, av, statp) *statp = EX_NOHOST; #endif s->s_namecanon.nc_stat = *statp; - if (*statp != EX_TEMPFAIL || UseNameServer) - return NULL; - - /* - ** Try to look it up in /etc/hosts - */ - - hp = gethostbyname(name); - if (hp == NULL) - { - /* no dice there either */ - s->s_namecanon.nc_stat = *statp = EX_NOHOST; - return NULL; - } - - s->s_namecanon.nc_stat = *statp = EX_OK; - cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); - s->s_namecanon.nc_cname = newstr(cp); - return cp; + return NULL; } } if ((cp = strchr(name, ']')) == NULL) return (NULL); *cp = '\0'; - in_addr = inet_addr(&name[1]); + in_addr.s_addr = inet_addr(&name[1]); /* nope -- ask the name server */ - hp = gethostbyaddr((char *)&in_addr, sizeof(struct in_addr), AF_INET); + hp = sm_gethostbyaddr((char *)&in_addr, INADDRSZ, AF_INET); s->s_namecanon.nc_errno = errno; #if NAMED_BIND s->s_namecanon.nc_herrno = h_errno; @@ -1331,7 +1502,7 @@ host_map_lookup(map, name, av, statp) } /* found a match -- copy out */ - cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), av); + cp = map_rewrite(map, (char *) hp->h_name, strlen(hp->h_name), av); s->s_namecanon.nc_stat = *statp = EX_OK; s->s_namecanon.nc_cname = newstr(cp); return cp; @@ -1346,6 +1517,10 @@ host_map_lookup(map, name, av, statp) ** A printable version of that sockaddr. */ +#if NETLINK +# include <net/if_dl.h> +#endif + char * anynet_ntoa(sap) register SOCKADDR *sap; @@ -1363,8 +1538,7 @@ anynet_ntoa(sap) switch (sap->sa.sa_family) { -#ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ -#ifdef NETUNIX +#if NETUNIX case AF_UNIX: if (sap->sunix.sun_path[0] != '\0') sprintf(buf, "[UNIX: %.64s]", sap->sunix.sun_path); @@ -1372,16 +1546,22 @@ anynet_ntoa(sap) sprintf(buf, "[UNIX: localhost]"); return buf; #endif -#endif -#ifdef NETINET +#if NETINET case AF_INET: - return inet_ntoa(((struct sockaddr_in *) sap)->sin_addr); + return inet_ntoa(sap->sin.sin_addr); #endif +#if NETLINK + case AF_LINK: + sprintf(buf, "[LINK: %s]", + link_ntoa((struct sockaddr_dl *) &sap->sa)); + return buf; +#endif default: - /* this case is only to ensure syntactic correctness */ - break; + /* this case is needed when nothing is #defined */ + /* in order to keep the switch syntactically correct */ + break; } /* unknown family -- just dump bytes */ @@ -1424,30 +1604,28 @@ hostnamebyanyaddr(sap) switch (sap->sa.sa_family) { -#ifdef NETINET +#if NETINET case AF_INET: - hp = gethostbyaddr((char *) &sap->sin.sin_addr, - sizeof sap->sin.sin_addr, + hp = sm_gethostbyaddr((char *) &sap->sin.sin_addr, + INADDRSZ, AF_INET); break; #endif -#ifdef NETISO +#if NETISO case AF_ISO: - hp = gethostbyaddr((char *) &sap->siso.siso_addr, + hp = sm_gethostbyaddr((char *) &sap->siso.siso_addr, sizeof sap->siso.siso_addr, AF_ISO); break; #endif -#ifdef MAYBENEXTRELEASE /*** UNTESTED *** UNTESTED *** UNTESTED ***/ case AF_UNIX: hp = NULL; break; -#endif default: - hp = gethostbyaddr(sap->sa.sa_data, + hp = sm_gethostbyaddr(sap->sa.sa_data, sizeof sap->sa.sa_data, sap->sa.sa_family); break; @@ -1458,13 +1636,13 @@ hostnamebyanyaddr(sap) #endif /* NAMED_BIND */ if (hp != NULL) - return hp->h_name; + return (char *) hp->h_name; else { /* produce a dotted quad */ - static char buf[512]; + static char buf[203]; - (void) sprintf(buf, "[%s]", anynet_ntoa(sap)); + (void) sprintf(buf, "[%.200s]", anynet_ntoa(sap)); return buf; } } @@ -1548,7 +1726,7 @@ host_map_lookup(map, name, avp, statp) { register struct hostent *hp; - hp = gethostbyname(name); + hp = sm_gethostbyname(name); if (hp != NULL) return hp->h_name; *statp = EX_NOHOST; diff --git a/usr.sbin/sendmail/src/deliver.c b/usr.sbin/sendmail/src/deliver.c index 437b1ad..51367ce 100644 --- a/usr.sbin/sendmail/src/deliver.c +++ b/usr.sbin/sendmail/src/deliver.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,20 +33,20 @@ */ #ifndef lint -static char sccsid[] = "@(#)deliver.c 8.84.1.4 (Berkeley) 3/28/95"; +static char sccsid[] = "@(#)deliver.c 8.185 (Berkeley) 11/18/95"; #endif /* not lint */ #include "sendmail.h" -#include <netdb.h> #include <errno.h> #if NAMED_BIND -#include <arpa/nameser.h> #include <resolv.h> extern int h_errno; #endif +#ifdef SMTP extern char SmtpError[]; +#endif /* ** SENDALL -- actually send all the messages. @@ -66,6 +66,7 @@ extern char SmtpError[]; ** appropriate action. */ +void sendall(e, mode) ENVELOPE *e; char mode; @@ -75,7 +76,10 @@ sendall(e, mode) int otherowners; register ENVELOPE *ee; ENVELOPE *splitenv = NULL; - bool announcequeueup; + bool oldverbose = Verbose; + bool somedeliveries = FALSE; + int pid; + extern void sendenvelope(); /* ** If we have had global, fatal errors, don't bother sending @@ -96,19 +100,20 @@ sendall(e, mode) if (mode == SM_DEFAULT) { mode = e->e_sendmode; - if (mode != SM_VERIFY && + if (mode != SM_VERIFY && mode != SM_DEFER && shouldqueue(e->e_msgpriority, e->e_ctime)) mode = SM_QUEUE; - announcequeueup = mode == SM_QUEUE; } - else - announcequeueup = FALSE; if (tTd(13, 1)) { + extern void printenvflags(); + printf("\n===== SENDALL: mode %c, id %s, e_from ", mode, e->e_id); printaddr(&e->e_from, FALSE); + printf("\te_flags = "); + printenvflags(e); printf("sendqueue:\n"); printaddr(e->e_sendqueue, TRUE); } @@ -124,12 +129,15 @@ sendall(e, mode) if (e->e_hopcount > MaxHopCount) { errno = 0; - queueup(e, TRUE, announcequeueup); +#ifdef QUEUE + queueup(e, mode == SM_QUEUE || mode == SM_DEFER); +#endif e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE; - syserr("554 too many hops %d (%d max): from %s via %s, to %s", + syserr("554 Too many hops %d (%d max): from %s via %s, to %s", e->e_hopcount, MaxHopCount, e->e_from.q_paddr, RealHostName == NULL ? "localhost" : RealHostName, e->e_sendqueue->q_paddr); + e->e_sendqueue->q_status = "5.4.6"; return; } @@ -151,7 +159,7 @@ sendall(e, mode) printaddr(&e->e_from, FALSE); } e->e_from.q_flags |= QDONTSEND; - (void) recipient(&e->e_from, &e->e_sendqueue, e); + (void) recipient(&e->e_from, &e->e_sendqueue, 0, e); } /* @@ -185,8 +193,17 @@ sendall(e, mode) for (q = e->e_sendqueue; q != NULL; q = q->q_next) { + if (tTd(13, 30)) + { + printf("Checking "); + printaddr(q, FALSE); + } if (bitset(QDONTSEND, q->q_flags)) + { + if (tTd(13, 30)) + printf(" ... QDONTSEND\n"); continue; + } if (q->q_owner != NULL) { @@ -210,6 +227,35 @@ sendall(e, mode) { otherowners++; } + + /* + ** If this mailer is expensive, and if we don't + ** want to make connections now, just mark these + ** addresses and return. This is useful if we + ** want to batch connections to reduce load. This + ** will cause the messages to be queued up, and a + ** daemon will come along to send the messages later. + */ + + if (bitset(QBADADDR|QQUEUEUP, q->q_flags)) + { + if (tTd(13, 30)) + printf(" ... QBADADDR|QQUEUEUP\n"); + continue; + } + if (NoConnect && !Verbose && + bitnset(M_EXPENSIVE, q->q_mailer->m_flags)) + { + if (tTd(13, 30)) + printf(" ... expensive\n"); + q->q_flags |= QQUEUEUP; + } + else + { + if (tTd(13, 30)) + printf(" ... deliverable\n"); + somedeliveries = TRUE; + } } if (owner != NULL && otherowners > 0) @@ -233,7 +279,7 @@ sendall(e, mode) ee->e_header = copyheader(e->e_header); ee->e_sendqueue = copyqueue(e->e_sendqueue); ee->e_errorqueue = copyqueue(e->e_errorqueue); - ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS|EF_SENDRECEIPT); + ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS|EF_SENDRECEIPT|EF_RET_PARAM); ee->e_flags |= EF_NORECEIPT; setsender(owner, ee, NULL, TRUE); if (tTd(13, 5)) @@ -244,33 +290,61 @@ sendall(e, mode) ee->e_from.q_flags |= QDONTSEND; ee->e_dfp = NULL; ee->e_xfp = NULL; - ee->e_df = NULL; ee->e_errormode = EM_MAIL; ee->e_sibling = splitenv; splitenv = ee; for (q = e->e_sendqueue; q != NULL; q = q->q_next) + { if (q->q_owner == owner) { q->q_flags |= QDONTSEND; q->q_flags &= ~QQUEUEUP; } + } for (q = ee->e_sendqueue; q != NULL; q = q->q_next) + { if (q->q_owner != owner) { q->q_flags |= QDONTSEND; q->q_flags &= ~QQUEUEUP; } + else + { + /* clear DSN parameters */ + q->q_flags &= ~(QHASNOTIFY|QPINGONSUCCESS); + q->q_flags |= QPINGONFAILURE|QPINGONDELAY; + } + } - if (e->e_df != NULL && mode != SM_VERIFY) + if (mode != SM_VERIFY && bitset(EF_HAS_DF, e->e_flags)) { + char df1buf[20], df2buf[20]; + ee->e_dfp = NULL; - ee->e_df = queuename(ee, 'd'); - ee->e_df = newstr(ee->e_df); - if (link(e->e_df, ee->e_df) < 0) + strcpy(df1buf, queuename(e, 'd')); + strcpy(df2buf, queuename(ee, 'd')); + if (link(df1buf, df2buf) < 0) { + int saverrno = errno; + syserr("sendall: link(%s, %s)", - e->e_df, ee->e_df); + df1buf, df2buf); + if (saverrno == EEXIST) + { + if (unlink(df2buf) < 0) + { + syserr("!sendall: unlink(%s): permanent", + df2buf); + /*NOTREACHED*/ + } + if (link(df1buf, df2buf) < 0) + { + syserr("!sendall: link(%s, %s): permanent", + df1buf, df2buf); + /*NOTREACHED*/ + } + } } } #ifdef LOG @@ -294,65 +368,33 @@ sendall(e, mode) e->e_flags |= EF_NORECEIPT; } + /* if nothing to be delivered, just queue up everything */ + if (!somedeliveries && mode != SM_QUEUE && mode != SM_DEFER && + mode != SM_VERIFY) + { + if (tTd(13, 29)) + printf("No deliveries: auto-queuing\n"); + mode = SM_QUEUE; + } + # ifdef QUEUE - if ((mode == SM_QUEUE || mode == SM_FORK || + if ((mode == SM_QUEUE || mode == SM_DEFER || mode == SM_FORK || (mode != SM_VERIFY && SuperSafe)) && !bitset(EF_INQUEUE, e->e_flags)) { /* be sure everything is instantiated in the queue */ - queueup(e, TRUE, announcequeueup); + queueup(e, mode == SM_QUEUE || mode == SM_DEFER); for (ee = splitenv; ee != NULL; ee = ee->e_sibling) - queueup(ee, TRUE, announcequeueup); + queueup(ee, mode == SM_QUEUE || mode == SM_DEFER); } #endif /* QUEUE */ - if (splitenv != NULL) - { - if (tTd(13, 1)) - { - printf("\nsendall: Split queue; remaining queue:\n"); - printaddr(e->e_sendqueue, TRUE); - } - - for (ee = splitenv; ee != NULL; ee = ee->e_sibling) - { - CurEnv = ee; - if (mode != SM_VERIFY) - openxscript(ee); - sendenvelope(ee, mode); - dropenvelope(ee); - } - - CurEnv = e; - } - sendenvelope(e, mode); -} - -sendenvelope(e, mode) - register ENVELOPE *e; - char mode; -{ - bool oldverbose; - int pid; - register ADDRESS *q; - char *qf; - char *id; - /* - ** If we have had global, fatal errors, don't bother sending - ** the message at all if we are in SMTP mode. Local errors - ** (e.g., a single address failing) will still cause the other - ** addresses to be sent. + ** If we belong in background, fork now. */ - if (bitset(EF_FATALERRS, e->e_flags) && - (OpMode == MD_SMTP || OpMode == MD_DAEMON)) - { - e->e_flags |= EF_CLRQUEUE; - return; - } - - oldverbose = Verbose; + if (tTd(13, 20)) + printf("sendall: final mode = %c\n", mode); switch (mode) { case SM_VERIFY: @@ -360,8 +402,10 @@ sendenvelope(e, mode) break; case SM_QUEUE: + case SM_DEFER: queueonly: - e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; + if (e->e_nrcpts > 0) + e->e_flags |= EF_INQUEUE; return; case SM_FORK: @@ -376,15 +420,17 @@ sendenvelope(e, mode) ** then restart from scratch in the child. */ - /* save id for future use */ - id = e->e_id; + { + /* save id for future use */ + char *qid = e->e_id; - /* now drop the envelope in the parent */ - e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; - dropenvelope(e); + /* now drop the envelope in the parent */ + e->e_flags |= EF_INQUEUE; + dropenvelope(e); - /* and reacquire in the child */ - (void) dowork(id, TRUE, FALSE, e); + /* and reacquire in the child */ + (void) dowork(qid, TRUE, FALSE, e); + } return; @@ -400,15 +446,16 @@ sendenvelope(e, mode) /* be sure we leave the temp files to our child */ /* can't call unlockqueue to avoid unlink of xfp */ if (e->e_lockfp != NULL) - (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); + (void) xfclose(e->e_lockfp, "sendenvelope lockfp", e->e_id); e->e_lockfp = NULL; /* close any random open files in the envelope */ closexscript(e); if (e->e_dfp != NULL) - (void) xfclose(e->e_dfp, "sendenvelope", e->e_df); + (void) xfclose(e->e_dfp, "sendenvelope dfp", e->e_id); e->e_dfp = NULL; - e->e_id = e->e_df = NULL; + e->e_id = NULL; + e->e_flags &= ~EF_HAS_DF; /* catch intermediate zombie */ (void) waitfor(pid); @@ -426,7 +473,7 @@ sendenvelope(e, mode) /* prevent parent from waiting if there was an error */ if (pid < 0) { - e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; + e->e_flags |= EF_INQUEUE; finis(); } @@ -447,6 +494,64 @@ sendenvelope(e, mode) break; } + if (splitenv != NULL) + { + if (tTd(13, 2)) + { + printf("\nsendall: Split queue; remaining queue:\n"); + printaddr(e->e_sendqueue, TRUE); + } + + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) + { + CurEnv = ee; + if (mode != SM_VERIFY) + openxscript(ee); + sendenvelope(ee, mode); + dropenvelope(ee); + } + + CurEnv = e; + } + sendenvelope(e, mode); + Verbose = oldverbose; + if (mode == SM_FORK) + finis(); +} + +void +sendenvelope(e, mode) + register ENVELOPE *e; + char mode; +{ + register ADDRESS *q; + bool didany; + + if (tTd(13, 10)) + printf("sendenvelope(%s) e_flags=0x%x\n", + e->e_id == NULL ? "[NOQUEUE]" : e->e_id, + e->e_flags); +#ifdef LOG + if (LogLevel > 80) + syslog(LOG_DEBUG, "%s: sendenvelope, flags=0x%x", + e->e_id == NULL ? "[NOQUEUE]" : e->e_id, + e->e_flags); +#endif + + /* + ** If we have had global, fatal errors, don't bother sending + ** the message at all if we are in SMTP mode. Local errors + ** (e.g., a single address failing) will still cause the other + ** addresses to be sent. + */ + + if (bitset(EF_FATALERRS, e->e_flags) && + (OpMode == MD_SMTP || OpMode == MD_DAEMON)) + { + e->e_flags |= EF_CLRQUEUE; + return; + } + /* ** Run through the list and send everything. ** @@ -456,14 +561,15 @@ sendenvelope(e, mode) e->e_nsent = 0; e->e_flags |= EF_GLOBALERRS; + didany = FALSE; /* now run through the queue */ for (q = e->e_sendqueue; q != NULL; q = q->q_next) { -#ifdef XDEBUG +#if XDEBUG char wbuf[MAXNAME + 20]; - (void) sprintf(wbuf, "sendall(%s)", q->q_paddr); + (void) sprintf(wbuf, "sendall(%.*s)", MAXNAME, q->q_paddr); checkfd012(wbuf); #endif if (mode == SM_VERIFY) @@ -491,21 +597,23 @@ sendenvelope(e, mode) if (e->e_nsent >= CheckpointInterval) { - queueup(e, TRUE, FALSE); + queueup(e, FALSE); e->e_nsent = 0; } # endif /* QUEUE */ (void) deliver(e, q); + didany = TRUE; } } - Verbose = oldverbose; + if (didany) + { + e->e_dtime = curtime(); + e->e_ntries++; + } -#ifdef XDEBUG +#if XDEBUG checkfd012("end of sendenvelope"); #endif - - if (mode == SM_FORK) - finis(); } /* ** DOFORK -- do a fork, retrying a couple of times on failure. @@ -563,9 +671,10 @@ sendenvelope(e, mode) ** returns twice, once in parent and once in child. */ +int dofork() { - register int pid; + register int pid = -1; DOFORK(fork); return (pid); @@ -592,6 +701,7 @@ dofork() ** The standard input is passed off to someone. */ +int deliver(e, firstto) register ENVELOPE *e; ADDRESS *firstto; @@ -602,22 +712,24 @@ deliver(e, firstto) register char **mvp; register char *p; register MAILER *m; /* mailer for this recipient */ - ADDRESS *ctladdr; - register MCI *mci; + ADDRESS *volatile ctladdr; + register MCI *volatile mci; register ADDRESS *to = firstto; - bool clever = FALSE; /* running user smtp to this mailer */ - ADDRESS *tochain = NULL; /* chain of users in this mailer call */ + volatile bool clever = FALSE; /* running user smtp to this mailer */ + ADDRESS *volatile tochain = NULL; /* users chain in this mailer call */ int rcode; /* response code */ char *firstsig; /* signature of firstto */ - int pid; - char *curhost; + int pid = -1; + char *volatile curhost; + time_t xstart; int mpvect[2]; int rpvect[2]; char *pv[MAXPV+1]; char tobuf[TOBUFSIZE]; /* text line of to people */ - char buf[MAXNAME]; - char rpathbuf[MAXNAME]; /* translated return path */ + char buf[MAXNAME + 1]; + char rpathbuf[MAXNAME + 1]; /* translated return path */ extern int checkcompat(); + extern void markfailure __P((ENVELOPE *, ADDRESS *, MCI *, int)); errno = 0; if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) @@ -636,7 +748,10 @@ deliver(e, firstto) host = to->q_host; CurEnv = e; /* just in case */ e->e_statmsg = NULL; +#ifdef SMTP SmtpError[0] = '\0'; +#endif + xstart = curtime(); if (tTd(10, 1)) printf("\n--deliver, id=%s, mailer=%s, host=`%s', first user=`%s'\n", @@ -645,33 +760,6 @@ deliver(e, firstto) printopenfds(FALSE); /* - ** If this mailer is expensive, and if we don't want to make - ** connections now, just mark these addresses and return. - ** This is useful if we want to batch connections to - ** reduce load. This will cause the messages to be - ** queued up, and a daemon will come along to send the - ** messages later. - ** This should be on a per-mailer basis. - */ - - if (NoConnect && bitnset(M_EXPENSIVE, m->m_flags) && !Verbose) - { - for (; to != NULL; to = to->q_next) - { - if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || - to->q_mailer != m) - continue; - to->q_flags |= QQUEUEUP; - e->e_to = to->q_paddr; - message("queued"); - if (LogLevel > 8) - logdelivery(m, NULL, "queued", NULL, e); - } - e->e_to = NULL; - return (0); - } - - /* ** Do initial argv setup. ** Insert the mailer name. Notice that $x expansion is ** NOT done on the mailer name. Then, if the mailer has @@ -684,7 +772,11 @@ deliver(e, firstto) /* rewrite from address, using rewriting rules */ rcode = EX_OK; - (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m, + if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags)) + p = e->e_sender; + else + p = e->e_from.q_paddr; + (void) strcpy(rpathbuf, remotename(p, m, RF_SENDERADDR|RF_CANONICAL, &rcode, e)); define('g', rpathbuf, e); /* translated return path */ @@ -726,7 +818,7 @@ deliver(e, firstto) break; /* this entry is safe -- go ahead and process it */ - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV - 3]) { @@ -788,11 +880,15 @@ deliver(e, firstto) } /* compute effective uid/gid when sending */ - /* XXX perhaps this should be to->q_mailer != LocalMailer ?? */ - /* XXX perhaps it should be a mailer flag? */ - if (to->q_mailer == ProgMailer || to->q_mailer == FileMailer) + if (bitnset(M_RUNASRCPT, to->q_mailer->m_flags)) ctladdr = getctladdr(to); + if (tTd(10, 2)) + { + printf("ctladdr="); + printaddr(ctladdr, FALSE); + } + user = to->q_user; e->e_to = to->q_paddr; if (tTd(10, 5)) @@ -809,16 +905,20 @@ deliver(e, firstto) if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) { - NoReturn = TRUE; + e->e_flags |= EF_NO_BODY_RETN; + to->q_status = "5.2.3"; usrerr("552 Message is too large; %ld bytes max", m->m_maxsize); - giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e); + giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, xstart, e); continue; } +#if NAMED_BIND + h_errno = 0; +#endif rcode = checkcompat(to, e); if (rcode != EX_OK) { - markfailure(e, to, rcode); - giveresponse(rcode, m, NULL, ctladdr, e); + markfailure(e, to, NULL, rcode); + giveresponse(rcode, m, NULL, ctladdr, xstart, e); continue; } @@ -860,12 +960,25 @@ deliver(e, firstto) ** with the others, so we fudge on the To person. */ - if (m == FileMailer) + if (strcmp(m->m_mailer, "[FILE]") == 0) { - rcode = mailfile(user, ctladdr, e); - giveresponse(rcode, m, NULL, ctladdr, e); + rcode = mailfile(user, ctladdr, SFF_CREAT, e); + giveresponse(rcode, m, NULL, ctladdr, xstart, e); + e->e_nsent++; if (rcode == EX_OK) + { to->q_flags |= QSENT; + if (bitnset(M_LOCALMAILER, m->m_flags) && + (e->e_receiptto != NULL || + bitset(QPINGONSUCCESS, to->q_flags))) + { + to->q_flags |= QDELIVERED; + to->q_status = "2.1.5"; + fprintf(e->e_xfp, "%s... Successfully delivered\n", + to->q_paddr); + } + } + to->q_statdate = curtime(); continue; } @@ -893,7 +1006,7 @@ deliver(e, firstto) if (!clever) { - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV - 2]) { @@ -919,7 +1032,7 @@ deliver(e, firstto) while (!clever && *++mvp != NULL) { - expand(*mvp, buf, &buf[sizeof buf - 1], e); + expand(*mvp, buf, sizeof buf, e); *pvp++ = newstr(buf); if (pvp >= &pv[MAXPV]) syserr("554 deliver: pv overflow after $u for %s", pv[0]); @@ -935,7 +1048,7 @@ deliver(e, firstto) */ /*XXX this seems a bit wierd */ - if (ctladdr == NULL && m != ProgMailer && + if (ctladdr == NULL && m != ProgMailer && m != FileMailer && bitset(QGOODUID, e->e_from.q_flags)) ctladdr = &e->e_from; @@ -950,6 +1063,9 @@ deliver(e, firstto) printav(pv); } errno = 0; +#if NAMED_BIND + h_errno = 0; +#endif CurHostName = NULL; @@ -966,16 +1082,31 @@ deliver(e, firstto) SmtpPhase = NULL; mci = NULL; -#ifdef XDEBUG +#if XDEBUG { char wbuf[MAXLINE]; /* make absolutely certain 0, 1, and 2 are in use */ - sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name); + sprintf(wbuf, "%s... openmailer(%s)", + shortenstring(e->e_to, 203), m->m_name); checkfd012(wbuf); } #endif + /* check for 8-bit available */ + if (bitset(EF_HAS8BIT, e->e_flags) && + bitnset(M_7BITS, m->m_flags) && + (bitset(EF_DONT_MIME, e->e_flags) || + !(bitset(MM_MIME8BIT, MimeMode) || + (bitset(EF_IS_MIME, e->e_flags) && + bitset(MM_CVTMIME, MimeMode))))) + { + usrerr("554 Cannot send 8-bit data to 7-bit destination"); + rcode = EX_DATAERR; + e->e_status = "5.6.3"; + goto give_up; + } + /* check for Local Person Communication -- not for mortals!!! */ if (strcmp(m->m_mailer, "[LPC]") == 0) { @@ -991,7 +1122,7 @@ deliver(e, firstto) { #ifdef DAEMON register int i; - register u_short port; + register volatile u_short port = 0; if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0') { @@ -1017,14 +1148,23 @@ deliver(e, firstto) goto give_up; } if (pv[2] != NULL) - port = atoi(pv[2]); - else - port = 0; + { + port = htons(atoi(pv[2])); + if (port == 0) + { + struct servent *sp = getservbyname(pv[2], "tcp"); + + if (sp == NULL) + syserr("Service %s unknown", pv[2]); + else + port = sp->s_port; + } + } tryhost: while (*curhost != '\0') { register char *p; - static char hostbuf[MAXNAME]; + static char hostbuf[MAXNAME + 1]; /* pull the next host from the signature */ p = strchr(curhost, ':'); @@ -1053,6 +1193,9 @@ tryhost: mci_dump(mci, FALSE); } CurHostName = mci->mci_host; + message("Using cached %sSMTP connection to %s via %s...", + bitset(MCIF_ESMTP, mci->mci_flags) ? "E" : "", + hostbuf, m->m_name); break; } mci->mci_mailer = m; @@ -1061,10 +1204,11 @@ tryhost: /* try the connection */ setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); - message("Connecting to %s (%s)...", + message("Connecting to %s via %s...", hostbuf, m->m_name); i = makeconnection(hostbuf, port, mci, bitnset(M_SECURE_PORT, m->m_flags)); + mci->mci_lastuse = curtime(); mci->mci_exitstat = i; mci->mci_errno = errno; #if NAMED_BIND @@ -1105,6 +1249,14 @@ tryhost: } else { + /* flush any expired connections */ + (void) mci_scan(NULL); + + /* announce the connection to verbose listeners */ + if (host == NULL || host[0] == '\0') + message("Connecting to %s...", m->m_name); + else + message("Connecting to %s via %s...", host, m->m_name); if (TrafficLogFile != NULL) { char **av; @@ -1119,7 +1271,7 @@ tryhost: if (pipe(mpvect) < 0) { syserr("%s... openmailer(%s): pipe (to mailer)", - e->e_to, m->m_name); + shortenstring(e->e_to, 203), m->m_name); if (tTd(11, 1)) printf("openmailer: NULL\n"); rcode = EX_OSERR; @@ -1127,10 +1279,11 @@ tryhost: } /* if this mailer speaks smtp, create a return pipe */ +#ifdef SMTP if (clever && pipe(rpvect) < 0) { syserr("%s... openmailer(%s): pipe (from mailer)", - e->e_to, m->m_name); + shortenstring(e->e_to, 203), m->m_name); (void) close(mpvect[0]); (void) close(mpvect[1]); if (tTd(11, 1)) @@ -1138,6 +1291,7 @@ tryhost: rcode = EX_OSERR; goto give_up; } +#endif /* ** Actually fork the mailer process. @@ -1159,14 +1313,16 @@ tryhost: { /* failure */ syserr("%s... openmailer(%s): cannot fork", - e->e_to, m->m_name); + shortenstring(e->e_to, 203), m->m_name); (void) close(mpvect[0]); (void) close(mpvect[1]); +#ifdef SMTP if (clever) { (void) close(rpvect[0]); (void) close(rpvect[1]); } +#endif if (tTd(11, 1)) printf("openmailer: NULL\n"); rcode = EX_OSERR; @@ -1176,9 +1332,7 @@ tryhost: { int i; int saveerrno; - char **ep; - char *env[MAXUSERENVIRON]; - extern char **environ; + struct stat stb; extern int DtableSize; if (e->e_lockfp != NULL) @@ -1189,23 +1343,61 @@ tryhost: (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGTERM, SIG_DFL); - /* reset user and group */ - if (!bitnset(M_RESTR, m->m_flags)) + if (m != FileMailer || stat(tochain->q_user, &stb) < 0) + stb.st_mode = 0; + + /* tweak niceness */ + if (m->m_nice != 0) + nice(m->m_nice); + + /* reset group id */ + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + (void) setgid(m->m_gid); + else if (bitset(S_ISGID, stb.st_mode)) + (void) setgid(stb.st_gid); + else if (ctladdr != NULL && ctladdr->q_gid != 0) { - if (ctladdr == NULL || ctladdr->q_uid == 0) - { + if (!DontInitGroups) + (void) initgroups(ctladdr->q_ruser != NULL ? + ctladdr->q_ruser : ctladdr->q_user, + ctladdr->q_gid); + (void) setgid(ctladdr->q_gid); + } + else + { + if (!DontInitGroups) (void) initgroups(DefUser, DefGid); + if (m->m_gid == 0) (void) setgid(DefGid); + else + (void) setgid(m->m_gid); + } + + /* reset user id */ + endpwent(); + if (bitnset(M_SPECIFIC_UID, m->m_flags)) + { +#if USESETEUID + (void) seteuid(m->m_uid); +#else +# if HASSETREUID + (void) setreuid(-1, m->m_uid); +# else + if (m->m_uid != geteuid()) + (void) setuid(m->m_uid); +# endif +#endif + } + else if (bitset(S_ISUID, stb.st_mode)) + (void) setuid(stb.st_uid); + else if (ctladdr != NULL && ctladdr->q_uid != 0) + (void) setuid(ctladdr->q_uid); + else + { + if (m->m_uid == 0) (void) setuid(DefUid); - } else - { - (void) initgroups(ctladdr->q_ruser? - ctladdr->q_ruser: ctladdr->q_user, - ctladdr->q_gid); - (void) setgid(ctladdr->q_gid); - (void) setuid(ctladdr->q_uid); - } + (void) setuid(m->m_uid); } if (tTd(11, 2)) @@ -1216,14 +1408,14 @@ tryhost: if (m->m_execdir != NULL) { char *p, *q; - char buf[MAXLINE]; + char buf[MAXLINE + 1]; for (p = m->m_execdir; p != NULL; p = q) { q = strchr(p, ':'); if (q != NULL) *q = '\0'; - expand(p, buf, &buf[sizeof buf] - 1, e); + expand(p, buf, sizeof buf, e); if (q != NULL) *q++ = ':'; if (tTd(11, 20)) @@ -1235,13 +1427,15 @@ tryhost: } /* arrange to filter std & diag output of command */ +#ifdef SMTP if (clever) { (void) close(rpvect[0]); if (dup2(rpvect[1], STDOUT_FILENO) < 0) { syserr("%s... openmailer(%s): cannot dup pipe %d for stdout", - e->e_to, m->m_name, rpvect[1]); + shortenstring(e->e_to, 203), + m->m_name, rpvect[1]); _exit(EX_OSERR); } (void) close(rpvect[1]); @@ -1253,15 +1447,16 @@ tryhost: if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0) { syserr("%s... openmailer(%s): cannot dup xscript %d for stdout", - e->e_to, m->m_name, - fileno(e->e_xfp)); + shortenstring(e->e_to, 203), + m->m_name, fileno(e->e_xfp)); _exit(EX_OSERR); } } +#endif if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) { syserr("%s... openmailer(%s): cannot dup stdout for stderr", - e->e_to, m->m_name); + shortenstring(e->e_to, 203), m->m_name); _exit(EX_OSERR); } @@ -1270,7 +1465,8 @@ tryhost: if (dup2(mpvect[0], STDIN_FILENO) < 0) { syserr("%s... openmailer(%s): cannot dup pipe %d for stdin", - e->e_to, m->m_name, mpvect[0]); + shortenstring(e->e_to, 203), + m->m_name, mpvect[0]); _exit(EX_OSERR); } (void) close(mpvect[0]); @@ -1284,32 +1480,15 @@ tryhost: (void) fcntl(i, F_SETFD, j | 1); } - /* - ** Set up the mailer environment - ** TZ is timezone information. - ** SYSTYPE is Apollo software sys type (required). - ** ISP is Apollo hardware system type (required). - */ - - i = 0; - env[i++] = "AGENT=sendmail"; - for (ep = environ; *ep != NULL; ep++) - { - if (strncmp(*ep, "TZ=", 3) == 0 || - strncmp(*ep, "ISP=", 4) == 0 || - strncmp(*ep, "SYSTYPE=", 8) == 0) - env[i++] = *ep; - } - env[i++] = NULL; - /* run disconnected from terminal */ (void) setsid(); /* try to execute the mailer */ - execve(m->m_mailer, pv, env); + execve(m->m_mailer, (ARGV_T) pv, (ARGV_T) UserEnviron); saveerrno = errno; syserr("Cannot exec %s", m->m_mailer); - if (m == LocalMailer || transienterror(saveerrno)) + if (bitnset(M_LOCALMAILER, m->m_flags) || + transienterror(saveerrno)) _exit(EX_OSERR); _exit(EX_UNAVAILABLE); } @@ -1330,14 +1509,17 @@ tryhost: syserr("deliver: cannot create mailer output channel, fd=%d", mpvect[1]); (void) close(mpvect[1]); +#ifdef SMTP if (clever) { (void) close(rpvect[0]); (void) close(rpvect[1]); } +#endif rcode = EX_OSERR; goto give_up; } +#ifdef SMTP if (clever) { (void) close(rpvect[1]); @@ -1354,6 +1536,7 @@ tryhost: } } else +#endif { mci->mci_flags |= MCIF_TEMP; mci->mci_in = NULL; @@ -1364,10 +1547,21 @@ tryhost: ** If we are in SMTP opening state, send initial protocol. */ + if (bitnset(M_7BITS, m->m_flags) && + (!clever || mci->mci_state == MCIS_CLOSED)) + mci->mci_flags |= MCIF_7BIT; +#ifdef SMTP if (clever && mci->mci_state != MCIS_CLOSED) - { smtpinit(m, mci, e); - } +#endif + + if (bitset(EF_HAS8BIT, e->e_flags) && + !bitset(EF_DONT_MIME, e->e_flags) && + bitnset(M_7BITS, m->m_flags)) + mci->mci_flags |= MCIF_CVT8TO7; + else + mci->mci_flags &= ~MCIF_CVT8TO7; + if (tTd(11, 1)) { printf("openmailer: "); @@ -1389,11 +1583,13 @@ tryhost: rcode, mci->mci_state, firstsig); rcode = EX_SOFTWARE; } - else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0') +#ifdef DAEMON + else if (curhost != NULL && *curhost != '\0') { /* try next MX site */ goto tryhost; } +#endif } else if (!clever) { @@ -1402,8 +1598,7 @@ tryhost: */ putfromline(mci, e); - (*e->e_puthdr)(mci, e); - putline("\n", mci); + (*e->e_puthdr)(mci, e->e_header, e); (*e->e_putbody)(mci, e, NULL); /* get the exit status */ @@ -1429,8 +1624,8 @@ tryhost: e->e_to = to->q_paddr; if ((i = smtprcpt(to, m, mci, e)) != EX_OK) { - markfailure(e, to, i); - giveresponse(i, m, mci, ctladdr, e); + markfailure(e, to, mci, i); + giveresponse(i, m, mci, ctladdr, xstart, e); } else { @@ -1494,21 +1689,40 @@ tryhost: give_up: if (tobuf[0] != '\0') - giveresponse(rcode, m, mci, ctladdr, e); + giveresponse(rcode, m, mci, ctladdr, xstart, e); for (to = tochain; to != NULL; to = to->q_tchain) { + /* see if address already marked */ + if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) + continue; + + /* mark bad addresses */ if (rcode != EX_OK) - markfailure(e, to, rcode); - else { - to->q_flags |= QSENT; - e->e_nsent++; - if (e->e_receiptto != NULL && - bitnset(M_LOCALMAILER, m->m_flags)) - { - fprintf(e->e_xfp, "%s... Successfully delivered\n", - to->q_paddr); - } + markfailure(e, to, mci, rcode); + continue; + } + + /* successful delivery */ + to->q_flags |= QSENT; + to->q_statdate = curtime(); + e->e_nsent++; + if (bitnset(M_LOCALMAILER, m->m_flags) && + (e->e_receiptto != NULL || + bitset(QPINGONSUCCESS, to->q_flags))) + { + to->q_flags |= QDELIVERED; + to->q_status = "2.1.5"; + fprintf(e->e_xfp, "%s... Successfully delivered\n", + to->q_paddr); + } + else if (bitset(QPINGONSUCCESS, to->q_flags) && + bitset(QPRIMARY, to->q_flags) && + !bitset(MCIF_DSN, mci->mci_flags)) + { + to->q_flags |= QRELAYED; + fprintf(e->e_xfp, "%s... relayed; expect no further notifications\n", + to->q_paddr); } } @@ -1516,13 +1730,14 @@ tryhost: ** Restore state and return. */ -#ifdef XDEBUG +#if XDEBUG { char wbuf[MAXLINE]; /* make absolutely certain 0, 1, and 2 are in use */ sprintf(wbuf, "%s... end of deliver(%s)", - e->e_to == NULL ? "NO-TO-LIST" : e->e_to, + e->e_to == NULL ? "NO-TO-LIST" + : shortenstring(e->e_to, 203), m->m_name); checkfd012(wbuf); } @@ -1538,6 +1753,7 @@ tryhost: ** Parameters: ** e -- the envelope we are sending. ** q -- the address to mark. +** mci -- mailer connection information. ** rcode -- the code signifying the particular failure. ** ** Returns: @@ -1549,12 +1765,14 @@ tryhost: ** the message will be queued, as appropriate. */ -markfailure(e, q, rcode) +void +markfailure(e, q, mci, rcode) register ENVELOPE *e; register ADDRESS *q; + register MCI *mci; int rcode; { - char buf[MAXLINE]; + char *stat = NULL; switch (rcode) { @@ -1571,6 +1789,71 @@ markfailure(e, q, rcode) q->q_flags |= QBADADDR; break; } + + /* find most specific error code possible */ + if (q->q_status == NULL && mci != NULL) + q->q_status = mci->mci_status; + if (q->q_status == NULL) + q->q_status = e->e_status; + if (q->q_status == NULL) + { + switch (rcode) + { + case EX_USAGE: + stat = "5.5.4"; + break; + + case EX_DATAERR: + stat = "5.5.2"; + break; + + case EX_NOUSER: + stat = "5.1.1"; + break; + + case EX_NOHOST: + stat = "5.1.2"; + break; + + case EX_NOINPUT: + case EX_CANTCREAT: + case EX_NOPERM: + stat = "5.3.0"; + break; + + case EX_UNAVAILABLE: + case EX_SOFTWARE: + case EX_OSFILE: + case EX_PROTOCOL: + case EX_CONFIG: + stat = "5.5.0"; + break; + + case EX_OSERR: + case EX_IOERR: + stat = "4.5.0"; + break; + + case EX_TEMPFAIL: + stat = "4.2.0"; + break; + } + if (stat != NULL) + q->q_status = stat; + } + + q->q_statdate = curtime(); + if (CurHostName != NULL && CurHostName[0] != '\0') + q->q_statmta = newstr(CurHostName); + if (rcode != EX_OK && q->q_rstatus == NULL && + q->q_mailer != NULL && q->q_mailer->m_diagtype != NULL && + strcasecmp(q->q_mailer->m_diagtype, "UNIX") == 0) + { + char buf[30]; + + (void) sprintf(buf, "%d", rcode); + q->q_rstatus = newstr(buf); + } } /* ** ENDMAILER -- Wait for mailer to terminate. @@ -1593,6 +1876,7 @@ markfailure(e, q, rcode) ** none. */ +int endmailer(mci, e, pv) register MCI *mci; register ENVELOPE *e; @@ -1656,6 +1940,8 @@ endmailer(mci, e, pv) ** response is given before the connection is made. ** ctladdr -- the controlling address for the recipient ** address(es). +** xstart -- the transaction start time, for computing +** transaction delays. ** e -- the current envelope. ** ** Returns: @@ -1666,11 +1952,13 @@ endmailer(mci, e, pv) ** ExitStat may be set. */ -giveresponse(stat, m, mci, ctladdr, e) +void +giveresponse(stat, m, mci, ctladdr, xstart, e) int stat; register MAILER *m; register MCI *mci; ADDRESS *ctladdr; + time_t xstart; ENVELOPE *e; { register const char *statmsg; @@ -1689,7 +1977,8 @@ giveresponse(stat, m, mci, ctladdr, e) statmsg = "250 Sent"; if (e->e_statmsg != NULL) { - (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg); + (void) sprintf(buf, "%s (%s)", + statmsg, shortenstring(e->e_statmsg, 403)); statmsg = buf; } } @@ -1773,7 +2062,7 @@ giveresponse(stat, m, mci, ctladdr, e) */ if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) - logdelivery(m, mci, &statmsg[4], ctladdr, e); + logdelivery(m, mci, &statmsg[4], ctladdr, xstart, e); if (tTd(11, 2)) printf("giveresponse: stat=%d, e->e_message=%s\n", @@ -1805,6 +2094,8 @@ giveresponse(stat, m, mci, ctladdr, e) ** log is occuring when no connection is active. ** stat -- the message to print for the status. ** ctladdr -- the controlling address for the to list. +** xstart -- the transaction start time, used for +** computing transaction delay. ** e -- the current envelope. ** ** Returns: @@ -1814,20 +2105,25 @@ giveresponse(stat, m, mci, ctladdr, e) ** none */ -logdelivery(m, mci, stat, ctladdr, e) +#define SPACELEFT(bp) (sizeof buf - ((bp) - buf)) + +void +logdelivery(m, mci, stat, ctladdr, xstart, e) MAILER *m; register MCI *mci; - char *stat; + const char *stat; ADDRESS *ctladdr; + time_t xstart; register ENVELOPE *e; { # ifdef LOG register char *bp; register char *p; int l; - char buf[512]; + char buf[1024]; # if (SYSLOG_BUFSIZE) >= 256 + /* ctladdr: max 106 bytes */ bp = buf; if (ctladdr != NULL) { @@ -1836,35 +2132,48 @@ logdelivery(m, mci, stat, ctladdr, e) bp += strlen(bp); if (bitset(QGOODUID, ctladdr->q_flags)) { - (void) sprintf(bp, " (%d/%d)", + (void) snprintf(bp, SPACELEFT(bp), " (%d/%d)", ctladdr->q_uid, ctladdr->q_gid); bp += strlen(bp); } } - (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); + /* delay & xdelay: max 41 bytes */ + snprintf(bp, SPACELEFT(bp), ", delay=%s", + pintvl(curtime() - e->e_ctime, TRUE)); bp += strlen(bp); + if (xstart != (time_t) 0) + { + snprintf(bp, SPACELEFT(bp), ", xdelay=%s", + pintvl(curtime() - xstart, TRUE)); + bp += strlen(bp); + } + + /* mailer: assume about 19 bytes (max 10 byte mailer name) */ if (m != NULL) { - (void) strcpy(bp, ", mailer="); - (void) strcat(bp, m->m_name); + snprintf(bp, SPACELEFT(bp), ", mailer=%s", m->m_name); bp += strlen(bp); } + /* relay: max 66 bytes for IPv4 addresses */ if (mci != NULL && mci->mci_host != NULL) { # ifdef DAEMON extern SOCKADDR CurHostAddr; # endif - (void) strcpy(bp, ", relay="); - (void) strcat(bp, mci->mci_host); + snprintf(bp, SPACELEFT(bp), ", relay=%s", + shortenstring(mci->mci_host, 40)); + bp += strlen(bp); # ifdef DAEMON - (void) strcat(bp, " ["); - (void) strcat(bp, anynet_ntoa(&CurHostAddr)); - (void) strcat(bp, "]"); + if (CurHostAddr.sa.sa_family != 0) + { + snprintf(bp, SPACELEFT(bp), " [%s]", + anynet_ntoa(&CurHostAddr)); + } # endif } else if (strcmp(stat, "queued") != 0) @@ -1873,8 +2182,8 @@ logdelivery(m, mci, stat, ctladdr, e) if (p != NULL && p[0] != '\0') { - (void) strcpy(bp, ", relay="); - (void) strcat(bp, p); + snprintf(bp, SPACELEFT(bp), ", relay=%s", + shortenstring(p, 40)); } } bp += strlen(bp); @@ -1889,6 +2198,7 @@ logdelivery(m, mci, stat, ctladdr, e) # define STATLEN 203 #endif + /* stat: max 210 bytes */ if ((bp - buf) > (sizeof buf - ((STATLEN) + 20))) { /* desperation move -- truncate data */ @@ -1901,10 +2211,11 @@ logdelivery(m, mci, stat, ctladdr, e) bp += strlen(bp); (void) strcpy(bp, shortenstring(stat, (STATLEN))); - + + /* id, to: max 13 + TOBUFSIZE bytes */ l = SYSLOG_BUFSIZE - 100 - strlen(buf); p = e->e_to; - while (strlen(p) >= l) + while (strlen(p) >= (SIZE_T) l) { register char *q = strchr(p + l, ','); @@ -1950,13 +2261,18 @@ logdelivery(m, mci, stat, ctladdr, e) bp = buf; sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); bp += strlen(bp); + if (xstart != (time_t) 0) + { + sprintf(bp, ", xdelay=%s", pintvl(curtime() - xstart, TRUE)); + bp += strlen(bp); + } if (m != NULL) { sprintf(bp, ", mailer=%s", m->m_name); bp += strlen(bp); } - syslog(LOG_INFO, "%s: %s", e->e_id, buf); + syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf); buf[0] = '\0'; if (mci != NULL && mci->mci_host != NULL) @@ -1965,12 +2281,11 @@ logdelivery(m, mci, stat, ctladdr, e) extern SOCKADDR CurHostAddr; # endif - sprintf(buf, "relay=%s", mci->mci_host); + sprintf(buf, "relay=%.100s", mci->mci_host); # ifdef DAEMON - (void) strcat(buf, " ["); - (void) strcat(buf, anynet_ntoa(&CurHostAddr)); - (void) strcat(buf, "]"); + if (CurHostAddr.sa.sa_family != 0) + sprintf(bp, " [%.100s]", anynet_ntoa(&CurHostAddr)); # endif } else if (strcmp(stat, "queued") != 0) @@ -1978,15 +2293,17 @@ logdelivery(m, mci, stat, ctladdr, e) char *p = macvalue('h', e); if (p != NULL && p[0] != '\0') - sprintf(buf, "relay=%s", p); + sprintf(buf, "relay=%.100s", p); } if (buf[0] != '\0') - syslog(LOG_INFO, "%s: %s", e->e_id, buf); + syslog(LOG_INFO, "%s: %.1000s", e->e_id, buf); syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63)); # endif /* short log buffer */ # endif /* LOG */ } + +#undef SPACELEFT /* ** PUTFROMLINE -- output a UNIX-style from line (or whatever) ** @@ -2008,23 +2325,23 @@ logdelivery(m, mci, stat, ctladdr, e) ** outputs some text to fp. */ +void putfromline(mci, e) register MCI *mci; ENVELOPE *e; { - char *template = "\201l\n"; + char *template = UnixFromLine; char buf[MAXLINE]; if (bitnset(M_NHDR, mci->mci_mailer->m_flags)) return; -# ifdef UGLYUUCP if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags)) { char *bang; char xbuf[MAXLINE]; - expand("\201g", buf, &buf[sizeof buf - 1], e); + expand("\201g", buf, sizeof buf, e); bang = strchr(buf, '!'); if (bang == NULL) { @@ -2034,13 +2351,13 @@ putfromline(mci, e) else { *bang++ = '\0'; - (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf); + (void) sprintf(xbuf, "From %.800s \201d remote from %.100s\n", + bang, buf); template = xbuf; } } -# endif /* UGLYUUCP */ - expand(template, buf, &buf[sizeof buf - 1], e); - putline(buf, mci); + expand(template, buf, sizeof buf, e); + putxline(buf, mci, PXLF_NOTHINGSPECIAL); } /* ** PUTBODY -- put the body of a message. @@ -2058,6 +2375,12 @@ putfromline(mci, e) ** The message is written onto fp. */ +/* values for output state variable */ +#define OS_HEAD 0 /* at beginning of line */ +#define OS_CR 1 /* read a carriage return */ +#define OS_INLINE 2 /* putting rest of line */ + +void putbody(mci, e, separator) register MCI *mci; register ENVELOPE *e; @@ -2069,45 +2392,244 @@ putbody(mci, e, separator) ** Output the body of the message */ + if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags)) + { + char *df = queuename(e, 'd'); + + e->e_dfp = fopen(df, "r"); + if (e->e_dfp == NULL) + syserr("putbody: Cannot open %s for %s from %s", + df, e->e_to, e->e_from.q_paddr); + } if (e->e_dfp == NULL) { - if (e->e_df != NULL) + if (bitset(MCIF_INHEADER, mci->mci_flags)) { - e->e_dfp = fopen(e->e_df, "r"); - if (e->e_dfp == NULL) - syserr("putbody: Cannot open %s for %s from %s", - e->e_df, e->e_to, e->e_from.q_paddr); + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; } + putline("<<< No Message Collected >>>", mci); + goto endofmessage; + } + if (e->e_dfino == (ino_t) 0) + { + struct stat stbuf; + + if (fstat(fileno(e->e_dfp), &stbuf) < 0) + e->e_dfino = -1; else - putline("<<< No Message Collected >>>", mci); + { + e->e_dfdev = stbuf.st_dev; + e->e_dfino = stbuf.st_ino; + } } - if (e->e_dfp != NULL) + rewind(e->e_dfp); + +#if MIME8TO7 + if (bitset(MCIF_CVT8TO7, mci->mci_flags)) { - rewind(e->e_dfp); - while (!ferror(mci->mci_out) && fgets(buf, sizeof buf, e->e_dfp) != NULL) + char *boundaries[MAXMIMENESTING + 1]; + + /* + ** Do 8 to 7 bit MIME conversion. + */ + + /* make sure it looks like a MIME message */ + if (hvalue("MIME-Version", e->e_header) == NULL) + putline("MIME-Version: 1.0", mci); + + if (hvalue("Content-Type", e->e_header) == NULL) { - if (buf[0] == 'F' && - bitnset(M_ESCFROM, mci->mci_mailer->m_flags) && - strncmp(buf, "From ", 5) == 0) - (void) putc('>', mci->mci_out); - if (buf[0] == '-' && buf[1] == '-' && separator != NULL) + sprintf(buf, "Content-Type: text/plain; charset=%s", + defcharset(e)); + putline(buf, mci); + } + + /* now do the hard work */ + boundaries[0] = NULL; + mime8to7(mci, e->e_header, e, boundaries, M87F_OUTER); + } + else +#endif + { + int ostate; + register char *bp; + register char *pbp; + register int c; + int padc; + char *buflim; + int pos = 0; + char peekbuf[10]; + + /* we can pass it through unmodified */ + if (bitset(MCIF_INHEADER, mci->mci_flags)) + { + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + } + + /* determine end of buffer; allow for short mailer lines */ + buflim = &buf[sizeof buf - 1]; + if (mci->mci_mailer->m_linelimit > 0 && + mci->mci_mailer->m_linelimit < sizeof buf - 1) + buflim = &buf[mci->mci_mailer->m_linelimit - 1]; + + /* copy temp file to output with mapping */ + ostate = OS_HEAD; + bp = buf; + pbp = peekbuf; + while (!ferror(mci->mci_out)) + { + register char *xp; + + if (pbp > peekbuf) + c = *--pbp; + else if ((c = getc(e->e_dfp)) == EOF) + break; + if (bitset(MCIF_7BIT, mci->mci_flags)) + c &= 0x7f; + switch (ostate) { - /* possible separator */ - int sl = strlen(separator); + case OS_HEAD: + if (c != '\r' && c != '\n' && bp < buflim) + { + *bp++ = c; + break; + } + + /* check beginning of line for special cases */ + *bp = '\0'; + pos = 0; + padc = EOF; + if (buf[0] == 'F' && + bitnset(M_ESCFROM, mci->mci_mailer->m_flags) && + strncmp(buf, "From ", 5) == 0) + { + padc = '>'; + } + if (buf[0] == '-' && buf[1] == '-' && + separator != NULL) + { + /* possible separator */ + int sl = strlen(separator); + + if (strncmp(&buf[2], separator, sl) == 0) + padc = ' '; + } + if (buf[0] == '.' && + bitnset(M_XDOT, mci->mci_mailer->m_flags)) + { + padc = '.'; + } + + /* now copy out saved line */ + if (TrafficLogFile != NULL) + { + fprintf(TrafficLogFile, "%05d >>> ", getpid()); + if (padc != EOF) + putc(padc, TrafficLogFile); + for (xp = buf; xp < bp; xp++) + putc(*xp, TrafficLogFile); + if (c == '\n') + fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + if (padc != EOF) + { + putc(padc, mci->mci_out); + pos++; + } + for (xp = buf; xp < bp; xp++) + putc(*xp, mci->mci_out); + if (c == '\n') + { + fputs(mci->mci_mailer->m_eol, + mci->mci_out); + pos = 0; + } + else + { + pos += bp - buf; + if (c != '\r') + *pbp++ = c; + } + bp = buf; - if (strncmp(&buf[2], separator, sl) == 0) - (void) putc(' ', mci->mci_out); + /* determine next state */ + if (c == '\n') + ostate = OS_HEAD; + else if (c == '\r') + ostate = OS_CR; + else + ostate = OS_INLINE; + continue; + + case OS_CR: + if (c == '\n') + { + /* got CRLF */ + fputs(mci->mci_mailer->m_eol, mci->mci_out); + if (TrafficLogFile != NULL) + { + fputs(mci->mci_mailer->m_eol, + TrafficLogFile); + } + ostate = OS_HEAD; + continue; + } + + /* had a naked carriage return */ + *pbp++ = c; + c = '\r'; + goto putch; + + case OS_INLINE: + if (c == '\r') + { + ostate = OS_CR; + continue; + } +putch: + if (mci->mci_mailer->m_linelimit > 0 && + pos > mci->mci_mailer->m_linelimit && + c != '\n') + { + putc('!', mci->mci_out); + fputs(mci->mci_mailer->m_eol, mci->mci_out); + if (TrafficLogFile != NULL) + { + fprintf(TrafficLogFile, "!%s", + mci->mci_mailer->m_eol); + } + ostate = OS_HEAD; + *pbp++ = c; + continue; + } + if (TrafficLogFile != NULL) + putc(c, TrafficLogFile); + putc(c, mci->mci_out); + pos++; + ostate = c == '\n' ? OS_HEAD : OS_INLINE; + break; } - putline(buf, mci); } - if (ferror(e->e_dfp)) + /* make sure we are at the beginning of a line */ + if (bp > buf) { - syserr("putbody: %s: read error", e->e_df); - ExitStat = EX_IOERR; + *bp = '\0'; + fputs(buf, mci->mci_out); + fputs(mci->mci_mailer->m_eol, mci->mci_out); } } + if (ferror(e->e_dfp)) + { + syserr("putbody: df%s: read error", e->e_id); + ExitStat = EX_IOERR; + } + +endofmessage: /* some mailers want extra blank line at end of message */ if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) && buf[0] != '\0' && buf[0] != '\n') @@ -2139,6 +2661,8 @@ putbody(mci, e, separator) ** filename -- the name of the file to send to. ** ctladdr -- the controlling address header -- includes ** the userid/groupid to be when sending. +** sfflags -- flags for opening. +** e -- the current envelope. ** ** Returns: ** The exit code associated with the operation. @@ -2147,13 +2671,15 @@ putbody(mci, e, separator) ** none. */ -mailfile(filename, ctladdr, e) +int +mailfile(filename, ctladdr, sfflags, e) char *filename; ADDRESS *ctladdr; + int sfflags; register ENVELOPE *e; { register FILE *f; - register int pid; + register int pid = -1; int mode; if (tTd(11, 1)) @@ -2184,22 +2710,27 @@ mailfile(filename, ctladdr, e) int oflags = O_WRONLY|O_APPEND; if (e->e_lockfp != NULL) - { - fclose(e->e_lockfp); - e->e_lockfp = NULL; - } + (void) close(fileno(e->e_lockfp)); (void) setsignal(SIGINT, SIG_DFL); (void) setsignal(SIGHUP, SIG_DFL); (void) setsignal(SIGTERM, SIG_DFL); (void) umask(OldUmask); + e->e_to = filename; + ExitStat = EX_OK; +#ifdef HASLSTAT + if ((SafeFileEnv != NULL ? lstat(filename, &stb) + : stat(filename, &stb)) < 0) +#else if (stat(filename, &stb) < 0) +#endif { stb.st_mode = FileMode; oflags |= O_CREAT|O_EXCL; } - else if (bitset(0111, stb.st_mode)) + else if (bitset(0111, stb.st_mode) || stb.st_nlink != 1 || + (SafeFileEnv != NULL && !S_ISREG(stb.st_mode))) exit(EX_CANTCREAT); mode = stb.st_mode; @@ -2207,59 +2738,108 @@ mailfile(filename, ctladdr, e) errno = 0; ExitStat = EX_OK; - if (ctladdr != NULL) + if (ctladdr != NULL || bitset(SFF_RUNASREALUID, sfflags)) { /* ignore setuid and setgid bits */ mode &= ~(S_ISGID|S_ISUID); } /* we have to open the dfile BEFORE setuid */ - if (e->e_dfp == NULL && e->e_df != NULL) + if (e->e_dfp == NULL && bitset(EF_HAS_DF, e->e_flags)) { - e->e_dfp = fopen(e->e_df, "r"); + char *df = queuename(e, 'd'); + + e->e_dfp = fopen(df, "r"); if (e->e_dfp == NULL) { syserr("mailfile: Cannot open %s for %s from %s", - e->e_df, e->e_to, e->e_from.q_paddr); + df, e->e_to, e->e_from.q_paddr); } } - if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) + /* select a new user to run as */ + if (!bitset(SFF_RUNASREALUID, sfflags)) { - if (ctladdr == NULL || ctladdr->q_uid == 0) + if (bitset(S_ISUID, mode)) { - (void) initgroups(DefUser, DefGid); + RealUserName = NULL; + RealUid = stb.st_uid; + } + else if (ctladdr != NULL && ctladdr->q_uid != 0) + { + if (ctladdr->q_ruser != NULL) + RealUserName = ctladdr->q_ruser; + else + RealUserName = ctladdr->q_user; + RealUid = ctladdr->q_uid; + } + else if (FileMailer != NULL && FileMailer->m_uid != 0) + { + RealUserName = DefUser; + RealUid = FileMailer->m_uid; } else { - (void) initgroups(ctladdr->q_ruser ? - ctladdr->q_ruser : ctladdr->q_user, - ctladdr->q_gid); + RealUserName = DefUser; + RealUid = DefUid; } + + /* select a new group to run as */ + if (bitset(S_ISGID, mode)) + RealGid = stb.st_gid; + else if (ctladdr != NULL && ctladdr->q_uid != 0) + RealGid = ctladdr->q_gid; + else if (FileMailer != NULL && FileMailer->m_gid != 0) + RealGid = FileMailer->m_gid; + else + RealGid = DefGid; } - if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) + + /* last ditch */ + if (!bitset(SFF_ROOTOK, sfflags)) { - if (ctladdr == NULL || ctladdr->q_uid == 0) - (void) setuid(DefUid); - else - (void) setuid(ctladdr->q_uid); + if (RealUid == 0) + RealUid = DefUid; + if (RealGid == 0) + RealGid = DefGid; + } + + /* now set the group and user ids */ + endpwent(); + if (RealUserName != NULL && !DontInitGroups) + (void) initgroups(RealUserName, RealGid); + (void) setgid(RealGid); + (void) setuid(RealUid); + + /* if you have a safe environment, go into it */ + if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0') + { + int i; + + if (chroot(SafeFileEnv) < 0) + { + syserr("mailfile: Cannot chroot(%s)", + SafeFileEnv); + exit(EX_CANTCREAT); + } + i = strlen(SafeFileEnv); + if (strncmp(SafeFileEnv, filename, i) == 0) + filename += i; } - FileName = filename; - LineNumber = 0; - f = dfopen(filename, oflags, FileMode); + if (chdir("/") < 0) + syserr("mailfile: cannot chdir(/)"); + + sfflags |= SFF_NOPATHCHECK; + sfflags &= ~SFF_OPENASROOT; + f = safefopen(filename, oflags, FileMode, sfflags); if (f == NULL) { message("554 cannot open: %s", errstring(errno)); exit(EX_CANTCREAT); } - if (fstat(fileno(f), &fsb) < 0 || - !bitset(O_CREAT, oflags) && - (stb.st_nlink != fsb.st_nlink || - stb.st_dev != fsb.st_dev || - stb.st_ino != fsb.st_ino || - stb.st_uid != fsb.st_uid)) + if (fstat(fileno(f), &stb) < 0) { - message("554 cannot write: file changed after open"); + message("554 cannot fstat %s", errstring(errno)); exit(EX_CANTCREAT); } @@ -2270,20 +2850,23 @@ mailfile(filename, ctladdr, e) mcibuf.mci_flags |= MCIF_7BIT; putfromline(&mcibuf, e); - (*e->e_puthdr)(&mcibuf, e); - putline("\n", &mcibuf); + (*e->e_puthdr)(&mcibuf, e->e_header, e); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); - if (ferror(f)) + if (fflush(f) < 0 || ferror(f)) { message("451 I/O error: %s", errstring(errno)); setstat(EX_IOERR); } - (void) xfclose(f, "mailfile", filename); - (void) fflush(stdout); /* reset ISUID & ISGID bits for paranoid systems */ +#if HASFCHMOD + (void) fchmod(fileno(f), (int) stb.st_mode); +#else (void) chmod(filename, (int) stb.st_mode); +#endif + (void) xfclose(f, "mailfile", filename); + (void) fflush(stdout); exit(ExitStat); /*NOTREACHED*/ } @@ -2337,7 +2920,7 @@ hostsignature(m, host, e) auto int rcode; char *hp; char *endp; - int oldoptions; + int oldoptions = _res.options; char *mxhosts[MAXMXHOSTS + 1]; #endif @@ -2366,10 +2949,7 @@ hostsignature(m, host, e) #if NAMED_BIND if (ConfigLevel < 2) - { - oldoptions = _res.options; _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ - } for (hp = host; hp != NULL; hp = endp) { @@ -2385,11 +2965,10 @@ hostsignature(m, host, e) /* update the connection info for this host */ mci = mci_get(hp, m); + mci->mci_lastuse = curtime(); mci->mci_exitstat = rcode; mci->mci_errno = errno; -#if NAMED_BIND mci->mci_herrno = h_errno; -#endif /* and return the original host name as the signature */ nmx = 1; diff --git a/usr.sbin/sendmail/src/domain.c b/usr.sbin/sendmail/src/domain.c index da2a795..8058330 100644 --- a/usr.sbin/sendmail/src/domain.c +++ b/usr.sbin/sendmail/src/domain.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1986 Eric P. Allman + * Copyright (c) 1986, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -36,23 +36,21 @@ #ifndef lint #if NAMED_BIND -static char sccsid[] = "@(#)domain.c 8.19.1.1 (Berkeley) 3/6/95 (with name server)"; +static char sccsid[] = "@(#)domain.c 8.54 (Berkeley) 9/28/95 (with name server)"; #else -static char sccsid[] = "@(#)domain.c 8.19.1.1 (Berkeley) 3/6/95 (without name server)"; +static char sccsid[] = "@(#)domain.c 8.54 (Berkeley) 9/28/95 (without name server)"; #endif #endif /* not lint */ #if NAMED_BIND #include <errno.h> -#include <arpa/nameser.h> #include <resolv.h> -#include <netdb.h> typedef union { HEADER qb1; - char qb2[PACKETSZ]; + u_char qb2[PACKETSZ]; } querybuf; static char MXHostBuf[MAXMXHOSTS*PACKETSZ]; @@ -69,15 +67,17 @@ static char MXHostBuf[MAXMXHOSTS*PACKETSZ]; # define NO_DATA NO_ADDRESS #endif -#ifndef HEADERSZ -# define HEADERSZ sizeof(HEADER) +#ifndef HFIXEDSZ +# define HFIXEDSZ 12 /* sizeof(HEADER) */ #endif -/* don't use sizeof because sizeof(long) is different on 64-bit machines */ -#define SHORTSIZE 2 /* size of a short (really, must be 2) */ -#define LONGSIZE 4 /* size of a long (really, must be 4) */ - #define MAXCNAMEDEPTH 10 /* maximum depth of CNAME recursion */ + +#if defined(__RES) && (__RES >= 19940415) +# define RES_UNC_T char * +#else +# define RES_UNC_T u_char * +#endif /* ** GETMXRR -- get MX resource records for a domain ** @@ -96,13 +96,13 @@ static char MXHostBuf[MAXMXHOSTS*PACKETSZ]; ** and 1 is returned. */ +int getmxrr(host, mxhosts, droplocalhost, rcode) char *host; char **mxhosts; bool droplocalhost; int *rcode; { - extern int h_errno; register u_char *eom, *cp; register int i, j, n; int nmx = 0; @@ -111,11 +111,13 @@ getmxrr(host, mxhosts, droplocalhost, rcode) querybuf answer; int ancount, qdcount, buflen; bool seenlocal = FALSE; - u_short pref, localpref, type; + u_short pref, type; + u_short localpref = 256; char *fallbackMX = FallBackMX; static bool firsttime = TRUE; - STAB *st; bool trycanon = FALSE; + int (*resfunc)(); + extern int res_query(), res_search(); u_short prefer[MAXMXHOSTS]; int weight[MAXMXHOSTS]; extern bool getcanonname(); @@ -125,15 +127,14 @@ getmxrr(host, mxhosts, droplocalhost, rcode) if (fallbackMX != NULL) { - if (firsttime && res_query(FallBackMX, C_IN, T_A, - (char *) &answer, sizeof answer) < 0) + 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 && - (st = stab(fallbackMX, ST_CLASS, ST_FIND)) != NULL && - bitnset('w', st->s_class)) + else if (droplocalhost && wordinclass(fallbackMX, 'w')) { /* don't use fallback for this pass */ fallbackMX = NULL; @@ -141,12 +142,29 @@ getmxrr(host, mxhosts, droplocalhost, rcode) firsttime = FALSE; } + *rcode = EX_OK; + /* efficiency hack -- numeric or non-MX lookups */ if (host[0] == '[') goto punt; + /* + ** If we don't have MX records in our host switch, don't + ** try for MX records. Note that this really isn't "right", + ** since we might be set up to try NIS first and then DNS; + ** if the host is found in NIS we really shouldn't be doing + ** MX lookups. However, that should be a degenerate case. + */ + + if (!UseNameServer) + goto punt; + if (HasWildcardMX && ConfigLevel >= 6) + resfunc = res_query; + else + resfunc = res_search; + errno = 0; - n = res_search(host, C_IN, T_MX, (char *)&answer, sizeof(answer)); + n = (*resfunc)(host, C_IN, T_MX, (u_char *) &answer, sizeof(answer)); if (n < 0) { if (tTd(8, 1)) @@ -163,25 +181,22 @@ getmxrr(host, mxhosts, droplocalhost, rcode) goto punt; case HOST_NOT_FOUND: -#ifdef BROKEN_RES_SEARCH - /* Ultrix resolver returns failure w/ h_errno=0 */ - case 0: +#if BROKEN_RES_SEARCH + case 0: /* Ultrix resolver retns failure w/ h_errno=0 */ #endif - /* the host just doesn't exist */ + /* host doesn't exist in DNS; might be in /etc/hosts */ + trycanon = TRUE; *rcode = EX_NOHOST; - - if (!UseNameServer) - { - /* might exist in /etc/hosts */ - goto punt; - } - break; + goto punt; case TRY_AGAIN: /* couldn't connect to the name server */ - if (!UseNameServer && errno == ECONNREFUSED) - goto punt; - + if (fallbackMX != NULL) + { + /* name server is hosed -- push to fallback */ + mxhosts[nmx++] = fallbackMX; + return nmx; + } /* it might come up later; better queue it up */ *rcode = EX_TEMPFAIL; break; @@ -199,7 +214,7 @@ getmxrr(host, mxhosts, droplocalhost, rcode) /* find first satisfactory answer */ hp = (HEADER *)&answer; - cp = (u_char *)&answer + HEADERSZ; + cp = (u_char *)&answer + HFIXEDSZ; eom = (u_char *)&answer + n; for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) if ((n = dn_skipname(cp, eom)) < 0) @@ -210,11 +225,11 @@ getmxrr(host, mxhosts, droplocalhost, rcode) while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1) { if ((n = dn_expand((u_char *)&answer, - eom, cp, (u_char *)bp, buflen)) < 0) + eom, cp, (RES_UNC_T) bp, buflen)) < 0) break; cp += n; GETSHORT(type, cp); - cp += SHORTSIZE + LONGSIZE; + cp += INT16SZ + INT32SZ; GETSHORT(n, cp); if (type != T_MX) { @@ -226,22 +241,25 @@ getmxrr(host, mxhosts, droplocalhost, rcode) } GETSHORT(pref, cp); if ((n = dn_expand((u_char *)&answer, eom, cp, - (u_char *)bp, buflen)) < 0) + (RES_UNC_T) bp, buflen)) < 0) break; cp += n; - if (droplocalhost && - (st = stab(bp, ST_CLASS, ST_FIND)) != NULL && - bitnset('w', st->s_class)) + if (wordinclass(bp, 'w')) { if (tTd(8, 3)) printf("found localhost (%s) in MX list, pref=%d\n", bp, pref); - if (!seenlocal || pref < localpref) - localpref = pref; - seenlocal = TRUE; - continue; + if (droplocalhost) + { + if (!seenlocal || pref < localpref) + localpref = pref; + seenlocal = TRUE; + continue; + } + weight[nmx] = 0; } - weight[nmx] = mxrand(bp); + else + weight[nmx] = mxrand(bp); prefer[nmx] = pref; mxhosts[nmx++] = bp; n = strlen(bp); @@ -284,11 +302,25 @@ getmxrr(host, mxhosts, droplocalhost, rcode) } } + /* delete duplicates from list (yes, some bozos have duplicates) */ + for (i = 0; i < nmx - 1; ) + { + if (strcasecmp(mxhosts[i], mxhosts[i + 1]) != 0) + i++; + else + { + /* compress out duplicate */ + for (j = i + 1; j < nmx; j++) + mxhosts[j] = mxhosts[j + 1]; + nmx--; + } + } + if (nmx == 0) { punt: if (seenlocal && - (!TryNullMXList || gethostbyname(host) == NULL)) + (!TryNullMXList || sm_gethostbyname(host) == NULL)) { /* ** If we have deleted all MX entries, this is @@ -336,8 +368,8 @@ punt: *bp++ = '.'; *bp = '\0'; } + nmx = 1; } - nmx = 1; } /* if we have a default lowest preference, include that */ @@ -364,6 +396,7 @@ punt: ** none. */ +int mxrand(host) register char *host; { @@ -391,13 +424,43 @@ mxrand(host) } hfunc &= 0xff; + hfunc++; if (tTd(17, 9)) printf(" = %d\n", hfunc); return hfunc; } /* -** GETCANONNAME -- get the canonical name for named host +** BESTMX -- find the best MX for a name +** +** This is really a hack, but I don't see any obvious way +** to generalize it at the moment. +*/ + +char * +bestmx_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + int nmx; + auto int rcode; + int saveopts = _res.options; + char *mxhosts[MAXMXHOSTS + 1]; + + _res.options &= ~(RES_DNSRCH|RES_DEFNAMES); + nmx = getmxrr(name, mxhosts, FALSE, &rcode); + _res.options = saveopts; + if (nmx <= 0) + return NULL; + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + else + return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); +} +/* +** DNS_GETCANONNAME -- get the canonical name for named host using DNS ** ** This algorithm tries to be smart about wildcard MX records. ** This is hard to do because DNS doesn't tell is if we matched @@ -419,6 +482,7 @@ mxrand(host) ** This is a value-result parameter. ** hbsize -- the size of the host buffer. ** trymx -- if set, try MX records as well as A and CNAME. +** statp -- pointer to place to store status. ** ** Returns: ** TRUE -- if the host matched. @@ -426,12 +490,12 @@ mxrand(host) */ bool -getcanonname(host, hbsize, trymx) +dns_getcanonname(host, hbsize, trymx, statp) char *host; int hbsize; bool trymx; + int *statp; { - extern int h_errno; register u_char *eom, *ap; register char *cp; register int n; @@ -444,7 +508,7 @@ getcanonname(host, hbsize, trymx) char **dp; char *mxmatch; bool amatch; - bool gotmx; + bool gotmx = FALSE; int qtype; int loopcnt; char *xp; @@ -453,10 +517,13 @@ getcanonname(host, hbsize, trymx) extern char *gethostalias(); if (tTd(8, 2)) - printf("getcanonname(%s)\n", host); + printf("dns_getcanonname(%s, trymx=%d)\n", host, trymx); if ((_res.options & RES_INIT) == 0 && res_init() == -1) - return (FALSE); + { + *statp = EX_UNAVAILABLE; + return FALSE; + } /* ** Initialize domain search list. If there is at least one @@ -470,10 +537,15 @@ getcanonname(host, hbsize, trymx) loopcnt = 0; cnameloop: - for (cp = host, n = 0; *cp; cp++) + /* Check for dots in the name */ + for (cp = host, n = 0; *cp != '\0'; cp++) if (*cp == '.') n++; + /* + ** If this is a simple name, determine whether it matches an + ** alias in the file defined by the environment variable HOSTALIASES. + */ if (n == 0 && (xp = gethostalias(host)) != NULL) { if (loopcnt++ > MAXCNAMEDEPTH) @@ -488,6 +560,17 @@ cnameloop: } } + /* + ** Build the search list. + ** If there is at least one dot in name, start with a null + ** domain to search the unmodified name first. + ** If name does not end with a dot and search up local domain + ** tree desired, append each local domain component to the + ** search list; if name contains no dots and default domain + ** name is desired, append default domain name to search list; + ** else if name ends in a dot, remove that dot. + */ + dp = searchlist; if (n > 0) *dp++ = ""; @@ -507,7 +590,8 @@ cnameloop: *dp = NULL; /* - ** Now run through the search list for the name in question. + ** Now loop through the search list, appending each domain in turn + ** name and searching for a match. */ mxmatch = NULL; @@ -518,11 +602,12 @@ cnameloop: if (qtype == T_ANY) gotmx = FALSE; if (tTd(8, 5)) - printf("getcanonname: trying %s.%s (%s)\n", host, *dp, + printf("dns_getcanonname: trying %s.%s (%s)\n", + host, *dp, qtype == T_ANY ? "ANY" : qtype == T_A ? "A" : qtype == T_MX ? "MX" : "???"); ret = res_querydomain(host, *dp, C_IN, qtype, - (u_char *) &answer, sizeof(answer)); + answer.qb2, sizeof(answer.qb2)); if (ret <= 0) { if (tTd(8, 7)) @@ -533,6 +618,7 @@ cnameloop: { /* the name server seems to be down */ h_errno = TRY_AGAIN; + *statp = EX_TEMPFAIL; return FALSE; } @@ -551,13 +637,7 @@ cnameloop: } } - if (mxmatch != NULL) - { - /* we matched before -- use that one */ - break; - } - - /* otherwise, try the next name */ + /* definite no -- try the next domain */ dp++; qtype = T_ANY; continue; @@ -566,13 +646,13 @@ cnameloop: printf("\tYES\n"); /* - ** This might be a bogus match. Search for A or - ** CNAME records. If we don't have a matching + ** Appear to have a match. Confirm it by searching for A or + ** CNAME records. If we don't have a local domain ** wild card MX record, we will accept MX as well. */ hp = (HEADER *) &answer; - ap = (u_char *) &answer + HEADERSZ; + ap = (u_char *) &answer + HFIXEDSZ; eom = (u_char *) &answer + ret; /* skip question part of response -- we know what we asked */ @@ -583,44 +663,66 @@ cnameloop: if (tTd(8, 20)) printf("qdcount failure (%d)\n", ntohs(hp->qdcount)); + *statp = EX_SOFTWARE; return FALSE; /* ???XXX??? */ } } amatch = FALSE; - for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; ap += n) + for (ancount = ntohs(hp->ancount); --ancount >= 0 && ap < eom; + ap += n) { n = dn_expand((u_char *) &answer, eom, ap, - (u_char *) nbuf, sizeof nbuf); + (RES_UNC_T) nbuf, sizeof nbuf); if (n < 0) break; ap += n; GETSHORT(type, ap); - ap += SHORTSIZE + LONGSIZE; + ap += INT16SZ + INT32SZ; GETSHORT(n, ap); switch (type) { case T_MX: gotmx = TRUE; - if (**dp != '\0') + if (**dp != '\0' && HasWildcardMX) { - /* got a match -- save that info */ + /* + ** If we are using MX matches and have + ** not yet gotten one, save this one + ** but keep searching for an A or + ** CNAME match. + */ + if (trymx && mxmatch == NULL) mxmatch = *dp; continue; } - /* exact MX matches are as good as an A match */ - /* fall through */ + /* + ** If we did not append a domain name, this + ** must have been a canonical name to start + ** with. Even if we did append a domain name, + ** in the absence of a wildcard MX this must + ** still be a real MX match. + ** Such MX matches are as good as an A match, + ** fall through. + */ case T_A: - /* good show */ + /* Flag that a good match was found */ amatch = TRUE; /* continue in case a CNAME also exists */ continue; case T_CNAME: + if (DontExpandCnames) + { + /* got CNAME -- guaranteed canonical */ + amatch = TRUE; + break; + } + if (loopcnt++ > MAXCNAMEDEPTH) { /*XXX should notify postmaster XXX*/ @@ -630,17 +732,18 @@ cnameloop: { char ebuf[MAXLINE]; - sprintf(ebuf, "Deferred: DNS failure: CNAME loop for %s", + sprintf(ebuf, "Deferred: DNS failure: CNAME loop for %.100s", host); CurEnv->e_message = newstr(ebuf); } h_errno = NO_RECOVERY; + *statp = EX_CONFIG; return FALSE; } /* value points at name */ if ((ret = dn_expand((u_char *)&answer, - eom, ap, (u_char *)nbuf, sizeof(nbuf))) < 0) + eom, ap, (RES_UNC_T) nbuf, sizeof(nbuf))) < 0) break; (void)strncpy(host, nbuf, hbsize); /* XXX */ host[hbsize - 1] = '\0'; @@ -661,14 +764,24 @@ cnameloop: if (amatch) { - /* got an A record and no CNAME */ + /* + ** Got a good match -- either an A, CNAME, or an + ** exact MX record. Save it and get out of here. + */ + mxmatch = *dp; break; } /* - ** If this was a T_ANY query, we may have the info but - ** need an explicit query. Try T_A, then T_MX. + ** Nothing definitive yet. + ** If this was a T_ANY query, we don't really know what + ** was returned -- it might have been a T_NS, + ** for example. Try T_A to be more specific + ** during the next pass. + ** If this was a T_A query and we haven't yet found a MX + ** match, try T_MX if allowed to do so. + ** Otherwise, try the next domain. */ if (qtype == T_ANY) @@ -677,39 +790,51 @@ cnameloop: qtype = T_MX; else { - /* really nothing in this domain; try the next */ qtype = T_ANY; dp++; } } + /* if nothing was found, we are done */ if (mxmatch == NULL) + { + *statp = EX_NOHOST; return FALSE; + } + + /* + ** Create canonical name and return. + ** If saved domain name is null, name was already canonical. + ** Otherwise append the saved domain name. + */ - /* create matching name and return */ (void) sprintf(nbuf, "%.*s%s%.*s", MAXDNAME, host, *mxmatch == '\0' ? "" : ".", MAXDNAME, mxmatch); strncpy(host, nbuf, hbsize); host[hbsize - 1] = '\0'; + if (tTd(8, 5)) + printf("dns_getcanonname: %s\n", host); + *statp = EX_OK; return TRUE; } + char * gethostalias(host) char *host; { char *fname; FILE *fp; - register char *p; + register char *p = NULL; char buf[MAXLINE]; static char hbuf[MAXDNAME]; fname = getenv("HOSTALIASES"); - if (fname == NULL || (fp = fopen(fname, "r")) == NULL) + if (fname == NULL || + (fp = safefopen(fname, O_RDONLY, 0, SFF_REGONLY)) == NULL) return NULL; - setbuf(fp, NULL); while (fgets(buf, sizeof buf, fp) != NULL) { for (p = buf; p != '\0' && !(isascii(*p) && isspace(*p)); p++) @@ -743,28 +868,4 @@ gethostalias(host) return hbuf; } - -#else /* not NAMED_BIND */ - -#include <netdb.h> - -bool -getcanonname(host, hbsize, trymx) - char *host; - int hbsize; - bool trymx; -{ - struct hostent *hp; - - hp = gethostbyname(host); - if (hp == NULL) - return (FALSE); - - if (strlen(hp->h_name) >= hbsize) - return (FALSE); - - (void) strcpy(host, hp->h_name); - return (TRUE); -} - -#endif /* not NAMED_BIND */ +#endif /* NAMED_BIND */ diff --git a/usr.sbin/sendmail/src/headers.c b/usr.sbin/sendmail/src/headers.c index a55ba95..9bad1f8 100644 --- a/usr.sbin/sendmail/src/headers.c +++ b/usr.sbin/sendmail/src/headers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.32 (Berkeley) 4/14/94"; +static char sccsid[] = "@(#)headers.c 8.82 (Berkeley) 10/28/95"; #endif /* not lint */ # include <errno.h> @@ -47,6 +47,7 @@ static char sccsid[] = "@(#)headers.c 8.32 (Berkeley) 4/14/94"; ** Parameters: ** line -- header as a text line. ** def -- if set, this is a default value. +** hdrp -- a pointer to the place to save the header. ** e -- the envelope including this header. ** ** Returns: @@ -57,9 +58,11 @@ static char sccsid[] = "@(#)headers.c 8.32 (Berkeley) 4/14/94"; ** Contents of 'line' are destroyed. */ -chompheader(line, def, e) +int +chompheader(line, def, hdrp, e) char *line; bool def; + HDR **hdrp; register ENVELOPE *e; { register char *p; @@ -69,11 +72,20 @@ chompheader(line, def, e) char *fvalue; struct hdrinfo *hi; bool cond = FALSE; + bool headeronly; BITMAP mopts; - char buf[MAXNAME]; + char buf[MAXNAME + 1]; if (tTd(31, 6)) - printf("chompheader: %s\n", line); + { + printf("chompheader: "); + xputs(line); + printf("\n"); + } + + headeronly = hdrp != NULL; + if (!headeronly) + hdrp = &e->e_header; /* strip off options */ clrbitmap(mopts); @@ -91,7 +103,7 @@ chompheader(line, def, e) p = q; } else - usrerr("553 header syntax error, line \"%s\"", line); + syserr("553 header syntax error, line \"%s\"", line); cond = TRUE; } @@ -114,6 +126,10 @@ chompheader(line, def, e) if (*fvalue == ' ') fvalue++; + /* security scan: long field names are end-of-header */ + if (strlen(fname) > 100) + return H_EOH; + /* see if it is a known type */ for (hi = HdrInfo; hi->hi_field != NULL; hi++) { @@ -126,17 +142,38 @@ chompheader(line, def, e) if (hi->hi_field == NULL) printf("no header match\n"); else - printf("header match, hi_flags=%o\n", hi->hi_flags); + printf("header match, hi_flags=%x\n", hi->hi_flags); } /* see if this is a resent message */ - if (!def && bitset(H_RESENT, hi->hi_flags)) + if (!def && !headeronly && bitset(H_RESENT, hi->hi_flags)) e->e_flags |= EF_RESENT; + /* if this is an Errors-To: header keep track of it now */ + if (UseErrorsTo && !def && !headeronly && + bitset(H_ERRORSTO, hi->hi_flags)) + (void) sendtolist(fvalue, NULLADDR, &e->e_errorqueue, 0, e); + /* if this means "end of header" quit now */ if (bitset(H_EOH, hi->hi_flags)) return (hi->hi_flags); +#ifdef LOTUS_NOTES_HACK + /* + ** Horrible hack to work around problem with Lotus Notes SMTP + ** mail gateway, which generates From: headers with newlines in + ** them and the <address> on the second line. Although this is + ** legal RFC 822, many MUAs don't handle this properly and thus + ** never find the actual address. + */ + + if (bitset(H_FROM, hi->hi_flags) && SingleLineFromHeader) + { + while ((p = strchr(fvalue, '\n')) != NULL) + *p = ' '; + } +#endif + /* ** Drop explicit From: if same as what we would generate. ** This is to make MH (which doesn't always give a full name) @@ -146,7 +183,8 @@ chompheader(line, def, e) p = "resent-from"; if (!bitset(EF_RESENT, e->e_flags)) p += 7; - if (!def && !bitset(EF_QUEUERUN, e->e_flags) && strcasecmp(fname, p) == 0) + if (!def && !headeronly && !bitset(EF_QUEUERUN, e->e_flags) && + strcasecmp(fname, p) == 0) { if (tTd(31, 2)) { @@ -158,7 +196,7 @@ chompheader(line, def, e) strcmp(fvalue, e->e_from.q_user) == 0)) return (hi->hi_flags); #ifdef MAYBENEXTRELEASE /* XXX UNTESTED XXX UNTESTED XXX UNTESTED XXX */ -#ifdef USERDB +#if USERDB else { auto ADDRESS a; @@ -183,13 +221,13 @@ chompheader(line, def, e) SuprErrs = TRUE; fancy = crackaddr(fvalue); if (parseaddr(fvalue, &a, RF_COPYNONE, '\0', NULL, e) != NULL && - a.q_mailer == LocalMailer && + 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, &buf[sizeof buf], e); + expand(fancy, buf, sizeof buf, e); define('g', oldg, e); fvalue = buf; } @@ -200,12 +238,20 @@ chompheader(line, def, e) } /* delete default value for this header */ - for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link) + for (hp = hdrp; (h = *hp) != NULL; hp = &h->h_link) { if (strcasecmp(fname, h->h_field) == 0 && bitset(H_DEFAULT, h->h_flags) && !bitset(H_FORCE, h->h_flags)) + { h->h_value = NULL; + if (!cond) + { + /* copy conditions from default case */ + bcopy((char *)h->h_mflags, (char *)mopts, + sizeof mopts); + } + } } /* create a new node */ @@ -222,7 +268,7 @@ chompheader(line, def, e) h->h_flags |= H_CHECK; /* hack to see if this is a new format message */ - if (!def && bitset(H_RCPT|H_FROM, h->h_flags) && + if (!def && !headeronly && bitset(H_RCPT|H_FROM, h->h_flags) && (strchr(fvalue, ',') != NULL || strchr(fvalue, '(') != NULL || strchr(fvalue, '<') != NULL || strchr(fvalue, ';') != NULL)) { @@ -239,7 +285,7 @@ chompheader(line, def, e) ** Parameters: ** field -- the name of the header field. ** value -- the value of the field. -** e -- the envelope to add them to. +** hp -- an indirect pointer to the header structure list. ** ** Returns: ** none. @@ -248,10 +294,11 @@ chompheader(line, def, e) ** adds the field on the list of headers for this envelope. */ -addheader(field, value, e) +void +addheader(field, value, hdrlist) char *field; char *value; - ENVELOPE *e; + HDR **hdrlist; { register HDR *h; register struct hdrinfo *hi; @@ -265,7 +312,7 @@ addheader(field, value, e) } /* find current place in list -- keep back pointer? */ - for (hp = &e->e_header; (h = *hp) != NULL; hp = &h->h_link) + for (hp = hdrlist; (h = *hp) != NULL; hp = &h->h_link) { if (strcasecmp(field, h->h_field) == 0) break; @@ -288,7 +335,7 @@ addheader(field, value, e) ** ** Parameters: ** field -- the field name. -** e -- the envelope containing the header. +** header -- the header list. ** ** Returns: ** pointer to the value part. @@ -299,13 +346,13 @@ addheader(field, value, e) */ char * -hvalue(field, e) +hvalue(field, header) char *field; - register ENVELOPE *e; + HDR *header; { register HDR *h; - for (h = e->e_header; h != NULL; h = h->h_link) + for (h = header; h != NULL; h = h->h_link) { if (!bitset(H_DEFAULT, h->h_flags) && strcasecmp(h->h_field, field) == 0) @@ -319,11 +366,17 @@ hvalue(field, e) ** A line is a header if it has a single word followed by ** optional white space followed by a colon. ** +** Header fields beginning with two dashes, although technically +** permitted by RFC822, are automatically rejected in order +** to make MIME work out. Without this we could have a technically +** legal header such as ``--"foo:bar"'' that would also be a legal +** MIME separator. +** ** Parameters: -** s -- string to check for possible headerness. +** h -- string to check for possible headerness. ** ** Returns: -** TRUE if s is a header. +** TRUE if h is a header. ** FALSE otherwise. ** ** Side Effects: @@ -331,12 +384,20 @@ hvalue(field, e) */ bool -isheader(s) - register char *s; +isheader(h) + char *h; { + register char *s = h; + + if (s[0] == '-' && s[1] == '-') + return FALSE; + while (*s > ' ' && *s != ':' && *s != '\0') s++; + if (h == s) + return FALSE; + /* following technically violates RFC822 */ while (isascii(*s) && isspace(*s)) s++; @@ -349,7 +410,9 @@ isheader(s) ** Parameters: ** e -- the envelope to process. ** full -- if set, do full processing (e.g., compute -** message priority). +** message priority). This should not be set +** when reading a queue file because some info +** needed to compute the priority is wrong. ** ** Returns: ** none. @@ -360,6 +423,7 @@ isheader(s) ** Aborts the message if the hop count is exceeded. */ +void eatheader(e, full) register ENVELOPE *e; bool full; @@ -382,28 +446,42 @@ eatheader(e, full) define('u', NULL, e); /* full name of from person */ - p = hvalue("full-name", e); + p = hvalue("full-name", e->e_header); if (p != NULL) define('x', p, e); if (tTd(32, 1)) printf("----- collected header -----\n"); - msgid = "<none>"; + msgid = NULL; for (h = e->e_header; h != NULL; h = h->h_link) { + if (tTd(32, 1)) + printf("%s: ", h->h_field); if (h->h_value == NULL) { if (tTd(32, 1)) - printf("%s: <NULL>\n", h->h_field); + printf("<NULL>\n"); continue; } /* do early binding */ if (bitset(H_DEFAULT, h->h_flags)) { - expand(h->h_value, buf, &buf[sizeof buf], e); + if (tTd(32, 1)) + { + printf("("); + xputs(h->h_value); + printf(") "); + } + expand(h->h_value, buf, sizeof buf, e); if (buf[0] != '\0') { + if (bitset(H_FROM, h->h_flags)) + { + extern char *crackaddr(); + + expand(crackaddr(buf), buf, sizeof buf, e); + } h->h_value = newstr(buf); h->h_flags &= ~H_DEFAULT; } @@ -411,7 +489,6 @@ eatheader(e, full) if (tTd(32, 1)) { - printf("%s: ", h->h_field); xputs(h->h_value); printf("\n"); } @@ -428,7 +505,7 @@ eatheader(e, full) int saveflags = e->e_flags; (void) sendtolist(h->h_value, NULLADDR, - &e->e_sendqueue, e); + &e->e_sendqueue, 0, e); /* delete fatal errors generated by this address */ if (!GrabTo && !bitset(EF_FATALERRS, saveflags)) @@ -436,7 +513,10 @@ eatheader(e, full) } /* save the message-id for logging */ - if (full && strcasecmp(h->h_field, "message-id") == 0) + p = "resent-message-id"; + if (!bitset(EF_RESENT, e->e_flags)) + p += 7; + if (strcasecmp(h->h_field, p) == 0) { msgid = h->h_value; while (isascii(*msgid) && isspace(*msgid)) @@ -446,11 +526,6 @@ eatheader(e, full) /* see if this is a return-receipt header */ if (bitset(H_RECEIPTTO, h->h_flags)) e->e_receiptto = h->h_value; - - /* see if this is an errors-to header */ - if (UseErrorsTo && bitset(H_ERRORSTO, h->h_flags)) - (void) sendtolist(h->h_value, NULLADDR, - &e->e_errorqueue, e); } if (tTd(32, 1)) printf("----------------------------\n"); @@ -464,21 +539,60 @@ eatheader(e, full) e->e_hopcount = hopcnt; /* message priority */ - p = hvalue("precedence", e); + p = hvalue("precedence", e->e_header); if (p != NULL) e->e_class = priencode(p); + if (e->e_class < 0) + e->e_timeoutclass = TOC_NONURGENT; + else if (e->e_class > 0) + e->e_timeoutclass = TOC_URGENT; if (full) + { e->e_msgpriority = e->e_msgsize - e->e_class * WkClassFact + e->e_nrcpts * WkRecipFact; + } + + /* message timeout priority */ + p = hvalue("priority", e->e_header); + if (p != NULL) + { + /* (this should be in the configuration file) */ + if (strcasecmp(p, "urgent")) + e->e_timeoutclass = TOC_URGENT; + else if (strcasecmp(p, "normal")) + e->e_timeoutclass = TOC_NORMAL; + else if (strcasecmp(p, "non-urgent")) + e->e_timeoutclass = TOC_NONURGENT; + } /* date message originated */ - p = hvalue("posted-date", e); + p = hvalue("posted-date", e->e_header); if (p == NULL) - p = hvalue("date", e); + p = hvalue("date", e->e_header); if (p != NULL) define('a', p, e); + /* check to see if this is a MIME message */ + if ((e->e_bodytype != NULL && + strcasecmp(e->e_bodytype, "8BITMIME") == 0) || + hvalue("MIME-Version", e->e_header) != NULL) + { + e->e_flags |= EF_IS_MIME; + if (HasEightBits) + e->e_bodytype = "8BITMIME"; + } + else if ((p = hvalue("Content-Type", e->e_header)) != NULL) + { + /* this may be an RFC 1049 message */ + p = strpbrk(p, ";/"); + if (p == NULL || *p == ';') + { + /* yep, it is */ + e->e_flags |= EF_DONT_MIME; + } + } + /* ** From person in antiquated ARPANET mode ** required by UK Grey Book e-mail gateways (sigh) @@ -493,7 +607,7 @@ eatheader(e, full) if (bitset(H_FROM, hi->hi_flags) && (!bitset(H_RESENT, hi->hi_flags) || bitset(EF_RESENT, e->e_flags)) && - (p = hvalue(hi->hi_field, e)) != NULL) + (p = hvalue(hi->hi_field, e->e_header)) != NULL) break; } if (hi->hi_field != NULL) @@ -510,7 +624,7 @@ eatheader(e, full) */ # ifdef LOG - if (full && LogLevel > 4) + if (bitset(EF_LOGSENDER, e->e_flags) && LogLevel > 4) logsender(e, msgid); # endif /* LOG */ e->e_flags &= ~EF_LOGSENDER; @@ -526,6 +640,7 @@ eatheader(e, full) ** none */ +void logsender(e, msgid) register ENVELOPE *e; char *msgid; @@ -534,8 +649,23 @@ logsender(e, msgid) char *name; register char *sbp; register char *p; - char hbuf[MAXNAME]; - char sbuf[MAXLINE]; + int l; + char hbuf[MAXNAME + 1]; + char sbuf[MAXLINE + 1]; + char mbuf[MAXNAME + 1]; + + /* don't allow newlines in the message-id */ + if (msgid != NULL) + { + l = strlen(msgid); + if (l > sizeof mbuf - 1) + l = sizeof mbuf - 1; + bcopy(msgid, mbuf, l); + mbuf[l] = '\0'; + p = mbuf; + while ((p = strchr(p, '\n')) != NULL) + *p++ = ' '; + } if (bitset(EF_RESPONSE, e->e_flags)) name = "[RESPONSE]"; @@ -552,7 +682,7 @@ logsender(e, msgid) if (RealHostAddr.sa.sa_family != 0) { p = &hbuf[strlen(hbuf)]; - (void) sprintf(p, " (%s)", + (void) sprintf(p, " (%.100s)", anynet_ntoa(&RealHostAddr)); } } @@ -561,12 +691,12 @@ logsender(e, msgid) # if (SYSLOG_BUFSIZE) >= 256 sbp = sbuf; sprintf(sbp, "from=%.200s, size=%ld, class=%d, pri=%ld, nrcpts=%d", - e->e_from.q_paddr, e->e_msgsize, e->e_class, - e->e_msgpriority, e->e_nrcpts); + e->e_from.q_paddr == NULL ? "<NONE>" : e->e_from.q_paddr, + e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); sbp += strlen(sbp); if (msgid != NULL) { - sprintf(sbp, ", msgid=%.100s", msgid); + sprintf(sbp, ", msgid=%.100s", mbuf); sbp += strlen(sbp); } if (e->e_bodytype != NULL) @@ -577,33 +707,35 @@ logsender(e, msgid) p = macvalue('r', e); if (p != NULL) (void) sprintf(sbp, ", proto=%.20s", p); - syslog(LOG_INFO, "%s: %s, relay=%s", + syslog(LOG_INFO, "%s: %.850s, relay=%.100s", e->e_id, sbuf, name); # else /* short syslog buffer */ syslog(LOG_INFO, "%s: from=%s", - e->e_id, shortenstring(e->e_from.q_paddr, 83)); + e->e_id, e->e_from.q_paddr == NULL ? "<NONE>" : + shortenstring(e->e_from.q_paddr, 83)); syslog(LOG_INFO, "%s: size=%ld, class=%ld, pri=%ld, nrcpts=%d", e->e_id, e->e_msgsize, e->e_class, e->e_msgpriority, e->e_nrcpts); if (msgid != NULL) - syslog(LOG_INFO, "%s: msgid=%s", e->e_id, msgid); + syslog(LOG_INFO, "%s: msgid=%s", + e->e_id, shortenstring(mbuf, 83)); sbp = sbuf; sprintf(sbp, "%s:", e->e_id); sbp += strlen(sbp); if (e->e_bodytype != NULL) { - sprintf(sbp, " bodytype=%s,", e->e_bodytype); + sprintf(sbp, " bodytype=%.20s,", e->e_bodytype); sbp += strlen(sbp); } p = macvalue('r', e); if (p != NULL) { - sprintf(sbp, " proto=%s,", p); + sprintf(sbp, " proto=%.20s,", p); sbp += strlen(sbp); } - syslog(LOG_INFO, "%s relay=%s", sbuf, name); + syslog(LOG_INFO, "%.400s relay=%.100s", sbuf, name); # endif # endif } @@ -620,6 +752,7 @@ logsender(e, msgid) ** none. */ +int priencode(p) char *p; { @@ -678,9 +811,12 @@ crackaddr(addr) bool putgmac = FALSE; bool quoteit = FALSE; bool gotangle = FALSE; + bool gotcolon = FALSE; register char *bp; char *buflim; - static char buf[MAXNAME]; + char *bufhead; + char *addrhead; + static char buf[MAXNAME + 1]; if (tTd(33, 1)) printf("crackaddr(%s)\n", addr); @@ -694,9 +830,9 @@ crackaddr(addr) ** adjusted later if we find them. */ - bp = buf; + bp = bufhead = buf; buflim = &buf[sizeof buf - 5]; - p = addr; + p = addrhead = addr; copylev = anglelev = realanglelev = cmtlev = realcmtlev = 0; qmode = realqmode = FALSE; @@ -780,8 +916,80 @@ crackaddr(addr) bp--; } + /* check for group: list; syntax */ + if (c == ':' && anglelev <= 0 && !gotcolon && !ColonOkInAddr) + { + register char *q; + + if (*p == ':') + { + /* special case -- :: syntax */ + if (cmtlev <= 0 && !qmode) + quoteit = TRUE; + if (copylev > 0 && !skipping) + { + *bp++ = c; + *bp++ = c; + } + p++; + goto putg; + } + + gotcolon = TRUE; + + bp = bufhead; + if (quoteit) + { + *bp++ = '"'; + + /* back up over the ':' and any spaces */ + --p; + while (isascii(*--p) && isspace(*p)) + continue; + p++; + } + for (q = addrhead; q < p; ) + { + c = *q++; + if (bp < buflim) + { + if (quoteit && c == '"') + *bp++ = '\\'; + *bp++ = c; + } + } + if (quoteit) + { + if (bp == &bufhead[1]) + bp--; + else + *bp++ = '"'; + while ((c = *p++) != ':') + { + if (bp < buflim) + *bp++ = c; + } + *bp++ = c; + } + + /* any trailing white space is part of group: */ + while (isascii(*p) && isspace(*p) && bp < buflim) + *bp++ = *p++; + copylev = 0; + putgmac = quoteit = FALSE; + bufhead = bp; + addrhead = p; + continue; + } + + if (c == ';' && copylev <= 0 && !ColonOkInAddr) + { + if (bp < buflim) + *bp++ = c; + } + /* check for characters that may have to be quoted */ - if (strchr(".'@,;:\\()[]", c) != NULL) + if (strchr(MustQuoteChars, c) != NULL) { /* ** If these occur as the phrase part of a <> @@ -809,7 +1017,7 @@ crackaddr(addr) if (!skipping) realanglelev = 1; - bp = buf; + bp = bufhead; if (quoteit) { *bp++ = '"'; @@ -820,7 +1028,7 @@ crackaddr(addr) continue; p++; } - for (q = addr; q < p; ) + for (q = addrhead; q < p; ) { c = *q++; if (bp < buflim) @@ -901,6 +1109,7 @@ crackaddr(addr) ** ** Parameters: ** mci -- the connection information. +** h -- the header to put. ** e -- envelope to use. ** ** Returns: @@ -917,27 +1126,45 @@ crackaddr(addr) # define MAX(a,b) (((a)>(b))?(a):(b)) #endif -putheader(mci, e) +void +putheader(mci, h, e) register MCI *mci; + register HDR *h; register ENVELOPE *e; { char buf[MAX(MAXLINE,BUFSIZ)]; - register HDR *h; char obuf[MAXLINE]; if (tTd(34, 1)) printf("--- putheader, mailer = %s ---\n", mci->mci_mailer->m_name); - for (h = e->e_header; h != NULL; h = h->h_link) + mci->mci_flags |= MCIF_INHEADER; + for (; h != NULL; h = h->h_link) { - register char *p; + register char *p = h->h_value; extern bool bitintersect(); if (tTd(34, 11)) { printf(" %s: ", h->h_field); - xputs(h->h_value); + xputs(p); + } + + /* suppress Content-Transfer-Encoding: if we are MIMEing */ + if (bitset(H_CTE, h->h_flags) && + bitset(MCIF_CVT8TO7|MCIF_INMIME, mci->mci_flags)) + { + if (tTd(34, 11)) + printf(" (skipped (content-transfer-encoding))\n"); + continue; + } + + if (bitset(MCIF_INMIME, mci->mci_flags)) + { + if (tTd(34, 11)) + printf("\n"); + goto vanilla; } if (bitset(H_CHECK|H_ACHECK, h->h_flags) && @@ -966,10 +1193,9 @@ putheader(mci, e) } /* macro expand value if generated internally */ - p = h->h_value; if (bitset(H_DEFAULT, h->h_flags)) { - expand(p, buf, &buf[sizeof buf], e); + expand(p, buf, sizeof buf, e); p = buf; if (p == NULL || *p == '\0') { @@ -979,6 +1205,23 @@ putheader(mci, e) } } + if (bitset(H_BCC, h->h_flags)) + { + /* Bcc: field -- either truncate or delete */ + if (bitset(EF_DELETE_BCC, e->e_flags)) + { + if (tTd(34, 11)) + printf(" (skipped -- bcc)\n"); + } + else + { + /* no other recipient headers: truncate value */ + (void) sprintf(obuf, "%s:", h->h_field); + putline(obuf, mci); + } + continue; + } + if (tTd(34, 11)) printf("\n"); @@ -995,21 +1238,51 @@ putheader(mci, e) { /* vanilla header line */ register char *nlp; + register char *obp; - (void) sprintf(obuf, "%s: ", h->h_field); +vanilla: + (void) sprintf(obuf, "%.200s: ", h->h_field); + obp = obuf + strlen(obuf); while ((nlp = strchr(p, '\n')) != NULL) { + *nlp = '\0'; - (void) strcat(obuf, p); + sprintf(obp, "%.*s", + sizeof obuf - (obp - obuf) - 1, p); *nlp = '\n'; putline(obuf, mci); p = ++nlp; - obuf[0] = '\0'; + obp = obuf; } - (void) strcat(obuf, p); + sprintf(obp, "%.*s", sizeof obuf - (obp - obuf) - 1, p); + putline(obuf, mci); + } + } + + /* + ** If we are converting this to a MIME message, add the + ** MIME headers. + */ + +#if MIME8TO7 + if (bitset(MM_MIME8BIT, MimeMode) && + bitset(EF_HAS8BIT, e->e_flags) && + !bitset(EF_DONT_MIME, e->e_flags) && + !bitnset(M_8BITS, mci->mci_mailer->m_flags) && + !bitset(MCIF_CVT8TO7, mci->mci_flags)) + { + if (hvalue("MIME-Version", e->e_header) == NULL) + putline("MIME-Version: 1.0", mci); + if (hvalue("Content-Type", e->e_header) == NULL) + { + sprintf(obuf, "Content-Type: text/plain; charset=%s", + defcharset(e)); putline(obuf, mci); } + if (hvalue("Content-Transfer-Encoding", e->e_header) == NULL) + putline("Content-Transfer-Encoding: 8bit", mci); } +#endif } /* ** COMMAIZE -- output a header field, making a comma-translated list. @@ -1051,7 +1324,7 @@ commaize(h, p, oldstyle, mci, e) printf("commaize(%s: %s)\n", h->h_field, p); obp = obuf; - (void) sprintf(obp, "%s: ", h->h_field); + (void) sprintf(obp, "%.200s: ", h->h_field); opos = strlen(h->h_field) + 2; obp += opos; omax = mci->mci_mailer->m_linelimit - 2; @@ -1088,7 +1361,7 @@ commaize(h, p, oldstyle, mci, e) char pvpbuf[PSBUFSIZE]; (void) prescan(p, oldstyle ? ' ' : ',', pvpbuf, - sizeof pvpbuf, &oldp); + sizeof pvpbuf, &oldp, NULL); p = oldp; /* look to see if we have an at sign */ @@ -1119,6 +1392,18 @@ commaize(h, p, oldstyle, mci, e) flags = RF_HEADERADDR|RF_ADDDOMAIN; if (bitset(H_FROM, h->h_flags)) flags |= RF_SENDERADDR; +#if USERDB + else if (e->e_from.q_mailer != NULL && + bitnset(M_UDBRECIPIENT, e->e_from.q_mailer->m_flags)) + { + extern char *udbsender(); + char *q; + + q = udbsender(name); + if (q != NULL) + name = q; + } +#endif stat = EX_OK; name = remotename(name, mci->mci_mailer, flags, &stat, e); if (*name == '\0') diff --git a/usr.sbin/sendmail/src/main.c b/usr.sbin/sendmail/src/main.c index bae41d5..1b2b9da 100644 --- a/usr.sbin/sendmail/src/main.c +++ b/usr.sbin/sendmail/src/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -39,17 +39,15 @@ static char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 8.55.1.7 (Berkeley) 3/5/95"; +static char sccsid[] = "@(#)main.c 8.162 (Berkeley) 11/18/95"; #endif /* not lint */ #define _DEFINE #include "sendmail.h" #if NAMED_BIND -#include <arpa/nameser.h> #include <resolv.h> #endif -#include <pwd.h> # ifdef lint char edata, end; @@ -94,21 +92,9 @@ ENVELOPE BlankEnvelope; /* a "blank" envelope */ ENVELOPE MainEnvelope; /* the envelope around the basic letter */ ADDRESS NullAddress = /* a null address */ { "", "", NULL, "" }; -char *UserEnviron[MAXUSERENVIRON + 2]; - /* saved user environment */ -char RealUserName[256]; /* the actual user id on this host */ char *CommandLineArgs; /* command line args for pid file */ bool Warn_Q_option = FALSE; /* warn about Q option use */ - -/* -** Pointers for setproctitle. -** This allows "ps" listings to give more useful information. -*/ - -# ifdef SETPROCTITLE -char **Argv = NULL; /* pointer to argument vector */ -char *LastArgv = NULL; /* end of argv */ -# endif /* SETPROCTITLE */ +char **SaveArgv; /* argument vector for re-execing */ static void obsolete(); @@ -118,8 +104,9 @@ ERROR %%%% Cannot have daemon mode without SMTP %%%% ERROR #endif /* SMTP */ #endif /* DAEMON */ -#define MAXCONFIGLEVEL 5 /* highest config version level known */ +#define MAXCONFIGLEVEL 6 /* highest config version level known */ +int main(argc, argv, envp) int argc; char **argv; @@ -127,7 +114,6 @@ main(argc, argv, envp) { register char *p; char **av; - extern int finis(); extern char Version[]; char *ep, *from; typedef int (*fnptr)(); @@ -139,22 +125,25 @@ main(argc, argv, envp) bool warn_C_flag = FALSE; char warn_f_flag = '\0'; static bool reenter = FALSE; - char *argv0 = argv[0]; struct passwd *pw; struct stat stb; + struct hostent *hp; char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */ + static char rnamebuf[MAXNAME]; /* holds RealUserName */ extern int DtableSize; extern int optind; + extern int opterr; extern time_t convtime(); - extern putheader(), putbody(); extern void intsig(); - extern char **myhostname(); + extern struct hostent *myhostname(); extern char *arpadate(); extern char *getauthinfo(); extern char *getcfname(); extern char *optarg; extern char **environ; extern void sigusr1(); + extern void sighup(); + extern void initmacros __P((ENVELOPE *)); /* ** Check to see if we reentered. @@ -172,8 +161,8 @@ main(argc, argv, envp) /* do machine-dependent initializations */ init_md(argc, argv); - /* arrange to dump state on signal */ #ifdef SIGUSR1 + /* arrange to dump state on user-1 signal */ setsignal(SIGUSR1, sigusr1); #endif @@ -211,7 +200,9 @@ main(argc, argv, envp) # else openlog("sendmail", LOG_PID); # endif -#endif +#endif + + tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); /* set up the blank envelope */ BlankEnvelope.e_puthdr = putheader; @@ -231,25 +222,29 @@ main(argc, argv, envp) RealUid = getuid(); RealGid = getgid(); - pw = getpwuid(RealUid); + pw = sm_getpwuid(RealUid); if (pw != NULL) - (void) strcpy(RealUserName, pw->pw_name); + (void) strcpy(rnamebuf, pw->pw_name); else - (void) sprintf(RealUserName, "Unknown UID %d", RealUid); + (void) sprintf(rnamebuf, "Unknown UID %d", RealUid); + RealUserName = rnamebuf; /* save command line arguments */ i = 0; for (av = argv; *av != NULL; ) i += strlen(*av++) + 1; + SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1)); CommandLineArgs = xalloc(i); p = CommandLineArgs; - for (av = argv; *av != NULL; ) + for (av = argv, i = 0; *av != NULL; ) { + SaveArgv[i++] = newstr(*av); if (av != argv) *p++ = ' '; strcpy(p, *av++); p += strlen(p); } + SaveArgv[i] = NULL; /* Handle any non-getoptable constructions. */ obsolete(argv); @@ -259,63 +254,98 @@ main(argc, argv, envp) */ #if defined(__osf__) || defined(_AIX3) -# define OPTIONS "B:b:C:cd:e:F:f:h:Iimno:p:q:r:sTtvX:x" -#endif -#if defined(ultrix) -# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mno:p:q:r:sTtvX:" +# define OPTIONS "B:b:C:cd:e:F:f:h:IiM:mnO:o:p:q:r:sTtvX:x" #endif -#if defined(NeXT) -# define OPTIONS "B:b:C:cd:e:F:f:h:IimnOo:p:q:r:sTtvX:" +#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:Iimno:p:q:r:sTtvX:" +# 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': - tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); tTflag(optarg); setbuf(stdout, (char *) NULL); - printf("Version %s\n", Version); break; } } + opterr = 1; - InChannel = stdin; - OutChannel = stdout; - - /* - ** Move the environment so setproctitle can use the space at - ** the top of memory. - */ + if (tTd(0, 1)) + { + int ll; + extern char *CompileOptions[]; - for (i = j = 0; j < MAXUSERENVIRON && (p = envp[i]) != NULL; i++) + printf("Version %s\n Compiled with:", Version); + av = CompileOptions; + ll = 7; + while (*av != NULL) + { + if (ll + strlen(*av) > 63) + { + putchar('\n'); + ll = 0; + } + if (ll == 0) + { + putchar('\t'); + putchar('\t'); + } + else + putchar(' '); + printf("%s", *av); + ll += strlen(*av++) + 1; + } + putchar('\n'); + } + if (tTd(0, 10)) { - if (strncmp(p, "IFS=", 4) == 0 || strncmp(p, "LD_", 3) == 0) - continue; - UserEnviron[j++] = newstr(p); + int ll; + extern char *OsCompileOptions[]; + + printf(" OS Defines:", Version); + av = OsCompileOptions; + ll = 7; + while (*av != NULL) + { + if (ll + strlen(*av) > 63) + { + putchar('\n'); + ll = 0; + } + if (ll == 0) + { + putchar('\t'); + putchar('\t'); + } + else + putchar(' '); + printf("%s", *av); + ll += strlen(*av++) + 1; + } + putchar('\n'); +#ifdef _PATH_UNIX + printf("Kernel symbols:\t%s\n", _PATH_UNIX); +#endif + printf(" Config file:\t%s\n", getcfname()); + printf(" Pid file:\t%s\n", PidFile); } - UserEnviron[j] = NULL; - environ = UserEnviron; -# ifdef SETPROCTITLE - /* - ** Save start and extent of argv for setproctitle. - */ + InChannel = stdin; + OutChannel = stdout; - Argv = argv; - if (i > 0) - LastArgv = envp[i - 1] + strlen(envp[i - 1]); - else - LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); -# endif /* SETPROCTITLE */ + /* initialize for setproctitle */ + initsetproctitle(argc, argv, envp); + + /* prime the child environment */ + setuserenv("AGENT", "sendmail"); if (setsignal(SIGINT, SIG_IGN) != SIG_IGN) (void) setsignal(SIGINT, intsig); - if (setsignal(SIGHUP, SIG_IGN) != SIG_IGN) - (void) setsignal(SIGHUP, intsig); (void) setsignal(SIGTERM, intsig); (void) setsignal(SIGPIPE, SIG_IGN); OldUmask = umask(022); @@ -335,12 +365,13 @@ main(argc, argv, envp) /* initialize some macros, etc. */ initmacros(CurEnv); + init_vendor_macros(CurEnv); /* version */ define('v', Version, CurEnv); /* hostname */ - av = myhostname(jbuf, sizeof jbuf); + hp = myhostname(jbuf, sizeof jbuf); if (jbuf[0] != '\0') { struct utsname utsname; @@ -357,7 +388,6 @@ main(argc, argv, envp) if (p[1] != '\0') { define('m', newstr(&p[1]), CurEnv); - setclass('m', &p[1]); } while (p != NULL && strchr(&p[1], '.') != NULL) { @@ -378,19 +408,42 @@ main(argc, argv, envp) p = jbuf; } if (tTd(0, 4)) - printf("UUCP nodename: %s\n", p); + printf(" UUCP nodename: %s\n", p); p = newstr(p); define('k', p, CurEnv); setclass('k', p); setclass('w', p); } - while (av != NULL && *av != NULL) + if (hp != NULL) { - if (tTd(0, 4)) - printf("\ta.k.a.: %s\n", *av); - setclass('w', *av++); + for (av = hp->h_aliases; av != NULL && *av != NULL; av++) + { + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", *av); + setclass('w', *av); + } +#if NETINET + if (hp->h_addrtype == AF_INET && hp->h_length == INADDRSZ) + { + register int i; + + for (i = 0; hp->h_addr_list[i] != NULL; i++) + { + char ipbuf[103]; + + sprintf(ipbuf, "[%.100s]", + inet_ntoa(*((struct in_addr *) hp->h_addr_list[i]))); + if (tTd(0, 4)) + printf("\ta.k.a.: %s\n", ipbuf); + setclass('w', ipbuf); + } + } +#endif } + /* probe interfaces and locate any additional names */ + load_if_names(); + /* current time */ define('b', arpadate((char *) NULL), CurEnv); @@ -447,9 +500,7 @@ main(argc, argv, envp) case MD_TEST: case MD_INITALIAS: case MD_PRINT: -#ifdef MAYBE_NEXT_RELEASE case MD_ARPAFTP: -#endif OpMode = j; break; @@ -466,17 +517,14 @@ main(argc, argv, envp) break; case 'B': /* body type */ - if (strcasecmp(optarg, "7bit") == 0 || - strcasecmp(optarg, "8bitmime") == 0) - CurEnv->e_bodytype = newstr(optarg); - else - usrerr("Illegal body type %s", optarg); + CurEnv->e_bodytype = optarg; break; case 'C': /* select configuration file (already done) */ if (RealUid != 0) warn_C_flag = TRUE; ConfFile = optarg; + endpwent(); (void) setgid(RealGid); (void) setuid(RealUid); safecf = FALSE; @@ -520,6 +568,10 @@ main(argc, argv, envp) setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv); break; + case 'O': /* set option (long form) */ + setoption(' ', optarg, FALSE, TRUE, CurEnv); + break; + case 'p': /* set protocol */ p = strchr(optarg, ':'); if (p != NULL) @@ -574,6 +626,7 @@ main(argc, argv, envp) break; case 'X': /* traffic log file */ + endpwent(); setgid(RealGid); setuid(RealUid); TrafficLogFile = fopen(optarg, "a"); @@ -599,9 +652,7 @@ main(argc, argv, envp) break; case 'e': /* error message disposition */ -# if defined(ultrix) case 'M': /* define macro */ -# endif setoption(j, optarg, FALSE, TRUE, CurEnv); break; @@ -619,8 +670,10 @@ main(argc, argv, envp) case 'x': /* random flag that OSF/1 & AIX mailx passes */ break; # endif -# if defined(NeXT) - case 'O': /* random flag that NeXT Mail.app passes */ +# if defined(sony_news) + case 'E': + case 'J': /* ignore flags for Japanese code conversion + impremented on Sony NEWS */ break; # endif @@ -638,23 +691,42 @@ main(argc, argv, envp) ** Extract special fields for local use. */ -#ifdef XDEBUG + /* set up ${opMode} for use in config file */ + { + char mbuf[2]; + + mbuf[0] = OpMode; + mbuf[1] = '\0'; + define(MID_OPMODE, newstr(mbuf), CurEnv); + } + +#if XDEBUG checkfd012("before readcf"); #endif + vendor_pre_defaults(CurEnv); readcf(getcfname(), safecf, CurEnv); + vendor_post_defaults(CurEnv); + + /* suppress error printing if errors mailed back or whatever */ + if (CurEnv->e_errormode != EM_PRINT) + HoldErrs = TRUE; + + /* set up the $=m class now, after .cf has a chance to redefine $m */ + expand("\201m", jbuf, sizeof jbuf, CurEnv); + setclass('m', jbuf); if (tTd(0, 1)) { - printf("SYSTEM IDENTITY (after readcf):"); - printf("\n\t (short domain name) $w = "); + printf("\n============ SYSTEM IDENTITY (after readcf) ============"); + printf("\n (short domain name) $w = "); xputs(macvalue('w', CurEnv)); - printf("\n\t(canonical domain name) $j = "); + printf("\n (canonical domain name) $j = "); xputs(macvalue('j', CurEnv)); - printf("\n\t (subdomain name) $m = "); + printf("\n (subdomain name) $m = "); xputs(macvalue('m', CurEnv)); - printf("\n\t (node name) $k = "); + printf("\n (node name) $k = "); xputs(macvalue('k', CurEnv)); - printf("\n"); + printf("\n========================================================\n\n"); } /* @@ -662,47 +734,48 @@ main(argc, argv, envp) */ #if NAMED_BIND - if (!bitset(RES_INIT, _res.options)) + if (UseNameServer && !bitset(RES_INIT, _res.options)) res_init(); +# ifdef RES_NOALIASES + _res.options |= RES_NOALIASES; +# endif #endif /* - ** Process authorization warnings from command line. + ** Do more command line checking -- these are things that + ** have to modify the results of reading the config file. */ + /* process authorization warnings from command line */ if (warn_C_flag) auth_warning(CurEnv, "Processed by %s with -C %s", RealUserName, ConfFile); -/* - if (warn_f_flag != '\0') - auth_warning(CurEnv, "%s set sender to %s using -%c", - RealUserName, from, warn_f_flag); -*/ if (Warn_Q_option) auth_warning(CurEnv, "Processed from queue %s", QueueDir); + /* check body type for legality */ + if (CurEnv->e_bodytype == NULL) + /* nothing */ ; + else if (strcasecmp(CurEnv->e_bodytype, "7BIT") == 0) + SevenBitInput = TRUE; + else if (strcasecmp(CurEnv->e_bodytype, "8BITMIME") == 0) + SevenBitInput = FALSE; + else + { + usrerr("Illegal body type %s", CurEnv->e_bodytype); + CurEnv->e_bodytype = NULL; + } + /* Enforce use of local time (null string overrides this) */ if (TimeZoneSpec == NULL) unsetenv("TZ"); else if (TimeZoneSpec[0] != '\0') - { - char **evp = UserEnviron; - char tzbuf[100]; - - strcpy(tzbuf, "TZ="); - strcpy(&tzbuf[3], TimeZoneSpec); - - while (*evp != NULL && strncmp(*evp, "TZ=", 3) != 0) - evp++; - if (*evp == NULL) - { - *evp++ = newstr(tzbuf); - *evp = NULL; - } - else - *evp++ = newstr(tzbuf); - } + setuserenv("TZ", TimeZoneSpec); + else + setuserenv("TZ", NULL); + tzset(); + /* check for sane configuration level */ if (ConfigLevel > MAXCONFIGLEVEL) { syserr("Warning: .cf version level (%d) exceeds program functionality (%d)", @@ -712,32 +785,24 @@ main(argc, argv, envp) if (MeToo) BlankEnvelope.e_flags |= EF_METOO; -# ifdef QUEUE - if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) + switch (OpMode) { - struct stat stbuf; + case MD_DAEMON: + /* remove things that don't make sense in daemon mode */ + FullName = NULL; + GrabTo = FALSE; - /* check to see if we own the queue directory */ - if (stat(QueueDir, &stbuf) < 0) - syserr("main: cannot stat %s", QueueDir); - if (stbuf.st_uid != RealUid) - { - /* nope, really a botch */ - usrerr("You do not have permission to process the queue"); - exit (EX_NOPERM); - } - } -# endif /* QUEUE */ + /* arrange to restart on hangup signal */ + setsignal(SIGHUP, sighup); + break; - switch (OpMode) - { case MD_INITALIAS: Verbose = TRUE; - break; + /* fall through... */ - case MD_DAEMON: - /* remove things that don't make sense in daemon mode */ - FullName = NULL; + default: + /* arrange to exit cleanly on hangup signal */ + setsignal(SIGHUP, intsig); break; } @@ -760,31 +825,56 @@ main(argc, argv, envp) UseErrorsTo = TRUE; } + /* set options that were previous macros */ + if (SmtpGreeting == NULL) + { + if (ConfigLevel < 7 && (p = macvalue('e', CurEnv)) != NULL) + SmtpGreeting = newstr(p); + else + SmtpGreeting = "\201j Sendmail \201v ready at \201b"; + } + if (UnixFromLine == NULL) + { + if (ConfigLevel < 7 && (p = macvalue('l', CurEnv)) != NULL) + UnixFromLine = newstr(p); + else + UnixFromLine = "From \201g \201d"; + } + /* our name for SMTP codes */ - expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv); + expand("\201j", jbuf, sizeof jbuf, CurEnv); MyHostName = jbuf; + if (strchr(jbuf, '.') == NULL) + message("WARNING: local host name (%s) is not qualified; fix $j in config file", + jbuf); /* make certain that this name is part of the $=w class */ setclass('w', MyHostName); /* the indices of built-in mailers */ st = stab("local", ST_MAILER, ST_FIND); - if (st == NULL) - syserr("No local mailer defined"); - else + if (st != NULL) LocalMailer = st->s_mailer; + else if (OpMode != MD_TEST || !warn_C_flag) + syserr("No local mailer defined"); st = stab("prog", ST_MAILER, ST_FIND); if (st == NULL) syserr("No prog mailer defined"); else + { ProgMailer = st->s_mailer; + clrbitn(M_MUSER, ProgMailer->m_flags); + } st = stab("*file*", ST_MAILER, ST_FIND); if (st == NULL) syserr("No *file* mailer defined"); else + { FileMailer = st->s_mailer; + clrbitn(M_MUSER, FileMailer->m_flags); + } st = stab("*include*", ST_MAILER, ST_FIND); if (st == NULL) @@ -792,6 +882,39 @@ main(argc, argv, envp) else InclMailer = st->s_mailer; + if (ConfigLevel < 6) + { + /* heuristic tweaking of local mailer for back compat */ + if (LocalMailer != NULL) + { + setbitn(M_ALIASABLE, LocalMailer->m_flags); + setbitn(M_HASPWENT, LocalMailer->m_flags); + setbitn(M_TRYRULESET5, LocalMailer->m_flags); + setbitn(M_CHECKINCLUDE, LocalMailer->m_flags); + setbitn(M_CHECKPROG, LocalMailer->m_flags); + setbitn(M_CHECKFILE, LocalMailer->m_flags); + setbitn(M_CHECKUDB, LocalMailer->m_flags); + } + if (ProgMailer != NULL) + setbitn(M_RUNASRCPT, ProgMailer->m_flags); + if (FileMailer != NULL) + setbitn(M_RUNASRCPT, FileMailer->m_flags); + + /* propogate some envariables into children */ + setuserenv("ISP", NULL); + setuserenv("SYSTYPE", NULL); + } + + /* MIME Content-Types that cannot be transfer encoded */ + setclass('n', "multipart/signed"); + + /* MIME message/* subtypes that can be treated as messages */ + setclass('s', "rfc822"); + + /* MIME Content-Transfer-Encodings that can be encoded */ + setclass('e', "7bit"); + setclass('e', "8bit"); + setclass('e', "binary"); /* operate in queue directory */ if (OpMode != MD_TEST && chdir(QueueDir) < 0) @@ -800,14 +923,32 @@ main(argc, argv, envp) ExitStat = EX_SOFTWARE; } +# ifdef QUEUE + if (queuemode && RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) + { + struct stat stbuf; + + /* check to see if we own the queue directory */ + if (stat(".", &stbuf) < 0) + syserr("main: cannot stat %s", QueueDir); + if (stbuf.st_uid != RealUid) + { + /* nope, really a botch */ + usrerr("You do not have permission to process the queue"); + exit (EX_NOPERM); + } + } +# endif /* QUEUE */ + /* if we've had errors so far, exit now */ if (ExitStat != EX_OK && OpMode != MD_TEST) { + endpwent(); setuid(RealUid); exit(ExitStat); } -#ifdef XDEBUG +#if XDEBUG checkfd012("before main() initmaps"); #endif @@ -822,6 +963,7 @@ main(argc, argv, envp) #ifdef QUEUE dropenvelope(CurEnv); printqueue(); + endpwent(); setuid(RealUid); exit(EX_OK); #else /* QUEUE */ @@ -832,10 +974,12 @@ main(argc, argv, envp) case MD_INITALIAS: /* initialize alias database */ initmaps(TRUE, CurEnv); + endpwent(); setuid(RealUid); exit(EX_OK); case MD_DAEMON: + case MD_SMTP: /* don't open alias database -- done in srvrsmtp */ break; @@ -848,35 +992,12 @@ main(argc, argv, envp) if (tTd(0, 15)) { /* print configuration table (or at least part of it) */ - printrules(); + if (tTd(0, 90)) + printrules(); for (i = 0; i < MAXMAILERS; i++) { - register struct mailer *m = Mailer[i]; - int j; - - if (m == NULL) - continue; - printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld F=", i, m->m_name, - m->m_mailer, m->m_se_rwset, m->m_sh_rwset, - m->m_re_rwset, m->m_rh_rwset, m->m_maxsize); - for (j = '\0'; j <= '\177'; j++) - if (bitnset(j, m->m_flags)) - (void) putchar(j); - printf(" E="); - xputs(m->m_eol); - if (m->m_argv != NULL) - { - char **a = m->m_argv; - - printf(" A="); - while (*a != NULL) - { - if (a != m->m_argv) - printf(" "); - xputs(*a++); - } - } - printf("\n"); + if (Mailer[i] != NULL) + printmailer(Mailer[i]); } } @@ -894,6 +1015,7 @@ main(argc, argv, envp) if (OpMode == MD_TEST) { char buf[MAXLINE]; + void intindebug(); if (isatty(fileno(stdin))) Verbose = TRUE; @@ -903,69 +1025,24 @@ main(argc, argv, envp) printf("ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n"); printf("Enter <ruleset> <address>\n"); } + if (setjmp(TopFrame) > 0) + printf("\n"); + (void) setsignal(SIGINT, intindebug); for (;;) { - register char **pvp; - char *q; - auto char *delimptr; - extern bool invalidaddr(); - extern char *crackaddr(); + extern void testmodeline __P((char *, ENVELOPE *)); if (Verbose) printf("> "); (void) fflush(stdout); if (fgets(buf, sizeof buf, stdin) == NULL) finis(); + p = strchr(buf, '\n'); + if (p != NULL) + *p = '\0'; if (!Verbose) - printf("> %s", buf); - switch (buf[0]) - { - case '#': - continue; - -#ifdef MAYBENEXTRELEASE - case 'C': /* try crackaddr */ - q = crackaddr(&buf[1]); - xputs(q); - printf("\n"); - continue; -#endif - } - - for (p = buf; isascii(*p) && isspace(*p); p++) - continue; - q = p; - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - if (*p == '\0') - { - printf("No address!\n"); - continue; - } - *p = '\0'; - if (invalidaddr(p + 1, NULL)) - continue; - do - { - char pvpbuf[PSBUFSIZE]; - - pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, - &delimptr); - if (pvp == NULL) - continue; - p = q; - while (*p != '\0') - { - int stat; - - stat = rewrite(pvp, atoi(p), 0, CurEnv); - if (stat != EX_OK) - printf("== Ruleset %s status %d\n", - p, stat); - while (*p != '\0' && *p++ != ',') - continue; - } - } while (*(p = delimptr) != '\0'); + printf("> %s\n", buf); + testmodeline(buf, CurEnv); } } @@ -976,6 +1053,7 @@ main(argc, argv, envp) if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0) { + (void) unsetenv("HOSTALIASES"); runqueue(FALSE); finis(); } @@ -994,7 +1072,7 @@ main(argc, argv, envp) { char dtype[200]; - if (!tTd(0, 1)) + if (!tTd(99, 100)) { /* put us in background */ i = fork(); @@ -1066,11 +1144,12 @@ main(argc, argv, envp) { CurEnv->e_sendmode = SM_VERIFY; CurEnv->e_errormode = EM_QUIET; + PostMasterCopy = NULL; } else { /* interactive -- all errors are global */ - CurEnv->e_flags |= EF_GLOBALERRS; + CurEnv->e_flags |= EF_GLOBALERRS|EF_LOGSENDER; } /* @@ -1078,6 +1157,9 @@ main(argc, argv, envp) */ initsys(CurEnv); + if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't')) + auth_warning(CurEnv, "%s set sender to %s using -%c", + RealUserName, from, warn_f_flag); setsender(from, CurEnv, NULL, FALSE); if (macvalue('s', CurEnv) == NULL) define('s', RealHostName, CurEnv); @@ -1089,7 +1171,7 @@ main(argc, argv, envp) /* collect body for UUCP return */ if (OpMode != MD_VERIFY) - collect(FALSE, FALSE, CurEnv); + collect(InChannel, FALSE, FALSE, NULL, CurEnv); finis(); } @@ -1111,7 +1193,7 @@ main(argc, argv, envp) if (OpMode != MD_VERIFY || GrabTo) { CurEnv->e_flags |= EF_GLOBALERRS; - collect(FALSE, FALSE, CurEnv); + collect(InChannel, FALSE, FALSE, NULL, CurEnv); } errno = 0; @@ -1139,6 +1221,15 @@ main(argc, argv, envp) finis(); } + + +void +intindebug() +{ + longjmp(TopFrame, 1); +} + + /* ** FINIS -- Clean up and exit. ** @@ -1152,12 +1243,18 @@ main(argc, argv, envp) ** exits sendmail */ +void finis() { if (tTd(2, 1)) - printf("\n====finis: stat %d e_flags %o, e_id=%s\n", - ExitStat, CurEnv->e_flags, + { + extern void printenvflags(); + + printf("\n====finis: stat %d e_id=%s e_flags=", + ExitStat, CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); + printenvflags(CurEnv); + } if (tTd(2, 9)) printopenfds(FALSE); @@ -1178,10 +1275,11 @@ finis() if (LogLevel > 78) syslog(LOG_DEBUG, "finis, pid=%d", getpid()); # endif /* LOG */ - if (ExitStat == EX_TEMPFAIL) + if (ExitStat == EX_TEMPFAIL || CurEnv->e_errormode == EM_BERKNET) ExitStat = EX_OK; /* reset uid for process accounting */ + endpwent(); setuid(RealUid); exit(ExitStat); @@ -1212,6 +1310,7 @@ intsig() #endif /* reset uid for process accounting */ + endpwent(); setuid(RealUid); exit(EX_OK); @@ -1255,12 +1354,18 @@ struct metamac MetaMacros[] = '\0' }; +#define MACBINDING(name, mid) \ + stab(name, ST_MACRO, ST_ENTER)->s_macro = mid; \ + MacroName[mid] = name; + +void initmacros(e) register ENVELOPE *e; { register struct metamac *m; - char buf[5]; register int c; + char buf[5]; + extern char *MacroName[256]; for (m = MetaMacros; m->metaname != '\0'; m++) { @@ -1277,11 +1382,11 @@ initmacros(e) } /* set defaults for some macros sendmail will use later */ - define('e', "\201j Sendmail \201v ready at \201b", e); - define('l', "From \201g \201d", e); define('n', "MAILER-DAEMON", e); - define('o', ".:@[]", e); - define('q', "<\201g>", e); + + /* set up external names for some internal macros */ + MACBINDING("opMode", MID_OPMODE); + /*XXX should probably add equivalents for all short macros here XXX*/ } /* ** DISCONNECT -- remove our connection with any foreground process @@ -1303,6 +1408,7 @@ initmacros(e) ** the controlling tty. */ +void disconnect(droplev, e) int droplev; register ENVELOPE *e; @@ -1312,14 +1418,13 @@ disconnect(droplev, e) if (tTd(52, 1)) printf("disconnect: In %d Out %d, e=%x\n", fileno(InChannel), fileno(OutChannel), e); - if (tTd(52, 5)) + if (tTd(52, 100)) { printf("don't\n"); return; } /* be sure we don't get nasty signals */ - (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGINT, SIG_IGN); (void) setsignal(SIGQUIT, SIG_IGN); @@ -1363,7 +1468,7 @@ disconnect(droplev, e) errno = 0; } -#ifdef XDEBUG +#if XDEBUG checkfd012("disconnect"); #endif @@ -1391,7 +1496,11 @@ obsolete(argv) /* skip over options that do have a value */ op = strchr(OPTIONS, ap[1]); if (op != NULL && *++op == ':' && ap[2] == '\0' && - ap[1] != 'd' && argv[1] != NULL && argv[1][0] != '-') + ap[1] != 'd' && +#if defined(sony_news) + ap[1] != 'E' && ap[1] != 'J' && +#endif + argv[1] != NULL && argv[1][0] != '-') { argv++; continue; @@ -1414,6 +1523,16 @@ obsolete(argv) /* if -d doesn't have an argument, use 0-99.1 */ if (ap[1] == 'd' && ap[2] == '\0') *argv = "-d0-99.1"; + +# if defined(sony_news) + /* if -E doesn't have an argument, use -EC */ + if (ap[1] == 'E' && ap[2] == '\0') + *argv = "-EC"; + + /* if -J doesn't have an argument, use -JJ */ + if (ap[1] == 'J' && ap[2] == '\0') + *argv = "-JJ"; +# endif } } /* @@ -1445,7 +1564,7 @@ auth_warning(e, msg, va_alist) { register char *p; static char hostbuf[48]; - extern char **myhostname(); + extern struct hostent *myhostname(); if (hostbuf[0] == '\0') (void) myhostname(hostbuf, sizeof hostbuf); @@ -1453,10 +1572,67 @@ auth_warning(e, msg, va_alist) (void) sprintf(buf, "%s: ", hostbuf); p = &buf[strlen(buf)]; VA_START(msg); - vsprintf(p, msg, ap); + vsnprintf(p, sizeof buf - (p - buf), msg, ap); VA_END; - addheader("X-Authentication-Warning", buf, e); + addheader("X-Authentication-Warning", buf, &e->e_header); +#ifdef LOG + if (LogLevel > 3) + syslog(LOG_INFO, "%s: Authentication-Warning: %.400s", + e->e_id == NULL ? "[NOQUEUE]" : e->e_id, buf); +#endif + } +} +/* +** SETUSERENV -- set an environment in the propogated environment +** +** Parameters: +** envar -- the name of the environment variable. +** value -- the value to which it should be set. If +** null, this is extracted from the incoming +** environment. If that is not set, the call +** to setuserenv is ignored. +** +** Returns: +** none. +*/ + +void +setuserenv(envar, value) + const char *envar; + const char *value; +{ + int i; + char **evp = UserEnviron; + char *p; + + if (value == NULL) + { + value = getenv(envar); + if (value == NULL) + return; + } + + i = strlen(envar); + p = (char *) xalloc(strlen(value) + i + 2); + strcpy(p, envar); + p[i++] = '='; + strcpy(&p[i], value); + + while (*evp != NULL && strncmp(*evp, p, i) != 0) + evp++; + if (*evp != NULL) + { + *evp++ = p; + } + else if (evp < &UserEnviron[MAXUSERENVIRON]) + { + *evp++ = p; + *evp = NULL; } + + /* make sure it is in our environment as well */ + if (putenv(p) < 0) + syserr("setuserenv: putenv(%s) failed", p); } /* ** DUMPSTATE -- dump state @@ -1470,17 +1646,16 @@ dumpstate(when) { #ifdef LOG register char *j = macvalue('j', CurEnv); - register STAB *s; syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---", when, j == NULL ? "<NULL>" : j); if (j != NULL) { - s = stab(j, ST_CLASS, ST_FIND); - if (s == NULL || !bitnset('w', s->s_class)) + if (!wordinclass(j, 'w')) syslog(LOG_DEBUG, "*** $j not in $=w ***"); } + syslog(LOG_DEBUG, "CurChildren = %d", CurChildren); syslog(LOG_DEBUG, "--- open file descriptors: ---"); printopenfds(TRUE); syslog(LOG_DEBUG, "--- connection cache: ---"); @@ -1508,3 +1683,431 @@ sigusr1() { dumpstate("user signal"); } + + +void +sighup() +{ +#ifdef LOG + if (LogLevel > 3) + syslog(LOG_INFO, "restarting %s on signal", SaveArgv[0]); +#endif + releasesignal(SIGHUP); + execv(SaveArgv[0], (ARGV_T) SaveArgv); +#ifdef LOG + if (LogLevel > 0) + syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]); +#endif + exit(EX_OSFILE); +} +/* +** TESTMODELINE -- process a test mode input line +** +** Parameters: +** line -- the input line. +** e -- the current environment. +** Syntax: +** # a comment +** .X process X as a configuration line +** =X dump a configuration item (such as mailers) +** $X dump a macro or class +** /X try an activity +** X normal process through rule set X +*/ + +void +testmodeline(line, e) + char *line; + ENVELOPE *e; +{ + register char *p; + char *q; + auto char *delimptr; + int mid; + int i, rs; + STAB *map; + char **s; + struct rewrite *rw; + ADDRESS a; + static int tryflags = RF_COPYNONE; + char exbuf[MAXLINE]; + extern bool invalidaddr __P((char *, char *)); + extern char *crackaddr __P((char *)); + extern void dump_class __P((STAB *, int)); + extern void translate_dollars __P((char *)); + + switch (line[0]) + { + case '#': + case 0: + return; + + case '?': + help("-bt"); + return; + + case '.': /* config-style settings */ + switch (line[1]) + { + case 'D': + mid = macid(&line[2], &delimptr); + if (mid == '\0') + return; + translate_dollars(delimptr); + define(mid, newstr(delimptr), e); + break; + + case 'C': + if (line[2] == '\0') /* not to call syserr() */ + return; + + mid = macid(&line[2], &delimptr); + if (mid == '\0') + return; + translate_dollars(delimptr); + expand(delimptr, exbuf, sizeof exbuf, e); + p = exbuf; + while (*p != '\0') + { + register char *wd; + char delim; + + while (*p != '\0' && isascii(*p) && isspace(*p)) + p++; + wd = p; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + delim = *p; + *p = '\0'; + if (wd[0] != '\0') + setclass(mid, wd); + *p = delim; + } + break; + + case '\0': + printf("Usage: .[DC]macro value(s)\n"); + break; + + default: + printf("Unknown \".\" command %s\n", line); + break; + } + return; + + case '=': /* config-style settings */ + switch (line[1]) + { + case 'S': /* dump rule set */ + rs = strtorwset(&line[2], NULL, ST_FIND); + if (rs < 0) + return; + rw = RewriteRules[rs]; + if (rw == NULL) + return; + do + { + putchar('R'); + s = rw->r_lhs; + while (*s != NULL) + { + xputs(*s++); + putchar(' '); + } + putchar('\t'); + putchar('\t'); + s = rw->r_rhs; + while (*s != NULL) + { + xputs(*s++); + putchar(' '); + } + putchar('\n'); + } while (rw = rw->r_next); + break; + + case 'M': + for (i = 0; i < MAXMAILERS; i++) + { + if (Mailer[i] != NULL) + printmailer(Mailer[i]); + } + break; + + case '\0': + printf("Usage: =Sruleset or =M\n"); + break; + + default: + printf("Unknown \"=\" command %s\n", line); + break; + } + return; + + case '-': /* set command-line-like opts */ + switch (line[1]) + { + case 'd': + tTflag(&line[2]); + break; + + case '\0': + printf("Usage: -d{debug arguments}\n"); + break; + + default: + printf("Unknown \"-\" command %s\n", line); + break; + } + return; + + case '$': + if (line[1] == '=') + { + mid = macid(&line[2], NULL); + if (mid != '\0') + stabapply(dump_class, mid); + return; + } + mid = macid(&line[1], NULL); + if (mid == '\0') + return; + p = macvalue(mid, e); + if (p == NULL) + printf("Undefined\n"); + else + { + xputs(p); + printf("\n"); + } + return; + + case '/': /* miscellaneous commands */ + p = &line[strlen(line)]; + while (--p >= line && isascii(*p) && isspace(*p)) + *p = '\0'; + p = strpbrk(line, " \t"); + if (p != NULL) + { + while (isascii(*p) && isspace(*p)) + *p++ = '\0'; + } + else + p = ""; + if (line[1] == '\0') + { + printf("Usage: /[canon|map|mx|parse|try|tryflags]\n"); + return; + } + if (strcasecmp(&line[1], "mx") == 0) + { +#if NAMED_BIND + /* look up MX records */ + int nmx; + auto int rcode; + char *mxhosts[MAXMXHOSTS + 1]; + + if (*p == '\0') + { + printf("Usage: /mx address\n"); + return; + } + nmx = getmxrr(p, mxhosts, FALSE, &rcode); + printf("getmxrr(%s) returns %d value(s):\n", p, nmx); + for (i = 0; i < nmx; i++) + printf("\t%s\n", mxhosts[i]); +#else + printf("No MX code compiled in\n"); +#endif + } + else if (strcasecmp(&line[1], "canon") == 0) + { + auto int rcode = EX_OK; + char host[MAXHOSTNAMELEN]; + + if (*p == '\0') + { + printf("Usage: /canon address\n"); + return; + } + strcpy(host, p); + getcanonname(host, sizeof(host), HasWildcardMX, &rcode); + printf("getcanonname(%s) returns %s (%d)\n", + p, host, rcode); + } + else if (strcasecmp(&line[1], "map") == 0) + { + auto int rcode = EX_OK; + + if (*p == '\0') + { + printf("Usage: /map mapname key\n"); + return; + } + for (q = p; *q != '\0' && !isspace(*q); q++) + continue; + if (*q == '\0') + { + printf("No key specified\n"); + return; + } + *q++ = '\0'; + map = stab(p, ST_MAP, ST_FIND); + if (map == NULL) + { + printf("Map named \"%s\" not found\n", p); + return; + } + printf("map_lookup: %s (%s) ", p, q); + p = (*map->s_map.map_class->map_lookup) + (&map->s_map, q, NULL, &rcode); + if (p == NULL) + printf("no match (%d)\n", rcode); + else + printf("returns %s (%d)\n", p, rcode); + } + else if (strcasecmp(&line[1], "try") == 0) + { + MAILER *m; + STAB *s; + auto int rcode = EX_OK; + + q = strpbrk(p, " \t"); + if (q != NULL) + { + while (isascii(*q) && isspace(*q)) + *q++ = '\0'; + } + if (q == NULL || *q == '\0') + { + printf("Usage: /try mailer address\n"); + return; + } + s = stab(p, ST_MAILER, ST_FIND); + if (s == NULL) + { + printf("Unknown mailer %s\n", p); + return; + } + m = s->s_mailer; + printf("Trying %s %s address %s for mailer %s\n", + bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope", + bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient", + q, p); + p = remotename(q, m, tryflags, &rcode, CurEnv); + printf("Rcode = %d, addr = %s\n", + rcode, p == NULL ? "<NULL>" : p); + } + else if (strcasecmp(&line[1], "tryflags") == 0) + { + if (*p == '\0') + { + printf("Usage: /tryflags [Hh|Ee][Ss|Rr]\n"); + return; + } + for (; *p != '\0'; p++) + { + switch (*p) + { + case 'H': + case 'h': + tryflags |= RF_HEADERADDR; + break; + + case 'E': + case 'e': + tryflags &= ~RF_HEADERADDR; + break; + + case 'S': + case 's': + tryflags |= RF_SENDERADDR; + break; + + case 'R': + case 'r': + tryflags &= ~RF_SENDERADDR; + break; + } + } + } + else if (strcasecmp(&line[1], "parse") == 0) + { + if (*p == '\0') + { + printf("Usage: /parse address\n"); + return; + } + q = crackaddr(p); + printf("Cracked address = "); + xputs(q); + printf("\nParsing %s %s address\n", + bitset(RF_HEADERADDR, tryflags) ? "header" : "envelope", + bitset(RF_SENDERADDR, tryflags) ? "sender" : "recipient"); + if (parseaddr(p, &a, tryflags, '\0', NULL, e) == NULL) + printf("Cannot parse\n"); + else if (a.q_host != NULL && a.q_host[0] != '\0') + printf("mailer %s, host %s, user %s\n", + a.q_mailer->m_name, a.q_host, a.q_user); + else + printf("mailer %s, user %s\n", + a.q_mailer->m_name, a.q_user); + } + else + { + printf("Unknown \"/\" command %s\n", line); + } + return; + } + + for (p = line; isascii(*p) && isspace(*p); p++) + continue; + q = p; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p == '\0') + { + printf("No address!\n"); + return; + } + *p = '\0'; + if (invalidaddr(p + 1, NULL)) + return; + do + { + register char **pvp; + char pvpbuf[PSBUFSIZE]; + + pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, + &delimptr, NULL); + if (pvp == NULL) + continue; + p = q; + while (*p != '\0') + { + int stat; + int rs = strtorwset(p, NULL, ST_FIND); + + if (rs < 0) + break; + stat = rewrite(pvp, rs, 0, e); + if (stat != EX_OK) + printf("== Ruleset %s (%d) status %d\n", + p, rs, stat); + while (*p != '\0' && *p++ != ',') + continue; + } + } while (*(p = delimptr) != '\0'); +} + + +void +dump_class(s, id) + register STAB *s; + int id; +{ + if (s->s_type != ST_CLASS) + return; + if (bitnset(id & 0xff, s->s_class)) + printf("%s\n", s->s_name); +} diff --git a/usr.sbin/sendmail/src/parseaddr.c b/usr.sbin/sendmail/src/parseaddr.c index 2683728..debccdf 100644 --- a/usr.sbin/sendmail/src/parseaddr.c +++ b/usr.sbin/sendmail/src/parseaddr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.31 (Berkeley) 4/15/94"; +static char sccsid[] = "@(#)parseaddr.c 8.86 (Berkeley) 9/28/95"; #endif /* not lint */ # include "sendmail.h" @@ -91,6 +91,7 @@ parseaddr(addr, a, flags, delim, delimptr, e) char pvpbuf[PSBUFSIZE]; extern ADDRESS *buildaddr(); extern bool invalidaddr(); + extern void allocaddr __P((ADDRESS *, int, char *)); /* ** Initialize and prescan address. @@ -103,7 +104,7 @@ parseaddr(addr, a, flags, delim, delimptr, e) if (delimptr == NULL) delimptr = &delimptrbuf; - pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr); + pvp = prescan(addr, delim, pvpbuf, sizeof pvpbuf, delimptr, NULL); if (pvp == NULL) { if (tTd(20, 1)) @@ -172,12 +173,15 @@ parseaddr(addr, a, flags, delim, delimptr, e) { char *msg = "Transient parse error -- message queued for future delivery"; + if (e->e_sendmode == SM_DEFER) + msg = "Deferring message until queue run"; if (tTd(20, 1)) printf("parseaddr: queuing message\n"); message(msg); - if (e->e_message == NULL) + if (e->e_message == NULL && e->e_sendmode != SM_DEFER) e->e_message = newstr(msg); a->q_flags |= QQUEUEUP; + a->q_status = "4.4.3"; } /* @@ -208,7 +212,7 @@ invalidaddr(addr, delimptr) register char *addr; char *delimptr; { - char savedelim; + char savedelim = '\0'; if (delimptr != NULL) { @@ -231,14 +235,14 @@ invalidaddr(addr, delimptr) } if (*addr == '\0') { - if (savedelim != '\0' && delimptr != NULL) + if (delimptr != NULL && savedelim != '\0') *delimptr = savedelim; return FALSE; } setstat(EX_USAGE); usrerr("553 Address contained invalid control characters"); addrfailure: - if (savedelim != '\0' && delimptr != NULL) + if (delimptr != NULL && savedelim != '\0') *delimptr = savedelim; return TRUE; } @@ -260,13 +264,14 @@ invalidaddr(addr, delimptr) ** Copies portions of a into local buffers as requested. */ +void allocaddr(a, flags, paddr) register ADDRESS *a; int flags; char *paddr; { if (tTd(24, 4)) - printf("allocaddr(flags=%o, paddr=%s)\n", flags, paddr); + printf("allocaddr(flags=%x, paddr=%s)\n", flags, paddr); a->q_paddr = paddr; @@ -311,6 +316,8 @@ allocaddr(a, flags, paddr) ** pvpbsize -- size of pvpbuf. ** delimptr -- if non-NULL, set to the location of the ** terminating delimiter. +** toktab -- if set, a token table to use for parsing. +** If NULL, use the default table. ** ** Returns: ** A pointer to a vector of tokens. @@ -323,8 +330,9 @@ allocaddr(a, flags, paddr) # define QST 2 /* in quoted string */ # define SPC 3 /* chewing up spaces */ # define ONE 4 /* pick up one character */ +# define ILL 5 /* illegal character */ -# define NSTATES 5 /* number of states */ +# define NSTATES 6 /* number of states */ # define TYPE 017 /* mask to select state type */ /* meta bits for table */ @@ -334,46 +342,102 @@ allocaddr(a, flags, paddr) static short StateTab[NSTATES][NSTATES] = { - /* oldst chtype> OPR ATM QST SPC ONE */ - /*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, - /*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B, - /*QST*/ QST, QST, OPR, QST, QST, - /*SPC*/ OPR, ATM, QST, SPC|M, ONE, - /*ONE*/ OPR, OPR, OPR, OPR, OPR, + /* oldst chtype> OPR ATM QST SPC ONE ILL */ + /*OPR*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|MB, + /*ATM*/ OPR|B, ATM, QST|B, SPC|MB, ONE|B, ILL|MB, + /*QST*/ QST, QST, OPR, QST, QST, QST, + /*SPC*/ OPR, ATM, QST, SPC|M, ONE, ILL|MB, + /*ONE*/ OPR, OPR, OPR, OPR, OPR, ILL|MB, + /*ILL*/ OPR|B, ATM|B, QST|B, SPC|MB, ONE|B, ILL|M, }; /* token type table -- it gets modified with $o characters */ -static TokTypeTab[256] = +static u_char TokTypeTab[256] = { - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM,ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, - OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, - ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,SPC,SPC,SPC,SPC,SPC,ATM,ATM, + /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* sp ! " # $ % & ' ( ) * + , - . / */ + SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,ATM,ATM,ATM,ATM, + /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* @ A B C D E F G H I J K L M N O */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* P Q R S T U V W X Y Z [ \ ] ^ _ */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* ` a b c d e f g h i j k l m n o */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* p q r s t u v w x y z { | } ~ del */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + + /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ + OPR,OPR,ONE,OPR,OPR,OPR,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, + /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ + OPR,OPR,OPR,ONE,ONE,ONE,OPR,OPR, OPR,OPR,OPR,OPR,OPR,OPR,OPR,OPR, + /* sp ! " # $ % & ' ( ) * + , - . / */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* @ A B C D E F G H I J K L M N O */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* P Q R S T U V W X Y Z [ \ ] ^ _ */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* ` a b c d e f g h i j k l m n o */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* p q r s t u v w x y z { | } ~ del */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, }; -#define toktype(c) ((int) TokTypeTab[(c) & 0xff]) +/* token type table for MIME parsing */ +u_char MimeTokenTab[256] = +{ + /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,SPC,SPC,SPC,SPC,SPC,ILL,ILL, + /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* sp ! " # $ % & ' ( ) * + , - . / */ + SPC,ATM,QST,ATM,ATM,ATM,ATM,ATM, ATM,SPC,ATM,ATM,OPR,ATM,ATM,OPR, + /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,OPR,OPR,OPR,OPR,OPR,OPR, + /* @ A B C D E F G H I J K L M N O */ + OPR,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* P Q R S T U V W X Y Z [ \ ] ^ _ */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,OPR,OPR,OPR,ATM,ATM, + /* ` a b c d e f g h i j k l m n o */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + /* p q r s t u v w x y z { | } ~ del */ + ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, + + /* nul soh stx etx eot enq ack bel bs ht nl vt np cr so si */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* sp ! " # $ % & ' ( ) * + , - . / */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* @ A B C D E F G H I J K L M N O */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* P Q R S T U V W X Y Z [ \ ] ^ _ */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* ` a b c d e f g h i j k l m n o */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, + /* p q r s t u v w x y z { | } ~ del */ + ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, ILL,ILL,ILL,ILL,ILL,ILL,ILL,ILL, +}; # define NOCHAR -1 /* signal nothing in lookahead token */ char ** -prescan(addr, delim, pvpbuf, pvpbsize, delimptr) +prescan(addr, delim, pvpbuf, pvpbsize, delimptr, toktab) char *addr; - char delim; + int delim; char pvpbuf[]; + int pvpbsize; char **delimptr; + u_char *toktab; { register char *p; register char *q; @@ -396,7 +460,14 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr) char obuf[50]; firsttime = FALSE; - expand("\201o", obuf, &obuf[sizeof obuf - sizeof DELIMCHARS], CurEnv); + if (OperatorChars == NULL) + { + if (ConfigLevel < 7) + OperatorChars = macvalue('o', CurEnv); + if (OperatorChars == NULL) + OperatorChars = ".:@[]"; + } + expand(OperatorChars, obuf, sizeof obuf - sizeof DELIMCHARS, CurEnv); strcat(obuf, DELIMCHARS); for (p = obuf; *p != '\0'; p++) { @@ -404,6 +475,8 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr) TokTypeTab[*p & 0xff] = OPR; } } + if (toktab == NULL) + toktab = TokTypeTab; /* make sure error messages don't have garbage on them */ errno = 0; @@ -437,6 +510,8 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr) if (q >= &pvpbuf[pvpbsize - 5]) { usrerr("553 Address too long"); + if (strlen(addr) > MAXNAME) + addr[MAXNAME] = '\0'; returnnull: if (delimptr != NULL) *delimptr = p; @@ -546,10 +621,17 @@ prescan(addr, delim, pvpbuf, pvpbsize, delimptr) if (c == delim && anglecnt <= 0 && state != QST) break; - newstate = StateTab[state][toktype(c)]; + newstate = StateTab[state][toktab[c & 0xff]]; if (tTd(22, 101)) printf("ns=%02o\n", newstate); state = newstate & TYPE; + if (state == ILL) + { + if (isascii(c) && isprint(c)) + usrerr("653 Illegal character %c", c); + else + usrerr("653 Illegal character 0x%02x", c); + } if (bitset(M, newstate)) c = NOCHAR; if (bitset(B, newstate)) @@ -642,10 +724,6 @@ struct match # define MAXMATCH 9 /* max params per rewrite */ -# ifndef MAXRULERECURSION -# define MAXRULERECURSION 50 /* max recursion depth */ -# endif - int rewrite(pvp, ruleset, reclevel, e) @@ -666,7 +744,7 @@ rewrite(pvp, ruleset, reclevel, e) struct match mlist[MAXMATCH]; /* stores match on LHS */ char *npvp[MAXATOM+1]; /* temporary space for rebuild */ - if (OpMode == MD_TEST || tTd(21, 2)) + if (OpMode == MD_TEST || tTd(21, 1)) { printf("rewrite: ruleset %2d input:", ruleset); printav(pvp); @@ -676,9 +754,10 @@ rewrite(pvp, ruleset, reclevel, e) syserr("554 rewrite: illegal ruleset number %d", ruleset); return EX_CONFIG; } - if (reclevel++ > MAXRULERECURSION) + if (reclevel++ > MaxRuleRecursion) { - syserr("rewrite: infinite recursion, ruleset %d", ruleset); + syserr("rewrite: excessive recursion (max %d), ruleset %d", + MaxRuleRecursion, ruleset); return EX_CONFIG; } if (pvp == NULL) @@ -740,7 +819,6 @@ rewrite(pvp, ruleset, reclevel, e) switch (*rp & 0377) { - register STAB *s; char buf[MAXLINE]; case MATCHCLASS: @@ -753,8 +831,7 @@ rewrite(pvp, ruleset, reclevel, e) goto backup; mlp->last = avp++; cataddr(mlp->first, mlp->last, buf, sizeof buf, '\0'); - s = stab(buf, ST_CLASS, ST_FIND); - if (s == NULL || !bitnset(rp[1], s->s_class)) + if (!wordinclass(buf, rp[1])) { if (tTd(21, 36)) { @@ -773,8 +850,7 @@ rewrite(pvp, ruleset, reclevel, e) case MATCHNCLASS: /* match any token not in a class */ - s = stab(ap, ST_CLASS, ST_FIND); - if (s != NULL && bitnset(rp[1], s->s_class)) + if (wordinclass(ap, rp[1])) goto backup; /* fall through */ @@ -1097,10 +1173,22 @@ rewrite(pvp, ruleset, reclevel, e) /* look it up */ cataddr(key_rvp, NULL, buf, sizeof buf, '\0'); argvect[0] = buf; - if (map != NULL && bitset(MF_OPEN, map->s_map.map_mflags)) + 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)) @@ -1115,7 +1203,21 @@ rewrite(pvp, ruleset, reclevel, e) /* should recover if stat == EX_TEMPFAIL */ if (stat == EX_TEMPFAIL) - rstat = stat; + { + rstat = EX_TEMPFAIL; + if (tTd(60, 1)) + printf("map_lookup(%s, %s) tempfail: errno=%d\n", + mapname, buf, errno); + if (e->e_message == NULL) + { + char mbuf[300]; + + sprintf(mbuf, "%.80s map: lookup (%s): deferred", + mapname, + shortenstring(buf, 203)); + e->e_message = newstr(mbuf); + } + } } else replac = NULL; @@ -1142,7 +1244,7 @@ rewrite(pvp, ruleset, reclevel, e) { /* scan the new replacement */ xpvp = prescan(replac, '\0', pvpbuf, - sizeof pvpbuf, NULL); + sizeof pvpbuf, NULL, NULL); if (xpvp == NULL) { /* prescan already printed error */ @@ -1182,11 +1284,15 @@ rewrite(pvp, ruleset, reclevel, e) } 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]); - stat = rewrite(pvp, atoi(npvp[1]), reclevel, e); + 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) @@ -1205,7 +1311,7 @@ rewrite(pvp, ruleset, reclevel, e) } } - if (OpMode == MD_TEST || tTd(21, 2)) + if (OpMode == MD_TEST || tTd(21, 1)) { printf("rewrite: ruleset %2d returns:", ruleset); printav(pvp); @@ -1260,15 +1366,17 @@ buildaddr(tv, a, flags, e) { struct mailer **mp; register struct mailer *m; - char *bp; - int spaceleft; + register char *p; + char *mname; + char **hostp; + char hbuf[MAXNAME + 1]; static MAILER errormailer; static char *errorargv[] = { "ERROR", NULL }; - static char buf[MAXNAME]; + static char ubuf[MAXNAME + 1]; if (tTd(24, 5)) { - printf("buildaddr, flags=%o, tv=", flags); + printf("buildaddr, flags=%x, tv=", flags); printav(tv); } @@ -1276,10 +1384,13 @@ buildaddr(tv, a, flags, e) a = (ADDRESS *) xalloc(sizeof *a); bzero((char *) a, sizeof *a); + /* set up default error return flags */ + a->q_flags |= QPINGONFAILURE|QPINGONDELAY; + /* figure out what net/mailer to use */ if (*tv == NULL || (**tv & 0377) != CANONNET) { - syserr("554 buildaddr: no net"); + syserr("554 buildaddr: no mailer in parsed address"); badaddr: a->q_flags |= QBADADDR; a->q_mailer = &errormailer; @@ -1292,91 +1403,97 @@ badaddr: } return a; } - tv++; - if (strcasecmp(*tv, "error") == 0) + mname = *++tv; + + /* extract host and user portions */ + if ((**++tv & 0377) == CANONHOST) + hostp = ++tv; + else + hostp = NULL; + while (*tv != NULL && (**tv & 0377) != CANONUSER) + tv++; + if (*tv == NULL) { - if ((**++tv & 0377) == CANONHOST) + syserr("554 buildaddr: no user"); + goto badaddr; + } + if (tv == hostp) + hostp = NULL; + else if (hostp != NULL) + cataddr(hostp, tv - 1, hbuf, sizeof hbuf, '\0'); + cataddr(++tv, NULL, ubuf, sizeof ubuf, ' '); + + /* save away the host name */ + if (strcasecmp(mname, "error") == 0) + { + if (hostp != NULL) { register struct errcodes *ep; - if (isascii(**++tv) && isdigit(**tv)) + if (strchr(hbuf, '.') != NULL) + { + a->q_status = newstr(hbuf); + setstat(dsntoexitstat(hbuf)); + } + else if (isascii(hbuf[0]) && isdigit(hbuf[0])) { - setstat(atoi(*tv)); + setstat(atoi(hbuf)); } else { for (ep = ErrorCodes; ep->ec_name != NULL; ep++) - if (strcasecmp(ep->ec_name, *tv) == 0) + if (strcasecmp(ep->ec_name, hbuf) == 0) break; setstat(ep->ec_code); } - tv++; } else setstat(EX_UNAVAILABLE); - if ((**tv & 0377) != CANONUSER) - syserr("554 buildaddr: error: no user"); - cataddr(++tv, NULL, buf, sizeof buf, ' '); - stripquotes(buf); - if (isascii(buf[0]) && isdigit(buf[0]) && - isascii(buf[1]) && isdigit(buf[1]) && - isascii(buf[2]) && isdigit(buf[2]) && - buf[3] == ' ') + stripquotes(ubuf); + if (isascii(ubuf[0]) && isdigit(ubuf[0]) && + isascii(ubuf[1]) && isdigit(ubuf[1]) && + isascii(ubuf[2]) && isdigit(ubuf[2]) && + ubuf[3] == ' ') { char fmt[10]; - strncpy(fmt, buf, 3); + strncpy(fmt, ubuf, 3); strcpy(&fmt[3], " %s"); - usrerr(fmt, buf + 4); + usrerr(fmt, ubuf + 4); + + /* + ** If this is a 4xx code and we aren't running + ** SMTP on our input, bounce this message; + ** otherwise it disappears without a trace. + */ + + if (fmt[0] == '4' && OpMode != MD_SMTP && + OpMode != MD_DAEMON) + { + e->e_flags |= EF_FATALERRS; + } } else { - usrerr("553 %s", buf); + usrerr("553 %s", ubuf); } goto badaddr; } for (mp = Mailer; (m = *mp++) != NULL; ) { - if (strcasecmp(m->m_name, *tv) == 0) + if (strcasecmp(m->m_name, mname) == 0) break; } if (m == NULL) { - syserr("554 buildaddr: unknown mailer %s", *tv); + syserr("554 buildaddr: unknown mailer %s", mname); goto badaddr; } a->q_mailer = m; /* figure out what host (if any) */ - tv++; - if ((**tv & 0377) == CANONHOST) - { - bp = buf; - spaceleft = sizeof buf - 1; - while (*++tv != NULL && (**tv & 0377) != CANONUSER) - { - int i = strlen(*tv); - - if (i > spaceleft) - { - /* out of space for this address */ - if (spaceleft >= 0) - syserr("554 buildaddr: host too long (%.40s...)", - buf); - i = spaceleft; - spaceleft = 0; - } - if (i <= 0) - continue; - bcopy(*tv, bp, i); - bp += i; - spaceleft -= i; - } - *bp = '\0'; - a->q_host = newstr(buf); - } - else + if (hostp == NULL) { if (!bitnset(M_LOCALMAILER, m->m_flags)) { @@ -1385,47 +1502,38 @@ badaddr: } a->q_host = NULL; } + else + a->q_host = newstr(hbuf); /* figure out the user */ - if (*tv == NULL || (**tv & 0377) != CANONUSER) + p = ubuf; + if (bitnset(M_CHECKUDB, m->m_flags) && *p == '@') { - syserr("554 buildaddr: no user"); - goto badaddr; + p++; + tv++; + a->q_flags |= QNOTREMOTE; } - tv++; /* do special mapping for local mailer */ - if (m == LocalMailer && *tv != NULL) + if (*p == '"') + p++; + if (*p == '|' && bitnset(M_CHECKPROG, m->m_flags)) + a->q_mailer = m = ProgMailer; + else if (*p == '/' && bitnset(M_CHECKFILE, m->m_flags)) + a->q_mailer = m = FileMailer; + else if (*p == ':' && bitnset(M_CHECKINCLUDE, m->m_flags)) { - register char *p = *tv; - - if (*p == '"') - p++; - if (*p == '|') - a->q_mailer = m = ProgMailer; - else if (*p == '/') - a->q_mailer = m = FileMailer; - else if (*p == ':') + /* may be :include: */ + stripquotes(ubuf); + if (strncasecmp(ubuf, ":include:", 9) == 0) { - /* may be :include: */ - cataddr(tv, NULL, buf, sizeof buf, '\0'); - stripquotes(buf); - if (strncasecmp(buf, ":include:", 9) == 0) - { - /* if :include:, don't need further rewriting */ - a->q_mailer = m = InclMailer; - a->q_user = &buf[9]; - return (a); - } + /* if :include:, don't need further rewriting */ + a->q_mailer = m = InclMailer; + a->q_user = newstr(&ubuf[9]); + return a; } } - if (m == LocalMailer && *tv != NULL && strcmp(*tv, "@") == 0) - { - tv++; - a->q_flags |= QNOTREMOTE; - } - /* rewrite according recipient mailer rewriting rules */ define('h', a->q_host, e); if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) @@ -1438,8 +1546,8 @@ badaddr: (void) rewrite(tv, 4, 0, e); /* save the result for the command line/RCPT argument */ - cataddr(tv, NULL, buf, sizeof buf, '\0'); - a->q_user = buf; + cataddr(tv, NULL, ubuf, sizeof ubuf, '\0'); + a->q_user = ubuf; /* ** Do mapping to lower case as requested by mailer @@ -1450,7 +1558,12 @@ badaddr: if (!bitnset(M_USR_UPPER, m->m_flags)) makelower(a->q_user); - return (a); + if (tTd(24, 6)) + { + printf("buildaddr => "); + printaddr(a, FALSE); + } + return a; } /* ** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs) @@ -1471,12 +1584,13 @@ badaddr: ** Destroys buf. */ +void cataddr(pvp, evp, buf, sz, spacesub) char **pvp; char **evp; char *buf; register int sz; - char spacesub; + int spacesub; { bool oatomtok = FALSE; bool natomtok = FALSE; @@ -1495,7 +1609,7 @@ cataddr(pvp, evp, buf, sz, spacesub) sz -= 2; while (*pvp != NULL && (i = strlen(*pvp)) < sz) { - natomtok = (toktype(**pvp) == ATM); + natomtok = (TokTypeTab[**pvp & 0xff] == ATM); if (oatomtok && natomtok) *p++ = spacesub; (void) strcpy(p, *pvp); @@ -1580,17 +1694,55 @@ sameaddr(a, b) ** none. */ +struct qflags +{ + char *qf_name; + u_long qf_bit; +}; + +struct qflags AddressFlags[] = +{ + "QDONTSEND", QDONTSEND, + "QBADADDR", QBADADDR, + "QGOODUID", QGOODUID, + "QPRIMARY", QPRIMARY, + "QQUEUEUP", QQUEUEUP, + "QSENT", QSENT, + "QNOTREMOTE", QNOTREMOTE, + "QSELFREF", QSELFREF, + "QVERIFIED", QVERIFIED, + "QBOGUSSHELL", QBOGUSSHELL, + "QUNSAFEADDR", QUNSAFEADDR, + "QPINGONSUCCESS", QPINGONSUCCESS, + "QPINGONFAILURE", QPINGONFAILURE, + "QPINGONDELAY", QPINGONDELAY, + "QHASNOTIFY", QHASNOTIFY, + "QRELAYED", QRELAYED, + "QEXPANDED", QEXPANDED, + "QDELIVERED", QDELIVERED, + "QDELAYED", QDELAYED, + "QTHISPASS", QTHISPASS, + NULL +}; + +void printaddr(a, follow) register ADDRESS *a; bool follow; { - bool first = TRUE; register MAILER *m; MAILER pseudomailer; + register struct qflags *qfp; + bool firstone; + + if (a == NULL) + { + printf("[NULL]\n"); + return; + } while (a != NULL) { - first = FALSE; printf("%x=", a); (void) fflush(stdout); @@ -1603,25 +1755,60 @@ printaddr(a, follow) m->m_name = "NULL"; } - printf("%s:\n\tmailer %d (%s), host `%s', user `%s', ruser `%s'\n", - a->q_paddr, m->m_mno, m->m_name, - a->q_host, a->q_user, - a->q_ruser ? a->q_ruser : "<null>"); - printf("\tnext=%x, flags=%o, alias %x, uid %d, gid %d\n", - a->q_next, a->q_flags, a->q_alias, a->q_uid, a->q_gid); + printf("%s:\n\tmailer %d (%s), host `%s'\n", + a->q_paddr == NULL ? "<null>" : a->q_paddr, + m->m_mno, m->m_name, + a->q_host == NULL ? "<null>" : a->q_host); + printf("\tuser `%s', ruser `%s'\n", + a->q_user, + a->q_ruser == NULL ? "<null>" : a->q_ruser); + printf("\tnext=%x, alias %x, uid %d, gid %d\n", + a->q_next, a->q_alias, a->q_uid, a->q_gid); + printf("\tflags=%lx<", a->q_flags); + firstone = TRUE; + for (qfp = AddressFlags; qfp->qf_name != NULL; qfp++) + { + if (!bitset(qfp->qf_bit, a->q_flags)) + continue; + if (!firstone) + printf(","); + firstone = FALSE; + printf("%s", qfp->qf_name); + } + printf(">\n"); printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n", a->q_owner == NULL ? "(none)" : a->q_owner, a->q_home == NULL ? "(none)" : a->q_home, a->q_fullname == NULL ? "(none)" : a->q_fullname); + printf("\torcpt=\"%s\", statmta=%s, rstatus=%s\n", + a->q_orcpt == NULL ? "(none)" : a->q_orcpt, + a->q_statmta == NULL ? "(none)" : a->q_statmta, + a->q_rstatus == NULL ? "(none)" : a->q_rstatus); if (!follow) return; a = a->q_next; } - if (first) - printf("[NULL]\n"); } +/* +** EMPTYADDR -- return TRUE if this address is empty (``<>'') +** +** Parameters: +** a -- pointer to the address +** +** Returns: +** TRUE -- if this address is "empty" (i.e., no one should +** ever generate replies to it. +** FALSE -- if it is a "regular" (read: replyable) address. +*/ +bool +emptyaddr(a) + register ADDRESS *a; +{ + return a->q_paddr == NULL || strcmp(a->q_paddr, "<>") == 0 || + a->q_user == NULL || strcmp(a->q_user, "<>") == 0; +} /* ** REMOTENAME -- return the name relative to the current mailer ** @@ -1657,8 +1844,8 @@ remotename(name, m, flags, pstat, e) char *fancy; char *oldg = macvalue('g', e); int rwset; - static char buf[MAXNAME]; - char lbuf[MAXNAME]; + static char buf[MAXNAME + 1]; + char lbuf[MAXNAME + 1]; char pvpbuf[PSBUFSIZE]; extern char *crackaddr(); @@ -1693,7 +1880,7 @@ remotename(name, m, flags, pstat, e) ** domain will be appended. */ - pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL); + pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL, NULL); if (pvp == NULL) return (name); if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL) @@ -1760,9 +1947,9 @@ remotename(name, m, flags, pstat, e) /* need to make sure route-addrs have <angle brackets> */ if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@') - expand("<\201g>", buf, &buf[sizeof buf - 1], e); + expand("<\201g>", buf, sizeof buf, e); else - expand(fancy, buf, &buf[sizeof buf - 1], e); + expand(fancy, buf, sizeof buf, e); define('g', oldg, e); @@ -1777,14 +1964,18 @@ remotename(name, m, flags, pstat, e) ** a -- the address to map (but just the user name part). ** sendq -- the sendq in which to install any replacement ** addresses. +** aliaslevel -- the alias nesting depth. +** e -- the envelope. ** ** Returns: ** none. */ -maplocaluser(a, sendq, e) +void +maplocaluser(a, sendq, aliaslevel, e) register ADDRESS *a; ADDRESS **sendq; + int aliaslevel; ENVELOPE *e; { register char **pvp; @@ -1797,7 +1988,7 @@ maplocaluser(a, sendq, e) printf("maplocaluser: "); printaddr(a, FALSE); } - pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr); + pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr, NULL); if (pvp == NULL) return; @@ -1818,8 +2009,8 @@ maplocaluser(a, sendq, e) printaddr(a, FALSE); } a1->q_alias = a; - allocaddr(a1, RF_COPYALL, NULL); - (void) recipient(a1, sendq, e); + allocaddr(a1, RF_COPYALL, a->q_paddr); + (void) recipient(a1, sendq, aliaslevel, e); } /* ** DEQUOTE_INIT -- initialize dequote map @@ -1841,6 +2032,7 @@ dequote_init(map, args) { register char *p = args; + map->map_mflags |= MF_KEEPQUOTES; for (;;) { while (isascii(*p) && isspace(*p)) @@ -1852,6 +2044,10 @@ dequote_init(map, args) case 'a': map->map_app = ++p; break; + + case 's': + map->map_coldelim = *++p; + break; } while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; @@ -1888,19 +2084,13 @@ dequote_map(map, name, av, statp) register char *p; register char *q; register char c; - int anglecnt; - int cmntcnt; - int quotecnt; - int spacecnt; - bool quotemode; - bool bslashmode; - - anglecnt = 0; - cmntcnt = 0; - quotecnt = 0; - spacecnt = 0; - quotemode = FALSE; - bslashmode = FALSE; + int anglecnt = 0; + int cmntcnt = 0; + int quotecnt = 0; + int spacecnt = 0; + bool quotemode = FALSE; + bool bslashmode = FALSE; + char spacesub = map->map_coldelim; for (p = q = name; (c = *p++) != '\0'; ) { @@ -1911,6 +2101,9 @@ dequote_map(map, name, av, statp) continue; } + if (c == ' ' && spacesub != '\0') + c = spacesub; + switch (c) { case '\\': diff --git a/usr.sbin/sendmail/src/readcf.c b/usr.sbin/sendmail/src/readcf.c index 4a2a820..4811e6d 100644 --- a/usr.sbin/sendmail/src/readcf.c +++ b/usr.sbin/sendmail/src/readcf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,14 +33,12 @@ */ #ifndef lint -static char sccsid[] = "@(#)readcf.c 8.23.1.3 (Berkeley) 3/5/95"; +static char sccsid[] = "@(#)readcf.c 8.138 (Berkeley) 11/20/95"; #endif /* not lint */ # include "sendmail.h" -# include <pwd.h> # include <grp.h> #if NAMED_BIND -# include <arpa/nameser.h> # include <resolv.h> #endif @@ -76,6 +74,7 @@ static char sccsid[] = "@(#)readcf.c 8.23.1.3 (Berkeley) 3/5/95"; ** Kmapname mapclass arguments.... ** Define keyed lookup of a given class. ** Arguments are class dependent. +** Eenvar=value Set the environment value to the given value. ** ** Parameters: ** cfname -- control file name. @@ -90,6 +89,7 @@ static char sccsid[] = "@(#)readcf.c 8.23.1.3 (Berkeley) 3/5/95"; ** Builds several internal tables. */ +void readcf(cfname, safe, e) char *cfname; bool safe; @@ -104,14 +104,18 @@ readcf(cfname, safe, e) int nfuzzy; char *file; bool optional; + int mid; char buf[MAXLINE]; register char *p; extern char **copyplist(); struct stat statb; char exbuf[MAXLINE]; char pvpbuf[MAXLINE + MAXATOM]; - extern char *munchstring(); - extern void makemapentry(); + static char *null_list[1] = { NULL }; + extern char *munchstring __P((char *, char **)); + extern void fileclass __P((int, char *, char *, bool, bool)); + extern void toomany __P((int, int)); + extern void translate_dollars __P((char *)); FileName = cfname; LineNumber = 0; @@ -137,7 +141,7 @@ readcf(cfname, safe, e) if (OpMode != MD_TEST && bitset(S_IWGRP|S_IWOTH, statb.st_mode)) { - if (OpMode == MD_DAEMON || OpMode == MD_FREEZE) + if (OpMode == MD_DAEMON || OpMode == MD_INITALIAS) fprintf(stderr, "%s: WARNING: dangerous write permissions\n", FileName); #ifdef LOG @@ -160,52 +164,8 @@ readcf(cfname, safe, e) continue; } - /* map $ into \201 for macro expansion */ - for (p = bp; *p != '\0'; p++) - { - if (*p == '#' && p > bp && ConfigLevel >= 3) - { - /* this is an on-line comment */ - register char *e; - - switch (*--p & 0377) - { - case MACROEXPAND: - /* it's from $# -- let it go through */ - p++; - break; - - case '\\': - /* it's backslash escaped */ - (void) strcpy(p, p + 1); - break; - - default: - /* delete preceeding white space */ - while (isascii(*p) && isspace(*p) && p > bp) - p--; - if ((e = strchr(++p, '\n')) != NULL) - (void) strcpy(p, e); - else - p[0] = p[1] = '\0'; - break; - } - continue; - } - - if (*p != '$') - continue; - - if (p[1] == '$') - { - /* actual dollar sign.... */ - (void) strcpy(p, p + 1); - continue; - } - - /* convert to macro expansion character */ - *p = MACROEXPAND; - } + /* do macro expansion mappings */ + translate_dollars(bp); /* interpret this line */ errno = 0; @@ -240,9 +200,9 @@ readcf(cfname, safe, e) /* expand and save the LHS */ *p = '\0'; - expand(&bp[1], exbuf, &exbuf[sizeof exbuf], e); + expand(&bp[1], exbuf, sizeof exbuf, e); rwp->r_lhs = prescan(exbuf, '\t', pvpbuf, - sizeof pvpbuf, NULL); + sizeof pvpbuf, NULL, NULL); nfuzzy = 0; if (rwp->r_lhs != NULL) { @@ -316,7 +276,10 @@ readcf(cfname, safe, e) } } else + { syserr("R line: null LHS"); + rwp->r_lhs = null_list; + } /* expand and save the RHS */ while (*++p == '\t') @@ -325,9 +288,9 @@ readcf(cfname, safe, e) while (*p != '\0' && *p != '\t') p++; *p = '\0'; - expand(q, exbuf, &exbuf[sizeof exbuf], e); + expand(q, exbuf, sizeof exbuf, e); rwp->r_rhs = prescan(exbuf, '\t', pvpbuf, - sizeof pvpbuf, NULL); + sizeof pvpbuf, NULL, NULL); if (rwp->r_rhs != NULL) { register char **ap; @@ -377,40 +340,51 @@ readcf(cfname, safe, e) } } else + { syserr("R line: null RHS"); + rwp->r_rhs = null_list; + } break; case 'S': /* select rewriting set */ - for (p = &bp[1]; isascii(*p) && isspace(*p); p++) - continue; - if (!isascii(*p) || !isdigit(*p)) - { - syserr("invalid argument to S line: \"%.20s\"", - &bp[1]); + expand(&bp[1], exbuf, sizeof exbuf, e); + ruleset = strtorwset(exbuf, NULL, ST_ENTER); + if (ruleset < 0) break; - } - ruleset = atoi(p); - if (ruleset >= MAXRWSETS || ruleset < 0) + rwp = RewriteRules[ruleset]; + if (rwp != NULL) { - syserr("bad ruleset %d (%d max)", ruleset, MAXRWSETS); - ruleset = 0; + while (rwp->r_next != NULL) + rwp = rwp->r_next; + fprintf(stderr, "WARNING: Ruleset %s redefined\n", + &bp[1]); } - rwp = NULL; break; case 'D': /* macro definition */ - p = munchstring(&bp[2], NULL); - define(bp[1], newstr(p), e); + mid = macid(&bp[1], &ep); + p = munchstring(ep, NULL); + define(mid, newstr(p), e); break; case 'H': /* required header line */ - (void) chompheader(&bp[1], TRUE, e); + (void) chompheader(&bp[1], TRUE, NULL, e); break; case 'C': /* word class */ - /* scan the list of words and set class for all */ - expand(&bp[2], exbuf, &exbuf[sizeof exbuf], e); - for (p = exbuf; *p != '\0'; ) + case 'T': /* trusted user (set class `t') */ + if (bp[0] == 'C') + { + mid = macid(&bp[1], &ep); + expand(ep, exbuf, sizeof exbuf, e); + p = exbuf; + } + else + { + mid = 't'; + p = &bp[1]; + } + while (*p != '\0') { register char *wd; char delim; @@ -423,13 +397,14 @@ readcf(cfname, safe, e) delim = *p; *p = '\0'; if (wd[0] != '\0') - setclass(bp[1], wd); + setclass(mid, wd); *p = delim; } break; case 'F': /* word class from file */ - for (p = &bp[2]; isascii(*p) && isspace(*p); ) + mid = macid(&bp[1], &ep); + for (p = ep; isascii(*p) && isspace(*p); ) p++; if (p[0] == '-' && p[1] == 'o') { @@ -437,22 +412,27 @@ readcf(cfname, safe, e) while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; while (isascii(*p) && isspace(*p)) - *p++; + p++; } else optional = FALSE; file = p; - while (*p != '\0' && !(isascii(*p) && isspace(*p))) - p++; - if (*p == '\0') + if (*file == '|') p = "%s"; else { - *p = '\0'; - while (isascii(*++p) && isspace(*p)) - continue; + while (*p != '\0' && !(isascii(*p) && isspace(*p))) + p++; + if (*p == '\0') + p = "%s"; + else + { + *p = '\0'; + while (isascii(*++p) && isspace(*p)) + continue; + } } - fileclass(bp[1], file, p, safe, optional); + fileclass(mid, file, p, safe, optional); break; #ifdef XLA @@ -475,7 +455,7 @@ readcf(cfname, safe, e) toomany('P', MAXPRIORITIES); break; } - for (p = &bp[1]; *p != '\0' && *p != '=' && *p != '\t'; p++) + for (p = &bp[1]; *p != '\0' && *p != '='; p++) continue; if (*p == '\0') goto badline; @@ -485,10 +465,6 @@ readcf(cfname, safe, e) NumPriorities++; break; - case 'T': /* trusted user(s) */ - /* this option is obsolete, but will be ignored */ - break; - case 'V': /* configuration syntax version */ for (p = &bp[1]; isascii(*p) && isspace(*p); p++) continue; @@ -499,13 +475,28 @@ readcf(cfname, safe, e) break; } ConfigLevel = strtol(p, &ep, 10); + + /* + ** Do heuristic tweaking for back compatibility. + */ + if (ConfigLevel >= 5) { /* level 5 configs have short name in $w */ p = macvalue('w', e); if (p != NULL && (p = strchr(p, '.')) != NULL) *p = '\0'; + define('w', macvalue('w', e), e); } + if (ConfigLevel >= 6) + { + ColonOkInAddr = FALSE; + } + + /* + ** Look for vendor code. + */ + if (*ep++ == '/') { /* extract vendor code */ @@ -520,7 +511,15 @@ readcf(cfname, safe, e) break; case 'K': - makemapentry(&bp[1]); + expand(&bp[1], exbuf, sizeof exbuf, e); + (void) makemapentry(exbuf); + break; + + case 'E': + p = strchr(bp, '='); + if (p != NULL) + *p++ = '\0'; + setuserenv(&bp[1], p); break; default: @@ -532,24 +531,133 @@ readcf(cfname, safe, e) } if (ferror(cf)) { - syserr("I/O read error", cfname); + syserr("I/O read error"); exit(EX_OSFILE); } fclose(cf); FileName = NULL; - if (stab("host", ST_MAP, ST_FIND) == NULL) + /* initialize host maps from local service tables */ + inithostmaps(); + + /* determine if we need to do special name-server frotz */ { - /* user didn't initialize: set up host map */ - strcpy(buf, "host host"); -#if NAMED_BIND - if (ConfigLevel >= 2) - strcat(buf, " -a."); + int nmaps; + char *maptype[MAXMAPSTACK]; + short mapreturn[MAXMAPACTIONS]; + + nmaps = switch_map_find("hosts", maptype, mapreturn); + UseNameServer = FALSE; + if (nmaps > 0 && nmaps <= MAXMAPSTACK) + { + register int mapno; + + for (mapno = 0; mapno < nmaps && !UseNameServer; mapno++) + { + if (strcmp(maptype[mapno], "dns") == 0) + UseNameServer = TRUE; + } + } + +#ifdef HESIOD + nmaps = switch_map_find("passwd", maptype, mapreturn); + UseHesiod = FALSE; + if (nmaps > 0 && nmaps <= MAXMAPSTACK) + { + register int mapno; + + for (mapno = 0; mapno < nmaps && !UseHesiod; mapno++) + { + if (strcmp(maptype[mapno], "hesiod") == 0) + UseHesiod = TRUE; + } + } #endif - makemapentry(buf); } } /* +** TRANSLATE_DOLLARS -- convert $x into internal form +** +** Actually does all appropriate pre-processing of a config line +** to turn it into internal form. +** +** Parameters: +** bp -- the buffer to translate. +** +** Returns: +** None. The buffer is translated in place. Since the +** translations always make the buffer shorter, this is +** safe without a size parameter. +*/ + +void +translate_dollars(bp) + char *bp; +{ + register char *p; + auto char *ep; + + for (p = bp; *p != '\0'; p++) + { + if (*p == '#' && p > bp && ConfigLevel >= 3) + { + /* this is an on-line comment */ + register char *e; + + switch (*--p & 0377) + { + case MACROEXPAND: + /* it's from $# -- let it go through */ + p++; + break; + + case '\\': + /* it's backslash escaped */ + (void) strcpy(p, p + 1); + break; + + default: + /* delete preceeding white space */ + while (isascii(*p) && isspace(*p) && + *p != '\n' && p > bp) + p--; + if ((e = strchr(++p, '\n')) != NULL) + (void) strcpy(p, e); + else + *p-- = '\0'; + break; + } + continue; + } + + if (*p != '$' || p[1] == '\0') + continue; + + if (p[1] == '$') + { + /* actual dollar sign.... */ + (void) strcpy(p, p + 1); + continue; + } + + /* convert to macro expansion character */ + *p++ = MACROEXPAND; + + /* special handling for $=, $~, $&, and $? */ + if (*p == '=' || *p == '~' || *p == '&' || *p == '?') + p++; + + /* convert macro name to code */ + *p = macid(p, &ep); + if (ep != p) + strcpy(p + 1, ep); + } + + /* strip trailing white space from the line */ + while (--p > bp && isascii(*p) && isspace(*p)) + *p = '\0'; +} +/* ** TOOMANY -- signal too many of some option ** ** Parameters: @@ -563,8 +671,9 @@ readcf(cfname, safe, e) ** gives a syserr. */ +void toomany(id, maxcnt) - char id; + int id; int maxcnt; { syserr("too many %c lines, %d max", id, maxcnt); @@ -589,6 +698,7 @@ toomany(id, maxcnt) ** the named class. */ +void fileclass(class, filename, fmt, safe, optional) int class; char *filename; @@ -597,7 +707,9 @@ fileclass(class, filename, fmt, safe, optional) bool optional; { FILE *f; - struct stat stbuf; + int sff; + int pid; + register char *p; char buf[MAXLINE]; if (tTd(37, 2)) @@ -605,42 +717,49 @@ fileclass(class, filename, fmt, safe, optional) if (filename[0] == '|') { - syserr("fileclass: pipes (F%c%s) not supported due to security problems", - class, filename); - return; - } - if (stat(filename, &stbuf) < 0) - { - if (tTd(37, 2)) - printf(" cannot stat (%s)\n", errstring(errno)); - if (!optional) - syserr("fileclass: cannot stat %s", filename); - return; - } - if (!S_ISREG(stbuf.st_mode)) - { - syserr("fileclass: %s not a regular file", filename); - return; + auto int fd; + int i; + char *argv[MAXPV + 1]; + + i = 0; + for (p = strtok(&filename[1], " \t"); p != NULL; p = strtok(NULL, " \t")) + { + if (i >= MAXPV) + break; + argv[i++] = p; + } + argv[i] = NULL; + pid = prog_open(argv, &fd, CurEnv); + if (pid < 0) + f = NULL; + else + f = fdopen(fd, "r"); } - if (!safe && access(filename, R_OK) < 0) + else { - syserr("fileclass: access denied on %s", filename); - return; + pid = -1; + sff = SFF_REGONLY; + if (safe) + sff |= SFF_OPENASROOT; + f = safefopen(filename, O_RDONLY, 0, sff); } - f = fopen(filename, "r"); if (f == NULL) { - syserr("fileclass: cannot open %s", filename); + if (!optional) + syserr("fileclass: cannot open %s", filename); return; } while (fgets(buf, sizeof buf, f) != NULL) { - register STAB *s; register char *p; -# ifdef SCANF +# if SCANF char wordbuf[MAXNAME+1]; +# endif + if (buf[0] == '#') + continue; +# if SCANF if (sscanf(buf, fmt, wordbuf) != 1) continue; p = wordbuf; @@ -675,6 +794,8 @@ fileclass(class, filename, fmt, safe, optional) } (void) fclose(f); + if (pid > 0) + (void) waitfor(pid); } /* ** MAKEMAILER -- define a new mailer. @@ -682,12 +803,19 @@ fileclass(class, filename, fmt, safe, optional) ** Parameters: ** line -- description of mailer. This is in labeled ** fields. The fields are: -** P -- the path to the mailer -** F -- the flags associated with the mailer ** A -- the argv for this mailer -** S -- the sender rewriting set -** R -- the recipient rewriting set +** C -- the character set for MIME conversions +** D -- the directory to run in ** E -- the eol string +** F -- the flags associated with the mailer +** L -- the maximum line length +** M -- the maximum message size +** N -- the niceness at which to run +** P -- the path to the mailer +** R -- the recipient rewriting set +** S -- the sender rewriting set +** T -- the mailer type (for DSNs) +** U -- the uid to run as ** The first word is the canonical name of the mailer. ** ** Returns: @@ -697,6 +825,7 @@ fileclass(class, filename, fmt, safe, optional) ** enters the mailer into the mailer table. */ +void makemailer(line) char *line; { @@ -709,18 +838,20 @@ makemailer(line) extern int NextMailer; extern char **makeargv(); extern char *munchstring(); - extern long atol(); /* allocate a mailer and set up defaults */ m = (struct mailer *) xalloc(sizeof *m); bzero((char *) m, sizeof *m); m->m_eol = "\n"; + m->m_uid = m->m_gid = 0; /* collect the mailer name */ for (p = line; *p != '\0' && *p != ',' && !(isascii(*p) && isspace(*p)); p++) continue; if (*p != '\0') *p++ = '\0'; + if (line[0] == '\0') + syserr("name required for mailer"); m->m_name = newstr(line); /* now scan through and assign info from the fields */ @@ -750,6 +881,8 @@ makemailer(line) switch (fcode) { case 'P': /* pathname */ + if (*p == '\0') + syserr("mailer %s: empty path name", m->m_name); m->m_mailer = newstr(p); break; @@ -761,12 +894,9 @@ makemailer(line) case 'S': /* sender rewriting ruleset */ case 'R': /* recipient rewriting ruleset */ - i = strtol(p, &endp, 10); - if (i < 0 || i >= MAXRWSETS) - { - syserr("invalid rewrite set, %d max", MAXRWSETS); + i = strtorwset(p, &endp, ST_ENTER); + if (i < 0) return; - } if (fcode == 'S') m->m_sh_rwset = m->m_se_rwset = i; else @@ -775,13 +905,9 @@ makemailer(line) p = endp; if (*p++ == '/') { - i = strtol(p, NULL, 10); - if (i < 0 || i >= MAXRWSETS) - { - syserr("invalid rewrite set, %d max", - MAXRWSETS); + i = strtorwset(p, NULL, ST_ENTER); + if (i < 0) return; - } if (fcode == 'S') m->m_sh_rwset = i; else @@ -790,10 +916,16 @@ makemailer(line) break; case 'E': /* end of line string */ + if (*p == '\0') + syserr("mailer %s: null end-of-line string", + m->m_name); m->m_eol = newstr(p); break; case 'A': /* argument vector */ + if (*p == '\0') + syserr("mailer %s: null argument vector", + m->m_name); m->m_argv = makeargv(p); break; @@ -805,23 +937,118 @@ makemailer(line) m->m_linelimit = atoi(p); break; + case 'N': /* run niceness */ + m->m_nice = atoi(p); + break; + case 'D': /* working directory */ + if (*p == '\0') + syserr("mailer %s: null working directory", + m->m_name); m->m_execdir = newstr(p); break; + + case 'C': /* default charset */ + if (*p == '\0') + syserr("mailer %s: null charset", m->m_name); + m->m_defcharset = newstr(p); + break; + + case 'T': /* MTA-Name/Address/Diagnostic types */ + /* extract MTA name type; default to "dns" */ + m->m_mtatype = newstr(p); + p = strchr(m->m_mtatype, '/'); + if (p != NULL) + { + *p++ = '\0'; + if (*p == '\0') + p = NULL; + } + if (*m->m_mtatype == '\0') + m->m_mtatype = "dns"; + + /* extract address type; default to "rfc822" */ + m->m_addrtype = p; + if (p != NULL) + p = strchr(p, '/'); + if (p != NULL) + { + *p++ = '\0'; + if (*p == '\0') + p = NULL; + } + if (m->m_addrtype == NULL || *m->m_addrtype == '\0') + m->m_addrtype = "rfc822"; + + /* extract diagnostic type; default to "smtp" */ + m->m_diagtype = p; + if (m->m_diagtype == NULL || *m->m_diagtype == '\0') + m->m_diagtype = "smtp"; + break; + + case 'U': /* user id */ + if (isascii(*p) && !isdigit(*p)) + { + char *q = p; + struct passwd *pw; + + while (*p != '\0' && isascii(*p) && + (isalnum(*p) || strchr("-_", *p) != NULL)) + p++; + while (isascii(*p) && isspace(*p)) + *p++ = '\0'; + if (*p != '\0') + *p++ = '\0'; + if (*q == '\0') + syserr("mailer %s: null user name", + m->m_name); + pw = sm_getpwnam(q); + if (pw == NULL) + syserr("readcf: mailer U= flag: unknown user %s", q); + else + { + m->m_uid = pw->pw_uid; + m->m_gid = pw->pw_gid; + } + } + else + { + auto char *q; + + m->m_uid = strtol(p, &q, 0); + p = q; + } + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + if (isascii(*p) && !isdigit(*p)) + { + char *q = p; + struct group *gr; + + while (isascii(*p) && isalnum(*p)) + p++; + *p++ = '\0'; + if (*q == '\0') + syserr("mailer %s: null group name", + m->m_name); + gr = getgrnam(q); + if (gr == NULL) + syserr("readcf: mailer U= flag: unknown group %s", q); + else + m->m_gid = gr->gr_gid; + } + else + { + m->m_gid = strtol(p, NULL, 0); + } + break; } p = delimptr; } - /* do some heuristic cleanup for back compatibility */ - if (bitnset(M_LIMITS, m->m_flags)) - { - if (m->m_linelimit == 0) - m->m_linelimit = SMTPLINELIM; - if (ConfigLevel < 2) - setbitn(M_7BITS, m->m_flags); - } - /* do some rationality checking */ if (m->m_argv == NULL) { @@ -840,6 +1067,27 @@ makemailer(line) return; } + /* do some heuristic cleanup for back compatibility */ + if (bitnset(M_LIMITS, m->m_flags)) + { + if (m->m_linelimit == 0) + m->m_linelimit = SMTPLINELIM; + if (ConfigLevel < 2) + setbitn(M_7BITS, m->m_flags); + } + + if (strcmp(m->m_mailer, "[IPC]") == 0 || + strcmp(m->m_mailer, "[TCP]") == 0) + { + if (m->m_mtatype == NULL) + m->m_mtatype = "dns"; + if (m->m_addrtype == NULL) + m->m_addrtype = "rfc822"; + if (m->m_diagtype == NULL) + m->m_diagtype = "smtp"; + } + + /* enter the mailer into the symbol table */ s = stab(m->m_name, ST_MAILER, ST_ENTER); if (s->s_mailer != NULL) { @@ -875,7 +1123,7 @@ munchstring(p, delimptr) bool quotemode = FALSE; static char buf[MAXLINE]; - for (q = buf; *p != '\0'; p++) + for (q = buf; *p != '\0' && q < &buf[sizeof buf - 1]; p++) { if (backslash) { @@ -973,6 +1221,7 @@ makeargv(p) ** prints rewrite rules. */ +void printrules() { register struct rewrite *rwp; @@ -993,7 +1242,52 @@ printrules() } } } +/* +** PRINTMAILER -- print mailer structure (for debugging) +** +** Parameters: +** m -- the mailer to print +** +** Returns: +** none. +*/ + +void +printmailer(m) + register MAILER *m; +{ + int j; + + printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld U=%d:%d F=", + m->m_mno, m->m_name, + m->m_mailer, m->m_se_rwset, m->m_sh_rwset, + m->m_re_rwset, m->m_rh_rwset, m->m_maxsize, + m->m_uid, m->m_gid); + for (j = '\0'; j <= '\177'; j++) + if (bitnset(j, m->m_flags)) + (void) putchar(j); + printf(" L=%d E=", m->m_linelimit); + xputs(m->m_eol); + if (m->m_defcharset != NULL) + printf(" C=%s", m->m_defcharset); + printf(" T=%s/%s/%s", + m->m_mtatype == NULL ? "<undefined>" : m->m_mtatype, + m->m_addrtype == NULL ? "<undefined>" : m->m_addrtype, + m->m_diagtype == NULL ? "<undefined>" : m->m_diagtype); + if (m->m_argv != NULL) + { + char **a = m->m_argv; + printf(" A="); + while (*a != NULL) + { + if (a != m->m_argv) + printf(" "); + xputs(*a++); + } + } + printf("\n"); +} /* ** SETOPTION -- set global processing option ** @@ -1015,6 +1309,7 @@ printrules() */ static BITMAP StickyOpt; /* set if option is stuck */ +extern void settimeout __P((char *, char *)); #if NAMED_BIND @@ -1040,23 +1335,222 @@ struct resolverflags #endif +struct optioninfo +{ + char *o_name; /* long name of option */ + u_char o_code; /* short name of option */ + bool o_safe; /* safe for random people to use */ +} OptionTab[] = +{ + "SevenBitInput", '7', TRUE, +#if MIME8TO7 + "EightBitMode", '8', TRUE, +#endif + "AliasFile", 'A', FALSE, + "AliasWait", 'a', FALSE, + "BlankSub", 'B', FALSE, + "MinFreeBlocks", 'b', TRUE, + "CheckpointInterval", 'C', TRUE, + "HoldExpensive", 'c', FALSE, + "AutoRebuildAliases", 'D', FALSE, + "DeliveryMode", 'd', TRUE, + "ErrorHeader", 'E', FALSE, + "ErrorMode", 'e', TRUE, + "TempFileMode", 'F', FALSE, + "SaveFromLine", 'f', FALSE, + "MatchGECOS", 'G', FALSE, + "HelpFile", 'H', FALSE, + "MaxHopCount", 'h', FALSE, + "ResolverOptions", 'I', FALSE, + "IgnoreDots", 'i', TRUE, + "ForwardPath", 'J', FALSE, + "SendMimeErrors", 'j', TRUE, + "ConnectionCacheSize", 'k', FALSE, + "ConnectionCacheTimeout", 'K', FALSE, + "UseErrorsTo", 'l', FALSE, + "LogLevel", 'L', FALSE, + "MeToo", 'm', TRUE, + "CheckAliases", 'n', FALSE, + "OldStyleHeaders", 'o', TRUE, + "DaemonPortOptions", 'O', FALSE, + "PrivacyOptions", 'p', TRUE, + "PostmasterCopy", 'P', FALSE, + "QueueFactor", 'q', FALSE, + "QueueDirectory", 'Q', FALSE, + "DontPruneRoutes", 'R', FALSE, + "Timeout", 'r', TRUE, + "StatusFile", 'S', FALSE, + "SuperSafe", 's', TRUE, + "QueueTimeout", 'T', FALSE, + "TimeZoneSpec", 't', FALSE, + "UserDatabaseSpec", 'U', FALSE, + "DefaultUser", 'u', FALSE, + "FallbackMXhost", 'V', FALSE, + "Verbose", 'v', TRUE, + "TryNullMXList", 'w', TRUE, + "QueueLA", 'x', FALSE, + "RefuseLA", 'X', FALSE, + "RecipientFactor", 'y', FALSE, + "ForkEachJob", 'Y', FALSE, + "ClassFactor", 'z', FALSE, + "RetryFactor", 'Z', FALSE, +#define O_QUEUESORTORD 0x81 + "QueueSortOrder", O_QUEUESORTORD, TRUE, +#define O_HOSTSFILE 0x82 + "HostsFile", O_HOSTSFILE, FALSE, +#define O_MQA 0x83 + "MinQueueAge", O_MQA, TRUE, +#define O_MHSA 0x84 +/* + "MaxHostStatAge", O_MHSA, TRUE, +*/ +#define O_DEFCHARSET 0x85 + "DefaultCharSet", O_DEFCHARSET, TRUE, +#define O_SSFILE 0x86 + "ServiceSwitchFile", O_SSFILE, FALSE, +#define O_DIALDELAY 0x87 + "DialDelay", O_DIALDELAY, TRUE, +#define O_NORCPTACTION 0x88 + "NoRecipientAction", O_NORCPTACTION, TRUE, +#define O_SAFEFILEENV 0x89 + "SafeFileEnvironment", O_SAFEFILEENV, FALSE, +#define O_MAXMSGSIZE 0x8a + "MaxMessageSize", O_MAXMSGSIZE, FALSE, +#define O_COLONOKINADDR 0x8b + "ColonOkInAddr", O_COLONOKINADDR, TRUE, +#define O_MAXQUEUERUN 0x8c + "MaxQueueRunSize", O_MAXQUEUERUN, TRUE, +#define O_MAXCHILDREN 0x8d +/* + "MaxDaemonChildren", O_MAXCHILDREN, FALSE, +*/ +#define O_KEEPCNAMES 0x8e + "DontExpandCnames", O_KEEPCNAMES, FALSE, +#define O_MUSTQUOTE 0x8f +/* + "MustQuoteChars", O_MUSTQUOTE, FALSE, +*/ +#define O_SMTPGREETING 0x90 + "SmtpGreetingMessage", O_SMTPGREETING, FALSE, +#define O_UNIXFROM 0x91 + "UnixFromLine", O_UNIXFROM, FALSE, +#define O_OPCHARS 0x92 + "OperatorChars", O_OPCHARS, FALSE, +#define O_DONTINITGRPS 0x93 + "DontInitGroups", O_DONTINITGRPS, TRUE, +#define O_SLFH 0x94 +#ifdef LOTUS_NOTES_HACK + "SingleLineFromHeader", O_SLFH, TRUE, +#endif + + NULL, '\0', FALSE, +}; + + + +void setoption(opt, val, safe, sticky, e) - char opt; + int opt; char *val; bool safe; bool sticky; register ENVELOPE *e; { register char *p; + register struct optioninfo *o; + char *subopt; + char buf[50]; extern bool atobool(); extern time_t convtime(); extern int QueueLA; extern int RefuseLA; extern bool Warn_Q_option; - extern bool trusteduser(); + + errno = 0; + if (opt == ' ') + { + /* full word options */ + struct optioninfo *sel; + + p = strchr(val, '='); + if (p == NULL) + p = &val[strlen(val)]; + while (*--p == ' ') + continue; + while (*++p == ' ') + *p = '\0'; + if (p == val) + { + syserr("readcf: null option name"); + return; + } + if (*p == '=') + *p++ = '\0'; + while (*p == ' ') + p++; + subopt = strchr(val, '.'); + if (subopt != NULL) + *subopt++ = '\0'; + sel = NULL; + for (o = OptionTab; o->o_name != NULL; o++) + { + if (strncasecmp(o->o_name, val, strlen(val)) != 0) + continue; + if (strlen(o->o_name) == strlen(val)) + { + /* completely specified -- this must be it */ + sel = NULL; + break; + } + if (sel != NULL) + break; + sel = o; + } + if (sel != NULL && o->o_name == NULL) + o = sel; + else if (o->o_name == NULL) + { + syserr("readcf: unknown option name %s", val); + return; + } + else if (sel != NULL) + { + syserr("readcf: ambiguous option name %s (matches %s and %s)", + val, sel->o_name, o->o_name); + return; + } + if (strlen(val) != strlen(o->o_name)) + { + bool oldVerbose = Verbose; + + Verbose = TRUE; + message("Option %s used as abbreviation for %s", + val, o->o_name); + Verbose = oldVerbose; + } + opt = o->o_code; + val = p; + } + else + { + for (o = OptionTab; o->o_name != NULL; o++) + { + if (o->o_code == opt) + break; + } + subopt = NULL; + } if (tTd(37, 1)) - printf("setoption %c=%s", opt, val); + { + printf(isascii(opt) && isprint(opt) ? + "setoption %s (%c).%s=" : + "setoption %s (0x%x).%s=", + o->o_name == NULL ? "<unknown>" : o->o_name, + opt, + subopt == NULL ? "" : subopt); + xputs(val); + } /* ** See if this option is preset for us. @@ -1075,7 +1569,7 @@ setoption(opt, val, safe, sticky, e) if (!safe && RealUid == 0) safe = TRUE; - if (!safe && strchr("bCdeijLmoprsvw7", opt) == NULL) + if (!safe && !o->o_safe) { if (opt != 'M' || (val[0] != 'r' && val[0] != 's')) { @@ -1085,6 +1579,7 @@ setoption(opt, val, safe, sticky, e) { if (tTd(37, 1)) printf("(Resetting uid)"); + endpwent(); (void) setgid(RealGid); (void) setuid(RealUid); } @@ -1093,12 +1588,53 @@ setoption(opt, val, safe, sticky, e) if (tTd(37, 1)) printf("\n"); - switch (opt) + switch (opt & 0xff) { case '7': /* force seven-bit input */ - SevenBit = atobool(val); + SevenBitInput = atobool(val); break; +#if MIME8TO7 + case '8': /* handling of 8-bit input */ + switch (*val) + { + case 'm': /* convert 8-bit, convert MIME */ + MimeMode = MM_CVTMIME|MM_MIME8BIT; + break; + + case 'p': /* pass 8 bit, convert MIME */ + MimeMode = MM_CVTMIME|MM_PASS8BIT; + break; + + case 's': /* strict adherence */ + MimeMode = MM_CVTMIME; + break; + +#if 0 + case 'r': /* reject 8-bit, don't convert MIME */ + MimeMode = 0; + break; + + case 'j': /* "just send 8" */ + MimeMode = MM_PASS8BIT; + break; + + case 'a': /* encode 8 bit if available */ + MimeMode = MM_MIME8BIT|MM_PASS8BIT|MM_CVTMIME; + break; + + case 'c': /* convert 8 bit to MIME, never 7 bit */ + MimeMode = MM_MIME8BIT; + break; +#endif + + default: + syserr("Unknown 8-bit mode %c", *val); + exit(EX_USAGE); + } + break; +#endif + case 'A': /* set default alias file */ if (val[0] == '\0') setalias("aliases"); @@ -1145,8 +1681,9 @@ setoption(opt, val, safe, sticky, e) break; case SM_QUEUE: /* queue only */ + case SM_DEFER: /* queue only and defer map lookups */ #ifndef QUEUE - syserr("need QUEUE to set -odqueue"); + syserr("need QUEUE to set -odqueue or -oddefer"); #endif /* QUEUE */ /* fall through..... */ @@ -1177,9 +1714,6 @@ setoption(opt, val, safe, sticky, e) case EM_MAIL: /* mail back */ case EM_BERKNET: /* do berknet error processing */ case EM_WRITE: /* write back (or mail) */ - HoldErrs = TRUE; - /* fall through... */ - case EM_PRINT: /* print errors normally (default) */ e->e_errormode = *val; break; @@ -1199,6 +1733,7 @@ setoption(opt, val, safe, sticky, e) break; case 'g': /* default gid */ + g_opt: if (isascii(*val) && isdigit(*val)) DefGid = atoi(val); else @@ -1208,7 +1743,8 @@ setoption(opt, val, safe, sticky, e) DefGid = -1; gr = getgrnam(val); if (gr == NULL) - syserr("readcf: option g: unknown group %s", val); + syserr("readcf: option %c: unknown group %s", + opt, val); else DefGid = gr->gr_gid; } @@ -1227,7 +1763,6 @@ setoption(opt, val, safe, sticky, e) case 'I': /* use internet domain name server */ #if NAMED_BIND - UseNameServer = TRUE; for (p = val; *p != 0; ) { bool clearmode; @@ -1249,6 +1784,11 @@ setoption(opt, val, safe, sticky, e) p++; if (*p != '\0') *p++ = '\0'; + if (strcasecmp(q, "HasWildcardMX") == 0) + { + HasWildcardMX = !clearmode; + continue; + } for (rfp = ResolverFlags; rfp->rf_name != NULL; rfp++) { if (strcasecmp(q, rfp->rf_name) == 0) @@ -1262,7 +1802,8 @@ setoption(opt, val, safe, sticky, e) _res.options |= rfp->rf_bits; } if (tTd(8, 2)) - printf("_res.options = %x\n", _res.options); + printf("_res.options = %x, HasWildcardMX = %d\n", + _res.options, HasWildcardMX); #else usrerr("name server (I option) specified but BIND not compiled in"); #endif @@ -1318,7 +1859,11 @@ setoption(opt, val, safe, sticky, e) /* 'N' available -- was "net name" */ case 'O': /* daemon options */ +#ifdef DAEMON setdaemonoptions(val); +#else + syserr("DaemonPortOptions (O option) set but DAEMON not compiled in"); +#endif break; case 'o': /* assume old style headers */ @@ -1379,7 +1924,10 @@ setoption(opt, val, safe, sticky, e) break; case 'r': /* read timeout */ - settimeouts(val); + if (subopt == NULL) + inittimeouts(val); + else + settimeout(subopt, val); break; case 'S': /* status file */ @@ -1398,9 +1946,9 @@ setoption(opt, val, safe, sticky, e) if (p != NULL) { *p++ = '\0'; - TimeOuts.to_q_warning = convtime(p, 'd'); + settimeout("queuewarn", p); } - TimeOuts.to_q_return = convtime(val, 'h'); + settimeout("queuereturn", val); break; case 't': /* time zone name */ @@ -1412,6 +1960,14 @@ setoption(opt, val, safe, sticky, e) break; case 'u': /* set default uid */ + for (p = val; *p != '\0'; p++) + { + if (*p == '.' || *p == '/' || *p == ':') + { + *p++ = '\0'; + break; + } + } if (isascii(*val) && isdigit(*val)) DefUid = atoi(val); else @@ -1419,14 +1975,22 @@ setoption(opt, val, safe, sticky, e) register struct passwd *pw; DefUid = -1; - pw = getpwnam(val); + pw = sm_getpwnam(val); if (pw == NULL) syserr("readcf: option u: unknown user %s", val); else + { DefUid = pw->pw_uid; + DefGid = pw->pw_gid; + } } setdefuser(); - break; + + /* handle the group if it is there */ + if (*p == '\0') + break; + val = p; + goto g_opt; case 'V': /* fallback MX host */ FallBackMX = newstr(val); @@ -1466,19 +2030,133 @@ setoption(opt, val, safe, sticky, e) WkTimeFact = atoi(val); break; + case O_QUEUESORTORD: /* queue sorting order */ + switch (*val) + { + case 'h': /* Host first */ + case 'H': + QueueSortOrder = QS_BYHOST; + break; + + case 'p': /* Priority order */ + case 'P': + QueueSortOrder = QS_BYPRIORITY; + break; + + default: + syserr("Invalid queue sort order \"%s\"", val); + } + break; + + case O_HOSTSFILE: /* pathname of /etc/hosts file */ + HostsFile = newstr(val); + break; + + case O_MQA: /* minimum queue age between deliveries */ + MinQueueAge = convtime(val, 'm'); + break; + + case O_MHSA: /* maximum age of cached host status */ + MaxHostStatAge = convtime(val, 'm'); + break; + + case O_DEFCHARSET: /* default character set for mimefying */ + DefaultCharSet = newstr(denlstring(val, TRUE, TRUE)); + break; + + case O_SSFILE: /* service switch file */ + ServiceSwitchFile = newstr(val); + break; + + case O_DIALDELAY: /* delay for dial-on-demand operation */ + DialDelay = convtime(val, 's'); + break; + + case O_NORCPTACTION: /* what to do if no recipient */ + if (strcasecmp(val, "none") == 0) + NoRecipientAction = NRA_NO_ACTION; + else if (strcasecmp(val, "add-to") == 0) + NoRecipientAction = NRA_ADD_TO; + else if (strcasecmp(val, "add-apparently-to") == 0) + NoRecipientAction = NRA_ADD_APPARENTLY_TO; + else if (strcasecmp(val, "add-bcc") == 0) + NoRecipientAction = NRA_ADD_BCC; + else if (strcasecmp(val, "add-to-undisclosed") == 0) + NoRecipientAction = NRA_ADD_TO_UNDISCLOSED; + else + syserr("Invalid NoRecipientAction: %s", val); + break; + + case O_SAFEFILEENV: /* chroot() environ for writing to files */ + SafeFileEnv = newstr(val); + break; + + case O_MAXMSGSIZE: /* maximum message size */ + MaxMessageSize = atol(val); + break; + + case O_COLONOKINADDR: /* old style handling of colon addresses */ + ColonOkInAddr = atobool(val); + break; + + case O_MAXQUEUERUN: /* max # of jobs in a single queue run */ + MaxQueueRun = atol(val); + break; + + case O_MAXCHILDREN: /* max # of children of daemon */ + MaxChildren = atoi(val); + break; + + case O_KEEPCNAMES: /* don't expand CNAME records */ + DontExpandCnames = atobool(val); + break; + + case O_MUSTQUOTE: /* must quote these characters in phrases */ + strcpy(buf, "@,;:\\()[]"); + if (strlen(val) < sizeof buf - 10) + strcat(buf, val); + MustQuoteChars = newstr(buf); + break; + + case O_SMTPGREETING: /* SMTP greeting message (old $e macro) */ + SmtpGreeting = newstr(munchstring(val, NULL)); + break; + + case O_UNIXFROM: /* UNIX From_ line (old $l macro) */ + UnixFromLine = newstr(munchstring(val, NULL)); + break; + + case O_OPCHARS: /* operator characters (old $o macro) */ + OperatorChars = newstr(munchstring(val, NULL)); + break; + + case O_DONTINITGRPS: /* don't call initgroups(3) */ + DontInitGroups = atobool(val); + break; + + case O_SLFH: /* make sure from fits on one line */ + SingleLineFromHeader = atobool(val); + break; + default: + if (tTd(37, 1)) + { + if (isascii(opt) && isprint(opt)) + printf("Warning: option %c unknown\n", opt); + else + printf("Warning: option 0x%x unknown\n", opt); + } break; } if (sticky) setbitn(opt, StickyOpt); - return; } /* -** SETCLASS -- set a word into a class +** SETCLASS -- set a string into a class ** ** Parameters: -** class -- the class to put the word in. -** word -- the word to enter +** class -- the class to put the string in. +** str -- the string to enter ** ** Returns: ** none. @@ -1487,15 +2165,16 @@ setoption(opt, val, safe, sticky, e) ** puts the word into the symbol table. */ -setclass(class, word) +void +setclass(class, str) int class; - char *word; + char *str; { register STAB *s; if (tTd(37, 8)) - printf("setclass(%c, %s)\n", class, word); - s = stab(word, ST_CLASS, ST_ENTER); + printf("setclass(%s, %s)\n", macname(class), str); + s = stab(str, ST_CLASS, ST_ENTER); setbitn(class, s->s_class); } /* @@ -1505,14 +2184,14 @@ setclass(class, word) ** line -- the config file line ** ** Returns: -** TRUE if it successfully entered the map entry. -** FALSE otherwise (usually syntax error). +** A pointer to the map that has been created. +** NULL if there was a syntax error. ** ** Side Effects: ** Enters the map into the dictionary. */ -void +MAP * makemapentry(line) char *line; { @@ -1527,11 +2206,11 @@ makemapentry(line) if (!(isascii(*p) && isalnum(*p))) { syserr("readcf: config K line: no map name"); - return; + return NULL; } mapname = p; - while (isascii(*++p) && isalnum(*p)) + while ((isascii(*++p) && isalnum(*p)) || *p == '_' || *p == '.') continue; if (*p != '\0') *p++ = '\0'; @@ -1540,7 +2219,7 @@ makemapentry(line) if (!(isascii(*p) && isalnum(*p))) { syserr("readcf: config K line, map %s: no map class", mapname); - return; + return NULL; } classname = p; while (isascii(*++p) && isalnum(*p)) @@ -1555,7 +2234,7 @@ makemapentry(line) if (class == NULL) { syserr("readcf: map %s: class %s not available", mapname, classname); - return; + return NULL; } /* enter the map */ @@ -1577,9 +2256,128 @@ makemapentry(line) s->s_map.map_domain == NULL ? "(null)" : s->s_map.map_domain, s->s_map.map_rebuild == NULL ? "(null)" : s->s_map.map_rebuild); } + + return &s->s_map; } /* -** SETTIMEOUTS -- parse and set timeout values +** STRTORWSET -- convert string to rewriting set number +** +** Parameters: +** p -- the pointer to the string to decode. +** endp -- if set, store the trailing delimiter here. +** stabmode -- ST_ENTER to create this entry, ST_FIND if +** it must already exist. +** +** Returns: +** The appropriate ruleset number. +** -1 if it is not valid (error already printed) +*/ + +int +strtorwset(p, endp, stabmode) + char *p; + char **endp; + int stabmode; +{ + int ruleset; + static int nextruleset = MAXRWSETS; + + while (isascii(*p) && isspace(*p)) + p++; + if (!isascii(*p)) + { + syserr("invalid ruleset name: \"%.20s\"", p); + return -1; + } + if (isdigit(*p)) + { + ruleset = strtol(p, endp, 10); + if (ruleset >= MAXRWSETS / 2 || ruleset < 0) + { + syserr("bad ruleset %d (%d max)", + ruleset, MAXRWSETS / 2); + ruleset = -1; + } + } + else + { + STAB *s; + char delim; + char *q; + + q = p; + while (*p != '\0' && isascii(*p) && + (isalnum(*p) || *p == '_')) + p++; + if (q == p || !isalpha(*q)) + { + /* no valid characters */ + syserr("invalid ruleset name: \"%.20s\"", q); + return -1; + } + while (isascii(*p) && isspace(*p)) + *p++ = '\0'; + delim = *p; + if (delim != '\0') + *p = '\0'; + s = stab(q, ST_RULESET, stabmode); + if (delim != '\0') + *p = delim; + + if (s == NULL) + { + syserr("unknown ruleset %s", q); + return -1; + } + + if (stabmode == ST_ENTER && delim == '=') + { + while (isascii(*++p) && isspace(*p)) + continue; + if (!isdigit(*p)) + { + syserr("bad ruleset definition \"%s\" (number required after `=')", q); + ruleset = -1; + } + else + { + ruleset = strtol(p, endp, 10); + if (ruleset >= MAXRWSETS / 2 || ruleset < 0) + { + syserr("bad ruleset number %d in \"%s\" (%d max)", + ruleset, q, MAXRWSETS / 2); + ruleset = -1; + } + } + } + else + { + if (endp != NULL) + *endp = p; + if (s->s_ruleset > 0) + ruleset = s->s_ruleset; + else if ((ruleset = --nextruleset) < MAXRWSETS / 2) + { + syserr("%s: too many named rulesets (%d max)", + q, MAXRWSETS / 2); + ruleset = -1; + } + } + if (s->s_ruleset > 0 && ruleset >= 0 && ruleset != s->s_ruleset) + { + syserr("%s: ruleset changed value (old %d, new %d)", + q, ruleset, s->s_ruleset); + ruleset = s->s_ruleset; + } + else if (ruleset > 0) + { + s->s_ruleset = ruleset; + } + } + return ruleset; +} +/* +** INITTIMEOUTS -- parse and set timeout values ** ** Parameters: ** val -- a pointer to the values. If NULL, do initial @@ -1596,7 +2394,8 @@ makemapentry(line) #define MINUTES * 60 #define HOUR * 3600 -settimeouts(val) +void +inittimeouts(val) register char *val; { register char *p; @@ -1604,6 +2403,7 @@ settimeouts(val) if (val == NULL) { + TimeOuts.to_connect = (time_t) 0 SECONDS; TimeOuts.to_initial = (time_t) 5 MINUTES; TimeOuts.to_helo = (time_t) 5 MINUTES; TimeOuts.to_mail = (time_t) 10 MINUTES; @@ -1615,7 +2415,12 @@ settimeouts(val) TimeOuts.to_quit = (time_t) 2 MINUTES; TimeOuts.to_nextcommand = (time_t) 1 HOUR; TimeOuts.to_miscshort = (time_t) 2 MINUTES; +#if IDENTPROTO TimeOuts.to_ident = (time_t) 30 SECONDS; +#else + TimeOuts.to_ident = (time_t) 0 SECONDS; +#endif + TimeOuts.to_fileopen = (time_t) 60 SECONDS; return; } @@ -1643,43 +2448,107 @@ settimeouts(val) } else { - register char *q = strchr(val, '='); - time_t to; + register char *q = strchr(val, ':'); - if (q == NULL) + if (q == NULL && (q = strchr(val, '=')) == NULL) { /* syntax error */ continue; } *q++ = '\0'; - to = convtime(q, 'm'); - - if (strcasecmp(val, "initial") == 0) - TimeOuts.to_initial = to; - else if (strcasecmp(val, "mail") == 0) - TimeOuts.to_mail = to; - else if (strcasecmp(val, "rcpt") == 0) - TimeOuts.to_rcpt = to; - else if (strcasecmp(val, "datainit") == 0) - TimeOuts.to_datainit = to; - else if (strcasecmp(val, "datablock") == 0) - TimeOuts.to_datablock = to; - else if (strcasecmp(val, "datafinal") == 0) - TimeOuts.to_datafinal = to; - else if (strcasecmp(val, "command") == 0) - TimeOuts.to_nextcommand = to; - else if (strcasecmp(val, "rset") == 0) - TimeOuts.to_rset = to; - else if (strcasecmp(val, "helo") == 0) - TimeOuts.to_helo = to; - else if (strcasecmp(val, "quit") == 0) - TimeOuts.to_quit = to; - else if (strcasecmp(val, "misc") == 0) - TimeOuts.to_miscshort = to; - else if (strcasecmp(val, "ident") == 0) - TimeOuts.to_ident = to; - else - syserr("settimeouts: invalid timeout %s", val); + settimeout(val, q); } } } +/* +** SETTIMEOUT -- set an individual timeout +** +** Parameters: +** name -- the name of the timeout. +** val -- the value of the timeout. +** +** Returns: +** none. +*/ + +void +settimeout(name, val) + char *name; + char *val; +{ + register char *p; + time_t to; + extern time_t convtime(); + + to = convtime(val, 'm'); + p = strchr(name, '.'); + if (p != NULL) + *p++ = '\0'; + + if (strcasecmp(name, "initial") == 0) + TimeOuts.to_initial = to; + else if (strcasecmp(name, "mail") == 0) + TimeOuts.to_mail = to; + else if (strcasecmp(name, "rcpt") == 0) + TimeOuts.to_rcpt = to; + else if (strcasecmp(name, "datainit") == 0) + TimeOuts.to_datainit = to; + else if (strcasecmp(name, "datablock") == 0) + TimeOuts.to_datablock = to; + else if (strcasecmp(name, "datafinal") == 0) + TimeOuts.to_datafinal = to; + else if (strcasecmp(name, "command") == 0) + TimeOuts.to_nextcommand = to; + else if (strcasecmp(name, "rset") == 0) + TimeOuts.to_rset = to; + else if (strcasecmp(name, "helo") == 0) + TimeOuts.to_helo = to; + else if (strcasecmp(name, "quit") == 0) + TimeOuts.to_quit = to; + else if (strcasecmp(name, "misc") == 0) + TimeOuts.to_miscshort = to; + else if (strcasecmp(name, "ident") == 0) + TimeOuts.to_ident = to; + else if (strcasecmp(name, "fileopen") == 0) + TimeOuts.to_fileopen = to; + else if (strcasecmp(name, "connect") == 0) + TimeOuts.to_connect = to; + else if (strcasecmp(name, "queuewarn") == 0) + { + to = convtime(val, 'h'); + if (p == NULL || strcmp(p, "*") == 0) + { + TimeOuts.to_q_warning[TOC_NORMAL] = to; + TimeOuts.to_q_warning[TOC_URGENT] = to; + TimeOuts.to_q_warning[TOC_NONURGENT] = to; + } + else if (strcasecmp(p, "normal") == 0) + TimeOuts.to_q_warning[TOC_NORMAL] = to; + else if (strcasecmp(p, "urgent") == 0) + TimeOuts.to_q_warning[TOC_URGENT] = to; + else if (strcasecmp(p, "non-urgent") == 0) + TimeOuts.to_q_warning[TOC_NONURGENT] = to; + else + syserr("settimeout: invalid queuewarn subtimeout %s", p); + } + else if (strcasecmp(name, "queuereturn") == 0) + { + to = convtime(val, 'd'); + if (p == NULL || strcmp(p, "*") == 0) + { + TimeOuts.to_q_return[TOC_NORMAL] = to; + TimeOuts.to_q_return[TOC_URGENT] = to; + TimeOuts.to_q_return[TOC_NONURGENT] = to; + } + else if (strcasecmp(p, "normal") == 0) + TimeOuts.to_q_return[TOC_NORMAL] = to; + else if (strcasecmp(p, "urgent") == 0) + TimeOuts.to_q_return[TOC_URGENT] = to; + else if (strcasecmp(p, "non-urgent") == 0) + TimeOuts.to_q_return[TOC_NONURGENT] = to; + else + syserr("settimeout: invalid queuereturn subtimeout %s", p); + } + else + syserr("settimeout: invalid timeout %s", name); +} diff --git a/usr.sbin/sendmail/src/recipient.c b/usr.sbin/sendmail/src/recipient.c index 0b12c2c..79126e9 100644 --- a/usr.sbin/sendmail/src/recipient.c +++ b/usr.sbin/sendmail/src/recipient.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,11 +33,10 @@ */ #ifndef lint -static char sccsid[] = "@(#)recipient.c 8.44.1.6 (Berkeley) 3/5/95"; +static char sccsid[] = "@(#)recipient.c 8.108 (Berkeley) 10/30/95"; #endif /* not lint */ # include "sendmail.h" -# include <pwd.h> /* ** SENDTOLIST -- Designate a send list. @@ -53,6 +52,8 @@ static char sccsid[] = "@(#)recipient.c 8.44.1.6 (Berkeley) 3/5/95"; ** expansion. ** sendq -- a pointer to the head of a queue to put ** these people into. +** aliaslevel -- the current alias nesting depth -- to +** diagnose loops. ** e -- the envelope in which to add these recipients. ** ** Returns: @@ -62,12 +63,15 @@ static char sccsid[] = "@(#)recipient.c 8.44.1.6 (Berkeley) 3/5/95"; ** none. */ -# define MAXRCRSN 10 +/* q_flags bits inherited from ctladdr */ +#define QINHERITEDBITS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY|QHASNOTIFY) -sendtolist(list, ctladdr, sendq, e) +int +sendtolist(list, ctladdr, sendq, aliaslevel, e) char *list; ADDRESS *ctladdr; ADDRESS **sendq; + int aliaslevel; register ENVELOPE *e; { register char *p; @@ -128,13 +132,58 @@ sendtolist(list, ctladdr, sendq, e) a->q_next = al; a->q_alias = ctladdr; - /* see if this should be marked as a primary address */ - if (ctladdr == NULL || - (firstone && *p == '\0' && bitset(QPRIMARY, ctladdr->q_flags))) - a->q_flags |= QPRIMARY; + /* arrange to inherit attributes from parent */ + if (ctladdr != NULL) + { + ADDRESS *b; + extern ADDRESS *self_reference(); + + /* self reference test */ + if (sameaddr(ctladdr, a)) + { + if (tTd(27, 5)) + { + printf("sendtolist: QSELFREF "); + printaddr(ctladdr, FALSE); + } + ctladdr->q_flags |= QSELFREF; + } + + /* check for address loops */ + b = self_reference(a, e); + if (b != NULL) + { + b->q_flags |= QSELFREF; + if (tTd(27, 5)) + { + printf("sendtolist: QSELFREF "); + printaddr(b, FALSE); + } + if (a != b) + { + if (tTd(27, 5)) + { + printf("sendtolist: QDONTSEND "); + printaddr(a, FALSE); + } + a->q_flags |= QDONTSEND; + b->q_flags |= a->q_flags & QNOTREMOTE; + continue; + } + } + + /* full name */ + if (a->q_fullname == NULL) + a->q_fullname = ctladdr->q_fullname; + + /* various flag bits */ + a->q_flags &= ~QINHERITEDBITS; + a->q_flags |= ctladdr->q_flags & QINHERITEDBITS; + + /* original recipient information */ + a->q_orcpt = ctladdr->q_orcpt; + } - if (ctladdr != NULL && sameaddr(ctladdr, a)) - ctladdr->q_flags |= QSELFREF; al = a; firstone = FALSE; } @@ -145,11 +194,7 @@ sendtolist(list, ctladdr, sendq, e) register ADDRESS *a = al; al = a->q_next; - a = recipient(a, sendq, e); - - /* arrange to inherit full name */ - if (a->q_fullname == NULL && ctladdr != NULL) - a->q_fullname = ctladdr->q_fullname; + a = recipient(a, sendq, aliaslevel, e); naddrs++; } @@ -168,6 +213,7 @@ sendtolist(list, ctladdr, sendq, e) ** sendq -- a pointer to the head of a queue to put the ** recipient in. Duplicate supression is done ** in this queue. +** aliaslevel -- the current alias nesting depth. ** e -- the current envelope. ** ** Returns: @@ -179,9 +225,10 @@ sendtolist(list, ctladdr, sendq, e) */ ADDRESS * -recipient(a, sendq, e) +recipient(a, sendq, aliaslevel, e) register ADDRESS *a; register ADDRESS **sendq; + int aliaslevel; register ENVELOPE *e; { register ADDRESS *q; @@ -190,15 +237,20 @@ recipient(a, sendq, e) register char *p; bool quoted = FALSE; /* set if the addr has a quote bit */ int findusercount = 0; - char buf[MAXNAME]; /* unquoted image of the user name */ + bool initialdontsend = bitset(QDONTSEND, a->q_flags); + int i; + char *buf; + char buf0[MAXNAME + 1]; /* unquoted image of the user name */ extern int safefile(); e->e_to = a->q_paddr; m = a->q_mailer; errno = 0; + if (aliaslevel == 0) + a->q_flags |= QPRIMARY; if (tTd(26, 1)) { - printf("\nrecipient: "); + printf("\nrecipient (%d): ", aliaslevel); printaddr(a, FALSE); } @@ -212,9 +264,11 @@ recipient(a, sendq, e) } /* break aliasing loops */ - if (AliasLevel > MAXRCRSN) + if (aliaslevel > MaxAliasRecursion) { - usrerr("554 aliasing/forwarding loop broken"); + a->q_status = "5.4.6"; + usrerr("554 aliasing/forwarding loop broken (%d aliases deep; %d max", + aliaslevel, MaxAliasRecursion); return (a); } @@ -222,10 +276,12 @@ recipient(a, sendq, e) ** Finish setting up address structure. */ - /* set the queue timeout */ - a->q_timeout = TimeOuts.to_q_return; - /* get unquoted user for file, program or user.name check */ + i = strlen(a->q_user); + if (i >= sizeof buf0) + buf = xalloc(i + 1); + else + buf = buf0; (void) strcpy(buf, a->q_user); for (p = buf; *p != '\0' && !quoted; p++) { @@ -240,17 +296,20 @@ recipient(a, sendq, e) if (a->q_alias == NULL) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 Cannot mail directly to programs"); } else if (bitset(QBOGUSSHELL, a->q_alias->q_flags)) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 User %s@%s doesn't have a valid shell for mailing to programs", a->q_alias->q_ruser, MyHostName); } else if (bitset(QUNSAFEADDR, a->q_alias->q_flags)) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 Address %s is unsafe for mailing to programs", a->q_alias->q_paddr); } @@ -283,7 +342,7 @@ recipient(a, sendq, e) else if (bitset(QSELFREF, q->q_flags)) q->q_flags |= a->q_flags & ~QDONTSEND; a = q; - goto testselfdestruct; + goto done; } } @@ -308,6 +367,7 @@ recipient(a, sendq, e) if (a->q_alias == NULL) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 Cannot mail directly to :include:s"); } else @@ -315,25 +375,29 @@ recipient(a, sendq, e) int ret; message("including file %s", a->q_user); - ret = include(a->q_user, FALSE, a, sendq, e); + ret = include(a->q_user, FALSE, a, sendq, aliaslevel, e); if (transienterror(ret)) { #ifdef LOG if (LogLevel > 2) syslog(LOG_ERR, "%s: include %s: transient error: %s", e->e_id == NULL ? "NOQUEUE" : e->e_id, - a->q_user, errstring(ret)); + shortenstring(a->q_user, 203), + errstring(ret)); #endif a->q_flags |= QQUEUEUP; a->q_flags &= ~QDONTSEND; usrerr("451 Cannot open %s: %s", - a->q_user, errstring(ret)); + shortenstring(a->q_user, 203), + errstring(ret)); } else if (ret != 0) { a->q_flags |= QBADADDR; + a->q_status = "5.2.4"; usrerr("550 Cannot open %s: %s", - a->q_user, errstring(ret)); + shortenstring(a->q_user, 203), + errstring(ret)); } } } @@ -345,44 +409,44 @@ recipient(a, sendq, e) if (a->q_alias == NULL) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 Cannot mail directly to files"); } else if (bitset(QBOGUSSHELL, a->q_alias->q_flags)) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 User %s@%s doesn't have a valid shell for mailing to files", a->q_alias->q_ruser, MyHostName); } else if (bitset(QUNSAFEADDR, a->q_alias->q_flags)) { a->q_flags |= QBADADDR; + a->q_status = "5.7.1"; usrerr("550 Address %s is unsafe for mailing to files", a->q_alias->q_paddr); } - else if (!writable(buf, getctladdr(a), SFF_ANYFILE)) + else if (!writable(buf, a->q_alias, SFF_CREAT)) { a->q_flags |= QBADADDR; - giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, e); + giveresponse(EX_CANTCREAT, m, NULL, a->q_alias, + (time_t) 0, e); } } - if (m != LocalMailer) - { - if (!bitset(QDONTSEND, a->q_flags)) - e->e_nrcpts++; - goto testselfdestruct; - } - /* try aliasing */ - alias(a, sendq, e); + if (!quoted && !bitset(QDONTSEND, a->q_flags) && + bitnset(M_ALIASABLE, m->m_flags)) + alias(a, sendq, aliaslevel, e); -# ifdef USERDB +# if USERDB /* if not aliased, look it up in the user database */ - if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags)) + if (!bitset(QDONTSEND|QNOTREMOTE|QVERIFIED, a->q_flags) && + bitnset(M_CHECKUDB, m->m_flags)) { extern int udbexpand(); - if (udbexpand(a, sendq, e) == EX_TEMPFAIL) + if (udbexpand(a, sendq, aliaslevel, e) == EX_TEMPFAIL) { a->q_flags |= QQUEUEUP; if (e->e_message == NULL) @@ -401,10 +465,6 @@ recipient(a, sendq, e) } # endif - /* if it was an alias or a UDB expansion, just return now */ - if (bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags)) - goto testselfdestruct; - /* ** If we have a level two config file, then pass the name through ** Ruleset 5 before sending it off. Ruleset 5 has the right @@ -418,10 +478,11 @@ recipient(a, sendq, e) ConfigLevel, RewriteRules[5]); printaddr(a, FALSE); } - if (!bitset(QNOTREMOTE, a->q_flags) && ConfigLevel >= 2 && - RewriteRules[5] != NULL) + if (!bitset(QNOTREMOTE|QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) && + ConfigLevel >= 2 && RewriteRules[5] != NULL && + bitnset(M_TRYRULESET5, m->m_flags)) { - maplocaluser(a, sendq, e); + maplocaluser(a, sendq, aliaslevel + 1, e); } /* @@ -429,7 +490,8 @@ recipient(a, sendq, e) ** and deliver it. */ - if (!bitset(QDONTSEND|QQUEUEUP, a->q_flags)) + if (!bitset(QDONTSEND|QQUEUEUP|QVERIFIED, a->q_flags) && + bitnset(M_HASPWENT, m->m_flags)) { auto bool fuzzy; register struct passwd *pw; @@ -440,11 +502,13 @@ recipient(a, sendq, e) if (pw == NULL) { a->q_flags |= QBADADDR; - giveresponse(EX_NOUSER, m, NULL, a->q_alias, e); + a->q_status = "5.1.1"; + giveresponse(EX_NOUSER, m, NULL, a->q_alias, + (time_t) 0, e); } else { - char nbuf[MAXNAME]; + char nbuf[MAXNAME + 1]; if (fuzzy) { @@ -453,9 +517,10 @@ recipient(a, sendq, e) if (findusercount++ > 3) { a->q_flags |= QBADADDR; + a->q_status = "5.4.6"; usrerr("554 aliasing/forwarding loop for %s broken", pw->pw_name); - return (a); + goto done; } /* see if it aliases */ @@ -473,36 +538,103 @@ recipient(a, sendq, e) buildfname(pw->pw_gecos, pw->pw_name, nbuf); if (nbuf[0] != '\0') a->q_fullname = newstr(nbuf); - if (pw->pw_shell != NULL && pw->pw_shell[0] != '\0' && - !usershellok(pw->pw_shell)) + if (!usershellok(pw->pw_name, pw->pw_shell)) { a->q_flags |= QBOGUSSHELL; } - if (!quoted) - forward(a, sendq, e); + if (bitset(EF_VRFYONLY, e->e_flags)) + { + /* don't do any more now */ + a->q_flags |= QVERIFIED; + } + else if (!quoted) + forward(a, sendq, aliaslevel, e); } } if (!bitset(QDONTSEND, a->q_flags)) e->e_nrcpts++; testselfdestruct: + a->q_flags |= QTHISPASS; if (tTd(26, 8)) { printf("testselfdestruct: "); - printaddr(a, TRUE); + printaddr(a, FALSE); + if (tTd(26, 10)) + { + printf("SENDQ:\n"); + printaddr(*sendq, TRUE); + printf("----\n"); + } } if (a->q_alias == NULL && a != &e->e_from && bitset(QDONTSEND, a->q_flags)) { - q = *sendq; - while (q != NULL && bitset(QDONTSEND, q->q_flags)) - q = q->q_next; + for (q = *sendq; q != NULL; q = q->q_next) + { + if (!bitset(QDONTSEND, q->q_flags)) + break; + } if (q == NULL) { a->q_flags |= QBADADDR; + a->q_status = "5.4.6"; usrerr("554 aliasing/forwarding loop broken"); } } + + done: + a->q_flags |= QTHISPASS; + if (buf != buf0) + free(buf); + + /* + ** If we are at the top level, check to see if this has + ** expanded to exactly one address. If so, it can inherit + ** the primaryness of the address. + ** + ** While we're at it, clear the QTHISPASS bits. + */ + + if (aliaslevel == 0) + { + int nrcpts = 0; + ADDRESS *only; + + for (q = *sendq; q != NULL; q = q->q_next) + { + if (bitset(QTHISPASS, q->q_flags) && + !bitset(QDONTSEND|QBADADDR, q->q_flags)) + { + nrcpts++; + only = q; + } + q->q_flags &= ~QTHISPASS; + } + if (nrcpts == 1) + { + /* check to see if this actually got a new owner */ + q = only; + while ((q = q->q_alias) != NULL) + { + if (q->q_owner != NULL) + break; + } + if (q == NULL) + only->q_flags |= QPRIMARY; + } + else if (!initialdontsend && nrcpts > 0) + { + /* arrange for return receipt */ + e->e_flags |= EF_SENDRECEIPT; + a->q_flags |= QEXPANDED; + if (e->e_xfp != NULL && bitset(QPINGONSUCCESS, a->q_flags)) + fprintf(e->e_xfp, + "%s... expanded to multiple addresses\n", + a->q_paddr); + } + } + return (a); } /* @@ -535,14 +667,14 @@ finduser(name, fuzzyp) { register struct passwd *pw; register char *p; - extern struct passwd *getpwent(); - extern struct passwd *getpwnam(); + bool tryagain; if (tTd(29, 4)) printf("finduser(%s): ", name); *fuzzyp = FALSE; +#ifdef HESIOD /* DEC Hesiod getpwnam accepts numeric strings -- short circuit it */ for (p = name; *p != '\0'; p++) if (!isascii(*p) || !isdigit(*p)) @@ -553,16 +685,35 @@ finduser(name, fuzzyp) printf("failed (numeric input)\n"); return NULL; } +#endif /* look up this login name using fast path */ - if ((pw = getpwnam(name)) != NULL) + if ((pw = sm_getpwnam(name)) != NULL) { if (tTd(29, 4)) printf("found (non-fuzzy)\n"); return (pw); } -#ifdef MATCHGECOS + /* try mapping it to lower case */ + tryagain = FALSE; + for (p = name; *p != '\0'; p++) + { + if (isascii(*p) && isupper(*p)) + { + *p = tolower(*p); + tryagain = TRUE; + } + } + if (tryagain && (pw = sm_getpwnam(name)) != NULL) + { + if (tTd(29, 4)) + printf("found (lower case)\n"); + *fuzzyp = TRUE; + return pw; + } + +#if MATCHGECOS /* see if fuzzy matching allowed */ if (!MatchGecos) { @@ -580,7 +731,17 @@ finduser(name, fuzzyp) (void) setpwent(); while ((pw = getpwent()) != NULL) { - char buf[MAXNAME]; + char buf[MAXNAME + 1]; + +# if 0 + if (strcasecmp(pw->pw_name, name) == 0) + { + if (tTd(29, 4)) + printf("found (case wrapped)\n"); + *fuzzyp = TRUE; + return pw; + } +# endif buildfname(pw->pw_gecos, pw->pw_name, buf); if (strchr(buf, ' ') != NULL && !strcasecmp(buf, name)) @@ -632,90 +793,53 @@ writable(filename, ctladdr, flags) { uid_t euid; gid_t egid; - int bits; - register char *p; char *uname; - struct stat stb; - extern char RealUserName[]; - - if (tTd(29, 5)) - printf("writable(%s, %x)\n", filename, flags); - -#ifdef HASLSTAT - if ((bitset(SFF_NOSLINK, flags) ? lstat(filename, &stb) - : stat(filename, &stb)) < 0) -#else - if (stat(filename, &stb) < 0) -#endif - { - /* file does not exist -- see if directory is safe */ - p = strrchr(filename, '/'); - if (p == NULL) - { - errno = ENOTDIR; - return FALSE; - } - *p = '\0'; - errno = safefile(filename, RealUid, RealGid, RealUserName, - SFF_MUSTOWN, S_IWRITE|S_IEXEC); - *p = '/'; - return errno == 0; - } -#ifdef SUID_ROOT_FILES_OK - /* really ought to be passed down -- and not a good idea */ - flags |= SFF_ROOTOK; -#endif + if (tTd(44, 5)) + printf("writable(%s, 0x%x)\n", filename, flags); /* ** File does exist -- check that it is writable. */ - if (bitset(0111, stb.st_mode)) - { - if (tTd(29, 5)) - printf("failed (mode %o: x bits)\n", stb.st_mode); - errno = EPERM; - return (FALSE); - } - if (ctladdr != NULL && geteuid() == 0) { euid = ctladdr->q_uid; egid = ctladdr->q_gid; uname = ctladdr->q_user; } - else + else if (bitset(SFF_RUNASREALUID, flags)) { euid = RealUid; egid = RealGid; uname = RealUserName; } - if (euid == 0) + else if (FileMailer != NULL && !bitset(SFF_ROOTOK, flags)) { - euid = DefUid; - uname = DefUser; + euid = FileMailer->m_uid; + egid = FileMailer->m_gid; + uname = NULL; + } + else + { + euid = egid = 0; + uname = NULL; } - if (egid == 0) - egid = DefGid; - if (geteuid() == 0) + if (!bitset(SFF_ROOTOK, flags)) { - if (bitset(S_ISUID, stb.st_mode) && - (stb.st_uid != 0 || bitset(SFF_ROOTOK, flags))) + if (euid == 0) { - euid = stb.st_uid; - uname = NULL; + euid = DefUid; + uname = DefUser; } - if (bitset(S_ISGID, stb.st_mode) && - (stb.st_gid != 0 || bitset(SFF_ROOTOK, flags))) - egid = stb.st_gid; + if (egid == 0) + egid = DefGid; } + if (geteuid() == 0 && + (ctladdr == NULL || !bitset(QGOODUID, ctladdr->q_flags))) + flags |= SFF_SETUIDOK; - if (tTd(29, 5)) - printf("\teu/gid=%d/%d, st_u/gid=%d/%d\n", - euid, egid, stb.st_uid, stb.st_gid); - - errno = safefile(filename, euid, egid, uname, flags, S_IWRITE); + errno = safefile(filename, euid, egid, uname, flags, S_IWRITE, NULL); return errno == 0; } /* @@ -730,6 +854,8 @@ writable(filename, ctladdr, flags) ** the important things. ** sendq -- a pointer to the head of the send queue ** to put these addresses in. +** aliaslevel -- the alias nesting depth. +** e -- the current envelope. ** ** Returns: ** open error status @@ -753,32 +879,29 @@ writable(filename, ctladdr, flags) */ static jmp_buf CtxIncludeTimeout; -static int includetimeout(); - -#ifndef S_IWOTH -# define S_IWOTH (S_IWRITE >> 6) -#endif +static void includetimeout(); int -include(fname, forwarding, ctladdr, sendq, e) +include(fname, forwarding, ctladdr, sendq, aliaslevel, e) char *fname; bool forwarding; ADDRESS *ctladdr; ADDRESS **sendq; + int aliaslevel; ENVELOPE *e; { - register FILE *fp = NULL; + FILE *volatile fp = NULL; char *oldto = e->e_to; char *oldfilename = FileName; int oldlinenumber = LineNumber; register EVENT *ev = NULL; int nincludes; register ADDRESS *ca; - uid_t saveduid, uid; - gid_t savedgid, gid; - char *uname; + volatile uid_t saveduid, uid; + volatile gid_t savedgid, gid; + char *volatile uname; int rval = 0; - int sfflags = forwarding ? SFF_MUSTOWN : SFF_ANYFILE; + int sfflags = SFF_REGONLY; struct stat st; char buf[MAXLINE]; #ifdef _POSIX_CHOWN_RESTRICTED @@ -813,30 +936,47 @@ include(fname, forwarding, ctladdr, sendq, e) if (tTd(27, 9)) printf("include: old uid = %d/%d\n", getuid(), geteuid()); + if (forwarding) + sfflags |= SFF_MUSTOWN|SFF_ROOTOK|SFF_NOSLINK; + ca = getctladdr(ctladdr); if (ca == NULL) { uid = DefUid; gid = DefGid; uname = DefUser; - saveduid = -1; } else { uid = ca->q_uid; gid = ca->q_gid; uname = ca->q_user; -#ifdef HASSETREUID - saveduid = geteuid(); - savedgid = getegid(); - if (saveduid == 0) - { + } +#if HASSETREUID || USESETEUID + saveduid = geteuid(); + savedgid = getegid(); + if (saveduid == 0) + { + if (!DontInitGroups) initgroups(uname, gid); - if (uid != 0) - (void) setreuid(0, uid); + if (gid != 0) + (void) setgid(gid); + if (uid != 0) + { +# if USESETEUID + if (seteuid(uid) < 0) + syserr("seteuid(%d) failure (real=%d, eff=%d)", + uid, getuid(), geteuid()); +# else + if (setreuid(0, uid) < 0) + syserr("setreuid(0, %d) failure (real=%d, eff=%d)", + uid, getuid(), geteuid()); +# endif + else + sfflags |= SFF_NOPATHCHECK; } -#endif } +#endif if (tTd(27, 9)) printf("include: new uid = %d/%d\n", getuid(), geteuid()); @@ -855,10 +995,13 @@ include(fname, forwarding, ctladdr, sendq, e) rval = EOPENTIMEOUT; goto resetuid; } - ev = setevent((time_t) 60, includetimeout, 0); + if (TimeOuts.to_fileopen > 0) + ev = setevent(TimeOuts.to_fileopen, includetimeout, 0); + else + ev = NULL; /* the input file must be marked safe */ - rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD); + rval = safefile(fname, uid, gid, uname, sfflags, S_IREAD, NULL); if (rval != 0) { /* don't use this :include: file */ @@ -876,17 +1019,29 @@ include(fname, forwarding, ctladdr, sendq, e) printf("include: open: %s\n", errstring(rval)); } } - clrevent(ev); + if (ev != NULL) + clrevent(ev); resetuid: -#ifdef HASSETREUID +#if HASSETREUID || USESETEUID if (saveduid == 0) { if (uid != 0) - if (setreuid(-1, 0) < 0 || setreuid(RealUid, 0) < 0) + { +# if USESETEUID + if (seteuid(0) < 0) + syserr("seteuid(0) failure (real=%d, eff=%d)", + getuid(), geteuid()); +# else + if (setreuid(-1, 0) < 0) + syserr("setreuid(-1, 0) failure (real=%d, eff=%d)", + getuid(), geteuid()); + if (setreuid(RealUid, 0) < 0) syserr("setreuid(%d, 0) failure (real=%d, eff=%d)", RealUid, getuid(), geteuid()); +# endif + } setgid(savedgid); } #endif @@ -924,25 +1079,34 @@ resetuid: } else { - char *sh; register struct passwd *pw; - sh = "/SENDMAIL/ANY/SHELL/"; - pw = getpwuid(st.st_uid); - if (pw != NULL) - { - ctladdr->q_ruser = newstr(pw->pw_name); - if (safechown) - sh = pw->pw_shell; - } + pw = sm_getpwuid(st.st_uid); if (pw == NULL) ctladdr->q_flags |= QBOGUSSHELL; - else if(!usershellok(sh)) + else { + char *sh; + + ctladdr->q_ruser = newstr(pw->pw_name); if (safechown) - ctladdr->q_flags |= QBOGUSSHELL; + sh = pw->pw_shell; else - ctladdr->q_flags |= QUNSAFEADDR; + sh = "/SENDMAIL/ANY/SHELL/"; + if (!usershellok(pw->pw_name, sh)) + { +#ifdef LOG + if (LogLevel >= 12) + syslog(LOG_INFO, "%s: user %s has bad shell %s, marked %s", + shortenstring(fname, 203), + pw->pw_name, sh, + safechown ? "bogus" : "unsafe"); +#endif + if (safechown) + ctladdr->q_flags |= QBOGUSSHELL; + else + ctladdr->q_flags |= QUNSAFEADDR; + } } } @@ -966,7 +1130,15 @@ resetuid: */ if (bitset(S_IWOTH, st.st_mode)) + { +#ifdef LOG + if (LogLevel >= 12) + syslog(LOG_INFO, "%s: world writable %s file, marked unsafe", + shortenstring(fname, 203), + forwarding ? "forward" : ":include:"); +#endif ctladdr->q_flags |= QUNSAFEADDR; + } /* read the file -- each line is a comma-separated list. */ FileName = fname; @@ -982,19 +1154,33 @@ resetuid: *p = '\0'; if (buf[0] == '#' || buf[0] == '\0') continue; + + /* <sp>#@# introduces a comment anywhere */ + /* for Japanese character sets */ + for (p = buf; (p = strchr(++p, '#')) != NULL; ) + { + if (p[1] == '@' && p[2] == '#' && + isascii(p[-1]) && isspace(p[-1]) && + (p[3] == '\0' || (isascii(p[3]) && isspace(p[3])))) + { + p[-1] = '\0'; + break; + } + } + if (buf[0] == '\0') + continue; + e->e_to = NULL; message("%s to %s", forwarding ? "forwarding" : "sending", buf); #ifdef LOG if (forwarding && LogLevel > 9) - syslog(LOG_INFO, "%s: forward %s => %s", + syslog(LOG_INFO, "%s: forward %.200s => %s", e->e_id == NULL ? "NOQUEUE" : e->e_id, - oldto, buf); + oldto, shortenstring(buf, 203)); #endif - AliasLevel++; - nincludes += sendtolist(buf, ctladdr, sendq, e); - AliasLevel--; + nincludes += sendtolist(buf, ctladdr, sendq, aliaslevel + 1, e); } if (ferror(fp) && tTd(27, 3)) @@ -1016,7 +1202,7 @@ resetuid: return rval; } -static +static void includetimeout() { longjmp(CtxIncludeTimeout, 1); @@ -1036,6 +1222,7 @@ includetimeout() ** send queue. */ +void sendtoargv(argv, e) register char **argv; register ENVELOPE *e; @@ -1044,7 +1231,7 @@ sendtoargv(argv, e) while ((p = *argv++) != NULL) { - (void) sendtolist(p, NULLADDR, &e->e_sendqueue, e); + (void) sendtolist(p, NULLADDR, &e->e_sendqueue, 0, e); } } /* @@ -1070,3 +1257,93 @@ getctladdr(a) a = a->q_alias; return (a); } +/* +** SELF_REFERENCE -- check to see if an address references itself +** +** The check is done through a chain of aliases. If it is part of +** a loop, break the loop at the "best" address, that is, the one +** that exists as a real user. +** +** This is to handle the case of: +** awc: Andrew.Chang +** Andrew.Chang: awc@mail.server +** which is a problem only on mail.server. +** +** Parameters: +** a -- the address to check. +** e -- the current envelope. +** +** Returns: +** The address that should be retained. +*/ + +ADDRESS * +self_reference(a, e) + ADDRESS *a; + ENVELOPE *e; +{ + ADDRESS *b; /* top entry in self ref loop */ + ADDRESS *c; /* entry that point to a real mail box */ + + if (tTd(27, 1)) + printf("self_reference(%s)\n", a->q_paddr); + + for (b = a->q_alias; b != NULL; b = b->q_alias) + { + if (sameaddr(a, b)) + break; + } + + if (b == NULL) + { + if (tTd(27, 1)) + printf("\t... no self ref\n"); + return NULL; + } + + /* + ** Pick the first address that resolved to a real mail box + ** i.e has a pw entry. The returned value will be marked + ** QSELFREF in recipient(), which in turn will disable alias() + ** from marking it QDONTSEND, which mean it will be used + ** as a deliverable address. + ** + ** The 2 key thing to note here are: + ** 1) we are in a recursive call sequence: + ** alias->sentolist->recipient->alias + ** 2) normally, when we return back to alias(), the address + ** will be marked QDONTSEND, since alias() assumes the + ** expanded form will be used instead of the current address. + ** This behaviour is turned off if the address is marked + ** QSELFREF We set QSELFREF when we return to recipient(). + */ + + c = a; + while (c != NULL) + { + if (bitnset(M_HASPWENT, c->q_mailer->m_flags)) + { + if (tTd(27, 2)) + printf("\t... getpwnam(%s)... ", c->q_user); + if (sm_getpwnam(c->q_user) != NULL) + { + if (tTd(27, 2)) + printf("found\n"); + + /* ought to cache results here */ + if (sameaddr(b, c)) + return b; + else + return c; + } + if (tTd(27, 2)) + printf("failed\n"); + } + c = c->q_alias; + } + + if (tTd(27, 1)) + printf("\t... cannot break loop for \"%s\"\n", a->q_paddr); + + return NULL; +} diff --git a/usr.sbin/sendmail/src/savemail.c b/usr.sbin/sendmail/src/savemail.c index 65c915d..9898cdd 100644 --- a/usr.sbin/sendmail/src/savemail.c +++ b/usr.sbin/sendmail/src/savemail.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -33,11 +33,10 @@ */ #ifndef lint -static char sccsid[] = "@(#)savemail.c 8.29 (Berkeley) 5/10/94"; +static char sccsid[] = "@(#)savemail.c 8.87 (Berkeley) 10/28/95"; #endif /* not lint */ # include "sendmail.h" -# include <pwd.h> /* ** SAVEMAIL -- Save mail on error @@ -49,6 +48,8 @@ static char sccsid[] = "@(#)savemail.c 8.29 (Berkeley) 5/10/94"; ** ** Parameters: ** e -- the envelope containing the message in error. +** sendbody -- if TRUE, also send back the body of the +** message; otherwise just send the header. ** ** Returns: ** none @@ -74,8 +75,10 @@ static char sccsid[] = "@(#)savemail.c 8.29 (Berkeley) 5/10/94"; # endif -savemail(e) +void +savemail(e, sendbody) register ENVELOPE *e; + bool sendbody; { register struct passwd *pw; register FILE *fp; @@ -83,8 +86,8 @@ savemail(e) auto ADDRESS *q = NULL; register char *p; MCI mcibuf; + int sfflags; char buf[MAXLINE+1]; - extern struct passwd *getpwnam(); extern char *ttypath(); typedef int (*fnptr)(); extern bool writable(); @@ -143,11 +146,6 @@ savemail(e) break; case EM_BERKNET: - /* mail back, but return o.k. exit status */ - ExitStat = EX_OK; - - /* fall through.... */ - case EM_MAIL: state = ESM_MAIL; break; @@ -187,7 +185,7 @@ savemail(e) switch (state) { case ESM_QUIET: - if (e->e_from.q_mailer == LocalMailer) + if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags)) state = ESM_DEADLETTER; else state = ESM_MAIL; @@ -207,7 +205,7 @@ savemail(e) break; } - expand("\201n", buf, &buf[sizeof buf - 1], e); + expand("\201n", buf, sizeof buf, e); printf("\r\nMessage from %s...\r\n", buf); printf("Errors occurred while sending mail.\r\n"); if (e->e_xfp != NULL) @@ -256,12 +254,12 @@ savemail(e) if (ExitStat == EX_CONFIG || ExitStat == EX_SOFTWARE) { (void) sendtolist("postmaster", - NULLADDR, &e->e_errorqueue, e); + NULLADDR, &e->e_errorqueue, 0, e); } - if (strcmp(e->e_from.q_paddr, "<>") != 0) + if (!emptyaddr(&e->e_from)) { (void) sendtolist(e->e_from.q_paddr, - NULLADDR, &e->e_errorqueue, e); + NULLADDR, &e->e_errorqueue, 0, e); } /* @@ -285,7 +283,7 @@ savemail(e) break; } if (returntosender(e->e_message, e->e_errorqueue, - (e->e_class >= 0), e) == 0) + sendbody, e) == 0) { state = ESM_DONE; break; @@ -301,15 +299,14 @@ savemail(e) */ q = NULL; - if (sendtolist("postmaster", NULL, &q, e) <= 0) + if (sendtolist("postmaster", NULL, &q, 0, e) <= 0) { syserr("553 cannot parse postmaster!"); ExitStat = EX_SOFTWARE; state = ESM_USRTMP; break; } - if (returntosender(e->e_message, - q, (e->e_class >= 0), e) == 0) + if (returntosender(e->e_message, q, sendbody, e) == 0) { state = ESM_DONE; break; @@ -330,44 +327,36 @@ savemail(e) */ p = NULL; - if (e->e_from.q_mailer == LocalMailer) + if (bitnset(M_HASPWENT, e->e_from.q_mailer->m_flags)) { if (e->e_from.q_home != NULL) p = e->e_from.q_home; - else if ((pw = getpwnam(e->e_from.q_user)) != NULL) + else if ((pw = sm_getpwnam(e->e_from.q_user)) != NULL) p = pw->pw_dir; } - if (p == NULL) + if (p == NULL || e->e_dfp == NULL) { - /* no local directory */ + /* no local directory or no data file */ state = ESM_MAIL; break; } - if (e->e_dfp != NULL) + + /* we have a home directory; write dead.letter */ + define('z', p, e); + expand("\201z/dead.letter", buf, sizeof buf, e); + sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_RUNASREALUID; + e->e_to = buf; + if (mailfile(buf, NULL, sfflags, e) == EX_OK) { bool oldverb = Verbose; - /* we have a home directory; open dead.letter */ - define('z', p, e); - expand("\201z/dead.letter", buf, &buf[sizeof buf - 1], e); Verbose = TRUE; - message("Saving message in %s", buf); + message("Saved message in %s", buf); Verbose = oldverb; - e->e_to = buf; - q = NULL; - (void) sendtolist(buf, &e->e_from, &q, e); - if (q != NULL && - !bitset(QBADADDR, q->q_flags) && - deliver(e, q) == 0) - state = ESM_DONE; - else - state = ESM_MAIL; - } - else - { - /* no data file -- try mailing back */ - state = ESM_MAIL; + state = ESM_DONE; + break; } + state = ESM_MAIL; break; case ESM_USRTMP: @@ -381,15 +370,19 @@ savemail(e) break; } - strcpy(buf, _PATH_VARTMP); - strcat(buf, "dead.letter"); - if (!writable(buf, NULLADDR, SFF_NOSLINK)) + if (SafeFileEnv != NULL && SafeFileEnv[0] != '\0') { state = ESM_PANIC; break; } - fp = dfopen(buf, O_WRONLY|O_CREAT|O_APPEND, FileMode); - if (fp == NULL) + + strcpy(buf, _PATH_VARTMP); + strcat(buf, "dead.letter"); + + sfflags = SFF_NOSLINK|SFF_CREAT|SFF_REGONLY|SFF_ROOTOK|SFF_OPENASROOT; + if (!writable(buf, NULL, sfflags) || + (fp = safefopen(buf, O_WRONLY|O_CREAT|O_APPEND, + FileMode, sfflags)) == NULL) { state = ESM_PANIC; break; @@ -402,13 +395,26 @@ savemail(e) mcibuf.mci_flags |= MCIF_7BIT; putfromline(&mcibuf, e); - (*e->e_puthdr)(&mcibuf, e); - putline("\n", &mcibuf); + (*e->e_puthdr)(&mcibuf, e->e_header, e); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); (void) fflush(fp); - state = ferror(fp) ? ESM_PANIC : ESM_DONE; - (void) xfclose(fp, "savemail", "/usr/tmp/dead.letter"); + if (!ferror(fp)) + { + bool oldverb = Verbose; + + Verbose = TRUE; + message("Saved message in %s", buf); + Verbose = oldverb; +#ifdef LOG + if (LogLevel > 3) + syslog(LOG_NOTICE, "Saved message in %s", buf); +#endif + state = ESM_DONE; + break; + } + state = ESM_PANIC; + (void) xfclose(fp, "savemail", buf); break; default: @@ -418,6 +424,7 @@ savemail(e) case ESM_PANIC: /* leave the locked queue & transcript files around */ + loseqfile(e, "savemail panic"); syserr("!554 savemail: cannot save rejected email anywhere"); } } @@ -441,24 +448,24 @@ savemail(e) ** mail. */ -static bool SendBody; - #define MAXRETURNS 6 /* max depth of returning messages */ #define ERRORFUDGE 100 /* nominal size of error message text */ +int returntosender(msg, returnq, sendbody, e) char *msg; ADDRESS *returnq; bool sendbody; register ENVELOPE *e; { - char buf[MAXNAME]; - extern putheader(), errbody(); register ENVELOPE *ee; ENVELOPE *oldcur = CurEnv; ENVELOPE errenvelope; static int returndepth; register ADDRESS *q; + char *p; + char buf[MAXNAME + 1]; + extern void errbody __P((MCI *, ENVELOPE *, char *)); if (returnq == NULL) return (-1); @@ -468,9 +475,14 @@ returntosender(msg, returnq, sendbody, e) if (tTd(6, 1)) { - printf("Return To Sender: msg=\"%s\", depth=%d, e=%x, returnq=", + printf("\n*** Return To Sender: msg=\"%s\", depth=%d, e=%x, returnq=", msg, returndepth, e); printaddr(returnq, TRUE); + if (tTd(6, 20)) + { + printf("Sendq="); + printaddr(e->e_sendqueue, TRUE); + } } if (++returndepth >= MAXRETURNS) @@ -482,9 +494,10 @@ returntosender(msg, returnq, sendbody, e) return (0); } - SendBody = sendbody; define('g', e->e_from.q_paddr, e); define('u', NULL, e); + + /* initialize error envelope */ ee = newenvelope(&errenvelope, e); define('a', "\201b", ee); define('r', "internal", ee); @@ -497,45 +510,97 @@ returntosender(msg, returnq, sendbody, e) ee->e_flags &= ~EF_OLDSTYLE; ee->e_sendqueue = returnq; ee->e_msgsize = ERRORFUDGE; - if (!NoReturn) + if (sendbody) ee->e_msgsize += e->e_msgsize; + else + ee->e_flags |= EF_NO_BODY_RETN; initsys(ee); for (q = returnq; q != NULL; q = q->q_next) { if (bitset(QBADADDR, q->q_flags)) continue; - if (!bitset(QDONTSEND, q->q_flags)) - ee->e_nrcpts++; - if (!DontPruneRoutes && pruneroute(q->q_paddr)) + { + register ADDRESS *p; + parseaddr(q->q_paddr, q, RF_COPYPARSE, '\0', NULL, e); + for (p = returnq; p != NULL; p = p->q_next) + { + if (p != q && sameaddr(p, q)) + q->q_flags |= QDONTSEND; + } + } + + if (!bitset(QDONTSEND, q->q_flags)) + ee->e_nrcpts++; if (q->q_alias == NULL) - addheader("To", q->q_paddr, ee); + addheader("To", q->q_paddr, &ee->e_header); } # ifdef LOG if (LogLevel > 5) - syslog(LOG_INFO, "%s: %s: return to sender: %s", - e->e_id, ee->e_id, msg); + { + if (bitset(EF_RESPONSE|EF_WARNING, e->e_flags)) + p = "return to sender"; + else + p = "postmaster notify"; + syslog(LOG_INFO, "%s: %s: %s: %s", + e->e_id, ee->e_id, p, shortenstring(msg, 203)); + } # endif - (void) sprintf(buf, "Returned mail: %.*s", sizeof buf - 20, msg); - addheader("Subject", buf, ee); if (SendMIMEErrors) { - addheader("MIME-Version", "1.0", ee); - (void) sprintf(buf, "%s.%ld/%s", + addheader("MIME-Version", "1.0", &ee->e_header); + + (void) sprintf(buf, "%s.%ld/%.100s", ee->e_id, curtime(), MyHostName); ee->e_msgboundary = newstr(buf); - (void) sprintf(buf, "multipart/mixed; boundary=\"%s\"", - ee->e_msgboundary); - addheader("Content-Type", buf, ee); + (void) sprintf(buf, +#if DSN + "multipart/report; report-type=delivery-status;\n\tboundary=\"%s\"", +#else + "multipart/mixed; boundary=\"%s\"", +#endif + ee->e_msgboundary); + addheader("Content-Type", buf, &ee->e_header); + + p = hvalue("Content-Transfer-Encoding", e->e_header); + if (p != NULL && strcasecmp(p, "binary") != 0) + p = NULL; + if (p == NULL && bitset(EF_HAS8BIT, e->e_flags)) + p = "8bit"; + if (p != NULL) + addheader("Content-Transfer-Encoding", p, &ee->e_header); + } + if (strncmp(msg, "Warning:", 8) == 0) + { + addheader("Subject", msg, &ee->e_header); + p = "warning-timeout"; + } + else if (strncmp(msg, "Postmaster warning:", 19) == 0) + { + addheader("Subject", msg, &ee->e_header); + p = "postmaster-warning"; + } + else if (strcmp(msg, "Return receipt") == 0) + { + addheader("Subject", msg, &ee->e_header); + p = "return-receipt"; + } + else + { + sprintf(buf, "Returned mail: %.*s", sizeof buf - 20, msg); + addheader("Subject", buf, &ee->e_header); + p = "failure"; } + (void) sprintf(buf, "auto-generated (%s)", p); + addheader("Auto-Submitted", buf, &ee->e_header); /* fake up an address header for the from person */ - expand("\201n", buf, &buf[sizeof buf - 1], e); + expand("\201n", buf, sizeof buf, e); if (parseaddr(buf, &ee->e_from, RF_COPYALL|RF_SENDERADDR, '\0', NULL, e) == NULL) { syserr("553 Can't parse myself!"); @@ -562,8 +627,15 @@ returntosender(msg, returnq, sendbody, e) CurEnv = oldcur; returndepth--; - /* should check for delivery errors here */ - return (0); + /* check for delivery errors */ + if (ee->e_parent == NULL || !bitset(EF_RESPONSE, ee->e_parent->e_flags)) + return 0; + for (q = ee->e_sendqueue; q != NULL; q = q->q_next) + { + if (bitset(QSENT, q->q_flags)) + return 0; + } + return -1; } /* ** ERRBODY -- output the body of an error message. @@ -574,6 +646,8 @@ returntosender(msg, returnq, sendbody, e) ** Parameters: ** mci -- the mailer connection information. ** e -- the envelope we are working in. +** separator -- any possible MIME separator. +** flags -- to modify the behaviour. ** ** Returns: ** none @@ -582,16 +656,25 @@ returntosender(msg, returnq, sendbody, e) ** Outputs the body of an error message. */ -errbody(mci, e) +void +errbody(mci, e, separator) register MCI *mci; register ENVELOPE *e; + char *separator; { register FILE *xfile; char *p; register ADDRESS *q; bool printheader; + bool sendbody; char buf[MAXLINE]; + extern char *xuntextify(); + if (bitset(MCIF_INHEADER, mci->mci_flags)) + { + putline("", mci); + mci->mci_flags &= ~MCIF_INHEADER; + } if (e->e_parent == NULL) { syserr("errbody: null parent"); @@ -635,7 +718,7 @@ errbody(mci, e) sprintf(buf, "The original message was received at %s", arpadate(ctime(&e->e_parent->e_ctime))); putline(buf, mci); - expand("from \201_", buf, &buf[sizeof buf - 1], e->e_parent); + expand("from \201_", buf, sizeof buf, e->e_parent); putline(buf, mci); putline("", mci); @@ -643,7 +726,7 @@ errbody(mci, e) ** Output error message header (if specified and available). */ - if (ErrMsgFile != NULL) + if (ErrMsgFile != NULL && !bitset(EF_SENDRECEIPT, e->e_parent->e_flags)) { if (*ErrMsgFile == '/') { @@ -652,7 +735,7 @@ errbody(mci, e) { while (fgets(buf, sizeof buf, xfile) != NULL) { - expand(buf, buf, &buf[sizeof buf - 1], e); + expand(buf, buf, sizeof buf, e); putline(buf, mci); } (void) fclose(xfile); @@ -661,7 +744,7 @@ errbody(mci, e) } else { - expand(ErrMsgFile, buf, &buf[sizeof buf - 1], e); + expand(ErrMsgFile, buf, sizeof buf, e); putline(buf, mci); putline("", mci); } @@ -674,27 +757,46 @@ errbody(mci, e) printheader = TRUE; for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) { - if (bitset(QBADADDR|QREPORT, q->q_flags)) + if (bitset(QBADADDR, q->q_flags)) { - if (printheader) - { - putline(" ----- The following addresses had delivery problems -----", - mci); - printheader = FALSE; - } - strcpy(buf, q->q_paddr); - if (bitset(QBADADDR, q->q_flags)) - strcat(buf, " (unrecoverable error)"); + if (!bitset(QPINGONFAILURE, q->q_flags)) + continue; + p = "unrecoverable error"; + } + else if (!bitset(QPRIMARY, q->q_flags)) + continue; + else if (bitset(QDELAYED, q->q_flags)) + p = "transient failure"; + else if (!bitset(QPINGONSUCCESS, q->q_flags)) + continue; + else if (bitset(QRELAYED, q->q_flags)) + p = "relayed to non-DSN-aware mailer"; + else if (bitset(QDELIVERED, q->q_flags)) + { + if (bitset(QEXPANDED, q->q_flags)) + p = "successfully delivered to mailing list"; else - strcat(buf, " (transient failure)"); + p = "successfully delivered to mailbox"; + } + else if (bitset(QEXPANDED, q->q_flags)) + p = "expanded by alias"; + else + continue; + + if (printheader) + { + putline(" ----- The following addresses have delivery notifications -----", + mci); + printheader = FALSE; + } + + sprintf(buf, "%s (%s)", shortenstring(q->q_paddr, 203), p); + putline(buf, mci); + if (q->q_alias != NULL) + { + sprintf(buf, " (expanded from: %s)", + shortenstring(q->q_alias->q_paddr, 203)); putline(buf, mci); - if (q->q_alias != NULL) - { - strcpy(buf, " (expanded from: "); - strcat(buf, q->q_alias->q_paddr); - strcat(buf, ")"); - putline(buf, mci); - } } } if (!printheader) @@ -713,46 +815,256 @@ errbody(mci, e) } else { - putline(" ----- Transcript of session follows -----\n", mci); + printheader = TRUE; if (e->e_xfp != NULL) (void) fflush(e->e_xfp); while (fgets(buf, sizeof buf, xfile) != NULL) + { + if (printheader) + putline(" ----- Transcript of session follows -----\n", mci); + printheader = FALSE; putline(buf, mci); + } (void) xfclose(xfile, "errbody xscript", p); } errno = 0; +#if DSN + /* + ** Output machine-readable version. + */ + + if (e->e_msgboundary != NULL) + { + putline("", mci); + (void) sprintf(buf, "--%s", e->e_msgboundary); + putline(buf, mci); + putline("Content-Type: message/delivery-status", mci); + putline("", mci); + + /* + ** Output per-message information. + */ + + /* original envelope id from MAIL FROM: line */ + if (e->e_parent->e_envid != NULL) + { + (void) sprintf(buf, "Original-Envelope-Id: %.800s", + xuntextify(e->e_parent->e_envid)); + putline(buf, mci); + } + + /* Reporting-MTA: is us (required) */ + (void) sprintf(buf, "Reporting-MTA: dns; %.800s", MyHostName); + putline(buf, mci); + + /* DSN-Gateway: not relevant since we are not translating */ + + /* Received-From-MTA: shows where we got this message from */ + if (RealHostName != NULL) + { + /* XXX use $s for type? */ + if (e->e_parent->e_from.q_mailer == NULL || + (p = e->e_parent->e_from.q_mailer->m_mtatype) == NULL) + p = "dns"; + (void) sprintf(buf, "Received-From-MTA: %s; %.800s", + p, RealHostName); + putline(buf, mci); + } + + /* Arrival-Date: -- when it arrived here */ + (void) sprintf(buf, "Arrival-Date: %s", + arpadate(ctime(&e->e_parent->e_ctime))); + putline(buf, mci); + + /* + ** Output per-address information. + */ + + for (q = e->e_parent->e_sendqueue; q != NULL; q = q->q_next) + { + register ADDRESS *r; + char *action; + + if (bitset(QBADADDR, q->q_flags)) + action = "failed"; + else if (!bitset(QPRIMARY, q->q_flags)) + continue; + else if (bitset(QDELIVERED, q->q_flags)) + { + if (bitset(QEXPANDED, q->q_flags)) + action = "delivered (to mailing list)"; + else + action = "delivered (to mailbox)"; + } + else if (bitset(QRELAYED, q->q_flags)) + action = "relayed (to non-DSN-aware mailer)"; + else if (bitset(QEXPANDED, q->q_flags)) + action = "expanded (to multi-recipient alias)"; + else if (bitset(QDELAYED, q->q_flags)) + action = "delayed"; + else + continue; + + putline("", mci); + + /* Original-Recipient: -- passed from on high */ + if (q->q_orcpt != NULL) + { + (void) sprintf(buf, "Original-Recipient: %.800s", + q->q_orcpt); + putline(buf, mci); + } + + /* Final-Recipient: -- the name from the RCPT command */ + p = e->e_parent->e_from.q_mailer->m_addrtype; + if (p == NULL) + p = "rfc822"; + for (r = q; r->q_alias != NULL; r = r->q_alias) + continue; + if (strchr(r->q_user, '@') == NULL) + { + (void) sprintf(buf, "Final-Recipient: %s; %.700s@%.100s", + p, r->q_user, MyHostName); + } + else + { + (void) sprintf(buf, "Final-Recipient: %s; %.800s", + p, r->q_user); + } + putline(buf, mci); + + /* X-Actual-Recipient: -- the real problem address */ + if (r != q && q->q_user[0] != '\0') + { + if (strchr(q->q_user, '@') == NULL) + { + (void) sprintf(buf, "X-Actual-Recipient: %s; %.700s@%.100s", + p, q->q_user, MyHostName); + } + else + { + (void) sprintf(buf, "X-Actual-Recipient: %s; %.800s", + p, q->q_user); + } + putline(buf, mci); + } + + /* Action: -- what happened? */ + sprintf(buf, "Action: %s", action); + putline(buf, mci); + + /* Status: -- what _really_ happened? */ + strcpy(buf, "Status: "); + if (q->q_status != NULL) + strcat(buf, q->q_status); + else if (bitset(QBADADDR, q->q_flags)) + strcat(buf, "5.0.0"); + else if (bitset(QQUEUEUP, q->q_flags)) + strcat(buf, "4.0.0"); + else + strcat(buf, "2.0.0"); + putline(buf, mci); + + /* Remote-MTA: -- who was I talking to? */ + if (q->q_statmta != NULL) + { + if (q->q_mailer == NULL || + (p = q->q_mailer->m_mtatype) == NULL) + p = "dns"; + (void) sprintf(buf, "Remote-MTA: %s; %.800s", + p, q->q_statmta); + p = &buf[strlen(buf) - 1]; + if (*p == '.') + *p = '\0'; + putline(buf, mci); + } + + /* Diagnostic-Code: -- actual result from other end */ + if (q->q_rstatus != NULL) + { + p = q->q_mailer->m_diagtype; + if (p == NULL) + p = "smtp"; + (void) sprintf(buf, "Diagnostic-Code: %s; %.800s", + p, q->q_rstatus); + putline(buf, mci); + } + + /* Last-Attempt-Date: -- fine granularity */ + if (q->q_statdate == (time_t) 0L) + q->q_statdate = curtime(); + (void) sprintf(buf, "Last-Attempt-Date: %s", + arpadate(ctime(&q->q_statdate))); + putline(buf, mci); + + /* Will-Retry-Until: -- for delayed messages only */ + if (bitset(QQUEUEUP, q->q_flags) && + !bitset(QBADADDR, q->q_flags)) + { + time_t xdate; + + xdate = e->e_parent->e_ctime + + TimeOuts.to_q_return[e->e_parent->e_timeoutclass]; + sprintf(buf, "Will-Retry-Until: %s", + arpadate(ctime(&xdate))); + putline(buf, mci); + } + } + } +#endif + /* ** Output text of original message */ - if (NoReturn) - SendBody = FALSE; putline("", mci); - if (e->e_parent->e_df != NULL) + if (bitset(EF_HAS_DF, e->e_parent->e_flags)) { - if (SendBody) - putline(" ----- Original message follows -----\n", mci); - else - putline(" ----- Message header follows -----\n", mci); - (void) fflush(mci->mci_out); + sendbody = !bitset(EF_NO_BODY_RETN, e->e_parent->e_flags) && + !bitset(EF_NO_BODY_RETN, e->e_flags); - if (e->e_msgboundary != NULL) + if (e->e_msgboundary == NULL) + { + if (sendbody) + putline(" ----- Original message follows -----\n", mci); + else + putline(" ----- Message header follows -----\n", mci); + (void) fflush(mci->mci_out); + } + else { - putline("", mci); (void) sprintf(buf, "--%s", e->e_msgboundary); + putline(buf, mci); - putline("Content-Type: message/rfc822", mci); - putline("", mci); + (void) sprintf(buf, "Content-Type: %s", + sendbody ? "message/rfc822" + : "text/rfc822-headers"); + putline(buf, mci); + + p = hvalue("Content-Transfer-Encoding", e->e_parent->e_header); + if (p != NULL && strcasecmp(p, "binary") != 0) + p = NULL; + if (p == NULL && bitset(EF_HAS8BIT, e->e_parent->e_flags)) + p = "8bit"; + if (p != NULL) + { + (void) sprintf(buf, "Content-Transfer-Encoding: %s", + p); + putline(buf, mci); + } } - putheader(mci, e->e_parent); putline("", mci); - if (SendBody) + putheader(mci, e->e_parent->e_header, e->e_parent); + if (sendbody) putbody(mci, e->e_parent, e->e_msgboundary); - else + else if (e->e_msgboundary == NULL) + { + putline("", mci); putline(" ----- Message body suppressed -----", mci); + } } - else + else if (e->e_msgboundary == NULL) { putline(" ----- No message was collected -----\n", mci); } @@ -773,8 +1085,250 @@ errbody(mci, e) syserr("errbody: I/O error"); } /* -** PRUNEROUTE -- prune an RFC-822 source route +** SMTPTODSN -- convert SMTP to DSN status code ** +** Parameters: +** smtpstat -- the smtp status code (e.g., 550). +** +** Returns: +** The DSN version of the status code. +*/ + +char * +smtptodsn(smtpstat) + int smtpstat; +{ + if (smtpstat < 0) + return "4.4.2"; + + switch (smtpstat) + { + case 450: /* Req mail action not taken: mailbox unavailable */ + return "4.2.0"; + + case 451: /* Req action aborted: local error in processing */ + return "4.3.0"; + + case 452: /* Req action not taken: insufficient sys storage */ + return "4.3.1"; + + case 500: /* Syntax error, command unrecognized */ + return "5.5.2"; + + case 501: /* Syntax error in parameters or arguments */ + return "5.5.4"; + + case 502: /* Command not implemented */ + return "5.5.1"; + + case 503: /* Bad sequence of commands */ + return "5.5.1"; + + case 504: /* Command parameter not implemented */ + return "5.5.4"; + + case 550: /* Req mail action not taken: mailbox unavailable */ + return "5.2.0"; + + case 551: /* User not local; please try <...> */ + return "5.1.6"; + + case 552: /* Req mail action aborted: exceeded storage alloc */ + return "5.2.2"; + + case 553: /* Req action not taken: mailbox name not allowed */ + return "5.1.3"; + + case 554: /* Transaction failed */ + return "5.0.0"; + } + + if ((smtpstat / 100) == 2) + return "2.0.0"; + if ((smtpstat / 100) == 4) + return "4.0.0"; + return "5.0.0"; +} +/* +** XTEXTIFY -- take regular text and turn it into DSN-style xtext +** +** Parameters: +** t -- the text to convert. +** +** Returns: +** The xtext-ified version of the same string. +*/ + +char * +xtextify(t) + register char *t; +{ + register char *p; + int l; + int nbogus; + static char *bp = NULL; + static int bplen = 0; + + /* figure out how long this xtext will have to be */ + nbogus = l = 0; + for (p = t; *p != '\0'; p++) + { + register int c = (*p & 0xff); + + /* ASCII dependence here -- this is the way the spec words it */ + if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(') + nbogus++; + l++; + } + if (nbogus == 0) + return t; + l += nbogus * 2 + 1; + + /* now allocate space if necessary for the new string */ + if (l > bplen) + { + if (bp != NULL) + free(bp); + bp = xalloc(l); + bplen = l; + } + + /* ok, copy the text with byte expansion */ + for (p = bp; *t != '\0'; ) + { + register int c = (*t++ & 0xff); + + /* ASCII dependence here -- this is the way the spec words it */ + if (c < '!' || c > '~' || c == '+' || c == '\\' || c == '(') + { + *p++ = '+'; + *p++ = "0123456789abcdef"[c >> 4]; + *p++ = "0123456789abcdef"[c & 0xf]; + } + else + *p++ = c; + } + *p = '\0'; + return bp; +} +/* +** XUNTEXTIFY -- take xtext and turn it into plain text +** +** Parameters: +** t -- the xtextified text. +** +** Returns: +** The decoded text. No attempt is made to deal with +** null strings in the resulting text. +*/ + +char * +xuntextify(t) + register char *t; +{ + register char *p; + int l; + static char *bp = NULL; + static int bplen = 0; + + /* heuristic -- if no plus sign, just return the input */ + if (strchr(t, '+') == NULL) + return t; + + /* xtext is always longer than decoded text */ + l = strlen(t); + if (l > bplen) + { + if (bp != NULL) + free(bp); + bp = xalloc(l); + bplen = l; + } + + /* ok, copy the text with byte compression */ + for (p = bp; *t != '\0'; t++) + { + register int c = *t & 0xff; + + if (c != '+') + { + *p++ = c; + continue; + } + + c = *++t & 0xff; + if (!isascii(c) || !isxdigit(c)) + { + /* error -- first digit is not hex */ + usrerr("bogus xtext: +%c", c); + t--; + continue; + } + if (isdigit(c)) + c -= '0'; + else if (isupper(c)) + c -= 'A' - 10; + else + c -= 'a' - 10; + *p = c << 4; + + c = *++t & 0xff; + if (!isascii(c) || !isxdigit(c)) + { + /* error -- second digit is not hex */ + usrerr("bogus xtext: +%x%c", *p >> 4, c); + t--; + continue; + } + if (isdigit(c)) + c -= '0'; + else if (isupper(c)) + c -= 'A' - 10; + else + c -= 'a' - 10; + *p++ |= c; + } + return bp; +} +/* +** XTEXTOK -- check if a string is legal xtext +** +** Xtext is used in Delivery Status Notifications. The spec was +** taken from draft-ietf-notary-mime-delivery-04.txt. +** +** Parameters: +** s -- the string to check. +** +** Returns: +** TRUE -- if 's' is legal xtext. +** FALSE -- if it has any illegal characters in it. +*/ + +bool +xtextok(s) + char *s; +{ + int c; + + while ((c = *s++) != '\0') + { + if (c == '+') + { + c = *s++; + if (!isascii(c) || !isxdigit(c)) + return FALSE; + c = *s++; + if (!isascii(c) || !isxdigit(c)) + return FALSE; + } + else if (c < '!' || c > '~' || c == '=') + return FALSE; + } + return TRUE; +} +/* +** PRUNEROUTE -- prune an RFC-822 source route +** ** Trims down a source route to the last internet-registered hop. ** This is encouraged by RFC 1123 section 5.3.3. ** @@ -789,6 +1343,7 @@ errbody(mci, e) ** modifies addr in-place */ +bool pruneroute(addr) char *addr; { diff --git a/usr.sbin/sendmail/src/sendmail.8 b/usr.sbin/sendmail/src/sendmail.8 index f03d3de..5b48ffc 100644 --- a/usr.sbin/sendmail/src/sendmail.8 +++ b/usr.sbin/sendmail/src/sendmail.8 @@ -29,9 +29,9 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" @(#)sendmail.8 8.4 (Berkeley) 12/11/93 +.\" @(#)sendmail.8 8.6 (Berkeley) 5/27/95 .\" -.Dd December 11, 1993 +.Dd May 27, 1995 .Dt SENDMAIL 8 .Os BSD 4 .Sh NAME @@ -209,6 +209,18 @@ is specified, will run in background. This option can be used safely with .Fl bd . +.It Fl qI Ns Ar substr +Limit processed jobs to those containing +.Ar substr +as a substring of the queue id. +.It Fl qR Ns Ar substr +Limit processed jobs to those containing +.Ar substr +as a substring of one of the recipients. +.It Fl qS Ns Ar substr +Limit processed jobs to those containing +.Ar substr +as a substring of the sender. .It Fl r Ns Ar name An alternate and obsolete form of the .Fl f @@ -259,6 +271,7 @@ successful deliveries (default 10). This avoids excessive duplicate deliveries when sending to long mailing lists interrupted by system crashes. +.ne 1i .It Li d Ns Ar x Set the delivery mode to .Ar x . diff --git a/usr.sbin/sendmail/src/sendmail.h b/usr.sbin/sendmail/src/sendmail.h index e61ebfb..66c7576 100644 --- a/usr.sbin/sendmail/src/sendmail.h +++ b/usr.sbin/sendmail/src/sendmail.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.43.1.3 (Berkeley) 3/5/95 + * @(#)sendmail.h 8.159 (Berkeley) 11/18/95 */ /* @@ -41,7 +41,7 @@ # ifdef _DEFINE # define EXTERN # ifndef lint -static char SmailSccsId[] = "@(#)sendmail.h 8.43.1.3 3/5/95"; +static char SmailSccsId[] = "@(#)sendmail.h 8.159 11/18/95"; # endif # else /* _DEFINE */ # define EXTERN extern @@ -53,10 +53,13 @@ static char SmailSccsId[] = "@(#)sendmail.h 8.43.1.3 3/5/95"; # include <stdio.h> # include <ctype.h> # include <setjmp.h> -# include <sysexits.h> # include <string.h> # include <time.h> # include <errno.h> +# ifdef EX_OK +# undef EX_OK /* for SVr4.2 SMP */ +# endif +# include <sysexits.h> # include "conf.h" # include "useful.h" @@ -68,38 +71,42 @@ static char SmailSccsId[] = "@(#)sendmail.h 8.43.1.3 3/5/95"; # ifdef DAEMON # include <sys/socket.h> # endif -# ifdef NETUNIX +# if NETUNIX # include <sys/un.h> # endif -# ifdef NETINET +# if NETINET # include <netinet/in.h> # endif -# ifdef NETISO +# if NETISO # include <netiso/iso.h> # endif -# ifdef NETNS +# if NETNS # include <netns/ns.h> # endif -# ifdef NETX25 +# if NETX25 # include <netccitt/x25.h> # endif +/* forward references for prototypes */ +typedef struct envelope ENVELOPE; +typedef struct mailer MAILER; + /* ** Data structure for bit maps. ** ** Each bit in this map can be referenced by an ascii character. -** This is 128 possible bits, or 12 8-bit bytes. +** This is 256 possible bits, or 32 8-bit bytes. */ -#define BITMAPBYTES 16 /* number of bytes in a bit map */ +#define BITMAPBYTES 32 /* number of bytes in a bit map */ #define BYTEBITS 8 /* number of bits in a byte */ /* internal macros */ -#define _BITWORD(bit) (bit / (BYTEBITS * sizeof (int))) -#define _BITBIT(bit) (1 << (bit % (BYTEBITS * sizeof (int)))) +#define _BITWORD(bit) ((bit) / (BYTEBITS * sizeof (int))) +#define _BITBIT(bit) (1 << ((bit) % (BYTEBITS * sizeof (int)))) typedef int BITMAP[BITMAPBYTES / sizeof (int)]; @@ -126,7 +133,7 @@ struct address char *q_ruser; /* real user name, or NULL if q_user */ char *q_host; /* host name */ struct mailer *q_mailer; /* mailer to use */ - u_short q_flags; /* status flags, see below */ + u_long q_flags; /* status flags, see below */ uid_t q_uid; /* user-id of receiver (if known) */ gid_t q_gid; /* group-id of receiver (if known) */ char *q_home; /* home dir (local mailer only) */ @@ -135,25 +142,51 @@ struct address struct address *q_alias; /* address this results from */ char *q_owner; /* owner of q_alias */ struct address *q_tchain; /* temporary use chain */ - time_t q_timeout; /* timeout for this address */ + char *q_orcpt; /* ORCPT parameter from RCPT TO: line */ + char *q_status; /* status code for DSNs */ + char *q_rstatus; /* remote status message for DSNs */ + time_t q_statdate; /* date of status messages */ + char *q_statmta; /* MTA generating q_rstatus */ + short q_specificity; /* how "specific" this address is */ }; typedef struct address ADDRESS; -# define QDONTSEND 000001 /* don't send to this address */ -# define QBADADDR 000002 /* this address is verified bad */ -# define QGOODUID 000004 /* the q_uid q_gid fields are good */ -# define QPRIMARY 000010 /* set from argv */ -# define QQUEUEUP 000020 /* queue for later transmission */ -# define QSENT 000040 /* has been successfully delivered */ -# define QNOTREMOTE 000100 /* not an address for remote forwarding */ -# define QSELFREF 000200 /* this address references itself */ -# define QVERIFIED 000400 /* verified, but not expanded */ -# define QREPORT 001000 /* report this address in return message */ -# define QBOGUSSHELL 002000 /* this entry has an invalid shell listed */ -# define QUNSAFEADDR 004000 /* address aquired through an unsafe path */ +# define QDONTSEND 0x00000001 /* don't send to this address */ +# define QBADADDR 0x00000002 /* this address is verified bad */ +# define QGOODUID 0x00000004 /* the q_uid q_gid fields are good */ +# define QPRIMARY 0x00000008 /* set from RCPT or argv */ +# define QQUEUEUP 0x00000010 /* queue for later transmission */ +# define QSENT 0x00000020 /* has been successfully delivered */ +# define QNOTREMOTE 0x00000040 /* address not for remote forwarding */ +# define QSELFREF 0x00000080 /* this address references itself */ +# define QVERIFIED 0x00000100 /* verified, but not expanded */ +# define QBOGUSSHELL 0x00000400 /* user has no valid shell listed */ +# define QUNSAFEADDR 0x00000800 /* address aquired via unsafe path */ +# define QPINGONSUCCESS 0x00001000 /* give return on successful delivery */ +# define QPINGONFAILURE 0x00002000 /* give return on failure */ +# define QPINGONDELAY 0x00004000 /* give return on message delay */ +# define QHASNOTIFY 0x00008000 /* propogate notify parameter */ +# define QRELAYED 0x00010000 /* DSN: relayed to non-DSN aware sys */ +# define QEXPANDED 0x00020000 /* DSN: undergone list expansion */ +# define QDELIVERED 0x00040000 /* DSN: successful final delivery */ +# define QDELAYED 0x00080000 /* DSN: message delayed */ +# define QTHISPASS 0x80000000 /* temp: address set this pass */ # define NULLADDR ((ADDRESS *) NULL) + +/* functions */ +extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *)); +extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, int, ENVELOPE *)); +extern char **prescan __P((char *, int, char[], int, char **, u_char *)); +extern int rewrite __P((char **, int, int, ENVELOPE *)); +extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *)); +extern ADDRESS *getctladdr __P((ADDRESS *)); +extern bool sameaddr __P((ADDRESS *, ADDRESS *)); +extern bool emptyaddr __P((ADDRESS *)); +extern void printaddr __P((ADDRESS *, bool)); +extern void cataddr __P((char **, char **, char *, int, int)); +extern int sendtolist __P((char *, ADDRESS *, ADDRESS **, int, ENVELOPE *)); /* ** Mailer definition structure. ** Every mailer known to the system is declared in this @@ -170,8 +203,12 @@ struct mailer { char *m_name; /* symbolic name of this mailer */ char *m_mailer; /* pathname of the mailer to use */ + char *m_mtatype; /* type of this MTA */ + char *m_addrtype; /* type for addresses */ + char *m_diagtype; /* type for diagnostics */ BITMAP m_flags; /* status flags, see below */ short m_mno; /* mailer number internally */ + short m_nice; /* niceness to run at (mostly for prog) */ char **m_argv; /* template argument vector */ short m_sh_rwset; /* rewrite set: sender header addresses */ short m_se_rwset; /* rewrite set: sender envelope addresses */ @@ -181,15 +218,18 @@ struct mailer long m_maxsize; /* size limit on message to this mailer */ int m_linelimit; /* max # characters per line */ char *m_execdir; /* directory to chdir to before execv */ + uid_t m_uid; /* UID to run as */ + gid_t m_gid; /* GID to run as */ + char *m_defcharset; /* default character set */ }; -typedef struct mailer MAILER; - /* bits for m_flags */ # define M_ESMTP 'a' /* run Extended SMTP protocol */ +# define M_ALIASABLE 'A' /* user can be LHS of an alias */ # define M_BLANKEND 'b' /* ensure blank line at end of message */ # define M_NOCOMMENT 'c' /* don't include comment part of address */ # define M_CANONICAL 'C' /* make addresses canonical "u@dom" */ +# define M_NOBRACKET 'd' /* never angle bracket envelope route-addrs */ /* 'D' CF: include Date: */ # define M_EXPENSIVE 'e' /* it costs to use this mailer.... */ # define M_ESCFROM 'E' /* escape From lines to >From */ @@ -198,25 +238,39 @@ typedef struct mailer MAILER; # define M_NO_NULL_FROM 'g' /* sender of errors should be $g */ # define M_HST_UPPER 'h' /* preserve host case distinction */ # define M_PREHEAD 'H' /* MAIL11V3: preview headers */ +# define M_UDBENVELOPE 'i' /* do udbsender rewriting on envelope */ # define M_INTERNAL 'I' /* SMTP to another sendmail site */ +# define M_UDBRECIPIENT 'j' /* do udbsender rewriting on recipient lines */ +# define M_NOLOOPCHECK 'k' /* don't check for loops in HELO command */ # define M_LOCALMAILER 'l' /* delivery is to this host */ # define M_LIMITS 'L' /* must enforce SMTP line limits */ # define M_MUSER 'm' /* can handle multiple users at once */ /* 'M' CF: include Message-Id: */ # define M_NHDR 'n' /* don't insert From line */ # define M_MANYSTATUS 'N' /* MAIL11V3: DATA returns multi-status */ +# define M_RUNASRCPT 'o' /* always run mailer as recipient */ # define M_FROMPATH 'p' /* use reverse-path in MAIL FROM: */ /* 'P' CF: include Return-Path: */ # define M_ROPT 'r' /* mailer takes picky -r flag */ # define M_SECURE_PORT 'R' /* try to send on a reserved TCP port */ # define M_STRIPQ 's' /* strip quote chars from user/host */ -# define M_RESTR 'S' /* must be daemon to execute */ +# define M_SPECIFIC_UID 'S' /* run as specific uid/gid */ # define M_USR_UPPER 'u' /* preserve user case distinction */ # define M_UGLYUUCP 'U' /* this wants an ugly UUCP from line */ +# define M_CONTENT_LEN 'v' /* add Content-Length: header (SVr4) */ /* 'V' UIUC: !-relativize all addresses */ +# define M_HASPWENT 'w' /* check for /etc/passwd entry */ /* 'x' CF: include Full-Name: */ # define M_XDOT 'X' /* use hidden-dot algorithm */ +# define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */ +# define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */ # define M_7BITS '7' /* use 7-bit path */ +# define M_8BITS '8' /* force "just send 8" behaviour */ +# define M_MAKE8BIT '9' /* convert 7 -> 8 bit if appropriate */ +# define M_CHECKINCLUDE ':' /* check for :include: files */ +# define M_CHECKPROG '|' /* check for |program addresses */ +# define M_CHECKFILE '/' /* check for /file addresses */ +# define M_CHECKUDB '@' /* user can be user database key */ EXTERN MAILER *Mailer[MAXMAILERS+1]; @@ -255,18 +309,21 @@ struct hdrinfo extern struct hdrinfo HdrInfo[]; /* bits for h_flags and hi_flags */ -# define H_EOH 00001 /* this field terminates header */ -# define H_RCPT 00002 /* contains recipient addresses */ -# define H_DEFAULT 00004 /* if another value is found, drop this */ -# define H_RESENT 00010 /* this address is a "Resent-..." address */ -# define H_CHECK 00020 /* check h_mflags against m_flags */ -# define H_ACHECK 00040 /* ditto, but always (not just default) */ -# define H_FORCE 00100 /* force this field, even if default */ -# define H_TRACE 00200 /* this field contains trace information */ -# define H_FROM 00400 /* this is a from-type field */ -# define H_VALID 01000 /* this field has a validated value */ -# define H_RECEIPTTO 02000 /* this field has return receipt info */ -# define H_ERRORSTO 04000 /* this field has error address info */ +# define H_EOH 0x0001 /* this field terminates header */ +# define H_RCPT 0x0002 /* contains recipient addresses */ +# define H_DEFAULT 0x0004 /* if another value is found, drop this */ +# define H_RESENT 0x0008 /* this address is a "Resent-..." address */ +# define H_CHECK 0x0010 /* check h_mflags against m_flags */ +# define H_ACHECK 0x0020 /* ditto, but always (not just default) */ +# define H_FORCE 0x0040 /* force this field, even if default */ +# define H_TRACE 0x0080 /* this field contains trace information */ +# define H_FROM 0x0100 /* this is a from-type field */ +# define H_VALID 0x0200 /* this field has a validated value */ +# define H_RECEIPTTO 0x0400 /* this field has return receipt info */ +# define H_ERRORSTO 0x0800 /* this field has error address info */ +# define H_CTE 0x1000 /* this field is a content-transfer-encoding */ +# define H_CTYPE 0x2000 /* this is a content-type field */ +# define H_BCC 0x4000 /* Bcc: header: strip value or delete */ /* ** Information about currently open connections to mailers, or to ** hosts that we have looked up recently. @@ -288,20 +345,27 @@ MCI 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 000001 /* this entry is valid */ -#define MCIF_TEMP 000002 /* don't cache this connection */ -#define MCIF_CACHED 000004 /* currently in open cache */ -#define MCIF_ESMTP 000010 /* this host speaks ESMTP */ -#define MCIF_EXPN 000020 /* EXPN command supported */ -#define MCIF_SIZE 000040 /* SIZE option supported */ -#define MCIF_8BITMIME 000100 /* BODY=8BITMIME supported */ -#define MCIF_7BIT 000200 /* strip this message to 7 bits */ -#define MCIF_MULTSTAT 000400 /* MAIL11V3: handles MULT status */ +#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 */ @@ -311,6 +375,11 @@ MCI #define MCIS_QUITING 4 /* running quit protocol */ #define MCIS_SSD 5 /* service shutting down */ #define MCIS_ERROR 6 /* I/O error on connection */ + +/* functions */ +extern MCI *mci_get __P((char *, MAILER *)); +extern void mci_cache __P((MCI *)); +extern void mci_flush __P((bool, MCI *)); /* ** Envelope structure. ** This structure defines the message itself. There is usually @@ -320,9 +389,7 @@ MCI ** will have their own envelope. */ -# define ENVELOPE struct envelope - -ENVELOPE +struct envelope { HDR *e_header; /* head of header list */ long e_msgpriority; /* adjusted priority of this message */ @@ -342,14 +409,14 @@ ENVELOPE short e_nsent; /* number of sends since checkpoint */ short e_sendmode; /* message send mode */ short e_errormode; /* error return mode */ - int (*e_puthdr)__P((MCI *, ENVELOPE *)); + short e_timeoutclass; /* message timeout class */ + void (*e_puthdr)__P((MCI *, HDR *, ENVELOPE *)); /* function to put header of message */ - int (*e_putbody)__P((MCI *, ENVELOPE *, char *)); + void (*e_putbody)__P((MCI *, ENVELOPE *, char *)); /* function to put body of message */ struct envelope *e_parent; /* the message this one encloses */ struct envelope *e_sibling; /* the next envelope of interest */ char *e_bodytype; /* type of message body */ - char *e_df; /* location of temp file */ FILE *e_dfp; /* temporary file */ char *e_id; /* code for this entry in queue */ FILE *e_xfp; /* transcript file */ @@ -358,16 +425,23 @@ ENVELOPE char *e_statmsg; /* stat msg (changes per delivery) */ char *e_msgboundary; /* MIME-style message part boundary */ char *e_origrcpt; /* original recipient (one only) */ - char *e_macro[128]; /* macro definitions */ + char *e_envid; /* envelope id from MAIL FROM: line */ + char *e_status; /* DSN status for this message */ + time_t e_dtime; /* time of last delivery attempt */ + int e_ntries; /* number of delivery attempts */ + dev_t e_dfdev; /* df file's device, for crash recov */ + ino_t e_dfino; /* df file's ino, for crash recovery */ + char *e_macro[256]; /* macro definitions */ }; /* values for e_flags */ #define EF_OLDSTYLE 0x0000001 /* use spaces (not commas) in hdrs */ #define EF_INQUEUE 0x0000002 /* this message is fully queued */ +#define EF_NO_BODY_RETN 0x0000004 /* omit message body on error */ #define EF_CLRQUEUE 0x0000008 /* disk copy is no longer needed */ #define EF_SENDRECEIPT 0x0000010 /* send a return receipt */ #define EF_FATALERRS 0x0000020 /* fatal errors occured */ -#define EF_KEEPQUEUE 0x0000040 /* keep queue files always */ +#define EF_DELETE_BCC 0x0000040 /* delete Bcc: headers entirely */ #define EF_RESPONSE 0x0000080 /* this is an error or return receipt */ #define EF_RESENT 0x0000100 /* this message is being forwarded */ #define EF_VRFYONLY 0x0000200 /* verify only (don't expand aliases) */ @@ -378,8 +452,23 @@ ENVELOPE #define EF_METOO 0x0004000 /* send to me too */ #define EF_LOGSENDER 0x0008000 /* need to log the sender */ #define EF_NORECEIPT 0x0010000 /* suppress all return-receipts */ +#define EF_HAS8BIT 0x0020000 /* at least one 8-bit char in body */ +#define EF_NL_NOT_EOL 0x0040000 /* don't accept raw NL as EOLine */ +#define EF_CRLF_NOT_EOL 0x0080000 /* don't accept CR-LF as EOLine */ +#define EF_RET_PARAM 0x0100000 /* RCPT command had RET argument */ +#define EF_HAS_DF 0x0200000 /* set when df file is instantiated */ +#define EF_IS_MIME 0x0400000 /* really is a MIME message */ +#define EF_DONT_MIME 0x0800000 /* never MIME this message */ EXTERN ENVELOPE *CurEnv; /* envelope currently being processed */ + +/* functions */ +extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *)); +extern void dropenvelope __P((ENVELOPE *)); +extern void clearenvelope __P((ENVELOPE *, bool)); + +extern void putheader __P((MCI *, HDR *, ENVELOPE *)); +extern void putbody __P((MCI *, ENVELOPE *, char *)); /* ** Message priority classes. ** @@ -434,35 +523,35 @@ EXTERN struct rewrite *RewriteRules[MAXRWSETS]; */ /* left hand side items */ -# define MATCHZANY 0220 /* match zero or more tokens */ -# define MATCHANY 0221 /* match one or more tokens */ -# define MATCHONE 0222 /* match exactly one token */ -# define MATCHCLASS 0223 /* match one token in a class */ -# define MATCHNCLASS 0224 /* match anything not in class */ -# define MATCHREPL 0225 /* replacement on RHS for above */ +# define MATCHZANY ((u_char)0220) /* match zero or more tokens */ +# define MATCHANY ((u_char)0221) /* match one or more tokens */ +# define MATCHONE ((u_char)0222) /* match exactly one token */ +# define MATCHCLASS ((u_char)0223) /* match one token in a class */ +# define MATCHNCLASS ((u_char)0224) /* match anything not in class */ +# define MATCHREPL ((u_char)0225) /* replacement on RHS for above */ /* right hand side items */ -# define CANONNET 0226 /* canonical net, next token */ -# define CANONHOST 0227 /* canonical host, next token */ -# define CANONUSER 0230 /* canonical user, next N tokens */ -# define CALLSUBR 0231 /* call another rewriting set */ +# define CANONNET ((u_char)0226) /* canonical net, next token */ +# define CANONHOST ((u_char)0227) /* canonical host, next token */ +# define CANONUSER ((u_char)0230) /* canonical user, next N tokens */ +# define CALLSUBR ((u_char)0231) /* call another rewriting set */ /* conditionals in macros */ -# define CONDIF 0232 /* conditional if-then */ -# define CONDELSE 0233 /* conditional else */ -# define CONDFI 0234 /* conditional fi */ +# define CONDIF ((u_char)0232) /* conditional if-then */ +# define CONDELSE ((u_char)0233) /* conditional else */ +# define CONDFI ((u_char)0234) /* conditional fi */ /* bracket characters for host name lookup */ -# define HOSTBEGIN 0235 /* hostname lookup begin */ -# define HOSTEND 0236 /* hostname lookup end */ +# define HOSTBEGIN ((u_char)0235) /* hostname lookup begin */ +# define HOSTEND ((u_char)0236) /* hostname lookup end */ /* bracket characters for generalized lookup */ -# define LOOKUPBEGIN 0205 /* generalized lookup begin */ -# define LOOKUPEND 0206 /* generalized lookup end */ +# define LOOKUPBEGIN ((u_char)0205) /* generalized lookup begin */ +# define LOOKUPEND ((u_char)0206) /* generalized lookup end */ /* macro substitution character */ -# define MACROEXPAND 0201 /* macro expansion */ -# define MACRODEXPAND 0202 /* deferred macro expansion */ +# define MACROEXPAND ((u_char)0201) /* macro expansion */ +# define MACRODEXPAND ((u_char)0202) /* deferred macro expansion */ /* to make the code clearer */ # define MATCHZERO CANONHOST @@ -473,6 +562,16 @@ struct metamac char metaname; /* external code (after $) */ u_char metaval; /* internal code (as above) */ }; + +/* values for macros with external names only */ +# define MID_OPMODE 0202 /* operation mode */ + +/* functions */ +extern void expand __P((char *, char *, size_t, ENVELOPE *)); +extern void define __P((int, char *, ENVELOPE *)); +extern char *macvalue __P((int, ENVELOPE *)); +extern char *macname __P((int)); +extern int macid __P((char *, char **)); /* ** Name canonification short circuit. ** @@ -505,6 +604,7 @@ NAMECANON # define MAPCLASS struct _mapclass # define MAP struct _map +# define MAXMAPACTIONS 3 /* size of map_actions array */ /* @@ -515,32 +615,47 @@ MAP { MAPCLASS *map_class; /* the class of this map */ char *map_mname; /* name of this map */ - int map_mflags; /* flags, see below */ + long map_mflags; /* flags, see below */ char *map_file; /* the (nominal) filename */ ARBPTR_T map_db1; /* the open database ptr */ ARBPTR_T map_db2; /* an "extra" database pointer */ + char *map_keycolnm; /* key column name */ + char *map_valcolnm; /* value column name */ + u_char map_keycolno; /* key column number */ + u_char map_valcolno; /* value column number */ + char map_coldelim; /* column delimiter */ char *map_app; /* to append to successful matches */ char *map_domain; /* the (nominal) NIS domain */ char *map_rebuild; /* program to run to do auto-rebuild */ time_t map_mtime; /* last database modification time */ + short map_specificity; /* specificity of alaases */ + MAP *map_stack[MAXMAPSTACK]; /* list for stacked maps */ + short map_return[MAXMAPACTIONS]; /* return bitmaps for stacked maps */ }; -/* bit values for map_flags */ -# define MF_VALID 0x0001 /* this entry is valid */ -# define MF_INCLNULL 0x0002 /* include null byte in key */ -# define MF_OPTIONAL 0x0004 /* don't complain if map not found */ -# define MF_NOFOLDCASE 0x0008 /* don't fold case in keys */ -# define MF_MATCHONLY 0x0010 /* don't use the map value */ -# define MF_OPEN 0x0020 /* this entry is open */ -# define MF_WRITABLE 0x0040 /* open for writing */ -# define MF_ALIAS 0x0080 /* this is an alias file */ -# define MF_TRY0NULL 0x0100 /* try with no null byte */ -# define MF_TRY1NULL 0x0200 /* try with the null byte */ -# define MF_LOCKED 0x0400 /* this map is currently locked */ -# define MF_ALIASWAIT 0x0800 /* alias map in aliaswait state */ -# define MF_IMPL_HASH 0x1000 /* implicit: underlying hash database */ -# define MF_IMPL_NDBM 0x2000 /* implicit: underlying NDBM database */ - +/* bit values for map_mflags */ +# define MF_VALID 0x00000001 /* this entry is valid */ +# define MF_INCLNULL 0x00000002 /* include null byte in key */ +# define MF_OPTIONAL 0x00000004 /* don't complain if map not found */ +# define MF_NOFOLDCASE 0x00000008 /* don't fold case in keys */ +# define MF_MATCHONLY 0x00000010 /* don't use the map value */ +# define MF_OPEN 0x00000020 /* this entry is open */ +# define MF_WRITABLE 0x00000040 /* open for writing */ +# define MF_ALIAS 0x00000080 /* this is an alias file */ +# define MF_TRY0NULL 0x00000100 /* try with no null byte */ +# define MF_TRY1NULL 0x00000200 /* try with the null byte */ +# define MF_LOCKED 0x00000400 /* this map is currently locked */ +# define MF_ALIASWAIT 0x00000800 /* alias map in aliaswait state */ +# define MF_IMPL_HASH 0x00001000 /* implicit: underlying hash database */ +# define MF_IMPL_NDBM 0x00002000 /* implicit: underlying NDBM database */ +# define MF_UNSAFEDB 0x00004000 /* this map is world writable */ +# define MF_APPEND 0x00008000 /* append new entry on rebuiled */ +# define MF_KEEPQUOTES 0x00010000 /* don't dequote key before lookup */ + +/* indices for map_actions */ +# define MA_NOTFOUND 0 /* member map returned "not found" */ +# define MA_UNAVAIL 1 /* member map is not available */ +# define MA_TRYAGAIN 2 /* member map returns temp failure */ /* ** The class of a map -- essentially the functions to call @@ -567,6 +682,11 @@ MAPCLASS #define MCF_ALIASOK 0x0001 /* can be used for aliases */ #define MCF_ALIASONLY 0x0002 /* usable only for aliases */ #define MCF_REBUILDABLE 0x0004 /* can rebuild alias files */ +#define MCF_OPTFILE 0x0008 /* file name is optional */ + +/* functions */ +extern char *map_rewrite __P((MAP *, char *, int, char **)); +extern MAP *makemapentry __P((char *)); /* ** Symbol table definitions */ @@ -587,6 +707,8 @@ struct symtab char *sv_hostsig; /* host signature */ MCI sv_mci; /* mailer connection info */ NAMECANON sv_namecanon; /* canonical name cache */ + int sv_macro; /* macro name => id mapping */ + int sv_ruleset; /* ruleset index */ } s_value; }; @@ -602,6 +724,8 @@ typedef struct symtab STAB; # define ST_MAP 6 /* mapping function */ # define ST_HOSTSIG 7 /* host signature */ # define ST_NAMECANON 8 /* cached canonical name */ +# define ST_MACRO 9 /* macro name to id mapping */ +# define ST_RULESET 10 /* ruleset index */ # define ST_MCI 16 /* mailer connection info (offset) */ # define s_class s_value.sv_class @@ -613,6 +737,8 @@ typedef struct symtab STAB; # define s_hostsig s_value.sv_hostsig # define s_map s_value.sv_map # define s_namecanon s_value.sv_namecanon +# define s_macro s_value.sv_macro +# define s_ruleset s_value.sv_ruleset extern STAB *stab __P((char *, int, int)); extern void stabapply __P((void (*)(STAB *, int), int)); @@ -632,7 +758,7 @@ extern void stabapply __P((void (*)(STAB *, int), int)); struct event { time_t ev_time; /* time of the function call */ - int (*ev_func)__P((int)); + void (*ev_func)__P((int)); /* function to call */ int ev_arg; /* argument to ev_func */ int ev_pid; /* pid that set this event */ @@ -642,8 +768,12 @@ struct event typedef struct event EVENT; EXTERN EVENT *EventQueue; /* head of event queue */ + +/* functions */ +extern EVENT *setevent __P((time_t, void(*)(), int)); +extern void clrevent __P((EVENT *)); /* -** Operation, send, and error modes +** Operation, send, error, and MIME modes ** ** The operation mode describes the basic operation of sendmail. ** This can be set from the command line, and is "send mail" by @@ -673,9 +803,9 @@ EXTERN char OpMode; /* operation mode, see below */ /* values for e_sendmode -- send modes */ #define SM_DELIVER 'i' /* interactive delivery */ -#define SM_QUICKD 'j' /* deliver w/o queueing */ #define SM_FORK 'b' /* deliver in background */ #define SM_QUEUE 'q' /* queue, don't deliver */ +#define SM_DEFER 'd' /* defer map lookups as well as queue */ #define SM_VERIFY 'v' /* verify only (used internally) */ /* used only as a parameter to sendall */ @@ -688,6 +818,37 @@ EXTERN char OpMode; /* operation mode, see below */ #define EM_WRITE 'w' /* write back errors */ #define EM_BERKNET 'e' /* special berknet processing */ #define EM_QUIET 'q' /* don't print messages (stat only) */ + + +/* MIME processing mode */ +EXTERN int MimeMode; + +/* bit values for MimeMode */ +#define MM_CVTMIME 0x0001 /* convert 8 to 7 bit MIME */ +#define MM_PASS8BIT 0x0002 /* just send 8 bit data blind */ +#define MM_MIME8BIT 0x0004 /* convert 8-bit data to MIME */ + +/* queue sorting order algorithm */ +EXTERN int QueueSortOrder; + +#define QS_BYPRIORITY 0 /* sort by message priority */ +#define QS_BYHOST 1 /* sort by first host name */ + + +/* how to handle messages without any recipient addresses */ +EXTERN int NoRecipientAction; + +#define NRA_NO_ACTION 0 /* just leave it as is */ +#define NRA_ADD_TO 1 /* add To: header */ +#define NRA_ADD_APPARENTLY_TO 2 /* add Apparently-To: header */ +#define NRA_ADD_BCC 3 /* add empty Bcc: header */ +#define NRA_ADD_TO_UNDISCLOSED 4 /* add To: undisclosed:; header */ + + +/* flags to putxline */ +#define PXLF_NOTHINGSPECIAL 0 /* no special mapping */ +#define PXLF_MAPFROM 0x0001 /* map From_ to >From_ */ +#define PXLF_STRIP8BIT 0x0002 /* strip 8th bit *e /* ** Additional definitions */ @@ -699,16 +860,16 @@ EXTERN char OpMode; /* operation mode, see below */ */ #define PRIV_PUBLIC 0 /* what have I got to hide? */ -#define PRIV_NEEDMAILHELO 00001 /* insist on HELO for MAIL, at least */ -#define PRIV_NEEDEXPNHELO 00002 /* insist on HELO for EXPN */ -#define PRIV_NEEDVRFYHELO 00004 /* insist on HELO for VRFY */ -#define PRIV_NOEXPN 00010 /* disallow EXPN command entirely */ -#define PRIV_NOVRFY 00020 /* disallow VRFY command entirely */ -#define PRIV_AUTHWARNINGS 00040 /* flag possible authorization probs */ -#define PRIV_NORECEIPTS 00100 /* disallow return receipts */ -#define PRIV_RESTRICTMAILQ 01000 /* restrict mailq command */ -#define PRIV_RESTRICTQRUN 02000 /* restrict queue run */ -#define PRIV_GOAWAY 00777 /* don't give no info, anyway, anyhow */ +#define PRIV_NEEDMAILHELO 0x0001 /* insist on HELO for MAIL, at least */ +#define PRIV_NEEDEXPNHELO 0x0002 /* insist on HELO for EXPN */ +#define PRIV_NEEDVRFYHELO 0x0004 /* insist on HELO for VRFY */ +#define PRIV_NOEXPN 0x0008 /* disallow EXPN command entirely */ +#define PRIV_NOVRFY 0x0010 /* disallow VRFY command entirely */ +#define PRIV_AUTHWARNINGS 0x0020 /* flag possible authorization probs */ +#define PRIV_NORECEIPTS 0x0040 /* disallow return receipts */ +#define PRIV_RESTRICTMAILQ 0x1000 /* restrict mailq command */ +#define PRIV_RESTRICTQRUN 0x2000 /* restrict queue run */ +#define PRIV_GOAWAY 0x0fff /* don't give no info, anyway, anyhow */ /* struct defining such things */ struct prival @@ -722,12 +883,12 @@ struct prival ** Flags passed to remotename, parseaddr, allocaddr, and buildaddr. */ -#define RF_SENDERADDR 0001 /* this is a sender address */ -#define RF_HEADERADDR 0002 /* this is a header address */ -#define RF_CANONICAL 0004 /* strip comment information */ -#define RF_ADDDOMAIN 0010 /* OK to do domain extension */ -#define RF_COPYPARSE 0020 /* copy parsed user & host */ -#define RF_COPYPADDR 0040 /* copy print address */ +#define RF_SENDERADDR 0x001 /* this is a sender address */ +#define RF_HEADERADDR 0x002 /* this is a header address */ +#define RF_CANONICAL 0x004 /* strip comment information */ +#define RF_ADDDOMAIN 0x008 /* OK to do domain extension */ +#define RF_COPYPARSE 0x010 /* copy parsed user & host */ +#define RF_COPYPADDR 0x020 /* copy print address */ #define RF_COPYALL (RF_COPYPARSE|RF_COPYPADDR) #define RF_COPYNONE 0 @@ -740,6 +901,23 @@ struct prival #define SFF_MUSTOWN 0x0001 /* user must own this file */ #define SFF_NOSLINK 0x0002 /* file cannot be a symbolic link */ #define SFF_ROOTOK 0x0004 /* ok for root to own this file */ +#define SFF_RUNASREALUID 0x0008 /* if no ctladdr, run as real uid */ +#define SFF_NOPATHCHECK 0x0010 /* don't bother checking dir path */ +#define SFF_SETUIDOK 0x0020 /* setuid files are ok */ +#define SFF_CREAT 0x0040 /* ok to create file if necessary */ +#define SFF_REGONLY 0x0080 /* regular files only */ + +/* flags that are actually specific to safefopen */ +#define SFF_OPENASROOT 0x1000 /* open as root instead of real user */ + + +/* +** Flags passed to mime8to7. +*/ + +#define M87F_OUTER 0 /* outer context */ +#define M87F_NO8BIT 0x0001 /* can't have 8-bit in this section */ +#define M87F_DIGEST 0x0002 /* processing multipart/digest */ /* @@ -747,27 +925,56 @@ struct prival ** we are forced to declare a supertype here. */ +#ifdef DAEMON union bigsockaddr { struct sockaddr sa; /* general version */ -#ifdef NETUNIX +#if NETUNIX struct sockaddr_un sunix; /* UNIX family */ #endif -#ifdef NETINET +#if NETINET struct sockaddr_in sin; /* INET family */ #endif -#ifdef NETISO +#if NETISO struct sockaddr_iso siso; /* ISO family */ #endif -#ifdef NETNS +#if NETNS struct sockaddr_ns sns; /* XNS family */ #endif -#ifdef NETX25 +#if NETX25 struct sockaddr_x25 sx25; /* X.25 family */ #endif }; #define SOCKADDR union bigsockaddr + +EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */ +extern char *anynet_ntoa __P((SOCKADDR *)); + +#endif + + +/* +** Vendor codes +** +** Vendors can customize sendmail to add special behaviour, +** generally for back compatibility. Ideally, this should +** be set up in the .cf file using the "V" command. However, +** it's quite reasonable for some vendors to want the default +** be their old version; this can be set using +** -DVENDOR_DEFAULT=VENDOR_xxx +** in the Makefile. +** +** Vendors should apply to sendmail@CS.Berkeley.EDU for +** unique vendor codes. +*/ + +#define VENDOR_BERKELEY 1 /* Berkeley-native configuration file */ +#define VENDOR_SUN 2 /* Sun-native configuration file */ +#define VENDOR_HP 3 /* Hewlett-Packard specific config syntax */ +#define VENDOR_IBM 4 /* IBM specific config syntax */ + +EXTERN int VendorCode; /* vendor-specific operation enhancements */ /* ** Global variables. */ @@ -778,7 +985,6 @@ EXTERN bool IgnrDot; /* don't let dot end messages */ EXTERN bool SaveFrom; /* save leading "From" lines */ EXTERN bool Verbose; /* set if blow-by-blow desired */ EXTERN bool GrabTo; /* if set, get recipients from msg */ -EXTERN bool NoReturn; /* don't return letter to sender */ EXTERN bool SuprErrs; /* set if we are suppressing errors */ EXTERN bool HoldErrs; /* only output errors to transcript */ EXTERN bool NoConnect; /* don't connect to non-local mailers */ @@ -787,20 +993,22 @@ EXTERN bool ForkQueueRuns; /* fork for each job when running the queue */ EXTERN bool AutoRebuild; /* auto-rebuild the alias database as needed */ EXTERN bool CheckAliases; /* parse addresses during newaliases */ EXTERN bool NoAlias; /* suppress aliasing */ -EXTERN bool UseNameServer; /* use internet domain name server */ -EXTERN bool SevenBit; /* force 7-bit data */ +EXTERN bool UseNameServer; /* using DNS -- interpret h_errno & MX RRs */ +EXTERN bool UseHesiod; /* using Hesiod -- interpret Hesiod errors */ +EXTERN bool SevenBitInput; /* force 7-bit data on input */ +EXTERN bool HasEightBits; /* has at least one eight bit input byte */ EXTERN time_t SafeAlias; /* interval to wait until @:@ in alias file */ EXTERN FILE *InChannel; /* input connection */ EXTERN FILE *OutChannel; /* output connection */ -EXTERN uid_t RealUid; /* when Daemon, real uid of caller */ -EXTERN gid_t RealGid; /* when Daemon, real gid of caller */ +EXTERN char *RealUserName; /* real user name of caller */ +EXTERN uid_t RealUid; /* real uid of caller */ +EXTERN gid_t RealGid; /* real gid of caller */ EXTERN uid_t DefUid; /* default uid to run as */ EXTERN gid_t DefGid; /* default gid to run as */ EXTERN char *DefUser; /* default user to run as (from DefUid) */ EXTERN int OldUmask; /* umask when sendmail starts up */ EXTERN int Errors; /* set if errors (local to single pass) */ EXTERN int ExitStat; /* exit status code */ -EXTERN int AliasLevel; /* depth of aliasing */ EXTERN int LineNumber; /* line number in current input */ EXTERN int LogLevel; /* level of logging to perform */ EXTERN int FileMode; /* mode on files */ @@ -817,7 +1025,6 @@ EXTERN char *FileName; /* name to print on error messages */ EXTERN char *SmtpPhase; /* current phase in SMTP processing */ EXTERN char *MyHostName; /* name of this host for SMTP messages */ EXTERN char *RealHostName; /* name of host we are talking to */ -EXTERN SOCKADDR RealHostAddr; /* address of host we are talking to */ EXTERN char *CurHostName; /* current host we are dealing with */ EXTERN jmp_buf TopFrame; /* branch-to-top-of-loop-on-error frame */ EXTERN bool QuickAbort; /* .... but only if we want a quick abort */ @@ -826,9 +1033,10 @@ EXTERN bool SendMIMEErrors; /* send error messages in MIME format */ EXTERN bool MatchGecos; /* look for user names in gecos field */ EXTERN bool UseErrorsTo; /* use Errors-To: header (back compat) */ EXTERN bool TryNullMXList; /* if we are the best MX, try host directly */ -extern bool CheckLoopBack; /* check for loopback on HELO packet */ EXTERN bool InChild; /* true if running in an SMTP subprocess */ EXTERN bool DisConnected; /* running with OutChannel redirected to xf */ +EXTERN bool ColonOkInAddr; /* single colon legal in address */ +EXTERN bool HasWildcardMX; /* don't use MX records when canonifying */ EXTERN char SpaceSub; /* substitution for <lwsp> */ EXTERN int PrivacyFlags; /* privacy flags */ EXTERN char *ConfFile; /* location of configuration file [conf.c] */ @@ -845,16 +1053,38 @@ EXTERN char *ForwardPath; /* path to search for .forward files */ EXTERN long MinBlocksFree; /* min # of blocks free on queue fs */ EXTERN char *FallBackMX; /* fall back MX host */ EXTERN long MaxMessageSize; /* advertised max size we will accept */ +EXTERN time_t MaxHostStatAge; /* max age of cached host status info */ +EXTERN time_t MinQueueAge; /* min delivery interval */ +EXTERN time_t DialDelay; /* delay between dial-on-demand tries */ +EXTERN char *SafeFileEnv; /* chroot location for file delivery */ +EXTERN char *HostsFile; /* path to /etc/hosts file */ +EXTERN int MaxQueueRun; /* maximum number of jobs in one queue run */ +EXTERN int MaxChildren; /* maximum number of daemonic children */ +EXTERN int CurChildren; /* current number of daemonic children */ +EXTERN char *SmtpGreeting; /* SMTP greeting message (old $e macro) */ +EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */ +EXTERN char *OperatorChars; /* operators (old $o macro) */ +EXTERN bool DontInitGroups; /* avoid initgroups() because of NIS cost */ +EXTERN bool SingleLineFromHeader; /* force From: header to be one line */ +EXTERN int MaxAliasRecursion; /* maximum depth of alias recursion */ +EXTERN int MaxRuleRecursion; /* maximum depth of ruleset recursion */ +EXTERN char *MustQuoteChars; /* quote these characters in phrases */ +EXTERN char *ServiceSwitchFile; /* backup service switch */ +EXTERN char *DefaultCharSet; /* default character set for MIME */ +EXTERN int DeliveryNiceness; /* how nice to be during delivery */ EXTERN char *PostMasterCopy; /* address to get errs cc's */ EXTERN int CheckpointInterval; /* queue file checkpoint interval */ EXTERN bool DontPruneRoutes; /* don't prune source routes */ -extern bool BrokenSmtpPeers; /* peers can't handle 2-line greeting */ +EXTERN bool DontExpandCnames; /* do not $[...$] expand CNAMEs */ EXTERN int MaxMciCache; /* maximum entries in MCI cache */ EXTERN time_t MciCacheTimeout; /* maximum idle time on connections */ +EXTERN time_t MciInfoTimeout; /* how long 'til we retry down hosts */ EXTERN char *QueueLimitRecipient; /* limit queue runs to this recipient */ EXTERN char *QueueLimitSender; /* limit queue runs to this sender */ EXTERN char *QueueLimitId; /* limit queue runs to this id */ EXTERN FILE *TrafficLogFile; /* file in which to log all traffic */ +EXTERN char *UserEnviron[MAXUSERENVIRON + 1]; + /* saved user environment */ extern int errno; @@ -875,16 +1105,23 @@ 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_rset; /* RSET command */ time_t to_helo; /* HELO command */ time_t to_quit; /* QUIT command */ time_t to_miscshort; /* misc short commands (NOOP, VERB, etc) */ time_t to_ident; /* IDENT protocol requests */ + time_t to_fileopen; /* opening :include: and .forward files */ /* following are per message */ - time_t to_q_return; /* queue return timeout */ - time_t to_q_warning; /* queue warning timeout */ + time_t to_q_return[MAXTOCLASS]; /* queue return timeouts */ + time_t to_q_warning[MAXTOCLASS]; /* queue warning timeouts */ } TimeOuts; +/* timeout classes for return and warning timeouts */ +# define TOC_NORMAL 0 /* normal delivery */ +# define TOC_URGENT 1 /* urgent delivery */ +# define TOC_NONURGENT 2 /* non-urgent delivery */ + /* ** Trace information @@ -920,43 +1157,59 @@ EXTERN u_char tTdvect[100]; ** Declarations of useful functions */ -extern ADDRESS *parseaddr __P((char *, ADDRESS *, int, int, char **, ENVELOPE *)); -extern char *xalloc __P((int)); -extern bool sameaddr __P((ADDRESS *, ADDRESS *)); -extern FILE *dfopen __P((char *, int, int)); -extern EVENT *setevent __P((time_t, int(*)(), int)); -extern char *sfgets __P((char *, int, FILE *, time_t, char *)); -extern char *queuename __P((ENVELOPE *, int)); -extern time_t curtime __P(()); -extern bool transienterror __P((int)); +extern char *xalloc __P((int)); +extern FILE *dfopen __P((char *, int, int)); +extern char *sfgets __P((char *, int, FILE *, time_t, char *)); +extern char *queuename __P((ENVELOPE *, int)); +extern time_t curtime __P(()); +extern bool transienterror __P((int)); +extern char *fgetfolded __P((char *, int, FILE *)); +extern char *username __P(()); +extern char *pintvl __P((time_t, bool)); +extern bool shouldqueue __P((long, time_t)); +extern bool lockfile __P((int, char *, char *, int)); +extern char *hostsignature __P((MAILER *, char *, ENVELOPE *)); +extern void openxscript __P((ENVELOPE *)); +extern void closexscript __P((ENVELOPE *)); +extern char *shortenstring __P((const char *, int)); +extern bool usershellok __P((char *, char *)); +extern void commaize __P((HDR *, char *, bool, MCI *, ENVELOPE *)); +extern char *hvalue __P((char *, HDR *)); +extern char *defcharset __P((ENVELOPE *)); +extern bool wordinclass __P((char *, int)); +extern char *denlstring __P((char *, bool, bool)); +extern void makelower __P((char *)); +extern void rebuildaliases __P((MAP *, bool)); +extern void readaliases __P((MAP *, FILE *, bool, bool)); +extern void finis __P(()); +extern void setsender __P((char *, ENVELOPE *, char **, bool)); +extern FILE *safefopen __P((char *, int, int, int)); +extern void xputs __P((const char *)); +extern void logsender __P((ENVELOPE *, char *)); +extern void smtprset __P((MAILER *, MCI *, ENVELOPE *)); +extern void smtpquit __P((MAILER *, MCI *, ENVELOPE *)); +extern void setuserenv __P((const char *, const char *)); +extern void disconnect __P((int, ENVELOPE *)); +extern void putxline __P((char *, MCI *, int)); +extern void dumpfd __P((int, bool, bool)); +extern void makemailer __P((char *)); +extern void putfromline __P((MCI *, ENVELOPE *)); +extern void setoption __P((int, char *, bool, bool, ENVELOPE *)); +extern void setclass __P((int, char *)); +extern void inittimeouts __P((char *)); +extern void logdelivery __P((MAILER *, MCI *, const char *, ADDRESS *, time_t, ENVELOPE *)); +extern void giveresponse __P((int, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *)); + extern const char *errstring __P((int)); -extern void expand __P((char *, char *, char *, ENVELOPE *)); -extern void define __P((int, char *, ENVELOPE *)); -extern char *macvalue __P((int, ENVELOPE *)); -extern char **prescan __P((char *, int, char[], int, char **)); -extern int rewrite __P((char **, int, int, ENVELOPE *)); -extern char *fgetfolded __P((char *, int, FILE *)); -extern ADDRESS *recipient __P((ADDRESS *, ADDRESS **, ENVELOPE *)); -extern ENVELOPE *newenvelope __P((ENVELOPE *, ENVELOPE *)); -extern void dropenvelope __P((ENVELOPE *)); -extern void clearenvelope __P((ENVELOPE *, int)); -extern char *username __P(()); -extern MCI *mci_get __P((char *, MAILER *)); -extern char *pintvl __P((time_t, int)); -extern char *map_rewrite __P((MAP *, char *, int, char **)); -extern ADDRESS *getctladdr __P((ADDRESS *)); -extern char *anynet_ntoa __P((SOCKADDR *)); -extern char *remotename __P((char *, MAILER *, int, int *, ENVELOPE *)); -extern bool shouldqueue __P((long, time_t)); -extern bool lockfile __P((int, char *, char *, int)); -extern char *hostsignature __P((MAILER *, char *, ENVELOPE *)); -extern void openxscript __P((ENVELOPE *)); -extern void closexscript __P((ENVELOPE *)); extern sigfunc_t setsignal __P((int, sigfunc_t)); -extern char *shortenstring __P((char *, int)); -extern bool usershellok __P((char *)); -extern void commaize __P((HDR *, char *, int, MCI *, ENVELOPE *)); -extern char *denlstring __P((char *, int, 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)); + +#ifdef XDEBUG +extern void checkfd012 __P((char *)); +#endif /* ellipsis is a different case though */ #ifdef __STDC__ @@ -972,3 +1225,13 @@ extern void usrerr(); extern void message(); extern void nmessage(); #endif + +#if !HASSNPRINTF +# ifdef __STDC__ +extern void snprintf(char *, size_t, const char *, ...); +extern void vsnprintf(char *, size_t, const char *, va_list); +# else +extern void snprintf(); +extern void vsnprintf(); +# endif +#endif diff --git a/usr.sbin/sendmail/src/srvrsmtp.c b/usr.sbin/sendmail/src/srvrsmtp.c index e2a09e4..69a4fbe 100644 --- a/usr.sbin/sendmail/src/srvrsmtp.c +++ b/usr.sbin/sendmail/src/srvrsmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.37 (Berkeley) 4/13/94 (with SMTP)"; +static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (with SMTP)"; #else -static char sccsid[] = "@(#)srvrsmtp.c 8.37 (Berkeley) 4/13/94 (without SMTP)"; +static char sccsid[] = "@(#)srvrsmtp.c 8.97 (Berkeley) 11/18/95 (without SMTP)"; #endif #endif /* not lint */ @@ -117,35 +117,34 @@ bool OneXact = FALSE; /* one xaction only this run */ char *CurSmtpClient; /* who's at the other end of channel */ static char *skipword(); -extern char RealUserName[]; #define MAXBADCOMMANDS 25 /* maximum number of bad commands */ +void smtp(e) - register ENVELOPE *e; + register ENVELOPE *volatile e; { register char *p; register struct cmd *c; char *cmd; auto ADDRESS *vrfyqueue; ADDRESS *a; - bool gotmail; /* mail command received */ - bool gothello; /* helo command received */ + volatile bool gotmail; /* mail command received */ + volatile bool gothello; /* helo command received */ bool vrfy; /* set if this is a vrfy command */ - char *protocol; /* sending protocol */ - char *sendinghost; /* sending hostname */ - unsigned long msize; /* approximate maximum message size */ - char *peerhostname; /* name of SMTP peer or "localhost" */ + char *volatile protocol; /* sending protocol */ + char *volatile sendinghost; /* sending hostname */ + char *volatile peerhostname; /* name of SMTP peer or "localhost" */ auto char *delimptr; char *id; - int nrcpts; /* number of RCPT commands */ + volatile int nrcpts = 0; /* number of RCPT commands */ bool doublequeue; - int badcommands = 0; /* count of bad commands */ + volatile int badcommands = 0; /* count of bad commands */ char inp[MAXLINE]; char cmdbuf[MAXLINE]; - extern char Version[]; extern ENVELOPE BlankEnvelope; + extern void help __P((char *)); if (fileno(OutChannel) != fileno(stdout)) { @@ -162,28 +161,41 @@ smtp(e) CurSmtpClient = CurHostName; setproctitle("server %s startup", CurSmtpClient); - expand("\201e", inp, &inp[sizeof inp], e); - if (BrokenSmtpPeers) +#ifdef LOG + if (LogLevel > 11) { - p = strchr(inp, '\n'); - if (p != NULL) - *p = '\0'; - message("220 %s", inp); + /* log connection information */ + syslog(LOG_INFO, "SMTP connect from %.100s (%.100s)", + CurSmtpClient, anynet_ntoa(&RealHostAddr)); } - else - { - char *q = inp; +#endif - while (q != NULL) - { - p = strchr(q, '\n'); - if (p != NULL) - *p++ = '\0'; - message("220-%s", q); - q = p; - } - message("220 ESMTP spoken here"); + /* output the first line, inserting "ESMTP" as second word */ + expand(SmtpGreeting, inp, sizeof inp, e); + p = strchr(inp, '\n'); + if (p != NULL) + *p++ = '\0'; + id = strchr(inp, ' '); + if (id == NULL) + id = &inp[strlen(inp)]; + cmd = p == NULL ? "220 %.*s ESMTP%s" : "220-%.*s ESMTP%s"; + message(cmd, id - inp, inp, id); + + /* output remaining lines */ + while ((id = p) != NULL && (p = strchr(id, '\n')) != NULL) + { + *p++ = '\0'; + if (isascii(*id) && isspace(*id)) + id++; + message("220-%s", id); + } + if (id != NULL) + { + if (isascii(*id) && isspace(*id)) + id++; + message("220 %s", id); } + protocol = NULL; sendinghost = macvalue('s', e); gothello = FALSE; @@ -213,7 +225,7 @@ smtp(e) /* read the input line */ SmtpPhase = "server cmd read"; - setproctitle("server %s cmd read", CurHostName); + setproctitle("server %s cmd read", CurSmtpClient); p = sfgets(inp, sizeof inp, InChannel, TimeOuts.to_nextcommand, SmtpPhase); @@ -226,7 +238,7 @@ smtp(e) MyHostName, CurSmtpClient); #ifdef LOG if (LogLevel > (gotmail ? 1 : 19)) - syslog(LOG_NOTICE, "lost input channel from %s", + syslog(LOG_NOTICE, "lost input channel from %.100s", CurSmtpClient); #endif if (InChild) @@ -285,6 +297,39 @@ smtp(e) protocol = "SMTP"; SmtpPhase = "server HELO"; } + + /* check for valid domain name (re 1123 5.2.5) */ + if (*p == '\0') + { + message("501 %s requires domain address", + cmdbuf); + break; + } + else + { + register char *q; + + for (q = p; *q != '\0'; q++) + { + if (!isascii(*q)) + break; + if (isalnum(*q)) + continue; + if (isspace(*q)) + { + *q = '\0'; + break; + } + if (strchr("[].-_#", *q) == NULL) + break; + } + if (*q != '\0') + { + message("501 Invalid domain name"); + break; + } + } + sendinghost = newstr(p); gothello = TRUE; if (c->cmdcode != CMDEHLO) @@ -300,10 +345,19 @@ smtp(e) MyHostName, CurSmtpClient); if (!bitset(PRIV_NOEXPN, PrivacyFlags)) message("250-EXPN"); +#if MIME8TO7 + message("250-8BITMIME"); +#endif if (MaxMessageSize > 0) message("250-SIZE %ld", MaxMessageSize); else message("250-SIZE"); +#if DSN + if (SendMIMEErrors) + message("250-DSN"); +#endif + message("250-VERB"); + message("250-ONEX"); message("250 HELP"); break; @@ -344,7 +398,7 @@ smtp(e) { auth_warning(e, "Host %s didn't use HELO protocol", - peerhostname); + CurSmtpClient); } #ifdef PICKY_HELO_CHECK if (strcasecmp(sendinghost, peerhostname) != 0 && @@ -352,7 +406,7 @@ smtp(e) strcasecmp(sendinghost, MyHostName) != 0)) { auth_warning(e, "Host %s claimed to be %s", - peerhostname, sendinghost); + CurSmtpClient, sendinghost); } #endif @@ -362,7 +416,7 @@ smtp(e) define('s', sendinghost, e); initsys(e); nrcpts = 0; - e->e_flags |= EF_LOGSENDER; + e->e_flags |= EF_LOGSENDER|EF_CLRQUEUE; setproctitle("%s %s: %.80s", e->e_id, CurSmtpClient, inp); /* child -- go do the processing */ @@ -392,19 +446,21 @@ smtp(e) /* check for possible spoofing */ if (RealUid != 0 && OpMode == MD_SMTP && - (e->e_from.q_mailer != LocalMailer && - strcmp(e->e_from.q_user, RealUserName) != 0)) + !wordinclass(RealUserName, 't') && + !bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) && + strcmp(e->e_from.q_user, RealUserName) != 0) { auth_warning(e, "%s owned process doing -bs", RealUserName); } /* now parse ESMTP arguments */ - msize = 0; + e->e_msgsize = 0; while (p != NULL && *p != '\0') { char *kp; char *vp = NULL; + extern void mail_esmtp_args __P((char *, char *, ENVELOPE *)); /* locate the beginning of the keyword */ while (isascii(*p) && isspace(*p)) @@ -435,59 +491,17 @@ smtp(e) printf("MAIL: got arg %s=\"%s\"\n", kp, vp == NULL ? "<null>" : vp); - if (strcasecmp(kp, "size") == 0) - { - if (vp == NULL) - { - usrerr("501 SIZE requires a value"); - /* NOTREACHED */ - } -# ifdef __STDC__ - msize = strtoul(vp, (char **) NULL, 10); -# else - msize = strtol(vp, (char **) NULL, 10); -# endif - } - else if (strcasecmp(kp, "body") == 0) - { - if (vp == NULL) - { - usrerr("501 BODY requires a value"); - /* NOTREACHED */ - } -# ifdef MIME - if (strcasecmp(vp, "8bitmime") == 0) - { - e->e_bodytype = "8BITMIME"; - SevenBit = FALSE; - } - else if (strcasecmp(vp, "7bit") == 0) - { - e->e_bodytype = "7BIT"; - SevenBit = TRUE; - } - else - { - usrerr("501 Unknown BODY type %s", - vp); - } -# endif - } - else - { - usrerr("501 %s parameter unrecognized", kp); - /* NOTREACHED */ - } + mail_esmtp_args(kp, vp, e); } - if (MaxMessageSize > 0 && msize > MaxMessageSize) + if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) { usrerr("552 Message size exceeds fixed maximum message size (%ld)", MaxMessageSize); /* NOTREACHED */ } - - if (!enoughspace(msize)) + + if (!enoughdiskspace(e->e_msgsize)) { message("452 Insufficient disk space; try again later"); break; @@ -517,11 +531,53 @@ smtp(e) p = skipword(p, "to"); if (p == NULL) break; - a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', NULL, e); + a = parseaddr(p, NULLADDR, RF_COPYALL, ' ', &delimptr, e); if (a == NULL) break; - a->q_flags |= QPRIMARY; - a = recipient(a, &e->e_sendqueue, e); + p = delimptr; + + /* now parse ESMTP arguments */ + while (p != NULL && *p != '\0') + { + char *kp; + char *vp = NULL; + extern void rcpt_esmtp_args __P((ADDRESS *, char *, char *, ENVELOPE *)); + + /* locate the beginning of the keyword */ + while (isascii(*p) && isspace(*p)) + p++; + if (*p == '\0') + break; + kp = p; + + /* skip to the value portion */ + while (isascii(*p) && isalnum(*p) || *p == '-') + p++; + if (*p == '=') + { + *p++ = '\0'; + vp = p; + + /* skip to the end of the value */ + while (*p != '\0' && *p != ' ' && + !(isascii(*p) && iscntrl(*p)) && + *p != '=') + p++; + } + + if (*p != '\0') + *p++ = '\0'; + + if (tTd(19, 1)) + printf("RCPT: got arg %s=\"%s\"\n", kp, + vp == NULL ? "<null>" : vp); + + rcpt_esmtp_args(a, kp, vp, e); + } + + /* save in recipient list after ESMTP mods */ + a = recipient(a, &e->e_sendqueue, 0, e); + if (Errors != 0) break; @@ -575,10 +631,18 @@ smtp(e) /* collect the text of the message */ SmtpPhase = "collect"; - collect(TRUE, doublequeue, e); + buffer_errors(); + collect(InChannel, TRUE, doublequeue, NULL, e); + flush_errors(TRUE); if (Errors != 0) goto abortmessage; - HoldErrs = TRUE; + + /* make sure we actually do delivery */ + e->e_flags &= ~EF_CLRQUEUE; + + /* from now on, we have to operate silently */ + buffer_errors(); + e->e_errormode = EM_MAIL; /* ** Arrange to send to everyone. @@ -599,42 +663,32 @@ smtp(e) */ SmtpPhase = "delivery"; - if (nrcpts != 1 && !doublequeue) - { - HoldErrs = TRUE; - e->e_errormode = EM_MAIL; - } e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); id = e->e_id; - /* send to all recipients */ - sendall(e, doublequeue ? SM_QUEUE : SM_DEFAULT); - e->e_to = NULL; - - /* issue success if appropriate and reset */ - if (Errors == 0 || HoldErrs) - message("250 %s Message accepted for delivery", id); - - if (bitset(EF_FATALERRS, e->e_flags) && !HoldErrs) + if (doublequeue) { - /* avoid sending back an extra message */ - e->e_flags &= ~EF_FATALERRS; - e->e_flags |= EF_CLRQUEUE; + /* make sure it is in the queue */ + queueup(e, FALSE); } else { - /* from now on, we have to operate silently */ - HoldErrs = TRUE; - e->e_errormode = EM_MAIL; + /* send to all recipients */ + sendall(e, SM_DEFAULT); + } + e->e_to = NULL; - /* if we just queued, poke it */ - if (doublequeue && e->e_sendmode != SM_QUEUE) - { - extern pid_t dowork(); + /* issue success message */ + message("250 %s Message accepted for delivery", id); - unlockqueue(e); - (void) dowork(id, TRUE, TRUE, e); - } + /* if we just queued, poke it */ + if (doublequeue && e->e_sendmode != SM_QUEUE && + e->e_sendmode != SM_DEFER) + { + extern pid_t dowork(); + + unlockqueue(e); + (void) dowork(id, TRUE, TRUE, e); } abortmessage: @@ -651,6 +705,9 @@ smtp(e) case CMDRSET: /* rset -- reset state */ message("250 Reset state"); + + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; e->e_flags |= EF_CLRQUEUE; if (InChild) finis(); @@ -668,13 +725,14 @@ smtp(e) PrivacyFlags)) { if (vrfy) - message("252 Who's to say?"); + message("252 Cannot VRFY user; try RCPT to attempt delivery (or try finger)"); else message("502 Sorry, we do not allow this operation"); #ifdef LOG if (LogLevel > 5) - syslog(LOG_INFO, "%s: %s [rejected]", - CurSmtpClient, inp); + syslog(LOG_INFO, "%.100s: %s [rejected]", + CurSmtpClient, + shortenstring(inp, 203)); #endif break; } @@ -689,14 +747,16 @@ smtp(e) break; #ifdef LOG if (LogLevel > 5) - syslog(LOG_INFO, "%s: %s", CurSmtpClient, inp); + syslog(LOG_INFO, "%.100s: %s", + CurSmtpClient, + shortenstring(inp, 203)); #endif vrfyqueue = NULL; QuickAbort = TRUE; if (vrfy) e->e_flags |= EF_VRFYONLY; while (*p != '\0' && isascii(*p) && isspace(*p)) - *p++; + p++; if (*p == '\0') { message("501 Argument required"); @@ -704,7 +764,7 @@ smtp(e) } else { - (void) sendtolist(p, NULLADDR, &vrfyqueue, e); + (void) sendtolist(p, NULLADDR, &vrfyqueue, 0, e); } if (Errors != 0) { @@ -718,6 +778,8 @@ smtp(e) } while (vrfyqueue != NULL) { + extern void printvrfyaddr __P((ADDRESS *, bool)); + a = vrfyqueue; while ((a = a->q_next) != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) @@ -742,6 +804,9 @@ smtp(e) message("221 %s closing connection", MyHostName); doquit: + /* arrange to ignore any current send list */ + e->e_sendqueue = NULL; + /* avoid future 050 messages */ disconnect(1, e); @@ -786,8 +851,8 @@ doquit: # ifdef LOG if (LogLevel > 0) syslog(LOG_CRIT, - "\"%s\" command from %s (%s)", - c->cmdname, peerhostname, + "\"%s\" command from %.100s (%.100s)", + c->cmdname, CurSmtpClient, anynet_ntoa(&RealHostAddr)); # endif /* FALL THROUGH */ @@ -847,7 +912,7 @@ skipword(p, w) { syntax: message("501 Syntax error in parameters scanning \"%s\"", - firstp); + shortenstring(firstp, 203)); Errors++; return (NULL); } @@ -865,6 +930,183 @@ skipword(p, w) return (p); } /* +** MAIL_ESMTP_ARGS -- process ESMTP arguments from MAIL line +** +** Parameters: +** kp -- the parameter key. +** vp -- the value of that parameter. +** e -- the envelope. +** +** Returns: +** none. +*/ + +void +mail_esmtp_args(kp, vp, e) + char *kp; + char *vp; + ENVELOPE *e; +{ + if (strcasecmp(kp, "size") == 0) + { + if (vp == NULL) + { + usrerr("501 SIZE requires a value"); + /* NOTREACHED */ + } +# if defined(__STDC__) && !defined(BROKEN_ANSI_LIBRARY) + e->e_msgsize = strtoul(vp, (char **) NULL, 10); +# else + e->e_msgsize = strtol(vp, (char **) NULL, 10); +# endif + } + else if (strcasecmp(kp, "body") == 0) + { + if (vp == NULL) + { + usrerr("501 BODY requires a value"); + /* NOTREACHED */ + } + else if (strcasecmp(vp, "8bitmime") == 0) + { + SevenBitInput = FALSE; + } + else if (strcasecmp(vp, "7bit") == 0) + { + SevenBitInput = TRUE; + } + else + { + usrerr("501 Unknown BODY type %s", + vp); + /* NOTREACHED */ + } + e->e_bodytype = newstr(vp); + } + else if (strcasecmp(kp, "envid") == 0) + { + if (vp == NULL) + { + usrerr("501 ENVID requires a value"); + /* NOTREACHED */ + } + if (!xtextok(vp)) + { + usrerr("501 Syntax error in ENVID parameter value"); + /* NOTREACHED */ + } + if (e->e_envid != NULL) + { + usrerr("501 Duplicate ENVID parameter"); + /* NOTREACHED */ + } + e->e_envid = newstr(vp); + } + else if (strcasecmp(kp, "ret") == 0) + { + if (vp == NULL) + { + usrerr("501 RET requires a value"); + /* NOTREACHED */ + } + if (bitset(EF_RET_PARAM, e->e_flags)) + { + usrerr("501 Duplicate RET parameter"); + /* NOTREACHED */ + } + e->e_flags |= EF_RET_PARAM; + if (strcasecmp(vp, "hdrs") == 0) + e->e_flags |= EF_NO_BODY_RETN; + else if (strcasecmp(vp, "full") != 0) + { + usrerr("501 Bad argument \"%s\" to RET", vp); + /* NOTREACHED */ + } + } + else + { + usrerr("501 %s parameter unrecognized", kp); + /* NOTREACHED */ + } +} +/* +** RCPT_ESMTP_ARGS -- process ESMTP arguments from RCPT line +** +** Parameters: +** a -- the address corresponding to the To: parameter. +** kp -- the parameter key. +** vp -- the value of that parameter. +** e -- the envelope. +** +** Returns: +** none. +*/ + +void +rcpt_esmtp_args(a, kp, vp, e) + ADDRESS *a; + char *kp; + char *vp; + ENVELOPE *e; +{ + if (strcasecmp(kp, "notify") == 0) + { + char *p; + + if (vp == NULL) + { + usrerr("501 NOTIFY requires a value"); + /* NOTREACHED */ + } + a->q_flags &= ~(QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY); + a->q_flags |= QHASNOTIFY; + if (strcasecmp(vp, "never") == 0) + return; + for (p = vp; p != NULL; vp = p) + { + p = strchr(p, ','); + if (p != NULL) + *p++ = '\0'; + if (strcasecmp(vp, "success") == 0) + a->q_flags |= QPINGONSUCCESS; + else if (strcasecmp(vp, "failure") == 0) + a->q_flags |= QPINGONFAILURE; + else if (strcasecmp(vp, "delay") == 0) + a->q_flags |= QPINGONDELAY; + else + { + usrerr("501 Bad argument \"%s\" to NOTIFY", + vp); + /* NOTREACHED */ + } + } + } + else if (strcasecmp(kp, "orcpt") == 0) + { + if (vp == NULL) + { + usrerr("501 ORCPT requires a value"); + /* NOTREACHED */ + } + if (strchr(vp, ';') == NULL || !xtextok(vp)) + { + usrerr("501 Syntax error in ORCPT parameter value"); + /* NOTREACHED */ + } + if (a->q_orcpt != NULL) + { + usrerr("501 Duplicate ORCPT parameter"); + /* NOTREACHED */ + } + a->q_orcpt = newstr(vp); + } + else + { + usrerr("501 %s parameter unrecognized", kp); + /* NOTREACHED */ + } +} +/* ** PRINTVRFYADDR -- print an entry in the verify queue ** ** Parameters: @@ -878,6 +1120,7 @@ skipword(p, w) ** Prints the appropriate 250 codes. */ +void printvrfyaddr(a, last) register ADDRESS *a; bool last; @@ -905,66 +1148,6 @@ printvrfyaddr(a, last) } } /* -** HELP -- implement the HELP command. -** -** Parameters: -** topic -- the topic we want help for. -** -** Returns: -** none. -** -** Side Effects: -** outputs the help file to message output. -*/ - -help(topic) - char *topic; -{ - register FILE *hf; - int len; - char buf[MAXLINE]; - bool noinfo; - - if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) - { - /* no help */ - errno = 0; - message("502 HELP not implemented"); - return; - } - - if (topic == NULL || *topic == '\0') - topic = "smtp"; - else - makelower(topic); - - len = strlen(topic); - noinfo = TRUE; - - while (fgets(buf, sizeof buf, hf) != NULL) - { - if (strncmp(buf, topic, len) == 0) - { - register char *p; - - p = strchr(buf, '\t'); - if (p == NULL) - p = buf; - else - p++; - fixcrlf(p, TRUE); - message("214-%s", p); - noinfo = FALSE; - } - } - - if (noinfo) - message("504 HELP topic unknown"); - else - message("214 End of HELP info"); - (void) fclose(hf); -} -/* ** RUNINCHILD -- return twice -- once in the child, then in the parent again ** ** Parameters: @@ -978,6 +1161,7 @@ help(topic) ** none. */ +int runinchild(label, e) char *label; register ENVELOPE *e; @@ -989,7 +1173,7 @@ runinchild(label, e) childpid = dofork(); if (childpid < 0) { - syserr("%s: cannot fork", label); + syserr("451 %s: cannot fork", label); return (1); } if (childpid > 0) @@ -997,12 +1181,12 @@ runinchild(label, e) auto int st; /* parent -- wait for child to complete */ - setproctitle("server %s child wait", CurHostName); + setproctitle("server %s child wait", CurSmtpClient); st = waitfor(childpid); if (st == -1) - syserr("%s: lost child", label); + syserr("451 %s: lost child", label); else if (!WIFEXITED(st)) - syserr("%s: died on signal %d", + syserr("451 %s: died on signal %d", label, st & 0177); /* if we exited on a QUIT command, complete the process */ @@ -1030,3 +1214,72 @@ runinchild(label, e) } # endif /* SMTP */ +/* +** HELP -- implement the HELP command. +** +** Parameters: +** topic -- the topic we want help for. +** +** Returns: +** none. +** +** Side Effects: +** outputs the help file to message output. +*/ + +void +help(topic) + char *topic; +{ + register FILE *hf; + int len; + bool noinfo; + char buf[MAXLINE]; + extern char Version[]; + + + if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) + { + /* no help */ + errno = 0; + message("502 Sendmail %s -- HELP not implemented", Version); + return; + } + + if (topic == NULL || *topic == '\0') + { + topic = "smtp"; + message("214-This is Sendmail version %s", Version); + noinfo = FALSE; + } + else + { + makelower(topic); + noinfo = TRUE; + } + + len = strlen(topic); + + while (fgets(buf, sizeof buf, hf) != NULL) + { + if (strncmp(buf, topic, len) == 0) + { + register char *p; + + p = strchr(buf, '\t'); + if (p == NULL) + p = buf; + else + p++; + fixcrlf(p, TRUE); + message("214-%s", p); + noinfo = FALSE; + } + } + + if (noinfo) + message("504 HELP topic \"%.10s\" unknown", topic); + else + message("214 End of HELP info"); + (void) fclose(hf); +} diff --git a/usr.sbin/sendmail/src/sysexits.h b/usr.sbin/sendmail/src/sysexits.h deleted file mode 100644 index 464cb11..0000000 --- a/usr.sbin/sendmail/src/sysexits.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _SYSEXITS_H_ -#define _SYSEXITS_H_ - -/* - * SYSEXITS.H -- Exit status codes for system programs. - * - * This include file attempts to categorize possible error - * exit statuses for system programs, notably delivermail - * and the Berkeley network. - * - * Error numbers begin at EX__BASE to reduce the possibility of - * clashing with other exit statuses that random programs may - * already return. The meaning of the codes is approximately - * as follows: - * - * EX_USAGE -- The command was used incorrectly, e.g., with - * the wrong number of arguments, a bad flag, a bad - * syntax in a parameter, or whatever. - * EX_DATAERR -- The input data was incorrect in some way. - * This should only be used for user's data & not - * system files. - * EX_NOINPUT -- An input file (not a system file) did not - * exist or was not readable. This could also include - * errors like "No message" to a mailer (if it cared - * to catch it). - * EX_NOUSER -- The user specified did not exist. This might - * be used for mail addresses or remote logins. - * EX_NOHOST -- The host specified did not exist. This is used - * in mail addresses or network requests. - * EX_UNAVAILABLE -- A service is unavailable. This can occur - * if a support program or file does not exist. This - * can also be used as a catchall message when something - * you wanted to do doesn't work, but you don't know - * why. - * EX_SOFTWARE -- An internal software error has been detected. - * This should be limited to non-operating system related - * errors as possible. - * EX_OSERR -- An operating system error has been detected. - * This is intended to be used for such things as "cannot - * fork", "cannot create pipe", or the like. It includes - * things like getuid returning a user that does not - * exist in the passwd file. - * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, - * etc.) does not exist, cannot be opened, or has some - * sort of error (e.g., syntax error). - * EX_CANTCREAT -- A (user specified) output file cannot be - * created. - * EX_IOERR -- An error occurred while doing I/O on some file. - * EX_TEMPFAIL -- temporary failure, indicating something that - * is not really an error. In sendmail, this means - * that a mailer (e.g.) could not create a connection, - * and the request should be reattempted later. - * EX_PROTOCOL -- the remote system returned something that - * was "not possible" during a protocol exchange. - * EX_NOPERM -- You did not have sufficient permission to - * perform the operation. This is not intended for - * file system problems, which should use NOINPUT or - * CANTCREAT, but rather for higher level permissions. - */ - -#define EX_OK 0 /* successful termination */ - -#define EX__BASE 64 /* base value for error messages */ - -#define EX_USAGE 64 /* command line usage error */ -#define EX_DATAERR 65 /* data format error */ -#define EX_NOINPUT 66 /* cannot open input */ -#define EX_NOUSER 67 /* addressee unknown */ -#define EX_NOHOST 68 /* host name unknown */ -#define EX_UNAVAILABLE 69 /* service unavailable */ -#define EX_SOFTWARE 70 /* internal software error */ -#define EX_OSERR 71 /* system error (e.g., can't fork) */ -#define EX_OSFILE 72 /* critical OS file missing */ -#define EX_CANTCREAT 73 /* can't create (user) output file */ -#define EX_IOERR 74 /* input/output error */ -#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ -#define EX_PROTOCOL 76 /* remote error in protocol */ -#define EX_NOPERM 77 /* permission denied */ -#define EX_CONFIG 78 /* configuration error */ - -#define EX__MAX 78 /* maximum listed value */ - -#endif /* !_SYSEXITS_H_ */ diff --git a/usr.sbin/sendmail/src/udb.c b/usr.sbin/sendmail/src/udb.c index 4739a08..bb83bef 100644 --- a/usr.sbin/sendmail/src/udb.c +++ b/usr.sbin/sendmail/src/udb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * @@ -35,21 +35,30 @@ #include "sendmail.h" #ifndef lint -#ifdef USERDB -static char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (with USERDB)"; +#if USERDB +static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (with USERDB)"; #else -static char sccsid [] = "@(#)udb.c 8.8 (Berkeley) 4/14/94 (without USERDB)"; +static char sccsid [] = "@(#)udb.c 8.32 (Berkeley) 11/18/95 (without USERDB)"; #endif #endif -#ifdef USERDB +#if USERDB #include <errno.h> -#include <netdb.h> -#include <db.h> + +#ifdef NEWDB +# include <db.h> +#else +# define DBT struct _data_base_thang_ +DBT +{ + void *data; /* pointer to data */ + size_t size; /* length of data */ +}; +#endif #ifdef HESIOD -#include <hesiod.h> +# include <hesiod.h> #endif /* HESIOD */ /* @@ -82,6 +91,7 @@ struct udbent } udb_forward; #define udb_fwdhost udb_u.udb_forward._udb_fwdhost +#ifdef NEWDB /* type UE_FETCH -- lookup in local database */ struct { @@ -90,6 +100,7 @@ struct udbent } udb_lookup; #define udb_dbname udb_u.udb_lookup._udb_dbname #define udb_dbp udb_u.udb_lookup._udb_dbp +#endif } udb_u; }; @@ -114,6 +125,8 @@ struct option ** Parameters: ** a -- address to expand. ** sendq -- pointer to head of sendq to put the expansions in. +** aliaslevel -- the current alias nesting depth. +** e -- the current envelope. ** ** Returns: ** EX_TEMPFAIL -- if something "odd" happened -- probably due @@ -132,13 +145,13 @@ int UdbSock = -1; bool UdbInitialized = FALSE; int -udbexpand(a, sendq, e) +udbexpand(a, sendq, aliaslevel, e) register ADDRESS *a; ADDRESS **sendq; + int aliaslevel; register ENVELOPE *e; { int i; - register char *p; DBT key; DBT info; bool breakout; @@ -201,6 +214,7 @@ udbexpand(a, sendq, e) switch (up->udb_type) { +#ifdef NEWDB case UDB_DBFETCH: key.data = keybuf; key.size = keylen; @@ -227,7 +241,6 @@ udbexpand(a, sendq, e) if (bitset(EF_VRFYONLY, e->e_flags)) { a->q_flags |= QVERIFIED; - e->e_nrcpts++; return EX_OK; } @@ -242,12 +255,11 @@ udbexpand(a, sendq, e) message("expanded to %s", user); #ifdef LOG if (LogLevel >= 10) - syslog(LOG_INFO, "%s: expand %s => %s", - e->e_id, e->e_to, user); + syslog(LOG_INFO, "%s: expand %.100s => %s", + e->e_id, e->e_to, + shortenstring(user, 203)); #endif - AliasLevel++; - naddrs += sendtolist(user, a, sendq, e); - AliasLevel--; + naddrs += sendtolist(user, a, sendq, aliaslevel + 1, e); if (user != buf) free(user); @@ -299,9 +311,11 @@ udbexpand(a, sendq, e) fprintf(e->e_xfp, "Message delivered to mailing list %s\n", a->q_paddr); - e->e_flags |= EF_SENDRECEIPT; } + e->e_flags |= EF_SENDRECEIPT; + a->q_flags |= QDELIVERED|QEXPANDED; break; +#endif #ifdef HESIOD case UDB_HESIOD: @@ -312,12 +326,45 @@ udbexpand(a, sendq, e) keybuf, keylen); /* look up the key via hesiod */ i = hes_udb_get(&key, &info); - if (i > 0 || info.size <= 0) + if (i < 0) { + syserr("udbexpand: hesiod-get %.*s stat %d", + key.size, key.data, i); + return EX_TEMPFAIL; + } + else if (i > 0 || info.size <= 0) + { +#if HES_GETMAILHOST + struct hes_postoffice *hp; +#endif + if (tTd(28, 2)) - printf("udbexpand: no match on %s (%d)\n", - keybuf, keylen); + printf("udbexpand: no match on %s (%d)\n", + keybuf, keylen); +#if HES_GETMAILHOST + if (tTd(28, 8)) + printf(" ... trying hes_getmailhost(%s)\n", + a->q_user); + hp = hes_getmailhost(a->q_user); + if (hp == NULL) + { + if (hes_error() == HES_ER_NET) + { + syserr("udbexpand: hesiod-getmail %s stat %d", + a->q_user, hes_error()); + return EX_TEMPFAIL; + } + if (tTd(28, 2)) + printf("hes_getmailhost(%s): %d\n", + a->q_user, hes_error(); + continue; + } + sprintf(info.data, "%s@%s", + hp->po_name, hp->po_host); + info.size = strlen(info.data); +#else continue; +#endif } if (tTd(28, 80)) printf("udbexpand: match %.*s: %.*s\n", @@ -327,8 +374,6 @@ udbexpand(a, sendq, e) if (bitset(EF_VRFYONLY, e->e_flags)) { a->q_flags |= QVERIFIED; - e->e_nrcpts++; - free(info.data); return EX_OK; } @@ -339,17 +384,15 @@ udbexpand(a, sendq, e) user = xalloc(info.size + 1); bcopy(info.data, user, info.size); user[info.size] = '\0'; - free(info.data); message("hesioded to %s", user); #ifdef LOG if (LogLevel >= 10) - syslog(LOG_INFO, "%s: hesiod %s => %s", - e->e_id, e->e_to, user); + syslog(LOG_INFO, "%s: hesiod %.100s => %s", + e->e_id, e->e_to, + shortenstring(user, 203)); #endif - AliasLevel++; - naddrs = sendtolist(user, a, sendq, e); - AliasLevel--; + naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); if (user != buf) free(user); @@ -363,12 +406,6 @@ udbexpand(a, sendq, e) } a->q_flags |= QDONTSEND; } - if (i < 0) - { - syserr("udbexpand: hesiod-get %.*s stat %d", - key.size, key.data, i); - return EX_TEMPFAIL; - } /* ** If this address has a -request address, reflect @@ -386,7 +423,6 @@ udbexpand(a, sendq, e) a->q_owner = xalloc(info.size + 1); bcopy(info.data, a->q_owner, info.size); a->q_owner[info.size] = '\0'; - free(info.data); break; #endif /* HESIOD */ @@ -405,9 +441,7 @@ udbexpand(a, sendq, e) (void) sprintf(user, "%s@%s", a->q_user, up->udb_fwdhost); message("expanded to %s", user); a->q_flags &= ~QSELFREF; - AliasLevel++; - naddrs = sendtolist(user, a, sendq, e); - AliasLevel--; + naddrs = sendtolist(user, a, sendq, aliaslevel + 1, e); if (naddrs > 0 && !bitset(QSELFREF, a->q_flags)) { if (tTd(28, 5)) @@ -509,6 +543,7 @@ udbmatch(user, field) switch (up->udb_type) { +#ifdef NEWDB case UDB_DBFETCH: key.data = keybuf; key.size = keylen; @@ -528,6 +563,7 @@ udbmatch(user, field) printf("udbmatch ==> %s\n", p); return p; break; +#endif #ifdef HESIOD case UDB_HESIOD: @@ -545,11 +581,9 @@ udbmatch(user, field) p = xalloc(info.size + 1); bcopy(info.data, p, info.size); p[info.size] = '\0'; - free(info.data); if (tTd(28, 1)) printf("udbmatch ==> %s\n", p); return p; - break; #endif /* HESIOD */ } } @@ -572,6 +606,7 @@ udbmatch(user, field) { switch (up->udb_type) { +#ifdef NEWDB case UDB_DBFETCH: /* get the default case for this database */ if (up->udb_default == NULL) @@ -613,6 +648,7 @@ udbmatch(user, field) printf("udbmatch ==> %s\n", p); return p; break; +#endif #ifdef HESIOD case UDB_HESIOD: @@ -634,7 +670,6 @@ udbmatch(user, field) up->udb_default = xalloc(info.size + 1); bcopy(info.data, up->udb_default, info.size); up->udb_default[info.size] = '\0'; - free(info.data); } else if (up->udb_default[0] == '\0') continue; @@ -649,7 +684,6 @@ udbmatch(user, field) continue; } - free(info.data); /* they exist -- build the actual address */ p = xalloc(strlen(user) + strlen(up->udb_default) + 2); (void) strcpy(p, user); @@ -667,6 +701,57 @@ udbmatch(user, field) return NULL; } /* +** UDB_MAP_LOOKUP -- look up arbitrary entry in user database map +** +** Parameters: +** map -- the map being queried. +** name -- the name to look up. +** av -- arguments to the map lookup. +** statp -- to get any error status. +** +** Returns: +** NULL if name not found in map. +** The rewritten name otherwise. +*/ + +char * +udb_map_lookup(map, name, av, statp) + MAP *map; + char *name; + char **av; + int *statp; +{ + char *val; + char *key; + char keybuf[MAXNAME + 1]; + + if (tTd(28, 20) || tTd(38, 20)) + printf("udb_map_lookup(%s, %s)\n", map->map_mname, name); + + if (bitset(MF_NOFOLDCASE, map->map_mflags)) + { + key = name; + } + else + { + int keysize = strlen(name); + + if (keysize > sizeof keybuf - 1) + keysize = sizeof keybuf - 1; + bcopy(name, keybuf, keysize); + keybuf[keysize] = '\0'; + makelower(keybuf); + key = keybuf; + } + val = udbmatch(key, map->map_file); + if (val == NULL) + return NULL; + if (bitset(MF_MATCHONLY, map->map_mflags)) + return map_rewrite(map, name, strlen(name), NULL); + else + return map_rewrite(map, val, strlen(val), av); +} +/* ** _UDBX_INIT -- parse the UDB specification, opening any valid entries. ** ** Parameters: @@ -688,9 +773,7 @@ int _udbx_init() { register char *p; - int i; register struct udbent *up; - char buf[BUFSIZ]; if (UdbInitialized) return EX_OK; @@ -705,11 +788,14 @@ _udbx_init() while (p != NULL) { char *spec; - auto int rcode; int nopts; +# if 0 + auto int rcode; int nmx; + int i; register struct hostent *h; char *mxhosts[MAXMXHOSTS + 1]; +# endif struct option opts[MAXUDBOPTS + 1]; while (*p == ' ' || *p == '\t' || *p == ',') @@ -743,10 +829,13 @@ _udbx_init() ** since it always matches the input. ** /dbname -- search the named database on the local ** host using the Berkeley db package. + ** Hesiod -- search the named database with BIND + ** using the MIT Hesiod package. */ switch (*spec) { +#if 0 case '+': /* search remote database */ case '*': /* search remote database (expand MX) */ if (*spec == '*') @@ -776,14 +865,14 @@ _udbx_init() for (i = 0; i < nmx; i++) { - h = gethostbyname(mxhosts[i]); + h = sm_gethostbyname(mxhosts[i]); if (h == NULL) continue; up->udb_type = UDB_REMOTE; up->udb_addr.sin_family = h->h_addrtype; bcopy(h->h_addr_list[0], (char *) &up->udb_addr.sin_addr, - sizeof up->udb_addr.sin_addr); + INADDRSZ); up->udb_addr.sin_port = UdbPort; up->udb_timeout = UdbTimeout; up++; @@ -796,6 +885,7 @@ _udbx_init() (void) fcntl(UdbSock, F_SETFD, 1); } break; +#endif case '@': /* forward to remote host */ up->udb_type = UDB_FORWARD; @@ -803,22 +893,31 @@ _udbx_init() up++; break; +#ifdef HESIOD case 'h': /* use hesiod */ case 'H': -#ifdef HESIOD if (strcasecmp(spec, "hesiod") != 0) - break; + goto badspec; up->udb_type = UDB_HESIOD; up++; -#endif /* HESIOD */ break; +#endif /* HESIOD */ +#ifdef NEWDB case '/': /* look up remote name */ up->udb_dbname = spec; errno = 0; up->udb_dbp = dbopen(spec, O_RDONLY, 0644, DB_BTREE, NULL); if (up->udb_dbp == NULL) { + if (tTd(28, 1)) + { + int saveerrno = errno; + + printf("dbopen(%s): %s", + spec, errstring(errno)); + errno = saveerrno; + } if (errno != ENOENT && errno != EACCES) { #ifdef LOG @@ -834,6 +933,12 @@ _udbx_init() up->udb_type = UDB_DBFETCH; up++; break; +#endif + + default: +badspec: + syserr("Unknown UDB spec %s", spec); + break; } } up->udb_type = UDB_EOLIST; @@ -844,15 +949,21 @@ _udbx_init() { switch (up->udb_type) { +#ifdef DAEMON case UDB_REMOTE: printf("REMOTE: addr %s, timeo %d\n", anynet_ntoa((SOCKADDR *) &up->udb_addr), up->udb_timeout); break; +#endif case UDB_DBFETCH: +#ifdef NEWDB printf("FETCH: file %s\n", up->udb_dbname); +#else + printf("FETCH\n"); +#endif break; case UDB_FORWARD: @@ -880,6 +991,7 @@ _udbx_init() */ tempfail: +#ifdef NEWDB for (up = UdbEnts; up->udb_type != UDB_EOLIST; up++) { if (up->udb_type == UDB_DBFETCH) @@ -887,6 +999,7 @@ _udbx_init() (*up->udb_dbp->close)(up->udb_dbp); } } +#endif return EX_TEMPFAIL; } @@ -929,20 +1042,24 @@ hes_udb_get(key, info) { char *name, *type; char *p, **hp; + char kbuf[MAXKEY + 1]; - name = key->data; - type = strchr(name, ':'); + strcpy(kbuf, key->data); + name = kbuf; + type = strrchr(name, ':'); if (type == NULL) return 1; - *type++ = '\0'; + if (strchr(name, '@') != NULL) + return 1; if (tTd(28, 1)) printf("hes_udb_get(%s, %s)\n", name, type); /* make the hesiod query */ hp = hes_resolve(name, type); - if (hp == NULL) + *--type = ':'; + if (hp == NULL || hp[0] == NULL) { /* network problem or timeout */ if (hes_error() == HES_ER_NET) @@ -954,19 +1071,19 @@ hes_udb_get(key, info) { /* ** If there are multiple matches, just return the - ** first one and free the others. + ** first one. ** ** XXX These should really be returned; for example, ** XXX it is legal for :maildrop to be multi-valued. */ - for (p = hp[1]; p; p++) - free(p); - info->data = hp[0]; info->size = (size_t) strlen(info->data); } + if (tTd(28, 80)) + printf("hes_udb_get => %s\n", *hp); + return 0; } #endif /* HESIOD */ @@ -974,9 +1091,10 @@ hes_udb_get(key, info) #else /* not USERDB */ int -udbexpand(a, sendq, e) +udbexpand(a, sendq, aliaslevel, e) ADDRESS *a; ADDRESS **sendq; + int aliaslevel; ENVELOPE *e; { return EX_OK; diff --git a/usr.sbin/sendmail/src/usersmtp.c b/usr.sbin/sendmail/src/usersmtp.c index 2850def..6233e0f 100644 --- a/usr.sbin/sendmail/src/usersmtp.c +++ b/usr.sbin/sendmail/src/usersmtp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.18 (Berkeley) 1/24/94 (with SMTP)"; +static char sccsid[] = "@(#)usersmtp.c 8.65 (Berkeley) 9/28/95 (with SMTP)"; #else -static char sccsid[] = "@(#)usersmtp.c 8.18 (Berkeley) 1/24/94 (without SMTP)"; +static char sccsid[] = "@(#)usersmtp.c 8.65 (Berkeley) 9/28/95 (without SMTP)"; #endif #endif /* not lint */ @@ -63,9 +63,7 @@ char SmtpError[MAXLINE] = ""; /* save failure error messages */ int SmtpPid; /* pid of mailer */ bool SmtpNeedIntro; /* need "while talking" in transcript */ -#ifdef __STDC__ -extern smtpmessage(char *f, MAILER *m, MCI *mci, ...); -#endif +extern void smtpmessage __P((char *f, MAILER *m, MCI *mci, ...)); /* ** SMTPINIT -- initialize SMTP. ** @@ -83,6 +81,7 @@ extern smtpmessage(char *f, MAILER *m, MCI *mci, ...); ** creates connection and sends initial protocol. */ +void smtpinit(m, mci, e) struct mailer *m; register MCI *mci; @@ -105,6 +104,8 @@ smtpinit(m, mci, e) SmtpError[0] = '\0'; CurHostName = mci->mci_host; /* XXX UGLY XXX */ + if (CurHostName == NULL) + CurHostName = MyHostName; SmtpNeedIntro = TRUE; switch (mci->mci_state) { @@ -186,18 +187,16 @@ tryhelo: ** Check to see if we actually ended up talking to ourself. ** This means we didn't know about an alias or MX, or we managed ** to connect to an echo server. - ** - ** If this code remains at all, "CheckLoopBack" should be - ** a mailer flag. This is a MAYBENEXTRELEASE feature. */ p = strchr(&SmtpReplyBuffer[4], ' '); if (p != NULL) *p = '\0'; - if (CheckLoopBack && strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) + if (!bitnset(M_NOLOOPCHECK, m->m_flags) && + strcasecmp(&SmtpReplyBuffer[4], MyHostName) == 0) { - syserr("553 %s config error: mail loops back to myself", - MyHostName); + syserr("553 %s config error: mail loops back to me (MX problem?)", + mci->mci_host); mci->mci_exitstat = EX_CONFIG; mci->mci_errno = 0; smtpquit(m, mci, e); @@ -244,9 +243,9 @@ tryhelo: /* ** ESMTP_CHECK -- check to see if this implementation likes ESMTP protocol ** -** ** Parameters: ** line -- the response line. +** firstline -- set if this is the first line of the reply. ** m -- the mailer. ** mci -- the mailer connection info. ** e -- the envelope. @@ -256,23 +255,24 @@ tryhelo: */ void -esmtp_check(line, m, mci, e) +esmtp_check(line, firstline, m, mci, e) char *line; + bool firstline; MAILER *m; register MCI *mci; ENVELOPE *e; { - if (strlen(line) < 5) - return; - line += 4; - if (strncmp(line, "ESMTP ", 6) == 0) + if (strstr(line, "ESMTP") != NULL) mci->mci_flags |= MCIF_ESMTP; + if (strstr(line, "8BIT-OK") != NULL) + mci->mci_flags |= MCIF_8BITOK; } /* ** HELO_OPTIONS -- process the options on a HELO line. ** ** Parameters: ** line -- the response line. +** firstline -- set if this is the first line of the reply. ** m -- the mailer. ** mci -- the mailer connection info. ** e -- the envelope. @@ -282,15 +282,19 @@ esmtp_check(line, m, mci, e) */ void -helo_options(line, m, mci, e) +helo_options(line, firstline, m, mci, e) char *line; + bool firstline; MAILER *m; register MCI *mci; ENVELOPE *e; { register char *p; - if (strlen(line) < 5) + if (firstline) + return; + + if (strlen(line) < (SIZE_T) 5) return; line += 4; p = strchr(line, ' '); @@ -309,6 +313,8 @@ helo_options(line, m, mci, e) } else if (strcasecmp(line, "expn") == 0) mci->mci_flags |= MCIF_EXPN; + else if (strcasecmp(line, "dsn") == 0) + mci->mci_flags |= MCIF_DSN; } /* ** SMTPMAILFROM -- send MAIL command @@ -319,6 +325,7 @@ helo_options(line, m, mci, e) ** e -- the envelope (including the sender to specify). */ +int smtpmailfrom(m, mci, e) struct mailer *m; MCI *mci; @@ -326,7 +333,8 @@ smtpmailfrom(m, mci, e) { int r; char *bufp; - char buf[MAXNAME]; + char *bodytype; + char buf[MAXNAME + 1]; char optbuf[MAXLINE]; if (tTd(18, 2)) @@ -338,6 +346,64 @@ smtpmailfrom(m, mci, e) else strcpy(optbuf, ""); + bodytype = e->e_bodytype; + if (bitset(MCIF_8BITMIME, mci->mci_flags)) + { + if (bodytype == NULL && + bitset(MM_MIME8BIT, MimeMode) && + bitset(EF_HAS8BIT, e->e_flags) && + !bitset(EF_DONT_MIME, e->e_flags) && + !bitnset(M_8BITS, m->m_flags)) + bodytype = "8BITMIME"; + if (bodytype != NULL) + { + strcat(optbuf, " BODY="); + strcat(optbuf, bodytype); + } + } + else if (bitnset(M_8BITS, m->m_flags) || + !bitset(EF_HAS8BIT, e->e_flags) || + bitset(MCIF_8BITOK, mci->mci_flags)) + { + /* just pass it through */ + } +#if MIME8TO7 + else if (bitset(MM_CVTMIME, MimeMode) && + !bitset(EF_DONT_MIME, e->e_flags) && + (!bitset(MM_PASS8BIT, MimeMode) || + bitset(EF_IS_MIME, e->e_flags))) + { + /* must convert from 8bit MIME format to 7bit encoded */ + mci->mci_flags |= MCIF_CVT8TO7; + } +#endif + else if (!bitset(MM_PASS8BIT, MimeMode)) + { + /* cannot just send a 8-bit version */ + usrerr("%s does not support 8BITMIME", mci->mci_host); + mci->mci_status = "5.6.3"; + return EX_DATAERR; + } + + if (bitset(MCIF_DSN, mci->mci_flags)) + { + if (e->e_envid != NULL) + { + strcat(optbuf, " ENVID="); + strcat(optbuf, e->e_envid); + } + + /* RET= parameter */ + if (bitset(EF_RET_PARAM, e->e_flags)) + { + strcat(optbuf, " RET="); + if (bitset(EF_NO_BODY_RETN, e->e_flags)) + strcat(optbuf, "HDRS"); + else + strcat(optbuf, "FULL"); + } + } + /* ** Send the MAIL command. ** Designates the sender. @@ -349,7 +415,7 @@ smtpmailfrom(m, mci, e) !bitnset(M_NO_NULL_FROM, m->m_flags)) (void) strcpy(buf, ""); else - expand("\201g", buf, &buf[sizeof buf - 1], e); + expand("\201g", buf, sizeof buf, e); if (buf[0] == '<') { /* strip off <angle brackets> (put back on below) */ @@ -360,7 +426,7 @@ smtpmailfrom(m, mci, e) } else bufp = buf; - if (e->e_from.q_mailer == LocalMailer || + if (bitnset(M_LOCALMAILER, e->e_from.q_mailer->m_flags) || !bitnset(M_FROMPATH, m->m_flags)) { smtpmessage("MAIL From:<%s>%s", m, mci, bufp, optbuf); @@ -373,37 +439,57 @@ smtpmailfrom(m, mci, e) SmtpPhase = mci->mci_phase = "client MAIL"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_mail, NULL); - if (r < 0 || REPLYTYPE(r) == 4) + if (r < 0 || r == 421) { + /* communications failure/service shutting down */ mci->mci_exitstat = EX_TEMPFAIL; mci->mci_errno = errno; smtpquit(m, mci, e); return EX_TEMPFAIL; } - else if (r == 250) + else if (REPLYTYPE(r) == 4) + { + return EX_TEMPFAIL; + } + else if (REPLYTYPE(r) == 2) { - mci->mci_exitstat = EX_OK; return EX_OK; } + else if (r == 501) + { + /* syntax error in arguments */ + mci->mci_status = "5.5.2"; + return EX_DATAERR; + } + else if (r == 553) + { + /* mailbox name not allowed */ + mci->mci_status = "5.1.3"; + return EX_DATAERR; + } else if (r == 552) { - /* signal service unavailable */ - mci->mci_exitstat = EX_UNAVAILABLE; - smtpquit(m, mci, e); + /* exceeded storage allocation */ + mci->mci_status = "5.2.2"; + return EX_UNAVAILABLE; + } + else if (REPLYTYPE(r) == 5) + { + /* unknown error */ return EX_UNAVAILABLE; } #ifdef LOG if (LogLevel > 1) { - syslog(LOG_CRIT, "%s: SMTP MAIL protocol error: %s", - e->e_id, SmtpReplyBuffer); + syslog(LOG_CRIT, "%s: %.100s: SMTP MAIL protocol error: %s", + e->e_id, mci->mci_host, + shortenstring(SmtpReplyBuffer, 403)); } #endif /* protocol error -- close up */ smtpquit(m, mci, e); - mci->mci_exitstat = EX_PROTOCOL; return EX_PROTOCOL; } /* @@ -422,6 +508,7 @@ smtpmailfrom(m, mci, e) ** Sends the mail via SMTP. */ +int smtprcpt(to, m, mci, e) ADDRESS *to; register MAILER *m; @@ -429,30 +516,77 @@ smtprcpt(to, m, mci, e) ENVELOPE *e; { register int r; + char optbuf[MAXLINE]; + extern char *smtptodsn(); + + strcpy(optbuf, ""); + if (bitset(MCIF_DSN, mci->mci_flags)) + { + /* NOTIFY= parameter */ + if (bitset(QHASNOTIFY, to->q_flags) && + bitset(QPRIMARY, to->q_flags)) + { + bool firstone = TRUE; - smtpmessage("RCPT To:<%s>", m, mci, to->q_user); + strcat(optbuf, " NOTIFY="); + if (bitset(QPINGONSUCCESS, to->q_flags)) + { + strcat(optbuf, "SUCCESS"); + firstone = FALSE; + } + if (bitset(QPINGONFAILURE, to->q_flags)) + { + if (!firstone) + strcat(optbuf, ","); + strcat(optbuf, "FAILURE"); + firstone = FALSE; + } + if (bitset(QPINGONDELAY, to->q_flags)) + { + if (!firstone) + strcat(optbuf, ","); + strcat(optbuf, "DELAY"); + firstone = FALSE; + } + if (firstone) + strcat(optbuf, "NEVER"); + } + + /* ORCPT= parameter */ + if (to->q_orcpt != NULL) + { + strcat(optbuf, " ORCPT="); + strcat(optbuf, to->q_orcpt); + } + } + + smtpmessage("RCPT To:<%s>%s", m, mci, to->q_user, optbuf); SmtpPhase = mci->mci_phase = "client RCPT"; setproctitle("%s %s: %s", e->e_id, CurHostName, mci->mci_phase); r = reply(m, mci, e, TimeOuts.to_rcpt, NULL); + to->q_rstatus = newstr(SmtpReplyBuffer); + to->q_status = smtptodsn(r); + to->q_statmta = mci->mci_host; if (r < 0 || REPLYTYPE(r) == 4) - return (EX_TEMPFAIL); + return EX_TEMPFAIL; else if (REPLYTYPE(r) == 2) - return (EX_OK); + return EX_OK; else if (r == 550 || r == 551 || r == 553) - return (EX_NOUSER); - else if (r == 552 || r == 554) - return (EX_UNAVAILABLE); + return EX_NOUSER; + else if (REPLYTYPE(r) == 5) + return EX_UNAVAILABLE; #ifdef LOG if (LogLevel > 1) { - syslog(LOG_CRIT, "%s: SMTP RCPT protocol error: %s", - e->e_id, SmtpReplyBuffer); + syslog(LOG_CRIT, "%s: %.100s: SMTP RCPT protocol error: %s", + e->e_id, mci->mci_host, + shortenstring(SmtpReplyBuffer, 403)); } #endif - return (EX_PROTOCOL); + return EX_PROTOCOL; } /* ** SMTPDATA -- send the data and clean up the transaction. @@ -469,8 +603,9 @@ smtprcpt(to, m, mci, e) */ static jmp_buf CtxDataTimeout; -static int datatimeout(); +static void datatimeout(); +int smtpdata(m, mci, e) struct mailer *m; register MCI *mci; @@ -496,20 +631,21 @@ smtpdata(m, mci, e) if (r < 0 || REPLYTYPE(r) == 4) { smtpquit(m, mci, e); - return (EX_TEMPFAIL); + return EX_TEMPFAIL; } - else if (r == 554) + else if (REPLYTYPE(r) == 5) { smtprset(m, mci, e); - return (EX_UNAVAILABLE); + return EX_UNAVAILABLE; } else if (r != 354) { #ifdef LOG if (LogLevel > 1) { - syslog(LOG_CRIT, "%s: SMTP DATA-1 protocol error: %s", - e->e_id, SmtpReplyBuffer); + syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-1 protocol error: %s", + e->e_id, mci->mci_host, + shortenstring(SmtpReplyBuffer, 403)); } #endif smtprset(m, mci, e); @@ -533,16 +669,22 @@ smtpdata(m, mci, e) } timeout = e->e_msgsize / 16; - if (timeout < (time_t) 60) - timeout = (time_t) 60; - timeout += e->e_nrcpts * 90; + if (timeout < (time_t) 600) + timeout = (time_t) 600; + timeout += e->e_nrcpts * 300; ev = setevent(timeout, datatimeout, 0); - /* now output the actual message */ - (*e->e_puthdr)(mci, e); - putline("\n", mci); + /* + ** Output the actual message. + */ + + (*e->e_puthdr)(mci, e->e_header, e); (*e->e_putbody)(mci, e, NULL); + /* + ** Cleanup after sending message. + */ + clrevent(ev); if (ferror(mci->mci_out)) @@ -569,28 +711,31 @@ smtpdata(m, mci, e) if (r < 0) { smtpquit(m, mci, e); - return (EX_TEMPFAIL); + return EX_TEMPFAIL; } mci->mci_state = MCIS_OPEN; e->e_statmsg = newstr(&SmtpReplyBuffer[4]); if (REPLYTYPE(r) == 4) - return (EX_TEMPFAIL); - else if (r == 250) - return (EX_OK); - else if (r == 552 || r == 554) - return (EX_UNAVAILABLE); + return EX_TEMPFAIL; + else if (REPLYCLASS(r) != 5) + /* fall through */ ; + else if (REPLYTYPE(r) == 2) + return EX_OK; + else if (REPLYTYPE(r) == 5) + return EX_UNAVAILABLE; #ifdef LOG if (LogLevel > 1) { - syslog(LOG_CRIT, "%s: SMTP DATA-2 protocol error: %s", - e->e_id, SmtpReplyBuffer); + syslog(LOG_CRIT, "%s: %.100s: SMTP DATA-2 protocol error: %s", + e->e_id, mci->mci_host, + shortenstring(SmtpReplyBuffer, 403)); } #endif - return (EX_PROTOCOL); + return EX_PROTOCOL; } -static int +static void datatimeout() { longjmp(CtxDataTimeout, 1); @@ -608,6 +753,7 @@ datatimeout() ** sends the final protocol and closes the connection. */ +void smtpquit(m, mci, e) register MAILER *m; register MCI *mci; @@ -647,6 +793,7 @@ smtpquit(m, mci, e) ** SMTPRSET -- send a RSET (reset) command */ +void smtprset(m, mci, e) register MAILER *m; register MCI *mci; @@ -670,6 +817,7 @@ smtprset(m, mci, e) ** SMTPPROBE -- check the connection state */ +int smtpprobe(mci) register MCI *mci; { @@ -693,9 +841,8 @@ smtpprobe(mci) ** mci -- the mailer connection info structure. ** e -- the current envelope. ** timeout -- the timeout for reads. -** pfunc -- processing function for second and subsequent -** lines of response -- if null, no special -** processing is done. +** pfunc -- processing function called on each line of response. +** If null, no special processing is done. ** ** Returns: ** reply code it reads. @@ -704,6 +851,7 @@ smtpprobe(mci) ** flushes the mail file. */ +int reply(m, mci, e, timeout, pfunc) MAILER *m; MCI *mci; @@ -749,7 +897,6 @@ reply(m, mci, e, timeout, pfunc) if (p == NULL) { bool oldholderrs; - extern char MsgBuf[]; /* err.c */ /* if the remote end closed early, fake an error */ if (errno == 0) @@ -770,16 +917,18 @@ reply(m, mci, e, timeout, pfunc) pause(); mci->mci_state = MCIS_ERROR; smtpquit(m, mci, e); -#ifdef XDEBUG +#if XDEBUG { char wbuf[MAXLINE]; char *p = wbuf; + if (e->e_to != NULL) { - sprintf(p, "%s... ", e->e_to); + sprintf(p, "%s... ", + shortenstring(e->e_to, 203)); p += strlen(p); } - sprintf(p, "reply(%s) during %s", + sprintf(p, "reply(%.100s) during %s", mci->mci_host, SmtpPhase); checkfd012(wbuf); } @@ -815,8 +964,8 @@ reply(m, mci, e, timeout, pfunc) nmessage("050 %s", bufp); /* process the line */ - if (pfunc != NULL && !firstline) - (*pfunc)(bufp, m, mci, e); + if (pfunc != NULL) + (*pfunc)(bufp, firstline, m, mci, e); firstline = FALSE; @@ -871,6 +1020,7 @@ reply(m, mci, e, timeout, pfunc) */ /*VARARGS1*/ +void #ifdef __STDC__ smtpmessage(char *f, MAILER *m, MCI *mci, ...) #else @@ -884,7 +1034,7 @@ smtpmessage(f, m, mci, va_alist) VA_LOCAL_DECL VA_START(mci); - (void) vsprintf(SmtpMsgBuffer, f, ap); + (void) vsnprintf(SmtpMsgBuffer, sizeof SmtpMsgBuffer, f, ap); VA_END; if (tTd(18, 1) || Verbose) diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c index b7e1d14..eac336e 100644 --- a/usr.sbin/sendmail/src/util.c +++ b/usr.sbin/sendmail/src/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1983 Eric P. Allman + * Copyright (c) 1983, 1995 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.39.1.5 (Berkeley) 3/5/95"; +static char sccsid[] = "@(#)util.c 8.84 (Berkeley) 11/18/95"; #endif /* not lint */ # include "sendmail.h" @@ -57,6 +57,7 @@ static char sccsid[] = "@(#)util.c 8.39.1.5 (Berkeley) 3/5/95"; ** deliver */ +void stripquotes(s) char *s; { @@ -107,8 +108,7 @@ xalloc(sz) p = malloc((unsigned) sz); if (p == NULL) { - syserr("Out of memory!!"); - abort(); + syserr("!Out of memory!!"); /* exit(EX_UNAVAILABLE); */ } return (p); @@ -208,6 +208,7 @@ copyqueue(addr) ** prints av. */ +void printav(av) register char **av; { @@ -253,8 +254,9 @@ lower(c) ** output to stdout */ +void xputs(s) - register char *s; + register const char *s; { register int c; register struct metamac *mp; @@ -269,11 +271,20 @@ xputs(s) { if (!isascii(c)) { - if (c == MATCHREPL || c == MACROEXPAND) + if (c == MATCHREPL) { putchar('$'); continue; } + if (c == MACROEXPAND) + { + putchar('$'); + if (strchr("=~&?", *s) != NULL) + putchar(*s++); + if (bitset(0200, *s)) + printf("{%s}", macname(*s++ & 0377)); + continue; + } for (mp = MetaMacros; mp->metaname != '\0'; mp++) { if ((mp->metaval & 0377) == c) @@ -282,6 +293,12 @@ xputs(s) break; } } + if (c == MATCHCLASS || c == MATCHNCLASS) + { + if (!bitset(0200, *s)) + continue; + printf("{%s}", macname(*s++ & 0377)); + } if (mp->metaname != '\0') continue; (void) putchar('\\'); @@ -296,9 +313,6 @@ xputs(s) /* wasn't a meta-macro -- find another way to print it */ switch (c) { - case '\0': - continue; - case '\n': c = 'n'; break; @@ -316,6 +330,8 @@ xputs(s) (void) putchar(c ^ 0100); continue; } + (void) putchar('\\'); + (void) putchar(c); } (void) fflush(stdout); } @@ -336,6 +352,7 @@ xputs(s) ** parse */ +void makelower(p) register char *p; { @@ -365,6 +382,7 @@ makelower(p) ** none. */ +void buildfname(gecos, login, buf) register char *gecos; char *login; @@ -415,6 +433,8 @@ buildfname(gecos, login, buf) ** SFF_MUSTOWN -- "uid" must own this file. ** SFF_NOSLINK -- file cannot be a symbolic link. ** mode -- mode bits that must match. +** st -- if set, points to a stat structure that will +** get the stat info for the file. ** ** Returns: ** 0 if fn exists, is owned by uid, and matches mode. @@ -438,104 +458,195 @@ buildfname(gecos, login, buf) # define S_IXUSR (S_IEXEC) #endif +#define ST_MODE_NOFILE 0171147 /* unlikely to occur */ + int -safefile(fn, uid, gid, uname, flags, mode) +safefile(fn, uid, gid, uname, flags, mode, st) char *fn; uid_t uid; gid_t gid; char *uname; int flags; int mode; + struct stat *st; { register char *p; register struct group *gr = NULL; + int file_errno = 0; struct stat stbuf; + struct stat fstbuf; - if (tTd(54, 4)) + if (tTd(44, 4)) printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n", fn, uid, gid, flags, mode); errno = 0; + if (st == NULL) + st = &fstbuf; - for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/') + /* first check to see if the file exists at all */ +#ifdef HASLSTAT + if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st) + : stat(fn, st)) < 0) +#else + if (stat(fn, st) < 0) +#endif { - *p = '\0'; - if (stat(fn, &stbuf) < 0) - break; - if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + file_errno = errno; + } + else if (bitset(SFF_SETUIDOK, flags) && + !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) && + S_ISREG(st->st_mode)) + { + /* + ** If final file is setuid, run as the owner of that + ** file. Gotta be careful not to reveal anything too + ** soon here! + */ + +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISUID, st->st_mode)) +#else + if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0) +#endif { - if (bitset(S_IXOTH, stbuf.st_mode)) - continue; - break; + uid = st->st_uid; + uname = NULL; } - if (stbuf.st_uid == uid && bitset(S_IXUSR, stbuf.st_mode)) - continue; - if (stbuf.st_gid == gid && bitset(S_IXGRP, stbuf.st_mode)) - continue; -#ifndef NO_GROUP_SET - if (uname != NULL && - ((gr != NULL && gr->gr_gid == stbuf.st_gid) || - (gr = getgrgid(stbuf.st_gid)) != NULL)) - { - register char **gp; +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISGID, st->st_mode)) +#else + if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0) +#endif + gid = st->st_gid; + } - for (gp = gr->gr_mem; *gp != NULL; gp++) - if (strcmp(*gp, uname) == 0) - break; - if (*gp != NULL && bitset(S_IXGRP, stbuf.st_mode)) + if (!bitset(SFF_NOPATHCHECK, flags) || + (uid == 0 && !bitset(SFF_ROOTOK, flags))) + { + /* check the path to the file for acceptability */ + for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/') + { + *p = '\0'; + if (stat(fn, &stbuf) < 0) + break; + if (uid == 0 && bitset(S_IWGRP|S_IWOTH, stbuf.st_mode)) + message("051 WARNING: writable directory %s", + fn); + if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + { + if (bitset(S_IXOTH, stbuf.st_mode)) + continue; + break; + } + if (stbuf.st_uid == uid && + bitset(S_IXUSR, stbuf.st_mode)) continue; - } + if (stbuf.st_gid == gid && + bitset(S_IXGRP, stbuf.st_mode)) + continue; +#ifndef NO_GROUP_SET + if (uname != NULL && + ((gr != NULL && gr->gr_gid == stbuf.st_gid) || + (gr = getgrgid(stbuf.st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++) + if (strcmp(*gp, uname) == 0) + break; + if (gp != NULL && *gp != NULL && + bitset(S_IXGRP, stbuf.st_mode)) + continue; + } #endif - if (!bitset(S_IXOTH, stbuf.st_mode)) - break; + if (!bitset(S_IXOTH, stbuf.st_mode)) + break; + } + if (p != NULL) + { + int ret = errno; + + if (ret == 0) + ret = EACCES; + if (tTd(44, 4)) + printf("\t[dir %s] %s\n", fn, errstring(ret)); + *p = '/'; + return ret; + } } - if (p != NULL) - { - int ret = errno; - if (ret == 0) - ret = EACCES; - if (tTd(54, 4)) - printf("\t[dir %s] %s\n", fn, errstring(ret)); - *p = '/'; - return ret; - } + /* + ** If the target file doesn't exist, check the directory to + ** ensure that it is writable by this user. + */ -#ifdef HASLSTAT - if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, &stbuf) - : stat(fn, &stbuf)) < 0) -#else - if (stat(fn, &stbuf) < 0) -#endif + if (file_errno != 0) { - int ret = errno; + int ret = file_errno; - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\t%s\n", errstring(ret)); errno = 0; + if (!bitset(SFF_CREAT, flags)) + return ret; + + /* check to see if legal to create the file */ + p = strrchr(fn, '/'); + if (p == NULL) + return ENOTDIR; + *p = '\0'; + if (stat(fn, &stbuf) >= 0) + { + int md = S_IWRITE|S_IEXEC; + if (stbuf.st_uid != uid) + md >>= 6; + if ((stbuf.st_mode & md) != md) + errno = EACCES; + } + ret = errno; + if (tTd(44, 4)) + printf("\t[final dir %s uid %d mode %o] %s\n", + fn, stbuf.st_uid, stbuf.st_mode, + errstring(ret)); + *p = '/'; + st->st_mode = ST_MODE_NOFILE; return ret; } #ifdef S_ISLNK - if (bitset(SFF_NOSLINK, flags) && S_ISLNK(stbuf.st_mode)) + if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode)) { - if (tTd(54, 4)) - printf("\t[slink mode %o]\tEPERM\n", stbuf.st_mode); + if (tTd(44, 4)) + printf("\t[slink mode %o]\tEPERM\n", st->st_mode); return EPERM; } #endif + if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[non-reg mode %o]\tEPERM\n", st->st_mode); + return EPERM; + } + if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) && + bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[exec bits %o]\tEPERM]\n", st->st_mode); + return EPERM; + } if (uid == 0 && !bitset(SFF_ROOTOK, flags)) mode >>= 6; - else if (stbuf.st_uid != uid) + else if (st->st_uid != uid) { mode >>= 3; - if (stbuf.st_gid == gid) + if (st->st_gid == gid) ; #ifndef NO_GROUP_SET else if (uname != NULL && - ((gr != NULL && gr->gr_gid == stbuf.st_gid) || - (gr = getgrgid(stbuf.st_gid)) != NULL)) + ((gr != NULL && gr->gr_gid == st->st_gid) || + (gr = getgrgid(st->st_gid)) != NULL)) { register char **gp; @@ -549,22 +660,104 @@ safefile(fn, uid, gid, uname, flags, mode) else mode >>= 3; } - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\t[uid %d, stat %o, mode %o] ", - stbuf.st_uid, stbuf.st_mode, mode); - if ((stbuf.st_uid == uid || stbuf.st_uid == 0 || + st->st_uid, st->st_mode, mode); + if ((st->st_uid == uid || st->st_uid == 0 || !bitset(SFF_MUSTOWN, flags)) && - (stbuf.st_mode & mode) == mode) + (st->st_mode & mode) == mode) { - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\tOK\n"); return 0; } - if (tTd(54, 4)) + if (tTd(44, 4)) printf("\tEACCES\n"); return EACCES; } /* +** SAFEFOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as fopen. +*/ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +FILE * +safefopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + int sff; +{ + int rval; + FILE *fp; + int smode; + struct stat stb, sta; + + if (bitset(O_CREAT, omode)) + sff |= SFF_CREAT; + smode = 0; + switch (omode & O_ACCMODE) + { + case O_RDONLY: + smode = S_IREAD; + break; + + case O_WRONLY: + smode = S_IWRITE; + break; + + case O_RDWR: + smode = S_IREAD|S_IWRITE; + break; + + default: + smode = 0; + break; + } + if (bitset(SFF_OPENASROOT, sff)) + rval = safefile(fn, 0, 0, NULL, sff, smode, &stb); + else + rval = safefile(fn, RealUid, RealGid, RealUserName, + sff, smode, &stb); + if (rval != 0) + { + errno = rval; + return NULL; + } + if (stb.st_mode == ST_MODE_NOFILE) + omode |= O_EXCL; + + fp = dfopen(fn, omode, cmode); + if (fp == NULL) + return NULL; + if (bitset(O_EXCL, omode)) + return fp; + if (fstat(fileno(fp), &sta) < 0 || + sta.st_nlink != stb.st_nlink || + sta.st_dev != stb.st_dev || + sta.st_ino != stb.st_ino || + sta.st_uid != stb.st_uid || + sta.st_gid != stb.st_gid) + { + syserr("554 cannot open: file %s changed after open", fn); + fclose(fp); + errno = EPERM; + return NULL; + } + return fp; +} +/* ** FIXCRLF -- fix <CR><LF> in line. ** ** Looks for the <CR><LF> combination and turns it into the @@ -583,6 +776,7 @@ safefile(fn, uid, gid, uname, flags, mode) ** line is changed in place. */ +void fixcrlf(line, stripnl) char *line; bool stripnl; @@ -607,10 +801,6 @@ fixcrlf(line, stripnl) ** whatever), so this tries to get around it. */ -#ifndef O_ACCMODE -# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) -#endif - struct omodes { int mask; @@ -693,16 +883,46 @@ dfopen(filename, omode, cmode) ** output of l to fp. */ +void putline(l, mci) register char *l; register MCI *mci; { + putxline(l, mci, PXLF_MAPFROM); +} +/* +** PUTXLINE -- putline with flags bits. +** +** This routine always guarantees outputing a newline (or CRLF, +** as appropriate) at the end of the string. +** +** Parameters: +** l -- line to put. +** mci -- the mailer connection information. +** pxflags -- flag bits: +** PXLF_MAPFROM -- map From_ to >From_. +** PXLF_STRIP8BIT -- strip 8th bit. +** +** Returns: +** none +** +** Side Effects: +** output of l to fp. +*/ + +void +putxline(l, mci, pxflags) + register char *l; + register MCI *mci; + int pxflags; +{ register char *p; register char svchar; int slop = 0; /* strip out 0200 bits -- these can look like TELNET protocol */ - if (bitset(MCIF_7BIT, mci->mci_flags)) + if (bitset(MCIF_7BIT, mci->mci_flags) || + bitset(PXLF_STRIP8BIT, pxflags)) { for (p = l; (svchar = *p) != '\0'; ++p) if (bitset(0200, svchar)) @@ -734,6 +954,15 @@ putline(l, mci) if (TrafficLogFile != NULL) (void) putc('.', TrafficLogFile); } + else if (l[0] == 'F' && slop == 0 && + bitset(PXLF_MAPFROM, pxflags) && + strncmp(l, "From ", 5) == 0 && + bitnset(M_ESCFROM, mci->mci_mailer->m_flags)) + { + (void) putc('>', mci->mci_out); + if (TrafficLogFile != NULL) + (void) putc('>', TrafficLogFile); + } fputs(l, mci->mci_out); (void) putc('!', mci->mci_out); fputs(mci->mci_mailer->m_eol, mci->mci_out); @@ -776,6 +1005,7 @@ putline(l, mci) ** f is unlinked. */ +void xunlink(f) char *f; { @@ -806,13 +1036,14 @@ xunlink(f) ** fp is closed. */ +void xfclose(fp, a, b) FILE *fp; char *a, *b; { if (tTd(53, 99)) printf("xfclose(%x) %s %s\n", fp, a, b); -#ifdef XDEBUG +#if XDEBUG if (fileno(fp) == 1) syserr("xfclose(%s %s): fd = 1", a, b); #endif @@ -839,10 +1070,7 @@ xfclose(fp, a, b) */ static jmp_buf CtxReadTimeout; -static int readtimeout(); -static EVENT *GlobalTimeout = NULL; -static bool EnableTimeout = FALSE; -static int ReadProgress; +static void readtimeout(); char * sfgets(buf, siz, fp, timeout, during) @@ -868,22 +1096,19 @@ sfgets(buf, siz, fp, timeout, during) { # ifdef LOG syslog(LOG_NOTICE, - "timeout waiting for input from %s during %s\n", + "timeout waiting for input from %.100s during %s", CurHostName? CurHostName: "local", during); # endif errno = 0; usrerr("451 timeout waiting for input during %s", during); buf[0] = '\0'; -#ifdef XDEBUG +#if XDEBUG checkfd012(during); #endif return (NULL); } - if (GlobalTimeout == NULL) - ev = setevent(timeout, readtimeout, 0); - else - EnableTimeout = TRUE; + ev = setevent(timeout, readtimeout, 0); } /* try to read */ @@ -898,10 +1123,7 @@ sfgets(buf, siz, fp, timeout, during) } /* clear the event if it has not sprung */ - if (GlobalTimeout == NULL) - clrevent(ev); - else - EnableTimeout = FALSE; + clrevent(ev); /* clean up the books and exit */ LineNumber++; @@ -914,50 +1136,30 @@ sfgets(buf, siz, fp, timeout, during) } if (TrafficLogFile != NULL) fprintf(TrafficLogFile, "%05d <<< %s", getpid(), buf); - if (SevenBit) + if (SevenBitInput) + { for (p = buf; *p != '\0'; p++) *p &= ~0200; - return (buf); -} - -void -sfgetset(timeout) - time_t timeout; -{ - /* cancel pending timer */ - if (GlobalTimeout != NULL) - { - clrevent(GlobalTimeout); - GlobalTimeout = NULL; } - - /* schedule fresh one if so requested */ - if (timeout != 0) + else if (!HasEightBits) { - ReadProgress = LineNumber; - GlobalTimeout = setevent(timeout, readtimeout, timeout); + for (p = buf; *p != '\0'; p++) + { + if (bitset(0200, *p)) + { + HasEightBits = TRUE; + break; + } + } } + return (buf); } -static +static void readtimeout(timeout) time_t timeout; { - /* terminate if ordinary timeout */ - if (GlobalTimeout == NULL) - longjmp(CtxReadTimeout, 1); - - /* terminate if no progress was made -- reset state */ - if (EnableTimeout && (LineNumber <= ReadProgress)) - { - EnableTimeout = FALSE; - GlobalTimeout = NULL; - longjmp(CtxReadTimeout, 2); - } - - /* schedule a new timeout */ - GlobalTimeout = NULL; - sfgetset(timeout); + longjmp(CtxReadTimeout, 1); } /* ** FGETFOLDED -- like fgets, but know about folded lines. @@ -1033,7 +1235,9 @@ fgetfolded(buf, n, f) } if (p == bp) return (NULL); - *--p = '\0'; + if (p[-1] == '\n') + p--; + *p = '\0'; return (bp); } /* @@ -1095,6 +1299,7 @@ atobool(s) ** none. */ +int atooct(s) register char *s; { @@ -1241,10 +1446,11 @@ strcontainedin(a, b) ** none */ +void checkfd012(where) char *where; { -#ifdef XDEBUG +#if XDEBUG register int i; struct stat stbuf; @@ -1277,9 +1483,9 @@ checkfd012(where) ** none. */ -#include <netdb.h> #include <arpa/inet.h> +void printopenfds(logit) bool logit; { @@ -1299,18 +1505,22 @@ printopenfds(logit) ** logit -- if set, send output to syslog instead of stdout. */ +void dumpfd(fd, printclosed, logit) int fd; bool printclosed; bool logit; { - register struct hostent *hp; register char *p; + char *hp; char *fmtstr; - struct sockaddr_in sin; +#ifdef S_IFSOCK + SOCKADDR sa; +#endif auto int slen; struct stat st; char buf[200]; + extern char *hostnamebyanyaddr(); p = buf; sprintf(p, "%3d: ", fd); @@ -1341,26 +1551,30 @@ dumpfd(fd, printclosed, logit) case S_IFSOCK: sprintf(p, "SOCK "); p += strlen(p); - slen = sizeof sin; - if (getsockname(fd, (struct sockaddr *) &sin, &slen) < 0) - sprintf(p, "(badsock)"); + slen = sizeof sa; + if (getsockname(fd, &sa.sa, &slen) < 0) + sprintf(p, "(%s)", errstring(errno)); else { - hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); - sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) - : hp->h_name, ntohs(sin.sin_port)); + hp = hostnamebyanyaddr(&sa); + if (sa.sa.sa_family == AF_INET) + sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port)); + else + sprintf(p, "%s", hp); } p += strlen(p); sprintf(p, "->"); p += strlen(p); - slen = sizeof sin; - if (getpeername(fd, (struct sockaddr *) &sin, &slen) < 0) - sprintf(p, "(badsock)"); + slen = sizeof sa; + if (getpeername(fd, &sa.sa, &slen) < 0) + sprintf(p, "(%s)", errstring(errno)); else { - hp = gethostbyaddr((char *) &sin.sin_addr, slen, AF_INET); - sprintf(p, "%s/%d", hp == NULL ? inet_ntoa(sin.sin_addr) - : hp->h_name, ntohs(sin.sin_port)); + hp = hostnamebyanyaddr(&sa); + if (sa.sa.sa_family == AF_INET) + sprintf(p, "%s/%d", hp, ntohs(sa.sin.sin_port)); + else + sprintf(p, "%s", hp); } break; #endif @@ -1411,7 +1625,7 @@ defprint: printit: #ifdef LOG if (logit) - syslog(LOG_DEBUG, "%s", buf); + syslog(LOG_DEBUG, "%.800s", buf); else #endif printf("%s\n", buf); @@ -1436,7 +1650,7 @@ printit: char * shortenstring(s, m) - register char *s; + register const char *s; int m; { int l; @@ -1444,7 +1658,7 @@ shortenstring(s, m) l = strlen(s); if (l < m) - return s; + return (char *) s; if (m > MAXSHORTSTR) m = MAXSHORTSTR; else if (m < 10) @@ -1466,6 +1680,240 @@ shortenstring(s, m) return buf; } /* +** SHORTEN_HOSTNAME -- strip local domain information off of hostname. +** +** Parameters: +** host -- the host to shorten (stripped in place). +** +** Returns: +** none. +*/ + +void +shorten_hostname(host) + char host[]; +{ + register char *p; + char *mydom; + int i; + bool canon = FALSE; + + /* strip off final dot */ + p = &host[strlen(host) - 1]; + if (*p == '.') + { + *p = '\0'; + canon = TRUE; + } + + /* see if there is any domain at all -- if not, we are done */ + p = strchr(host, '.'); + if (p == NULL) + return; + + /* yes, we have a domain -- see if it looks like us */ + mydom = macvalue('m', CurEnv); + if (mydom == NULL) + mydom = ""; + i = strlen(++p); + if ((canon ? strcasecmp(p, mydom) : strncasecmp(p, mydom, i)) == 0 && + (mydom[i] == '.' || mydom[i] == '\0')) + *--p = '\0'; +} +/* +** PROG_OPEN -- open a program for reading +** +** Parameters: +** argv -- the argument list. +** pfd -- pointer to a place to store the file descriptor. +** e -- the current envelope. +** +** Returns: +** pid of the process -- -1 if it failed. +*/ + +int +prog_open(argv, pfd, e) + char **argv; + int *pfd; + ENVELOPE *e; +{ + int pid; + int i; + int saveerrno; + int fdv[2]; + char *p, *q; + char buf[MAXLINE + 1]; + extern int DtableSize; + + if (pipe(fdv) < 0) + { + syserr("%s: cannot create pipe for stdout", argv[0]); + return -1; + } + pid = fork(); + if (pid < 0) + { + syserr("%s: cannot fork", argv[0]); + close(fdv[0]); + close(fdv[1]); + return -1; + } + if (pid > 0) + { + /* parent */ + close(fdv[1]); + *pfd = fdv[0]; + return pid; + } + + /* child -- close stdin */ + close(0); + + /* stdout goes back to parent */ + close(fdv[0]); + if (dup2(fdv[1], 1) < 0) + { + syserr("%s: cannot dup2 for stdout", argv[0]); + _exit(EX_OSERR); + } + close(fdv[1]); + + /* stderr goes to transcript if available */ + if (e->e_xfp != NULL) + { + if (dup2(fileno(e->e_xfp), 2) < 0) + { + syserr("%s: cannot dup2 for stderr", argv[0]); + _exit(EX_OSERR); + } + } + + /* this process has no right to the queue file */ + if (e->e_lockfp != NULL) + close(fileno(e->e_lockfp)); + + /* run as default user */ + endpwent(); + setgid(DefGid); + setuid(DefUid); + + /* run in some directory */ + if (ProgMailer != NULL) + p = ProgMailer->m_execdir; + else + p = NULL; + for (; p != NULL; p = q) + { + q = strchr(p, ':'); + if (q != NULL) + *q = '\0'; + expand(p, buf, sizeof buf, e); + if (q != NULL) + *q++ = ':'; + if (buf[0] != '\0' && chdir(buf) >= 0) + break; + } + if (p == NULL) + { + /* backup directories */ + if (chdir("/tmp") < 0) + (void) chdir("/"); + } + + /* arrange for all the files to be closed */ + for (i = 3; i < DtableSize; i++) + { + register int j; + + if ((j = fcntl(i, F_GETFD, 0)) != -1) + (void) fcntl(i, F_SETFD, j | 1); + } + + /* now exec the process */ + execve(argv[0], (ARGV_T) argv, (ARGV_T) UserEnviron); + + /* woops! failed */ + saveerrno = errno; + syserr("%s: cannot exec", argv[0]); + if (transienterror(saveerrno)) + _exit(EX_OSERR); + _exit(EX_CONFIG); +} +/* +** GET_COLUMN -- look up a Column in a line buffer +** +** Parameters: +** line -- the raw text line to search. +** col -- the column number to fetch. +** delim -- the delimiter between columns. If null, +** use white space. +** buf -- the output buffer. +** +** Returns: +** buf if successful. +** NULL otherwise. +*/ + +char * +get_column(line, col, delim, buf) + char line[]; + int col; + char delim; + char buf[]; +{ + char *p; + char *begin, *end; + int i; + char delimbuf[3]; + + if (delim == '\0') + strcpy(delimbuf, "\n\t "); + else + { + delimbuf[0] = delim; + delimbuf[1] = '\0'; + } + + p = line; + if (*p == '\0') + return NULL; /* line empty */ + if (*p == delim && col == 0) + return NULL; /* first column empty */ + + begin = line; + + if (col == 0 && delim == '\0') + { + while (*begin && isspace(*begin)) + begin++; + } + + for (i = 0; i < col; i++) + { + if ((begin = strpbrk(begin, delimbuf)) == NULL) + return NULL; /* no such column */ + begin++; + if (delim == '\0') + { + while (*begin && isspace(*begin)) + begin++; + } + } + + end = strpbrk(begin, delimbuf); + if (end == NULL) + { + strcpy(buf, begin); + } + else + { + strncpy(buf, begin, end - begin); + buf[end - begin] = '\0'; + } + return buf; +} +/* ** CLEANSTRCPY -- copy string keeping out bogus characters ** ** Parameters: @@ -1517,8 +1965,8 @@ cleanstrcpy(t, f, l) char * denlstring(s, strict, logattacks) char *s; - int strict; - int logattacks; + bool strict; + bool logattacks; { register char *p; int l; @@ -1545,14 +1993,16 @@ denlstring(s, strict, logattacks) for (p = bp; (p = strchr(p, '\n')) != NULL; ) *p++ = ' '; +/* #ifdef LOG if (logattacks) { - syslog(LOG_NOTICE, "POSSIBLE ATTACK from %s: newline in string \"%s\"", + syslog(LOG_NOTICE, "POSSIBLE ATTACK from %.100s: newline in string \"%s\"", RealHostName == NULL ? "[UNKNOWN]" : RealHostName, - shortenstring(bp, 80)); + shortenstring(bp, 203)); } #endif +*/ return bp; } |