diff -urN qmail-1.03-orig/Makefile qmail-1.03/Makefile
--- qmail-1.03-orig/Makefile	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/Makefile	2003-10-07 17:24:42.000000000 -0400
@@ -136,6 +136,10 @@
 compile auto_usera.c
 	./compile auto_usera.c
 
+base64.o: \
+compile base64.c base64.h stralloc.h substdio.h str.h
+	./compile base64.c
+
 binm1: \
 binm1.sh conf-qmail
 	cat binm1.sh \
@@ -217,9 +221,9 @@
 
 case.a: \
 makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
-case_starts.o
+case_starts.o case_startb.o
 	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
-	case_lowers.o case_starts.o
+	case_lowers.o case_starts.o case_startb.o
 
 case_diffb.o: \
 compile case_diffb.c case.h
@@ -237,6 +241,10 @@
 compile case_lowers.c case.h
 	./compile case_lowers.c
 
+case_startb.o: \
+compile case_startb.c case.h
+	./compile case_startb.c
+
 case_starts.o: \
 compile case_starts.c case.h
 	./compile case_starts.c
@@ -810,6 +818,24 @@
 instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
 binm3 binm3+df
 
+libqmailio: \
+libqmailio.so libqmailio.a
+	/bin/true
+
+libqmailio.so: \
+libqmailio.c
+	$(CC) -O2 -fPIC -shared -Wl,-soname,libqmailio.so -o libqmailio.so libqmailio.c
+
+libqmailio.a: \
+libqmailio.c
+	$(CC) -O2 -c libqmailio.c ; ar r libqmailio.a libqmailio.o
+
+libqmailio_install: \
+libqmailio
+	/usr/bin/install -m 755 libqmailio.so /usr/lib
+	/usr/bin/install -m 644 libqmailio.a /usr/lib
+	ldconfig
+
 load: \
 make-load warn-auto.sh systype
 	( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
@@ -890,6 +916,38 @@
 readwrite.h open.h headerbody.h maildir.h strerr.h
 	./compile maildirwatch.c
 
+maildirgetquota.o: \
+compile maildirgetquota.c maildirgetquota.h maildirmisc.h
+	./compile maildirgetquota.c
+
+maildirflags.o: \
+compile maildirflags.c
+	./compile maildirflags.c
+
+maildiropen.o: \
+compile maildiropen.c maildirmisc.h
+	./compile maildiropen.c
+
+maildirparsequota.o: \
+compile maildirparsequota.c
+	./compile maildirparsequota.c
+
+maildirquota.o: \
+compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
+	./compile maildirquota.c
+
+overmaildirquota.o: \
+compile overmaildirquota.c 
+	./compile overmaildirquota.c
+
+strtimet.o: \
+compile strtimet.c 
+	./compile strtimet.c
+
+strpidt.o: \
+compile strpidt.c 
+	./compile strpidt.c
+
 mailsubj: \
 warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh mailsubj.sh \
@@ -913,6 +971,9 @@
 	cat auto-ccld.sh make-load.sh > make-load
 	chmod 755 make-load
 
+make-load.sh: \
+libqmailio_install
+
 make-makelib: \
 make-makelib.sh auto-ccld.sh
 	cat auto-ccld.sh make-makelib.sh > make-makelib
@@ -1174,12 +1235,15 @@
 load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
 slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
 wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
-fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
+maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
+strtimet.o strpidt.o
 	./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
 	slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
 	lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
 	substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
-	auto_patrn.o  `cat socket.lib`
+	auto_patrn.o  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
 
 qmail-local.0: \
 qmail-local.8
@@ -1269,11 +1333,13 @@
 qmail-pop3d: \
 load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
 maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
-stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
+maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
 	./load qmail-pop3d commands.o case.a timeoutread.o \
 	timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
 	open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
-	fs.a  `cat socket.lib`
+	fs.a  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
 
 qmail-pop3d.0: \
 qmail-pop3d.8
@@ -1444,6 +1510,7 @@
 substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
 	./load qmail-remote control.o constmap.o timeoutread.o \
 	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
+	tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
 	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
 	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
 	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
@@ -1483,12 +1550,12 @@
 trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
 datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
 lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-auto_split.o
+auto_split.o env.a
 	./load qmail-send qsutil.o control.o constmap.o newfield.o \
 	prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
 	qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
 	wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o 
+	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
 
 qmail-send.0: \
 qmail-send.8
@@ -1535,14 +1602,16 @@
 load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
-open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
-fs.a auto_qmail.o socket.lib
+open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a auto_qmail.o base64.o socket.lib dns.o dns.lib
 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
 	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+	tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
-	socket.lib`
+	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \
+	socket.lib` -L`head -1 conf-vpopmail`/lib `head -1 conf-vpop-ld` \
+	-L/usr/lib/mysql  -lmysqlclient -lz dns.o `cat dns.lib`
 
 qmail-smtpd.0: \
 qmail-smtpd.8
@@ -1553,8 +1622,9 @@
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
-exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
-	./compile qmail-smtpd.c
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h wait.h \
+fd.h base64.h
+	./compile qmail-smtpd.c -I`head -1 conf-vpopmail`/include
 
 qmail-start: \
 load qmail-start.o prot.o fd.a auto_uids.o
@@ -2108,6 +2178,19 @@
 compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
 	./compile timeoutwrite.c
 
+qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
+qmail-remote: tls.o ssl_timeoutio.o
+qmail-smtpd.o: tls.h ssl_timeoutio.h
+qmail-remote.o: tls.h ssl_timeoutio.h
+
+tls.o: \
+compile tls.c exit.h error.h
+	./compile tls.c
+
+ssl_timeoutio.o: \
+compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
+	./compile ssl_timeoutio.c
+
 token822.o: \
 compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
 gen_alloc.h gen_allocdefs.h
@@ -2139,3 +2222,13 @@
 wait_pid.o: \
 compile wait_pid.c error.h haswaitp.h
 	./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+	@$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail Makefile-cert.mk
+	@cat Makefile-cert.mk \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
diff -urN qmail-1.03-orig/Makefile-cert.mk qmail-1.03/Makefile-cert.mk
--- qmail-1.03-orig/Makefile-cert.mk	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/Makefile-cert.mk	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,21 @@
+cert-req: req.pem
+cert cert-req: QMAIL/control/clientcert.pem
+	@:
+
+QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
+	ln -s $< $@
+
+QMAIL/control/servercert.pem:
+	PATH=$$PATH:/usr/local/ssl/bin \
+		openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
+	chmod 640 $@
+	chown qmaild.qmail $@
+
+req.pem:
+	PATH=$$PATH:/usr/local/ssl/bin openssl req \
+		-new -nodes -out $@ -keyout QMAIL/control/servercert.pem
+	chmod 640 QMAIL/control/servercert.pem
+	chown qmaild.qmail QMAIL/control/servercert.pem
+	@echo
+	@echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
+	@echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
diff -urN qmail-1.03-orig/Makefile.orig qmail-1.03/Makefile.orig
--- qmail-1.03-orig/Makefile.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/Makefile.orig	2003-10-07 17:22:01.000000000 -0400
@@ -0,0 +1,2230 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+SHELL=/bin/sh
+
+default: it
+
+addresses.0: \
+addresses.5
+	nroff -man addresses.5 > addresses.0
+
+alloc.a: \
+makelib alloc.o alloc_re.o
+	./makelib alloc.a alloc.o alloc_re.o
+
+alloc.o: \
+compile alloc.c alloc.h error.h
+	./compile alloc.c
+
+alloc_re.o: \
+compile alloc_re.c alloc.h byte.h
+	./compile alloc_re.c
+
+auto-ccld.sh: \
+conf-cc conf-ld warn-auto.sh
+	( cat warn-auto.sh; \
+	echo CC=\'`head -1 conf-cc`\'; \
+	echo LD=\'`head -1 conf-ld`\' \
+	) > auto-ccld.sh
+
+auto-gid: \
+load auto-gid.o substdio.a error.a str.a fs.a
+	./load auto-gid substdio.a error.a str.a fs.a 
+
+auto-gid.o: \
+compile auto-gid.c subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+	./compile auto-gid.c
+
+auto-int: \
+load auto-int.o substdio.a error.a str.a fs.a
+	./load auto-int substdio.a error.a str.a fs.a 
+
+auto-int.o: \
+compile auto-int.c substdio.h readwrite.h exit.h scan.h fmt.h
+	./compile auto-int.c
+
+auto-int8: \
+load auto-int8.o substdio.a error.a str.a fs.a
+	./load auto-int8 substdio.a error.a str.a fs.a 
+
+auto-int8.o: \
+compile auto-int8.c substdio.h readwrite.h exit.h scan.h fmt.h
+	./compile auto-int8.c
+
+auto-str: \
+load auto-str.o substdio.a error.a str.a
+	./load auto-str substdio.a error.a str.a 
+
+auto-str.o: \
+compile auto-str.c substdio.h readwrite.h exit.h
+	./compile auto-str.c
+
+auto-uid: \
+load auto-uid.o substdio.a error.a str.a fs.a
+	./load auto-uid substdio.a error.a str.a fs.a 
+
+auto-uid.o: \
+compile auto-uid.c subfd.h substdio.h substdio.h readwrite.h exit.h \
+scan.h fmt.h
+	./compile auto-uid.c
+
+auto_break.c: \
+auto-str conf-break
+	./auto-str auto_break \
+	"`head -1 conf-break`" > auto_break.c
+
+auto_break.o: \
+compile auto_break.c
+	./compile auto_break.c
+
+auto_patrn.c: \
+auto-int8 conf-patrn
+	./auto-int8 auto_patrn `head -1 conf-patrn` > auto_patrn.c
+
+auto_patrn.o: \
+compile auto_patrn.c
+	./compile auto_patrn.c
+
+auto_qmail.c: \
+auto-str conf-qmail
+	./auto-str auto_qmail `head -1 conf-qmail` > auto_qmail.c
+
+auto_qmail.o: \
+compile auto_qmail.c
+	./compile auto_qmail.c
+
+auto_spawn.c: \
+auto-int conf-spawn
+	./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c
+
+auto_spawn.o: \
+compile auto_spawn.c
+	./compile auto_spawn.c
+
+auto_split.c: \
+auto-int conf-split
+	./auto-int auto_split `head -1 conf-split` > auto_split.c
+
+auto_split.o: \
+compile auto_split.c
+	./compile auto_split.c
+
+auto_uids.c: \
+auto-uid auto-gid conf-users conf-groups
+	( ./auto-uid auto_uida `head -1 conf-users` \
+	&&./auto-uid auto_uidd `head -2 conf-users | tail -1` \
+	&&./auto-uid auto_uidl `head -3 conf-users | tail -1` \
+	&&./auto-uid auto_uido `head -4 conf-users | tail -1` \
+	&&./auto-uid auto_uidp `head -5 conf-users | tail -1` \
+	&&./auto-uid auto_uidq `head -6 conf-users | tail -1` \
+	&&./auto-uid auto_uidr `head -7 conf-users | tail -1` \
+	&&./auto-uid auto_uids `head -8 conf-users | tail -1` \
+	&&./auto-gid auto_gidq `head -1 conf-groups` \
+	&&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \
+	) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c
+
+auto_uids.o: \
+compile auto_uids.c
+	./compile auto_uids.c
+
+auto_usera.c: \
+auto-str conf-users
+	./auto-str auto_usera `head -1 conf-users` > auto_usera.c
+
+auto_usera.o: \
+compile auto_usera.c
+	./compile auto_usera.c
+
+base64.o: \
+compile base64.c base64.h stralloc.h substdio.h str.h
+	./compile base64.c
+
+binm1: \
+binm1.sh conf-qmail
+	cat binm1.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm1
+	chmod 755 binm1
+
+binm1+df: \
+binm1+df.sh conf-qmail
+	cat binm1+df.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm1+df
+	chmod 755 binm1+df
+
+binm2: \
+binm2.sh conf-qmail
+	cat binm2.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm2
+	chmod 755 binm2
+
+binm2+df: \
+binm2+df.sh conf-qmail
+	cat binm2+df.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm2+df
+	chmod 755 binm2+df
+
+binm3: \
+binm3.sh conf-qmail
+	cat binm3.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm3
+	chmod 755 binm3
+
+binm3+df: \
+binm3+df.sh conf-qmail
+	cat binm3+df.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> binm3+df
+	chmod 755 binm3+df
+
+bouncesaying: \
+load bouncesaying.o strerr.a error.a substdio.a str.a wait.a
+	./load bouncesaying strerr.a error.a substdio.a str.a \
+	wait.a 
+
+bouncesaying.0: \
+bouncesaying.1
+	nroff -man bouncesaying.1 > bouncesaying.0
+
+bouncesaying.o: \
+compile bouncesaying.c fork.h strerr.h error.h wait.h sig.h exit.h
+	./compile bouncesaying.c
+
+byte_chr.o: \
+compile byte_chr.c byte.h
+	./compile byte_chr.c
+
+byte_copy.o: \
+compile byte_copy.c byte.h
+	./compile byte_copy.c
+
+byte_cr.o: \
+compile byte_cr.c byte.h
+	./compile byte_cr.c
+
+byte_diff.o: \
+compile byte_diff.c byte.h
+	./compile byte_diff.c
+
+byte_rchr.o: \
+compile byte_rchr.c byte.h
+	./compile byte_rchr.c
+
+byte_zero.o: \
+compile byte_zero.c byte.h
+	./compile byte_zero.c
+
+case.a: \
+makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
+case_starts.o
+	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
+	case_lowers.o case_starts.o
+
+case_diffb.o: \
+compile case_diffb.c case.h
+	./compile case_diffb.c
+
+case_diffs.o: \
+compile case_diffs.c case.h
+	./compile case_diffs.c
+
+case_lowerb.o: \
+compile case_lowerb.c case.h
+	./compile case_lowerb.c
+
+case_lowers.o: \
+compile case_lowers.c case.h
+	./compile case_lowers.c
+
+case_starts.o: \
+compile case_starts.c case.h
+	./compile case_starts.c
+
+cdb.a: \
+makelib cdb_hash.o cdb_unpack.o cdb_seek.o
+	./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o
+
+cdb_hash.o: \
+compile cdb_hash.c cdb.h uint32.h
+	./compile cdb_hash.c
+
+cdb_seek.o: \
+compile cdb_seek.c cdb.h uint32.h
+	./compile cdb_seek.c
+
+cdb_unpack.o: \
+compile cdb_unpack.c cdb.h uint32.h
+	./compile cdb_unpack.c
+
+cdbmake.a: \
+makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o
+	./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \
+	cdbmake_add.o
+
+cdbmake_add.o: \
+compile cdbmake_add.c cdbmake.h uint32.h
+	./compile cdbmake_add.c
+
+cdbmake_hash.o: \
+compile cdbmake_hash.c cdbmake.h uint32.h
+	./compile cdbmake_hash.c
+
+cdbmake_pack.o: \
+compile cdbmake_pack.c cdbmake.h uint32.h
+	./compile cdbmake_pack.c
+
+cdbmss.o: \
+compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+	./compile cdbmss.c
+
+check: \
+it man
+	./instcheck
+
+chkshsgr: \
+load chkshsgr.o
+	./load chkshsgr 
+
+chkshsgr.o: \
+compile chkshsgr.c exit.h
+	./compile chkshsgr.c
+
+chkspawn: \
+load chkspawn.o substdio.a error.a str.a fs.a auto_spawn.o
+	./load chkspawn substdio.a error.a str.a fs.a auto_spawn.o 
+
+chkspawn.o: \
+compile chkspawn.c substdio.h subfd.h substdio.h fmt.h select.h \
+exit.h auto_spawn.h
+	./compile chkspawn.c
+
+clean: \
+TARGETS
+	rm -f `cat TARGETS`
+
+coe.o: \
+compile coe.c coe.h
+	./compile coe.c
+
+commands.o: \
+compile commands.c commands.h substdio.h stralloc.h gen_alloc.h str.h \
+case.h
+	./compile commands.c
+
+compile: \
+make-compile warn-auto.sh systype
+	( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \
+	compile
+	chmod 755 compile
+
+condredirect: \
+load condredirect.o qmail.o strerr.a fd.a sig.a wait.a seek.a env.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+	./load condredirect qmail.o strerr.a fd.a sig.a wait.a \
+	seek.a env.a substdio.a error.a str.a fs.a auto_qmail.o 
+
+condredirect.0: \
+condredirect.1
+	nroff -man condredirect.1 > condredirect.0
+
+condredirect.o: \
+compile condredirect.c sig.h readwrite.h exit.h env.h error.h fork.h \
+wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h
+	./compile condredirect.c
+
+config: \
+warn-auto.sh config.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh config.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> config
+	chmod 755 config
+
+config-fast: \
+warn-auto.sh config-fast.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh config-fast.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> config-fast
+	chmod 755 config-fast
+
+constmap.o: \
+compile constmap.c constmap.h alloc.h case.h
+	./compile constmap.c
+
+control.o: \
+compile control.c readwrite.h open.h getln.h stralloc.h gen_alloc.h \
+substdio.h error.h control.h alloc.h scan.h
+	./compile control.c
+
+date822fmt.o: \
+compile date822fmt.c datetime.h fmt.h date822fmt.h
+	./compile date822fmt.c
+
+datemail: \
+warn-auto.sh datemail.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh datemail.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> datemail
+	chmod 755 datemail
+
+datetime.a: \
+makelib datetime.o datetime_un.o
+	./makelib datetime.a datetime.o datetime_un.o
+
+datetime.o: \
+compile datetime.c datetime.h
+	./compile datetime.c
+
+datetime_un.o: \
+compile datetime_un.c datetime.h
+	./compile datetime_un.c
+
+direntry.h: \
+compile trydrent.c direntry.h1 direntry.h2
+	( ./compile trydrent.c >/dev/null 2>&1 \
+	&& cat direntry.h2 || cat direntry.h1 ) > direntry.h
+	rm -f trydrent.o
+
+dns.lib: \
+tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \
+alloc.a error.a fs.a str.a
+	( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
+	ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+	-lresolv `cat socket.lib` ) >/dev/null 2>&1 \
+	&& echo -lresolv || exit 0 ) > dns.lib
+	rm -f tryrsolv.o tryrsolv
+
+dns.o: \
+compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
+stralloc.h gen_alloc.h dns.h case.h
+	./compile dns.c
+
+dnscname: \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnscname.o: \
+compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h
+	./compile dnscname.c
+
+dnsdoe.o: \
+compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h
+	./compile dnsdoe.c
+
+dnsfq: \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsfq.o: \
+compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+	./compile dnsfq.c
+
+dnsip: \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsip.o: \
+compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+	./compile dnsip.c
+
+dnsmxip: \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a  `cat \
+	dns.lib` `cat socket.lib`
+
+dnsmxip.o: \
+compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \
+now.h datetime.h exit.h
+	./compile dnsmxip.c
+
+dnsptr: \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsptr.o: \
+compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnsptr.c
+
+dot-qmail.0: \
+dot-qmail.5
+	nroff -man dot-qmail.5 > dot-qmail.0
+
+dot-qmail.5: \
+dot-qmail.9 conf-break conf-spawn
+	cat dot-qmail.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> dot-qmail.5
+
+elq: \
+warn-auto.sh elq.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh elq.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> elq
+	chmod 755 elq
+
+env.a: \
+makelib env.o envread.o
+	./makelib env.a env.o envread.o
+
+env.o: \
+compile env.c str.h alloc.h env.h
+	./compile env.c
+
+envelopes.0: \
+envelopes.5
+	nroff -man envelopes.5 > envelopes.0
+
+envread.o: \
+compile envread.c env.h str.h
+	./compile envread.c
+
+error.a: \
+makelib error.o error_str.o error_temp.o
+	./makelib error.a error.o error_str.o error_temp.o
+
+error.o: \
+compile error.c error.h
+	./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+	./compile error_str.c
+
+error_temp.o: \
+compile error_temp.c error.h
+	./compile error_temp.c
+
+except: \
+load except.o strerr.a error.a substdio.a str.a wait.a
+	./load except strerr.a error.a substdio.a str.a wait.a 
+
+except.0: \
+except.1
+	nroff -man except.1 > except.0
+
+except.o: \
+compile except.c fork.h strerr.h wait.h error.h exit.h
+	./compile except.c
+
+fd.a: \
+makelib fd_copy.o fd_move.o
+	./makelib fd.a fd_copy.o fd_move.o
+
+fd_copy.o: \
+compile fd_copy.c fd.h
+	./compile fd_copy.c
+
+fd_move.o: \
+compile fd_move.c fd.h
+	./compile fd_move.c
+
+fifo.o: \
+compile fifo.c hasmkffo.h fifo.h
+	./compile fifo.c
+
+find-systype: \
+find-systype.sh auto-ccld.sh
+	cat auto-ccld.sh find-systype.sh > find-systype
+	chmod 755 find-systype
+
+fmt_str.o: \
+compile fmt_str.c fmt.h
+	./compile fmt_str.c
+
+fmt_strn.o: \
+compile fmt_strn.c fmt.h
+	./compile fmt_strn.c
+
+fmt_uint.o: \
+compile fmt_uint.c fmt.h
+	./compile fmt_uint.c
+
+fmt_uint0.o: \
+compile fmt_uint0.c fmt.h
+	./compile fmt_uint0.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+	./compile fmt_ulong.c
+
+fmtqfn.o: \
+compile fmtqfn.c fmtqfn.h fmt.h auto_split.h
+	./compile fmtqfn.c
+
+forgeries.0: \
+forgeries.7
+	nroff -man forgeries.7 > forgeries.0
+
+fork.h: \
+compile load tryvfork.c fork.h1 fork.h2
+	( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \
+	2>&1 \
+	&& cat fork.h2 || cat fork.h1 ) > fork.h
+	rm -f tryvfork.o tryvfork
+
+forward: \
+load forward.o qmail.o strerr.a alloc.a fd.a wait.a sig.a env.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+	./load forward qmail.o strerr.a alloc.a fd.a wait.a sig.a \
+	env.a substdio.a error.a str.a fs.a auto_qmail.o 
+
+forward.0: \
+forward.1
+	nroff -man forward.1 > forward.0
+
+forward.o: \
+compile forward.c sig.h readwrite.h exit.h env.h qmail.h substdio.h \
+strerr.h substdio.h fmt.h
+	./compile forward.c
+
+fs.a: \
+makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \
+scan_ulong.o scan_8long.o
+	./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \
+	fmt_ulong.o scan_ulong.o scan_8long.o
+
+getln.a: \
+makelib getln.o getln2.o
+	./makelib getln.a getln.o getln2.o
+
+getln.o: \
+compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h
+	./compile getln.c
+
+getln2.o: \
+compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h
+	./compile getln2.c
+
+getopt.a: \
+makelib subgetopt.o sgetopt.o
+	./makelib getopt.a subgetopt.o sgetopt.o
+
+gfrom.o: \
+compile gfrom.c str.h gfrom.h
+	./compile gfrom.c
+
+hasflock.h: \
+tryflock.c compile load
+	( ( ./compile tryflock.c && ./load tryflock ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASFLOCK 1 || exit 0 ) > hasflock.h
+	rm -f tryflock.o tryflock
+
+hasmkffo.h: \
+trymkffo.c compile load
+	( ( ./compile trymkffo.c && ./load trymkffo ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASMKFIFO 1 || exit 0 ) > hasmkffo.h
+	rm -f trymkffo.o trymkffo
+
+hasnpbg1.h: \
+trynpbg1.c compile load open.h open.a fifo.h fifo.o select.h
+	( ( ./compile trynpbg1.c \
+	&& ./load trynpbg1 fifo.o open.a && ./trynpbg1 ) \
+	>/dev/null 2>&1 \
+	&& echo \#define HASNAMEDPIPEBUG1 1 || exit 0 ) > \
+	hasnpbg1.h
+	rm -f trynpbg1.o trynpbg1
+
+hassalen.h: \
+trysalen.c compile
+	( ./compile trysalen.c >/dev/null 2>&1 \
+	&& echo \#define HASSALEN 1 || exit 0 ) > hassalen.h
+	rm -f trysalen.o
+
+hassgact.h: \
+trysgact.c compile load
+	( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h
+	rm -f trysgact.o trysgact
+
+hassgprm.h: \
+trysgprm.c compile load
+	( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h
+	rm -f trysgprm.o trysgprm
+
+hasshsgr.h: \
+chkshsgr warn-shsgr tryshsgr.c compile load
+	./chkshsgr || ( cat warn-shsgr; exit 1 )
+	( ( ./compile tryshsgr.c \
+	&& ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \
+	&& echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \
+	hasshsgr.h
+	rm -f tryshsgr.o tryshsgr
+
+haswaitp.h: \
+trywaitp.c compile load
+	( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h
+	rm -f trywaitp.o trywaitp
+
+headerbody.o: \
+compile headerbody.c stralloc.h gen_alloc.h substdio.h getln.h \
+hfield.h headerbody.h
+	./compile headerbody.c
+
+hfield.o: \
+compile hfield.c hfield.h
+	./compile hfield.c
+
+hier.o: \
+compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h
+	./compile hier.c
+
+home: \
+home.sh conf-qmail
+	cat home.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> home
+	chmod 755 home
+
+home+df: \
+home+df.sh conf-qmail
+	cat home+df.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> home+df
+	chmod 755 home+df
+
+hostname: \
+load hostname.o substdio.a error.a str.a dns.lib socket.lib
+	./load hostname substdio.a error.a str.a  `cat dns.lib` \
+	`cat socket.lib`
+
+hostname.o: \
+compile hostname.c substdio.h subfd.h substdio.h readwrite.h exit.h
+	./compile hostname.c
+
+idedit: \
+load idedit.o strerr.a substdio.a error.a str.a fs.a wait.a open.a \
+seek.a
+	./load idedit strerr.a substdio.a error.a str.a fs.a \
+	wait.a open.a seek.a 
+
+idedit.o: \
+compile idedit.c readwrite.h exit.h scan.h fmt.h strerr.h open.h \
+seek.h fork.h
+	./compile idedit.c
+
+install: \
+load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
+strerr.a substdio.a open.a error.a str.a fs.a
+	./load install fifo.o hier.o auto_qmail.o auto_split.o \
+	auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a 
+
+install-big: \
+load install-big.o fifo.o install.o auto_qmail.o auto_split.o \
+auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a
+	./load install-big fifo.o install.o auto_qmail.o \
+	auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \
+	str.a fs.a 
+
+install-big.o: \
+compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \
+fifo.h
+	./compile install-big.c
+
+install.o: \
+compile install.c substdio.h strerr.h error.h open.h readwrite.h \
+exit.h
+	./compile install.c
+
+instcheck: \
+load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
+strerr.a substdio.a error.a str.a fs.a
+	./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \
+	auto_uids.o strerr.a substdio.a error.a str.a fs.a 
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+	./compile instcheck.c
+
+ip.o: \
+compile ip.c fmt.h scan.h ip.h
+	./compile ip.c
+
+ipalloc.o: \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+gen_alloc.h
+	./compile ipalloc.c
+
+ipme.o: \
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+	./compile ipme.c
+
+ipmeprint: \
+load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
+error.a str.a fs.a socket.lib
+	./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a  `cat socket.lib`
+
+ipmeprint.o: \
+compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
+ipalloc.h ip.h gen_alloc.h exit.h
+	./compile ipmeprint.c
+
+it: \
+qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \
+qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \
+predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
+qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
+qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
+qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
+dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
+forward preline condredirect bouncesaying except maildirmake \
+maildir2mbox maildirwatch qail elq pinq idedit install-big install \
+instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
+binm3 binm3+df
+
+libqmailio: \
+libqmailio.so libqmailio.a
+	/bin/true
+
+libqmailio.so: \
+libqmailio.c
+	$(CC) -O2 -fPIC -shared -Wl,-soname,libqmailio.so -o libqmailio.so libqmailio.c
+
+libqmailio.a: \
+libqmailio.c
+	$(CC) -O2 -c libqmailio.c ; ar r libqmailio.a libqmailio.o
+
+libqmailio_install: \
+libqmailio
+	/usr/bin/install -m 755 libqmailio.so /usr/lib
+	/usr/bin/install -m 644 libqmailio.a /usr/lib
+	ldconfig
+
+load: \
+make-load warn-auto.sh systype
+	( cat warn-auto.sh; ./make-load "`cat systype`" ) > load
+	chmod 755 load
+
+lock.a: \
+makelib lock_ex.o lock_exnb.o lock_un.o
+	./makelib lock.a lock_ex.o lock_exnb.o lock_un.o
+
+lock_ex.o: \
+compile lock_ex.c hasflock.h lock.h
+	./compile lock_ex.c
+
+lock_exnb.o: \
+compile lock_exnb.c hasflock.h lock.h
+	./compile lock_exnb.c
+
+lock_un.o: \
+compile lock_un.c hasflock.h lock.h
+	./compile lock_un.c
+
+maildir.0: \
+maildir.5
+	nroff -man maildir.5 > maildir.0
+
+maildir.o: \
+compile maildir.c prioq.h datetime.h gen_alloc.h env.h stralloc.h \
+gen_alloc.h direntry.h datetime.h now.h datetime.h str.h maildir.h \
+strerr.h
+	./compile maildir.c
+
+maildir2mbox: \
+load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a fs.a datetime.a
+	./load maildir2mbox maildir.o prioq.o now.o myctime.o \
+	gfrom.o lock.a getln.a env.a open.a strerr.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a datetime.a 
+
+maildir2mbox.0: \
+maildir2mbox.1
+	nroff -man maildir2mbox.1 > maildir2mbox.0
+
+maildir2mbox.o: \
+compile maildir2mbox.c readwrite.h prioq.h datetime.h gen_alloc.h \
+env.h stralloc.h gen_alloc.h subfd.h substdio.h substdio.h getln.h \
+error.h open.h lock.h gfrom.h str.h exit.h myctime.h maildir.h \
+strerr.h
+	./compile maildir2mbox.c
+
+maildirmake: \
+load maildirmake.o strerr.a substdio.a error.a str.a
+	./load maildirmake strerr.a substdio.a error.a str.a 
+
+maildirmake.0: \
+maildirmake.1
+	nroff -man maildirmake.1 > maildirmake.0
+
+maildirmake.o: \
+compile maildirmake.c strerr.h exit.h
+	./compile maildirmake.c
+
+maildirwatch: \
+load maildirwatch.o hfield.o headerbody.o maildir.o prioq.o now.o \
+getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \
+str.a
+	./load maildirwatch hfield.o headerbody.o maildir.o \
+	prioq.o now.o getln.a env.a open.a strerr.a stralloc.a \
+	alloc.a substdio.a error.a str.a 
+
+maildirwatch.0: \
+maildirwatch.1
+	nroff -man maildirwatch.1 > maildirwatch.0
+
+maildirwatch.o: \
+compile maildirwatch.c getln.h substdio.h subfd.h substdio.h prioq.h \
+datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \
+readwrite.h open.h headerbody.h maildir.h strerr.h
+	./compile maildirwatch.c
+
+maildirgetquota.o: \
+compile maildirgetquota.c maildirgetquota.h maildirmisc.h
+	./compile maildirgetquota.c
+
+maildirflags.o: \
+compile maildirflags.c
+	./compile maildirflags.c
+
+maildiropen.o: \
+compile maildiropen.c maildirmisc.h
+	./compile maildiropen.c
+
+maildirparsequota.o: \
+compile maildirparsequota.c
+	./compile maildirparsequota.c
+
+maildirquota.o: \
+compile maildirquota.c maildirquota.h maildirmisc.h numlib.h
+	./compile maildirquota.c
+
+overmaildirquota.o: \
+compile overmaildirquota.c 
+	./compile overmaildirquota.c
+
+strtimet.o: \
+compile strtimet.c 
+	./compile strtimet.c
+
+strpidt.o: \
+compile strpidt.c 
+	./compile strpidt.c
+
+mailsubj: \
+warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh mailsubj.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> mailsubj
+	chmod 755 mailsubj
+
+mailsubj.0: \
+mailsubj.1
+	nroff -man mailsubj.1 > mailsubj.0
+
+make-compile: \
+make-compile.sh auto-ccld.sh
+	cat auto-ccld.sh make-compile.sh > make-compile
+	chmod 755 make-compile
+
+make-load: \
+make-load.sh auto-ccld.sh
+	cat auto-ccld.sh make-load.sh > make-load
+	chmod 755 make-load
+
+make-load.sh: \
+libqmailio_install
+
+make-makelib: \
+make-makelib.sh auto-ccld.sh
+	cat auto-ccld.sh make-makelib.sh > make-makelib
+	chmod 755 make-makelib
+
+makelib: \
+make-makelib warn-auto.sh systype
+	( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \
+	makelib
+	chmod 755 makelib
+
+man: \
+qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \
+qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \
+qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \
+qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \
+qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \
+qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \
+preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \
+maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \
+qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \
+qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \
+envelopes.0 forgeries.0
+
+mbox.0: \
+mbox.5
+	nroff -man mbox.5 > mbox.0
+
+myctime.o: \
+compile myctime.c datetime.h fmt.h myctime.h
+	./compile myctime.c
+
+ndelay.a: \
+makelib ndelay.o ndelay_off.o
+	./makelib ndelay.a ndelay.o ndelay_off.o
+
+ndelay.o: \
+compile ndelay.c ndelay.h
+	./compile ndelay.c
+
+ndelay_off.o: \
+compile ndelay_off.c ndelay.h
+	./compile ndelay_off.c
+
+newfield.o: \
+compile newfield.c fmt.h datetime.h stralloc.h gen_alloc.h \
+date822fmt.h newfield.h stralloc.h
+	./compile newfield.c
+
+now.o: \
+compile now.c datetime.h now.h datetime.h
+	./compile now.c
+
+open.a: \
+makelib open_append.o open_excl.o open_read.o open_trunc.o \
+open_write.o
+	./makelib open.a open_append.o open_excl.o open_read.o \
+	open_trunc.o open_write.o
+
+open_append.o: \
+compile open_append.c open.h
+	./compile open_append.c
+
+open_excl.o: \
+compile open_excl.c open.h
+	./compile open_excl.c
+
+open_read.o: \
+compile open_read.c open.h
+	./compile open_read.c
+
+open_trunc.o: \
+compile open_trunc.c open.h
+	./compile open_trunc.c
+
+open_write.o: \
+compile open_write.c open.h
+	./compile open_write.c
+
+pinq: \
+warn-auto.sh pinq.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh pinq.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> pinq
+	chmod 755 pinq
+
+predate: \
+load predate.o datetime.a strerr.a sig.a fd.a wait.a substdio.a \
+error.a str.a fs.a
+	./load predate datetime.a strerr.a sig.a fd.a wait.a \
+	substdio.a error.a str.a fs.a 
+
+predate.o: \
+compile predate.c datetime.h fork.h wait.h fd.h fmt.h strerr.h \
+substdio.h subfd.h substdio.h readwrite.h exit.h
+	./compile predate.c
+
+preline: \
+load preline.o strerr.a fd.a wait.a sig.a env.a getopt.a substdio.a \
+error.a str.a
+	./load preline strerr.a fd.a wait.a sig.a env.a getopt.a \
+	substdio.a error.a str.a 
+
+preline.0: \
+preline.1
+	nroff -man preline.1 > preline.0
+
+preline.o: \
+compile preline.c fd.h sgetopt.h subgetopt.h readwrite.h strerr.h \
+substdio.h exit.h fork.h wait.h env.h sig.h error.h
+	./compile preline.c
+
+prioq.o: \
+compile prioq.c alloc.h gen_allocdefs.h prioq.h datetime.h \
+gen_alloc.h
+	./compile prioq.c
+
+proc: \
+proc.sh conf-qmail
+	cat proc.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> proc
+	chmod 755 proc
+
+proc+df: \
+proc+df.sh conf-qmail
+	cat proc+df.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> proc+df
+	chmod 755 proc+df
+
+prot.o: \
+compile prot.c hasshsgr.h prot.h
+	./compile prot.c
+
+qail: \
+warn-auto.sh qail.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh qail.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> qail
+	chmod 755 qail
+
+qbiff: \
+load qbiff.o headerbody.o hfield.o getln.a env.a open.a stralloc.a \
+alloc.a substdio.a error.a str.a
+	./load qbiff headerbody.o hfield.o getln.a env.a open.a \
+	stralloc.a alloc.a substdio.a error.a str.a 
+
+qbiff.0: \
+qbiff.1
+	nroff -man qbiff.1 > qbiff.0
+
+qbiff.o: \
+compile qbiff.c readwrite.h stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h
+	./compile qbiff.c
+
+qmail-clean: \
+load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+	./load qmail-clean fmtqfn.o now.o getln.a sig.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+	auto_split.o 
+
+qmail-clean.0: \
+qmail-clean.8
+	nroff -man qmail-clean.8 > qmail-clean.0
+
+qmail-clean.o: \
+compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \
+direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h
+	./compile qmail-clean.c
+
+qmail-command.0: \
+qmail-command.8
+	nroff -man qmail-command.8 > qmail-command.0
+
+qmail-control.0: \
+qmail-control.5
+	nroff -man qmail-control.5 > qmail-control.0
+
+qmail-control.5: \
+qmail-control.9 conf-break conf-spawn
+	cat qmail-control.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-control.5
+
+qmail-getpw: \
+load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \
+auto_usera.o
+	./load qmail-getpw case.a substdio.a error.a str.a fs.a \
+	auto_break.o auto_usera.o 
+
+qmail-getpw.0: \
+qmail-getpw.8
+	nroff -man qmail-getpw.8 > qmail-getpw.0
+
+qmail-getpw.8: \
+qmail-getpw.9 conf-break conf-spawn
+	cat qmail-getpw.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-getpw.8
+
+qmail-getpw.o: \
+compile qmail-getpw.c readwrite.h substdio.h subfd.h substdio.h \
+error.h exit.h byte.h str.h case.h fmt.h auto_usera.h auto_break.h \
+qlx.h
+	./compile qmail-getpw.c
+
+qmail-header.0: \
+qmail-header.5
+	nroff -man qmail-header.5 > qmail-header.0
+
+qmail-inject: \
+load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \
+control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \
+getln.a sig.a getopt.a datetime.a token822.o env.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+	./load qmail-inject headerbody.o hfield.o newfield.o \
+	quote.o now.o control.o date822fmt.o constmap.o qmail.o \
+	case.a fd.a wait.a open.a getln.a sig.a getopt.a datetime.a \
+	token822.o env.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a auto_qmail.o 
+
+qmail-inject.0: \
+qmail-inject.8
+	nroff -man qmail-inject.8 > qmail-inject.0
+
+qmail-inject.o: \
+compile qmail-inject.c sig.h substdio.h stralloc.h gen_alloc.h \
+subfd.h substdio.h sgetopt.h subgetopt.h getln.h alloc.h str.h fmt.h \
+hfield.h token822.h gen_alloc.h control.h env.h gen_alloc.h \
+gen_allocdefs.h error.h qmail.h substdio.h now.h datetime.h exit.h \
+quote.h headerbody.h auto_qmail.h newfield.h stralloc.h constmap.h
+	./compile qmail-inject.c
+
+qmail-limits.0: \
+qmail-limits.7
+	nroff -man qmail-limits.7 > qmail-limits.0
+
+qmail-limits.7: \
+qmail-limits.9 conf-break conf-spawn
+	cat qmail-limits.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-limits.7
+
+qmail-local: \
+load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \
+slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \
+wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib maildirquota.o \
+maildirgetquota.o maildiropen.o maildirparsequota.o overmaildirquota.o \
+strtimet.o strpidt.o
+	./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \
+	slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \
+	lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \
+	substdio.a error.a str.a fs.a datetime.a auto_qmail.o \
+	auto_patrn.o  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildiropen.o maildirparsequota.o overmaildirquota.o strtimet.o strpidt.o
+
+qmail-local.0: \
+qmail-local.8
+	nroff -man qmail-local.8 > qmail-local.0
+
+qmail-local.o: \
+compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \
+open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \
+substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \
+gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \
+substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h
+	./compile qmail-local.c
+
+qmail-log.0: \
+qmail-log.5
+	nroff -man qmail-log.5 > qmail-log.0
+
+qmail-lspawn: \
+load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \
+case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a auto_qmail.o auto_uids.o auto_spawn.o
+	./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \
+	sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \
+	auto_spawn.o 
+
+qmail-lspawn.0: \
+qmail-lspawn.8
+	nroff -man qmail-lspawn.8 > qmail-lspawn.0
+
+qmail-lspawn.o: \
+compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \
+gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \
+slurpclose.h auto_qmail.h auto_uids.h qlx.h
+	./compile qmail-lspawn.c
+
+qmail-newmrh: \
+load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \
+stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o
+	./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \
+	seek.a case.a stralloc.a alloc.a strerr.a substdio.a \
+	error.a str.a auto_qmail.o 
+
+qmail-newmrh.0: \
+qmail-newmrh.8
+	nroff -man qmail-newmrh.8 > qmail-newmrh.0
+
+qmail-newmrh.8: \
+qmail-newmrh.9 conf-break conf-spawn
+	cat qmail-newmrh.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-newmrh.8
+
+qmail-newmrh.o: \
+compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \
+getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \
+uint32.h substdio.h
+	./compile qmail-newmrh.c
+
+qmail-newu: \
+load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \
+stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o
+	./load qmail-newu cdbmss.o getln.a open.a seek.a cdbmake.a \
+	case.a stralloc.a alloc.a substdio.a error.a str.a \
+	auto_qmail.o 
+
+qmail-newu.0: \
+qmail-newu.8
+	nroff -man qmail-newu.8 > qmail-newu.0
+
+qmail-newu.8: \
+qmail-newu.9 conf-break conf-spawn
+	cat qmail-newu.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-newu.8
+
+qmail-newu.o: \
+compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \
+getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \
+readwrite.h open.h error.h case.h auto_qmail.h
+	./compile qmail-newu.c
+
+qmail-pop3d: \
+load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \
+maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib maildirquota.o \
+maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
+	./load qmail-pop3d commands.o case.a timeoutread.o \
+	timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \
+	open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \
+	fs.a  `cat socket.lib` maildirquota.o maildirgetquota.o \
+    maildirparsequota.o maildirflags.o maildiropen.o strtimet.o strpidt.o
+
+qmail-pop3d.0: \
+qmail-pop3d.8
+	nroff -man qmail-pop3d.8 > qmail-pop3d.0
+
+qmail-pop3d.o: \
+compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \
+substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \
+str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \
+timeoutwrite.h
+	./compile qmail-pop3d.c
+
+qmail-popup: \
+load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \
+case.a fd.a sig.a wait.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a socket.lib
+	./load qmail-popup commands.o timeoutread.o timeoutwrite.o \
+	now.o case.a fd.a sig.a wait.a stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a  `cat socket.lib`
+
+qmail-popup.0: \
+qmail-popup.8
+	nroff -man qmail-popup.8 > qmail-popup.0
+
+qmail-popup.o: \
+compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \
+substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \
+readwrite.h timeoutread.h timeoutwrite.h
+	./compile qmail-popup.c
+
+qmail-pw2u: \
+load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a auto_usera.o \
+auto_break.o auto_qmail.o
+	./load qmail-pw2u constmap.o control.o open.a getln.a \
+	case.a getopt.a stralloc.a alloc.a substdio.a error.a str.a \
+	fs.a auto_usera.o auto_break.o auto_qmail.o 
+
+qmail-pw2u.0: \
+qmail-pw2u.8
+	nroff -man qmail-pw2u.8 > qmail-pw2u.0
+
+qmail-pw2u.8: \
+qmail-pw2u.9 conf-break conf-spawn
+	cat qmail-pw2u.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-pw2u.8
+
+qmail-pw2u.o: \
+compile qmail-pw2u.c substdio.h readwrite.h subfd.h substdio.h \
+sgetopt.h subgetopt.h control.h constmap.h stralloc.h gen_alloc.h \
+fmt.h str.h scan.h open.h error.h getln.h auto_break.h auto_qmail.h \
+auto_usera.h
+	./compile qmail-pw2u.c
+
+qmail-qmqpc: \
+load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \
+getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib
+	./load qmail-qmqpc slurpclose.o timeoutread.o \
+	timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \
+	sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \
+	error.a str.a fs.a  `cat socket.lib`
+
+qmail-qmqpc.0: \
+qmail-qmqpc.8
+	nroff -man qmail-qmqpc.8 > qmail-qmqpc.0
+
+qmail-qmqpc.o: \
+compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \
+stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \
+timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h
+	./compile qmail-qmqpc.c
+
+qmail-qmqpd: \
+load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \
+env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a
+	./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \
+	auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \
+	str.a datetime.a fs.a 
+
+qmail-qmqpd.0: \
+qmail-qmqpd.8
+	nroff -man qmail-qmqpd.8 > qmail-qmqpd.0
+
+qmail-qmqpd.o: \
+compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \
+sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h
+	./compile qmail-qmqpd.c
+
+qmail-qmtpd: \
+load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \
+date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \
+getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o
+	./load qmail-qmtpd rcpthosts.o control.o constmap.o \
+	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+	datetime.a open.a getln.a sig.a case.a env.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o 
+
+qmail-qmtpd.0: \
+qmail-qmtpd.8
+	nroff -man qmail-qmtpd.8 > qmail-qmtpd.0
+
+qmail-qmtpd.o: \
+compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \
+substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \
+auto_qmail.h readwrite.h control.h received.h
+	./compile qmail-qmtpd.c
+
+qmail-qread: \
+load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \
+open.a getln.a stralloc.a alloc.a substdio.a error.a str.a fs.a \
+auto_qmail.o auto_split.o
+	./load qmail-qread fmtqfn.o readsubdir.o date822fmt.o \
+	datetime.a open.a getln.a stralloc.a alloc.a substdio.a \
+	error.a str.a fs.a auto_qmail.o auto_split.o 
+
+qmail-qread.0: \
+qmail-qread.8
+	nroff -man qmail-qread.8 > qmail-qread.0
+
+qmail-qread.o: \
+compile qmail-qread.c stralloc.h gen_alloc.h substdio.h subfd.h \
+substdio.h fmt.h str.h getln.h fmtqfn.h readsubdir.h direntry.h \
+auto_qmail.h open.h datetime.h date822fmt.h readwrite.h error.h \
+exit.h
+	./compile qmail-qread.c
+
+qmail-qstat: \
+warn-auto.sh qmail-qstat.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh qmail-qstat.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> qmail-qstat
+	chmod 755 qmail-qstat
+
+qmail-qstat.0: \
+qmail-qstat.8
+	nroff -man qmail-qstat.8 > qmail-qstat.0
+
+qmail-queue: \
+load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \
+datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \
+str.a fs.a auto_qmail.o auto_split.o auto_uids.o
+	./load qmail-queue triggerpull.o fmtqfn.o now.o \
+	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+	auto_split.o auto_uids.o 
+
+qmail-queue.0: \
+qmail-queue.8
+	nroff -man qmail-queue.8 > qmail-queue.0
+
+qmail-queue.o: \
+compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \
+alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \
+auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
+	./compile qmail-queue.c
+
+qmail-remote: \
+load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
+ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
+	./load qmail-remote control.o constmap.o timeoutread.o \
+	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
+	tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
+	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
+	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
+
+qmail-remote.0: \
+qmail-remote.8
+	nroff -man qmail-remote.8 > qmail-remote.0
+
+qmail-remote.o: \
+compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \
+subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
+alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
+gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
+tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
+	./compile qmail-remote.c
+
+qmail-rspawn: \
+load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
+seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
+auto_qmail.o auto_uids.o auto_spawn.o
+	./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
+	sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
+	substdio.a error.a str.a auto_qmail.o auto_uids.o \
+	auto_spawn.o 
+
+qmail-rspawn.0: \
+qmail-rspawn.8
+	nroff -man qmail-rspawn.8 > qmail-rspawn.0
+
+qmail-rspawn.o: \
+compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \
+tcpto.h
+	./compile qmail-rspawn.c
+
+qmail-send: \
+load qmail-send.o qsutil.o control.o constmap.o newfield.o prioq.o \
+trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
+datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
+lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+auto_split.o env.a
+	./load qmail-send qsutil.o control.o constmap.o newfield.o \
+	prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
+	qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
+	wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
+
+qmail-send.0: \
+qmail-send.8
+	nroff -man qmail-send.8 > qmail-send.0
+
+qmail-send.8: \
+qmail-send.9 conf-break conf-spawn
+	cat qmail-send.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-send.8
+
+qmail-send.o: \
+compile qmail-send.c readwrite.h sig.h direntry.h control.h select.h \
+open.h seek.h exit.h lock.h ndelay.h now.h datetime.h getln.h \
+substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \
+scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \
+qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \
+fmtqfn.h readsubdir.h direntry.h
+	./compile qmail-send.c
+
+qmail-showctl: \
+load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
+alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \
+auto_patrn.o auto_spawn.o auto_split.o
+	./load qmail-showctl auto_uids.o control.o open.a getln.a \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a \
+	auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \
+	auto_split.o 
+
+qmail-showctl.0: \
+qmail-showctl.8
+	nroff -man qmail-showctl.8 > qmail-showctl.0
+
+qmail-showctl.o: \
+compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \
+str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \
+auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \
+auto_split.h
+	./compile qmail-showctl.c
+
+qmail-smtpd: \
+load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
+date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
+open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+fs.a auto_qmail.o base64.o socket.lib dns.o dns.lib
+	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
+	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+	tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
+	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
+	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o `cat \
+	socket.lib` -L`head -1 conf-vpopmail`/lib `head -1 conf-vpop-ld` \
+	-L/usr/lib/mysql  -lmysqlclient -lz dns.o `cat dns.lib`
+
+qmail-smtpd.0: \
+qmail-smtpd.8
+	nroff -man qmail-smtpd.8 > qmail-smtpd.0
+
+qmail-smtpd.o: \
+compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
+substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
+error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
+substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h wait.h \
+fd.h base64.h
+	./compile qmail-smtpd.c -I`head -1 conf-vpopmail`/include
+
+qmail-start: \
+load qmail-start.o prot.o fd.a auto_uids.o
+	./load qmail-start prot.o fd.a auto_uids.o 
+
+qmail-start.0: \
+qmail-start.8
+	nroff -man qmail-start.8 > qmail-start.0
+
+qmail-start.8: \
+qmail-start.9 conf-break conf-spawn
+	cat qmail-start.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-start.8
+
+qmail-start.o: \
+compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h
+	./compile qmail-start.c
+
+qmail-tcpok: \
+load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \
+auto_qmail.o
+	./load qmail-tcpok open.a lock.a strerr.a substdio.a \
+	error.a str.a auto_qmail.o 
+
+qmail-tcpok.0: \
+qmail-tcpok.8
+	nroff -man qmail-tcpok.8 > qmail-tcpok.0
+
+qmail-tcpok.o: \
+compile qmail-tcpok.c strerr.h substdio.h lock.h open.h readwrite.h \
+auto_qmail.h exit.h
+	./compile qmail-tcpok.c
+
+qmail-tcpto: \
+load qmail-tcpto.o ip.o now.o open.a lock.a substdio.a error.a str.a \
+fs.a auto_qmail.o
+	./load qmail-tcpto ip.o now.o open.a lock.a substdio.a \
+	error.a str.a fs.a auto_qmail.o 
+
+qmail-tcpto.0: \
+qmail-tcpto.8
+	nroff -man qmail-tcpto.8 > qmail-tcpto.0
+
+qmail-tcpto.o: \
+compile qmail-tcpto.c substdio.h subfd.h substdio.h auto_qmail.h \
+fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h
+	./compile qmail-tcpto.c
+
+qmail-upq: \
+warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh qmail-upq.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> qmail-upq
+	chmod 755 qmail-upq
+
+qmail-users.0: \
+qmail-users.5
+	nroff -man qmail-users.5 > qmail-users.0
+
+qmail-users.5: \
+qmail-users.9 conf-break conf-spawn
+	cat qmail-users.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-users.5
+
+qmail.0: \
+qmail.7
+	nroff -man qmail.7 > qmail.0
+
+qmail.o: \
+compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \
+qmail.h substdio.h auto_qmail.h
+	./compile qmail.c
+
+qreceipt: \
+load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \
+getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a auto_qmail.o
+	./load qreceipt headerbody.o hfield.o quote.o token822.o \
+	qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \
+	substdio.a error.a str.a auto_qmail.o 
+
+qreceipt.0: \
+qreceipt.1
+	nroff -man qreceipt.1 > qreceipt.0
+
+qreceipt.o: \
+compile qreceipt.c sig.h env.h substdio.h stralloc.h gen_alloc.h \
+subfd.h substdio.h getln.h alloc.h str.h hfield.h token822.h \
+gen_alloc.h error.h gen_alloc.h gen_allocdefs.h headerbody.h exit.h \
+open.h quote.h qmail.h substdio.h
+	./compile qreceipt.c
+
+qsmhook: \
+load qsmhook.o sig.a case.a fd.a wait.a getopt.a env.a stralloc.a \
+alloc.a substdio.a error.a str.a
+	./load qsmhook sig.a case.a fd.a wait.a getopt.a env.a \
+	stralloc.a alloc.a substdio.a error.a str.a 
+
+qsmhook.o: \
+compile qsmhook.c fd.h stralloc.h gen_alloc.h readwrite.h sgetopt.h \
+subgetopt.h wait.h env.h byte.h str.h alloc.h exit.h fork.h case.h \
+subfd.h substdio.h error.h substdio.h sig.h
+	./compile qsmhook.c
+
+qsutil.o: \
+compile qsutil.c stralloc.h gen_alloc.h readwrite.h substdio.h \
+qsutil.h
+	./compile qsutil.c
+
+quote.o: \
+compile quote.c stralloc.h gen_alloc.h str.h quote.h
+	./compile quote.c
+
+rcpthosts.o: \
+compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
+constmap.h stralloc.h gen_alloc.h rcpthosts.h
+	./compile rcpthosts.c
+
+readsubdir.o: \
+compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
+auto_split.h
+	./compile readsubdir.c
+
+received.o: \
+compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
+datetime.h date822fmt.h received.h
+	./compile received.c
+
+remoteinfo.o: \
+compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \
+timeoutread.h timeoutwrite.h remoteinfo.h
+	./compile remoteinfo.c
+
+scan_8long.o: \
+compile scan_8long.c scan.h
+	./compile scan_8long.c
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+	./compile scan_ulong.c
+
+seek.a: \
+makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o
+	./makelib seek.a seek_cur.o seek_end.o seek_set.o \
+	seek_trunc.o
+
+seek_cur.o: \
+compile seek_cur.c seek.h
+	./compile seek_cur.c
+
+seek_end.o: \
+compile seek_end.c seek.h
+	./compile seek_end.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+	./compile seek_set.c
+
+seek_trunc.o: \
+compile seek_trunc.c seek.h
+	./compile seek_trunc.c
+
+select.h: \
+compile trysysel.c select.h1 select.h2
+	( ./compile trysysel.c >/dev/null 2>&1 \
+	&& cat select.h2 || cat select.h1 ) > select.h
+	rm -f trysysel.o trysysel
+
+sendmail: \
+load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \
+auto_qmail.o
+	./load sendmail env.a getopt.a alloc.a substdio.a error.a \
+	str.a auto_qmail.o 
+
+sendmail.o: \
+compile sendmail.c sgetopt.h subgetopt.h substdio.h subfd.h \
+substdio.h alloc.h auto_qmail.h exit.h env.h str.h
+	./compile sendmail.c
+
+setup: \
+it man
+	./install
+
+sgetopt.o: \
+compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \
+subgetopt.h
+	./compile sgetopt.c
+
+shar: \
+FILES BLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias \
+INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL.vsm \
+REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE \
+THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL \
+PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem \
+PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood \
+PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README \
+BIN.Makefile BIN.setup idedit.c conf-break auto_break.h conf-spawn \
+auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \
+auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \
+addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 \
+envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 \
+maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \
+qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \
+qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \
+qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \
+qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \
+qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \
+qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \
+qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \
+qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \
+qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \
+qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \
+qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \
+qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \
+qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \
+qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \
+dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \
+sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \
+except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \
+maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \
+datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h \
+commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c \
+myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \
+readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c \
+tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \
+trynpbg1.c trysyslog.c conf-cc conf-ld home.sh home+df.sh proc.sh \
+proc+df.sh binm1.sh binm2.sh binm3.sh binm1+df.sh binm2+df.sh \
+binm3+df.sh find-systype.sh make-compile.sh make-load.sh \
+make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c \
+auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \
+install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \
+case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \
+cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \
+cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \
+coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
+fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \
+open.h open_append.c open_excl.c open_read.c open_trunc.c \
+open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \
+conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h \
+stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \
+stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \
+stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c \
+substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h \
+subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h \
+exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c \
+timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 \
+uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c \
+trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
+sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
+trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
+byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
+str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
+getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \
+subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \
+error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \
+fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \
+slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \
+headerbody.h headerbody.c token822.h token822.c control.h control.c \
+datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \
+date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \
+ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
+ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
+prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
+	shar -m `cat FILES` > shar
+	chmod 400 shar
+
+sig.a: \
+makelib sig_alarm.o sig_block.o sig_catch.o sig_pause.o sig_pipe.o \
+sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o
+	./makelib sig.a sig_alarm.o sig_block.o sig_catch.o \
+	sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o \
+	sig_bug.o sig_misc.o
+
+sig_alarm.o: \
+compile sig_alarm.c sig.h
+	./compile sig_alarm.c
+
+sig_block.o: \
+compile sig_block.c sig.h hassgprm.h
+	./compile sig_block.c
+
+sig_bug.o: \
+compile sig_bug.c sig.h
+	./compile sig_bug.c
+
+sig_catch.o: \
+compile sig_catch.c sig.h hassgact.h
+	./compile sig_catch.c
+
+sig_child.o: \
+compile sig_child.c sig.h
+	./compile sig_child.c
+
+sig_hup.o: \
+compile sig_hup.c sig.h
+	./compile sig_hup.c
+
+sig_misc.o: \
+compile sig_misc.c sig.h
+	./compile sig_misc.c
+
+sig_pause.o: \
+compile sig_pause.c sig.h hassgprm.h
+	./compile sig_pause.c
+
+sig_pipe.o: \
+compile sig_pipe.c sig.h
+	./compile sig_pipe.c
+
+sig_term.o: \
+compile sig_term.c sig.h
+	./compile sig_term.c
+
+slurpclose.o: \
+compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \
+error.h
+	./compile slurpclose.c
+
+socket.lib: \
+trylsock.c compile load
+	( ( ./compile trylsock.c && \
+	./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \
+	&& echo -lsocket -lnsl || exit 0 ) > socket.lib
+	rm -f trylsock.o trylsock
+
+spawn.o: \
+compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
+stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \
+auto_qmail.h auto_uids.h auto_spawn.h
+	./chkspawn
+	./compile spawn.c
+
+splogger: \
+load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
+	./load splogger substdio.a error.a str.a fs.a  `cat \
+	syslog.lib` `cat socket.lib`
+
+splogger.0: \
+splogger.8
+	nroff -man splogger.8 > splogger.0
+
+splogger.o: \
+compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \
+scan.h fmt.h
+	./compile splogger.c
+
+str.a: \
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
+byte_cr.o byte_zero.o
+	./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
+	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
+	byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+
+str_chr.o: \
+compile str_chr.c str.h
+	./compile str_chr.c
+
+str_cpy.o: \
+compile str_cpy.c str.h
+	./compile str_cpy.c
+
+str_diff.o: \
+compile str_diff.c str.h
+	./compile str_diff.c
+
+str_diffn.o: \
+compile str_diffn.c str.h
+	./compile str_diffn.c
+
+str_len.o: \
+compile str_len.c str.h
+	./compile str_len.c
+
+str_rchr.o: \
+compile str_rchr.c str.h
+	./compile str_rchr.c
+
+str_start.o: \
+compile str_start.c str.h
+	./compile str_start.c
+
+stralloc.a: \
+makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \
+stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \
+stralloc_catb.o stralloc_arts.o
+	./makelib stralloc.a stralloc_eady.o stralloc_pend.o \
+	stralloc_copy.o stralloc_opys.o stralloc_opyb.o \
+	stralloc_cat.o stralloc_cats.o stralloc_catb.o \
+	stralloc_arts.o
+
+stralloc_arts.o: \
+compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_arts.c
+
+stralloc_cat.o: \
+compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+	./compile stralloc_cat.c
+
+stralloc_catb.o: \
+compile stralloc_catb.c stralloc.h gen_alloc.h byte.h
+	./compile stralloc_catb.c
+
+stralloc_cats.o: \
+compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_cats.c
+
+stralloc_copy.o: \
+compile stralloc_copy.c byte.h stralloc.h gen_alloc.h
+	./compile stralloc_copy.c
+
+stralloc_eady.o: \
+compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+	./compile stralloc_eady.c
+
+stralloc_opyb.o: \
+compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h
+	./compile stralloc_opyb.c
+
+stralloc_opys.o: \
+compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_opys.c
+
+stralloc_pend.o: \
+compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+	./compile stralloc_pend.c
+
+strerr.a: \
+makelib strerr_sys.o strerr_die.o
+	./makelib strerr.a strerr_sys.o strerr_die.o
+
+strerr_die.o: \
+compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h
+	./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+	./compile strerr_sys.c
+
+subfderr.o: \
+compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfderr.c
+
+subfdin.o: \
+compile subfdin.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdin.c
+
+subfdins.o: \
+compile subfdins.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdins.c
+
+subfdout.o: \
+compile subfdout.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdout.c
+
+subfdouts.o: \
+compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdouts.c
+
+subgetopt.o: \
+compile subgetopt.c subgetopt.h
+	./compile subgetopt.c
+
+substdi.o: \
+compile substdi.c substdio.h byte.h error.h
+	./compile substdi.c
+
+substdio.a: \
+makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \
+subfdouts.o subfdin.o subfdins.o substdio_copy.o
+	./makelib substdio.a substdio.o substdi.o substdo.o \
+	subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \
+	substdio_copy.o
+
+substdio.o: \
+compile substdio.c substdio.h
+	./compile substdio.c
+
+substdio_copy.o: \
+compile substdio_copy.c substdio.h
+	./compile substdio_copy.c
+
+substdo.o: \
+compile substdo.c substdio.h str.h byte.h error.h
+	./compile substdo.c
+
+syslog.lib: \
+trysyslog.c compile load
+	( ( ./compile trysyslog.c && \
+	./load trysyslog -lgen ) >/dev/null 2>&1 \
+	&& echo -lgen || exit 0 ) > syslog.lib
+	rm -f trysyslog.o trysyslog
+
+systype: \
+find-systype trycpp.c
+	./find-systype > systype
+
+tcp-env: \
+load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load tcp-env dns.o remoteinfo.o timeoutread.o \
+	timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
+	sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a  `cat dns.lib` `cat socket.lib`
+
+tcp-env.0: \
+tcp-env.1
+	nroff -man tcp-env.1 > tcp-env.0
+
+tcp-env.o: \
+compile tcp-env.c sig.h stralloc.h gen_alloc.h str.h env.h fmt.h \
+scan.h subgetopt.h ip.h dns.h byte.h remoteinfo.h exit.h case.h
+	./compile tcp-env.c
+
+tcp-environ.0: \
+tcp-environ.5
+	nroff -man tcp-environ.5 > tcp-environ.0
+
+tcpto.o: \
+compile tcpto.c tcpto.h open.h lock.h seek.h now.h datetime.h ip.h \
+byte.h datetime.h readwrite.h
+	./compile tcpto.c
+
+tcpto_clean.o: \
+compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h
+	./compile tcpto_clean.c
+
+timeoutconn.o: \
+compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \
+byte.h timeoutconn.h
+	./compile timeoutconn.c
+
+timeoutread.o: \
+compile timeoutread.c timeoutread.h select.h error.h readwrite.h
+	./compile timeoutread.c
+
+timeoutwrite.o: \
+compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
+	./compile timeoutwrite.c
+
+qmail-smtpd: tls.o ssl_timeoutio.o ndelay.a
+qmail-remote: tls.o ssl_timeoutio.o
+qmail-smtpd.o: tls.h ssl_timeoutio.h
+qmail-remote.o: tls.h ssl_timeoutio.h
+
+tls.o: \
+compile tls.c exit.h error.h
+	./compile tls.c
+
+ssl_timeoutio.o: \
+compile ssl_timeoutio.c ssl_timeoutio.h select.h error.h ndelay.h
+	./compile ssl_timeoutio.c
+
+token822.o: \
+compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \
+gen_alloc.h gen_allocdefs.h
+	./compile token822.c
+
+trigger.o: \
+compile trigger.c select.h open.h trigger.h hasnpbg1.h
+	./compile trigger.c
+
+triggerpull.o: \
+compile triggerpull.c ndelay.h open.h triggerpull.h
+	./compile triggerpull.c
+
+uint32.h: \
+tryulong32.c compile load uint32.h1 uint32.h2
+	( ( ./compile tryulong32.c && ./load tryulong32 && \
+	./tryulong32 ) >/dev/null 2>&1 \
+	&& cat uint32.h2 || cat uint32.h1 ) > uint32.h
+	rm -f tryulong32.o tryulong32
+
+wait.a: \
+makelib wait_pid.o wait_nohang.o
+	./makelib wait.a wait_pid.o wait_nohang.o
+
+wait_nohang.o: \
+compile wait_nohang.c haswaitp.h
+	./compile wait_nohang.c
+
+wait_pid.o: \
+compile wait_pid.c error.h haswaitp.h
+	./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+	@$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail Makefile-cert.mk
+	@cat Makefile-cert.mk \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
diff -urN qmail-1.03-orig/Makefile.rej qmail-1.03/Makefile.rej
--- qmail-1.03-orig/Makefile.rej	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/Makefile.rej	2003-10-03 14:15:10.000000000 -0400
@@ -0,0 +1,29 @@
+***************
+*** 1535,1547 ****
+  load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+  timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
+  date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
+- open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
+  fs.a auto_qmail.o socket.lib
+  	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
+  	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+  	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+  	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
+- 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
+  	socket.lib`
+  
+  qmail-smtpd.0: \
+--- 1535,1547 ----
+  load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+  timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
+  date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
++ open.a sig.a case.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \
+  fs.a auto_qmail.o socket.lib
+  	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
+  	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+  	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+  	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
++ 	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
+  	socket.lib`
+  
+  qmail-smtpd.0: \
diff -urN qmail-1.03-orig/README.auth qmail-1.03/README.auth
--- qmail-1.03-orig/README.auth	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/README.auth	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,175 @@
+*** Warning! Cuidado! Vorsicht! ***
+===================================
+*** Version 0.30 of the patch changes the arguments which must be
+*** passed to qmail-smtpd.  If you are upgrading from a previous
+*** version of the patch, take care to ensure your invocation of
+*** qmail-smtpd uses the correct arguments.  Otherwise, your server
+*** may run as an open relay!
+===================================
+*** Warning! Cuidado! Vorsicht! ***
+
+
+This patch adds ESMTP AUTH authentication protocol support to
+qmail-1.03.  It's originally based on Mrs. Brisby's smtp-auth patch
+with many enhancements from Krzysztof Dabrowski <brush@elysium.pl>.
+
+Beginning with version 0.30, the patch was completely rewritten to
+use only djb's string functions by Eric M. Johnston <emj@postal.net>.
+
+You can always get the newest version from:
+http://members.elysium.pl/brush/qmail-smtpd-auth/
+
+To use all of it's functionality you will also have to obtain and
+install Krzysztof's cmd5checkpw utility available at:
+http://members.elysium.pl/brush/cmd5checkpw/
+
+If you need more information about SMTP-AUTH itself and the
+client/server support and configuration, visit:
+http://members.elysium.pl/brush/smtp-auth/
+
+---
+
+Detailed patch information:
+
+This patch adds the ESMTP AUTH option to qmail-1.03, allowing the
+LOGIN, PLAIN, and CRAM-MD5 AUTH types. An appropriate checkpassword
+tool is necessary to support the authentication.  See
+http://cr.yp.to/checkpwd.html for more information on the interface.
+Note that the checkpassword tool should support all of the AUTH types
+advertised by qmail-smtpd.
+
+As reflected in the modified qmail-smtpd(8) man page, qmail-smtpd
+must be invoked with three arguments: hostname, checkprogram, and
+subprogram.  If these arguments are missing, qmail-smtpd will still
+advertise availability of AUTH, but will fail with a permanent error
+when AUTH is used.
+
+hostname is simply used to form the CRAM-MD5 challenge.  qmail-smtpd
+invokes checkprogram, feeding it the username and password, in the
+case of LOGIN or PLAIN, or the username, challenge, and response, in
+the case of CRAM-MD5.  If the user is permitted, checkprogram invokes
+subprogram, which just has to exit with a status of 0 for the user to
+be authenticated.  Otherwise, checkprogram exits with a non-zero
+status.  subprogram can usually be /usr/bin/true (or /bin/true,
+depending on your flavor of OS).
+
+If the user is successfully authenticated, the RELAYCLIENT
+environment variable is effectively set for the SMTP session, and
+the TCPREMOTEINFO environment variable is set to the authenticated
+username, overriding any value that tcpserver may have set.  The
+value of TCPREMOTEINFO is reflected in a Received header.
+
+
+How to install it:
+
+Simply patch your qmail-1.03 distribution with the included patch
+file and recompile & install like usual.
+
+The steps to do this are as follows (assuming your virgin
+qmail-1.03 install is in "../qmail-1.03"):
+
+  cp README.auth base64.c base64.h ../qmail-1.03
+  patch -d ../qmail-1.03 < auth.patch
+
+Install qmail normally, with the exception of the new arguments
+to qmail-smtpd described elsewhere in this file.
+
+Also obtain, unpack, compile and install the cmd5checkpw utility
+(or some other checkpassword utility) and add a sample account to
+/etc/poppasswd file.  This file must be readable by the qmail-smtpd
+user, usually qmaild.
+
+
+How to use it:
+
+*** Warning: In version 0.30 the arguments have changed from
+*** previous versions of qmail-smtpd-auth.  Take care to make sure
+*** you update your startup scripts if updating!
+
+If you're running qmail-smtpd from inetd, you'll want to do the
+following:
+
+smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env tcp-env \
+/var/qmail/bin/qmail-smtpd mail.acme.com /bin/cmd5checkpw /bin/true
+
+Replace mail.acme.com with your hostname.  The second argument to
+qmail-smtpd is your checkpassword utility (preferably cmd5checkpw
+or some alternative that can handle CRAM-MD5).  The third argument
+is the executable that the checkpassword utility execs when
+authentication is successful.  (Note that the location of "true"
+is OS dependent: you may need /usr/bin/true.)
+
+Invocations using tcpserver will require analagous changes.  Give
+your inetd a kill -HUP or restart tcpserver and away you go.
+
+
+Caveats:
+
+Please note that as authentication needs vary wildly across
+installations, no effort has been made to make this patch work ``out
+of the box.''  You'll have to procure or develop your own
+checkpassword program.  Also note that CRAM-MD5 will require you to
+keep plaintext passwords.  You'll probably want to disable this AUTH
+type if you're just using /etc/passwd (keeping in mind that PLAIN and
+LOGIN aren't quite as safe over the wire) -- just undefine AUTHCRAM
+in qmail-smtpd.
+
+Krzysztof Dabrowski's cmd5checkpw tool used as an example in this
+document supports the three AUTH types included in this patch.
+It's available at http://www.elysium.pl/members/brush/cmd5checkpw/.
+
+This patch has been generated against the stock qmail 1.03
+distribution.  The results of combining this patch with others are
+unknown.
+
+
+Features:
+
+This patch supports the following auth methods: LOGIN, PLAIN and
+CRAM-MD5.
+
+
+Compatibility:
+
+The following MUA's are confirmed to work with this patch:
+
+Eudora 4.2.2		-	CRAM-MD5
+Eudora 5.0.2 		- 	CRAM-MD5
+The Bat 1.39		-	LOGIN & CRAM-MD5
+Outlook Express 4	- 	LOGIN
+Outlook Express 5	-	LOGIN
+Outlook 2000 		- 	LOGIN
+Netscape 4.x		-	LOGIN & PLAIN
+Netscape 4.0x		-	LOGIN
+Pegasus Mail 3.1x	-	CRAM-MD5
+
+
+Various compatibility issues:
+
+Testing with Pegasus Mail 3.1 revealed that it requires the new style
+(RFC recommended) greeting message.  Both styles are now enabled to
+maintain the highest degree of compatibility with various clients.
+This fix was suggested by David Harris <David.Harris@pmail.gen.nz>,
+the developer of Pegasus Mail.
+
+
+Acknowledgments:
+
+This patch is based on work by Krzysztof Dabrowski at
+http://members.elysium.pl/brush/qmail-smtpd-auth/ and ``Mrs. Brisby''
+at http://www.nimh.org/hacks/qmail-smtpd.c which has been further
+developed by Eric M. Johnston <emj@postal.net>.
+
+---
+
+THIS SOFTWARE IS IN THE PUBLIC DOMAIN, IS PROVIDED BY THE AUTHOR
+``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 AUTHOR 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.
diff -urN qmail-1.03-orig/README.chkuser qmail-1.03/README.chkuser
--- qmail-1.03-orig/README.chkuser	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/README.chkuser	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,49 @@
+Introduction
+------------
++
+The vpopmail chkuser patch was original written by Interazioni di Antonio
+Nati (http://www.interazioni.it/qmail/, tonix@interazioni.it).  I have taken
+the 1.0 version of the patch
+(http://www.interazioni.it/qmail/qmail-smtpd-chkusr-1.0.patch) and tried to
+make it more portable, by adding in DJB style conf-* files for the vpopmail
+home directory and the extra libraries to link in.  I then modified the
+Makefile to use these files to set -I~vpopmail/include when qmail-smtpd.o is
+built, eliminating the need for hard coded paths in qmail-smtpd.c, and
+-L~vpopmail/lib when qmail-smtpd is linked.
++
+So far, this has only been tested using pristine qmail source and vpopmail
+5.3.5 using cdb on a Red Hat 7.1 machine and vpopmail 5.3.12 using cdb on a
+Mandrake 8.1 machine.  YMMV.
++
+Instructions
+------------
++
+Edit conf-vpopmail if you installed vpopmail in another location besides
+/home/vpopmail
+
+p-ld and add any other libraries (like -lmysqlclient if you
+used mysql) needed for your vpopmail authentication method.  If you're using
+a stock vpopmail install with cdb, you shouldn't have to change this.  In
+some cases, you may need to add -lcrypto in addition to -lcrypt
++
+After that, build qmail as you normally would.  According to the original
+patch, after qmail has been installed, you need to change the ownership and
+permissions on qmail-smtpd:
++
+chown qmaild /var/qmail/bin/qmail-smtpd
+chown nofiles /var/qmail/bin/qmail-smtpd
+chmod 6555 /var/qmail/bin/qmail-smtpd
++
+If you're using tcpserver to start qmail-smtpd (and if you're not, why
+aren't you? :-D ), add -u <vpopmail-user-uid> -g <vpopmail-group-gid> to the
+tcpserver line.
++
+Good Luck!
++
+Author
+------
++
+This document and the patch variation was done by David L. Weiner
+<dave@gallowglass.org>.  Visit my webpage at http://www.gallowglass.org for
+more qmail stuff.
++
diff -urN qmail-1.03-orig/README.libqmailio qmail-1.03/README.libqmailio
--- qmail-1.03-orig/README.libqmailio	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/README.libqmailio	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,44 @@
+This package has been integrated into the patched qmail distro.  Make will
+build the libraries and install them in /var/lib.
+
+Joshua Megerman
+josh@coyotetechnical.com
+2/13/03
+-----Original Message-----
+Here's a new version of the library which I sent to this list last night.
+The earlier version works but I received some valuable feedback from Bruce
+Guenter and also did some rethinking myself.
+
+The name of the library was not good. The library is not universal, e.g. it
+doesn't have any effect on those libio calls like fopen(). It only changes
+how link(), unlink(), open() and rename() work because qmail uses only them.
+So I changed the name of the library to libqmailio. Second, I learnt from
+Bruce that I don't really need a variable-length argument list for open().
+Third, I changed to syscall() instead of __open, __link and __unlink.
+
+In the first version I used realpath() to get the canonicalized absolute
+pathname. My idea was that it would also resolve symbolic links so that I
+would fsync the right directory where eg. a file is created and not the
+directory where a symbolic link is. But it's not necessary because qmail
+doesn't need it and it seems that realpath() uses lots of system calls to
+traverse the directory tree. And actually it didn't work right for unlinks
+because unlink doesn't follow symbolic links. So I removed realpath().
+
+So what is this all about? qmail relies on the BSD semantics of immediate
+update of directories on the disk when link(), unlink(), open() and rename()
+calls are used. But Linux writes them to the disk asynchronously. My library
+loaded before libc changes those calls to do the corresponding directory
+writes too. Then qmail should be reliable against power outages also in
+Linux.
+
+This is a separate package from qmail. syncs.c and Makefile attached.
+"make install" installs both a shared and a static version of the library to
+/usr/lib. After that qmail should be recompiled with the little patch (also
+attached). (If you would prefer to link the library statically, just remove
+the shared library. Then qmail uses the static one.)
+
+By the way, Linus's patch for speeding up the directory syncs applies
+directly to the release kernels 2.0.3x too. I attach it too.
+
+Thanks to Linus and Bruce.
+
diff -urN qmail-1.03-orig/TARGETS qmail-1.03/TARGETS
--- qmail-1.03-orig/TARGETS	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/TARGETS	2003-10-03 14:08:48.000000000 -0400
@@ -15,6 +15,14 @@
 slurpclose.o
 make-makelib
 makelib
+maildirflags.o
+maildirparsequota.o
+maildiropen.o
+maildirgetquota.o
+maildirquota.o
+overmaildirquota.o
+strtimet.o
+strpidt.o
 case_diffb.o
 case_diffs.o
 case_lowerb.o
@@ -168,6 +176,8 @@
 constmap.o
 timeoutread.o
 timeoutwrite.o
+tls.o
+ssl_timeoutio.o
 timeoutconn.o
 tcpto.o
 dns.o
@@ -250,6 +260,7 @@
 qmail-qmtpd.o
 rcpthosts.o
 qmail-qmtpd
+base64.o
 qmail-smtpd.o
 qmail-smtpd
 sendmail.o
@@ -320,6 +331,7 @@
 binm2+df
 binm3
 binm3+df
+Makefile-cert
 it
 qmail-local.0
 qmail-lspawn.0
@@ -385,3 +397,6 @@
 man
 setup
 check
+libqmailio.a
+libqmailio.o
+libqmailio.so
diff -urN qmail-1.03-orig/TARGETS.orig qmail-1.03/TARGETS.orig
--- qmail-1.03-orig/TARGETS.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/TARGETS.orig	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,391 @@
+auto-ccld.sh
+make-load
+find-systype
+systype
+load
+make-compile
+compile
+fork.h
+qmail-local.o
+qmail.o
+quote.o
+now.o
+gfrom.o
+myctime.o
+slurpclose.o
+make-makelib
+makelib
+case_diffb.o
+case_diffs.o
+case_lowerb.o
+case_lowers.o
+case_starts.o
+case.a
+getln.o
+getln2.o
+getln.a
+subgetopt.o
+sgetopt.o
+getopt.a
+sig_alarm.o
+hassgprm.h
+sig_block.o
+hassgact.h
+sig_catch.o
+sig_pause.o
+sig_pipe.o
+sig_child.o
+sig_hup.o
+sig_term.o
+sig_bug.o
+sig_misc.o
+sig.a
+open_append.o
+open_excl.o
+open_read.o
+open_trunc.o
+open_write.o
+open.a
+seek_cur.o
+seek_end.o
+seek_set.o
+seek_trunc.o
+seek.a
+hasflock.h
+lock_ex.o
+lock_exnb.o
+lock_un.o
+lock.a
+fd_copy.o
+fd_move.o
+fd.a
+haswaitp.h
+wait_pid.o
+wait_nohang.o
+wait.a
+env.o
+envread.o
+env.a
+stralloc_eady.o
+stralloc_pend.o
+stralloc_copy.o
+stralloc_opys.o
+stralloc_opyb.o
+stralloc_cat.o
+stralloc_cats.o
+stralloc_catb.o
+stralloc_arts.o
+stralloc.a
+alloc.o
+alloc_re.o
+alloc.a
+strerr_sys.o
+strerr_die.o
+strerr.a
+substdio.o
+substdi.o
+substdo.o
+subfderr.o
+subfdout.o
+subfdouts.o
+subfdin.o
+subfdins.o
+substdio_copy.o
+substdio.a
+error.o
+error_str.o
+error_temp.o
+error.a
+str_len.o
+str_diff.o
+str_diffn.o
+str_cpy.o
+str_chr.o
+str_rchr.o
+str_start.o
+byte_chr.o
+byte_rchr.o
+byte_diff.o
+byte_copy.o
+byte_cr.o
+byte_zero.o
+str.a
+fmt_str.o
+fmt_strn.o
+fmt_uint.o
+fmt_uint0.o
+fmt_ulong.o
+scan_ulong.o
+scan_8long.o
+fs.a
+datetime.o
+datetime_un.o
+datetime.a
+auto-str.o
+auto-str
+auto_qmail.c
+auto_qmail.o
+auto-int8.o
+auto-int8
+auto_patrn.c
+auto_patrn.o
+socket.lib
+qmail-local
+uint32.h
+qmail-lspawn.o
+select.h
+chkspawn.o
+auto-int.o
+auto-int
+auto_spawn.c
+auto_spawn.o
+chkspawn
+spawn.o
+chkshsgr.o
+chkshsgr
+hasshsgr.h
+prot.o
+coe.o
+cdb_hash.o
+cdb_unpack.o
+cdb_seek.o
+cdb.a
+auto-uid.o
+auto-uid
+auto-gid.o
+auto-gid
+auto_uids.c
+auto_uids.o
+qmail-lspawn
+qmail-getpw.o
+auto_break.c
+auto_break.o
+auto_usera.c
+auto_usera.o
+qmail-getpw
+qmail-remote.o
+control.o
+constmap.o
+timeoutread.o
+timeoutwrite.o
+timeoutconn.o
+tcpto.o
+dns.o
+ip.o
+ipalloc.o
+hassalen.h
+ipme.o
+ndelay.o
+ndelay_off.o
+ndelay.a
+dns.lib
+qmail-remote
+qmail-rspawn.o
+tcpto_clean.o
+qmail-rspawn
+direntry.h
+qmail-clean.o
+fmtqfn.o
+auto_split.c
+auto_split.o
+qmail-clean
+qmail-send.o
+qsutil.o
+newfield.o
+prioq.o
+hasmkffo.h
+fifo.o
+hasnpbg1.h
+trigger.o
+readsubdir.o
+date822fmt.o
+qmail-send
+qmail-start.o
+qmail-start
+splogger.o
+syslog.lib
+splogger
+qmail-queue.o
+triggerpull.o
+qmail-queue
+qmail-inject.o
+headerbody.o
+hfield.o
+token822.o
+qmail-inject
+predate.o
+predate
+datemail
+mailsubj
+qmail-upq
+qmail-showctl.o
+qmail-showctl
+qmail-newu.o
+cdbmss.o
+cdbmake_pack.o
+cdbmake_hash.o
+cdbmake_add.o
+cdbmake.a
+qmail-newu
+qmail-pw2u.o
+qmail-pw2u
+qmail-qread.o
+qmail-qread
+qmail-qstat
+qmail-tcpto.o
+qmail-tcpto
+qmail-tcpok.o
+qmail-tcpok
+qmail-pop3d.o
+commands.o
+maildir.o
+qmail-pop3d
+qmail-popup.o
+qmail-popup
+qmail-qmqpc.o
+qmail-qmqpc
+qmail-qmqpd.o
+received.o
+qmail-qmqpd
+qmail-qmtpd.o
+rcpthosts.o
+qmail-qmtpd
+base64.o
+qmail-smtpd.o
+qmail-smtpd
+sendmail.o
+sendmail
+tcp-env.o
+remoteinfo.o
+tcp-env
+qmail-newmrh.o
+qmail-newmrh
+config
+config-fast
+dnscname.o
+dnsdoe.o
+dnscname
+dnsptr.o
+dnsptr
+dnsip.o
+dnsip
+dnsmxip.o
+dnsmxip
+dnsfq.o
+dnsfq
+hostname.o
+hostname
+ipmeprint.o
+ipmeprint
+qreceipt.o
+qreceipt
+qsmhook.o
+qsmhook
+qbiff.o
+qbiff
+forward.o
+forward
+preline.o
+preline
+condredirect.o
+condredirect
+bouncesaying.o
+bouncesaying
+except.o
+except
+maildirmake.o
+maildirmake
+maildir2mbox.o
+maildir2mbox
+maildirwatch.o
+maildirwatch
+qail
+elq
+pinq
+idedit.o
+idedit
+install-big.o
+install.o
+install-big
+hier.o
+install
+instcheck.o
+instcheck
+home
+home+df
+proc
+proc+df
+binm1
+binm1+df
+binm2
+binm2+df
+binm3
+binm3+df
+it
+qmail-local.0
+qmail-lspawn.0
+qmail-getpw.8
+qmail-getpw.0
+qmail-remote.0
+qmail-rspawn.0
+qmail-clean.0
+qmail-send.8
+qmail-send.0
+qmail-start.8
+qmail-start.0
+splogger.0
+qmail-queue.0
+qmail-inject.0
+mailsubj.0
+qmail-showctl.0
+qmail-newu.8
+qmail-newu.0
+qmail-pw2u.8
+qmail-pw2u.0
+qmail-qread.0
+qmail-qstat.0
+qmail-tcpto.0
+qmail-tcpok.0
+qmail-pop3d.0
+qmail-popup.0
+qmail-qmqpc.0
+qmail-qmqpd.0
+qmail-qmtpd.0
+qmail-smtpd.0
+tcp-env.0
+qmail-newmrh.8
+qmail-newmrh.0
+qreceipt.0
+qbiff.0
+forward.0
+preline.0
+condredirect.0
+bouncesaying.0
+except.0
+maildirmake.0
+maildir2mbox.0
+maildirwatch.0
+qmail.0
+qmail-limits.7
+qmail-limits.0
+qmail-log.0
+qmail-control.5
+qmail-control.0
+qmail-header.0
+qmail-users.5
+qmail-users.0
+dot-qmail.5
+dot-qmail.0
+qmail-command.0
+tcp-environ.0
+maildir.0
+mbox.0
+addresses.0
+envelopes.0
+forgeries.0
+man
+setup
+check
+libqmailio.a
+libqmailio.o
+libqmailio.so
diff -urN qmail-1.03-orig/base64.c qmail-1.03/base64.c
--- qmail-1.03-orig/base64.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/base64.c	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,90 @@
+#include "base64.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "str.h"
+
+static char *b64alpha =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define B64PAD '='
+
+/* returns 0 ok, 1 illegal, -1 problem */
+
+int b64decode(in,l,out)
+const unsigned char *in;
+int l;
+stralloc *out; /* not null terminated */
+{
+  int i, j;
+  unsigned char a[4];
+  unsigned char b[3];
+  char *s;
+
+  if (l == 0)
+  {
+    if (!stralloc_copys(out,"")) return -1;
+    return 0;
+  }
+
+  if (!stralloc_ready(out,l + 2)) return -1; /* XXX generous */
+  s = out->s;
+
+  for (i = 0;i < l;i += 4) {
+    for (j = 0;j < 4;j++)
+      if ((i + j) < l && in[i + j] != B64PAD)
+      {
+        a[j] = str_chr(b64alpha,in[i + j]);
+        if (a[j] > 63) return 1;
+      }
+      else a[j] = 0;
+
+    b[0] = (a[0] << 2) | (a[1] >> 4);
+    b[1] = (a[1] << 4) | (a[2] >> 2);
+    b[2] = (a[2] << 6) | (a[3]);
+
+    *s++ = b[0];
+
+    if (in[i + 1] == B64PAD) break;
+    *s++ = b[1];
+
+    if (in[i + 2] == B64PAD) break;
+    *s++ = b[2];
+  }
+  out->len = s - out->s;
+  while (out->len && !out->s[out->len - 1]) --out->len; /* XXX avoid? */
+  return 0;
+}
+
+int b64encode(in,out)
+stralloc *in;
+stralloc *out; /* not null terminated */
+{
+  unsigned char a, b, c;
+  int i;
+  char *s;
+
+  if (in->len == 0)
+  {
+    if (!stralloc_copys(out,"")) return -1;
+    return 0;
+  }
+
+  if (!stralloc_ready(out,in->len / 3 * 4 + 4)) return -1;
+  s = out->s;
+
+  for (i = 0;i < in->len;i += 3) {
+    a = in->s[i];
+    b = i + 1 < in->len ? in->s[i + 1] : 0;
+    c = i + 2 < in->len ? in->s[i + 2] : 0;
+
+    *s++ = b64alpha[a >> 2];
+    *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
+
+    if (i + 1 >= in->len) *s++ = B64PAD;
+    else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
+
+    if (i + 2 >= in->len) *s++ = B64PAD;
+    else *s++ = b64alpha[c & 63];
+  }
+  out->len = s - out->s;
+  return 0;
+}
diff -urN qmail-1.03-orig/base64.h qmail-1.03/base64.h
--- qmail-1.03-orig/base64.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/base64.h	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,7 @@
+#ifndef BASE64_H
+#define BASE64_H
+
+extern int b64decode();
+extern int b64encode();
+
+#endif
diff -urN qmail-1.03-orig/case_startb.c qmail-1.03/case_startb.c
--- qmail-1.03-orig/case_startb.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/case_startb.c	2003-10-07 17:24:42.000000000 -0400
@@ -0,0 +1,21 @@
+#include "case.h"
+
+int case_startb(s,len,t)
+register char *s;
+unsigned int len;
+register char *t;
+{
+  register unsigned char x;
+  register unsigned char y;
+
+  for (;;) {
+    y = *t++ - 'A';
+    if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+    if (!y) return 1;
+    if (!len) return 0;
+    --len;
+    x = *s++ - 'A';
+    if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+    if (x != y) return 0;
+  }
+}
Binary files qmail-1.03-orig/case_startb.o and qmail-1.03/case_startb.o differ
diff -urN qmail-1.03-orig/cdb_seek.c qmail-1.03/cdb_seek.c
--- qmail-1.03-orig/cdb_seek.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/cdb_seek.c	2003-10-03 14:09:42.000000000 -0400
@@ -1,6 +1,5 @@
 #include <sys/types.h>
 #include <errno.h>
-extern int errno;
 #include "cdb.h"
 
 #ifndef SEEK_SET
diff -urN qmail-1.03-orig/chkspawn.c qmail-1.03/chkspawn.c
--- qmail-1.03-orig/chkspawn.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/chkspawn.c	2003-10-03 14:08:48.000000000 -0400
@@ -22,8 +22,8 @@
     _exit(1);
   }
 
-  if (auto_spawn > 255) {
-    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n");
+  if (auto_spawn > 65000) {
+    substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 65000.\n");
     substdio_flush(subfderr);
     _exit(1);
   }
diff -urN qmail-1.03-orig/conf-cc qmail-1.03/conf-cc
--- qmail-1.03-orig/conf-cc	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/conf-cc	2003-10-03 14:08:48.000000000 -0400
@@ -1,3 +1,3 @@
-cc -O2
+cc -O2 -DTLS=20021228 -I/usr/local/ssl/include
 
 This will be used to compile .c files.
diff -urN qmail-1.03-orig/conf-spawn qmail-1.03/conf-spawn
--- qmail-1.03-orig/conf-spawn	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/conf-spawn	2003-10-03 14:08:48.000000000 -0400
@@ -1,4 +1,4 @@
-120
+500
 
 This is a silent concurrency limit. You can't set it above 255. On some
 systems you can't set it above 125. qmail will refuse to compile if the
diff -urN qmail-1.03-orig/conf-vpop-ld qmail-1.03/conf-vpop-ld
--- qmail-1.03-orig/conf-vpop-ld	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/conf-vpop-ld	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,6 @@
+-lvpopmail -lcrypt
+
+These are the additional libraries to link in when building qmail-smtpd
+for the vpopmail chkuser patch.  The path to ~vpopmail/lib is already
+specified in the makefile.
+
diff -urN qmail-1.03-orig/conf-vpopmail qmail-1.03/conf-vpopmail
--- qmail-1.03-orig/conf-vpopmail	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/conf-vpopmail	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,5 @@
+/var/vpopmail
+
+This is the vpopmail home directory.  The vpopmail chkuser patch
+needs to know where to find the vpopmail includes and libraries
+
diff -urN qmail-1.03-orig/control.c qmail-1.03/control.c
--- qmail-1.03-orig/control.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/control.c	2003-10-03 14:08:48.000000000 -0400
@@ -85,6 +85,40 @@
  return 1;
 }
 
+int control_readnativefile(sa,fn)
+stralloc *sa;
+char *fn;
+{
+ substdio ss;
+ int fd;
+ int match;
+
+ if (!stralloc_copys(sa,"")) return -1;
+
+ fd = open_read(fn);
+ if (fd == -1) 
+  {
+   if (errno == error_noent)
+    {
+     if (!stralloc_0(sa)) return -1;
+     return 1;
+    }
+   return -1;
+  }
+
+ substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf));
+
+ for (;;)
+  {
+   if (getln(&ss,&line,&match,'\n') == -1) break;
+   if (!match && !line.len) { close(fd); return 1; }
+   if (!stralloc_cat(sa,&line)) break;
+   if (!match) { close(fd); return 1; }
+  }
+ close(fd);
+ return -1;
+}
+
 int control_readfile(sa,fn,flagme)
 stralloc *sa;
 char *fn;
diff -urN qmail-1.03-orig/control.h qmail-1.03/control.h
--- qmail-1.03-orig/control.h	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/control.h	2003-10-03 14:08:48.000000000 -0400
@@ -5,6 +5,7 @@
 extern int control_readline();
 extern int control_rldef();
 extern int control_readint();
+extern int control_readnativefile();
 extern int control_readfile();
 
 #endif
diff -urN qmail-1.03-orig/date822fmt.c qmail-1.03/date822fmt.c
--- qmail-1.03-orig/date822fmt.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/date822fmt.c	2003-10-03 14:08:48.000000000 -0400
@@ -1,3 +1,4 @@
+#include <time.h>
 #include "datetime.h"
 #include "fmt.h"
 #include "date822fmt.h"
@@ -12,18 +13,51 @@
 {
   unsigned int i;
   unsigned int len;
+  time_t now;
+  datetime_sec utc;
+  datetime_sec local;
+  struct tm *tm;
+  struct datetime new_dt;
+  int minutes;
+
+  utc = datetime_untai(dt);
+  now = (time_t)utc;
+  tm = localtime(&now);
+  new_dt.year = tm->tm_year;
+  new_dt.mon = tm->tm_mon;
+  new_dt.mday = tm->tm_mday;
+  new_dt.hour = tm->tm_hour;
+  new_dt.min = tm->tm_min;
+  new_dt.sec = tm->tm_sec;
+  local = datetime_untai(&new_dt);
+
   len = 0;
-  i = fmt_uint(s,dt->mday); len += i; if (s) s += i;
+  i = fmt_uint(s,new_dt.mday); len += i; if (s) s += i;
   i = fmt_str(s," "); len += i; if (s) s += i;
-  i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i;
+  i = fmt_str(s,montab[new_dt.mon]); len += i; if (s) s += i;
   i = fmt_str(s," "); len += i; if (s) s += i;
-  i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i;
+  i = fmt_uint(s,new_dt.year + 1900); len += i; if (s) s += i;
   i = fmt_str(s," "); len += i; if (s) s += i;
-  i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i;
+  i = fmt_uint0(s,new_dt.hour,2); len += i; if (s) s += i;
   i = fmt_str(s,":"); len += i; if (s) s += i;
-  i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i;
+  i = fmt_uint0(s,new_dt.min,2); len += i; if (s) s += i;
   i = fmt_str(s,":"); len += i; if (s) s += i;
-  i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i;
-  i = fmt_str(s," -0000\n"); len += i; if (s) s += i;
+  i = fmt_uint0(s,new_dt.sec,2); len += i; if (s) s += i;
+
+  if (local < utc) {
+    minutes = (utc - local + 30) / 60;
+    i = fmt_str(s," -"); len += i; if (s) s += i;
+    i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i;
+    i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i;
+  }
+  else {
+    minutes = (local - utc + 30) / 60;
+    i = fmt_str(s," +"); len += i; if (s) s += i;
+    i = fmt_uint0(s,minutes / 60,2); len += i; if (s) s += i;
+    i = fmt_uint0(s,minutes % 60,2); len += i; if (s) s += i;
+  }
+
+  i = fmt_str(s,"\n"); len += i; if (s) s += i;
+
   return len;
 }
diff -urN qmail-1.03-orig/dns.c qmail-1.03/dns.c
--- qmail-1.03-orig/dns.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/dns.c	2003-10-03 14:09:43.000000000 -0400
@@ -7,8 +7,6 @@
 #include <errno.h>
 extern int res_query();
 extern int res_search();
-extern int errno;
-extern int h_errno;
 #include "ip.h"
 #include "ipalloc.h"
 #include "fmt.h"
@@ -21,10 +19,12 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }
 
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;
+static u_long saveresoptions;
 
 static int numanswers;
 static char name[MAXDNAME];
@@ -45,18 +45,33 @@
  errno = 0;
  if (!stralloc_copy(&glue,domain)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+  if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+   responsebuflen = PACKETSZ+1;
+  else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+     (responselen > 0 && (((HEADER *)response.buf)->tc)))
+  {
+   if (responsebuflen < 65536)
+    if (alloc_re(&response.buf, responsebuflen, 65536))
+     responsebuflen = 65536;
+    else return DNS_MEM;
+    saveresoptions = _res.options;
+    _res.options |= RES_USEVC;
+    responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+    _res.options = saveresoptions;
+  }
  if (responselen <= 0)
   {
    if (errno == ECONNREFUSED) return DNS_SOFT;
    if (h_errno == TRY_AGAIN) return DNS_SOFT;
    return DNS_HARD;
   }
- if (responselen >= sizeof(response))
-   responselen = sizeof(response);
  responseend = response.buf + responselen;
  responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
  while (n-- > 0)
   {
    i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -66,7 +81,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -269,12 +284,11 @@
 int pref;
 {
  int r;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
 
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -293,9 +307,16 @@
    ix.ip = ip;
    ix.pref = pref;
    if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
+   if (r == 1) {
+#ifdef IX_FQDN
+     ix.fqdn = glue.s;
+#endif
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
   }
+  }
+#ifdef IX_FQDN
+ glue.s = 0;
+#endif
  return 0;
 }
 
@@ -315,7 +336,7 @@
 {
  int r;
  struct mx { stralloc sa; unsigned short p; } *mx;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
  int nummx;
  int i;
  int j;
@@ -327,7 +348,6 @@
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
diff -urN qmail-1.03-orig/error.3 qmail-1.03/error.3
--- qmail-1.03-orig/error.3	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/error.3	2003-10-03 14:09:43.000000000 -0400
@@ -3,8 +3,7 @@
 error \- syscall error codes
 .SH SYNTAX
 .B #include <error.h>
-
-extern int \fBerrno\fP;
+.B #include <errno.h>
 
 extern int \fBerror_intr\fP;
 .br
diff -urN qmail-1.03-orig/error.h qmail-1.03/error.h
--- qmail-1.03-orig/error.h	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/error.h	2003-10-03 14:09:43.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef ERROR_H
 #define ERROR_H
 
-extern int errno;
+#include <errno.h>
 
 extern int error_intr;
 extern int error_nomem;
diff -urN qmail-1.03-orig/ipalloc.h qmail-1.03/ipalloc.h
--- qmail-1.03-orig/ipalloc.h	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/ipalloc.h	2003-10-03 14:08:48.000000000 -0400
@@ -3,7 +3,15 @@
 
 #include "ip.h"
 
+#ifdef TLS
+# define IX_FQDN 1
+#endif
+
+#ifdef IX_FQDN
+struct ip_mx { struct ip_address ip; int pref; char *fqdn; } ;
+#else
 struct ip_mx { struct ip_address ip; int pref; } ;
+#endif
 
 #include "gen_alloc.h"
 
diff -urN qmail-1.03-orig/ipme.c qmail-1.03/ipme.c
--- qmail-1.03-orig/ipme.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/ipme.c	2003-10-03 14:08:48.000000000 -0400
@@ -46,6 +46,11 @@
   ipme.len = 0;
   ix.pref = 0;
  
+  /* 0.0.0.0 is a special address which always refers to 
+   * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a.
+  */
+  byte_copy(&ix.ip,4,"\0\0\0\0");
+  if (!ipalloc_append(&ipme,&ix)) { return 0; }
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
  
   len = 256;
diff -urN qmail-1.03-orig/libqmailio.c qmail-1.03/libqmailio.c
--- qmail-1.03-orig/libqmailio.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/libqmailio.c	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,71 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#define open XXX_open
+#include <fcntl.h>
+#undef open
+#include <unistd.h>
+#include <string.h>
+#include <syscall.h>
+#include <stdio.h>
+
+static int fdirsyncfn(const char *filename)
+{
+   char dirname[MAXPATHLEN];
+   char *slash;
+   int retval;
+   int dirfd;
+   
+   strncpy(dirname,filename,MAXPATHLEN);
+   dirname[MAXPATHLEN-1]=0;
+   if ((slash=strrchr(dirname,'/'))) {
+      if (slash == dirname)
+	strcpy(dirname,"/");
+      else
+	*slash = 0;
+   } else
+     strcpy(dirname,".");
+   if ((dirfd = syscall(SYS_open,dirname,O_RDONLY)) == -1)
+     return -1;
+   retval = fsync(dirfd);
+   syscall(SYS_close,dirfd);      
+   return retval;
+}
+
+int open(const char *file,int oflag,mode_t mode)
+{
+   int fd;
+   
+   if ((fd = syscall(SYS_open,file,oflag,mode)) == -1)
+     return fd;
+   if (oflag & (O_WRONLY | O_RDWR))
+     if (fdirsyncfn(file) == -1) {
+	syscall(SYS_close,fd);
+	return -1;
+     }
+   return fd;
+}
+
+int link(const char *oldpath,const char *newpath)
+{
+   if(syscall(SYS_link,oldpath,newpath) == -1)
+     return -1;
+   return fdirsyncfn(newpath);
+}
+
+int unlink(const char *path)
+{
+   if(syscall(SYS_unlink,path) == -1)
+     return -1;
+   return fdirsyncfn(path);
+}
+
+int rename(const char *oldpath,const char *newpath)
+{
+   if (syscall(SYS_rename,oldpath,newpath) == -1)
+     return -1;
+   if (fdirsyncfn(newpath) == -1)
+     return -1;
+   return fdirsyncfn(oldpath);
+}
+
diff -urN qmail-1.03-orig/maildirflags.c qmail-1.03/maildirflags.c
--- qmail-1.03-orig/maildirflags.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirflags.c	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include	<sys/types.h>
+#include	<string.h>
+
+static const char rcsid[]="$Id: maildirflags.c,v 1.1 2000/10/07 01:10:19 mrsam Exp $";
+
+int maildir_hasflag(const char *filename, char flag)
+{
+	const char *p=strrchr(filename, '/');
+
+	if (p)
+		filename=p+1;
+
+	p=strrchr(p, ':');
+	if (p && strncmp(p, ":2,", 3) == 0 &&
+	    strchr(p+3, flag))
+		return (1);
+	return (0);
+}
diff -urN qmail-1.03-orig/maildirgetquota.c qmail-1.03/maildirgetquota.c
--- qmail-1.03-orig/maildirgetquota.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirgetquota.c	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#include	"maildirgetquota.h"
+#include	"maildirmisc.h"
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#include	<stdlib.h>
+#include	<string.h>
+#include	<fcntl.h>
+#include	<sys/types.h>
+#include	<sys/stat.h>
+
+int	maildir_getquota(const char *dir, char buf[QUOTABUFSIZE])
+{
+char	*p;
+struct	stat	stat_buf;
+int	n;
+int	l;
+
+	p=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+	if (!p)	return (-1);
+
+	strcat(strcpy(p, dir), "/maildirfolder");
+	if (stat(p, &stat_buf) == 0)
+	{
+		strcat(strcpy(p, dir), "/..");
+		n=maildir_getquota(p, buf);
+		free(p);
+		return (n);
+	}
+
+	strcat(strcpy(p, dir), "/maildirsize");
+	n=maildir_safeopen(p, O_RDONLY, 0);
+	free(p);
+	if (n < 0)	return (n);
+	if ((l=read(n, buf, QUOTABUFSIZE-1)) < 0)
+	{
+		close(n);
+		return (-1);
+	}
+	close(n);
+	for (n=0; n<l; n++)
+		if (buf[n] == '\n')	break;
+	buf[n]=0;
+	return (0);
+}
diff -urN qmail-1.03-orig/maildirgetquota.h qmail-1.03/maildirgetquota.h
--- qmail-1.03-orig/maildirgetquota.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirgetquota.h	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,30 @@
+#ifndef	maildirgetquota_h
+#define	maildirgetquota_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+#include	<sys/types.h>
+#include	<stdio.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+static const char maildirgetquota_h_rcsid[]="$Id: maildirgetquota.h,v 1.5 1999/12/06 13:21:05 mrsam Exp $";
+
+#define	QUOTABUFSIZE	256
+
+int maildir_getquota(const char *, char [QUOTABUFSIZE]);
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -urN qmail-1.03-orig/maildirmisc.h qmail-1.03/maildirmisc.h
--- qmail-1.03-orig/maildirmisc.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirmisc.h	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,145 @@
+#ifndef	maildirmisc_h
+#define	maildirmisc_h
+
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+static const char maildirmisc_h_rcsid[]="$Id: maildirmisc.h,v 1.8 2000/12/25 17:33:06 mrsam Exp $";
+
+/*
+**
+** Miscellaneous maildir-related code
+**
+*/
+
+/* Some special folders */
+
+#define	INBOX	"INBOX"
+#define	DRAFTS	"Drafts"
+#define	SENT	"Sent"
+#define	TRASH	"Trash"
+
+#define	SHAREDSUBDIR	"shared-folders"
+
+char *maildir_folderdir(const char *,		/* maildir */
+	const char *);				/* folder name */
+	/* Returns the directory corresponding to foldername (foldername is
+	** checked to make sure that it's a valid name, else we set errno
+	** to EINVAL, and return (0).
+	*/
+
+char *maildir_filename(const char *,		/* maildir */
+	const char *,				/* folder */
+	const char *);				/* filename */
+	/*
+	** Builds the filename to this message, suitable for opening.
+	** If the file doesn't appear to be there, search the maildir to
+	** see if someone changed the flags, and return the current filename.
+	*/
+
+int maildir_safeopen(const char *,		/* filename */
+	int,				/* mode */
+	int);				/* perm */
+
+/*
+**	Same arguments as open().  When we're accessing a shared maildir,
+**	prevent someone from playing cute and dumping a bunch of symlinks
+**	in there.  This function will open the indicate file only if the
+**	last component is not a symlink.
+**	This is implemented by opening the file with O_NONBLOCK (to prevent
+**	a DOS attack of someone pointing the symlink to a pipe, causing
+**	the open to hang), clearing O_NONBLOCK, then stat-int the file
+**	descriptor, lstating the filename, and making sure that dev/ino
+**	match.
+*/
+
+int maildir_semisafeopen(const char *,	/* filename */
+	int,				/* mode */
+	int);				/* perm */
+
+/*
+** Same thing, except that we allow ONE level of soft link indirection,
+** because we're reading from our own maildir, which points to the
+** message in the sharable maildir.
+*/
+
+int maildir_mkdir(const char *);	/* directory */
+/*
+** Create maildir including all subdirectories in the path (like mkdir -p)
+*/
+
+void maildir_purgetmp(const char *);		/* maildir */
+	/* purges old stuff out of tmp */
+
+void maildir_purge(const char *,		/* directory */
+	unsigned);				/* time_t to purge */
+
+void maildir_getnew(const char *,		/* maildir */
+	const char *);				/* folder */
+	/* move messages from new to cur */
+
+int maildir_deletefolder(const char *,		/* maildir */
+	const char *);				/* folder */
+	/* deletes a folder */
+
+int maildir_mddelete(const char *);	/* delete a maildir folder by path */
+
+void maildir_list_sharable(const char *,	/* maildir */
+	void (*)(const char *, void *),		/* callback function */
+	void *);				/* 2nd arg to callback func */
+	/* list sharable folders */
+
+int maildir_shared_subscribe(const char *,	/* maildir */
+		const char *);			/* folder */
+	/* subscribe to a shared folder */
+
+void maildir_list_shared(const char *,		/* maildir */
+	void (*)(const char *, void *),		/* callback function */
+	void *);			/* 2nd arg to the callback func */
+	/* list subscribed folders */
+
+int maildir_shared_unsubscribe(const char *,	/* maildir */
+		const char *);			/* folder */
+	/* unsubscribe from a shared folder */
+
+char *maildir_shareddir(const char *,		/* maildir */
+	const char *);				/* folder */
+	/*
+	** Validate and return a path to a shared folder.  folderdir must be
+	** a name of a valid shared folder.
+	*/
+
+void maildir_shared_sync(const char *);		/* maildir */
+	/* "sync" the shared folder */
+
+int maildir_sharedisro(const char *);		/* maildir */
+	/* maildir is a shared read-only folder */
+
+int maildir_unlinksharedmsg(const char *);	/* filename */
+	/* Remove a message from a shared folder */
+
+/* Internal function that reads a symlink */
+
+char *maildir_getlink(const char *);
+
+	/* Determine whether the maildir filename has a certain flag */
+
+int maildir_hasflag(const char *filename, char);
+
+#define	MAILDIR_DELETED(f)	maildir_hasflag((f), 'T')
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -urN qmail-1.03-orig/maildiropen.c qmail-1.03/maildiropen.c
--- qmail-1.03-orig/maildiropen.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildiropen.c	2003-10-03 14:08:48.000000000 -0400
@@ -0,0 +1,133 @@
+/*
+** Copyright 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include	<sys/types.h>
+#include	<sys/stat.h>
+#include	<string.h>
+#include	<stdlib.h>
+#include	<time.h>
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#include	<stdio.h>
+#include	<ctype.h>
+#include	<errno.h>
+#include	<fcntl.h>
+
+#include	"maildirmisc.h"
+
+static const char rcsid[]="$Id: maildiropen.c,v 1.7 2000/12/10 04:43:44 mrsam Exp $";
+
+char *maildir_getlink(const char *filename)
+{
+#if     HAVE_READLINK
+size_t	bufsiz;
+char	*buf;
+
+	bufsiz=0;
+	buf=0;
+
+	for (;;)
+	{
+	int	n;
+
+		if (buf)	free(buf);
+		bufsiz += 256;
+		if ((buf=malloc(bufsiz)) == 0)
+		{
+			perror("malloc");
+			return (0);
+		}
+		if ((n=readlink(filename, buf, bufsiz)) < 0)
+		{
+			free(buf);
+			return (0);
+		}
+		if (n < bufsiz)
+		{
+			buf[n]=0;
+			break;
+		}
+	}
+	return (buf);
+#else
+	return (0);
+#endif
+}
+
+int maildir_semisafeopen(const char *path, int mode, int perm)
+{
+
+#if	HAVE_READLINK
+
+char	*l=maildir_getlink(path);
+
+	if (l)
+	{
+	int	f;
+
+		if (*l != '/')
+		{
+		char	*q=malloc(strlen(path)+strlen(l)+2);
+		char	*s;
+
+			if (!q)
+			{
+				free(l);
+				return (-1);
+			}
+
+			strcpy(q, path);
+			if ((s=strchr(q, '/')) != 0)
+				s[1]=0;
+			else	*q=0;
+			strcat(q, l);
+			free(l);
+			l=q;
+		}
+
+		f=maildir_safeopen(l, mode, perm);
+
+		free(l);
+		return (f);
+	}
+#endif
+
+	return (maildir_safeopen(path, mode, perm));
+}
+		
+int maildir_safeopen(const char *path, int mode, int perm)
+{
+struct	stat	stat1, stat2;
+
+int	fd=open(path, mode
+#ifdef	O_NONBLOCK
+			| O_NONBLOCK
+#else
+			| O_NDELAY
+#endif
+				, perm);
+
+	if (fd < 0)	return (fd);
+	if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, &stat1)
+	    || lstat(path, &stat2))
+	{
+		close(fd);
+		return (-1);
+	}
+
+	if (stat1.st_dev != stat2.st_dev || stat1.st_ino != stat2.st_ino)
+	{
+		close(fd);
+		errno=ENOENT;
+		return (-1);
+	}
+
+	return (fd);
+}
diff -urN qmail-1.03-orig/maildirparsequota.c qmail-1.03/maildirparsequota.c
--- qmail-1.03-orig/maildirparsequota.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirparsequota.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,44 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include	"maildirquota.h"
+#include	<stdlib.h>
+#include	<string.h>
+
+static const char rcsid[]="$Id: maildirparsequota.c,v 1.2 1999/12/06 13:21:05 mrsam Exp $";
+
+int maildir_parsequota(const char *n, unsigned long *s)
+{
+const char *o;
+int	yes;
+
+	if ((o=strrchr(n, '/')) == 0)	o=n;
+
+	for (; *o; o++)
+		if (*o == ':')	break;
+	yes=0;
+	for ( ; o >= n; --o)
+	{
+		if (*o == '/')	break;
+
+		if (*o == ',' && o[1] == 'S' && o[2] == '=')
+		{
+			yes=1;
+			o += 3;
+			break;
+		}
+	}
+	if (yes)
+	{
+		*s=0;
+		while (*o >= '0' && *o <= '9')
+			*s= *s*10 + (*o++ - '0');
+		return (0);
+	}
+	return (-1);
+}
diff -urN qmail-1.03-orig/maildirquota.c qmail-1.03/maildirquota.c
--- qmail-1.03-orig/maildirquota.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirquota.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,685 @@
+/*
+** Copyright 1998 - 2002 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+/* #if HAVE_DIRENT_H */
+#include <dirent.h>
+#define NAMLEN(dirent) strlen((dirent)->d_name)
+/* #else
+#define dirent direct
+#define NAMLEN(dirent) (dirent)->d_namlen
+#if HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif
+#if HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#if HAVE_NDIR_H
+#include <ndir.h>
+#endif
+#endif */
+#include	<sys/types.h>
+/* #if	HAVE_SYS_STAT_H */
+#include	<sys/stat.h>
+/* #endif */
+#include	<sys/uio.h>
+
+#include	"maildirquota.h"
+#include	"maildirmisc.h"
+#include	<stdio.h>
+#include	<stdlib.h>
+#include	<string.h>
+#include	<errno.h>
+/* #if	HAVE_FCNTL_H */
+#include	<fcntl.h>
+/* #endif */
+#if	HAVE_UNISTD_H
+#include	<unistd.h>
+#endif
+#include	<time.h>
+#include	"numlib.h"
+
+static const char rcsid[]="$Id: maildirquota.c,v 1.9 2002/05/01 04:05:33 mrsam Exp $";
+
+/* Read the maildirsize file */
+
+int maildirsize_read(const char *filename,	/* The filename */
+	int *fdptr,	/* Keep the file descriptor open */
+	off_t *sizeptr,	/* Grand total of maildir size */
+	unsigned *cntptr, /* Grand total of message count */
+	unsigned *nlines, /* # of lines in maildirsize */
+	struct stat *statptr)	/* The stats on maildirsize */
+{
+char buf[5120];
+int f;
+char *p;
+unsigned l;
+int n;
+int first;
+
+	if ((f=maildir_safeopen(filename, O_RDWR|O_APPEND, 0)) < 0)
+		return (-1);
+	p=buf;
+	l=sizeof(buf);
+
+	while (l)
+	{
+		n=read(f, p, l);
+		if (n < 0)
+		{
+			close(f);
+			return (-1);
+		}
+		if (n == 0)	break;
+		p += n;
+		l -= n;
+	}
+	if (l == 0 || fstat(f, statptr))	/* maildir too big */
+	{
+		close(f);
+		return (-1);
+	}
+
+	*sizeptr=0;
+	*cntptr=0;
+	*nlines=0;
+	*p=0;
+	p=buf;
+	first=1;
+	while (*p)
+	{
+	long n=0;
+	int c=0;
+	char	*q=p;
+
+		while (*p)
+			if (*p++ == '\n')
+			{
+				p[-1]=0;
+				break;
+			}
+
+		if (first)
+		{
+			first=0;
+			continue;
+		}
+		sscanf(q, "%ld %d", &n, &c);
+		*sizeptr += n;
+		*cntptr += c;
+		++ *nlines;
+	}
+	*fdptr=f;
+	return (0);
+}
+
+static char *makenewmaildirsizename(const char *, int *);
+static int countcurnew(const char *, time_t *, off_t *, unsigned *);
+static int countsubdir(const char *, const char *,
+		time_t *, off_t *, unsigned *);
+static int statcurnew(const char *, time_t *);
+static int statsubdir(const char *, const char *, time_t *);
+
+#define	MDQUOTA_SIZE	'S'	/* Total size of all messages in maildir */
+#define	MDQUOTA_BLOCKS	'B'	/* Total # of blocks for all messages in
+				maildir -- NOT IMPLEMENTED */
+#define	MDQUOTA_COUNT	'C'	/* Total number of messages in maildir */
+
+static int qcalc(off_t s, unsigned n, const char *quota, int *percentage)
+{
+off_t i;
+int	spercentage=0;
+int	npercentage=0;
+
+	errno=ENOSPC;
+	while (quota && *quota)
+	{
+		int x=1;
+
+		if (*quota < '0' || *quota > '9')
+		{
+			++quota;
+			continue;
+		}
+		i=0;
+		while (*quota >= '0' && *quota <= '9')
+			i=i*10 + (*quota++ - '0');
+		switch (*quota)	{
+		default:
+			if (i < s)
+			{
+				*percentage=100;
+				return (-1);
+			}
+
+			/*
+			** For huge quotas, over 20mb,
+			** divide numerator & denominator by 1024 to prevent
+			** an overflow when multiplying by 100
+			*/
+
+			x=1;
+			if (i > 20000000) x=1024;
+
+			spercentage = i ? (s/x) * 100 / (i/x):100;
+			break;
+		case 'C':
+
+			if (i < n)
+			{
+				*percentage=100;
+				return (-1);
+			}
+
+			/* Ditto */
+
+			x=1;
+			if (i > 20000000) x=1024;
+
+			npercentage = i ? ((off_t)n/x) * 100 / (i/x):100;
+			break;
+		}
+	}
+	*percentage = spercentage > npercentage ? spercentage:npercentage;
+	return (0);
+}
+
+static int	doaddquota(const char *, int, const char *, long, int, int);
+
+static int docheckquota(const char *dir,
+	int *maildirsize_fdptr,
+	const char *quota_type,
+	long xtra_size,
+	int xtra_cnt, int *percentage);
+
+
+int maildir_checkquota(const char *dir,
+	int *maildirsize_fdptr,
+	const char *quota_type,
+	long xtra_size,
+	int xtra_cnt)
+{
+int	dummy;
+
+	return (docheckquota(dir, maildirsize_fdptr, quota_type,
+		xtra_size, xtra_cnt, &dummy));
+}
+
+int maildir_readquota(const char *dir, const char *quota_type)
+{
+int	percentage=0;
+int	fd=-1;
+
+	(void)docheckquota(dir, &fd, quota_type, 0, 0, &percentage);
+	if (fd >= 0)
+		close(fd);
+	return (percentage);
+}
+
+static int docheckquota(const char *dir,
+	int *maildirsize_fdptr,
+	const char *quota_type,
+	long xtra_size,
+	int xtra_cnt,
+	int *percentage)
+{
+char	*checkfolder=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+char	*newmaildirsizename;
+struct stat stat_buf;
+int	maildirsize_fd;
+off_t	maildirsize_size;
+unsigned maildirsize_cnt;
+unsigned maildirsize_nlines;
+int	n;
+time_t	tm;
+time_t	maxtime;
+DIR	*dirp;
+struct dirent *de;
+
+	if (checkfolder == 0)	return (-1);
+	*maildirsize_fdptr= -1;
+	strcat(strcpy(checkfolder, dir), "/maildirfolder");
+	if (stat(checkfolder, &stat_buf) == 0)	/* Go to parent */
+	{
+		strcat(strcpy(checkfolder, dir), "/..");
+		n=docheckquota(checkfolder, maildirsize_fdptr,
+			quota_type, xtra_size, xtra_cnt, percentage);
+		free(checkfolder);
+		return (n);
+	}
+	if (!quota_type || !*quota_type)	return (0);
+
+	strcat(strcpy(checkfolder, dir), "/maildirsize");
+	time(&tm);
+	if (maildirsize_read(checkfolder, &maildirsize_fd,
+		&maildirsize_size, &maildirsize_cnt,
+		&maildirsize_nlines, &stat_buf) == 0)
+	{
+		n=qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+			quota_type, percentage);
+
+		if (n == 0)
+		{
+			free(checkfolder);
+			*maildirsize_fdptr=maildirsize_fd;
+			return (0);
+		}
+		close(maildirsize_fd);
+
+		if (maildirsize_nlines == 1 && tm < stat_buf.st_mtime + 15*60)
+			return (n);
+	}
+
+	maxtime=0;
+	maildirsize_size=0;
+	maildirsize_cnt=0;
+
+	if (countcurnew(dir, &maxtime, &maildirsize_size, &maildirsize_cnt))
+	{
+		free(checkfolder);
+		return (-1);
+	}
+
+	dirp=opendir(dir);
+	while (dirp && (de=readdir(dirp)) != 0)
+	{
+		if (countsubdir(dir, de->d_name, &maxtime, &maildirsize_size,
+			&maildirsize_cnt))
+		{
+			free(checkfolder);
+			closedir(dirp);
+			return (-1);
+		}
+	}
+	if (dirp)
+	{
+#if	CLOSEDIR_VOID
+		closedir(dirp);
+#else
+		if (closedir(dirp))
+		{
+			free(checkfolder);
+			return (-1);
+		}
+#endif
+	}
+
+	newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+	if (!newmaildirsizename)
+	{
+		free(checkfolder);
+		return (-1);
+	}
+
+	*maildirsize_fdptr=maildirsize_fd;
+
+	if (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+		maildirsize_cnt, 1))
+	{
+		free(newmaildirsizename);
+		unlink(newmaildirsizename);
+		close(maildirsize_fd);
+		*maildirsize_fdptr= -1;
+		free(checkfolder);
+		return (-1);
+	}
+
+	strcat(strcpy(checkfolder, dir), "/maildirsize");
+
+	if (rename(newmaildirsizename, checkfolder))
+	{
+		free(checkfolder);
+		unlink(newmaildirsizename);
+		close(maildirsize_fd);
+		*maildirsize_fdptr= -1;
+	}
+	free(checkfolder);
+	free(newmaildirsizename);
+
+	tm=0;
+
+	if (statcurnew(dir, &tm))
+	{
+		close(maildirsize_fd);
+		*maildirsize_fdptr= -1;
+		return (-1);
+	}
+
+	dirp=opendir(dir);
+	while (dirp && (de=readdir(dirp)) != 0)
+	{
+		if (statsubdir(dir, de->d_name, &tm))
+		{
+			close(maildirsize_fd);
+			*maildirsize_fdptr= -1;
+			closedir(dirp);
+			return (-1);
+		}
+	}
+	if (dirp)
+	{
+#if	CLOSEDIR_VOID
+		closedir(dirp);
+#else
+		if (closedir(dirp))
+		{
+			close(maildirsize_fd);
+			*maildirsize_fdptr= -1;
+			return (-1);
+		}
+#endif
+	}
+
+	if (tm != maxtime)	/* Race condition, someone changed something */
+	{
+		errno=EAGAIN;
+		return (-1);
+	}
+
+	return (qcalc(maildirsize_size+xtra_size, maildirsize_cnt+xtra_cnt,
+		quota_type, percentage));
+}
+
+int	maildir_addquota(const char *dir, int maildirsize_fd,
+	const char *quota_type, long maildirsize_size, int maildirsize_cnt)
+{
+	if (!quota_type || !*quota_type)	return (0);
+	return (doaddquota(dir, maildirsize_fd, quota_type, maildirsize_size,
+			maildirsize_cnt, 0));
+}
+
+static int doaddquota(const char *dir, int maildirsize_fd,
+	const char *quota_type, long maildirsize_size, int maildirsize_cnt,
+	int isnew)
+{
+union	{
+	char	buf[100];
+	struct stat stat_buf;
+	} u;				/* Scrooge */
+char	*newname2=0;
+char	*newmaildirsizename=0;
+struct	iovec	iov[3];
+int	niov;
+struct	iovec	*p;
+int	n;
+
+	niov=0;
+	if ( maildirsize_fd < 0)
+	{
+		newname2=(char *)malloc(strlen(dir)+sizeof("/maildirfolder"));
+		if (!newname2)	return (-1);
+		strcat(strcpy(newname2, dir), "/maildirfolder");
+		if (stat(newname2, &u.stat_buf) == 0)
+		{
+			strcat(strcpy(newname2, dir), "/..");
+			n=doaddquota(newname2, maildirsize_fd, quota_type,
+					maildirsize_size, maildirsize_cnt,
+					isnew);
+			free(newname2);
+			return (n);
+		}
+
+		strcat(strcpy(newname2, dir), "/maildirsize");
+
+		if ((maildirsize_fd=maildir_safeopen(newname2,
+			O_RDWR|O_APPEND, 0644)) < 0)
+		{
+			newmaildirsizename=makenewmaildirsizename(dir, &maildirsize_fd);
+			if (!newmaildirsizename)
+			{
+				free(newname2);
+				return (-1);
+			}
+
+			maildirsize_fd=maildir_safeopen(newmaildirsizename,
+				O_CREAT|O_RDWR|O_APPEND, 0644);
+
+			if (maildirsize_fd < 0)
+			{
+				free(newname2);
+				return (-1);
+			}
+			isnew=1;
+		}
+	}
+
+	if (isnew)
+	{
+		iov[0].iov_base=(caddr_t)quota_type;
+		iov[0].iov_len=strlen(quota_type);
+		iov[1].iov_base=(caddr_t)"\n";
+		iov[1].iov_len=1;
+		niov=2;
+	}
+
+
+	sprintf(u.buf, "%ld %d\n", maildirsize_size, maildirsize_cnt);
+	iov[niov].iov_base=(caddr_t)u.buf;
+	iov[niov].iov_len=strlen(u.buf);
+
+	p=iov;
+	++niov;
+	n=0;
+	while (niov)
+	{
+		if (n)
+		{
+			if (n < p->iov_len)
+			{
+				p->iov_base=
+					(caddr_t)((char *)p->iov_base + n);
+				p->iov_len -= n;
+			}
+			else
+			{
+				n -= p->iov_len;
+				++p;
+				--niov;
+				continue;
+			}
+		}
+
+		n=writev( maildirsize_fd, p, niov);
+
+		if (n <= 0)
+		{
+			if (newname2)
+			{
+				close(maildirsize_fd);
+				free(newname2);
+			}
+			return (-1);
+		}
+	}
+	if (newname2)
+	{
+		close(maildirsize_fd);
+
+		if (newmaildirsizename)
+		{
+			rename(newmaildirsizename, newname2);
+			free(newmaildirsizename);
+		}
+		free(newname2);
+	}
+	return (0);
+}
+
+/* New maildirsize is built in the tmp subdirectory */
+
+static char *makenewmaildirsizename(const char *dir, int *fd)
+{
+char	hostname[256];
+struct	stat stat_buf;
+time_t	t;
+char	*p;
+
+	hostname[0]=0;
+	hostname[sizeof(hostname)-1]=0;
+	gethostname(hostname, sizeof(hostname)-1);
+	p=(char *)malloc(strlen(dir)+strlen(hostname)+130);
+	if (!p)	return (0);
+
+	for (;;)
+	{
+	char	tbuf[NUMBUFSIZE];
+	char	pbuf[NUMBUFSIZE];
+
+		time(&t);
+		strcat(strcpy(p, dir), "/tmp/");
+		sprintf(p+strlen(p), "%s.%s_NeWmAiLdIrSiZe.%s",
+			str_time_t(t, tbuf),
+			str_pid_t(getpid(), pbuf), hostname);
+
+		if (stat( (const char *)p, &stat_buf) < 0 &&
+			(*fd=maildir_safeopen(p,
+				O_CREAT|O_RDWR|O_APPEND, 0644)) >= 0)
+			break;
+		sleep(3);
+	}
+	return (p);
+}
+
+static int statcurnew(const char *dir, time_t *maxtimestamp)
+{
+char	*p=(char *)malloc(strlen(dir)+5);
+struct	stat	stat_buf;
+
+	if (!p)	return (-1);
+	strcat(strcpy(p, dir), "/cur");
+	if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+		*maxtimestamp=stat_buf.st_mtime;
+	strcat(strcpy(p, dir), "/new");
+	if ( stat(p, &stat_buf) == 0 && stat_buf.st_mtime > *maxtimestamp)
+		*maxtimestamp=stat_buf.st_mtime;
+	free(p);
+	return (0);
+}
+
+static int statsubdir(const char *dir, const char *subdir, time_t *maxtime)
+{
+char	*p;
+int	n;
+
+	if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+		strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+		return (0);
+
+	p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+	if (!p)	return (-1);
+	strcat(strcat(strcpy(p, dir), "/"), subdir);
+	n=statcurnew(p, maxtime);
+	free(p);
+	return (n);
+}
+
+static int docount(const char *, time_t *, off_t *, unsigned *);
+
+static int countcurnew(const char *dir, time_t *maxtime,
+	off_t *sizep, unsigned *cntp)
+{
+char	*p=(char *)malloc(strlen(dir)+5);
+int	n;
+
+	if (!p)	return (-1);
+	strcat(strcpy(p, dir), "/new");
+	n=docount(p, maxtime, sizep, cntp);
+	if (n == 0)
+	{
+		strcat(strcpy(p, dir), "/cur");
+		n=docount(p, maxtime, sizep, cntp);
+	}
+	free(p);
+	return (n);
+}
+
+static int countsubdir(const char *dir, const char *subdir, time_t *maxtime,
+	off_t *sizep, unsigned *cntp)
+{
+char	*p;
+int	n;
+
+	if ( *subdir != '.' || strcmp(subdir, ".") == 0 ||
+		strcmp(subdir, "..") == 0 || strcmp(subdir, "." TRASH) == 0)
+		return (0);
+
+	p=(char *)malloc(strlen(dir)+strlen(subdir)+2);
+	if (!p)	return (2);
+	strcat(strcat(strcpy(p, dir), "/"), subdir);
+	n=countcurnew(p, maxtime, sizep, cntp);
+	free(p);
+	return (n);
+}
+
+static int docount(const char *dir, time_t *dirstamp,
+	off_t *sizep, unsigned *cntp)
+{
+struct	stat	stat_buf;
+char	*p;
+DIR	*dirp;
+struct dirent *de;
+unsigned long	s;
+
+	if (stat(dir, &stat_buf))	return (0);	/* Ignore */
+	if (stat_buf.st_mtime > *dirstamp)	*dirstamp=stat_buf.st_mtime;
+	if ((dirp=opendir(dir)) == 0)	return (0);
+	while ((de=readdir(dirp)) != 0)
+	{
+	const char *n=de->d_name;
+
+		if (*n == '.')	continue;
+
+		/* PATCH - do not count msgs marked as deleted */
+
+		for ( ; *n; n++)
+		{
+			if (n[0] != ':' || n[1] != '2' ||
+				n[2] != ',')	continue;
+			n += 3;
+			while (*n >= 'A' && *n <= 'Z')
+			{
+				if (*n == 'T')	break;
+				++n;
+			}
+			break;
+		}
+		if (*n == 'T')	continue;
+		n=de->d_name;
+
+
+		if (maildir_parsequota(n, &s) == 0)
+			stat_buf.st_size=s;
+		else
+		{
+			p=(char *)malloc(strlen(dir)+strlen(n)+2);
+			if (!p)
+			{
+				closedir(dirp);
+				return (-1);
+			}
+			strcat(strcat(strcpy(p, dir), "/"), n);
+			if (stat(p, &stat_buf))
+			{
+				free(p);
+				continue;
+			}
+			free(p);
+		}
+		*sizep += stat_buf.st_size;
+		++*cntp;
+	}
+
+#if	CLOSEDIR_VOID
+	closedir(dirp);
+#else
+	if (closedir(dirp))
+		return (-1);
+#endif
+	return (0);
+}
diff -urN qmail-1.03-orig/maildirquota.h qmail-1.03/maildirquota.h
--- qmail-1.03-orig/maildirquota.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/maildirquota.h	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,45 @@
+#ifndef	maildirquota_h
+#define	maildirquota_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+#include	<sys/types.h>
+#include	<stdio.h>
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+static const char maildirquota_h_rcsid[]="$Id: maildirquota.h,v 1.2 2000/09/04 17:10:28 mrsam Exp $";
+
+int maildir_checkquota(const char *,	/* Pointer to directory */
+	int *,	/* Initialized to -1, or opened descriptor for maildirsize */
+	const char *,	/* The quota */
+	long,		/* Extra bytes planning to add/remove from maildir */
+	int);		/* Extra messages planning to add/remove from maildir */
+
+int maildir_addquota(const char *,	/* Pointer to the maildir */
+	int,	/* Must be the int pointed to by 2nd arg to checkquota */
+	const char *,	/* The quota */
+	long,	/* +/- bytes */
+	int);	/* +/- files */
+
+int maildir_readquota(const char *,	/* Directory */
+	const char *);			/* Quota, from getquota */
+
+int maildir_parsequota(const char *, unsigned long *);
+	/* Attempt to parse file size encoded in filename.  Returns 0 if
+	** parsed, non-zero if we didn't parse. */
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff -urN qmail-1.03-orig/make-load.sh qmail-1.03/make-load.sh
--- qmail-1.03-orig/make-load.sh	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/make-load.sh	2003-10-03 14:08:49.000000000 -0400
@@ -1,2 +1,2 @@
 echo 'main="$1"; shift'
-echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}'
+echo exec "$LD" '-o "$main" "$main".o ${1+"$@"} -lqmailio'
diff -urN qmail-1.03-orig/numlib.h qmail-1.03/numlib.h
--- qmail-1.03-orig/numlib.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/numlib.h	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,45 @@
+#ifndef	numlib_h
+#define	numlib_h
+
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+static const char numlib_h_rcsid[]="$Id: numlib.h,v 1.3 2001/08/12 15:46:40 mrsam Exp $";
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+
+#include	<sys/types.h>
+#include	<time.h>
+
+#define	NUMBUFSIZE	60
+
+/* Convert various system types to decimal */
+
+char	*str_time_t(time_t, char *);
+char	*str_off_t(off_t, char *);
+char	*str_pid_t(pid_t, char *);
+char	*str_ino_t(ino_t, char *);
+char	*str_uid_t(uid_t, char *);
+char	*str_gid_t(gid_t, char *);
+char	*str_size_t(size_t, char *);
+
+char	*str_sizekb(unsigned long, char *);	/* X Kb or X Mb */
+
+/* Convert selected system types to hex */
+
+char	*strh_time_t(time_t, char *);
+char	*strh_pid_t(pid_t, char *);
+char	*strh_ino_t(ino_t, char *);
+
+#ifdef	__cplusplus
+}
+#endif
+#endif
diff -urN qmail-1.03-orig/overmaildirquota.c qmail-1.03/overmaildirquota.c
--- qmail-1.03-orig/overmaildirquota.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/overmaildirquota.c	2003-10-03 14:21:17.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+** Copyright 1998 - 1999 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include        "maildirquota.h"
+#include        <stdlib.h>
+#include        <string.h>
+#include        <errno.h>
+#include        <sys/stat.h>
+
+static const char rcsid[]="$Id: overquota.c,v 1.0 2002/06/09 16:21:05 mr sam Exp $";
+
+
+int user_over_maildirquota( const char *dir, const char *q)
+{
+struct  stat    stat_buf;
+int     quotafd;
+int     ret_value;
+
+        if (fstat(0, &stat_buf) == 0 && S_ISREG(stat_buf.st_mode) &&
+                stat_buf.st_size > 0 && *q)
+        {
+                if (maildir_checkquota(dir, &quotafd, q, stat_buf.st_size, 1)
+                        && errno != EAGAIN)
+                {
+                        if (quotafd >= 0)       close(quotafd);
+                        ret_value = 1;
+                } else {
+                        maildir_addquota(dir, quotafd, q, stat_buf.st_size, 1);
+                        if (quotafd >= 0)       close(quotafd);
+                        ret_value = 0;
+                }
+        } else {
+                ret_value = 0;
+        }
+
+        return(ret_value);
+}
diff -urN qmail-1.03-orig/qmail-control.9 qmail-1.03/qmail-control.9
--- qmail-1.03-orig/qmail-control.9	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-control.9	2003-10-03 14:08:49.000000000 -0400
@@ -43,6 +43,8 @@
 .I badmailfrom	\fR(none)	\fRqmail-smtpd
 .I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
 .I bouncehost	\fIme	\fRqmail-send
+.I clientca.pem	\fR(none)	\fRqmail-smtpd
+.I clientcert.pem	\fR(none)	\fRqmail-remote
 .I concurrencylocal	\fR10	\fRqmail-send
 .I concurrencyremote	\fR20	\fRqmail-send
 .I defaultdomain	\fIme	\fRqmail-inject
@@ -55,17 +57,24 @@
 .I idhost	\fIme	\fRqmail-inject
 .I localiphost	\fIme	\fRqmail-smtpd
 .I locals	\fIme	\fRqmail-send
+.I mfcheck	\fR0	\fRqmail-smtpd
 .I morercpthosts	\fR(none)	\fRqmail-smtpd
 .I percenthack	\fR(none)	\fRqmail-send
 .I plusdomain	\fIme	\fRqmail-inject
 .I qmqpservers	\fR(none)	\fRqmail-qmqpc
 .I queuelifetime	\fR604800	\fRqmail-send
 .I rcpthosts	\fR(none)	\fRqmail-smtpd
+.I rsa512.pem	\fR(none)	\fRqmail-smtpd
+.I servercert.pem	\fR(none)	\fRqmail-smtpd
 .I smtpgreeting	\fIme	\fRqmail-smtpd
 .I smtproutes	\fR(none)	\fRqmail-remote
 .I timeoutconnect	\fR60	\fRqmail-remote
 .I timeoutremote	\fR1200	\fRqmail-remote
 .I timeoutsmtpd	\fR1200	\fRqmail-smtpd
+.I tlsclients	\fR(none)	\fRqmail-smtpd
+.I tlsclientciphers	\fR(none)	\fRqmail-remote
+.I tlshosts/FQDN.pem	\fR(none)	\fRqmail-remote
+.I tlsserverciphers	\fR(none)	\fRqmail-smtpd
 .I virtualdomains	\fR(none)	\fRqmail-send
 .fi
 .RE
diff -urN qmail-1.03-orig/qmail-control.9.orig qmail-1.03/qmail-control.9.orig
--- qmail-1.03-orig/qmail-control.9.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/qmail-control.9.orig	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,79 @@
+.TH qmail-control 5
+.SH "NAME"
+qmail-control \- qmail configuration files
+.SH "INTRODUCTION"
+You can change the behavior of the
+.B qmail
+system by modifying
+.BR qmail 's
+.I control files
+in
+.BR QMAILHOME/control .
+
+.B qmail
+can survive with just one control file,
+.IR me ,
+containing the
+fully-qualified name of the current host.
+This file is used as the default for
+other hostname-related control files.
+
+Comments are allowed
+in
+.IR badmailfrom ,
+.IR locals ,
+.IR percenthack ,
+.IR qmqpservers ,
+.IR rcpthosts ,
+.IR smtproutes ,
+and
+.IR virtualdomains .
+Trailing spaces and tabs are allowed in any control file.
+
+The following table lists all control files
+other than
+.IR me .
+See the corresponding man pages for further details.
+
+.RS
+.nf
+.ta 5c 10c
+control	default	used by
+
+.I badmailfrom	\fR(none)	\fRqmail-smtpd
+.I bouncefrom	\fRMAILER-DAEMON	\fRqmail-send
+.I bouncehost	\fIme	\fRqmail-send
+.I concurrencylocal	\fR10	\fRqmail-send
+.I concurrencyremote	\fR20	\fRqmail-send
+.I defaultdomain	\fIme	\fRqmail-inject
+.I defaulthost	\fIme	\fRqmail-inject
+.I databytes	\fR0	\fRqmail-smtpd
+.I doublebouncehost	\fIme	\fRqmail-send
+.I doublebounceto	\fRpostmaster	\fRqmail-send
+.I envnoathost	\fIme	\fRqmail-send
+.I helohost	\fIme	\fRqmail-remote
+.I idhost	\fIme	\fRqmail-inject
+.I localiphost	\fIme	\fRqmail-smtpd
+.I locals	\fIme	\fRqmail-send
+.I mfcheck	\fR0	\fRqmail-smtpd
+.I morercpthosts	\fR(none)	\fRqmail-smtpd
+.I percenthack	\fR(none)	\fRqmail-send
+.I plusdomain	\fIme	\fRqmail-inject
+.I qmqpservers	\fR(none)	\fRqmail-qmqpc
+.I queuelifetime	\fR604800	\fRqmail-send
+.I rcpthosts	\fR(none)	\fRqmail-smtpd
+.I smtpgreeting	\fIme	\fRqmail-smtpd
+.I smtproutes	\fR(none)	\fRqmail-remote
+.I timeoutconnect	\fR60	\fRqmail-remote
+.I timeoutremote	\fR1200	\fRqmail-remote
+.I timeoutsmtpd	\fR1200	\fRqmail-smtpd
+.I virtualdomains	\fR(none)	\fRqmail-send
+.fi
+.RE
+.SH "SEE ALSO"
+qmail-inject(8),
+qmail-qmqpc(8),
+qmail-remote(8),
+qmail-send(8),
+qmail-showctl(8),
+qmail-smtpd(8)
diff -urN qmail-1.03-orig/qmail-local.c qmail-1.03/qmail-local.c
--- qmail-1.03-orig/qmail-local.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-local.c	2003-10-03 14:10:07.000000000 -0400
@@ -63,9 +63,55 @@
 stralloc cmds = {0};
 stralloc messline = {0};
 stralloc foo = {0};
+stralloc qsender = {0};
+stralloc tmpline = {0};
+char *verhhost = (char *)0;
+char *verhlocal = (char *)0;
+int flagheader,flagdobody;
+unsigned int i;
+
+int verhline(sa)
+stralloc *sa;
+/* substitutes ##L => recipient local, ##H => recipient host if VERP sender */
+/* returns 0 normally, -1 on out-of-memory */
+{
+  register char *cp;
+  char *cpnext,*cpafter;
+
+  if (!verhlocal) return 0;				/* no VERP SENDER */
+  cp = sa->s;
+  cpnext = sa->s;
+  cpafter = cp + sa->len;
+  tmpline.len = 0;					/* clear */
+  for (;;) {
+    while (cp < cpafter && *cp++ != '#');
+    if (cp + 1 < cpafter && *cp == '#') {		/* found '##' */
+      cp++;
+      if (*cp == 'L') {					/* ##L */
+	if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+	cp++;
+	cpnext = cp;
+	if (!stralloc_cats(&tmpline,verhlocal)) return -1;
+      } else if (*cp == 'H') {				/* ##H */
+	if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+	cp++;
+	cpnext = cp;
+	if (!stralloc_cats(&tmpline,verhhost)) return -1;
+      }
+    }
+    if (cp >= cpafter) {
+      if (tmpline.len) {	/* true if we've done any substitutions */
+	if (!stralloc_catb(&tmpline,cpnext,cpafter - cpnext)) return -1;
+	if (!stralloc_copy(sa,&tmpline)) return -1;
+      }
+      return 0;
+    }
+  }
+}
 
 char buf[1024];
 char outbuf[1024];
+#define QUOTABUFSIZE    256
 
 /* child process */
 
@@ -82,13 +128,20 @@
  char host[64];
  char *s;
  int loop;
+ int match;
  struct stat st;
  int fd;
  substdio ss;
  substdio ssout;
+ char quotabuf[QUOTABUFSIZE];
 
  sig_alarmcatch(sigalrm);
  if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (maildir_getquota(dir, quotabuf) == 0) {
+  if (user_over_maildirquota(dir,quotabuf)==1) {
+   _exit(1);
+  }
+ }
  pid = getpid();
  host[0] = 0;
  gethostname(host,sizeof(host));
@@ -99,7 +152,10 @@
    s += fmt_str(s,"tmp/");
    s += fmt_ulong(s,time); *s++ = '.';
    s += fmt_ulong(s,pid); *s++ = '.';
-   s += fmt_strn(s,host,sizeof(host)); *s++ = 0;
+   s += fmt_strn(s,host,sizeof(host));
+   s += fmt_strn(s,",S=",sizeof(",S="));
+   if (fstat(0,&st) == -1) if (errno == error_noent) break;
+   s += fmt_ulong(s,st.st_size); *s++ = 0;
    if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
    /* really should never get to this point */
    if (loop == 2) _exit(1);
@@ -117,11 +173,27 @@
  if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;
  if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;
 
- switch(substdio_copy(&ssout,&ss))
-  {
-   case -2: tryunlinktmp(); _exit(4);
-   case -3: goto fail;
-  }
+ flagheader = 1;
+ flagdobody = 0;
+ do {				/* for VERH */
+   if (getln(&ss,&messline,&match,'\n') != 0)
+     { tryunlinktmp(); _exit(4); }
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       flagheader = 0;
+       if (!flagdobody) verhlocal = (char *)0;
+     }
+     if (messline.s[0] == '#') {	/* continue in body */
+       flagdobody = 1;			/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+	 messline.s[i - 1] = messline.s[i];
+       messline.len--;			/* always >= 1 from \n */
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) goto fail;
+   if (substdio_put(&ssout,messline.s,messline.len) == -1) goto fail;
+ } while (match);
 
  if (substdio_flush(&ssout) == -1) goto fail;
  if (fsync(fd) == -1) goto fail;
@@ -159,6 +231,7 @@
  switch(wait_exitcode(wstat))
   {
    case 0: break;
+   case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
    case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
    case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
    case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
@@ -193,6 +266,8 @@
 
  substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
  substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ flagheader = 1;
+ flagdobody = 0;
  if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs;
  if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs;
  if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs;
@@ -207,6 +282,20 @@
    if (!match && !messline.len) break;
    if (gfrom(messline.s,messline.len))
      if (substdio_bput(&ssout,">",1)) goto writeerrs;
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       if (!flagdobody) verhlocal = (char *)0;
+       flagheader = 0;
+     }
+     if (messline.s[0] == '#') {		/* continue in body */
+       flagdobody = 1;				/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+         messline.s[i - 1] = messline.s[i];
+       messline.len--;
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) goto writeerrs;
    if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs;
    if (!match)
     {
@@ -276,9 +365,24 @@
  if (qmail_open(&qqt) == -1) temp_fork();
  mailforward_qp = qmail_qp(&qqt);
  qmail_put(&qqt,dtline.s,dtline.len);
+ flagheader = 1;
  do
   {
    if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; }
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       flagheader = 0;
+       if (!flagdobody) verhlocal = (char *)0;
+     }
+     if (messline.s[0] == '#') {	/* continue in body */
+       flagdobody = 1;			/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+	 messline.s[i - 1] = messline.s[i];
+       messline.len--;
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) { qmail_fail(&qqt); break; }
    qmail_put(&qqt,messline.s,messline.len);
   }
  while (match);
@@ -458,6 +562,7 @@
  datetime_sec starttime;
  int flagforwardonly;
  char *x;
+ char *cplast;
 
  umask(077);
  sig_pipeignore();
@@ -518,9 +623,9 @@
 
  if (!env_put2("SENDER",sender)) temp_nomem();
 
- if (!quote2(&foo,sender)) temp_nomem();
+ if (!quote2(&qsender,sender)) temp_nomem();
  if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem();
- if (!stralloc_cat(&rpline,&foo)) temp_nomem();
+ if (!stralloc_cat(&rpline,&qsender)) temp_nomem();
  for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '\n') rpline.s[i] = '_';
  if (!stralloc_cats(&rpline,">\n")) temp_nomem();
 
@@ -528,6 +633,33 @@
  if (!stralloc_0(&foo)) temp_nomem();
  if (!env_put2("RPLINE",foo.s)) temp_nomem();
 
+ i = byte_rchr(qsender.s,qsender.len,'@');		/* for VERH */
+ if (i != qsender.len) {				/* got @ */
+   cplast = qsender.s + i;
+   *cplast = '\0';
+   if (qsender.s[i = str_rchr(qsender.s,'=')]) {	/* got = */
+     qsender.s[i] = '\0';
+     cplast = qsender.s + i;
+     verhhost = qsender.s + i + 1;
+     i = str_rchr(qsender.s,'-');
+     if (qsender.s[i] == '-') {
+       for (;;) {
+	 if (case_starts(qsender.s + i + 1,"return-")) {
+	   verhlocal = qsender.s + i + 9 + str_chr(qsender.s + i + 8,'-');
+					/* here to avoid work if not VERP */
+					/* verhhost not used if verhlocal=0 */
+           for (x = verhlocal; x < cplast; x++)
+             if (*x == '\n') *x = '_';	/* \n would ruin */
+	   break;
+	 }
+	 j = byte_rchr(qsender.s,i,'-');
+	 if (j == i) break;
+	 i = j;
+       }
+     }
+   }
+ }
+
  if (!stralloc_copys(&ufline,"From ")) temp_nomem();
  if (*sender)
   {
@@ -645,7 +777,7 @@
     {
      cmds.s[j] = 0;
      k = j;
-     while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+     while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
        cmds.s[--k] = 0;
      switch(cmds.s[i])
       {
diff -urN qmail-1.03-orig/qmail-local.c.orig qmail-1.03/qmail-local.c.orig
--- qmail-1.03-orig/qmail-local.c.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/qmail-local.c.orig	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,830 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "readwrite.h"
+#include "sig.h"
+#include "env.h"
+#include "byte.h"
+#include "exit.h"
+#include "fork.h"
+#include "open.h"
+#include "wait.h"
+#include "lock.h"
+#include "seek.h"
+#include "substdio.h"
+#include "getln.h"
+#include "strerr.h"
+#include "subfd.h"
+#include "sgetopt.h"
+#include "alloc.h"
+#include "error.h"
+#include "stralloc.h"
+#include "fmt.h"
+#include "str.h"
+#include "now.h"
+#include "case.h"
+#include "quote.h"
+#include "qmail.h"
+#include "slurpclose.h"
+#include "myctime.h"
+#include "gfrom.h"
+#include "auto_patrn.h"
+
+void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }
+
+void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); }
+void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); }
+void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); }
+void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); }
+void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); }
+void temp_slowlock()
+{ strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); }
+void temp_qmail(fn) char *fn;
+{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }
+
+int flagdoit;
+int flag99;
+
+char *user;
+char *homedir;
+char *local;
+char *dash;
+char *ext;
+char *host;
+char *sender;
+char *aliasempty;
+
+stralloc safeext = {0};
+stralloc ufline = {0};
+stralloc rpline = {0};
+stralloc envrecip = {0};
+stralloc dtline = {0};
+stralloc qme = {0};
+stralloc ueo = {0};
+stralloc cmds = {0};
+stralloc messline = {0};
+stralloc foo = {0};
+stralloc qsender = {0};
+stralloc tmpline = {0};
+char *verhhost = (char *)0;
+char *verhlocal = (char *)0;
+int flagheader,flagdobody;
+unsigned int i;
+
+int verhline(sa)
+stralloc *sa;
+/* substitutes ##L => recipient local, ##H => recipient host if VERP sender */
+/* returns 0 normally, -1 on out-of-memory */
+{
+  register char *cp;
+  char *cpnext,*cpafter;
+
+  if (!verhlocal) return 0;				/* no VERP SENDER */
+  cp = sa->s;
+  cpnext = sa->s;
+  cpafter = cp + sa->len;
+  tmpline.len = 0;					/* clear */
+  for (;;) {
+    while (cp < cpafter && *cp++ != '#');
+    if (cp + 1 < cpafter && *cp == '#') {		/* found '##' */
+      cp++;
+      if (*cp == 'L') {					/* ##L */
+	if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+	cp++;
+	cpnext = cp;
+	if (!stralloc_cats(&tmpline,verhlocal)) return -1;
+      } else if (*cp == 'H') {				/* ##H */
+	if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+	cp++;
+	cpnext = cp;
+	if (!stralloc_cats(&tmpline,verhhost)) return -1;
+      }
+    }
+    if (cp >= cpafter) {
+      if (tmpline.len) {	/* true if we've done any substitutions */
+	if (!stralloc_catb(&tmpline,cpnext,cpafter - cpnext)) return -1;
+	if (!stralloc_copy(sa,&tmpline)) return -1;
+      }
+      return 0;
+    }
+  }
+}
+
+char buf[1024];
+char outbuf[1024];
+#define QUOTABUFSIZE    256
+
+/* child process */
+
+char fntmptph[80 + FMT_ULONG * 2];
+char fnnewtph[80 + FMT_ULONG * 2];
+void tryunlinktmp() { unlink(fntmptph); }
+void sigalrm() { tryunlinktmp(); _exit(3); }
+
+void maildir_child(dir)
+char *dir;
+{
+ unsigned long pid;
+ unsigned long time;
+ char host[64];
+ char *s;
+ int loop;
+ int match;
+ struct stat st;
+ int fd;
+ substdio ss;
+ substdio ssout;
+ char quotabuf[QUOTABUFSIZE];
+
+ sig_alarmcatch(sigalrm);
+ if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); }
+ if (maildir_getquota(dir, quotabuf) == 0) {
+  if (user_over_maildirquota(dir,quotabuf)==1) {
+   _exit(1);
+  }
+ }
+ pid = getpid();
+ host[0] = 0;
+ gethostname(host,sizeof(host));
+ for (loop = 0;;++loop)
+  {
+   time = now();
+   s = fntmptph;
+   s += fmt_str(s,"tmp/");
+   s += fmt_ulong(s,time); *s++ = '.';
+   s += fmt_ulong(s,pid); *s++ = '.';
+   s += fmt_strn(s,host,sizeof(host));
+   s += fmt_strn(s,",S=",sizeof(",S="));
+   if (fstat(0,&st) == -1) if (errno == error_noent) break;
+   s += fmt_ulong(s,st.st_size); *s++ = 0;
+   if (stat(fntmptph,&st) == -1) if (errno == error_noent) break;
+   /* really should never get to this point */
+   if (loop == 2) _exit(1);
+   sleep(2);
+  }
+ str_copy(fnnewtph,fntmptph);
+ byte_copy(fnnewtph,3,"new");
+
+ alarm(86400);
+ fd = open_excl(fntmptph);
+ if (fd == -1) _exit(1);
+
+ substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+ substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;
+ if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;
+
+ flagheader = 1;
+ flagdobody = 0;
+ do {				/* for VERH */
+   if (getln(&ss,&messline,&match,'\n') != 0)
+     { tryunlinktmp(); _exit(4); }
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       flagheader = 0;
+       if (!flagdobody) verhlocal = (char *)0;
+     }
+     if (messline.s[0] == '#') {	/* continue in body */
+       flagdobody = 1;			/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+	 messline.s[i - 1] = messline.s[i];
+       messline.len--;			/* always >= 1 from \n */
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) goto fail;
+   if (substdio_put(&ssout,messline.s,messline.len) == -1) goto fail;
+ } while (match);
+
+ if (substdio_flush(&ssout) == -1) goto fail;
+ if (fsync(fd) == -1) goto fail;
+ if (close(fd) == -1) goto fail; /* NFS dorks */
+
+ if (link(fntmptph,fnnewtph) == -1) goto fail;
+   /* if it was error_exist, almost certainly successful; i hate NFS */
+ tryunlinktmp(); _exit(0);
+
+ fail: tryunlinktmp(); _exit(1);
+}
+
+/* end child process */
+
+void maildir(fn)
+char *fn;
+{
+ int child;
+ int wstat;
+
+ if (seek_begin(0) == -1) temp_rewind();
+
+ switch(child = fork())
+  {
+   case -1:
+     temp_fork();
+   case 0:
+     maildir_child(fn);
+     _exit(111);
+  }
+
+ wait_pid(&wstat,child);
+ if (wait_crashed(wstat))
+   temp_childcrashed();
+ switch(wait_exitcode(wstat))
+  {
+   case 0: break;
+   case 1: strerr_die1x(1, "User over quota. (#5.1.1)");
+   case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
+   case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
+   case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
+   default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)");
+  }
+}
+
+void mailfile(fn)
+char *fn;
+{
+ int fd;
+ substdio ss;
+ substdio ssout;
+ int match;
+ seek_pos pos;
+ int flaglocked;
+
+ if (seek_begin(0) == -1) temp_rewind();
+
+ fd = open_append(fn);
+ if (fd == -1)
+   strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)");
+
+ sig_alarmcatch(temp_slowlock);
+ alarm(30);
+ flaglocked = (lock_ex(fd) != -1);
+ alarm(0);
+ sig_alarmdefault();
+
+ seek_end(fd);
+ pos = seek_cur(fd);
+
+ substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+ substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ flagheader = 1;
+ flagdobody = 0;
+ if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs;
+ if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs;
+ if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs;
+ for (;;)
+  {
+   if (getln(&ss,&messline,&match,'\n') != 0) 
+    {
+     strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0);
+     if (flaglocked) seek_trunc(fd,pos); close(fd);
+     _exit(111);
+    }
+   if (!match && !messline.len) break;
+   if (gfrom(messline.s,messline.len))
+     if (substdio_bput(&ssout,">",1)) goto writeerrs;
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       if (!flagdobody) verhlocal = (char *)0;
+       flagheader = 0;
+     }
+     if (messline.s[0] == '#') {		/* continue in body */
+       flagdobody = 1;				/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+         messline.s[i - 1] = messline.s[i];
+       messline.len--;
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) goto writeerrs;
+   if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs;
+   if (!match)
+    {
+     if (substdio_bputs(&ssout,"\n")) goto writeerrs;
+     break;
+    }
+  }
+ if (substdio_bputs(&ssout,"\n")) goto writeerrs;
+ if (substdio_flush(&ssout)) goto writeerrs;
+ if (fsync(fd) == -1) goto writeerrs;
+ close(fd);
+ return;
+
+ writeerrs:
+ strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0);
+ if (flaglocked) seek_trunc(fd,pos);
+ close(fd);
+ _exit(111);
+}
+
+void mailprogram(prog)
+char *prog;
+{
+ int child;
+ char *(args[4]);
+ int wstat;
+
+ if (seek_begin(0) == -1) temp_rewind();
+
+ switch(child = fork())
+  {
+   case -1:
+     temp_fork();
+   case 0:
+     args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
+     sig_pipedefault();
+     execv(*args,args);
+     strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)");
+  }
+
+ wait_pid(&wstat,child);
+ if (wait_crashed(wstat))
+   temp_childcrashed();
+ switch(wait_exitcode(wstat))
+  {
+   case 100:
+   case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100);
+   case 0: break;
+   case 99: flag99 = 1; break;
+   default: _exit(111);
+  }
+}
+
+unsigned long mailforward_qp = 0;
+
+void mailforward(recips)
+char **recips;
+{
+ struct qmail qqt;
+ char *qqx;
+ substdio ss;
+ int match;
+
+ if (seek_begin(0) == -1) temp_rewind();
+ substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+
+ if (qmail_open(&qqt) == -1) temp_fork();
+ mailforward_qp = qmail_qp(&qqt);
+ qmail_put(&qqt,dtline.s,dtline.len);
+ flagheader = 1;
+ do
+  {
+   if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; }
+   if (flagheader) {
+     if (match && messline.len == 1) {
+       flagheader = 0;
+       if (!flagdobody) verhlocal = (char *)0;
+     }
+     if (messline.s[0] == '#') {	/* continue in body */
+       flagdobody = 1;			/* remove leading '#' */
+       for (i = 1; i < messline.len; i++)
+	 messline.s[i - 1] = messline.s[i];
+       messline.len--;
+     }
+   }
+   if (verhlocal)
+     if (verhline(&messline) == -1) { qmail_fail(&qqt); break; }
+   qmail_put(&qqt,messline.s,messline.len);
+  }
+ while (match);
+ qmail_from(&qqt,ueo.s);
+ while (*recips) qmail_to(&qqt,*recips++);
+ qqx = qmail_close(&qqt);
+ if (!*qqx) return;
+ strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,".");
+}
+
+void bouncexf()
+{
+ int match;
+ substdio ss;
+
+ if (seek_begin(0) == -1) temp_rewind();
+ substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
+ for (;;)
+  {
+   if (getln(&ss,&messline,&match,'\n') != 0) temp_read();
+   if (!match) break;
+   if (messline.len <= 1)
+     break;
+   if (messline.len == dtline.len)
+     if (!str_diffn(messline.s,dtline.s,dtline.len))
+       strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)");
+  }
+}
+
+void checkhome()
+{
+ struct stat st;
+
+ if (stat(".",&st) == -1)
+   strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)");
+ if (st.st_mode & auto_patrn)
+   strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)");
+ if (st.st_mode & 01000)
+   if (flagdoit)
+     strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)");
+   else
+     strerr_warn1("Warning: home directory is sticky.",0);
+}
+
+int qmeox(dashowner)
+char *dashowner;
+{
+ struct stat st;
+
+ if (!stralloc_copys(&qme,".qmail")) temp_nomem();
+ if (!stralloc_cats(&qme,dash)) temp_nomem();
+ if (!stralloc_cat(&qme,&safeext)) temp_nomem();
+ if (!stralloc_cats(&qme,dashowner)) temp_nomem();
+ if (!stralloc_0(&qme)) temp_nomem();
+ if (stat(qme.s,&st) == -1)
+  {
+   if (error_temp(errno)) temp_qmail(qme.s);
+   return -1;
+  }
+ return 0;
+}
+
+int qmeexists(fd,cutable)
+int *fd;
+int *cutable;
+{
+  struct stat st;
+
+  if (!stralloc_0(&qme)) temp_nomem();
+
+  *fd = open_read(qme.s);
+  if (*fd == -1) {
+    if (error_temp(errno)) temp_qmail(qme.s);
+    if (errno == error_perm) temp_qmail(qme.s);
+    if (errno == error_acces) temp_qmail(qme.s);
+    return 0;
+  }
+
+  if (fstat(*fd,&st) == -1) temp_qmail(qme.s);
+  if ((st.st_mode & S_IFMT) == S_IFREG) {
+    if (st.st_mode & auto_patrn)
+      strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)");
+    *cutable = !!(st.st_mode & 0100);
+    return 1;
+  }
+  close(*fd);
+  return 0;
+}
+
+/* "" "": "" */
+/* "-/" "": "-/" "-/default" */
+/* "-/" "a": "-/a" "-/default" */
+/* "-/" "a-": "-/a-" "-/a-default" "-/default" */
+/* "-/" "a-b": "-/a-b" "-/a-default" "-/default" */
+/* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" */
+/* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" */
+
+void qmesearch(fd,cutable)
+int *fd;
+int *cutable;
+{
+  int i;
+
+  if (!stralloc_copys(&qme,".qmail")) temp_nomem();
+  if (!stralloc_cats(&qme,dash)) temp_nomem();
+  if (!stralloc_cat(&qme,&safeext)) temp_nomem();
+  if (qmeexists(fd,cutable)) {
+    if (safeext.len >= 7) {
+      i = safeext.len - 7;
+      if (!byte_diff("default",7,safeext.s + i))
+	if (i <= str_len(ext)) /* paranoia */
+	  if (!env_put2("DEFAULT",ext + i)) temp_nomem();
+    }
+    return;
+  }
+
+  for (i = safeext.len;i >= 0;--i)
+    if (!i || (safeext.s[i - 1] == '-')) {
+      if (!stralloc_copys(&qme,".qmail")) temp_nomem();
+      if (!stralloc_cats(&qme,dash)) temp_nomem();
+      if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem();
+      if (!stralloc_cats(&qme,"default")) temp_nomem();
+      if (qmeexists(fd,cutable)) {
+	if (i <= str_len(ext)) /* paranoia */
+	  if (!env_put2("DEFAULT",ext + i)) temp_nomem();
+        return;
+      }
+    }
+
+  *fd = -1;
+}
+
+unsigned long count_file = 0;
+unsigned long count_forward = 0;
+unsigned long count_program = 0;
+char count_buf[FMT_ULONG];
+
+void count_print()
+{
+ substdio_puts(subfdoutsmall,"did ");
+ substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_file));
+ substdio_puts(subfdoutsmall,"+");
+ substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_forward));
+ substdio_puts(subfdoutsmall,"+");
+ substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_program));
+ substdio_puts(subfdoutsmall,"\n");
+ if (mailforward_qp)
+  {
+   substdio_puts(subfdoutsmall,"qp ");
+   substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,mailforward_qp));
+   substdio_puts(subfdoutsmall,"\n");
+  }
+ substdio_flush(subfdoutsmall);
+}
+
+void sayit(type,cmd,len)
+char *type;
+char *cmd;
+int len;
+{
+ substdio_puts(subfdoutsmall,type);
+ substdio_put(subfdoutsmall,cmd,len);
+ substdio_putsflush(subfdoutsmall,"\n");
+}
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ int opt;
+ int i;
+ int j;
+ int k;
+ int fd;
+ int numforward;
+ char **recips;
+ datetime_sec starttime;
+ int flagforwardonly;
+ char *x;
+ char *cplast;
+
+ umask(077);
+ sig_pipeignore();
+
+ if (!env_init()) temp_nomem();
+
+ flagdoit = 1;
+ while ((opt = getopt(argc,argv,"nN")) != opteof)
+   switch(opt)
+    {
+     case 'n': flagdoit = 0; break;
+     case 'N': flagdoit = 1; break;
+     default:
+       usage();
+    }
+ argc -= optind;
+ argv += optind;
+
+ if (!(user = *argv++)) usage();
+ if (!(homedir = *argv++)) usage();
+ if (!(local = *argv++)) usage();
+ if (!(dash = *argv++)) usage();
+ if (!(ext = *argv++)) usage();
+ if (!(host = *argv++)) usage();
+ if (!(sender = *argv++)) usage();
+ if (!(aliasempty = *argv++)) usage();
+ if (*argv) usage();
+
+ if (homedir[0] != '/') usage();
+ if (chdir(homedir) == -1)
+   strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)");
+ checkhome();
+
+ if (!env_put2("HOST",host)) temp_nomem();
+ if (!env_put2("HOME",homedir)) temp_nomem();
+ if (!env_put2("USER",user)) temp_nomem();
+ if (!env_put2("LOCAL",local)) temp_nomem();
+
+ if (!stralloc_copys(&envrecip,local)) temp_nomem();
+ if (!stralloc_cats(&envrecip,"@")) temp_nomem();
+ if (!stralloc_cats(&envrecip,host)) temp_nomem();
+
+ if (!stralloc_copy(&foo,&envrecip)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("RECIPIENT",foo.s)) temp_nomem();
+
+ if (!stralloc_copys(&dtline,"Delivered-To: ")) temp_nomem();
+ if (!stralloc_cat(&dtline,&envrecip)) temp_nomem();
+ for (i = 0;i < dtline.len;++i) if (dtline.s[i] == '\n') dtline.s[i] = '_';
+ if (!stralloc_cats(&dtline,"\n")) temp_nomem();
+
+ if (!stralloc_copy(&foo,&dtline)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("DTLINE",foo.s)) temp_nomem();
+
+ if (flagdoit)
+   bouncexf();
+
+ if (!env_put2("SENDER",sender)) temp_nomem();
+
+ if (!quote2(&qsender,sender)) temp_nomem();
+ if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem();
+ if (!stralloc_cat(&rpline,&qsender)) temp_nomem();
+ for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '\n') rpline.s[i] = '_';
+ if (!stralloc_cats(&rpline,">\n")) temp_nomem();
+
+ if (!stralloc_copy(&foo,&rpline)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("RPLINE",foo.s)) temp_nomem();
+
+ i = byte_rchr(qsender.s,qsender.len,'@');		/* for VERH */
+ if (i != qsender.len) {				/* got @ */
+   cplast = qsender.s + i;
+   *cplast = '\0';
+   if (qsender.s[i = str_rchr(qsender.s,'=')]) {	/* got = */
+     qsender.s[i] = '\0';
+     cplast = qsender.s + i;
+     verhhost = qsender.s + i + 1;
+     i = str_rchr(qsender.s,'-');
+     if (qsender.s[i] == '-') {
+       for (;;) {
+	 if (case_starts(qsender.s + i + 1,"return-")) {
+	   verhlocal = qsender.s + i + 9 + str_chr(qsender.s + i + 8,'-');
+					/* here to avoid work if not VERP */
+					/* verhhost not used if verhlocal=0 */
+           for (x = verhlocal; x < cplast; x++)
+             if (*x == '\n') *x = '_';	/* \n would ruin */
+	   break;
+	 }
+	 j = byte_rchr(qsender.s,i,'-');
+	 if (j == i) break;
+	 i = j;
+       }
+     }
+   }
+ }
+
+ if (!stralloc_copys(&ufline,"From ")) temp_nomem();
+ if (*sender)
+  {
+   int len; int i; char ch;
+
+   len = str_len(sender);
+   if (!stralloc_readyplus(&ufline,len)) temp_nomem();
+   for (i = 0;i < len;++i)
+    {
+     ch = sender[i];
+     if ((ch == ' ') || (ch == '\t') || (ch == '\n')) ch = '-';
+     ufline.s[ufline.len + i] = ch;
+    }
+   ufline.len += len;
+  }
+ else
+   if (!stralloc_cats(&ufline,"MAILER-DAEMON")) temp_nomem();
+ if (!stralloc_cats(&ufline," ")) temp_nomem();
+ starttime = now();
+ if (!stralloc_cats(&ufline,myctime(starttime))) temp_nomem();
+
+ if (!stralloc_copy(&foo,&ufline)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("UFLINE",foo.s)) temp_nomem();
+
+ x = ext;
+ if (!env_put2("EXT",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT2",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT3",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT4",x)) temp_nomem();
+
+ if (!stralloc_copys(&safeext,ext)) temp_nomem();
+ case_lowerb(safeext.s,safeext.len);
+ for (i = 0;i < safeext.len;++i)
+   if (safeext.s[i] == '.')
+     safeext.s[i] = ':';
+
+ i = str_len(host);
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST2",foo.s)) temp_nomem();
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST3",foo.s)) temp_nomem();
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST4",foo.s)) temp_nomem();
+
+ flagforwardonly = 0;
+ qmesearch(&fd,&flagforwardonly);
+ if (fd == -1)
+   if (*dash)
+     strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
+
+ if (!stralloc_copys(&ueo,sender)) temp_nomem();
+ if (str_diff(sender,""))
+   if (str_diff(sender,"#@[]"))
+     if (qmeox("-owner") == 0)
+      {
+       if (qmeox("-owner-default") == 0)
+	{
+         if (!stralloc_copys(&ueo,local)) temp_nomem();
+         if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem();
+         if (!stralloc_cats(&ueo,host)) temp_nomem();
+         if (!stralloc_cats(&ueo,"-@[]")) temp_nomem();
+	}
+       else
+	{
+         if (!stralloc_copys(&ueo,local)) temp_nomem();
+         if (!stralloc_cats(&ueo,"-owner@")) temp_nomem();
+         if (!stralloc_cats(&ueo,host)) temp_nomem();
+	}
+      }
+ if (!stralloc_0(&ueo)) temp_nomem();
+ if (!env_put2("NEWSENDER",ueo.s)) temp_nomem();
+
+ if (!stralloc_ready(&cmds,0)) temp_nomem();
+ cmds.len = 0;
+ if (fd != -1)
+   if (slurpclose(fd,&cmds,256) == -1) temp_nomem();
+
+ if (!cmds.len)
+  {
+   if (!stralloc_copys(&cmds,aliasempty)) temp_nomem();
+   flagforwardonly = 0;
+  }
+ if (!cmds.len || (cmds.s[cmds.len - 1] != '\n'))
+   if (!stralloc_cats(&cmds,"\n")) temp_nomem();
+
+ numforward = 0;
+ i = 0;
+ for (j = 0;j < cmds.len;++j)
+   if (cmds.s[j] == '\n')
+    {
+     switch(cmds.s[i]) { case '#': case '.': case '/': case '|': break;
+       default: ++numforward; }
+     i = j + 1;
+    }
+
+ recips = (char **) alloc((numforward + 1) * sizeof(char *));
+ if (!recips) temp_nomem();
+ numforward = 0;
+
+ flag99 = 0;
+
+ i = 0;
+ for (j = 0;j < cmds.len;++j)
+   if (cmds.s[j] == '\n')
+    {
+     cmds.s[j] = 0;
+     k = j;
+     while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
+       cmds.s[--k] = 0;
+     switch(cmds.s[i])
+      {
+       case 0: /* k == i */
+	 if (i) break;
+         strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)");
+       case '#':
+         break;
+       case '.':
+       case '/':
+	 ++count_file;
+	 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)");
+	 if (cmds.s[k - 1] == '/')
+           if (flagdoit) maildir(cmds.s + i);
+           else sayit("maildir ",cmds.s + i,k - i);
+	 else
+           if (flagdoit) mailfile(cmds.s + i);
+           else sayit("mbox ",cmds.s + i,k - i);
+         break;
+       case '|':
+	 ++count_program;
+	 if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)");
+         if (flagdoit) mailprogram(cmds.s + i + 1);
+         else sayit("program ",cmds.s + i + 1,k - i - 1);
+         break;
+       case '+':
+	 if (str_equal(cmds.s + i + 1,"list"))
+	   flagforwardonly = 1;
+	 break;
+       case '&':
+         ++i;
+       default:
+	 ++count_forward;
+         if (flagdoit) recips[numforward++] = cmds.s + i;
+         else sayit("forward ",cmds.s + i,k - i);
+         break;
+      }
+     i = j + 1;
+     if (flag99) break;
+    }
+
+ if (numforward) if (flagdoit)
+  {
+   recips[numforward] = 0;
+   mailforward(recips);
+  }
+
+ count_print();
+ _exit(0);
+}
diff -urN qmail-1.03-orig/qmail-pop3d.c qmail-1.03/qmail-pop3d.c
--- qmail-1.03-orig/qmail-pop3d.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-pop3d.c	2003-10-03 14:08:49.000000000 -0400
@@ -16,6 +16,11 @@
 #include "readwrite.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
+#include <errno.h>
+#include "maildirquota.h"
+#include "maildirmisc.h"
+
+#define QUOTABUFSIZE 256
 
 void die() { _exit(0); }
 
@@ -45,19 +50,15 @@
 {
   substdio_put(&ssout,buf,len);
 }
-void puts(s) char *s;
-{
-  substdio_puts(&ssout,s);
-}
 void flush()
 {
   substdio_flush(&ssout);
 }
 void err(s) char *s;
 {
-  puts("-ERR ");
-  puts(s);
-  puts("\r\n");
+  substdio_puts(&ssout,"-ERR ");
+  substdio_puts(&ssout,s);
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
@@ -73,7 +74,7 @@
 void err_nosuch() { err("unable to open that message"); }
 void err_nounlink() { err("unable to unlink all deleted messages"); }
 
-void okay() { puts("+OK \r\n"); flush(); }
+void okay() { substdio_puts(&ssout,"+OK \r\n"); flush(); }
 
 void printfn(fn) char *fn;
 {
@@ -153,11 +154,11 @@
  
   total = 0;
   for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
-  puts("+OK ");
+  substdio_puts(&ssout,"+OK ");
   put(strnum,fmt_uint(strnum,numm));
-  puts(" ");
+  substdio_puts(&ssout," ");
   put(strnum,fmt_ulong(strnum,total));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
@@ -171,18 +172,41 @@
 
 void pop3_last()
 {
-  puts("+OK ");
+  substdio_puts(&ssout,"+OK ");
   put(strnum,fmt_uint(strnum,last));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
   flush();
 }
 
 void pop3_quit()
 {
   int i;
+  char quotabuf[QUOTABUFSIZE];
+  int has_quota=maildir_getquota(".", quotabuf);
+
+  long deleted_bytes=0;
+  long deleted_messages=0;
+
   for (i = 0;i < numm;++i)
     if (m[i].flagdeleted) {
-      if (unlink(m[i].fn) == -1) err_nounlink();
+      unsigned long un=0;
+      const char *filename=m[i].fn;
+      if (has_quota == 0 && !MAILDIR_DELETED(filename)) {
+          if (maildir_parsequota(filename, &un)) {
+              struct stat stat_buf;
+
+              if (stat(filename, &stat_buf) == 0)
+                  un=stat_buf.st_size;
+          }
+      }
+      if (unlink(m[i].fn) == -1) {
+          err_nounlink();
+          un=0;
+      }
+      if (un) {
+          deleted_bytes -= un;
+          deleted_messages -= 1;
+      }
     }
     else
       if (str_start(m[i].fn,"new/")) {
@@ -192,6 +216,21 @@
 	if (!stralloc_0(&line)) die_nomem();
 	rename(m[i].fn,line.s); /* if it fails, bummer */
       }
+
+    if (deleted_messages < 0) {
+        int quotafd;
+
+        if (maildir_checkquota(".", &quotafd, quotabuf, deleted_bytes,
+                               deleted_messages) && errno != EAGAIN &&
+                               deleted_bytes >= 0)
+            {
+                if (quotafd >= 0) close (quotafd);
+            } else {
+                 maildir_addquota(".", quotafd, quotabuf,
+                                 deleted_bytes, deleted_messages);
+                 if (quotafd >= 0) close(quotafd);
+            }
+        }
   okay();
   die();
 }
@@ -222,10 +261,10 @@
 int flaguidl;
 {
   put(strnum,fmt_uint(strnum,i + 1));
-  puts(" ");
+  substdio_puts(&ssout," ");
   if (flaguidl) printfn(m[i].fn);
   else put(strnum,fmt_ulong(strnum,m[i].size));
-  puts("\r\n");
+  substdio_puts(&ssout,"\r\n");
 }
 
 void dolisting(arg,flaguidl) char *arg; int flaguidl;
@@ -234,7 +273,7 @@
   if (*arg) {
     i = msgno(arg);
     if (i == -1) return;
-    puts("+OK ");
+    substdio_puts(&ssout,"+OK ");
     list(i,flaguidl);
   }
   else {
@@ -242,7 +281,7 @@
     for (i = 0;i < numm;++i)
       if (!m[i].flagdeleted)
 	list(i,flaguidl);
-    puts(".\r\n");
+    substdio_puts(&ssout,".\r\n");
   }
   flush();
 }
diff -urN qmail-1.03-orig/qmail-remote.8 qmail-1.03/qmail-remote.8
--- qmail-1.03-orig/qmail-remote.8	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-remote.8	2003-10-03 14:08:49.000000000 -0400
@@ -114,6 +114,10 @@
 always exits zero.
 .SH "CONTROL FILES"
 .TP 5
+.I clientcert.pem
+SSL certificate that is used to authenticate with the remote server
+during a TLS session.
+.TP 5
 .I helohost
 Current host name,
 for use solely in saying hello to the remote SMTP server.
@@ -156,6 +160,8 @@
 this tells
 .B qmail-remote
 to look up MX records as usual.
+.I port 
+value of 465 (deprecated smtps port) causes TLS session to be started.
 .I smtproutes
 may include wildcards:
 
@@ -195,6 +201,26 @@
 .B qmail-remote
 will wait for each response from the remote SMTP server.
 Default: 1200.
+
+.TP 5
+.I tlsclientciphers
+A set of OpenSSL client cipher strings. Multiple ciphers
+contained in a string should be separated by a colon.
+
+.TP 5
+.I tlshosts/<FQDN>.pem
+.B qmail-remote
+requires authentication from servers for which this certificate exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server). One of the
+.I dNSName
+or the
+.I CommonName
+attributes have to match.
+
+.B WARNING:
+this option may cause mail to be delayed, bounced, doublebounced, or lost.
+
 .SH "SEE ALSO"
 addresses(5),
 envelopes(5),
diff -urN qmail-1.03-orig/qmail-remote.c qmail-1.03/qmail-remote.c
--- qmail-1.03-orig/qmail-remote.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-remote.c	2003-10-03 14:08:49.000000000 -0400
@@ -39,6 +39,7 @@
 static stralloc sauninit = {0};
 
 stralloc helohost = {0};
+stralloc outgoingip = {0};
 stralloc routes = {0};
 struct constmap maproutes;
 stralloc host = {0};
@@ -47,6 +48,18 @@
 saa reciplist = {0};
 
 struct ip_address partner;
+struct ip_address outip;
+
+#ifdef TLS
+# include <sys/stat.h>
+# include "tls.h"
+# include "ssl_timeoutio.h"
+# include <openssl/x509v3.h>
+# define EHLO 1
+
+int tls_init();
+const char *ssl_err_str = 0;
+#endif 
 
 void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
 void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
@@ -56,6 +69,7 @@
 ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?';
 if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
 
+void temp_noip() { out("Zinvalid ipaddr in control/outgoingip (#4.3.0)\n"); zerodie(); }
 void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
 void temp_oserr() { out("Z\
 System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); }
@@ -99,6 +113,9 @@
   outhost();
   out(" but connection died. ");
   if (flagcritical) out("Possible duplicate! ");
+#ifdef TLS
+  if (ssl_err_str) { out(ssl_err_str); out(" "); }
+#endif
   out("(#4.4.2)\n");
   zerodie();
 }
@@ -110,6 +127,12 @@
 int saferead(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl) {
+    r = ssl_timeoutread(timeout, smtpfd, smtpfd, ssl, buf, len);
+    if (r < 0) ssl_err_str = ssl_strerror();
+  } else
+#endif
   r = timeoutread(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -117,6 +140,12 @@
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl) {
+    r = ssl_timeoutwrite(timeout, smtpfd, smtpfd, ssl, buf, len);
+    if (r < 0) ssl_err_str = ssl_strerror();
+  } else
+#endif 
   r = timeoutwrite(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -163,6 +192,59 @@
   return code;
 }
 
+#ifdef EHLO
+saa ehlokw = {0}; /* list of EHLO keywords and parameters */
+int maxehlokwlen = 0;
+
+unsigned long ehlo()
+{
+  stralloc *sa;
+  char *s, *e, *p;
+  unsigned long code;
+
+  if (ehlokw.len > maxehlokwlen) maxehlokwlen = ehlokw.len;
+  ehlokw.len = 0;
+
+# ifdef MXPS
+  if (type == 's') return 0;
+# endif
+
+  substdio_puts(&smtpto, "EHLO ");
+  substdio_put(&smtpto, helohost.s, helohost.len);
+  substdio_puts(&smtpto, "\r\n");
+  substdio_flush(&smtpto);
+
+  code = smtpcode();
+  if (code != 250) return code;
+
+  s = smtptext.s;
+  while (*s++ != '\n') ; /* skip the first line: contains the domain */
+
+  e = smtptext.s + smtptext.len - 6; /* 250-?\n */
+  while (s <= e)
+  {
+    if (!saa_readyplus(&ehlokw, 1)) temp_nomem();
+    sa = ehlokw.sa + ehlokw.len++;
+    if (ehlokw.len > maxehlokwlen) *sa = sauninit; else sa->len = 0;
+
+    /* smtptext is known to end in a '\n' */
+    for (p = (s += 4); ; ++p)
+      if (*p == '\n' || *p == ' ' || *p == '\t') {
+        if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
+        if (*p++ == '\n') break;
+        while (*p == ' ' || *p == '\t') ;
+        s = p;
+      }
+    s = p;
+    /* keyword should consist of alpha-num and '-'
+     * broken AUTH might use '=' instead of space */
+    for (p = sa->s; *p; ++p) if (*p == '=') { *p = 0; break; }
+  }
+
+  return 250;
+}
+#endif
+
 void outsmtptext()
 {
   int i; 
@@ -179,6 +261,11 @@
 char *prepend;
 char *append;
 {
+#ifdef TLS
+  /* shouldn't talk to the client unless in an appropriate state */
+  int state = ssl ? ssl->state : SSL_ST_BEFORE;
+  if (state & SSL_ST_OK || !smtps && state & SSL_ST_BEFORE)
+#endif
   substdio_putsflush(&smtpto,"QUIT\r\n");
   /* waiting for remote side is just too ridiculous */
   out(prepend);
@@ -186,22 +273,93 @@
   out(append);
   out(".\n");
   outsmtptext();
+
+#if defined(TLS) && defined(DEBUG)
+  if (ssl) {
+    X509 *peercert;
+
+    out("STARTTLS proto="); out(SSL_get_version(ssl));
+    out("; cipher="); out(SSL_get_cipher(ssl));
+
+    /* we want certificate details */
+    if (peercert = SSL_get_peer_certificate(ssl)) {
+      char *str;
+
+      str = X509_NAME_oneline(X509_get_subject_name(peercert), NULL, 0);
+      out("; subject="); out(str); OPENSSL_free(str);
+
+      str = X509_NAME_oneline(X509_get_issuer_name(peercert), NULL, 0);
+      out("; issuer="); out(str); OPENSSL_free(str);
+
+      X509_free(peercert);
+    }
+    out(";\n");
+  }
+#endif
+
   zerodie();
 }
 
+stralloc verh = {0};				/* quoted recipient */
+int flagverh;					/* argc */
+char *vp;					/* argv[3] */
+
 void blast()
 {
+  unsigned int posat, i;
+  int flagdobody,flagheader;
   int r;
   char ch;
 
+  posat = 0;					/* stays 0 if no VERH */
+  flagdobody = 0;				/* => 0 at first blank line */
+  flagheader = 1;
+  if (flagverh == 4) {				/* only if single recipient */
+    if (!quote2(&verh,vp)) temp_nomem();	/* non-canonicalized */
+    for (i = 0; i < verh.len; i++)		/* \n would destroy message */
+      if (verh.s[i] == '\n') verh.s[i] = '_';
+    posat = byte_rchr(verh.s,verh.len,'@');	/* posat=0 if no VERH */
+    if (posat == verh.len) posat = 0;
+  }
   for (;;) {
     r = substdio_get(&ssin,&ch,1);
     if (r == 0) break;
     if (r == -1) temp_read();
     if (ch == '.')
       substdio_put(&smtpto,".",1);
+    if (flagheader) {
+      if (ch == '\n') {		/* header ends */
+	flagheader = 0;
+	if (!flagdobody) posat = 0;
+      } else if (ch == '#') {	/* # starting line => VERH ... */
+	flagdobody = 1;		/* continues in body and ... */
+	continue;		/* character is suppressed. */
+      }
+    }
     while (ch != '\n') {
-      substdio_put(&smtpto,&ch,1);
+      if (ch == '#' && posat) {			/*   ... # */
+        r = substdio_get(&ssin,&ch,1);
+        if (r == 0) perm_partialline();
+        if (r == -1) temp_read();
+        if (ch == '#') {			/*  ... ## */
+	  r = substdio_get(&ssin,&ch,1);
+	  if (r == 0) perm_partialline();
+	  if (r == -1) temp_read();
+	  if (ch == 'L')			/* ... ##L */
+	    substdio_put(&smtpto,verh.s,posat);
+	  else if (ch == 'H')			/* ... ##H */
+	    substdio_put(&smtpto,verh.s + posat + 1,verh.len - posat - 1);
+	  else {        /* neither 'L' nor 'H' => write "##" */
+	    substdio_put(&smtpto,"##",2);
+	    continue;   /* already read next byte => goto while-loop entry */
+	  }
+	} else {
+	  substdio_put(&smtpto,"#",1);
+	  if (ch == '\n') break;
+	  substdio_put(&smtpto,&ch,1);
+        }
+      } else
+        substdio_put(&smtpto,&ch,1);
       r = substdio_get(&ssin,&ch,1);
       if (r == 0) perm_partialline();
       if (r == -1) temp_read();
@@ -214,6 +372,182 @@
   substdio_flush(&smtpto);
 }
 
+#ifdef TLS
+char *partner_fqdn = 0;
+
+# define TLS_QUIT quit(ssl ? "; connected to " : "; connecting to ", "")
+void tls_quit(const char *s1, const char *s2)
+{
+  out(s1); if (s2) { out(": "); out(s2); } TLS_QUIT;
+}
+# define tls_quit_error(s) tls_quit(s, ssl_error())
+
+int match_partner(const char *s, int len)
+{
+  if (!case_diffb(partner_fqdn, len, s) && !partner_fqdn[len]) return 1;
+  /* we also match if the name is *.domainname */
+  if (*s == '*') {
+    const char *domain = partner_fqdn + str_chr(partner_fqdn, '.');
+    if (!case_diffb(domain, --len, ++s) && !domain[len]) return 1;
+  }
+  return 0;
+}
+
+/* don't want to fail handshake if certificate can't be verified */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+int tls_init()
+{
+  int i;
+  SSL *myssl;
+  SSL_CTX *ctx;
+  stralloc saciphers = {0};
+  const char *ciphers, *servercert = 0;
+
+  if (partner_fqdn) {
+    struct stat st;
+    stralloc tmp = {0};
+    if (!stralloc_copys(&tmp, "control/tlshosts/")
+      || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn))
+      || !stralloc_catb(&tmp, ".pem", 5)) temp_nomem();
+    if (stat(tmp.s, &st)) alloc_free(tmp.s); else servercert = tmp.s;
+  }
+ 
+  if (!smtps) {
+    stralloc *sa = ehlokw.sa;
+    unsigned int len = ehlokw.len;
+    /* look for STARTTLS among EHLO keywords */
+    for ( ; len && case_diffs(sa->s, "STARTTLS"); ++sa, --len) ;
+    if (!len) {
+      if (!servercert) return 0;
+      out("ZNo TLS achieved while "); out(servercert);
+      out(" exists"); smtptext.len = 0; TLS_QUIT;
+    }
+  }
+
+  SSL_library_init();
+  ctx = SSL_CTX_new(SSLv23_client_method());
+  if (!ctx) {
+    if (!smtps && !servercert) return 0;
+    smtptext.len = 0;
+    tls_quit_error("ZTLS error initializing ctx");
+  }
+
+  if (servercert) {
+    if (!SSL_CTX_load_verify_locations(ctx, servercert, NULL)) {
+      SSL_CTX_free(ctx);
+      smtptext.len = 0;
+      out("ZTLS unable to load "); tls_quit_error(servercert);
+    }
+    /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_cb);
+  }
+
+  /* let the other side complain if it needs a cert and we don't have one */
+# define CLIENTCERT "control/clientcert.pem"
+  if (SSL_CTX_use_certificate_chain_file(ctx, CLIENTCERT))
+    SSL_CTX_use_RSAPrivateKey_file(ctx, CLIENTCERT, SSL_FILETYPE_PEM);
+# undef CLIENTCERT
+
+  myssl = SSL_new(ctx);
+  SSL_CTX_free(ctx);
+  if (!myssl) {
+    if (!smtps && !servercert) return 0;
+    smtptext.len = 0;
+    tls_quit_error("ZTLS error initializing ssl");
+  }
+
+  if (!smtps) substdio_putsflush(&smtpto, "STARTTLS\r\n");
+
+  /* while the server is preparing a responce, do something else */
+  if (control_readfile(&saciphers, "control/tlsclientciphers", 0) == -1)
+    { SSL_free(myssl); temp_control(); }
+  if (saciphers.len) {
+    for (i = 0; i < saciphers.len - 1; ++i)
+      if (!saciphers.s[i]) saciphers.s[i] = ':';
+    ciphers = saciphers.s;
+  }
+  else ciphers = "DEFAULT";
+  SSL_set_cipher_list(myssl, ciphers);
+  alloc_free(saciphers.s);
+
+  /* SSL_set_options(myssl, SSL_OP_NO_TLSv1); */
+  SSL_set_fd(myssl, smtpfd);
+
+  /* read the responce to STARTTLS */
+  if (!smtps) {
+    if (smtpcode() != 220) {
+      SSL_free(myssl);
+      if (!servercert) return 0;
+      out("ZSTARTTLS rejected while ");
+      out(servercert); out(" exists"); TLS_QUIT;
+    }
+    smtptext.len = 0;
+  }
+
+  ssl = myssl;
+  if (ssl_timeoutconn(timeout, smtpfd, smtpfd, ssl) <= 0)
+    tls_quit("ZTLS connect failed", ssl_strerror());
+
+  if (servercert) {
+    X509 *peercert;
+    STACK_OF(GENERAL_NAME) *gens;
+
+    int r = SSL_get_verify_result(ssl);
+    if (r != X509_V_OK) {
+      out("ZTLS unable to verify server with ");
+      tls_quit(servercert, X509_verify_cert_error_string(r));
+    }
+    alloc_free(servercert);
+
+    peercert = SSL_get_peer_certificate(ssl);
+    if (!peercert) {
+      out("ZTLS unable to verify server ");
+      tls_quit(partner_fqdn, "no certificate provided");
+    }
+
+    /* RFC 2595 section 2.4: find a matching name
+     * first find a match among alternative names */
+    gens = X509_get_ext_d2i(peercert, NID_subject_alt_name, 0, 0);
+    if (gens) {
+      for (i = 0, r = sk_GENERAL_NAME_num(gens); i < r; ++i)
+      {
+        const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i);
+        if (gn->type == GEN_DNS)
+          if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
+      }
+      sk_GENERAL_NAME_free(gens);
+    }
+
+    /* no alternative name matched, look up commonName */
+    if (!gens || i >= r) {
+      stralloc peer = {0};
+      X509_NAME *subj = X509_get_subject_name(peercert);
+      i = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
+      if (i >= 0) {
+        const ASN1_STRING *s = X509_NAME_get_entry(subj, i)->value;
+        if (s) { peer.len = s->length; peer.s = s->data; }
+      }
+      if (peer.len <= 0) {
+        out("ZTLS unable to verify server ");
+        tls_quit(partner_fqdn, "certificate contains no valid commonName");
+      }
+      if (!match_partner(peer.s, peer.len)) {
+        out("ZTLS unable to verify server "); out(partner_fqdn);
+        out(": received certificate for "); outsafe(&peer); TLS_QUIT;
+      }
+    }
+
+    X509_free(peercert);
+  }
+
+  if (smtps) if (smtpcode() != 220)
+    quit("ZTLS Connected to "," but greeting failed");
+
+  return 1;
+}
+#endif
+
 stralloc recip = {0};
 
 void smtp()
@@ -221,15 +555,58 @@
   unsigned long code;
   int flagbother;
   int i;
+
+#ifndef PORT_SMTP
+  /* the qmtpc patch uses smtp_port and undefines PORT_SMTP */
+# define port smtp_port
+#endif
+
+#ifdef TLS
+# ifdef MXPS
+  if (type == 'S') smtps = 1;
+  else if (type != 's')
+# endif
+    if (port == 465) smtps = 1;
+  if (!smtps)
+#endif
  
-  if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but greeting failed");
+  if (code != 220) quit("ZConnected to "," but greeting failed");
  
+#ifdef EHLO
+# ifdef TLS
+  if (!smtps)
+# endif
+  code = ehlo();
+
+# ifdef TLS
+  if (tls_init())
+    /* RFC2487 says we should issue EHLO (even if we might not need
+     * extensions); at the same time, it does not prohibit a server
+     * to reject the EHLO and make us fallback to HELO */
+    code = ehlo();
+# endif
+
+  if (code == 250) {
+    /* add EHLO response checks here */
+
+    /* and if EHLO failed, use HELO */
+  } else {
+#endif
+
   substdio_puts(&smtpto,"HELO ");
   substdio_put(&smtpto,helohost.s,helohost.len);
   substdio_puts(&smtpto,"\r\n");
   substdio_flush(&smtpto);
-  if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but my name was rejected");
+  if (code != 250) quit("ZConnected to "," but my name was rejected");
  
+#ifdef EHLO
+  }
+#endif
+
   substdio_puts(&smtpto,"MAIL FROM:<");
   substdio_put(&smtpto,sender.s,sender.len);
   substdio_puts(&smtpto,">\r\n");
@@ -254,7 +631,11 @@
       outsmtptext(); zero();
     }
     else {
-      out("r"); zero();
+      /*
+       * James Raftery <james@now.ie>
+       * Log _real_ envelope recipient, post canonicalisation.
+       */
+      out("r"); out("<"); outsafe(&reciplist.sa[i]); out("> "); zero();
       flagbother = 1;
     }
   }
@@ -310,6 +691,7 @@
 
 void getcontrols()
 {
+  int r;
   if (control_init() == -1) temp_control();
   if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control();
   if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
@@ -324,6 +706,12 @@
     case 1:
       if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
   }
+ r = control_readline(&outgoingip,"control/outgoingip");
+ if (-1 == r) { if (errno == error_nomem) temp_nomem(); temp_control(); }
+ if (0 == r && !stralloc_copy(&outgoingip, "0.0.0.0")) temp_nomem();
+ if (0 == strcmp(outgoingip.s, "0.0.0.0"))
+   { outip.d[0]=outip.d[1]=outip.d[2]=outip.d[3]=(unsigned long) 0; }
+ else if (!ip_scan(outgoingip.s, &outip)) temp_noip();
 }
 
 void main(argc,argv)
@@ -341,6 +729,8 @@
  
   sig_pipeignore();
   if (argc < 4) perm_usage();
+  flagverh = argc;
+  vp = argv[3];
   if (chdir(auto_qmail) == -1) temp_chdir();
   getcontrols();
  
@@ -414,9 +804,12 @@
     smtpfd = socket(AF_INET,SOCK_STREAM,0);
     if (smtpfd == -1) temp_oserr();
  
-    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
+    if (timeoutconn(smtpfd,&ip.ix[i].ip,&outip,(unsigned int) port,timeoutconnect) == 0) {
       tcpto_err(&ip.ix[i].ip,0);
       partner = ip.ix[i].ip;
+#ifdef TLS
+      partner_fqdn = ip.ix[i].fqdn;
+#endif
       smtp(); /* does not return */
     }
     tcpto_err(&ip.ix[i].ip,errno == error_timeout);
diff -urN qmail-1.03-orig/qmail-send.c qmail-1.03/qmail-send.c
--- qmail-1.03-orig/qmail-send.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-send.c	2003-10-03 14:08:49.000000000 -0400
@@ -47,6 +47,10 @@
 stralloc percenthack = {0};
 struct constmap mappercenthack;
 stralloc locals = {0};
+stralloc bouncemessage = {0};
+stralloc bouncesubject = {0};
+stralloc doublebouncemessage = {0};
+stralloc doublebouncesubject = {0};
 struct constmap maplocals;
 stralloc vdoms = {0};
 struct constmap mapvdoms;
@@ -55,6 +59,7 @@
 stralloc bouncehost = {0};
 stralloc doublebounceto = {0};
 stralloc doublebouncehost = {0};
+stralloc boundary = {0};
 
 char strnum2[FMT_ULONG];
 char strnum3[FMT_ULONG];
@@ -262,6 +267,8 @@
  while (!stralloc_copys(&comm_buf[c],"")) nomem();
  ch = delnum;
  while (!stralloc_append(&comm_buf[c],&ch)) nomem();
+ ch = delnum >> 8;
+ while (!stralloc_append(&comm_buf[c],&ch)) nomem();
  fnmake_split(id);
  while (!stralloc_cats(&comm_buf[c],fn.s)) nomem();
  while (!stralloc_0(&comm_buf[c])) nomem();
@@ -661,6 +668,7 @@
  static stralloc quoted = {0};
  datetime_sec birth;
  unsigned long qp;
+ int endhdr, lastlf, z;
 
  if (!getinfo(&sender,&birth,id)) return 0; /* XXX: print warning */
 
@@ -702,12 +710,33 @@
    qmail_puts(&qqt,"\nTo: ");
    while (!quote2(&quoted,bouncerecip)) nomem();
    qmail_put(&qqt,quoted.s,quoted.len);
-   qmail_puts(&qqt,"\n\
-Subject: failure notice\n\
-\n\
-Hi. This is the qmail-send program at ");
-   qmail_put(&qqt,bouncehost.s,bouncehost.len);
-   qmail_puts(&qqt,*sender.s ? ".\n\
+   if (*sender.s) {
+                          /* MIME header with boundary */
+     qmail_puts(&qqt,"\nMIME-Version: 1.0\n"
+                      "Content-Type: multipart/mixed; "
+                      "boundary=\"");
+     if (!stralloc_copyb(&boundary,strnum2,fmt_ulong(strnum2,birth))) nomem();
+     if (!stralloc_cat(&boundary,&bouncehost)) nomem();
+     if (!stralloc_catb(&boundary,strnum2,fmt_ulong(strnum2,id))) nomem();
+     qmail_put(&qqt,boundary.s,boundary.len);
+     qmail_puts(&qqt,"\"\nSubject: failure notice\n\n--");
+     qmail_put(&qqt,boundary.s,boundary.len);   /* def type is text/plain */
+   } else {
+     qmail_puts(&qqt,"\nSubject: ");
+     qmail_put(&qqt,doublebouncesubject.s,doublebouncesubject.len);
+   }
+   qmail_puts(&qqt,"\n\n");
+   if (*sender.s && bouncemessage.s[0]) {
+     qmail_put(&qqt,bouncemessage.s,bouncemessage.len);
+     qmail_puts(&qqt,"\n");
+   } else if (!*sender.s && doublebouncemessage.s[0]) {
+     qmail_put(&qqt,doublebouncemessage.s,doublebouncemessage.len);
+     qmail_puts(&qqt,"\n");
+   }
+   else {
+     qmail_puts(&qqt,"Hi. This is the qmail-send program at ");
+     qmail_put(&qqt,bouncehost.s,bouncehost.len);
+     qmail_puts(&qqt,*sender.s ? ".\n\
 I'm afraid I wasn't able to deliver your message to the following addresses.\n\
 This is a permanent error; I've given up. Sorry it didn't work out.\n\
 \n\
@@ -715,7 +744,7 @@
 I tried to deliver a bounce message to this address, but the bounce bounced!\n\
 \n\
 ");
-
+   }
    fd = open_read(fn2.s);
    if (fd == -1)
      qmail_fail(&qqt);
@@ -729,7 +758,9 @@
        qmail_fail(&qqt);
     }
 
-   qmail_puts(&qqt,*sender.s ? "--- Below this line is a copy of the message.\n\n" : "--- Below this line is the original bounce.\n\n");
+   qmail_puts(&qqt,*sender.s ? "--- Enclosed are the original headers of the message.\n\n--" : "--- Enclosed is the original bounce.\n\n--");
+   qmail_put(&qqt,boundary.s,boundary.len);	/* enclosure boundary */
+   qmail_puts(&qqt,"\nContent-Type: message/rfc822\n\n");
    qmail_puts(&qqt,"Return-Path: <");
    while (!quote2(&quoted,sender.s)) nomem();
    qmail_put(&qqt,quoted.s,quoted.len);
@@ -741,13 +772,31 @@
    else
     {
      substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
-     while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
+
+     endhdr = 0; lastlf = 0;
+     while((r = substdio_get(&ssread,buf,sizeof(buf))) && (!endhdr)) {
+       if(lastlf && (*buf == '\n')) /* case \n\n spanned across two get() */
+         break;
+       for(z=0; z<r; z++) {
+         if((buf[z] == '\n') && (buf[z+1] == '\n')) {
+           r = z;
+	   endhdr = 1;
+	 }
+         else if((buf[z]) == '\n')
+           lastlf = 1;
+       }
        qmail_put(&qqt,buf,r);
+     }
+
      close(fd);
      if (r == -1)
        qmail_fail(&qqt);
     }
 
+   qmail_puts(&qqt,"\n\n(Body supressed)\n\n--");		/* end boundary */
+   qmail_put(&qqt,boundary.s,boundary.len);
+   qmail_puts(&qqt,"--\n");
+
    qmail_from(&qqt,bouncesender);
    qmail_to(&qqt,bouncerecip);
    if (*qmail_close(&qqt))
@@ -906,41 +955,42 @@
      dline[c].len = REPORTMAX;
      /* qmail-lspawn and qmail-rspawn are responsible for keeping it short */
      /* but from a security point of view, we don't trust rspawn */
-   if (!ch && (dline[c].len > 1))
+   if (!ch && (dline[c].len > 2))
     {
      delnum = (unsigned int) (unsigned char) dline[c].s[0];
+     delnum += (unsigned int) ((unsigned int) dline[c].s[1]) << 8;
      if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used)
        log1("warning: internal error: delivery report out of range\n");
      else
       {
        strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0;
-       if (dline[c].s[1] == 'Z')
+       if (dline[c].s[2] == 'Z')
 	 if (jo[d[c][delnum].j].flagdying)
 	  {
-	   dline[c].s[1] = 'D';
+	   dline[c].s[2] = 'D';
 	   --dline[c].len;
 	   while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem();
 	   while (!stralloc_0(&dline[c])) nomem();
 	  }
-       switch(dline[c].s[1])
+       switch(dline[c].s[2])
 	{
 	 case 'K':
 	   log3("delivery ",strnum3,": success: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
 	 case 'Z':
 	   log3("delivery ",strnum3,": deferral: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
 	   break;
 	 case 'D':
 	   log3("delivery ",strnum3,": failure: ");
-	   logsafe(dline[c].s + 2);
+	   logsafe(dline[c].s + 3);
 	   log1("\n");
-	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2);
+	   addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 3);
 	   markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos);
 	   --jo[d[c][delnum].j].numtodo;
 	   break;
@@ -1454,6 +1504,10 @@
  if (!stralloc_cat(&doublebounceto,&doublebouncehost)) return 0;
  if (!stralloc_0(&doublebounceto)) return 0;
  if (control_readfile(&locals,"control/locals",1) != 1) return 0;
+ if (control_readnativefile(&bouncemessage,"control/bouncemessage") != 1) return 0;
+ if (control_readnativefile(&doublebouncemessage,"control/doublebouncemessage") != 1) return 0;
+ if (control_rldef(&bouncesubject,"control/bouncesubject",0,"failure notice") != 1) return 0;
+ if (control_rldef(&doublebouncesubject,"control/doublebouncesubject",0,"failure notice") != 1) return 0;
  if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0;
  switch(control_readfile(&percenthack,"control/percenthack",0))
   {
@@ -1544,7 +1598,7 @@
  numjobs = 0;
  for (c = 0;c < CHANNELS;++c)
   {
-   char ch;
+   char ch, ch1;
    int u;
    int r;
    do
@@ -1552,7 +1606,13 @@
    while ((r == -1) && (errno == error_intr));
    if (r < 1)
     { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
+   do
+     r = read(chanfdin[c],&ch1,1);
+   while ((r == -1) && (errno == error_intr));
+   if (r < 1)
+    { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); }
    u = (unsigned int) (unsigned char) ch;
+   u += (unsigned int) ((unsigned char) ch1) << 8;
    if (concurrency[c] > u) concurrency[c] = u;
    numjobs += concurrency[c];
   }
diff -urN qmail-1.03-orig/qmail-smtpd.8 qmail-1.03/qmail-smtpd.8
--- qmail-1.03-orig/qmail-smtpd.8	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-smtpd.8	2003-10-03 14:08:49.000000000 -0400
@@ -3,6 +3,11 @@
 qmail-smtpd \- receive mail via SMTP
 .SH SYNOPSIS
 .B qmail-smtpd
+[
+.I hostname
+.I checkprogram
+.I subprogram
+]
 .SH DESCRIPTION
 .B qmail-smtpd
 receives mail messages via the Simple Mail Transfer Protocol (SMTP)
@@ -14,6 +19,15 @@
 see
 .BR tcp-environ(5) .
 
+If the environment variable
+.B SMTPS
+is non-empty,
+.B qmail-smtpd
+starts a TLS session (to support the deprecated SMTPS protocol,
+normally on port 465). Otherwise,
+.B qmail-smtpd
+offers the STARTTLS extension to ESMTP.
+
 .B qmail-smtpd
 is responsible for counting hops.
 It rejects any message with 100 or more 
@@ -23,7 +37,29 @@
 header fields.
 
 .B qmail-smtpd
-supports ESMTP, including the 8BITMIME and PIPELINING options.
+supports ESMTP, including the 8BITMIME, PIPELINING, and AUTH options.
+
+.B qmail-smtpd
+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types.  It invokes
+.IR checkprogram ,
+which reads on file descriptor 3 the username, a 0 byte, the password
+or challenge derived from
+.IR hostname ,
+another 0 byte, a CRAM-MD5 response (if applicable to the AUTH type),
+and a final 0 byte.
+.I checkprogram
+invokes
+.I subprogram
+upon successful authentication, which should in turn return 0 to
+.BR qmail-smtpd ,
+effectively setting the environment variables RELAYCLIENT and TCPREMOTEINFO
+(any supplied value replaced with the authenticated username).
+.B qmail-smtpd
+will reject the authentication attempt if it receives a nonzero return
+value from
+.I checkprogram
+or
+.IR subprogram .
 .SH TRANSPARENCY
 .B qmail-smtpd
 converts the SMTP newline convention into the UNIX newline convention
@@ -49,6 +85,12 @@
 .BR @\fIhost ,
 meaning every address at
 .IR host .
+
+.TP 5
+.I clientca.pem
+A list of Certifying Authority (CA) certificates that are used to verify
+the client-presented certificates during a TLS-encrypted session.
+
 .TP 5
 .I databytes
 Maximum number of bytes allowed in a message,
@@ -97,6 +139,12 @@
 This is done before
 .IR rcpthosts .
 .TP 5
+.I mfcheck
+If set,
+.B qmail-smtpd
+tries to resolve the domain of the envelope from address.  It can be
+handy when you want to filter out spamhosts.
+.TP 5
 .I morercpthosts
 Extra allowed RCPT domains.
 If
@@ -151,6 +199,19 @@
 
 Envelope recipient addresses without @ signs are
 always allowed through.
+
+.TP 5
+.I rsa512.pem
+If this 512 RSA key is provided,
+.B qmail-smtpd
+will use it for TLS sessions instead of generaring one on-the-fly.
+
+.TP 5
+.I servercert.pem
+SSL certificate to be presented to clients in
+TLS-encrypted sessions. Certifying Authority
+(CA) and intermediate certificates can be added at the end of the file.
+
 .TP 5
 .I smtpgreeting
 SMTP greeting message.
@@ -169,6 +230,24 @@
 .B qmail-smtpd
 will wait for each new buffer of data from the remote SMTP client.
 Default: 1200.
+
+.TP 5
+.I tlsclients
+A list of email addresses. When relay rules would reject an incoming message,
+.B qmail-smtpd
+can allow it if the client presents a certificate that can be verified against
+the CA list in
+.I clientca.pem
+and the certificate email address is in
+.IR tlsclients .
+
+.TP 5
+.I tlsserverciphers
+A set of OpenSSL cipher strings. Multiple ciphers contained in a
+string should be separated by a colon. If the environment variable
+.B TLSCIPHERS
+is set to such a string, it takes precedence.
+
 .SH "SEE ALSO"
 tcp-env(1),
 tcp-environ(5),
@@ -177,3 +256,6 @@
 qmail-newmrh(8),
 qmail-queue(8),
 qmail-remote(8)
+.SH "HISTORY"
+The patch enabling the ESMTP AUTH option is not part of the standard
+qmail-1.03 distribution.
diff -urN qmail-1.03-orig/qmail-smtpd.8.orig qmail-1.03/qmail-smtpd.8.orig
--- qmail-1.03-orig/qmail-smtpd.8.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/qmail-smtpd.8.orig	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,215 @@
+.TH qmail-smtpd 8
+.SH NAME
+qmail-smtpd \- receive mail via SMTP
+.SH SYNOPSIS
+.B qmail-smtpd
+[
+.I hostname
+.I checkprogram
+.I subprogram
+]
+.SH DESCRIPTION
+.B qmail-smtpd
+receives mail messages via the Simple Mail Transfer Protocol (SMTP)
+and invokes
+.B qmail-queue
+to deposit them into the outgoing queue.
+.B qmail-smtpd
+must be supplied several environment variables;
+see
+.BR tcp-environ(5) .
+
+.B qmail-smtpd
+is responsible for counting hops.
+It rejects any message with 100 or more 
+.B Received
+or
+.B Delivered-To
+header fields.
+
+.B qmail-smtpd
+supports ESMTP, including the 8BITMIME, PIPELINING, and AUTH options.
+
+.B qmail-smtpd
+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types.  It invokes
+.IR checkprogram ,
+which reads on file descriptor 3 the username, a 0 byte, the password
+or challenge derived from
+.IR hostname ,
+another 0 byte, a CRAM-MD5 response (if applicable to the AUTH type),
+and a final 0 byte.
+.I checkprogram
+invokes
+.I subprogram
+upon successful authentication, which should in turn return 0 to
+.BR qmail-smtpd ,
+effectively setting the environment variables RELAYCLIENT and TCPREMOTEINFO
+(any supplied value replaced with the authenticated username).
+.B qmail-smtpd
+will reject the authentication attempt if it receives a nonzero return
+value from
+.I checkprogram
+or
+.IR subprogram .
+.SH TRANSPARENCY
+.B qmail-smtpd
+converts the SMTP newline convention into the UNIX newline convention
+by converting CR LF into LF.
+It returns a temporary error and drops the connection on bare LFs;
+see
+.BR http://pobox.com/~djb/docs/smtplf.html .
+
+.B qmail-smtpd
+accepts messages that contain long lines or non-ASCII characters,
+even though such messages violate the SMTP protocol.
+.SH "CONTROL FILES"
+.TP 5
+.I badmailfrom
+Unacceptable envelope sender addresses.
+.B qmail-smtpd
+will reject every recipient address for a message
+if the envelope sender address is listed in
+.IR badmailfrom .
+A line in
+.I badmailfrom
+may be of the form
+.BR @\fIhost ,
+meaning every address at
+.IR host .
+.TP 5
+.I databytes
+Maximum number of bytes allowed in a message,
+or 0 for no limit.
+Default: 0.
+If a message exceeds this limit,
+.B qmail-smtpd
+returns a permanent error code to the client;
+in contrast, if
+the disk is full or
+.B qmail-smtpd
+hits a resource limit,
+.B qmail-smtpd
+returns a temporary error code.
+
+.I databytes
+counts bytes as stored on disk, not as transmitted through the network.
+It does not count the
+.B qmail-smtpd
+Received line, the
+.B qmail-queue
+Received line, or the envelope.
+
+If the environment variable
+.B DATABYTES
+is set, it overrides
+.IR databytes .
+.TP 5
+.I localiphost
+Replacement host name for local IP addresses.
+Default:
+.IR me ,
+if that is supplied.
+.B qmail-smtpd
+is responsible for recognizing dotted-decimal addresses for the
+current host.
+When it sees a recipient address of the form
+.IR box@[d.d.d.d] ,
+where
+.I d.d.d.d
+is a local IP address,
+it replaces
+.IR [d.d.d.d]
+with
+.IR localiphost .
+This is done before
+.IR rcpthosts .
+.TP 5
+.I mfcheck
+If set,
+.B qmail-smtpd
+tries to resolve the domain of the envelope from address.  It can be
+handy when you want to filter out spamhosts.
+.TP 5
+.I morercpthosts
+Extra allowed RCPT domains.
+If
+.I rcpthosts
+and
+.I morercpthosts
+both exist,
+.I morercpthosts
+is effectively appended to
+.IR rcpthosts .
+
+You must run
+.B qmail-newmrh
+whenever
+.I morercpthosts
+changes.
+
+Rule of thumb for large sites:
+Put your 50 most commonly used domains into
+.IR rcpthosts ,
+and the rest into
+.IR morercpthosts .
+.TP 5
+.I rcpthosts
+Allowed RCPT domains.
+If
+.I rcpthosts
+is supplied,
+.B qmail-smtpd
+will reject
+any envelope recipient address with a domain not listed in
+.IR rcpthosts .
+
+Exception:
+If the environment variable
+.B RELAYCLIENT
+is set,
+.B qmail-smtpd
+will ignore
+.IR rcpthosts ,
+and will append the value of
+.B RELAYCLIENT
+to each incoming recipient address.
+
+.I rcpthosts
+may include wildcards:
+
+.EX
+   heaven.af.mil
+   .heaven.af.mil
+.EE
+
+Envelope recipient addresses without @ signs are
+always allowed through.
+.TP 5
+.I smtpgreeting
+SMTP greeting message.
+Default:
+.IR me ,
+if that is supplied;
+otherwise
+.B qmail-smtpd
+will refuse to run.
+The first word of
+.I smtpgreeting
+should be the current host's name.
+.TP 5
+.I timeoutsmtpd
+Number of seconds
+.B qmail-smtpd
+will wait for each new buffer of data from the remote SMTP client.
+Default: 1200.
+.SH "SEE ALSO"
+tcp-env(1),
+tcp-environ(5),
+qmail-control(5),
+qmail-inject(8),
+qmail-newmrh(8),
+qmail-queue(8),
+qmail-remote(8)
+.SH "HISTORY"
+The patch enabling the ESMTP AUTH option is not part of the standard
+qmail-1.03 distribution.
diff -urN qmail-1.03-orig/qmail-smtpd.c qmail-1.03/qmail-smtpd.c
--- qmail-1.03-orig/qmail-smtpd.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail-smtpd.c	2003-10-09 11:42:54.000000000 -0400
@@ -1,3 +1,13 @@
+
+/*
+ * 
+ * Patch 'qmail-smtpd-chkusr' v.1.0
+ * for qmail 1.03 and vpopmail 5.3.3
+ * 
+ * Antonio Nati tonix@interazioni.it
+ * 
+ */
+
 #include "sig.h"
 #include "readwrite.h"
 #include "stralloc.h"
@@ -23,14 +33,44 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "strerr.h"
+#include "wait.h"
+#include "fd.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include "vpopmail.h"
+#include "vauth.h"
+#include "vpopmail_config.h"
+#include "dns.h"
 
+#define AUTHCRAM
 #define MAXHOPS 100
 unsigned int databytes = 0;
+unsigned int mfchk = 0;
 int timeout = 1200;
 
+const char *protocol = "SMTP";
+
+#ifdef TLS
+# include "tls.h"
+# include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
+#endif
+
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl && fd == ssl_wfd)
+    r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
   r = timeoutwrite(timeout,fd,buf,len);
   if (r <= 0) _exit(1);
   return r;
@@ -50,8 +90,22 @@
 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
 
 void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_hmf() { out("553 sorry, your envelope sender domain must exist (#5.7.  1)\r\n"); }
+void err_smf() { out("451 DNS temporary failure (#4.3.0)\r\n"); }
+void err_brt() { out("553 sorry, this recipient is in my badrecipientto list (#5.7.1)\r\n"); }
+#ifndef TLS
 void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
+#else
+void err_nogateway()
+{
+  out("553 sorry, that domain isn't in my list of allowed rcpthosts");
+  tls_nogateway();
+  out(" (#5.7.1)\r\n");
+}
+#endif
+void err_badbounce() { out("550 sorry, bounce messages should have a single envelope recipient (#5.7.1)\r\n"); }
 void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
+void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
 void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
 void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
@@ -59,6 +113,15 @@
 void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
 
+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+int err_authabrt() { out("501 auth exchange cancelled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
 
 stralloc greeting = {0};
 
@@ -96,6 +159,11 @@
 int bmfok = 0;
 stralloc bmf = {0};
 struct constmap mapbmf;
+int sigsok = 0;
+stralloc sigs = {0};
+int brtok = 0;
+stralloc brt = {0};
+struct constmap mapbrt;
 
 void setup()
 {
@@ -112,11 +180,23 @@
 
   if (rcpthosts_init() == -1) die_control();
 
+  if (control_readint(&mfchk,"control/mfcheck") == -1) die_control();
+  x = env_get("MFCHECK");
+  if (x) { scan_ulong(x,&u); mfchk = u; }
+
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
   if (bmfok == -1) die_control();
   if (bmfok)
     if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+
+  brtok = control_readfile(&brt,"control/badrcptto",0);
+  if (brtok == -1) die_control();
+  if (brtok)
+    if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem();
  
+  sigsok = control_readfile(&sigs,"control/signatures",0);
+  if (sigsok == -1) die_control();
+
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
   if (x) { scan_ulong(x,&u); databytes = u; }
@@ -131,6 +211,11 @@
   if (!remotehost) remotehost = "unknown";
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
+
+#ifdef TLS
+  if (env_get("SMTPS")) { smtps = 1; tls_init(); }
+  else
+#endif
   dohelo(remotehost);
 }
 
@@ -197,6 +282,40 @@
   return 1;
 }
 
+int sizelimit(arg)
+char *arg;
+{
+  int i;
+  long r;
+  unsigned long sizebytes = 0;
+
+  i = str_chr(arg,'<');
+  if (arg[i])
+    arg += i + 1;
+  else {
+    arg += str_chr(arg,':');
+    if (*arg == ':') ++arg;
+    while (*arg == ' ') ++arg;
+  }
+
+  arg += str_chr(arg,' ');
+  if (*arg == ' ') while (*arg == ' ') ++arg;
+  else return 1;
+
+  i = str_chr(arg,'=');
+  arg[i] = 0;
+  if (case_equals(arg,"SIZE")) {
+    arg += i;
+    while (*++arg && *arg > 47 && *arg < 58) {
+      sizebytes *= 10;
+      sizebytes += *arg - 48;
+    }
+    r = databytes - sizebytes;
+    if (r < 0) return 0;
+  }
+  return 1;
+}
+
 int bmfcheck()
 {
   int j;
@@ -208,11 +327,266 @@
   return 0;
 }
 
+int brtcheck()
+{
+  int j;
+  if (!brtok) return 0;
+  if (constmap(&mapbrt,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbrt,addr.s + j,addr.len - j - 1)) return 1;
+  return 0;
+}
+void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); }
+
+int realrcpt_check()
+{
+  stralloc user = {0};
+  stralloc domain = {0};
+  stralloc domain_path = {0};
+  stralloc bounce_path = {0};
+  stralloc alias_name = {0};
+  stralloc alias_path = {0};
+  stralloc mailing_path = {0};
+  int count;
+  int retstat = 0;
+  struct vqpasswd *user_passwd = NULL;
+  int fd_file = -1;
+  int read_char;
+  DIR *dir_file = NULL;
+  uid_t eff_uid;
+  gid_t eff_gid;
+  int offset;
+  char read_buf[1024];
+
+/* if not local rcpthost we cannot control mailbox */
+/* this line should only be uncommented if addrallowed is not
+ * called elsewhere - otherwise qmail-smtp will fail if
+ * morercpthosts.cdb exists.
+*/
+/*
+ if (!addrallowed()) { return 1; }
+*/
+
+/* Set up our variables */
+
+/* qmail-smtpd is running now as (effective) qmaild:qnofiles */
+/* Save the effective UID & GID (qmaild:qnofiles) */
+  eff_uid = geteuid ();
+  eff_gid = getegid ();
+
+/* Search the '@' character */
+  count = byte_rchr(addr.s,addr.len,'@');
+
+/* The following lines could interest people using # instead of @ in e-mail address */
+/* If '@' not found search the '%' character */
+/*
+  if (count >= addr.len) {
+    count = byte_rchr(addr.s,addr.len,'%');
+  }
+*/
+
+/*
+ * Give extra room to variables used often or used outside stralloc_x calls
+ * This should make all safer and even faster
+ * (when these fields are used by stralloc_x routines)
+*/
+  if (!stralloc_ready (&domain, 200)) die_nomem();
+  if (!stralloc_ready (&domain_path, 200)) die_nomem();
+
+  if (count < addr.len) {
+    if (!stralloc_copyb (&user, addr.s, count)) die_nomem();
+    if (!stralloc_0 (&user)) die_nomem();
+    if (!stralloc_copys (&domain, addr.s + count + 1)) die_nomem();
+    if (!stralloc_0 (&domain)) die_nomem();
+  }
+  else {
+    if (!stralloc_copys (&user, addr.s)) die_nomem();
+    if (!stralloc_0 (&user)) die_nomem();
+    if (!stralloc_copys (&domain, DEFAULT_DOMAIN)) die_nomem();
+    if (!stralloc_0 (&domain)) die_nomem();
+  }
+
+/* My personal control: continue only if a domain (default or not) is specified */
+
+  if (domain.len == 1)
+    return 0;
+
+/* Now set new effective UID & GID, getting it from real UID & GID (vpopmail:vchkpw) */
+
+  setegid (getgid());
+  seteuid (getuid());
+
+/* qmail-smtpd is running now as effective vpopmail:vchkpw */
+
+  case_lowers (user.s);
+  case_lowers (domain.s);
+
+/* Check if domain is a real domain */
+
+  if (!stralloc_0 (&domain)) die_nomem();
+  vget_real_domain(domain.s, domain.a);
+
+  domain.len = strlen (domain.s);
+  if (domain.len > (domain.a - 1)) die_nomem();
+
+/* Let's get domain's real path */
+  vget_assign(domain.s, domain_path.s, 156, NULL, NULL);
+
+  domain_path.len = strlen (domain_path.s);
+
+/* Now Let's start the test suite */
+
+	switch (0) {
+
+	case 0:
+/* Check if domain has bouncing enabled */
+
+		/* Allocate room for bounce_path */
+  		if (!stralloc_ready (&bounce_path, 200)) die_nomem();
+		if (!stralloc_copy (&bounce_path, &domain_path)) die_nomem();
+  		if (!stralloc_cats (&bounce_path, "/.qmail-default")) die_nomem();
+		if (!stralloc_0 (&bounce_path)) die_nomem();
+
+  		read_char = 0;
+  		fd_file = open_read (bounce_path.s);	
+  		if (fd_file != -1) {
+      			read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
+      			close (fd_file);
+      			if (read_char < 0) read_char = 0;
+  			}
+  		read_buf[read_char] = 0;
+
+  		if ( strstr(read_buf, "bounce-no-mailbox") == NULL ) {
+			retstat = 1;
+			break;
+  		}
+  
+	case 1:
+/* User control: check the existance of a real user */
+
+	  	user_passwd = vauth_getpw (user.s, domain.s);
+	  	if (user_passwd != NULL) {
+
+		/* If user exists check if he has BOUNCE_MAIL flag set */
+
+			if (user_passwd->pw_gid & BOUNCE_MAIL)
+		    		retstat = 0;
+	    		else
+		    		retstat = 1;
+			break;
+	  	}
+
+	case 2:
+/* Check for aliases/forwards - valias*/
+
+		if (valias_select (user.s, domain.s) != NULL) {
+			retstat = 1;
+			break;
+		}
+
+	case 3:
+/* Check for aliases/forwards - .qmail-x files */
+
+		/* Allocate room for alias_path */
+  		if (!stralloc_ready (&alias_path, 200)) die_nomem();
+	    	if (!stralloc_copy (&alias_name, &user)) die_nomem();
+
+		/* Change all '.' in ':' before continuing on aliases */
+	    	for (count = 0; count < alias_name.len; ++count)
+	      	if (*(alias_name.s + count) == '.') *(alias_name.s + count) = ':';
+
+	    	if (!stralloc_copy (&alias_path, &domain_path)) die_nomem();
+	    	if (!stralloc_cats (&alias_path, "/.qmail-")) die_nomem();
+	    	if (!stralloc_cats (&alias_path, alias_name.s)) die_nomem();
+	    	if (!stralloc_0 (&alias_path)) die_nomem();
+
+		/* access executes anyway as real (vpopmail:vchkpw), that's ok */
+	    	if (access (alias_path.s, F_OK) == 0) {
+	      		retstat = 1;
+			break;
+	    	}
+
+	case 4:
+/* Let's check for mailing lists */
+
+		/* Allocate room for mailing_path */
+  		if (!stralloc_ready (&mailing_path, 300)) die_nomem();
+
+		/* Search for the outer '-' character */
+	      	for (offset = user.len - 1; offset > 0; --offset)
+			if (*(user.s + offset) == '-')  {
+				if (!stralloc_copy (&mailing_path, &domain_path)) die_nomem();
+	      			if (!stralloc_cats (&mailing_path, "/")) die_nomem();
+	      			if (!stralloc_catb (&mailing_path, user.s, offset)) die_nomem();
+	      			if (!stralloc_cats (&mailing_path, "/mailinglist")) die_nomem();
+	      			if (!stralloc_0 (&mailing_path)) die_nomem();
+				/* access executes anyway as real (vpopmail:vchkpw), that's ok */
+			    	if (access (mailing_path.s, F_OK) == 0) {
+                			retstat = 1;
+                			break;
+	            		}
+	        	}
+
+/*
+ * Add this code if another case is following
+		if (retstat == 1)
+			break;
+*/
+	    
+	} /* end switch */
+
+/* Now switch back effective to saved UID & GID (qmaild:qnofiles) */
+
+  setegid (eff_gid);
+  seteuid (eff_uid);
+
+/* qmail-smtpd is running again as (effective) qmaild:qnofiles */
+
+  return retstat;
+}
+
+
+int mfcheck()
+{
+  stralloc sa = {0};
+  ipalloc ia = {0};
+  unsigned int random;
+  int j;
+
+  if (!mfchk) return 0;
+  random = now() + (getpid() << 16);
+  j = byte_rchr(addr.s,addr.len,'@') + 1;
+  if (j < addr.len) {
+    stralloc_copys(&sa, addr.s + j);
+    dns_init(0);
+    j = dns_mxip(&ia,&sa,random);
+    if (j < 0) return j;
+  }
+  return 0;
+}
+
+int sigscheck(stralloc *line) {
+  int i, j;
+
+  j = 0;
+  for (i = 0; i < sigs.len; i++) if (!sigs.s[i]) {
+    if (i-j < line->len)
+      if (!str_diffn(line->s,sigs.s+j,i-j))
+	return 1;
+    j = i+1;
+  }
+  return 0;
+}
+
 int addrallowed()
 {
   int r;
   r = rcpthosts(addr.s,str_len(addr.s));
   if (r == -1) die_control();
+#ifdef TLS
+  if (r == 0) if (tls_verify()) r = -2;
+#endif
   return r;
 }
 
@@ -221,17 +595,36 @@
 int flagbarf; /* defined if seenmail */
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
+int recipcount;
 
 void smtp_helo(arg) char *arg;
 {
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
 }
+/* ESMTP extensions are published here */
 void smtp_ehlo(arg) char *arg;
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  smtp_greet("250-");
+#ifdef TLS
+  if (!ssl) out("\r\n250-STARTTLS");
+#endif
+#ifdef AUTHCRAM
+  out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+  out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+#else
+  out("\r\n250-AUTH LOGIN PLAIN");
+  out("\r\n250-AUTH=LOGIN PLAIN");
+#endif
+  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
 }
+char size_buf[FMT_ULONG];
+void smtp_size()
+{
+  size_buf[fmt_ulong(size_buf,(unsigned long) databytes)] = 0;
+  out("250 SIZE "); out(size_buf); out("\r\n");
+}
 void smtp_rset()
 {
   seenmail = 0;
@@ -240,17 +633,28 @@
 void smtp_mail(arg) char *arg;
 {
   if (!addrparse(arg)) { err_syntax(); return; }
+  if (databytes && !sizelimit(arg)) { err_size(); return; }
   flagbarf = bmfcheck();
+  switch(mfcheck()) {
+    case DNS_HARD: err_hmf(); return;
+    case DNS_SOFT: err_smf(); return;
+    case DNS_MEM: die_nomem();
+  }
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  recipcount = 0;
   out("250 ok\r\n");
 }
 void smtp_rcpt(arg) char *arg; {
   if (!seenmail) { err_wantmail(); return; }
   if (!addrparse(arg)) { err_syntax(); return; }
-  if (flagbarf) { err_bmf(); return; }
+  if (flagbarf) {
+    strerr_warn4("qmail-smtpd: badmailfrom: ",mailfrom.s," at ",remoteip,0);
+    err_bmf();
+    return;
+  }
   if (relayclient) {
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
@@ -258,9 +662,12 @@
   }
   else
     if (!addrallowed()) { err_nogateway(); return; }
+  if (!env_get("RELAYCLIENT") && brtcheck()) { err_brt(); return; }
+  if (!realrcpt_check()) { err_realrcpt(); return; }
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  recipcount++;
   out("250 ok\r\n");
 }
 
@@ -269,6 +676,11 @@
 {
   int r;
   flush();
+#ifdef TLS
+  if (ssl && fd == ssl_rfd)
+    r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
   r = timeoutread(timeout,fd,buf,len);
   if (r == -1) if (errno == error_timeout) die_alarm();
   if (r <= 0) die_read();
@@ -281,9 +693,131 @@
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
 
+int linespastheader;          /* =0 after boundary is found in body, */
+                                /* until blank line */
+char linetype;
+int flagexecutable;
+
+stralloc line = {0};
+stralloc content = {0};
+stralloc boundary = {0};
+int boundary_start;
+
+/*
+
+def put(ch):
+    line.append(ch)
+    if ch == '\n':
+        if linepastheader == 0:
+            if line.beginswith('Content-Type:'):
+                content =
+
+ put() puts characters into the queue.  We remember those characters
+   and form them into a line.  When we get a newline, we examine the
+   line.  If we're currently in a header (0 linespastheader), we look
+   for Content-Type.  If we're at the newline that ends a header, we
+   look to see if the content is multipart.  If it is, then we push
+   the current boundary, remember the boundary, otherwise we set the
+   boundary to the empty string.  Set the linespastheader to 1.  When
+   linespastheader is 1, and the boundary is empty, scan the line for
+   signatures.  If the boundary is non-empty, look for a match against
+   the boundary.  If it matches and is followed by two dashes, pop the
+   boundary, otherwise set linespastheader to 0.
+*/
+
 void put(ch)
 char *ch;
 {
+  char *cp, *cpstart, *cpafter;
+  unsigned int len;
+
+  if (line.len < 1024)
+    if (!stralloc_catb(&line,ch,1)) die_nomem();
+
+  if (*ch == '\n') {
+    if (linespastheader == 0) {
+      if (line.len == 1) {
+      linespastheader = 1;
+      if (content.len) {                      /* MIME header */
+        cp = content.s;
+        len = content.len;
+        while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
+        cpstart = cp;
+        if (len && *cp == '"') {                      /* might be commented */
+          ++cp; --len; cpstart = cp;
+          while (len && *cp != '"') { ++cp; --len; }
+        } else {
+          while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
+            ++cp; --len;
+          }
+        }
+
+        cpafter = content.s+content.len;
+        while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
+          ++cp;
+          while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
+          if (case_startb(cp,cpafter - cp,"boundary=")) {
+            cp += 9;                  /* after boundary= */
+            if (cp < cpafter && *cp == '"') {
+              ++cp;
+              cpstart = cp;
+              while (cp < cpafter && *cp != '"') ++cp;
+            } else {
+              cpstart = cp;
+              while (cp < cpafter &&
+                 *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
+            }
+            /* push the current boundary.  Append a null and remember start. */
+            if (!stralloc_0(&boundary)) die_nomem();
+            boundary_start = boundary.len;
+            if (!stralloc_cats(&boundary,"--")) die_nomem();
+            if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
+                    die_nomem();
+            break;
+          }
+        }
+      }
+      } else { /* non-blank header line */
+      if ((*line.s == ' ' || *line.s == '\t')) {
+        switch(linetype) {
+          case 'C': if (!stralloc_catb(&content,line.s,line.len-1)) die_nomem(); break;
+          default: break;
+        }
+      } else {
+        if (case_startb(line.s,line.len,"content-type:")) {
+          if (!stralloc_copyb(&content,line.s+13,line.len-14)) die_nomem();
+          linetype = 'C';
+        } else {
+          linetype = ' ';
+        }
+      }
+      }
+    } else {      /* non-header line */
+      if (boundary.len-boundary_start && *line.s == '-' && line.len > (boundary.len-boundary_start) &&
+        !str_diffn(line.s,boundary.s+boundary_start,boundary.len-boundary_start)) { /* matches a boundary */
+      if (line.len > boundary.len-boundary_start + 2 &&
+            line.s[boundary.len-boundary_start+0] == '-' &&
+            line.s[boundary.len-boundary_start+1] == '-') {
+        /* XXXX - pop the boundary here */
+        if (boundary_start) boundary.len = boundary_start - 1;
+        boundary_start = boundary.len;
+        while(boundary_start--) if (!boundary.s[boundary_start]) break;
+        boundary_start++;
+        linespastheader = 2;
+      } else {
+        linespastheader = 0;
+      }
+      } else if (linespastheader == 1) { /* first line -- match a signature? */
+      if (sigscheck(&line)) {
+        flagexecutable = 1;
+        qmail_fail(&qqt);
+      }
+      linespastheader = 2;
+      }
+    }
+    line.len = 0;
+  }
+
   if (bytestooverflow)
     if (!--bytestooverflow)
       qmail_fail(&qqt);
@@ -372,13 +906,20 @@
  
   if (!seenmail) { err_wantmail(); return; }
   if (!rcptto.len) { err_wantrcpt(); return; }
+  if (mailfrom.len == 1 && recipcount > 1) { err_badbounce(); return; }
   seenmail = 0;
   if (databytes) bytestooverflow = databytes + 1;
+  boundary.len = 0;
+  boundary_start = 0;
+  content.len = 0;
+  linespastheader = 0;
+  flagexecutable = 0;
+  linetype = ' ';
   if (qmail_open(&qqt) == -1) { err_qqt(); return; }
   qp = qmail_qp(&qqt);
   out("354 go ahead\r\n");
  
-  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
   blast(&hops);
   hops = (hops >= MAXHOPS);
   if (hops) qmail_fail(&qqt);
@@ -389,27 +930,449 @@
   if (!*qqx) { acceptmessage(qp); return; }
   if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
   if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+  if (flagexecutable) { out("552 We don't accept email with executable attachments or content. Please place these types of files into a zip or similar archive and resend the email. (#5.3.4)\r\n"); return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");
 }
 
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0};
+static stralloc user = {0};
+static stralloc pass = {0};
+static stralloc resp = {0};
+static stralloc slop = {0};
+char *hostname;
+char **childargs;
+substdio ssup;
+char upbuf[128];
+int authd = 0;
+
+int authgetl(void) {
+  int i;
+
+  if (!stralloc_copys(&authin, "")) die_nomem();
+
+  for (;;) {
+    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+    i = substdio_get(&ssin,authin.s + authin.len,1);
+    if (i != 1) die_read();
+    if (authin.s[authin.len] == '\n') break;
+    ++authin.len;
+  }
+
+  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+  authin.s[authin.len] = 0;
+
+  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+  if (authin.len == 0) { return err_input(); }
+  return authin.len;
+}
+
+int authenticate(void)
+{
+  int child;
+  int wstat;
+  int pi[2];
+
+  if (!stralloc_0(&user)) die_nomem();
+  if (!stralloc_0(&pass)) die_nomem();
+  if (!stralloc_0(&resp)) die_nomem();
+
+  if (fd_copy(2,1) == -1) return err_pipe();
+  close(3);
+  if (pipe(pi) == -1) return err_pipe();
+  if (pi[0] != 3) return err_pipe();
+  switch(child = fork()) {
+    case -1:
+      return err_fork();
+    case 0:
+      close(pi[1]);
+      sig_pipedefault();
+      execvp(*childargs, childargs);
+      _exit(1);
+  }
+  close(pi[0]);
+
+  substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
+  if (substdio_put(&ssup,user.s,user.len) == -1) return err_write();
+  if (substdio_put(&ssup,pass.s,pass.len) == -1) return err_write();
+  if (substdio_put(&ssup,resp.s,resp.len) == -1) return err_write();
+  if (substdio_flush(&ssup) == -1) return err_write();
+
+  close(pi[1]);
+  byte_zero(pass.s,pass.len);
+  byte_zero(upbuf,sizeof upbuf);
+  if (wait_pid(&wstat,child) == -1) return err_child();
+  if (wait_crashed(wstat)) return err_child();
+  if (wait_exitcode(wstat)) { sleep(5); return 1; } /* no */
+  return 0; /* yes */
+}
+
+int auth_login(arg) char *arg;
+{
+  int r;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+  }
+  else {
+    out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+  }
+  if (r == -1) die_nomem();
+
+  out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+  if (r == -1) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();  
+}
+
+int auth_plain(arg) char *arg;
+{
+  int r, id = 0;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&slop) == 1) return err_input();
+  }
+  else {
+    out("334 \r\n"); flush();
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  }
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+  while (slop.s[id]) id++; /* ignore authorize-id */
+
+  if (slop.len > id + 1)
+    if (!stralloc_copys(&user,slop.s + id + 1)) die_nomem();
+  if (slop.len > id + user.len + 2)
+    if (!stralloc_copys(&pass,slop.s + id + user.len + 2)) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+#ifdef AUTHCRAM
+int auth_cram()
+{
+  int i, r;
+  char *s;
+
+  s = unique;
+  s += fmt_uint(s,getpid());
+  *s++ = '.';
+  s += fmt_ulong(s,(unsigned long) now());
+  *s++ = '@';
+  *s++ = 0;
+
+  if (!stralloc_copys(&pass,"<")) die_nomem();
+  if (!stralloc_cats(&pass,unique)) die_nomem();
+  if (!stralloc_cats(&pass,hostname)) die_nomem();
+  if (!stralloc_cats(&pass,">")) die_nomem();
+  if (b64encode(&pass,&slop) < 0) die_nomem();
+  if (!stralloc_0(&slop)) die_nomem();
+
+  out("334 ");
+  out(slop.s);
+  out("\r\n");
+  flush();
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+
+  i = str_chr(slop.s,' ');
+  s = slop.s + i;
+  while (*s == ' ') ++s;
+  slop.s[i] = 0;
+  if (!stralloc_copys(&user,slop.s)) die_nomem();
+  if (!stralloc_copys(&resp,s)) die_nomem();
+
+  if (!user.len || !resp.len) return err_input();
+  return authenticate();
+}
+#endif
+
+struct authcmd {
+  char *text;
+  int (*fun)();
+} authcmds[] = {
+  { "login", auth_login }
+, { "plain", auth_plain }
+#ifdef AUTHCRAM
+, { "cram-md5", auth_cram }
+#endif
+, { 0, err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+  int i;
+  char *cmd = arg;
+
+  if (!hostname || !*childargs)
+  {
+    out("503 auth not available (#5.3.3)\r\n");
+    return;
+  }
+  if (authd) { err_authd(); return; }
+  if (seenmail) { err_authmail(); return; }
+
+  if (!stralloc_copys(&user,"")) die_nomem();
+  if (!stralloc_copys(&pass,"")) die_nomem();
+  if (!stralloc_copys(&resp,"")) die_nomem();
+
+  i = str_chr(cmd,' ');   
+  arg = cmd + i;
+  while (*arg == ' ') ++arg;
+  cmd[i] = 0;
+
+  for (i = 0;authcmds[i].text;++i)
+    if (case_equals(authcmds[i].text,cmd)) break;
+
+  switch (authcmds[i].fun(arg)) {
+    case 0:
+      authd = 1;
+      relayclient = "";
+      remoteinfo = user.s;
+      if (!env_unset("TCPREMOTEINFO")) die_read();
+      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+      out("235 ok, go ahead (#2.0.0)\r\n");
+      break;
+    case 1:
+      out("535 authorization failed (#5.7.0)\r\n");
+  }
+}
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+  if (ssl) err_unimpl();
+  else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+  else tls_init();
+}
+
+RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 512;
+  if (keylen == 512) {
+    BIO *in = BIO_new_file("control/rsa512.pem", "r");
+    if (in) {
+      RSA *rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, NULL);
+      BIO_free(in);
+      if (rsa) return rsa;
+    }
+  }
+  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+/* don't want to fail handshake if cert isn't verifiable */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+void tls_nogateway()
+{
+  /* there may be cases when relayclient is set */
+  if (!ssl || relayclient) return;
+  out("; no valid cert for gatewaying");
+  if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
+}
+void tls_out(const char *s1, const char *s2)
+{
+  out("454 TLS "); out(s1);
+  if (s2) { out(": "); out(s2); }
+  out(" (#4.3.0)\r\n"); flush();
+}
+void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
+
+# define CLIENTCA "control/clientca.pem"
+# define SERVERCERT "control/servercert.pem"
+
+int tls_verify()
+{
+  stralloc clients = {0};
+  struct constmap mapclients;
+
+  if (!ssl || relayclient || ssl_verified) return 0;
+  ssl_verified = 1; /* don't do this twice */
+
+  /* request client cert to see if it can be verified by one of our CAs
+   * and the associated email address matches an entry in tlsclients */
+  switch (control_readfile(&clients, "control/tlsclients", 0))
+  {
+  case 1:
+    if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
+      /* if CLIENTCA contains all the standart root certificates, a
+       * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
+       * it is probably due to 0.9.6b supporting only 8k key exchange
+       * data while the 0.9.6c release increases that limit to 100k */
+      STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
+      if (sk) {
+        SSL_set_client_CA_list(ssl, sk);
+        SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
+        break;
+      }
+      constmap_free(&mapclients);
+    }
+  case 0: alloc_free(clients.s); return 0;
+  case -1: die_control();
+  }
+
+  if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
+    const char *err = ssl_strerror();
+    tls_out("rehandshake failed", err); die_read();
+  }
+
+  do { /* one iteration */
+    X509 *peercert;
+    X509_NAME *subj;
+    stralloc email = {0};
+
+    int n = SSL_get_verify_result(ssl);
+    if (n != X509_V_OK)
+      { ssl_verify_err = X509_verify_cert_error_string(n); break; }
+    peercert = SSL_get_peer_certificate(ssl);
+    if (!peercert) break;
+
+    subj = X509_get_subject_name(peercert);
+    n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
+    if (n >= 0) {
+      const ASN1_STRING *s = X509_NAME_get_entry(subj, n)->value;
+      if (s) { email.len = s->length; email.s = s->data; }
+    }
+
+    if (email.len <= 0)
+      ssl_verify_err = "contains no email address";
+    else if (!constmap(&mapclients, email.s, email.len))
+      ssl_verify_err = "email address not in my list of tlsclients";
+    else {
+      /* add the cert email to the proto if it helped allow relaying */
+      --proto.len;
+      if (!stralloc_cats(&proto, "\n  cert ") /* continuation line */
+        || !stralloc_catb(&proto, email.s, email.len)
+        || !stralloc_0(&proto)) die_nomem();
+      relayclient = "";
+      protocol = proto.s;
+    }
+
+    X509_free(peercert);
+  } while (0);
+  constmap_free(&mapclients); alloc_free(clients.s);
+
+  /* we are not going to need this anymore: free the memory */
+  SSL_set_client_CA_list(ssl, NULL);
+  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
+
+  return relayclient ? 1 : 0;
+}
+
+void tls_init()
+{
+  SSL *myssl;
+  SSL_CTX *ctx;
+  const char *ciphers;
+  stralloc saciphers = {0};
+
+  SSL_library_init();
+
+  /* a new SSL context with the bare minimum of options */
+  ctx = SSL_CTX_new(SSLv23_server_method());
+  if (!ctx) { tls_err("unable to initialize ctx"); return; }
+
+  if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
+    { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
+  SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
+  /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
+
+  /* a new SSL object, with the rest added to it directly to avoid copying */
+  myssl = SSL_new(ctx);
+  SSL_CTX_free(ctx);
+  if (!myssl) { tls_err("unable to initialize ssl"); return; }
+
+  /* this will also check whether publc and private keys match */
+  if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
+    { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
+
+  ciphers = env_get("TLSCIPHERS");
+  if (!ciphers) {
+    if (control_readfile(&saciphers, "control/tlsserverciphers") == -1)
+      { SSL_free(myssl); die_control(); }
+    if (saciphers.len) { /* convert all '\0's except the last one to ':' */
+      int i;
+      for (i = 0; i < saciphers.len - 1; ++i)
+        if (!saciphers.s[i]) saciphers.s[i] = ':';
+      ciphers = saciphers.s;
+    }
+  }
+  if (!ciphers || !*ciphers) ciphers = "DEFAULT";
+  SSL_set_cipher_list(myssl, ciphers);
+  alloc_free(saciphers.s);
+
+  SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
+  SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
+  SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
+
+  if (!smtps) { out("220 ready for tls\r\n"); flush(); }
+
+  if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
+    /* neither cleartext nor any other response here is part of a standard */
+    const char *err = ssl_strerror();
+    ssl_free(myssl); tls_out("connection failed", err); die_read();
+  }
+  ssl = myssl;
+
+  /* populate the protocol string, used in Received */
+  if (!stralloc_copys(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted SMTP")) die_nomem();
+  if (smtps) if (!stralloc_append(&proto, "S")) die_nomem();
+  if (!stralloc_0(&proto)) die_nomem();
+  protocol = proto.s;
+
+  /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
+  dohelo(remotehost);
+}
+
+# undef SERVERCERT
+# undef CLIENTCA
+
+#endif
+
 struct commands smtpcommands[] = {
   { "rcpt", smtp_rcpt, 0 }
 , { "mail", smtp_mail, 0 }
 , { "data", smtp_data, flush }
+, { "auth", smtp_auth, flush }
 , { "quit", smtp_quit, flush }
 , { "helo", smtp_helo, flush }
 , { "ehlo", smtp_ehlo, flush }
 , { "rset", smtp_rset, 0 }
 , { "help", smtp_help, flush }
+#ifdef TLS
+, { "starttls", smtp_tls, flush }
+#endif
 , { "noop", err_noop, flush }
 , { "vrfy", err_vrfy, flush }
 , { 0, err_unimpl, flush }
 } ;
 
-void main()
+void main(argc,argv)
+int argc;
+char **argv;
 {
+  hostname = argv[1];
+  childargs = argv + 2;
+
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
diff -urN qmail-1.03-orig/qmail-smtpd.c.orig qmail-1.03/qmail-smtpd.c.orig
--- qmail-1.03-orig/qmail-smtpd.c.orig	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/qmail-smtpd.c.orig	2003-10-07 17:24:11.000000000 -0400
@@ -0,0 +1,1241 @@
+
+/*
+ * 
+ * Patch 'qmail-smtpd-chkusr' v.1.0
+ * for qmail 1.03 and vpopmail 5.3.3
+ * 
+ * Antonio Nati tonix@interazioni.it
+ * 
+ */
+
+#include "sig.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "control.h"
+#include "received.h"
+#include "constmap.h"
+#include "error.h"
+#include "ipme.h"
+#include "ip.h"
+#include "qmail.h"
+#include "str.h"
+#include "fmt.h"
+#include "scan.h"
+#include "byte.h"
+#include "case.h"
+#include "env.h"
+#include "now.h"
+#include "exit.h"
+#include "rcpthosts.h"
+#include "timeoutread.h"
+#include "timeoutwrite.h"
+#include "commands.h"
+#include "strerr.h"
+#include "wait.h"
+#include "fd.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <stdio.h>
+#include "vpopmail.h"
+#include "vauth.h"
+#include "vpopmail_config.h"
+#include "dns.h"
+
+#define AUTHCRAM
+#define MAXHOPS 100
+unsigned int databytes = 0;
+unsigned int mfchk = 0;
+int timeout = 1200;
+
+const char *protocol = "SMTP";
+
+#ifdef TLS
+# include "tls.h"
+# include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
+#endif
+
+int safewrite(fd,buf,len) int fd; char *buf; int len;
+{
+  int r;
+#ifdef TLS
+  if (ssl && fd == ssl_wfd)
+    r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
+  r = timeoutwrite(timeout,fd,buf,len);
+  if (r <= 0) _exit(1);
+  return r;
+}
+
+char ssoutbuf[512];
+substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
+
+void flush() { substdio_flush(&ssout); }
+void out(s) char *s; { substdio_puts(&ssout,s); }
+
+void die_read() { _exit(1); }
+void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); }
+void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); }
+void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); }
+void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
+void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
+
+void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_hmf() { out("553 sorry, your envelope sender domain must exist (#5.7.  1)\r\n"); }
+void err_smf() { out("451 DNS temporary failure (#4.3.0)\r\n"); }
+void err_brt() { out("553 sorry, this recipient is in my badrecipientto list (#5.7.1)\r\n"); }
+#ifndef TLS
+void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
+#else
+void err_nogateway()
+{
+  out("553 sorry, that domain isn't in my list of allowed rcpthosts");
+  tls_nogateway();
+  out(" (#5.7.1)\r\n");
+}
+#endif
+void err_badbounce() { out("550 sorry, bounce messages should have a single envelope recipient (#5.7.1)\r\n"); }
+void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
+void err_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
+void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
+void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
+void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); }
+void err_noop() { out("250 ok\r\n"); }
+void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
+void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
+
+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+int err_authabrt() { out("501 auth exchange cancelled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
+
+stralloc greeting = {0};
+
+void smtp_greet(code) char *code;
+{
+  substdio_puts(&ssout,code);
+  substdio_put(&ssout,greeting.s,greeting.len);
+}
+void smtp_help()
+{
+  out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+}
+void smtp_quit()
+{
+  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
+}
+
+char *remoteip;
+char *remotehost;
+char *remoteinfo;
+char *local;
+char *relayclient;
+
+stralloc helohost = {0};
+char *fakehelo; /* pointer into helohost, or 0 */
+
+void dohelo(arg) char *arg; {
+  if (!stralloc_copys(&helohost,arg)) die_nomem(); 
+  if (!stralloc_0(&helohost)) die_nomem(); 
+  fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0;
+}
+
+int liphostok = 0;
+stralloc liphost = {0};
+int bmfok = 0;
+stralloc bmf = {0};
+struct constmap mapbmf;
+int brtok = 0;
+stralloc brt = {0};
+struct constmap mapbrt;
+
+void setup()
+{
+  char *x;
+  unsigned long u;
+ 
+  if (control_init() == -1) die_control();
+  if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1)
+    die_control();
+  liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0);
+  if (liphostok == -1) die_control();
+  if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
+  if (timeout <= 0) timeout = 1;
+
+  if (rcpthosts_init() == -1) die_control();
+
+  if (control_readint(&mfchk,"control/mfcheck") == -1) die_control();
+  x = env_get("MFCHECK");
+  if (x) { scan_ulong(x,&u); mfchk = u; }
+
+  bmfok = control_readfile(&bmf,"control/badmailfrom",0);
+  if (bmfok == -1) die_control();
+  if (bmfok)
+    if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
+
+  brtok = control_readfile(&brt,"control/badrcptto",0);
+  if (brtok == -1) die_control();
+  if (brtok)
+    if (!constmap_init(&mapbrt,brt.s,brt.len,0)) die_nomem();
+ 
+  if (control_readint(&databytes,"control/databytes") == -1) die_control();
+  x = env_get("DATABYTES");
+  if (x) { scan_ulong(x,&u); databytes = u; }
+  if (!(databytes + 1)) --databytes;
+ 
+  remoteip = env_get("TCPREMOTEIP");
+  if (!remoteip) remoteip = "unknown";
+  local = env_get("TCPLOCALHOST");
+  if (!local) local = env_get("TCPLOCALIP");
+  if (!local) local = "unknown";
+  remotehost = env_get("TCPREMOTEHOST");
+  if (!remotehost) remotehost = "unknown";
+  remoteinfo = env_get("TCPREMOTEINFO");
+  relayclient = env_get("RELAYCLIENT");
+  if (env_get("EXECUTABLEOK")) checkexecutable = 0;
+
+#ifdef TLS
+  if (env_get("SMTPS")) { smtps = 1; tls_init(); }
+  else
+#endif
+  dohelo(remotehost);
+}
+
+
+stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */
+
+int addrparse(arg)
+char *arg;
+{
+  int i;
+  char ch;
+  char terminator;
+  struct ip_address ip;
+  int flagesc;
+  int flagquoted;
+ 
+  terminator = '>';
+  i = str_chr(arg,'<');
+  if (arg[i])
+    arg += i + 1;
+  else { /* partner should go read rfc 821 */
+    terminator = ' ';
+    arg += str_chr(arg,':');
+    if (*arg == ':') ++arg;
+    while (*arg == ' ') ++arg;
+  }
+
+  /* strip source route */
+  if (*arg == '@') while (*arg) if (*arg++ == ':') break;
+
+  if (!stralloc_copys(&addr,"")) die_nomem();
+  flagesc = 0;
+  flagquoted = 0;
+  for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */
+    if (flagesc) {
+      if (!stralloc_append(&addr,&ch)) die_nomem();
+      flagesc = 0;
+    }
+    else {
+      if (!flagquoted && (ch == terminator)) break;
+      switch(ch) {
+        case '\\': flagesc = 1; break;
+        case '"': flagquoted = !flagquoted; break;
+        default: if (!stralloc_append(&addr,&ch)) die_nomem();
+      }
+    }
+  }
+  /* could check for termination failure here, but why bother? */
+  if (!stralloc_append(&addr,"")) die_nomem();
+
+  if (liphostok) {
+    i = byte_rchr(addr.s,addr.len,'@');
+    if (i < addr.len) /* if not, partner should go read rfc 821 */
+      if (addr.s[i + 1] == '[')
+        if (!addr.s[i + 1 + ip_scanbracket(addr.s + i + 1,&ip)])
+          if (ipme_is(&ip)) {
+            addr.len = i + 1;
+            if (!stralloc_cat(&addr,&liphost)) die_nomem();
+            if (!stralloc_0(&addr)) die_nomem();
+          }
+  }
+
+  if (addr.len > 900) return 0;
+  return 1;
+}
+
+int sizelimit(arg)
+char *arg;
+{
+  int i;
+  long r;
+  unsigned long sizebytes = 0;
+
+  i = str_chr(arg,'<');
+  if (arg[i])
+    arg += i + 1;
+  else {
+    arg += str_chr(arg,':');
+    if (*arg == ':') ++arg;
+    while (*arg == ' ') ++arg;
+  }
+
+  arg += str_chr(arg,' ');
+  if (*arg == ' ') while (*arg == ' ') ++arg;
+  else return 1;
+
+  i = str_chr(arg,'=');
+  arg[i] = 0;
+  if (case_equals(arg,"SIZE")) {
+    arg += i;
+    while (*++arg && *arg > 47 && *arg < 58) {
+      sizebytes *= 10;
+      sizebytes += *arg - 48;
+    }
+    r = databytes - sizebytes;
+    if (r < 0) return 0;
+  }
+  return 1;
+}
+
+int bmfcheck()
+{
+  int j;
+  if (!bmfok) return 0;
+  if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1;
+  return 0;
+}
+
+int brtcheck()
+{
+  int j;
+  if (!brtok) return 0;
+  if (constmap(&mapbrt,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbrt,addr.s + j,addr.len - j - 1)) return 1;
+  return 0;
+}
+void err_realrcpt() { out("550 sorry, no mailbox here by that name (#5.1.1 - chkusr)\r\n"); }
+
+int realrcpt_check()
+{
+  stralloc user = {0};
+  stralloc domain = {0};
+  stralloc domain_path = {0};
+  stralloc bounce_path = {0};
+  stralloc alias_name = {0};
+  stralloc alias_path = {0};
+  stralloc mailing_path = {0};
+  int count;
+  int retstat = 0;
+  struct vqpasswd *user_passwd = NULL;
+  int fd_file = -1;
+  int read_char;
+  DIR *dir_file = NULL;
+  uid_t eff_uid;
+  gid_t eff_gid;
+  int offset;
+  char read_buf[1024];
+
+/* if not local rcpthost we cannot control mailbox */
+/* this line should only be uncommented if addrallowed is not
+ * called elsewhere - otherwise qmail-smtp will fail if
+ * morercpthosts.cdb exists.
+*/
+/*
+ if (!addrallowed()) { return 1; }
+*/
+
+/* Set up our variables */
+
+/* qmail-smtpd is running now as (effective) qmaild:qnofiles */
+/* Save the effective UID & GID (qmaild:qnofiles) */
+  eff_uid = geteuid ();
+  eff_gid = getegid ();
+
+/* Search the '@' character */
+  count = byte_rchr(addr.s,addr.len,'@');
+
+/* The following lines could interest people using # instead of @ in e-mail address */
+/* If '@' not found search the '%' character */
+/*
+  if (count >= addr.len) {
+    count = byte_rchr(addr.s,addr.len,'%');
+  }
+*/
+
+/*
+ * Give extra room to variables used often or used outside stralloc_x calls
+ * This should make all safer and even faster
+ * (when these fields are used by stralloc_x routines)
+*/
+  if (!stralloc_ready (&domain, 200)) die_nomem();
+  if (!stralloc_ready (&domain_path, 200)) die_nomem();
+
+  if (count < addr.len) {
+    if (!stralloc_copyb (&user, addr.s, count)) die_nomem();
+    if (!stralloc_0 (&user)) die_nomem();
+    if (!stralloc_copys (&domain, addr.s + count + 1)) die_nomem();
+    if (!stralloc_0 (&domain)) die_nomem();
+  }
+  else {
+    if (!stralloc_copys (&user, addr.s)) die_nomem();
+    if (!stralloc_0 (&user)) die_nomem();
+    if (!stralloc_copys (&domain, DEFAULT_DOMAIN)) die_nomem();
+    if (!stralloc_0 (&domain)) die_nomem();
+  }
+
+/* My personal control: continue only if a domain (default or not) is specified */
+
+  if (domain.len == 1)
+    return 0;
+
+/* Now set new effective UID & GID, getting it from real UID & GID (vpopmail:vchkpw) */
+
+  setegid (getgid());
+  seteuid (getuid());
+
+/* qmail-smtpd is running now as effective vpopmail:vchkpw */
+
+  case_lowers (user.s);
+  case_lowers (domain.s);
+
+/* Check if domain is a real domain */
+
+  if (!stralloc_0 (&domain)) die_nomem();
+  vget_real_domain(domain.s, domain.a);
+
+  domain.len = strlen (domain.s);
+  if (domain.len > (domain.a - 1)) die_nomem();
+
+/* Let's get domain's real path */
+  vget_assign(domain.s, domain_path.s, 156, NULL, NULL);
+
+  domain_path.len = strlen (domain_path.s);
+
+/* Now Let's start the test suite */
+
+	switch (0) {
+
+	case 0:
+/* Check if domain has bouncing enabled */
+
+		/* Allocate room for bounce_path */
+  		if (!stralloc_ready (&bounce_path, 200)) die_nomem();
+		if (!stralloc_copy (&bounce_path, &domain_path)) die_nomem();
+  		if (!stralloc_cats (&bounce_path, "/.qmail-default")) die_nomem();
+		if (!stralloc_0 (&bounce_path)) die_nomem();
+
+  		read_char = 0;
+  		fd_file = open_read (bounce_path.s);	
+  		if (fd_file != -1) {
+      			read_char = read (fd_file, read_buf, sizeof(read_buf) - 1);
+      			close (fd_file);
+      			if (read_char < 0) read_char = 0;
+  			}
+  		read_buf[read_char] = 0;
+
+  		if ( strstr(read_buf, "bounce-no-mailbox") == NULL ) {
+			retstat = 1;
+			break;
+  		}
+  
+	case 1:
+/* User control: check the existance of a real user */
+
+	  	user_passwd = vauth_getpw (user.s, domain.s);
+	  	if (user_passwd != NULL) {
+
+		/* If user exists check if he has BOUNCE_MAIL flag set */
+
+			if (user_passwd->pw_gid & BOUNCE_MAIL)
+		    		retstat = 0;
+	    		else
+		    		retstat = 1;
+			break;
+	  	}
+
+	case 2:
+/* Check for aliases/forwards - valias*/
+
+		if (valias_select (user.s, domain.s) != NULL) {
+			retstat = 1;
+			break;
+		}
+
+	case 3:
+/* Check for aliases/forwards - .qmail-x files */
+
+		/* Allocate room for alias_path */
+  		if (!stralloc_ready (&alias_path, 200)) die_nomem();
+	    	if (!stralloc_copy (&alias_name, &user)) die_nomem();
+
+		/* Change all '.' in ':' before continuing on aliases */
+	    	for (count = 0; count < alias_name.len; ++count)
+	      	if (*(alias_name.s + count) == '.') *(alias_name.s + count) = ':';
+
+	    	if (!stralloc_copy (&alias_path, &domain_path)) die_nomem();
+	    	if (!stralloc_cats (&alias_path, "/.qmail-")) die_nomem();
+	    	if (!stralloc_cats (&alias_path, alias_name.s)) die_nomem();
+	    	if (!stralloc_0 (&alias_path)) die_nomem();
+
+		/* access executes anyway as real (vpopmail:vchkpw), that's ok */
+	    	if (access (alias_path.s, F_OK) == 0) {
+	      		retstat = 1;
+			break;
+	    	}
+
+	case 4:
+/* Let's check for mailing lists */
+
+		/* Allocate room for mailing_path */
+  		if (!stralloc_ready (&mailing_path, 300)) die_nomem();
+
+		/* Search for the outer '-' character */
+	      	for (offset = user.len - 1; offset > 0; --offset)
+			if (*(user.s + offset) == '-')  {
+				if (!stralloc_copy (&mailing_path, &domain_path)) die_nomem();
+	      			if (!stralloc_cats (&mailing_path, "/")) die_nomem();
+	      			if (!stralloc_catb (&mailing_path, user.s, offset)) die_nomem();
+	      			if (!stralloc_cats (&mailing_path, "/mailinglist")) die_nomem();
+	      			if (!stralloc_0 (&mailing_path)) die_nomem();
+				/* access executes anyway as real (vpopmail:vchkpw), that's ok */
+			    	if (access (mailing_path.s, F_OK) == 0) {
+                			retstat = 1;
+                			break;
+	            		}
+	        	}
+
+/*
+ * Add this code if another case is following
+		if (retstat == 1)
+			break;
+*/
+	    
+	} /* end switch */
+
+/* Now switch back effective to saved UID & GID (qmaild:qnofiles) */
+
+  setegid (eff_gid);
+  seteuid (eff_uid);
+
+/* qmail-smtpd is running again as (effective) qmaild:qnofiles */
+
+  return retstat;
+}
+
+
+int mfcheck()
+{
+  stralloc sa = {0};
+  ipalloc ia = {0};
+  unsigned int random;
+  int j;
+
+  if (!mfchk) return 0;
+  random = now() + (getpid() << 16);
+  j = byte_rchr(addr.s,addr.len,'@') + 1;
+  if (j < addr.len) {
+    stralloc_copys(&sa, addr.s + j);
+    dns_init(0);
+    j = dns_mxip(&ia,&sa,random);
+    if (j < 0) return j;
+  }
+  return 0;
+}
+
+int addrallowed()
+{
+  int r;
+  r = rcpthosts(addr.s,str_len(addr.s));
+  if (r == -1) die_control();
+#ifdef TLS
+  if (r == 0) if (tls_verify()) r = -2;
+#endif
+  return r;
+}
+
+
+int seenmail = 0;
+int flagbarf; /* defined if seenmail */
+stralloc mailfrom = {0};
+stralloc rcptto = {0};
+int recipcount;
+
+void smtp_helo(arg) char *arg;
+{
+  smtp_greet("250 "); out("\r\n");
+  seenmail = 0; dohelo(arg);
+}
+/* ESMTP extensions are published here */
+void smtp_ehlo(arg) char *arg;
+{
+  smtp_greet("250-");
+#ifdef TLS
+  if (!ssl) out("\r\n250-STARTTLS");
+#endif
+#ifdef AUTHCRAM
+  out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+  out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+#else
+  out("\r\n250-AUTH LOGIN PLAIN");
+  out("\r\n250-AUTH=LOGIN PLAIN");
+#endif
+  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  seenmail = 0; dohelo(arg);
+}
+char size_buf[FMT_ULONG];
+void smtp_size()
+{
+  size_buf[fmt_ulong(size_buf,(unsigned long) databytes)] = 0;
+  out("250 SIZE "); out(size_buf); out("\r\n");
+}
+void smtp_rset()
+{
+  seenmail = 0;
+  out("250 flushed\r\n");
+}
+void smtp_mail(arg) char *arg;
+{
+  if (!addrparse(arg)) { err_syntax(); return; }
+  if (databytes && !sizelimit(arg)) { err_size(); return; }
+  flagbarf = bmfcheck();
+  switch(mfcheck()) {
+    case DNS_HARD: err_hmf(); return;
+    case DNS_SOFT: err_smf(); return;
+    case DNS_MEM: die_nomem();
+  }
+  seenmail = 1;
+  if (!stralloc_copys(&rcptto,"")) die_nomem();
+  if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
+  if (!stralloc_0(&mailfrom)) die_nomem();
+  recipcount = 0;
+  out("250 ok\r\n");
+}
+void smtp_rcpt(arg) char *arg; {
+  if (!seenmail) { err_wantmail(); return; }
+  if (!addrparse(arg)) { err_syntax(); return; }
+  if (flagbarf) {
+    strerr_warn4("qmail-smtpd: badmailfrom: ",mailfrom.s," at ",remoteip,0);
+    err_bmf();
+    return;
+  }
+  if (relayclient) {
+    --addr.len;
+    if (!stralloc_cats(&addr,relayclient)) die_nomem();
+    if (!stralloc_0(&addr)) die_nomem();
+  }
+  else
+    if (!addrallowed()) { err_nogateway(); return; }
+  if (!env_get("RELAYCLIENT") && brtcheck()) { err_brt(); return; }
+  if (!realrcpt_check()) { err_realrcpt(); return; }
+  if (!stralloc_cats(&rcptto,"T")) die_nomem();
+  if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
+  if (!stralloc_0(&rcptto)) die_nomem();
+  recipcount++;
+  out("250 ok\r\n");
+}
+
+
+int saferead(fd,buf,len) int fd; char *buf; int len;
+{
+  int r;
+  flush();
+#ifdef TLS
+  if (ssl && fd == ssl_rfd)
+    r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
+  r = timeoutread(timeout,fd,buf,len);
+  if (r == -1) if (errno == error_timeout) die_alarm();
+  if (r <= 0) die_read();
+  return r;
+}
+
+char ssinbuf[1024];
+substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
+
+struct qmail qqt;
+unsigned int bytestooverflow = 0;
+
+void put(ch)
+char *ch;
+{
+  char *cp, *cpstart, *cpafter;
+  unsigned int len;
+
+  if (bytestooverflow)
+    if (!--bytestooverflow)
+      qmail_fail(&qqt);
+  qmail_put(&qqt,ch,1);
+}
+
+void blast(hops)
+int *hops;
+{
+  char ch;
+  int state;
+  int flaginheader;
+  int pos; /* number of bytes since most recent \n, if fih */
+  int flagmaybex; /* 1 if this line might match RECEIVED, if fih */
+  int flagmaybey; /* 1 if this line might match \r\n, if fih */
+  int flagmaybez; /* 1 if this line might match DELIVERED, if fih */
+ 
+  state = 1;
+  *hops = 0;
+  flaginheader = 1;
+  pos = 0; flagmaybex = flagmaybey = flagmaybez = 1;
+  for (;;) {
+    substdio_get(&ssin,&ch,1);
+    if (flaginheader) {
+      if (pos < 9) {
+        if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0;
+        if (flagmaybez) if (pos == 8) ++*hops;
+        if (pos < 8)
+          if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0;
+        if (flagmaybex) if (pos == 7) ++*hops;
+        if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
+        if (flagmaybey) if (pos == 1) flaginheader = 0;
+      }
+      ++pos;
+      if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
+    }
+    switch(state) {
+      case 0:
+        if (ch == '\n') straynewline();
+        if (ch == '\r') { state = 4; continue; }
+        break;
+      case 1: /* \r\n */
+        if (ch == '\n') straynewline();
+        if (ch == '.') { state = 2; continue; }
+        if (ch == '\r') { state = 4; continue; }
+        state = 0;
+        break;
+      case 2: /* \r\n + . */
+        if (ch == '\n') straynewline();
+        if (ch == '\r') { state = 3; continue; }
+        state = 0;
+        break;
+      case 3: /* \r\n + .\r */
+        if (ch == '\n') return;
+        put(".");
+        put("\r");
+        if (ch == '\r') { state = 4; continue; }
+        state = 0;
+        break;
+      case 4: /* + \r */
+        if (ch == '\n') { state = 1; break; }
+        if (ch != '\r') { put("\r"); state = 0; }
+    }
+    put(&ch);
+  }
+}
+
+char accept_buf[FMT_ULONG];
+void acceptmessage(qp) unsigned long qp;
+{
+  datetime_sec when;
+  when = now();
+  out("250 ok ");
+  accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0;
+  out(accept_buf);
+  out(" qp ");
+  accept_buf[fmt_ulong(accept_buf,qp)] = 0;
+  out(accept_buf);
+  out("\r\n");
+}
+
+void smtp_data() {
+  int hops;
+  unsigned long qp;
+  char *qqx;
+ 
+  if (!seenmail) { err_wantmail(); return; }
+  if (!rcptto.len) { err_wantrcpt(); return; }
+  if (mailfrom.len == 1 && recipcount > 1) { err_badbounce(); return; }
+  seenmail = 0;
+  if (databytes) bytestooverflow = databytes + 1;
+  if (qmail_open(&qqt) == -1) { err_qqt(); return; }
+  qp = qmail_qp(&qqt);
+  out("354 go ahead\r\n");
+ 
+  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
+  blast(&hops);
+  hops = (hops >= MAXHOPS);
+  if (hops) qmail_fail(&qqt);
+  qmail_from(&qqt,mailfrom.s);
+  qmail_put(&qqt,rcptto.s,rcptto.len);
+ 
+  qqx = qmail_close(&qqt);
+  if (!*qqx) { acceptmessage(qp); return; }
+  if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
+  if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+  if (*qqx == 'D') out("554 "); else out("451 ");
+  out(qqx + 1);
+  out("\r\n");
+}
+
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0};
+static stralloc user = {0};
+static stralloc pass = {0};
+static stralloc resp = {0};
+static stralloc slop = {0};
+char *hostname;
+char **childargs;
+substdio ssup;
+char upbuf[128];
+int authd = 0;
+
+int authgetl(void) {
+  int i;
+
+  if (!stralloc_copys(&authin, "")) die_nomem();
+
+  for (;;) {
+    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+    i = substdio_get(&ssin,authin.s + authin.len,1);
+    if (i != 1) die_read();
+    if (authin.s[authin.len] == '\n') break;
+    ++authin.len;
+  }
+
+  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+  authin.s[authin.len] = 0;
+
+  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+  if (authin.len == 0) { return err_input(); }
+  return authin.len;
+}
+
+int authenticate(void)
+{
+  int child;
+  int wstat;
+  int pi[2];
+
+  if (!stralloc_0(&user)) die_nomem();
+  if (!stralloc_0(&pass)) die_nomem();
+  if (!stralloc_0(&resp)) die_nomem();
+
+  if (fd_copy(2,1) == -1) return err_pipe();
+  close(3);
+  if (pipe(pi) == -1) return err_pipe();
+  if (pi[0] != 3) return err_pipe();
+  switch(child = fork()) {
+    case -1:
+      return err_fork();
+    case 0:
+      close(pi[1]);
+      sig_pipedefault();
+      execvp(*childargs, childargs);
+      _exit(1);
+  }
+  close(pi[0]);
+
+  substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
+  if (substdio_put(&ssup,user.s,user.len) == -1) return err_write();
+  if (substdio_put(&ssup,pass.s,pass.len) == -1) return err_write();
+  if (substdio_put(&ssup,resp.s,resp.len) == -1) return err_write();
+  if (substdio_flush(&ssup) == -1) return err_write();
+
+  close(pi[1]);
+  byte_zero(pass.s,pass.len);
+  byte_zero(upbuf,sizeof upbuf);
+  if (wait_pid(&wstat,child) == -1) return err_child();
+  if (wait_crashed(wstat)) return err_child();
+  if (wait_exitcode(wstat)) { sleep(5); return 1; } /* no */
+  return 0; /* yes */
+}
+
+int auth_login(arg) char *arg;
+{
+  int r;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+  }
+  else {
+    out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+  }
+  if (r == -1) die_nomem();
+
+  out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+  if (r == -1) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();  
+}
+
+int auth_plain(arg) char *arg;
+{
+  int r, id = 0;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&slop) == 1) return err_input();
+  }
+  else {
+    out("334 \r\n"); flush();
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  }
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+  while (slop.s[id]) id++; /* ignore authorize-id */
+
+  if (slop.len > id + 1)
+    if (!stralloc_copys(&user,slop.s + id + 1)) die_nomem();
+  if (slop.len > id + user.len + 2)
+    if (!stralloc_copys(&pass,slop.s + id + user.len + 2)) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+#ifdef AUTHCRAM
+int auth_cram()
+{
+  int i, r;
+  char *s;
+
+  s = unique;
+  s += fmt_uint(s,getpid());
+  *s++ = '.';
+  s += fmt_ulong(s,(unsigned long) now());
+  *s++ = '@';
+  *s++ = 0;
+
+  if (!stralloc_copys(&pass,"<")) die_nomem();
+  if (!stralloc_cats(&pass,unique)) die_nomem();
+  if (!stralloc_cats(&pass,hostname)) die_nomem();
+  if (!stralloc_cats(&pass,">")) die_nomem();
+  if (b64encode(&pass,&slop) < 0) die_nomem();
+  if (!stralloc_0(&slop)) die_nomem();
+
+  out("334 ");
+  out(slop.s);
+  out("\r\n");
+  flush();
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+
+  i = str_chr(slop.s,' ');
+  s = slop.s + i;
+  while (*s == ' ') ++s;
+  slop.s[i] = 0;
+  if (!stralloc_copys(&user,slop.s)) die_nomem();
+  if (!stralloc_copys(&resp,s)) die_nomem();
+
+  if (!user.len || !resp.len) return err_input();
+  return authenticate();
+}
+#endif
+
+struct authcmd {
+  char *text;
+  int (*fun)();
+} authcmds[] = {
+  { "login", auth_login }
+, { "plain", auth_plain }
+#ifdef AUTHCRAM
+, { "cram-md5", auth_cram }
+#endif
+, { 0, err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+  int i;
+  char *cmd = arg;
+
+  if (!hostname || !*childargs)
+  {
+    out("503 auth not available (#5.3.3)\r\n");
+    return;
+  }
+  if (authd) { err_authd(); return; }
+  if (seenmail) { err_authmail(); return; }
+
+  if (!stralloc_copys(&user,"")) die_nomem();
+  if (!stralloc_copys(&pass,"")) die_nomem();
+  if (!stralloc_copys(&resp,"")) die_nomem();
+
+  i = str_chr(cmd,' ');   
+  arg = cmd + i;
+  while (*arg == ' ') ++arg;
+  cmd[i] = 0;
+
+  for (i = 0;authcmds[i].text;++i)
+    if (case_equals(authcmds[i].text,cmd)) break;
+
+  switch (authcmds[i].fun(arg)) {
+    case 0:
+      authd = 1;
+      relayclient = "";
+      remoteinfo = user.s;
+      if (!env_unset("TCPREMOTEINFO")) die_read();
+      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+      out("235 ok, go ahead (#2.0.0)\r\n");
+      break;
+    case 1:
+      out("535 authorization failed (#5.7.0)\r\n");
+  }
+}
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+  if (ssl) err_unimpl();
+  else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+  else tls_init();
+}
+
+RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 512;
+  if (keylen == 512) {
+    BIO *in = BIO_new_file("control/rsa512.pem", "r");
+    if (in) {
+      RSA *rsa = PEM_read_bio_RSAPrivateKey(in, NULL, NULL, NULL);
+      BIO_free(in);
+      if (rsa) return rsa;
+    }
+  }
+  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+/* don't want to fail handshake if cert isn't verifiable */
+int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) { return 1; }
+
+void tls_nogateway()
+{
+  /* there may be cases when relayclient is set */
+  if (!ssl || relayclient) return;
+  out("; no valid cert for gatewaying");
+  if (ssl_verify_err) { out(": "); out(ssl_verify_err); }
+}
+void tls_out(const char *s1, const char *s2)
+{
+  out("454 TLS "); out(s1);
+  if (s2) { out(": "); out(s2); }
+  out(" (#4.3.0)\r\n"); flush();
+}
+void tls_err(const char *s) { tls_out(s, ssl_error()); if (smtps) die_read(); }
+
+# define CLIENTCA "control/clientca.pem"
+# define SERVERCERT "control/servercert.pem"
+
+int tls_verify()
+{
+  stralloc clients = {0};
+  struct constmap mapclients;
+
+  if (!ssl || relayclient || ssl_verified) return 0;
+  ssl_verified = 1; /* don't do this twice */
+
+  /* request client cert to see if it can be verified by one of our CAs
+   * and the associated email address matches an entry in tlsclients */
+  switch (control_readfile(&clients, "control/tlsclients", 0))
+  {
+  case 1:
+    if (constmap_init(&mapclients, clients.s, clients.len, 0)) {
+      /* if CLIENTCA contains all the standart root certificates, a
+       * 0.9.6b client might fail with SSL_R_EXCESSIVE_MESSAGE_SIZE;
+       * it is probably due to 0.9.6b supporting only 8k key exchange
+       * data while the 0.9.6c release increases that limit to 100k */
+      STACK_OF(X509_NAME) *sk = SSL_load_client_CA_file(CLIENTCA);
+      if (sk) {
+        SSL_set_client_CA_list(ssl, sk);
+        SSL_set_verify(ssl, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
+        break;
+      }
+      constmap_free(&mapclients);
+    }
+  case 0: alloc_free(clients.s); return 0;
+  case -1: die_control();
+  }
+
+  if (ssl_timeoutrehandshake(timeout, ssl_rfd, ssl_wfd, ssl) <= 0) {
+    const char *err = ssl_strerror();
+    tls_out("rehandshake failed", err); die_read();
+  }
+
+  do { /* one iteration */
+    X509 *peercert;
+    X509_NAME *subj;
+    stralloc email = {0};
+
+    int n = SSL_get_verify_result(ssl);
+    if (n != X509_V_OK)
+      { ssl_verify_err = X509_verify_cert_error_string(n); break; }
+    peercert = SSL_get_peer_certificate(ssl);
+    if (!peercert) break;
+
+    subj = X509_get_subject_name(peercert);
+    n = X509_NAME_get_index_by_NID(subj, NID_pkcs9_emailAddress, -1);
+    if (n >= 0) {
+      const ASN1_STRING *s = X509_NAME_get_entry(subj, n)->value;
+      if (s) { email.len = s->length; email.s = s->data; }
+    }
+
+    if (email.len <= 0)
+      ssl_verify_err = "contains no email address";
+    else if (!constmap(&mapclients, email.s, email.len))
+      ssl_verify_err = "email address not in my list of tlsclients";
+    else {
+      /* add the cert email to the proto if it helped allow relaying */
+      --proto.len;
+      if (!stralloc_cats(&proto, "\n  cert ") /* continuation line */
+        || !stralloc_catb(&proto, email.s, email.len)
+        || !stralloc_0(&proto)) die_nomem();
+      relayclient = "";
+      protocol = proto.s;
+    }
+
+    X509_free(peercert);
+  } while (0);
+  constmap_free(&mapclients); alloc_free(clients.s);
+
+  /* we are not going to need this anymore: free the memory */
+  SSL_set_client_CA_list(ssl, NULL);
+  SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
+
+  return relayclient ? 1 : 0;
+}
+
+void tls_init()
+{
+  SSL *myssl;
+  SSL_CTX *ctx;
+  const char *ciphers;
+  stralloc saciphers = {0};
+
+  SSL_library_init();
+
+  /* a new SSL context with the bare minimum of options */
+  ctx = SSL_CTX_new(SSLv23_server_method());
+  if (!ctx) { tls_err("unable to initialize ctx"); return; }
+
+  if (!SSL_CTX_use_certificate_chain_file(ctx, SERVERCERT))
+    { SSL_CTX_free(ctx); tls_err("missing certificate"); return; }
+  SSL_CTX_load_verify_locations(ctx, CLIENTCA, NULL);
+  /* set the callback here; SSL_set_verify didn't work before 0.9.6c */
+  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, verify_cb);
+
+  /* a new SSL object, with the rest added to it directly to avoid copying */
+  myssl = SSL_new(ctx);
+  SSL_CTX_free(ctx);
+  if (!myssl) { tls_err("unable to initialize ssl"); return; }
+
+  /* this will also check whether publc and private keys match */
+  if (!SSL_use_RSAPrivateKey_file(myssl, SERVERCERT, SSL_FILETYPE_PEM))
+    { SSL_free(myssl); tls_err("no valid RSA private key"); return; }
+
+  ciphers = env_get("TLSCIPHERS");
+  if (!ciphers) {
+    if (control_readfile(&saciphers, "control/tlsserverciphers") == -1)
+      { SSL_free(myssl); die_control(); }
+    if (saciphers.len) { /* convert all '\0's except the last one to ':' */
+      int i;
+      for (i = 0; i < saciphers.len - 1; ++i)
+        if (!saciphers.s[i]) saciphers.s[i] = ':';
+      ciphers = saciphers.s;
+    }
+  }
+  if (!ciphers || !*ciphers) ciphers = "DEFAULT";
+  SSL_set_cipher_list(myssl, ciphers);
+  alloc_free(saciphers.s);
+
+  SSL_set_tmp_rsa_callback(myssl, tmp_rsa_cb);
+  SSL_set_rfd(myssl, ssl_rfd = substdio_fileno(&ssin));
+  SSL_set_wfd(myssl, ssl_wfd = substdio_fileno(&ssout));
+
+  if (!smtps) { out("220 ready for tls\r\n"); flush(); }
+
+  if (ssl_timeoutaccept(timeout, ssl_rfd, ssl_wfd, myssl) <= 0) {
+    /* neither cleartext nor any other response here is part of a standard */
+    const char *err = ssl_strerror();
+    ssl_free(myssl); tls_out("connection failed", err); die_read();
+  }
+  ssl = myssl;
+
+  /* populate the protocol string, used in Received */
+  if (!stralloc_copys(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted SMTP")) die_nomem();
+  if (smtps) if (!stralloc_append(&proto, "S")) die_nomem();
+  if (!stralloc_0(&proto)) die_nomem();
+  protocol = proto.s;
+
+  /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
+  dohelo(remotehost);
+}
+
+# undef SERVERCERT
+# undef CLIENTCA
+
+#endif
+
+struct commands smtpcommands[] = {
+  { "rcpt", smtp_rcpt, 0 }
+, { "mail", smtp_mail, 0 }
+, { "data", smtp_data, flush }
+, { "auth", smtp_auth, flush }
+, { "quit", smtp_quit, flush }
+, { "helo", smtp_helo, flush }
+, { "ehlo", smtp_ehlo, flush }
+, { "rset", smtp_rset, 0 }
+, { "help", smtp_help, flush }
+#ifdef TLS
+, { "starttls", smtp_tls, flush }
+#endif
+, { "noop", err_noop, flush }
+, { "vrfy", err_vrfy, flush }
+, { 0, err_unimpl, flush }
+} ;
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+  hostname = argv[1];
+  childargs = argv + 2;
+
+  sig_pipeignore();
+  if (chdir(auto_qmail) == -1) die_control();
+  setup();
+  if (ipme_init() != 1) die_ipme();
+  smtp_greet("220 ");
+  out(" ESMTP\r\n");
+  if (commands(&ssin,&smtpcommands) == 0) die_read();
+  die_nomem();
+}
diff -urN qmail-1.03-orig/qmail-smtpd.c.rej qmail-1.03/qmail-smtpd.c.rej
--- qmail-1.03-orig/qmail-smtpd.c.rej	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/qmail-smtpd.c.rej	2003-10-07 17:24:42.000000000 -0400
@@ -0,0 +1,160 @@
+***************
+*** 96,101 ****
+  int bmfok = 0;
+  stralloc bmf = {0};
+  struct constmap mapbmf;
+  
+  void setup()
+  {
+--- 96,103 ----
+  int bmfok = 0;
+  stralloc bmf = {0};
+  struct constmap mapbmf;
++ int sigsok = 0;
++ stralloc sigs = {0};
+  
+  void setup()
+  {
+***************
+*** 635,643 ****
+  struct qmail qqt;
+  unsigned int bytestooverflow = 0;
+  
+  void put(ch)
+  char *ch;
+  {
+    if (bytestooverflow)
+      if (!--bytestooverflow)
+        qmail_fail(&qqt);
+--- 653,783 ----
+  struct qmail qqt;
+  unsigned int bytestooverflow = 0;
+  
++ int linespastheader;		/* =0 after boundary is found in body, */
++                                 /* until blank line */
++ char linetype;
++ int flagexecutable;
++ 
++ stralloc line = {0};
++ stralloc content = {0};
++ stralloc boundary = {0};
++ int boundary_start;
++ 
++ /*
++ 
++ def put(ch):
++     line.append(ch)
++     if ch == '\n':
++         if linepastheader == 0:
++             if line.beginswith('Content-Type:'):
++                 content = 
++ 
++  put() puts characters into the queue.  We remember those characters
++    and form them into a line.  When we get a newline, we examine the
++    line.  If we're currently in a header (0 linespastheader), we look
++    for Content-Type.  If we're at the newline that ends a header, we
++    look to see if the content is multipart.  If it is, then we push
++    the current boundary, remember the boundary, otherwise we set the
++    boundary to the empty string.  Set the linespastheader to 1.  When
++    linespastheader is 1, and the boundary is empty, scan the line for
++    signatures.  If the boundary is non-empty, look for a match against
++    the boundary.  If it matches and is followed by two dashes, pop the
++    boundary, otherwise set linespastheader to 0.
++ */
++ 
+  void put(ch)
+  char *ch;
+  {
++   char *cp, *cpstart, *cpafter;
++   unsigned int len;
++ 
++   if (line.len < 1024)
++     if (!stralloc_catb(&line,ch,1)) die_nomem();
++ 
++   if (*ch == '\n') {
++     if (linespastheader == 0) {
++       if (line.len == 1) {
++ 	linespastheader = 1;	
++ 	if (content.len) {			/* MIME header */
++ 	  cp = content.s;
++ 	  len = content.len;
++ 	  while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
++ 	  cpstart = cp;
++ 	  if (len && *cp == '"') {			/* might be commented */
++ 	    ++cp; --len; cpstart = cp;
++ 	    while (len && *cp != '"') { ++cp; --len; }
++ 	  } else {
++ 	    while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
++ 	      ++cp; --len;
++ 	    }
++ 	  }
++ 
++ 	  cpafter = content.s+content.len;
++ 	  while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
++ 	    ++cp;
++ 	    while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
++ 	    if (case_startb(cp,cpafter - cp,"boundary=")) {
++ 	      cp += 9;			/* after boundary= */
++ 	      if (cp < cpafter && *cp == '"') {
++ 		++cp;
++ 		cpstart = cp;
++ 		while (cp < cpafter && *cp != '"') ++cp;
++ 	      } else {
++ 		cpstart = cp;
++ 		while (cp < cpafter &&
++ 		   *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
++ 	      }
++ 	      /* push the current boundary.  Append a null and remember start. */
++ 	      if (!stralloc_0(&boundary)) die_nomem();
++ 	      boundary_start = boundary.len;
++ 	      if (!stralloc_cats(&boundary,"--")) die_nomem();
++ 	      if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
++ 		      die_nomem();
++ 	      break;
++ 	    }
++ 	  }
++ 	}
++       } else { /* non-blank header line */
++ 	if ((*line.s == ' ' || *line.s == '\t')) {
++ 	  switch(linetype) {
++ 	    case 'C': if (!stralloc_catb(&content,line.s,line.len-1)) die_nomem(); break;
++ 	    default: break;
++ 	  }
++ 	} else {
++ 	  if (case_startb(line.s,line.len,"content-type:")) {
++ 	    if (!stralloc_copyb(&content,line.s+13,line.len-14)) die_nomem();
++ 	    linetype = 'C';
++ 	  } else {
++ 	    linetype = ' ';
++ 	  }
++ 	}
++       }
++     } else {      /* non-header line */
++       if (boundary.len-boundary_start && *line.s == '-' && line.len > (boundary.len-boundary_start) &&
++ 	  !str_diffn(line.s,boundary.s+boundary_start,boundary.len-boundary_start)) { /* matches a boundary */
++ 	if (line.len > boundary.len-boundary_start + 2 &&
++             line.s[boundary.len-boundary_start+0] == '-' &&
++             line.s[boundary.len-boundary_start+1] == '-') {
++ 	  /* XXXX - pop the boundary here */
++ 	  if (boundary_start) boundary.len = boundary_start - 1;
++ 	  boundary_start = boundary.len;
++ 	  while(boundary_start--) if (!boundary.s[boundary_start]) break;
++ 	  boundary_start++;
++ 	  linespastheader = 2;
++ 	} else {
++ 	  linespastheader = 0;
++ 	}
++       } else if (linespastheader == 1) { /* first line -- match a signature? */
++ 	if (sigscheck(&line)) {
++ 	  flagexecutable = 1;
++ 	  qmail_fail(&qqt);
++ 	}
++ 	linespastheader = 2;
++       }
++     }
++     line.len = 0;
++   }
++ 
+    if (bytestooverflow)
+      if (!--bytestooverflow)
+        qmail_fail(&qqt);
diff -urN qmail-1.03-orig/qmail.c qmail-1.03/qmail.c
--- qmail-1.03-orig/qmail.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/qmail.c	2003-10-03 14:08:49.000000000 -0400
@@ -6,8 +6,17 @@
 #include "fd.h"
 #include "qmail.h"
 #include "auto_qmail.h"
+#include "env.h"
 
-static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+static char *binqqargs[2] = { 0, 0 } ;
+
+static void setup_qqargs()
+{
+  if(!binqqargs[0])
+    binqqargs[0] = env_get("QMAILQUEUE");
+  if(!binqqargs[0])
+    binqqargs[0] = "bin/qmail-queue";
+}
 
 int qmail_open(qq)
 struct qmail *qq;
@@ -15,6 +24,8 @@
   int pim[2];
   int pie[2];
 
+  setup_qqargs();
+
   if (pipe(pim) == -1) return -1;
   if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
  
diff -urN qmail-1.03-orig/remoteinfo.c qmail-1.03/remoteinfo.c
--- qmail-1.03-orig/remoteinfo.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/remoteinfo.c	2003-10-03 14:08:49.000000000 -0400
@@ -44,12 +44,12 @@
   s = socket(AF_INET,SOCK_STREAM,0);
   if (s == -1) return 0;
  
-  byte_zero(&sin,sizeof(sin));
+/*  byte_zero(&sin,sizeof(sin));
   sin.sin_family = AF_INET;
   byte_copy(&sin.sin_addr,4,ipl);
   sin.sin_port = 0;
-  if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; }
-  if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; }
+  if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } */
+  if (timeoutconn(s,ipr,ipl,113,timeout) == -1) { close(s); return 0; }
   fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY);
  
   len = 0;
diff -urN qmail-1.03-orig/signatures qmail-1.03/signatures
--- qmail-1.03-orig/signatures	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/signatures	2003-10-07 17:39:23.000000000 -0400
@@ -0,0 +1,18 @@
+# Windows executables seen in active virii
+TVqQAAMAA
+TVpQAAIAA
+# Additional windows executable signatures not yet seen in virii
+TVpAALQAc
+TVpyAXkAX
+TVrmAU4AA
+TVrhARwAk
+TVoFAQUAA
+TVoAAAQAA
+TVoIARMAA
+TVouARsAA
+TVrQAT8AA
+# .ZIPfile signature seen in SoBig.E:
+UEsDBBQAA
+# .GIF file found in the current Microsoft virus making the rounds.
+R0lGODlhaAA7APcAAP///+rp6puSp6GZrDUjUUc6Zn53mFJMdbGvvVtXh2xre8bF1x8cU4yLprOy
+
diff -urN qmail-1.03-orig/spawn.c qmail-1.03/spawn.c
--- qmail-1.03-orig/spawn.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/spawn.c	2003-10-03 14:08:49.000000000 -0400
@@ -63,7 +63,7 @@
 int flagreading = 1;
 char outbuf[1024]; substdio ssout;
 
-int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */
+int stage = 0; /* reading 0:delnum 1:delnum2 2:messid 3:sender 4:recip */
 int flagabort = 0; /* if 1, everything except delnum is garbage */
 int delnum;
 stralloc messid = {0};
@@ -73,6 +73,7 @@
 void err(s) char *s;
 {
  char ch; ch = delnum; substdio_put(&ssout,&ch,1);
+ ch = delnum >> 8; substdio_put(&ssout,&ch,1);
  substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1);
 }
 
@@ -155,16 +156,19 @@
     {
      case 0:
        delnum = (unsigned int) (unsigned char) ch;
-       messid.len = 0; stage = 1; break;
+       stage = 1; break;
      case 1:
+       delnum += (unsigned int) ((unsigned int) ch) << 8;
+       messid.len = 0; stage = 2; break;
+     case 2:
        if (!stralloc_append(&messid,&ch)) flagabort = 1;
        if (ch) break;
-       sender.len = 0; stage = 2; break;
-     case 2:
+       sender.len = 0; stage = 3; break;
+     case 3:
        if (!stralloc_append(&sender,&ch)) flagabort = 1;
        if (ch) break;
-       recip.len = 0; stage = 3; break;
-     case 3:
+       recip.len = 0; stage = 4; break;
+     case 4:
        if (!stralloc_append(&recip,&ch)) flagabort = 1;
        if (ch) break;
        docmd();
@@ -201,7 +205,8 @@
 
  initialize(argc,argv);
 
- ch = auto_spawn; substdio_putflush(&ssout,&ch,1);
+ ch = auto_spawn; substdio_put(&ssout,&ch,1);
+ ch = auto_spawn >> 8; substdio_putflush(&ssout,&ch,1);
 
  for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; }
 
@@ -236,7 +241,8 @@
 	   continue; /* read error on a readable pipe? be serious */
 	 if (r == 0)
 	  {
-           ch = i; substdio_put(&ssout,&ch,1);
+           char ch; ch = i; substdio_put(&ssout,&ch,1);
+           ch = i >> 8; substdio_put(&ssout,&ch,1);
 	   report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len);
 	   substdio_put(&ssout,"",1);
 	   substdio_flush(&ssout);
diff -urN qmail-1.03-orig/ssl_timeoutio.c qmail-1.03/ssl_timeoutio.c
--- qmail-1.03-orig/ssl_timeoutio.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/ssl_timeoutio.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,94 @@
+#include "select.h"
+#include "error.h"
+#include "ndelay.h"
+#include "ssl_timeoutio.h"
+
+int ssl_timeoutio(int (*fun)(),
+  long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+  int n;
+  const long end = t + time(NULL);
+
+  do {
+    fd_set fds;
+    struct timeval tv;
+
+    const int r = buf ? fun(ssl, buf, len) : fun(ssl);
+    if (r > 0) return r;
+
+    t = end - time(NULL);
+    if (t < 0) break;
+    tv.tv_sec = t; tv.tv_usec = 0;
+
+    FD_ZERO(&fds);
+    switch (SSL_get_error(ssl, r))
+    {
+    default: return r; /* some other error */
+    case SSL_ERROR_WANT_READ:
+      FD_SET(rfd, &fds); n = select(rfd + 1, &fds, NULL, NULL, &tv);
+      break;
+    case SSL_ERROR_WANT_WRITE:
+      FD_SET(wfd, &fds); n = select(wfd + 1, NULL, &fds, NULL, &tv);
+      break;
+    }
+
+    /* n is the number of descriptors that changed status */
+  } while (n > 0);
+
+  if (n != -1) errno = error_timeout;
+  return -1;
+}
+
+int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl)
+{
+  int r;
+
+  /* if connection is established, keep NDELAY */
+  if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
+  r = ssl_timeoutio(SSL_accept, t, rfd, wfd, ssl, NULL, 0);
+
+  if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
+  else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+  return r;
+}
+
+int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl)
+{
+  int r;
+
+  /* if connection is established, keep NDELAY */
+  if (ndelay_on(rfd) == -1 || ndelay_on(wfd) == -1) return -1;
+  r = ssl_timeoutio(SSL_connect, t, rfd, wfd, ssl, NULL, 0);
+
+  if (r <= 0) { ndelay_off(rfd); ndelay_off(wfd); }
+  else SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+
+  return r;
+}
+
+int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl)
+{
+  int r;
+
+  SSL_renegotiate(ssl);
+  r = ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
+  if (r <= 0 || ssl->type == SSL_ST_CONNECT) return r;
+
+  /* this is for the server only */
+  ssl->state = SSL_ST_ACCEPT;
+  return ssl_timeoutio(SSL_do_handshake, t, rfd, wfd, ssl, NULL, 0);
+}
+
+int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+  if (!buf) return 0;
+  if (SSL_pending(ssl)) return SSL_read(ssl, buf, len);
+  return ssl_timeoutio(SSL_read, t, rfd, wfd, ssl, buf, len);
+}
+
+int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+  if (!buf) return 0;
+  return ssl_timeoutio(SSL_write, t, rfd, wfd, ssl, buf, len);
+}
diff -urN qmail-1.03-orig/ssl_timeoutio.h qmail-1.03/ssl_timeoutio.h
--- qmail-1.03-orig/ssl_timeoutio.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/ssl_timeoutio.h	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,21 @@
+#ifndef SSL_TIMEOUTIO_H
+#define SSL_TIMEOUTIO_H
+
+#include <openssl/ssl.h>
+
+/* the version is like this: 0xMNNFFPPS: major minor fix patch status */
+#if OPENSSL_VERSION_NUMBER < 0x00906000L
+# error "Need OpenSSL version at least 0.9.6"
+#endif
+
+int ssl_timeoutconn(long t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutaccept(long t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutrehandshake(long t, int rfd, int wfd, SSL *ssl);
+
+int ssl_timeoutread(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+int ssl_timeoutwrite(long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+int ssl_timeoutio(
+  int (*fun)(), long t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+#endif
diff -urN qmail-1.03-orig/strpidt.c qmail-1.03/strpidt.c
--- qmail-1.03-orig/strpidt.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/strpidt.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	"numlib.h"
+#include	<string.h>
+
+static const char rcsid[]="$Id: strpidt.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $";
+
+char *str_pid_t(pid_t t, char *arg)
+{
+char	buf[NUMBUFSIZE];
+char	*p=buf+sizeof(buf)-1;
+
+	*p=0;
+	do
+	{
+		*--p= '0' + (t % 10);
+		t=t / 10;
+	} while(t);
+	return (strcpy(arg, p));
+}
diff -urN qmail-1.03-orig/strtimet.c qmail-1.03/strtimet.c
--- qmail-1.03-orig/strtimet.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/strtimet.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+** Copyright 1998 - 2000 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if	HAVE_CONFIG_H
+#include	"config.h"
+#endif
+#include	"numlib.h"
+#include	<string.h>
+
+static const char rcsid[]="$Id: strtimet.c,v 1.3 2000/05/27 04:59:26 mrsam Exp $";
+
+char *str_time_t(time_t t, char *arg)
+{
+char	buf[NUMBUFSIZE];
+char	*p=buf+sizeof(buf)-1;
+
+	*p=0;
+	do
+	{
+		*--p= '0' + (t % 10);
+		t=t / 10;
+	} while(t);
+	return (strcpy(arg, p));
+}
diff -urN qmail-1.03-orig/timeoutconn.c qmail-1.03/timeoutconn.c
--- qmail-1.03-orig/timeoutconn.c	1998-06-15 06:53:16.000000000 -0400
+++ qmail-1.03/timeoutconn.c	2003-10-03 14:08:49.000000000 -0400
@@ -10,9 +10,10 @@
 #include "byte.h"
 #include "timeoutconn.h"
 
-int timeoutconn(s,ip,port,timeout)
+int timeoutconn(s,ip,outip,port,timeout)
 int s;
 struct ip_address *ip;
+struct ip_address *outip;
 unsigned int port;
 int timeout;
 {
@@ -22,6 +23,13 @@
   fd_set wfds;
   struct timeval tv;
  
+  /* bind() an outgoing ipaddr */
+  byte_zero(&sin,sizeof(sin));
+  byte_copy(&sin.sin_addr.s_addr,4,outip);
+  sin.sin_family = AF_INET;
+
+  if (-1 == bind(s,(struct sockaddr *) &sin,sizeof(sin))) return -1;
+
   byte_zero(&sin,sizeof(sin));
   byte_copy(&sin.sin_addr,4,ip);
   x = (char *) &sin.sin_port;
diff -urN qmail-1.03-orig/tls.c qmail-1.03/tls.c
--- qmail-1.03-orig/tls.c	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/tls.c	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,26 @@
+#include "exit.h"
+#include "error.h"
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+int smtps = 0;
+SSL *ssl = NULL;
+
+void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
+void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
+
+const char *strerror(int);
+const char *ssl_error()
+{
+  int r = ERR_get_error();
+  if (!r) return NULL;
+  SSL_load_error_strings();
+  return ERR_error_string(r, NULL);
+}
+const char *ssl_strerror()
+{
+  const char *err = ssl_error();
+  if (err) return err;
+  if (!errno) return 0;
+  return errno == error_timeout ? "timed out" : strerror(errno);
+}
diff -urN qmail-1.03-orig/tls.h qmail-1.03/tls.h
--- qmail-1.03-orig/tls.h	1969-12-31 19:00:00.000000000 -0500
+++ qmail-1.03/tls.h	2003-10-03 14:08:49.000000000 -0400
@@ -0,0 +1,16 @@
+#ifndef TLS_H
+#define TLS_H
+
+#include <openssl/ssl.h>
+
+extern int smtps;
+extern SSL *ssl;
+
+void ssl_free(SSL *myssl);
+void ssl_exit(int status);
+# define _exit ssl_exit
+
+const char *ssl_error();
+const char *ssl_strerror();
+
+#endif
