diff -urN qmail-1.03/FILES qmail-1.03-with-plesk-8.6/FILES
--- qmail-1.03/FILES	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/FILES	2008-08-26 03:06:46.000000000 +0200
@@ -135,6 +135,8 @@
 dnsip.c
 dnsmxip.c
 dnsptr.c
+dnstxt.c
+spfquery.c
 hostname.c
 ipmeprint.c
 tcp-env.c
@@ -335,13 +337,16 @@
 byte.h
 byte_chr.c
 byte_copy.c
+byte_cspn.c
 byte_cr.c
 byte_diff.c
 byte_rchr.c
+byte_rcspn.c
 byte_zero.c
 str.h
 str_chr.c
 str_cpy.c
+str_cpyb.c
 str_diff.c
 str_diffn.c
 str_len.c
@@ -401,6 +406,8 @@
 date822fmt.c
 dns.h
 dns.c
+spf.h
+spf.c
 trylsock.c
 tryrsolv.c
 ip.h
diff -urN qmail-1.03/Makefile qmail-1.03-with-plesk-8.6/Makefile
--- qmail-1.03/Makefile	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/Makefile	2008-08-26 03:07:49.000000000 +0200
@@ -112,17 +112,17 @@
 
 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-uid auto_uida `head -1 conf-users` `id -u \`head -1 conf-users\` ` \
+           &&./auto-uid auto_uidd `head -2 conf-users | tail -1` `id -u \`head -2 conf-users | tail -1\`` \
+           &&./auto-uid auto_uidl `head -3 conf-users | tail -1` `id -u \`head -3 conf-users | tail -1\`` \
+           &&./auto-uid auto_uido `head -4 conf-users | tail -1` `id -u \`head -4 conf-users | tail -1\`` \
+           &&./auto-uid auto_uidp `head -5 conf-users | tail -1` `id -u \`head -5 conf-users | tail -1\`` \
+           &&./auto-uid auto_uidq `head -6 conf-users | tail -1` `id -u \`head -6 conf-users | tail -1\`` \
+           &&./auto-uid auto_uidr `head -7 conf-users | tail -1` `id -u \`head -7 conf-users | tail -1\`` \
+           &&./auto-uid auto_uids `head -8 conf-users | tail -1` `id -u \`head -8 conf-users | tail -1\`` \
+           &&./auto-gid auto_gidq `head -1 conf-groups` 1002 \
+           &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` 1001 \
+           )> auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c
 
 auto_uids.o: \
 compile auto_uids.c
@@ -203,6 +203,10 @@
 compile byte_cr.c byte.h
 	./compile byte_cr.c
 
+byte_cspn.o: \
+compile byte_cspn.c byte.h
+	./compile byte_cspn.c
+
 byte_diff.o: \
 compile byte_diff.c byte.h
 	./compile byte_diff.c
@@ -211,6 +215,10 @@
 compile byte_rchr.c byte.h
 	./compile byte_rchr.c
 
+byte_rcspn.o: \
+compile byte_rcspn.c byte.h
+	./compile byte_rcspn.c
+
 byte_zero.o: \
 compile byte_zero.c byte.h
 	./compile byte_zero.c
@@ -263,7 +271,7 @@
 	cdbmake_add.o
 
 cdbmake_add.o: \
-compile cdbmake_add.c cdbmake.h uint32.h
+compile cdbmake_add.c cdbmake.h alloc.h uint32.h
 	./compile cdbmake_add.c
 
 cdbmake_hash.o: \
@@ -393,84 +401,96 @@
 	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
+tryrsolv.c compile load socket.lib dns.o ipalloc.o strsalloc.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 \
+	ipalloc.o strsalloc.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 ip.h ipalloc.h strsalloc.h gen_alloc.h fmt.h alloc.h \
+str.h stralloc.h dns.h case.h
 	./compile dns.c
 
 dnscname: \
-load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+	./load dnscname dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+compile dnscname.c substdio.h subfd.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 substdio.h subfd.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 \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+	./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
 	./compile dnsfq.c
 
 dnsip: \
-load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+	./load dnsip dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 substdio.h subfd.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.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 \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 \
+compile dnsmxip.c substdio.h subfd.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h strsalloc.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 \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+	./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 \
+compile dnsptr.c substdio.h subfd.h stralloc.h gen_alloc.h \
 str.h scan.h dns.h dnsdoe.h ip.h exit.h
 	./compile dnsptr.c
 
+dnstxt: \
+load dnstxt.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnstxt dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnstxt.o: \
+compile dnstxt.c substdio.h subfd.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnstxt.c
+
 dot-qmail.0: \
 dot-qmail.5
 	nroff -man dot-qmail.5 > dot-qmail.0
@@ -777,24 +797,24 @@
 	./compile ip.c
 
 ipalloc.o: \
-compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.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 hassalen.h byte.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.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`
+load ipmeprint.o ipme.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a socket.lib
+	./load ipmeprint ipme.o ip.o ipalloc.o strsalloc.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
+ipalloc.h strsalloc.h ip.h gen_alloc.h exit.h
 	./compile ipmeprint.c
 
 it: \
@@ -804,11 +824,11 @@
 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 \
+dnsptr dnsip dnsmxip dnsfq dnstxt 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
+binm3 binm3+df spfquery qmail-dk
 
 load: \
 make-load warn-auto.sh systype
@@ -1439,12 +1459,13 @@
 
 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 \
+timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o strsalloc.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 \
-	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
+	tls.o ssl_timeoutio.o `cat ssl.lib` \
+	ipalloc.o strsalloc.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`
 
@@ -1455,7 +1476,7 @@
 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 \
+alloc.h quote.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.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
@@ -1483,12 +1504,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
@@ -1528,21 +1549,27 @@
 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
+auto_split.h spf.h
 	./compile qmail-showctl.c
 
+qmail-spp.o: \
+compile qmail-spp.c readwrite.h stralloc.h substdio.h control.h str.h \
+byte.h env.h exit.h wait.h fork.h fd.h fmt.h getln.h
+	./compile qmail-spp.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 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 substdio.a error.a str.a strsalloc.o spf.o dns.o \
+fs.a auto_qmail.o qmail-spp.o socket.lib 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 `cat ssl.lib` \
 	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 \
+	datetime.a getln.a open.a sig.a case.a env.a stralloc.a strsalloc.o spf.o dns.o qmail-spp.o \
 	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
-	socket.lib`
+	socket.lib` `cat dns.lib`
 
 qmail-smtpd.0: \
 qmail-smtpd.8
@@ -1551,9 +1578,9 @@
 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 \
+error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h strsalloc.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
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h spf.h qmail-spp.h
 	./compile qmail-smtpd.c
 
 qmail-start: \
@@ -1779,7 +1806,7 @@
 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 \
+dnsip.c dnsmxip.c dnsptr.c dnstxt.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 \
@@ -1813,8 +1840,9 @@
 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 \
+byte_copy.c byte_cr.c byte_cspn.c byte_diff.c byte_rchr.c byte_rcspn.c \
+byte_zero.c str.h spf.c spf.h spfquery.c \
+str_chr.c str_cpy.c str_cpyb.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 \
@@ -1824,7 +1852,7 @@
 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 \
+ipalloc.h strsalloc.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
@@ -1892,11 +1920,28 @@
 
 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 \
+stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
 auto_qmail.h auto_uids.h auto_spawn.h
 	./chkspawn
 	./compile spawn.c
 
+spf.o: \
+compile spf.c stralloc.h gen_alloc.h alloc.h ipme.h ip.h ipalloc.h \
+strsalloc.h str.h fmt.h scan.h byte.h now.h case.h
+	./compile spf.c
+
+spfquery: \
+load spfquery.o spf.o ip.o ipme.o ipalloc.o strsalloc.o now.o dns.o \
+datetime.a stralloc.a alloc.a str.a substdio.a error.a fs.a case.a dns.lib
+	./load spfquery spf.o ip.o ipme.o ipalloc.o strsalloc.o \
+	now.o dns.o datetime.a stralloc.a alloc.a str.a substdio.a \
+	case.a error.a fs.a `cat dns.lib` `cat socket.lib`
+
+spfquery.o: \
+compile spfquery.c substdio.h subfd.h stralloc.h gen_alloc.h alloc.h \
+spf.h exit.h
+	./compile spfquery.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 \
@@ -1912,12 +1957,12 @@
 	./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
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_cpyb.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o byte_rcspn.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_cpyb.o \
+	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o \
+	byte_rcspn.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o
 
 str_chr.o: \
 compile str_chr.c str.h
@@ -1927,6 +1972,10 @@
 compile str_cpy.c str.h
 	./compile str_cpy.c
 
+str_cpyb.o: \
+compile str_cpyb.c str.h
+	./compile str_cpyb.c
+
 str_diff.o: \
 compile str_diff.c str.h
 	./compile str_diff.c
@@ -2006,6 +2055,11 @@
 compile strerr_sys.c error.h strerr.h
 	./compile strerr_sys.c
 
+strsalloc.o: \
+compile strsalloc.c alloc.h gen_allocdefs.h stralloc.h strsalloc.h \
+gen_alloc.h
+	./compile strsalloc.c
+
 subfderr.o: \
 compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
 	./compile subfderr.c
@@ -2066,11 +2120,11 @@
 
 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
+timeoutconn.o ip.o ipalloc.o strsalloc.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 \
+	timeoutwrite.o timeoutconn.o ip.o ipalloc.o strsalloc.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: \
@@ -2108,6 +2162,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 +2206,28 @@
 wait_pid.o: \
 compile wait_pid.c error.h haswaitp.h
 	./compile wait_pid.c
+
+qmail-dk: \
+load qmail-dk.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 fd.a wait.a \
+env.a getln.a control.o stralloc.a dns.lib
+	./load qmail-dk triggerpull.o fmtqfn.o now.o \
+	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+	substdio.a error.a fs.a auto_qmail.o \
+	auto_split.o auto_uids.o \
+	fd.a wait.a \
+		`cat dk.lib` `cat ssl.lib` env.a control.o open.a getln.a \
+	stralloc.a alloc.a  scan_ulong.o str.a `cat dns.lib`
+
+qmail-dk.0: \
+qmail-dk.8
+	nroff -man qmail-dk.8 > qmail-dk.0
+
+qmail-dk.o: \
+compile qmail-dk.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 \
+env.h wait.h fd.h fork.h str.h \
+auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
+	./compile qmail-dk.c
+
diff -urN qmail-1.03/Makefile.orig qmail-1.03-with-plesk-8.6/Makefile.orig
--- qmail-1.03/Makefile.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/Makefile.orig	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,2233 @@
+# 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
+
+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_cspn.o: \
+compile byte_cspn.c byte.h
+	./compile byte_cspn.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_rcspn.o: \
+compile byte_rcspn.c byte.h
+	./compile byte_rcspn.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 alloc.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 strsalloc.o ip.o \
+stralloc.a alloc.a error.a fs.a str.a
+	( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
+	ipalloc.o strsalloc.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 strsalloc.h gen_alloc.h fmt.h alloc.h \
+str.h stralloc.h dns.h case.h
+	./compile dns.c
+
+dnscname: \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 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 exit.h dns.h dnsdoe.h
+	./compile dnsdoe.c
+
+dnsfq: \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
+	./compile dnsfq.c
+
+dnsip: \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h exit.h
+	./compile dnsip.c
+
+dnsmxip: \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h strsalloc.h \
+now.h datetime.h exit.h
+	./compile dnsmxip.c
+
+dnsptr: \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.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 strsalloc.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 stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnsptr.c
+
+dnstxt: \
+load dnstxt.o dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnstxt dns.o dnsdoe.o ip.o ipalloc.o strsalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnstxt.o: \
+compile dnstxt.c substdio.h subfd.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnstxt.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 \
+gen_alloc.h
+	./compile ipalloc.c
+
+ipme.o: \
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h strsalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.h
+	./compile ipme.c
+
+ipmeprint: \
+load ipmeprint.o ipme.o ip.o ipalloc.o strsalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a socket.lib
+	./load ipmeprint ipme.o ip.o ipalloc.o strsalloc.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 strsalloc.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 dnstxt 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 spfquery qmail-dk
+
+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
+
+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-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
+	./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`
+
+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
+	./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`
+
+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 strsalloc.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 `cat ssl.lib` \
+	ipalloc.o strsalloc.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 strsalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h strsalloc.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
+	./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 
+
+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 spf.h
+	./compile qmail-showctl.c
+
+qmail-spp.o: \
+compile qmail-spp.c readwrite.h stralloc.h substdio.h control.h str.h \
+byte.h env.h exit.h wait.h fork.h fd.h fmt.h getln.h
+	./compile qmail-spp.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 substdio.a error.a str.a strsalloc.o spf.o dns.o \
+fs.a auto_qmail.o qmail-spp.o socket.lib 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 `cat ssl.lib` \
+	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 strsalloc.o spf.o dns.o qmail-spp.o \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
+	socket.lib` `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 strsalloc.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 spf.h qmail-spp.h
+	./compile qmail-smtpd.c
+
+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 dnstxt.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_cspn.c byte_diff.c byte_rchr.c byte_rcspn.c \
+byte_zero.c str.h spf.c spf.h spfquery.c \
+str_chr.c str_cpy.c str_cpyb.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 strsalloc.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 alloc.h coe.h open.h error.h \
+auto_qmail.h auto_uids.h auto_spawn.h
+	./chkspawn
+	./compile spawn.c
+
+spf.o: \
+compile spf.c stralloc.h gen_alloc.h alloc.h ipme.h ip.h ipalloc.h \
+strsalloc.h str.h fmt.h scan.h byte.h now.h case.h
+	./compile spf.c
+
+spfquery: \
+load spfquery.o spf.o ip.o ipme.o ipalloc.o strsalloc.o now.o dns.o \
+datetime.a stralloc.a alloc.a str.a substdio.a error.a fs.a case.a dns.lib
+	./load spfquery spf.o ip.o ipme.o ipalloc.o strsalloc.o \
+	now.o dns.o datetime.a stralloc.a alloc.a str.a substdio.a \
+	case.a error.a fs.a `cat dns.lib` `cat socket.lib`
+
+spfquery.o: \
+compile spfquery.c substdio.h subfd.h stralloc.h gen_alloc.h alloc.h \
+spf.h exit.h
+	./compile spfquery.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_cpyb.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o byte_rcspn.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_cpyb.o \
+	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_cspn.o \
+	byte_rcspn.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_cpyb.o: \
+compile str_cpyb.c str.h
+	./compile str_cpyb.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
+
+strsalloc.o: \
+compile strsalloc.c alloc.h gen_allocdefs.h stralloc.h strsalloc.h \
+gen_alloc.h
+	./compile strsalloc.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 strsalloc.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 strsalloc.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
+
+qmail-dk: \
+load qmail-dk.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 fd.a wait.a \
+env.a getln.a control.o stralloc.a dns.lib
+	./load qmail-dk triggerpull.o fmtqfn.o now.o \
+	date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \
+	substdio.a error.a fs.a auto_qmail.o \
+	auto_split.o auto_uids.o \
+	fd.a wait.a \
+		`cat dk.lib` `cat ssl.lib` env.a control.o open.a getln.a \
+	stralloc.a alloc.a  scan_ulong.o str.a `cat dns.lib`
+
+qmail-dk.0: \
+qmail-dk.8
+	nroff -man qmail-dk.8 > qmail-dk.0
+
+qmail-dk.o: \
+compile qmail-dk.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 \
+env.h wait.h fd.h fork.h str.h \
+auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h
+	./compile qmail-dk.c
+
diff -urN qmail-1.03/TARGETS qmail-1.03-with-plesk-8.6/TARGETS
--- qmail-1.03/TARGETS	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/TARGETS	2008-08-26 03:06:46.000000000 +0200
@@ -100,11 +100,14 @@
 str_diff.o
 str_diffn.o
 str_cpy.o
+str_cpyb.o
 str_chr.o
 str_rchr.o
 str_start.o
 byte_chr.o
 byte_rchr.o
+byte_cspn.o
+byte_rcspn.o
 byte_diff.o
 byte_copy.o
 byte_cr.o
@@ -168,11 +171,15 @@
 constmap.o
 timeoutread.o
 timeoutwrite.o
+tls.o
+ssl_timeoutio.o
 timeoutconn.o
 tcpto.o
 dns.o
+spf.o
 ip.o
 ipalloc.o
+strsalloc.o
 hassalen.h
 ipme.o
 ndelay.o
@@ -212,6 +219,9 @@
 headerbody.o
 hfield.o
 token822.o
+spf.o
+spfquery.o
+spfquery
 qmail-inject
 predate.o
 predate
@@ -270,6 +280,8 @@
 dnsip
 dnsmxip.o
 dnsmxip
+dnstxt.o
+dnstxt
 dnsfq.o
 dnsfq
 hostname.o
diff -urN qmail-1.03/TARGETS.orig qmail-1.03-with-plesk-8.6/TARGETS.orig
--- qmail-1.03/TARGETS.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/TARGETS.orig	2008-08-26 03:06:45.000000000 +0200
@@ -0,0 +1,389 @@
+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
+tls.o
+ssl_timeoutio.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
+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
diff -urN qmail-1.03/alloc.c qmail-1.03-with-plesk-8.6/alloc.c
--- qmail-1.03/alloc.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/alloc.c	2008-08-26 03:06:45.000000000 +0200
@@ -4,7 +4,7 @@
 extern void free();
 
 #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */
-#define SPACE 4096 /* must be multiple of ALIGNMENT */
+#define SPACE 8192 /* must be multiple of ALIGNMENT */
 
 typedef union { char irrelevant[ALIGNMENT]; double d; } aligned;
 static aligned realspace[SPACE / ALIGNMENT];
diff -urN qmail-1.03/auto-gid.c qmail-1.03-with-plesk-8.6/auto-gid.c
--- qmail-1.03/auto-gid.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/auto-gid.c	2008-08-26 03:06:45.000000000 +0200
@@ -1,5 +1,4 @@
 #include <sys/types.h>
-#include <grp.h>
 #include "subfd.h"
 #include "substdio.h"
 #include "readwrite.h"
@@ -22,29 +21,19 @@
 {
   char *name;
   char *value;
-  struct group *gr;
-  char strnum[FMT_ULONG];
+  char *gid;
 
   name = argv[1];
   if (!name) _exit(100);
   value = argv[2];
   if (!value) _exit(100);
-
-  gr = getgrnam(value);
-  if (!gr) {
-    substdio_puts(subfderr,"fatal: unable to find group ");
-    substdio_puts(subfderr,value);
-    substdio_puts(subfderr,"\n");
-    substdio_flush(subfderr);
-    _exit(111);
-  }
-
-  strnum[fmt_ulong(strnum,(unsigned long) gr->gr_gid)] = 0;
+  gid = argv[3];
+  if (!gid) _exit(100);
 
   outs("int ");
   outs(name);
   outs(" = ");
-  outs(strnum);
+  outs(gid);
   outs(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
   _exit(0);
diff -urN qmail-1.03/auto-uid.c qmail-1.03-with-plesk-8.6/auto-uid.c
--- qmail-1.03/auto-uid.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/auto-uid.c	2008-08-26 03:06:45.000000000 +0200
@@ -1,5 +1,4 @@
 #include <sys/types.h>
-#include <pwd.h>
 #include "subfd.h"
 #include "substdio.h"
 #include "readwrite.h"
@@ -22,29 +21,19 @@
 {
   char *name;
   char *value;
-  struct passwd *pw;
-  char strnum[FMT_ULONG];
+  char *uid;
 
   name = argv[1];
   if (!name) _exit(100);
   value = argv[2];
   if (!value) _exit(100);
-
-  pw = getpwnam(value);
-  if (!pw) {
-    substdio_puts(subfderr,"fatal: unable to find user ");
-    substdio_puts(subfderr,value);
-    substdio_puts(subfderr,"\n");
-    substdio_flush(subfderr);
-    _exit(111);
-  }
-
-  strnum[fmt_ulong(strnum,(unsigned long) pw->pw_uid)] = 0;
+  uid = argv[3];
+  if (!uid) _exit(100);
 
   outs("int ");
   outs(name);
   outs(" = ");
-  outs(strnum);
+  outs(uid);
   outs(";\n");
   if (substdio_flush(&ss1) == -1) _exit(111);
   _exit(0);
diff -urN qmail-1.03/byte.h qmail-1.03-with-plesk-8.6/byte.h
--- qmail-1.03/byte.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/byte.h	2008-08-26 03:06:46.000000000 +0200
@@ -3,6 +3,8 @@
 
 extern unsigned int byte_chr();
 extern unsigned int byte_rchr();
+extern unsigned int byte_cspn();
+extern unsigned int byte_rcspn();
 extern void byte_copy();
 extern void byte_copyr();
 extern int byte_diff();
diff -urN qmail-1.03/byte_cspn.c qmail-1.03-with-plesk-8.6/byte_cspn.c
--- qmail-1.03/byte_cspn.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/byte_cspn.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,11 @@
+#include "byte.h"
+
+unsigned int byte_cspn(s,n,c)
+register char *s;
+register unsigned int n;
+register char *c;
+{
+  while(*c)
+    n = byte_chr(s,n,*c++);
+  return n;
+}
diff -urN qmail-1.03/byte_rcspn.c qmail-1.03-with-plesk-8.6/byte_rcspn.c
--- qmail-1.03/byte_rcspn.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/byte_rcspn.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,17 @@
+#include "byte.h"
+
+unsigned int byte_rcspn(s,n,c)
+register char *s;
+register unsigned int n;
+register char *c;
+{
+  unsigned int ret,pos,i;
+
+  for(ret = n,pos = 0;*c;++c) {
+    i = byte_rchr(s + pos,n - pos,*c) + pos;
+    if (i < n) ret = pos = i;
+  }
+
+  return ret;
+}
+
diff -urN qmail-1.03/cdbmake_add.c qmail-1.03-with-plesk-8.6/cdbmake_add.c
--- qmail-1.03/cdbmake_add.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/cdbmake_add.c	2008-08-26 03:06:46.000000000 +0200
@@ -1,3 +1,4 @@
+#include "alloc.h"
 #include "cdbmake.h"
 
 void cdbmake_init(cdbm)
diff -urN qmail-1.03/chkspawn.c qmail-1.03-with-plesk-8.6/chkspawn.c
--- qmail-1.03/chkspawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/chkspawn.c	2008-08-26 03:06:45.000000000 +0200
@@ -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/commands.c qmail-1.03-with-plesk-8.6/commands.c
--- qmail-1.03/commands.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/commands.c	2008-08-26 03:06:46.000000000 +0200
@@ -35,6 +35,6 @@
 
     for (i = 0;c[i].text;++i) if (case_equals(c[i].text,cmd.s)) break;
     c[i].fun(arg);
-    if (c[i].flush) c[i].flush();
+    if (c[i].flush) c[i].flush(0);
   }
 }
diff -urN qmail-1.03/commands.h qmail-1.03-with-plesk-8.6/commands.h
--- qmail-1.03/commands.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/commands.h	2008-08-26 03:06:46.000000000 +0200
@@ -3,8 +3,8 @@
 
 struct commands {
   char *text;
-  void (*fun)();
-  void (*flush)();
+  void (*fun)(char*);
+  void (*flush)(char*);
 } ;
 
 extern int commands();
diff -urN qmail-1.03/conf-cc qmail-1.03-with-plesk-8.6/conf-cc
--- qmail-1.03/conf-cc	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/conf-cc	2008-08-26 03:06:45.000000000 +0200
@@ -1,3 +1,3 @@
-cc -O2
+cc -O2 -DTLS=20040419
 
 This will be used to compile .c files.
diff -urN qmail-1.03/conf-spawn qmail-1.03-with-plesk-8.6/conf-spawn
--- qmail-1.03/conf-spawn	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/conf-spawn	2008-08-26 03:07:14.000000000 +0200
@@ -1,4 +1,4 @@
-120
+255
 
 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/date822fmt.c qmail-1.03-with-plesk-8.6/date822fmt.c
--- qmail-1.03/date822fmt.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/date822fmt.c	2008-08-26 03:06:46.000000000 +0200
@@ -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/dk.lib qmail-1.03-with-plesk-8.6/dk.lib
--- qmail-1.03/dk.lib	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/dk.lib	2008-08-26 03:19:58.000000000 +0200
@@ -0,0 +1 @@
+-ldomainkeys
diff -urN qmail-1.03/dns.c qmail-1.03-with-plesk-8.6/dns.c
--- qmail-1.03/dns.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/dns.c	2008-08-26 03:06:46.000000000 +0200
@@ -2,7 +2,13 @@
 #include <netdb.h>
 #include <sys/types.h>
 #include <netinet/in.h>
+
+#if defined(__APPLE__)
+#include <arpa/nameser_compat.h>
+#else
 #include <arpa/nameser.h>
+#endif
+
 #include <resolv.h>
 #include <errno.h>
 extern int res_query();
@@ -11,6 +17,7 @@
 extern int h_errno;
 #include "ip.h"
 #include "ipalloc.h"
+#include "strsalloc.h"
 #include "fmt.h"
 #include "alloc.h"
 #include "str.h"
@@ -21,14 +28,17 @@
 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];
 static struct ip_address ip;
+static stralloc txt = {0};
 unsigned short pref;
 
 static stralloc glue = {0};
@@ -45,18 +55,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 +91,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -179,6 +204,49 @@
  return 0;
 }
 
+static int findtxt(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   unsigned short txtpos;
+   unsigned char txtlen;
+
+   txt.len = 0;
+   for (txtpos = 0;txtpos < rrdlen;txtpos += txtlen)
+    {
+     txtlen = responsepos[txtpos++];
+     if (txtlen > rrdlen-txtpos) txtlen = rrdlen-txtpos;
+     if (!stralloc_catb(&txt,&responsepos[txtpos],txtlen)) return DNS_MEM;
+    }
+
+   responsepos += rrdlen;
+   return 1;
+ }
+
+ responsepos += rrdlen;
+ return 0;
+}
+
 void dns_init(flagsearch)
 int flagsearch;
 {
@@ -237,15 +305,18 @@
  return len;
 }
 
-int dns_ptr(sa,ip)
-stralloc *sa;
+static int dns_ptrplus(ssa,ip)
+strsalloc *ssa;
 struct ip_address *ip;
 {
+ stralloc sa = {0};
  int r;
 
- if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
- sa->len = iaafmt(sa->s,ip);
- switch(resolve(sa,T_PTR))
+ if (!stralloc_ready(&sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa.len = iaafmt(sa.s,ip);
+ r = resolve(&sa,T_PTR);
+ alloc_free(sa.s);
+ switch(r)
   {
    case DNS_MEM: return DNS_MEM;
    case DNS_SOFT: return DNS_SOFT;
@@ -256,25 +327,46 @@
    if (r == DNS_SOFT) return DNS_SOFT;
    if (r == 1)
     {
-     if (!stralloc_copys(sa,name)) return DNS_MEM;
-     return 0;
+     stralloc sa2 = {0};
+     if (!stralloc_copys(&sa2,name)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa2)) return DNS_MEM;
     }
   }
+ if (ssa->len) return 0;
  return DNS_HARD;
 }
 
+int dns_ptr(ssa,ip)
+strsalloc *ssa;
+struct ip_address *ip;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_ptrplus(ssa,ip);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
+
+
 static int dns_ipplus(ia,sa,pref)
 ipalloc *ia;
 stralloc *sa;
 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 +385,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 +414,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 +426,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;
@@ -398,3 +496,49 @@
  alloc_free(mx);
  return flagsoft;
 }
+
+
+static int dns_txtplus(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+
+ switch(resolve(sa,T_TXT)) 
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findtxt(T_TXT)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     stralloc sa = {0};
+     if (!stralloc_copy(&sa,&txt)) return DNS_MEM;
+     if (!strsalloc_append(ssa,&sa)) return DNS_MEM;
+    }
+  }
+ if (ssa->len) return 0;
+ return DNS_HARD;
+}
+
+int dns_txt(ssa,sa)
+strsalloc *ssa;
+stralloc *sa;
+{
+ int r;
+ int j;
+
+ if (!strsalloc_readyplus(ssa,0)) return DNS_MEM;
+ ssa->len = 0;
+ r = dns_txtplus(ssa,sa);
+ if (r < 0)
+  {
+   for (j = 0;j < ssa->len;++j)
+    alloc_free(ssa->sa[j].s);
+   ssa->len = 0;
+  }
+ return r;
+}
diff -urN qmail-1.03/dns.c.orig qmail-1.03-with-plesk-8.6/dns.c.orig
--- qmail-1.03/dns.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/dns.c.orig	2008-08-26 03:06:45.000000000 +0200
@@ -0,0 +1,428 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#if defined(__APPLE__)
+#include <arpa/nameser_compat.h>
+#else
+#include <arpa/nameser.h>
+#endif
+
+#include <resolv.h>
+#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"
+#include "alloc.h"
+#include "str.h"
+#include "stralloc.h"
+#include "dns.h"
+#include "case.h"
+
+static unsigned short getshort(c) unsigned char *c;
+{ unsigned short u; u = c[0]; return (u << 8) + c[1]; }
+
+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];
+static struct ip_address ip;
+unsigned short pref;
+
+static stralloc glue = {0};
+
+static int (*lookup)() = res_query;
+
+static int resolve(domain,type)
+stralloc *domain;
+int type;
+{
+ int n;
+ int i;
+
+ errno = 0;
+ if (!stralloc_copy(&glue,domain)) return DNS_MEM;
+ if (!stralloc_0(&glue)) return DNS_MEM;
+ 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;
+  }
+ responseend = response.buf + responselen;
+ responsepos = response.buf + sizeof(HEADER);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
+ while (n-- > 0)
+  {
+   i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+   if (i < 0) return DNS_SOFT;
+   responsepos += i;
+   i = responseend - responsepos;
+   if (i < QFIXEDSZ) return DNS_SOFT;
+   responsepos += QFIXEDSZ;
+  }
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
+ return 0;
+}
+
+static int findname(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   if (dn_expand(response.buf,responseend,responsepos,name,MAXDNAME) < 0)
+     return DNS_SOFT;
+   responsepos += rrdlen;
+   return 1;
+  }
+   
+ responsepos += rrdlen;
+ return 0;
+}
+
+static int findip(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   if (rrdlen < 4)
+     return DNS_SOFT;
+   ip.d[0] = responsepos[0];
+   ip.d[1] = responsepos[1];
+   ip.d[2] = responsepos[2];
+   ip.d[3] = responsepos[3];
+   responsepos += rrdlen;
+   return 1;
+  }
+   
+ responsepos += rrdlen;
+ return 0;
+}
+
+static int findmx(wanttype)
+int wanttype;
+{
+ unsigned short rrtype;
+ unsigned short rrdlen;
+ int i;
+
+ if (numanswers <= 0) return 2;
+ --numanswers;
+ if (responsepos == responseend) return DNS_SOFT;
+
+ i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
+ if (i < 0) return DNS_SOFT;
+ responsepos += i;
+
+ i = responseend - responsepos;
+ if (i < 4 + 3 * 2) return DNS_SOFT;
+   
+ rrtype = getshort(responsepos);
+ rrdlen = getshort(responsepos + 8);
+ responsepos += 10;
+
+ if (rrtype == wanttype)
+  {
+   if (rrdlen < 3)
+     return DNS_SOFT;
+   pref = (responsepos[0] << 8) + responsepos[1];
+   if (dn_expand(response.buf,responseend,responsepos + 2,name,MAXDNAME) < 0)
+     return DNS_SOFT;
+   responsepos += rrdlen;
+   return 1;
+  }
+   
+ responsepos += rrdlen;
+ return 0;
+}
+
+void dns_init(flagsearch)
+int flagsearch;
+{
+ res_init();
+ if (flagsearch) lookup = res_search;
+}
+
+int dns_cname(sa)
+stralloc *sa;
+{
+ int r;
+ int loop;
+ for (loop = 0;loop < 10;++loop)
+  {
+   if (!sa->len) return loop;
+   if (sa->s[sa->len - 1] == ']') return loop;
+   if (sa->s[sa->len - 1] == '.') { --sa->len; continue; }
+   switch(resolve(sa,T_ANY))
+    {
+     case DNS_MEM: return DNS_MEM;
+     case DNS_SOFT: return DNS_SOFT;
+     case DNS_HARD: return loop;
+     default:
+       while ((r = findname(T_CNAME)) != 2)
+	{
+	 if (r == DNS_SOFT) return DNS_SOFT;
+	 if (r == 1)
+	  {
+	   if (!stralloc_copys(sa,name)) return DNS_MEM;
+	   break;
+	  }
+	}
+       if (r == 2) return loop;
+    }
+  }
+ return DNS_HARD; /* alias loop */
+}
+
+#define FMT_IAA 40
+
+static int iaafmt(s,ip)
+char *s;
+struct ip_address *ip;
+{
+ unsigned int i;
+ unsigned int len;
+ len = 0;
+ i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i;
+ i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i;
+ return len;
+}
+
+int dns_ptr(sa,ip)
+stralloc *sa;
+struct ip_address *ip;
+{
+ int r;
+
+ if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM;
+ sa->len = iaafmt(sa->s,ip);
+ switch(resolve(sa,T_PTR))
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findname(T_PTR)) != 2)
+  {
+   if (r == DNS_SOFT) return DNS_SOFT;
+   if (r == 1)
+    {
+     if (!stralloc_copys(sa,name)) return DNS_MEM;
+     return 0;
+    }
+  }
+ return DNS_HARD;
+}
+
+static int dns_ipplus(ia,sa,pref)
+ipalloc *ia;
+stralloc *sa;
+int pref;
+{
+ int r;
+ struct ip_mx ix = {0};
+
+ if (!stralloc_copy(&glue,sa)) return DNS_MEM;
+ if (!stralloc_0(&glue)) return DNS_MEM;
+ if (glue.s[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;
+     return 0;
+    }
+ }
+
+ switch(resolve(sa,T_A))
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return DNS_HARD;
+  }
+ while ((r = findip(T_A)) != 2)
+  {
+   ix.ip = ip;
+   ix.pref = pref;
+   if (r == DNS_SOFT) return DNS_SOFT;
+   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;
+}
+
+int dns_ip(ia,sa)
+ipalloc *ia;
+stralloc *sa;
+{
+ if (!ipalloc_readyplus(ia,0)) return DNS_MEM;
+ ia->len = 0;
+ return dns_ipplus(ia,sa,0);
+}
+
+int dns_mxip(ia,sa,random)
+ipalloc *ia;
+stralloc *sa;
+unsigned long random;
+{
+ int r;
+ struct mx { stralloc sa; unsigned short p; } *mx;
+ struct ip_mx ix = {0};
+ int nummx;
+ int i;
+ int j;
+ int flagsoft;
+
+ if (!ipalloc_readyplus(ia,0)) return DNS_MEM;
+ ia->len = 0;
+
+ if (!stralloc_copy(&glue,sa)) return DNS_MEM;
+ if (!stralloc_0(&glue)) return DNS_MEM;
+ if (glue.s[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;
+     return 0;
+    }
+ }
+
+ switch(resolve(sa,T_MX))
+  {
+   case DNS_MEM: return DNS_MEM;
+   case DNS_SOFT: return DNS_SOFT;
+   case DNS_HARD: return dns_ip(ia,sa);
+  }
+
+ mx = (struct mx *) alloc(numanswers * sizeof(struct mx));
+ if (!mx) return DNS_MEM;
+ nummx = 0;
+
+ while ((r = findmx(T_MX)) != 2)
+  {
+   if (r == DNS_SOFT) { alloc_free(mx); return DNS_SOFT; }
+   if (r == 1)
+    {
+     mx[nummx].p = pref;
+     mx[nummx].sa.s = 0;
+     if (!stralloc_copys(&mx[nummx].sa,name))
+      {
+       while (nummx > 0) alloc_free(mx[--nummx].sa.s);
+       alloc_free(mx); return DNS_MEM;
+      }
+     ++nummx;
+    }
+  }
+
+ if (!nummx) return dns_ip(ia,sa); /* e.g., CNAME -> A */
+
+ flagsoft = 0;
+ while (nummx > 0)
+  {
+   unsigned long numsame;
+
+   i = 0;
+   numsame = 1;
+   for (j = 1;j < nummx;++j)
+     if (mx[j].p < mx[i].p)
+      {
+       i = j;
+       numsame = 1;
+      }
+     else if (mx[j].p == mx[i].p)
+      {
+       ++numsame;
+       random = random * 69069 + 1;
+       if ((random / 2) < (2147483647 / numsame))
+         i = j;
+      }
+
+   switch(dns_ipplus(ia,&mx[i].sa,mx[i].p))
+    {
+     case DNS_MEM: case DNS_SOFT:
+       flagsoft = 1; break;
+    }
+
+   alloc_free(mx[i].sa.s);
+   mx[i] = mx[--nummx];
+  }
+
+ alloc_free(mx);
+ return flagsoft;
+}
diff -urN qmail-1.03/dns.h qmail-1.03-with-plesk-8.6/dns.h
--- qmail-1.03/dns.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/dns.h	2008-08-26 03:06:46.000000000 +0200
@@ -10,5 +10,6 @@
 int dns_mxip();
 int dns_ip();
 int dns_ptr();
+int dns_txt();
 
 #endif
diff -urN qmail-1.03/dnsfq.c qmail-1.03-with-plesk-8.6/dnsfq.c
--- qmail-1.03/dnsfq.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/dnsfq.c	2008-08-26 03:06:46.000000000 +0200
@@ -5,15 +5,19 @@
 #include "dnsdoe.h"
 #include "ip.h"
 #include "ipalloc.h"
+#include "strsalloc.h"
 #include "exit.h"
 
 stralloc sa = {0};
+strsalloc ssa = {0};
 ipalloc ia = {0};
 
 void main(argc,argv)
 int argc;
 char **argv;
 {
+ int j;
+
  if (!argv[1]) _exit(100);
 
  if (!stralloc_copys(&sa,argv[1]))
@@ -25,8 +29,11 @@
   {
    substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100);
   }
- dnsdoe(dns_ptr(&sa,&ia.ix[0].ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ia.ix[0].ip));
+ for(j = 0;j < ssa.len;++j)
+  {
+   substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+   substdio_putsflush(subfdout,"\n");
+  }
  _exit(0);
 }
diff -urN qmail-1.03/dnsptr.c qmail-1.03-with-plesk-8.6/dnsptr.c
--- qmail-1.03/dnsptr.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/dnsptr.c	2008-08-26 03:06:46.000000000 +0200
@@ -6,22 +6,28 @@
 #include "dns.h"
 #include "dnsdoe.h"
 #include "ip.h"
+#include "strsalloc.h"
 #include "exit.h"
 
-stralloc sa = {0};
+strsalloc ssa = {0};
 struct ip_address ip;
 
 void main(argc,argv)
 int argc;
 char **argv;
 {
+ int j;
+
  if (!argv[1]) _exit(100);
 
  ip_scan(argv[1],&ip);
 
  dns_init(0);
- dnsdoe(dns_ptr(&sa,&ip));
- substdio_putflush(subfdout,sa.s,sa.len);
- substdio_putsflush(subfdout,"\n");
+ dnsdoe(dns_ptr(&ssa,&ip));
+ for(j = 0;j < ssa.len;++j)
+  {
+   substdio_putflush(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+   substdio_putsflush(subfdout,"\n");
+  }
  _exit(0);
 }
diff -urN qmail-1.03/dnstxt.c qmail-1.03-with-plesk-8.6/dnstxt.c
--- qmail-1.03/dnstxt.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/dnstxt.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,32 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "str.h"
+#include "scan.h"
+#include "dns.h"
+#include "dnsdoe.h"
+#include "strsalloc.h"
+#include "exit.h"
+
+strsalloc ssa = {0};
+stralloc sa = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+ int j;
+
+ if (!argv[1]) _exit(100);
+
+ if (!stralloc_copys(&sa, argv[1]))
+  { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); }
+ dns_init(0);
+ dnsdoe(dns_txt(&ssa,&sa));
+ for (j = 0;j < ssa.len;++j)
+  {
+   substdio_put(subfdout,ssa.sa[j].s,ssa.sa[j].len);
+   substdio_putsflush(subfdout,"\n");
+  }
+ _exit(0);
+}
diff -urN qmail-1.03/domainkeys.h qmail-1.03-with-plesk-8.6/domainkeys.h
--- qmail-1.03/domainkeys.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/domainkeys.h	2008-08-26 03:11:55.000000000 +0200
@@ -0,0 +1,377 @@
+/* This file is automatically created from the corresponding .c file */
+/* Do not change this file; change the .c file instead. */
+/* This is libdomainkeys.  It's Copyright (c) 2004 Yahoo, Inc.
+ * This code incorporates intellectual property owned by
+ * Yahoo! and licensed pursuant to the Yahoo! DomainKeys Public License
+ * Agreement: http://domainkeys.sourceforge.net/license/softwarelicense1-0.html
+ */
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+
+#ifdef SWIG
+%module domainkeys
+%{
+#include "domainkeys.h"
+%}
+#endif
+
+#include "dktrace.h"
+
+/* Performance/Debug options.
+ * Uncomment below or use -D switch in gcc
+ * DK_DEBUG Dumps whatever dkhash() hashes in to stderr and turns on
+ *  some debug warnings that should never happen
+ * DK_HASH_BUFF Enables code that uses a buffer when processing the
+ *  canocalized message, reducing calls to the crypto library (from dkhash()),
+ *  but can use up slightly more memory
+*/
+//#define DK_DEBUG 1
+#define DK_HASH_BUFF 1
+
+
+#define DKMARK ('D' | 'K'<<8 | 'E'<<16 | 'Y'<<24)
+#define DK_SIGNING_SIGN 0
+#define DK_SIGNING_VERIFY 1
+#define DK_SIGNING_NOSIGN 2
+#define DK_SIGNING_NOVERIFY 3
+#define DK_MALLOC(s)  OPENSSL_malloc(s)
+#define DK_MFREE(s)   OPENSSL_free(s); s = NULL;
+#define DKERR(x) ((dk->errline=__LINE__),(dk->errfile=__FILE__),(x))
+#define DK_BLOCK 1024 //default size of malloc'd block
+
+/*
+ * Option Flags for dk_setopts
+ * OR together or run dk_setopts several times
+ * All option flags are OFF by default
+*/
+#define DKOPT_TRACE_h 0x01 //enables tracking character count in pre-canon header
+#define DKOPT_TRACE_H 0x02 //enables tracking character count in post-canon header
+#define DKOPT_TRACE_b 0x04 //enables tracking character count in pre-canon body
+#define DKOPT_TRACE_B 0x08 //enables tracking character count in post-canon header
+#define DKOPT_RDUPE 0x10 //enables skipping duplicate headers when generateing a signature
+
+typedef enum
+{
+  DK_STAT_OK, /* Function completed successfully */
+  DK_STAT_BADSIG, /* Signature was available but failed to verify against domain specified key */
+  DK_STAT_NOSIG, /* No signature available in message */
+  DK_STAT_NOKEY, /* No public key available (permanent failure) */
+  DK_STAT_BADKEY, /* Unusable key, public if verifying, private if signing */
+  DK_STAT_CANTVRFY, /* Cannot get domain key to verify signature (temporary failure) */
+  DK_STAT_SYNTAX, /* Message is not valid syntax. Signature could not be created/checked */
+  DK_STAT_NORESOURCE, /* Could not get critical resource (temporary failure) */
+  DK_STAT_ARGS, /* Arguments are not usable. */
+  DK_STAT_REVOKED,    /* Key has been revoked. */
+  DK_STAT_INTERNAL, /* cannot call this routine in this context.  Internal error. */
+  DK_STAT_GRANULARITY, /* Granularity mismatch: sender doesn't match g= option. */
+} DK_STAT;
+
+typedef enum
+{
+  DK_FLAG_TESTING = 1,    /* set when in testing mode. */
+  DK_FLAG_SIGNSALL = 2,   /* domain signs all outgoing email. */
+  DK_FLAG_SET = 4,    /* flags set from a successful DNS query */
+  DK_FLAG_G = 8,    /* g tag was present in the selector. */
+} DK_FLAGS;
+typedef enum
+{
+  DK_TXT_KEY = 0,
+  DK_TXT_POLICY
+} DK_TXT;
+
+typedef enum
+{
+  DK_CANON_SIMPLE = 0,
+  DK_CANON_NOFWS = 1,
+} DK_CANON;
+/* STARTSTRUCT */
+typedef struct
+{
+
+} DK_LIB;
+/* STOPSTRUCT */
+
+//UnixWare Fix -Tim
+/* STARTSTRUCT */
+typedef struct
+{
+} DK;
+/* STOPSTRUCT */
+
+
+/* returns the source file from which an error was returned. */
+char * dk_errfile(DK *dk)
+;
+
+
+/* returns the source line number from which an error was returned. */
+int dk_errline(DK *dk)
+;
+
+
+/* Per-process, one-time initialization
+ * Returns library structure for subsequent dk_sign or dk_verify calls.
+ * Consult statp before using.
+ *
+ * When terminating the PROCESS its a good idea to call dk_shutdown()
+ * When terminating a THREAD it's a good idea to call ERR_remove_state(0); defined in <openssl/err.h>
+ * NOTE: DK_LIB pointers are safe to use over multiple threads
+ *       DK pointers are NOT safe to use over multiple threads
+ */
+DK_LIB *dk_init(DK_STAT *statp)
+;
+
+
+/* Per-process, one-time cleanup
+ * Should be called just before the application ends.
+ * the dklib pointer is not valid anymore after this call
+ * This function should be called even if dk_init failed.
+ * It's safe to call dk_shutdown with a NULL pointer
+ */
+void dk_shutdown(DK_LIB * dklib)
+;
+
+
+/* Set dk options, use instead of dk_remdupe and dk_enable_trace
+ * Can be called multiple times.
+ * use after dk_sign()/dk_verify()
+ *
+ * the bits field can be an OR of any of the following
+ *DKOPT_TRACE_h Trace pre-canon header
+ *DKOPT_TRACE_H Trace post-canon header
+ *DKOPT_TRACE_b Trace pre-canon body
+ *DKOPT_TRACE_B Trace post-canon body
+ *DKOPT_RDUPE   Exclude duplicate headers from hash (Signing only)
+ */
+DK_STAT dk_setopts(DK *dk, int bits)
+;
+
+
+/* returns the int holding the options set
+ * See dk_setopts for bit flags
+ */
+int dk_getopts(DK *dk)
+;
+
+
+/* DEPRECATED in favor of calling dk_setopts().
+ * Enables character trace tracking
+ *
+ * use after dk_sign()/dk_verify()
+ */
+DK_STAT dk_enable_trace(DK *dk)
+;
+
+
+/* Prints trace table to *store variable (char string)
+ * *dk is the container for the table
+ * *store is a pointer to a character array to output to
+ * store_size is the size of the character array *store
+ *
+ */
+DK_STAT dk_get_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
+;
+
+
+/* Prints difference trace table to *store variable (char string)
+ * *dk is the container for the table
+ * *store is a pointer to a character array to output to
+ * store_size is the size of the character array *store
+ * return DK_STAT_NOSIG if no DK-Trace header was found
+ */
+DK_STAT dk_compare_trace(DK *dk, DK_TRACE_TYPE type, char *store, int store_size)
+;
+
+
+/* Sets the DNS key/policy record manually (no DNS lookup)
+ * txtrecord needs to be set to "e=perm;" to force a permanent DNS failure
+ * txtrecord needs to be set to "e=temp;" to force a temporary DNS failure
+ * Valid DK_TXT types are:
+ * DK_TXT_KEY (normal selector record; for <selctor>._domainkey.<domain>)
+ * DK_TXT_POLICY (domain policy record; for _domainkey.<domain>)
+ */
+DK_STAT dk_settxt(DK *dk, DK_TXT recordtype, const char *txtrecord)
+;
+
+
+/* Per-message, may be threaded.
+ * canon is one of DK_CANON_*.
+ * Returns state structure for operation.  Consult statp before using.
+ */
+DK *dk_sign(DK_LIB *dklib, DK_STAT *statp, int canon)
+;
+
+
+/* Per-message, may be threaded.
+ * Returns state structure for operation.  Consult statp before using.
+ */
+DK *dk_verify(DK_LIB *dklib, DK_STAT *statp)
+;
+
+
+/* DEPRECATED in favor of calling dk_setopts()
+ * set option to remove dupe headers
+ * should be called after dk_sign();
+ * any int NOT 0 turns dupe removal on
+ */
+DK_STAT dk_remdupe(DK *dk,int i)
+;
+
+
+/* Returns the policy flags belonging to the signing domain.
+ * Sender: overrides From:, and the d= entry in the DK-Sig overrides both.
+ * If the policy flags were not successfully fetched, DK_FLAG_SET will not
+ * be set.
+ */
+DK_FLAGS dk_policy(DK *dk)
+;
+
+
+/* Copies the header names that were signed into the pointer.
+ * Returns the number of bytes copied.
+ * ptr may be NULL, in which case the bytes are just counted, not copied.
+ * Feel free to call this twice; once to get the length, and again to
+ * copy the data.
+ * NOTE: If the return value is 0 then an error occured.
+ *	It's a good idea to check for this
+ */
+int dk_headers(DK *dk, char *ptr)
+;
+
+
+/* Must NOT include dots inserted for SMTP encapsulation.
+ * Must NOT include CRLF.CRLF which terminates the message.
+ * Otherwise must be exactly that which is sent or received over the SMTP session.
+ * May be called multiple times (not necessary to read an entire message into memory).
+ */
+DK_STAT dk_message(DK *dk, const unsigned char *ptr, size_t len)
+;
+
+
+/* DEPRECATED in favor of calling dk_address().
+ * Returns a pointer to a null-terminated domain name portion of an RFC 2822 address.
+ * If a Sender: was encountered, it returns that domain.  Otherwise,
+ * if a From: was encountered, it returns that domain.  Otherwise,
+ * return NULL.
+ * return NULL if no domain name found in the address.
+ * return NULL if the dk is unusable for any reason.
+ * return NULL if the address is unusable for any reason.
+ */
+char *dk_from(DK *dk)
+;
+
+
+/* Returns a pointer to the selector name used or NULL if there isn't one
+ * Added by rjp
+ */
+const char *dk_selector(DK *dk)
+;
+
+
+/* Returns a pointer to the domain name used or NULL if there isn't one
+ */
+const char *dk_domain(DK *dk)
+;
+
+
+/*
+ * Returns a pointer to a string which begins with "N", "S", or "F",
+ * corresponding to None, Sender: and From:, respectively.
+ * This single character is followed by a null-terminated RFC 2822 address.
+ * The first character is "N" if no valid address has been seen yet,
+ * "S" if the address came from the Sender: field, and "F" if the
+ * address came from the From: field.
+ */
+char *dk_address(DK *dk)
+;
+
+
+/*
+ * Returns a pointer to a null-terminated string containing the granularity
+ * value found in the selector DNS record, if any, but only after dk_end
+ * has been called. Otherwise returns NULL.
+ */
+char *dk_granularity(DK *dk)
+;
+
+
+/*
+ * Called at end-of-message (before response to DATA-dot, if synchronous with SMTP session).
+ * If verifying, returns signature validity.
+ * This does not calculate the signature.  Call dk_getsig() for that.
+ * Flags are returned indirectly through dkf.
+ * If you pass in NULL for dkf, the flags will not be fetched.
+ * If there is a DK-Sig line, the d= entry will be used to fetch the flags.
+ * Otherwise the Sender: domain will be used to fetch the flags.
+ * Otherwise the From: domain will be used to fetch the flags.
+ *
+ * NOTE: If for some reason dk_end() returns an error (!DK_STAT_OK) dk_policy() should be called
+ * to get the domain signing policy (o=) and handle accordingly.
+ * dkf (selector flags) wont be set if dk_end() returns
+ * DK_STAT_NOSIG
+ * DK_STAT_NOKEY
+ * DK_STAT_SYNTAX
+ * DK_STAT_NORESOURCE
+ * DK_STAT_BADKEY
+ * DK_STAT_CANTVERIFY
+ */
+DK_STAT dk_end(DK *dk, DK_FLAGS *dkf)
+;
+
+
+/*
+ * DEPRECATED in favor of calling dk_end and dk_policy() directly.
+ * If you pass in NULL for dkf, the policy flags will not be fetched.
+ * If the message verified okay, the policy flags will not be fetched.
+ */
+DK_STAT dk_eom(DK *dk, DK_FLAGS *dkf)
+;
+
+
+/*
+ *
+ * privatekey is the private key used to create the signature; It should contain
+ * the entire contents of a PEM-format private key file, thusly it will begin with
+ * -----BEGIN RSA PRIVATE KEY-----.  It should be null-terminated.
+ */
+size_t dk_siglen(void *privatekey)
+;
+
+
+/*
+ * Sets buf to a null-terminated string.
+ * If the message is being signed, signature is stored in the buffer.
+ * If the message is being verified, returns DK_STAT_INTERNAL.
+ * privatekey is the private key used to create the signature; It should contain
+ * the entire contents of a PEM-format private key file, thus it will begin with
+ * -----BEGIN RSA PRIVATE KEY-----.  It should be null-terminated.
+ * If you pass in NULL for buf, you'll get back DK_STAT_NORESOURCE.
+ * If len is not big enough, you'll get back DK_STAT_NORESOURCE.
+ */
+DK_STAT dk_getsig(DK *dk, void *privatekey, unsigned char buf[], size_t len)
+;
+
+
+/*
+ * Free all resources associated with this message.
+ * dk is no longer usable.
+ * if doClearErrState != 0, the OpenSSL ErrorState is freed.
+ * Set clearErrState=0 if you use other openssl functions and
+ * want to call openssl's ERR_remove_state(0) by yourself
+ * ERR_remove_state(0) is declared in <openssl/err.h>
+ */
+DK_STAT dk_free(DK *dk, int doClearErrState)
+;
+
+
+/*
+ * return a pointer to a string which describes st.
+ * The string is structured.  All the characters up to the first colon
+ * contain the name of the DK_STAT constant.  From there to the end of
+ * string is a human-readable description of the error.
+ */
+const char *DK_STAT_to_string(DK_STAT st)
+;
+
+
diff -urN qmail-1.03/error.h qmail-1.03-with-plesk-8.6/error.h
--- qmail-1.03/error.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/error.h	2008-08-26 03:06:45.000000000 +0200
@@ -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/hier.c qmail-1.03-with-plesk-8.6/hier.c
--- qmail-1.03/hier.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/hier.c	2008-08-26 03:06:46.000000000 +0200
@@ -4,8 +4,20 @@
 #include "fmt.h"
 #include "fifo.h"
 
+#include <stdlib.h>
+
 char buf[100 + FMT_ULONG];
 
+char *basedir;
+void setbasedir(void)
+{
+	basedir = getenv("LOCALDIST");
+	if (!basedir)
+		basedir = auto_qmail;
+}
+
+#define auto_qmail basedir
+
 void dsplit(base,uid,mode)
 char *base; /* must be under 100 bytes */
 int uid;
@@ -29,6 +41,8 @@
 
 void hier()
 {
+  setbasedir();
+
   h(auto_qmail,auto_uido,auto_gidq,0755);
 
   d(auto_qmail,"control",auto_uido,auto_gidq,0755);
@@ -55,6 +69,8 @@
   d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700);
 
   dsplit("queue/mess",auto_uidq,0750);
+  dsplit("queue/todo",auto_uidq,0750);
+  dsplit("queue/intd",auto_uidq,0700);
   dsplit("queue/info",auto_uids,0700);
   dsplit("queue/local",auto_uids,0700);
   dsplit("queue/remote",auto_uids,0700);
@@ -64,21 +80,26 @@
   z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600);
   p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622);
 
-  c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","home",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0555);
 
   c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
+#if !(defined(__APPLE__) && defined(__ppc__))
   c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
+#else
+  c(auto_qmail,"doc","SENDMAIL.txt",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.txt",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644);
   c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644);
@@ -100,49 +121,50 @@
   c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644);
 
   c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711);
-  c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700);
-  c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700);
-  c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-dk",auto_uidq,auto_gidq,04711);
+  c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0555);
   c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711);
   c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
-  c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
-  c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711);
-  c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
-  c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","except",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0555);
+  c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0555);
 
   c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
@@ -150,7 +172,9 @@
   c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644);
+#if !defined(SKIP_CONFLICTING_MANUALS)
   c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644);
@@ -172,7 +196,9 @@
   c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644);
 
+#if !defined(SKIP_CONFLICTING_MANUALS)
   c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644);
@@ -180,7 +206,9 @@
   c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644);
+#if !defined(SKIP_CONFLICTING_MANUALS)
   c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644);
diff -urN qmail-1.03/hier.c.orig qmail-1.03-with-plesk-8.6/hier.c.orig
--- qmail-1.03/hier.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/hier.c.orig	1998-06-15 12:53:16.000000000 +0200
@@ -0,0 +1,252 @@
+#include "auto_qmail.h"
+#include "auto_split.h"
+#include "auto_uids.h"
+#include "fmt.h"
+#include "fifo.h"
+
+char buf[100 + FMT_ULONG];
+
+void dsplit(base,uid,mode)
+char *base; /* must be under 100 bytes */
+int uid;
+int mode;
+{
+  char *x;
+  unsigned long i;
+
+  d(auto_qmail,base,uid,auto_gidq,mode);
+
+  for (i = 0;i < auto_split;++i) {
+    x = buf;
+    x += fmt_str(x,base);
+    x += fmt_str(x,"/");
+    x += fmt_ulong(x,i);
+    *x = 0;
+
+    d(auto_qmail,buf,uid,auto_gidq,mode);
+  }
+}
+
+void hier()
+{
+  h(auto_qmail,auto_uido,auto_gidq,0755);
+
+  d(auto_qmail,"control",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"users",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"bin",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"boot",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"doc",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/cat7",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/cat8",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/man1",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/man5",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/man7",auto_uido,auto_gidq,0755);
+  d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755);
+
+  d(auto_qmail,"alias",auto_uida,auto_gidq,02755);
+
+  d(auto_qmail,"queue",auto_uidq,auto_gidq,0750);
+  d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700);
+  d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700);
+  d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750);
+  d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700);
+
+  dsplit("queue/mess",auto_uidq,0750);
+  dsplit("queue/info",auto_uids,0700);
+  dsplit("queue/local",auto_uids,0700);
+  dsplit("queue/remote",auto_uids,0700);
+
+  d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750);
+  z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644);
+  z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600);
+  p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622);
+
+  c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755);
+
+  c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.maildir",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.mbox",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","INSTALL.vsm",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","TEST.deliver",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","TEST.receive",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","REMOVE.sendmail",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","REMOVE.binmail",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.local2alias",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.local2ext",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.local2local",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.local2rem",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.local2virt",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.nullclient",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644);
+
+  c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711);
+  c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700);
+  c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711);
+  c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755);
+  c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755);
+
+  c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-control.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-control.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-header.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-header.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-log.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-log.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","qmail-users.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644);
+
+  c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man7","qmail-limits.7",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat7","qmail-limits.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644);
+
+  c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","bouncesaying.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","maildirwatch.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","maildirwatch.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","mailsubj.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","mailsubj.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","qreceipt.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","qreceipt.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","qbiff.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","qbiff.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","preline.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","preline.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man1","tcp-env.1",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat1","tcp-env.0",auto_uido,auto_gidq,0644);
+
+  c(auto_qmail,"man/man8","qmail-local.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-local.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-lspawn.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-lspawn.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-getpw.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-getpw.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-remote.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-remote.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-rspawn.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-rspawn.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-clean.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-clean.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-send.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-send.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-start.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-start.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","splogger.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","splogger.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-queue.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-queue.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-inject.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-pw2u.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-qread.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-qread.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-qstat.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-qstat.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-tcpok.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-tcpok.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-tcpto.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-tcpto.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-pop3d.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-pop3d.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-popup.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-popup.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-qmqpc.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-qmqpc.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-qmqpd.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-qmqpd.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-qmtpd.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-qmtpd.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-smtpd.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644);
+  c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644);
+}
diff -urN qmail-1.03/install-big.c qmail-1.03-with-plesk-8.6/install-big.c
--- qmail-1.03/install-big.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/install-big.c	2008-08-26 03:06:45.000000000 +0200
@@ -172,7 +172,9 @@
   c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644);
 
+#if !defined(SKIP_CONFLICTING_MANUALS)
   c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644);
@@ -180,7 +182,9 @@
   c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644);
+#if !defined(SKIP_CONFLICTING_MANUALS)
   c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644);
+#endif
   c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644);
diff -urN qmail-1.03/install.c qmail-1.03-with-plesk-8.6/install.c
--- qmail-1.03/install.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/install.c	2008-08-26 03:06:45.000000000 +0200
@@ -1,3 +1,9 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "auto_uids.h"
 #include "substdio.h"
 #include "strerr.h"
 #include "error.h"
@@ -11,17 +17,130 @@
 
 int fdsourcedir = -1;
 
+typedef struct {
+    const char* qu_name;
+    int qu_id;
+} qmail_uid_t;
+
+qmail_uid_t *qmail_uids = NULL;
+qmail_uid_t *qmail_gids = NULL;
+
+void init_ids(qmail_uid_t** dst, const qmail_uid_t* src, size_t size)
+{
+  int i;
+
+  (*dst) = malloc(size*sizeof(qmail_uid_t));
+  for (i=0; i < size; i++) {
+    if (src[i].qu_name != NULL) {
+      (*dst)[i].qu_name = strdup(src[i].qu_name);
+    } else {
+      (*dst)[i].qu_name = NULL;
+    }
+    (*dst)[i].qu_id = src[i].qu_id;
+  }
+}
+
+static const char* get_name(const qmail_uid_t* table, int id)
+{
+  const qmail_uid_t* iter;
+
+  for (iter = table; iter->qu_name != NULL; iter++) {
+    if (iter->qu_id == id)
+      return iter->qu_name;
+  }
+
+  fprintf(stderr, "No user/group with id=%d\n", id);
+  exit(1);
+}
+
+static FILE* out = NULL;
+void write_log(int uid, int gid, const char* path, const char* dir, const char* file)
+{
+  const char* user;
+  const char* group;
+  static char* prefix = NULL;
+  static size_t prefix_len = 0;
+  const qmail_uid_t uids[] = {
+    {"alias", auto_uida},
+    {"qmaild", auto_uidd},
+    {"qmaill", auto_uidl},
+    {"root", auto_uido},
+    {"qmailp", auto_uidp},
+    {"qmailq", auto_uidq},
+    {"qmailr", auto_uidr},
+    {"qmails", auto_uids},
+    {NULL, 0}
+  };
+  const qmail_uid_t gids[] = {
+    {"0", 0},
+    {"qmail", auto_gidq},
+    {"nofiles", auto_gidn},
+    {NULL, 0}
+  };
+
+  if (uid == 0 && gid == 0)
+    return;
+
+  if (qmail_uids == NULL) {
+    init_ids(&qmail_uids, uids, sizeof(uids)/sizeof(qmail_uid_t));
+    init_ids(&qmail_gids, gids, sizeof(gids)/sizeof(qmail_uid_t));
+  }
+
+  if (out == NULL) {
+    char* out_filename = getenv("FILE_LIST");
+    if (out_filename == NULL) {
+      out = stderr;
+    } else {
+      out = fopen(out_filename, "w");
+      if (out == NULL) {
+        perror("Cannot open $FILE_LIST for append");
+        fprintf(stderr, "File: %s\n", out_filename);
+        exit(1);
+      }
+    }
+  }
+
+  if (prefix == NULL) {
+    prefix = getenv("FILE_LIST_PREFIX");
+    if (prefix == NULL) {
+	prefix = "";
+    } else {
+	prefix_len = strlen(prefix);
+    }
+  }
+
+  user = get_name(qmail_uids, uid);
+  group = get_name(qmail_gids, gid);
+  if (strncmp(path, prefix, prefix_len) == 0) {
+    path += prefix_len;
+  }
+  if (file == NULL) {
+    fprintf(out, "%s,%s,%s\n", user, group, path);
+  } else if (dir == NULL) {
+    fprintf(out, "%s,%s,%s/%s\n", user, group, path, file);
+  } else {
+    fprintf(out, "%s,%s,%s/%s/%s\n", user, group, path, dir, file);
+  }
+}
+
+void fix_gid(int* gid_p, int mode)
+{
+  // if perms for group == perms for others, and no setguid, set group to root
+  if (((mode&S_IRWXO) == ((mode&S_IRWXG)>>3)) && (mode&S_ISGID) == 0)
+    *gid_p = 0;
+}
+
 void h(home,uid,gid,mode)
 char *home;
 int uid;
 int gid;
 int mode;
 {
+  fix_gid(&gid, mode);
   if (mkdir(home,0700) == -1)
     if (errno != error_exist)
       strerr_die4sys(111,FATAL,"unable to mkdir ",home,": ");
-  if (chown(home,uid,gid) == -1)
-    strerr_die4sys(111,FATAL,"unable to chown ",home,": ");
+  write_log(uid, gid, home, NULL, NULL);
   if (chmod(home,mode) == -1)
     strerr_die4sys(111,FATAL,"unable to chmod ",home,": ");
 }
@@ -33,13 +152,13 @@
 int gid;
 int mode;
 {
+  fix_gid(&gid, mode);
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
   if (mkdir(subdir,0700) == -1)
     if (errno != error_exist)
       strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": ");
-  if (chown(subdir,uid,gid) == -1)
-    strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": ");
+  write_log(uid, gid, home, NULL, subdir);
   if (chmod(subdir,mode) == -1)
     strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": ");
 }
@@ -51,13 +170,13 @@
 int gid;
 int mode;
 {
+  fix_gid(&gid, mode);
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
   if (fifo_make(fifo,0700) == -1)
     if (errno != error_exist)
       strerr_die6sys(111,FATAL,"unable to mkfifo ",home,"/",fifo,": ");
-  if (chown(fifo,uid,gid) == -1)
-    strerr_die6sys(111,FATAL,"unable to chown ",home,"/",fifo,": ");
+  write_log(uid, gid, home, NULL, fifo);
   if (chmod(fifo,mode) == -1)
     strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",fifo,": ");
 }
@@ -78,6 +197,8 @@
   int fdin;
   int fdout;
 
+  fix_gid(&gid, mode);
+
   if (fchdir(fdsourcedir) == -1)
     strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
 
@@ -111,8 +232,7 @@
   if (close(fdout) == -1) /* NFS silliness */
     strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": ");
 
-  if (chown(file,uid,gid) == -1)
-    strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": ");
+  write_log(uid, gid, home, subdir, file);
   if (chmod(file,mode) == -1)
     strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": ");
 }
@@ -127,6 +247,8 @@
 {
   int fdout;
 
+  fix_gid(&gid, mode);
+
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
 
@@ -146,8 +268,7 @@
   if (close(fdout) == -1) /* NFS silliness */
     strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": ");
 
-  if (chown(file,uid,gid) == -1)
-    strerr_die6sys(111,FATAL,"unable to chown ",home,"/",file,": ");
+  write_log(uid, gid, home, NULL, file);
   if (chmod(file,mode) == -1)
     strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",file,": ");
 }
@@ -160,5 +281,6 @@
 
   umask(077);
   hier();
+  fclose(out);
   _exit(0);
 }
diff -urN qmail-1.03/ipalloc.h qmail-1.03-with-plesk-8.6/ipalloc.h
--- qmail-1.03/ipalloc.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/ipalloc.h	2008-08-26 03:06:45.000000000 +0200
@@ -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/ipme.c qmail-1.03-with-plesk-8.6/ipme.c
--- qmail-1.03/ipme.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/ipme.c	2008-08-26 03:06:45.000000000 +0200
@@ -48,7 +48,7 @@
  
   if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1;
  
-  len = 256;
+  len = 512;
   for (;;) {
     if (!stralloc_ready(&buf,len)) { close(s); return 0; }
     buf.len = 0;
Binary files qmail-1.03/libdomainkeys.a and qmail-1.03-with-plesk-8.6/libdomainkeys.a differ
diff -urN qmail-1.03/qmail-clean.c qmail-1.03-with-plesk-8.6/qmail-clean.c
--- qmail-1.03/qmail-clean.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-clean.c	2008-08-26 03:06:45.000000000 +0200
@@ -73,22 +73,26 @@
    if (line.len < 7) { respond("x"); continue; }
    if (line.len > 100) { respond("x"); continue; }
    if (line.s[line.len - 1]) { respond("x"); continue; } /* impossible */
-   for (i = 5;i < line.len - 1;++i)
+   for (i = line.len - 2;i > 4;--i)
+    {
+     if (line.s[i] == '/') break;
      if ((unsigned char) (line.s[i] - '0') > 9)
       { respond("x"); continue; }
-   if (!scan_ulong(line.s + 5,&id)) { respond("x"); continue; }
+    }
+   if (line.s[i] == '/')
+     if (!scan_ulong(line.s + i + 1,&id)) { respond("x"); continue; }
    if (byte_equal(line.s,5,"foop/"))
     {
 #define U(prefix,flag) fmtqfn(fnbuf,prefix,id,flag); \
 if (unlink(fnbuf) == -1) if (errno != error_noent) { respond("!"); continue; }
-     U("intd/",0)
+     U("intd/",1)
      U("mess/",1)
      respond("+");
     }
    else if (byte_equal(line.s,4,"todo/"))
     {
-     U("intd/",0)
-     U("todo/",0)
+     U("intd/",1)
+     U("todo/",1)
      respond("+");
     }
    else
diff -urN qmail-1.03/qmail-control.9 qmail-1.03-with-plesk-8.6/qmail-control.9
--- qmail-1.03/qmail-control.9	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-control.9	2008-08-26 03:06:46.000000000 +0200
@@ -43,11 +43,15 @@
 .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
 .I defaulthost	\fIme	\fRqmail-inject
 .I databytes	\fR0	\fRqmail-smtpd
+.I dhparam1024.pem	\fR(none)	\fRqmail-smtpd
+.I dhparam512.pem	\fR(none)	\fRqmail-smtpd
 .I doublebouncehost	\fIme	\fRqmail-send
 .I doublebounceto	\fRpostmaster	\fRqmail-send
 .I envnoathost	\fIme	\fRqmail-send
@@ -61,11 +65,21 @@
 .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 spfbehavior	\fR0	\fRqmail-smtpd
+.I spfexp	\fR(default)	\fRqmail-smtpd
+.I spfguess	\fR(none)	\fRqmail-smtpd
+.I spfrules	\fR(none)	\fRqmail-smtpd
 .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/qmail-control.9.orig qmail-1.03-with-plesk-8.6/qmail-control.9.orig
--- qmail-1.03/qmail-control.9.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-control.9.orig	2008-08-26 03:06:45.000000000 +0200
@@ -0,0 +1,88 @@
+.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 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
+.I defaulthost	\fIme	\fRqmail-inject
+.I databytes	\fR0	\fRqmail-smtpd
+.I dhparam1024.pem	\fR(none)	\fRqmail-smtpd
+.I dhparam512.pem	\fR(none)	\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 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
+.SH "SEE ALSO"
+qmail-inject(8),
+qmail-qmqpc(8),
+qmail-remote(8),
+qmail-send(8),
+qmail-showctl(8),
+qmail-smtpd(8)
Binary files qmail-1.03/qmail-dk and qmail-1.03-with-plesk-8.6/qmail-dk differ
diff -urN qmail-1.03/qmail-dk.8 qmail-1.03-with-plesk-8.6/qmail-dk.8
--- qmail-1.03/qmail-dk.8	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-dk.8	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,123 @@
+.TH qmail-dk 8
+.SH NAME
+qmail-dk \- sign/verify and queue a mail message for delivery
+.SH SYNOPSIS
+.B qmail-dk
+.SH DESCRIPTION
+.B qmail-dk
+has the same interface as
+.B qmail-queue
+except that it inserts an appropriate DomainKeys header before it
+queues the message.  There are two separate ways to invoke
+.BR qmail-dk .
+For one way, you can patch qmail with the http://qmail.org/qmailqueue
+patch and set QMAILQUEUE to point to qmail-dk in the environment when
+you send or receive email.
+For another way, you can rename qmail-queue to qmail-queue.orig, and set DKQUEUE=bin/qmail-queue.orig.
+
+.B qmail-dk
+has been patched with
+.BR qmail-dk-0.54-auth.patch ,
+which sets up a bit of automatic behavior.  If RELAYCLIENT is found in
+the environment, qmail-dk imports the DKSIGN environment variable and
+tries to sign the mail.  If RELAYCLIENT is not found in the environment,
+DKVERIFY is imported, and we attempt to verify the mail.
+
+.B qmail-dk
+supports DomainKey signing and verification.  It uses the libdomainkey
+and OpenSSL libraries.  To sign a message, set the
+.B DKSIGN
+environment variable to the pathname to the private key that will be
+used to sign the message.  If there is a % character in the environment
+variable, it is removed and replaced by the domain name in the From: header.
+If, after substituting the %, that file does not exist, the message will not be signed.
+If there is no % and the file does not exist, the message will be rejected with error 32.
+The selector will be taken from the
+basename of the file.  The private key should be created by 
+.BR dknewkey ,
+which comes with libdomainkey.
+
+To verify a message, set the
+.B DKVERIFY
+environment variable to a desired set of letters.  Precisely, if you
+want a libdomainkey return status to generate an error, include that
+letter, where A is the first return status (DK_STAT_OK), B is the
+second (DK_STAT_BADSIG), etc.  The letter should be uppercase if you
+want a permanent error to be returned (exit code 13), and lowercase if
+you want a temporary error to be returned (exit code 82).
+
+For example, if you want to permanently reject messages that have a
+signature that has been revoked, include the letter 'K' in the
+.B DKVERIFY
+environment variable.  A conservative set of letters is
+.BR DEGIJKfh .
+Reject permanently BADSIG, NOKEY, BADKEY, SYNTAX, ARGS, REVOKED, and
+INTERNAL errors, and temporarily CANTVRFY and NORESOURCE.  Add in
+.B B
+if you want to reject messages that have a signature that doesn't
+verify (presumably because the message is a forgery or has been
+damaged in transit.  Note that
+.B qmail-dk
+always inserts the 
+.B DomainKey-Status
+header, so that messages can be
+rejected at delivery time, or in the mail reader.
+
+Typically, you would sign messages generated on-host by setting
+.B DKSIGN
+in the environment before running an email program.  DKSIGN will be carried
+through qmail's sendmail emulation through 
+.B qmail-inject
+to
+.BR qmail-dk .
+You would also set it for
+.B qmail-smtpd
+at the same time
+.B RELAYCLIENT
+is set, most often in the tcpserver cdb file.  If a host is authorized
+to relay, you probably want to sign messages sent by that host.
+.B DKVERIFY
+should be set for all other hosts.
+
+If neither
+.B DKSIGN
+nor
+.B DKVERIFY
+are set, then
+.B DKSIGN
+will be set to /etc/domainkeys/%/default.  If such a private key exists, it will be used to sign the domain.
+
+.B qmail-dk
+will ordinarily spawn qmail-queue, but if DKQUEUE is set in the environment,
+the program that it points to will be executed instead.  If DKQUEUE is not set, and
+.B qmail-dk
+has been invoked as
+.B qmail-queue
+then
+.B qmail-queue.orig
+is spawned instead.
+
+.SH "EXIT CODES"
+.B qmail-dk
+returns the same exit codes as qmail-queue with these additions:
+.TP 5
+.B 32
+The private key file does not exist.
+.TP 5
+.B 57
+Trouble waiting for qmail-queue to exit.
+.TP 5
+.B 58
+Unable to vfork.
+.TP 5
+.B 59
+Unable to create a pipe to qmail-queue.
+.SH "SEE ALSO"
+addresses(5),
+envelopes(5),
+qmail-header(5),
+qmail-inject(8),
+qmail-qmqpc(8),
+qmail-queue(8),
+qmail-send(8),
+qmail-smtpd(8)
diff -urN qmail-1.03/qmail-dk.c qmail-1.03-with-plesk-8.6/qmail-dk.c
--- qmail-1.03/qmail-dk.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-dk.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,333 @@
+#include <sys/types.h>
+#include "readwrite.h"
+#include "sig.h"
+#include "exit.h"
+#include "open.h"
+#include "seek.h"
+#include "fmt.h"
+#include "alloc.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "datetime.h"
+#include "now.h"
+#include "fork.h"
+#include "wait.h"
+#include "extra.h"
+#include "auto_qmail.h"
+#include "auto_uids.h"
+#include "date822fmt.h"
+#include "fmtqfn.h"
+#include "env.h"
+#include "control.h"
+#include <domainkeys.h>
+
+#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
+#define ADDR 1003
+
+//default definition of DKVERIFY:
+#define DKVERIFY_STRING	"BDEGIJKfh"
+//http://wiki.qmailtoaster.com/index.php/Domainkeys#DKVERIFY
+//To make the verification more stringent by permanently rejecting incoming mail that has
+//a DomainKey signature but fails to verify against the published public key
+//for the sender's domain, add "B" to the list: "BDEGIJKfh"
+  
+char inbuf[2048];
+struct substdio ssin;
+char outbuf[256];
+struct substdio ssout;
+
+datetime_sec starttime;
+struct datetime dt;
+unsigned long mypid;
+unsigned long uid;
+char *pidfn; // temp filename for write
+int messfd;  // temp filename fd for write
+int readfd;  // same temp filename fd for read
+
+char tmp[FMT_ULONG];
+
+//char *relayclient;
+char *dksign = 0;
+stralloc dksignature = {0};
+stralloc dkoutput = {0};
+char *dkverify = 0;
+char *dkqueue = 0;
+DK_LIB *dklib;
+DK *dk;
+DK_STAT st;
+
+void die(e) int e; {
+ if (!e){
+    //fprintf(stderr, "PASS\n"); 
+ } else {
+    //fprintf(stderr, "REJECT\n");
+    fprintf (stderr, "LOG domainkeys-handler exited with status %d\n", e);
+ }
+ _exit(e); 
+}
+void die_write() { die(53); }
+void die_read() { die(54); }
+void sigalrm() { /* thou shalt not clean up here */ die(52); }
+void sigbug() { die(81); }
+void maybe_die_dk(e) DK_STAT e; {
+  switch(e) {
+  case DK_STAT_BADKEY: die(55);
+  case DK_STAT_CANTVRFY: die(74);
+  case DK_STAT_NORESOURCE: die(51);
+  case DK_STAT_ARGS: die(12);
+  case DK_STAT_SYNTAX: 
+	if (!dksign){ // dkverify
+	    die(31);
+	}
+	break;
+  case DK_STAT_INTERNAL: die(81);
+  }
+}
+
+unsigned int pidfmt(s,seq)
+char *s;
+unsigned long seq;
+{
+ unsigned int i;
+ unsigned int len;
+
+ len = 0;
+ i = fmt_str(s,"/tmp/qmail-dk."); len += i; if (s) s += i;
+ i = fmt_ulong(s,mypid); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,starttime); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,seq); len += i; if (s) s += i;
+ ++len; if (s) *s++ = 0;
+
+ return len;
+}
+
+void pidopen()
+{
+ unsigned int len;
+ unsigned long seq;
+
+ seq = 1;
+ len = pidfmt((char *) 0,seq);
+ pidfn = alloc(len);
+ if (!pidfn) die(51);
+
+ for (seq = 1;seq < 10;++seq)
+  {
+   if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
+   pidfmt(pidfn,seq);
+   messfd = open_excl(pidfn);
+   if (messfd != -1) return;
+  }
+
+ die(63);
+}
+
+static void write_signature(DK *dk, char *keyfn)
+{
+ char advice[2048];
+ char *selector;
+ char *from;
+ static stralloc keyfnfrom = {0};
+ int i;
+
+ from = dk_from(dk);
+ i = str_chr(keyfn, '%');
+ if (keyfn[i]) {
+   if (!stralloc_copyb(&keyfnfrom,keyfn,i)) die(51);
+   if (!stralloc_cats(&keyfnfrom,from)) die(51);
+   if (!stralloc_cats(&keyfnfrom,keyfn + i + 1)) die(51);
+ } else {
+   if (!stralloc_copys(&keyfnfrom,keyfn)) die(51);
+ }
+ if (!stralloc_0(&keyfnfrom)) die(51);
+
+ switch(control_readfile(&dksignature,keyfnfrom.s,0)) {
+ case 0:
+   if (keyfn[i]) return;
+   die(32);
+ case 1: break;
+ default: die(31);
+ }
+ for(i=0; i < dksignature.len; i++)
+   if (dksignature.s[i] == '\0') dksignature.s[i] = '\n';
+ if (!stralloc_0(&dksignature)) die(51);
+
+ st = dk_getsig(dk, dksignature.s, advice, sizeof(advice));
+ maybe_die_dk(st);
+
+ if (!stralloc_cats(&dkoutput,
+   "Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys\n"
+	   "DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;\n"
+	   "  s=")) die(51);
+ selector = keyfn;
+ while (*keyfn) {
+   if (*keyfn == '/') selector = keyfn+1;
+    keyfn++;
+ }
+ if (!stralloc_cats(&dkoutput,selector)) die(51);
+ if (!stralloc_cats(&dkoutput,"; d=")) die(51);
+ if (from) {
+   if (!stralloc_cats(&dkoutput,from)) die(51);
+ } else if (!stralloc_cats(&dkoutput,"unknown")) die(51);
+ if (!stralloc_cats(&dkoutput,";\n  b=")) die(51);
+ if (!stralloc_cats(&dkoutput,advice)) die(51);
+ if (!stralloc_cats(&dkoutput,"  ;\n")) die(51);
+}
+
+//static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+
+void main(int argc, char *argv[])
+{
+ unsigned int len;
+ char ch;
+ char *context;
+// int pim[2];
+// int wstat;
+// unsigned long pid;
+
+ context = argv[1];
+
+ sig_blocknone();
+ umask(033);
+
+// relayclient = env_get("RELAYCLIENT");
+// if(relayclient){
+//  dksign = env_get("DKSIGN");
+//  if(! dksign)
+//   dksign = "/etc/domainkeys/%/default";
+// }else{
+//  dkverify = env_get("DKVERIFY");
+// }
+
+ if (!strncmp(context, "sign", 4)) {
+  dksign = "/etc/domainkeys/%/default";
+ } else if (!strncmp(context, "verify", 6)) {
+  dkverify = DKVERIFY_STRING;
+ }
+
+// dkqueue = env_get("DKQUEUE");
+// if (dkqueue && *dkqueue) binqqargs[0] = dkqueue;
+// else if (str_equal(argv[0]+str_rchr(argv[0], '/'), "/qmail-queue"))
+//   binqqargs[0] = "bin/qmail-queue.orig";
+
+ if (dksign || dkverify) {
+   dklib = dk_init(0);
+   if (!dklib) die(51);
+ }
+ if (dksign) {
+    dk = dk_sign(dklib, &st, DK_CANON_NOFWS);
+    if (!dk) die(31);
+ } else if (dkverify) {
+    dk = dk_verify(dklib, &st);
+    if (!dk) die(31);
+ }
+
+ mypid = getpid();
+ uid = getuid();
+ starttime = now();
+ datetime_tai(&dt,starttime);
+
+ sig_pipeignore();
+ sig_miscignore();
+ sig_alarmcatch(sigalrm);
+ sig_bugcatch(sigbug);
+
+ alarm(DEATH);
+
+ pidopen();
+ readfd = open_read(pidfn);
+ if (unlink(pidfn) == -1) die(63);
+
+ substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
+
+ for (;;) {
+   register int n;
+   register char *x;
+   int i;
+
+   n = substdio_feed(&ssin);
+   if (n < 0) die_read();
+   if (!n) break;
+   x = substdio_PEEK(&ssin);
+   if (dksign || dkverify)
+     for(i=0; i < n; i++) {
+       if (x[i] == '\n') st = dk_message(dk, "\r\n", 2);
+       else st = dk_message(dk, x+i, 1);
+       maybe_die_dk(st);
+      }
+   if (substdio_put(&ssout,x,n) == -1) die_write();
+   substdio_SEEK(&ssin,n);
+ }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+
+ if (dksign || dkverify) {
+   st = dk_eom(dk, (void *)0);
+   maybe_die_dk(st);
+   if (dksign) {
+     write_signature(dk, dksign);
+   } else if (dkverify) {
+     char *status;
+     if (!stralloc_copys(&dkoutput,"DomainKey-Status: ")) die(51);
+     switch(st) {
+     case DK_STAT_OK:         status = "good        "; break;
+     case DK_STAT_BADSIG:     status = "bad         "; break;
+     case DK_STAT_NOSIG:      status = "no signature"; break;
+     case DK_STAT_NOKEY:
+     case DK_STAT_CANTVRFY:   status = "no key      "; break;
+     case DK_STAT_BADKEY:     status = "bad key     "; break;
+     case DK_STAT_INTERNAL:
+     case DK_STAT_ARGS:
+     case DK_STAT_SYNTAX:     status = "bad format  "; break;
+     case DK_STAT_NORESOURCE: status = "no resources"; break;
+     case DK_STAT_REVOKED:    status = "revoked     "; break;
+     }
+     if (!stralloc_cats(&dkoutput,status)) die(51);
+     if (!stralloc_cats(&dkoutput,"\n")) die(51);
+     if (dkverify[str_chr(dkverify, 'A'+st)]) die(13);
+     if (dkverify[str_chr(dkverify, 'a'+st)]) die(82);
+   }
+ }
+/*
+ if (pipe(pim) == -1) die(59);
+ 
+ switch(pid = vfork()) {
+ case -1:
+   close(pim[0]); close(pim[1]);
+   die(58);
+ case 0:
+   close(pim[1]);
+   if (fd_move(0,pim[0]) == -1) die(120);
+   if (chdir(auto_qmail) == -1) die(61);
+   execv(*binqqargs,binqqargs);
+   die(120);
+ }
+
+ close(pim[0]);
+*/
+ substdio_fdbuf(&ssin,read,readfd,inbuf,sizeof(inbuf));
+// substdio_fdbuf(&ssout,write,pim[1],outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssout,write,1,outbuf,sizeof(outbuf));
+
+ if (substdio_bput(&ssout,dkoutput.s,dkoutput.len) == -1) die_write();
+ switch(substdio_copy(&ssout,&ssin))
+  {
+   case -2: die_read();
+   case -3: die_write();
+  }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+// close(pim[1]);
+
+// if (wait_pid(&wstat,pid) != pid)
+//   die(57);
+// if (wait_crashed(wstat))
+//   die(57);
+// die(wait_exitcode(wstat));
+
+ die(0);
+}
Binary files qmail-1.03/qmail-dk.o and qmail-1.03-with-plesk-8.6/qmail-dk.o differ
diff -urN qmail-1.03/qmail-inject.c qmail-1.03-with-plesk-8.6/qmail-inject.c
--- qmail-1.03/qmail-inject.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-inject.c	2008-08-26 03:06:46.000000000 +0200
@@ -40,6 +40,9 @@
 char *mailrhost;
 char *mailruser;
 
+int rcptcounter = 0; 
+int maxrcpt = -1; 
+
 stralloc control_idhost = {0};
 stralloc control_defaultdomain = {0};
 stralloc control_defaulthost = {0};
@@ -61,6 +64,8 @@
 void temp() { _exit(111); }
 void die_nomem() {
  substdio_putsflush(subfderr,"qmail-inject: fatal: out of memory\n"); temp(); }
+void die_rcpt() {
+ substdio_putsflush(subfderr,"qmail-inject: fatal: max number of recipients exceeded\n"); perm(); }
 void die_invalid(sa) stralloc *sa; {
  substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: ");
  substdio_putflush(subfderr,sa->s,sa->len); perm(); }
@@ -407,6 +412,10 @@
      substdio_putsflush(subfderr,"\n");
      perm();
   }
+
+ rcptcounter++;
+ if (checkrcptcount() == 1) die_rcpt();
+  
  token822_reverse(&tr);
  rwgeneric(&tr);
  rwappend(&tr,&reciplist);
@@ -675,7 +684,15 @@
    die_read();
  x = env_get("QMAILIDHOST");
  if (x) if (!stralloc_copys(&control_idhost,x)) die_nomem();
+ 
+ if (control_readint(&maxrcpt,"control/maxrcpt") == -1) die_read();
 }
+ 
+int checkrcptcount() { 
+  if (maxrcpt == -1) {return 0;} 
+  else if (rcptcounter > maxrcpt) {return 1;} 
+  else {return 0;} 
+} 
 
 #define RECIP_DEFAULT 1
 #define RECIP_ARGS 2
@@ -734,6 +751,8 @@
  if (!saa_readyplus(&hrrlist,1)) die_nomem();
  if (!saa_readyplus(&reciplist,1)) die_nomem();
 
+ rcptcounter = 0;
+
  while ((opt = getopt(argc,argv,"aAhHnNf:")) != opteof)
    switch(opt)
     {
diff -urN qmail-1.03/qmail-pop3d.c qmail-1.03-with-plesk-8.6/qmail-pop3d.c
--- qmail-1.03/qmail-pop3d.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-pop3d.c	2008-08-26 03:06:46.000000000 +0200
@@ -66,14 +66,14 @@
 void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
 
 void err_syntax() { err("syntax error"); }
-void err_unimpl() { err("unimplemented"); }
+void err_unimpl(char* arg) { err("unimplemented"); }
 void err_deleted() { err("already deleted"); }
 void err_nozero() { err("messages are counted from 1"); }
 void err_toobig() { err("not that many messages"); }
 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(char* arg) { puts("+OK \r\n"); flush(); }
 
 void printfn(fn) char *fn;
 {
@@ -146,7 +146,7 @@
   }
 }
 
-void pop3_stat()
+void pop3_stat(char* arg)
 {
   int i;
   unsigned long total;
@@ -161,15 +161,15 @@
   flush();
 }
 
-void pop3_rset()
+void pop3_rset(char* arg)
 {
   int i;
   for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
   last = 0;
-  okay();
+  okay(0);
 }
 
-void pop3_last()
+void pop3_last(char* arg)
 {
   puts("+OK ");
   put(strnum,fmt_uint(strnum,last));
@@ -177,7 +177,7 @@
   flush();
 }
 
-void pop3_quit()
+void pop3_quit(char* arg)
 {
   int i;
   for (i = 0;i < numm;++i)
@@ -192,7 +192,7 @@
 	if (!stralloc_0(&line)) die_nomem();
 	rename(m[i].fn,line.s); /* if it fails, bummer */
       }
-  okay();
+  okay(0);
   die();
 }
 
@@ -214,7 +214,7 @@
   if (i == -1) return;
   m[i].flagdeleted = 1;
   if (i + 1 > last) last = i + 1;
-  okay();
+  okay(0);
 }
 
 void list(i,flaguidl)
@@ -238,7 +238,7 @@
     list(i,flaguidl);
   }
   else {
-    okay();
+    okay(0);
     for (i = 0;i < numm;++i)
       if (!m[i].flagdeleted)
 	list(i,flaguidl);
@@ -267,7 +267,7 @@
  
   fd = open_read(m[i].fn);
   if (fd == -1) { err_nosuch(); return; }
-  okay();
+  okay(0);
   substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
   blast(&ssmsg,limit);
   close(fd);
@@ -299,7 +299,7 @@
  
   getlist();
 
-  okay();
+  okay(0);
   commands(&ssin,pop3commands);
   die();
 }
diff -urN qmail-1.03/qmail-popup.c qmail-1.03-with-plesk-8.6/qmail-popup.c
--- qmail-1.03/qmail-popup.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-popup.c	2008-08-26 03:06:46.000000000 +0200
@@ -64,10 +64,10 @@
 
 void err_syntax() { err("syntax error"); }
 void err_wantuser() { err("USER first"); }
-void err_authoriz() { err("authorization first"); }
+void err_authoriz(char* arg) { err("authorization first"); }
 
-void okay() { puts("+OK \r\n"); flush(); }
-void pop3_quit() { okay(); die(); }
+void okay(char* arg) { puts("+OK \r\n"); flush(); }
+void pop3_quit(char* arg) { okay(0); die(); }
 
 
 char unique[FMT_ULONG + FMT_ULONG + 3];
@@ -87,7 +87,16 @@
   int child;
   int wstat;
   int pi[2];
- 
+
+  /* K2, this should eliminate overly long user/pass combinations */
+  if(strlen(user) >= 40)
+  {
+     user[39]='\0';
+     userlen=strlen(user);
+  }
+  if(strlen(pass) >= 40)
+     pass[39]='\0';
+  
   if (fd_copy(2,1) == -1) die_pipe();
   close(3);
   if (pipe(pi) == -1) die_pipe();
@@ -136,7 +145,7 @@
 void pop3_user(arg) char *arg;
 {
   if (!*arg) { err_syntax(); return; }
-  okay();
+  okay(0);
   seenuser = 1;
   if (!stralloc_copys(&username,arg)) die_nomem(); 
   if (!stralloc_0(&username)) die_nomem(); 
diff -urN qmail-1.03/qmail-qmtpd.c qmail-1.03-with-plesk-8.6/qmail-qmtpd.c
--- qmail-1.03/qmail-qmtpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-qmtpd.c	2008-08-26 03:06:46.000000000 +0200
@@ -45,8 +45,8 @@
   for (;;) {
     substdio_get(&ssin,&ch,1);
     if (ch == ':') return len;
-    if (len > 200000000) resources();
     len = 10 * len + (ch - '0');
+    if (len > 200000000 || ch < '0' || ch > '9') resources();
   }
 }
 
@@ -193,8 +193,8 @@
         substdio_get(&ssin,&ch,1);
         --biglen;
         if (ch == ':') break;
-        if (len > 200000000) resources();
         len = 10 * len + (ch - '0');
+    if (len > 200000000 || ch < '0' || ch > '9') resources();
       }
       if (len >= biglen) badproto();
       if (len + relayclientlen >= 1000) {
diff -urN qmail-1.03/qmail-qstat.sh qmail-1.03-with-plesk-8.6/qmail-qstat.sh
--- qmail-1.03/qmail-qstat.sh	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-qstat.sh	2008-08-26 03:06:45.000000000 +0200
@@ -1,7 +1,7 @@
 cd QMAIL
 messdirs=`echo queue/mess/* | wc -w`
 messfiles=`find queue/mess/* -print | wc -w`
-tododirs=`echo queue/todo | wc -w`
-todofiles=`find queue/todo -print | wc -w`
+tododirs=`echo queue/todo/* | wc -w`
+todofiles=`find queue/todo/* -print | wc -w`
 echo messages in queue: `expr $messfiles - $messdirs`
 echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs`
diff -urN qmail-1.03/qmail-qstat.sh.orig qmail-1.03-with-plesk-8.6/qmail-qstat.sh.orig
--- qmail-1.03/qmail-qstat.sh.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-qstat.sh.orig	1998-06-15 12:53:16.000000000 +0200
@@ -0,0 +1,7 @@
+cd QMAIL
+messdirs=`echo queue/mess/* | wc -w`
+messfiles=`find queue/mess/* -print | wc -w`
+tododirs=`echo queue/todo | wc -w`
+todofiles=`find queue/todo -print | wc -w`
+echo messages in queue: `expr $messfiles - $messdirs`
+echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs`
diff -urN qmail-1.03/qmail-queue.c qmail-1.03-with-plesk-8.6/qmail-queue.c
--- qmail-1.03/qmail-queue.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-queue.c	2008-08-26 03:06:45.000000000 +0200
@@ -180,8 +180,8 @@
 
  messnum = pidst.st_ino;
  messfn = fnnum("mess/",1);
- todofn = fnnum("todo/",0);
- intdfn = fnnum("intd/",0);
+ todofn = fnnum("todo/",1);
+ intdfn = fnnum("intd/",1);
 
  if (link(pidfn,messfn) == -1) die(64);
  if (unlink(pidfn) == -1) die(63);
diff -urN qmail-1.03/qmail-queue.c.orig qmail-1.03-with-plesk-8.6/qmail-queue.c.orig
--- qmail-1.03/qmail-queue.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-queue.c.orig	1998-06-15 12:53:16.000000000 +0200
@@ -0,0 +1,254 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "readwrite.h"
+#include "sig.h"
+#include "exit.h"
+#include "open.h"
+#include "seek.h"
+#include "fmt.h"
+#include "alloc.h"
+#include "substdio.h"
+#include "datetime.h"
+#include "now.h"
+#include "triggerpull.h"
+#include "extra.h"
+#include "auto_qmail.h"
+#include "auto_uids.h"
+#include "date822fmt.h"
+#include "fmtqfn.h"
+
+#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
+#define ADDR 1003
+
+char inbuf[2048];
+struct substdio ssin;
+char outbuf[256];
+struct substdio ssout;
+
+datetime_sec starttime;
+struct datetime dt;
+unsigned long mypid;
+unsigned long uid;
+char *pidfn;
+struct stat pidst;
+unsigned long messnum;
+char *messfn;
+char *todofn;
+char *intdfn;
+int messfd;
+int intdfd;
+int flagmademess = 0;
+int flagmadeintd = 0;
+
+void cleanup()
+{
+ if (flagmadeintd)
+  {
+   seek_trunc(intdfd,0);
+   if (unlink(intdfn) == -1) return;
+  }
+ if (flagmademess)
+  {
+   seek_trunc(messfd,0);
+   if (unlink(messfn) == -1) return;
+  }
+}
+
+void die(e) int e; { _exit(e); }
+void die_write() { cleanup(); die(53); }
+void die_read() { cleanup(); die(54); }
+void sigalrm() { /* thou shalt not clean up here */ die(52); }
+void sigbug() { die(81); }
+
+unsigned int receivedlen;
+char *received;
+/* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
+
+static unsigned int receivedfmt(s)
+char *s;
+{
+ unsigned int i;
+ unsigned int len;
+ len = 0;
+ i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
+ i = fmt_ulong(s,mypid); len += i; if (s) s += i;
+ i = fmt_str(s," invoked "); len += i; if (s) s += i;
+ if (uid == auto_uida)
+  { i = fmt_str(s,"by alias"); len += i; if (s) s += i; }
+ else if (uid == auto_uidd)
+  { i = fmt_str(s,"from network"); len += i; if (s) s += i; }
+ else if (uid == auto_uids)
+  { i = fmt_str(s,"for bounce"); len += i; if (s) s += i; }
+ else
+  {
+   i = fmt_str(s,"by uid "); len += i; if (s) s += i;
+   i = fmt_ulong(s,uid); len += i; if (s) s += i;
+  }
+ i = fmt_str(s,"); "); len += i; if (s) s += i;
+ i = date822fmt(s,&dt); len += i; if (s) s += i;
+ return len;
+}
+
+void received_setup()
+{
+ receivedlen = receivedfmt((char *) 0);
+ received = alloc(receivedlen + 1);
+ if (!received) die(51);
+ receivedfmt(received);
+}
+
+unsigned int pidfmt(s,seq)
+char *s;
+unsigned long seq;
+{
+ unsigned int i;
+ unsigned int len;
+
+ len = 0;
+ i = fmt_str(s,"pid/"); len += i; if (s) s += i;
+ i = fmt_ulong(s,mypid); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,starttime); len += i; if (s) s += i;
+ i = fmt_str(s,"."); len += i; if (s) s += i;
+ i = fmt_ulong(s,seq); len += i; if (s) s += i;
+ ++len; if (s) *s++ = 0;
+
+ return len;
+}
+
+char *fnnum(dirslash,flagsplit)
+char *dirslash;
+int flagsplit;
+{
+ char *s;
+
+ s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
+ if (!s) die(51);
+ fmtqfn(s,dirslash,messnum,flagsplit);
+ return s;
+}
+
+void pidopen()
+{
+ unsigned int len;
+ unsigned long seq;
+
+ seq = 1;
+ len = pidfmt((char *) 0,seq);
+ pidfn = alloc(len);
+ if (!pidfn) die(51);
+
+ for (seq = 1;seq < 10;++seq)
+  {
+   if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */
+   pidfmt(pidfn,seq);
+   messfd = open_excl(pidfn);
+   if (messfd != -1) return;
+  }
+
+ die(63);
+}
+
+char tmp[FMT_ULONG];
+
+void main()
+{
+ unsigned int len;
+ char ch;
+
+ sig_blocknone();
+ umask(033);
+ if (chdir(auto_qmail) == -1) die(61);
+ if (chdir("queue") == -1) die(62);
+
+ mypid = getpid();
+ uid = getuid();
+ starttime = now();
+ datetime_tai(&dt,starttime);
+
+ received_setup();
+
+ sig_pipeignore();
+ sig_miscignore();
+ sig_alarmcatch(sigalrm);
+ sig_bugcatch(sigbug);
+
+ alarm(DEATH);
+
+ pidopen();
+ if (fstat(messfd,&pidst) == -1) die(63);
+
+ messnum = pidst.st_ino;
+ messfn = fnnum("mess/",1);
+ todofn = fnnum("todo/",0);
+ intdfn = fnnum("intd/",0);
+
+ if (link(pidfn,messfn) == -1) die(64);
+ if (unlink(pidfn) == -1) die(63);
+ flagmademess = 1;
+
+ substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
+
+ if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
+
+ switch(substdio_copy(&ssout,&ssin))
+  {
+   case -2: die_read();
+   case -3: die_write();
+  }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+ if (fsync(messfd) == -1) die_write();
+
+ intdfd = open_excl(intdfn);
+ if (intdfd == -1) die(65);
+ flagmadeintd = 1;
+
+ substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf));
+ substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf));
+
+ if (substdio_bput(&ssout,"u",1) == -1) die_write();
+ if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
+ if (substdio_bput(&ssout,"",1) == -1) die_write();
+
+ if (substdio_bput(&ssout,"p",1) == -1) die_write();
+ if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
+ if (substdio_bput(&ssout,"",1) == -1) die_write();
+
+ if (substdio_get(&ssin,&ch,1) < 1) die_read();
+ if (ch != 'F') die(91);
+ if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+ for (len = 0;len < ADDR;++len)
+  {
+   if (substdio_get(&ssin,&ch,1) < 1) die_read();
+   if (substdio_put(&ssout,&ch,1) == -1) die_write();
+   if (!ch) break;
+  }
+ if (len >= ADDR) die(11);
+
+ if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
+
+ for (;;)
+  {
+   if (substdio_get(&ssin,&ch,1) < 1) die_read();
+   if (!ch) break;
+   if (ch != 'T') die(91);
+   if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+   for (len = 0;len < ADDR;++len)
+    {
+     if (substdio_get(&ssin,&ch,1) < 1) die_read();
+     if (substdio_bput(&ssout,&ch,1) == -1) die_write();
+     if (!ch) break;
+    }
+   if (len >= ADDR) die(11);
+  }
+
+ if (substdio_flush(&ssout) == -1) die_write();
+ if (fsync(intdfd) == -1) die_write();
+
+ if (link(intdfn,todofn) == -1) die(66);
+
+ triggerpull();
+ die(0);
+}
diff -urN qmail-1.03/qmail-remote.8 qmail-1.03-with-plesk-8.6/qmail-remote.8
--- qmail-1.03/qmail-remote.8	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-remote.8	2008-08-26 03:06:45.000000000 +0200
@@ -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/qmail-remote.c qmail-1.03-with-plesk-8.6/qmail-remote.c
--- qmail-1.03/qmail-remote.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-remote.c	2008-08-26 03:06:46.000000000 +0200
@@ -48,7 +48,18 @@
 
 struct ip_address partner;
 
-void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
+#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) const char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
 void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
 void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
 void outsafe(sa) stralloc *sa; { int i; char ch;
@@ -99,6 +110,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 +124,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 +137,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 +189,65 @@
   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)
+  {
+    int wasspace = 0;
+
+    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 (!wasspace)
+           if (!stralloc_catb(sa, s, p - s) || !stralloc_0(sa)) temp_nomem();
+         if (*p == '\n') break;
+         wasspace = 1;
+       } else if (wasspace == 1) {
+         wasspace = 0;
+         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 +264,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,6 +276,30 @@
   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();
 }
 
@@ -214,6 +328,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_pop_free(gens, GENERAL_NAME_free);
+    }
+
+    /* 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,8 +511,45 @@
   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 >= 400 && code < 600) { return;} /* try next MX, see RFC-2821 */
+  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);
@@ -230,6 +557,10 @@
   substdio_flush(&smtpto);
   if (smtpcode() != 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");
@@ -417,7 +748,10 @@
     if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
       tcpto_err(&ip.ix[i].ip,0);
       partner = ip.ix[i].ip;
-      smtp(); /* does not return */
+#ifdef TLS
+      partner_fqdn = ip.ix[i].fqdn;
+#endif
+      smtp(); /* only returns when the next MX is to be tried */
     }
     tcpto_err(&ip.ix[i].ip,errno == error_timeout);
     close(smtpfd);
diff -urN qmail-1.03/qmail-send.c qmail-1.03-with-plesk-8.6/qmail-send.c
--- qmail-1.03/qmail-send.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-send.c	2008-08-26 03:06:45.000000000 +0200
@@ -96,7 +96,7 @@
 }
 
 void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); }
-void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); }
+void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,1); }
 void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); }
 void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); }
 void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); }
@@ -262,6 +262,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();
@@ -906,41 +908,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;
@@ -1216,7 +1219,8 @@
 /* this file is too long ---------------------------------------------- TODO */
 
 datetime_sec nexttodorun;
-DIR *tododir; /* if 0, have to opendir again */
+int flagtododir = 0; /* if 0, have to readsubdir_init again */
+readsubdir todosubdir;
 stralloc todoline = {0};
 char todobuf[SUBSTDIO_INSIZE];
 char todobufinfo[512];
@@ -1224,7 +1228,7 @@
 
 void todo_init()
 {
- tododir = 0;
+ flagtododir = 0;
  nexttodorun = now();
  trigger_set();
 }
@@ -1236,7 +1240,7 @@
 {
  if (flagexitasap) return;
  trigger_selprep(nfds,rfds);
- if (tododir) *wakeup = 0;
+ if (flagtododir) *wakeup = 0;
  if (*wakeup > nexttodorun) *wakeup = nexttodorun;
 }
 
@@ -1253,8 +1257,7 @@
  char ch;
  int match;
  unsigned long id;
- unsigned int len;
- direntry *d;
+ int z;
  int c;
  unsigned long uid;
  unsigned long pid;
@@ -1265,32 +1268,26 @@
 
  if (flagexitasap) return;
 
- if (!tododir)
+ if (!flagtododir)
   {
    if (!trigger_pulled(rfds))
      if (recent < nexttodorun)
        return;
    trigger_set();
-   tododir = opendir("todo");
-   if (!tododir)
-    {
-     pausedir("todo");
-     return;
-    }
+   readsubdir_init(&todosubdir, "todo", pausedir);
+   flagtododir = 1;
    nexttodorun = recent + SLEEP_TODO;
   }
 
- d = readdir(tododir);
- if (!d)
+ switch(readsubdir_next(&todosubdir, &id))
   {
-   closedir(tododir);
-   tododir = 0;
-   return;
+    case 1:
+      break;
+    case 0:
+      flagtododir = 0;
+    default:
+      return;
   }
- if (str_equal(d->d_name,".")) return;
- if (str_equal(d->d_name,"..")) return;
- len = scan_ulong(d->d_name,&id);
- if (!len || d->d_name[len]) return;
 
  fnmake_todo(id);
 
@@ -1544,7 +1541,7 @@
  numjobs = 0;
  for (c = 0;c < CHANNELS;++c)
   {
-   char ch;
+   char ch, ch1;
    int u;
    int r;
    do
@@ -1552,7 +1549,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/qmail-send.c.orig qmail-1.03-with-plesk-8.6/qmail-send.c.orig
--- qmail-1.03/qmail-send.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-send.c.orig	2008-08-26 03:06:45.000000000 +0200
@@ -0,0 +1,1621 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "readwrite.h"
+#include "sig.h"
+#include "direntry.h"
+#include "control.h"
+#include "select.h"
+#include "open.h"
+#include "seek.h"
+#include "exit.h"
+#include "lock.h"
+#include "ndelay.h"
+#include "now.h"
+#include "getln.h"
+#include "substdio.h"
+#include "alloc.h"
+#include "error.h"
+#include "stralloc.h"
+#include "str.h"
+#include "byte.h"
+#include "fmt.h"
+#include "scan.h"
+#include "case.h"
+#include "auto_qmail.h"
+#include "trigger.h"
+#include "newfield.h"
+#include "quote.h"
+#include "qmail.h"
+#include "qsutil.h"
+#include "prioq.h"
+#include "constmap.h"
+#include "fmtqfn.h"
+#include "readsubdir.h"
+
+/* critical timing feature #1: if not triggered, do not busy-loop */
+/* critical timing feature #2: if triggered, respond within fixed time */
+/* important timing feature: when triggered, respond instantly */
+#define SLEEP_TODO 1500 /* check todo/ every 25 minutes in any case */
+#define SLEEP_FUZZ 1 /* slop a bit on sleeps to avoid zeno effect */
+#define SLEEP_FOREVER 86400 /* absolute maximum time spent in select() */
+#define SLEEP_CLEANUP 76431 /* time between cleanups */
+#define SLEEP_SYSFAIL 123
+#define OSSIFIED 129600 /* 36 hours; _must_ exceed q-q's DEATH (24 hours) */
+
+int lifetime = 604800;
+
+stralloc percenthack = {0};
+struct constmap mappercenthack;
+stralloc locals = {0};
+struct constmap maplocals;
+stralloc vdoms = {0};
+struct constmap mapvdoms;
+stralloc envnoathost = {0};
+stralloc bouncefrom = {0};
+stralloc bouncehost = {0};
+stralloc doublebounceto = {0};
+stralloc doublebouncehost = {0};
+
+char strnum2[FMT_ULONG];
+char strnum3[FMT_ULONG];
+
+#define CHANNELS 2
+char *chanaddr[CHANNELS] = { "local/", "remote/" };
+char *chanstatusmsg[CHANNELS] = { " local ", " remote " };
+char *tochan[CHANNELS] = { " to local ", " to remote " };
+int chanfdout[CHANNELS] = { 1, 3 };
+int chanfdin[CHANNELS] = { 2, 4 };
+int chanskip[CHANNELS] = { 10, 20 };
+
+int flagexitasap = 0; void sigterm() { flagexitasap = 1; }
+int flagrunasap = 0; void sigalrm() { flagrunasap = 1; }
+int flagreadasap = 0; void sighup() { flagreadasap = 1; }
+
+void cleandied() { log1("alert: oh no! lost qmail-clean connection! dying...\n");
+ flagexitasap = 1; }
+
+int flagspawnalive[CHANNELS];
+void spawndied(c) int c; { log1("alert: oh no! lost spawn connection! dying...\n");
+ flagspawnalive[c] = 0; flagexitasap = 1; }
+
+#define REPORTMAX 10000
+
+datetime_sec recent;
+
+
+/* this file is too long ----------------------------------------- FILENAMES */
+
+stralloc fn = {0};
+stralloc fn2 = {0};
+char fnmake_strnum[FMT_ULONG];
+
+void fnmake_init()
+{
+ while (!stralloc_ready(&fn,FMTQFN)) nomem();
+ while (!stralloc_ready(&fn2,FMTQFN)) nomem();
+}
+
+void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); }
+void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); }
+void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); }
+void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); }
+void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); }
+void fnmake2_bounce(id) unsigned long id;
+{ fn2.len = fmtqfn(fn2.s,"bounce/",id,0); }
+void fnmake_chanaddr(id,c) unsigned long id; int c;
+{ fn.len = fmtqfn(fn.s,chanaddr[c],id,1); }
+
+
+/* this file is too long ----------------------------------------- REWRITING */
+
+stralloc rwline = {0};
+
+/* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */
+/* may trash recip. must set up rwline, between a T and a \0. */
+int rewrite(recip)
+char *recip;
+{
+  int i;
+  int j;
+  char *x;
+  static stralloc addr = {0};
+  int at;
+
+  if (!stralloc_copys(&rwline,"T")) return 0;
+  if (!stralloc_copys(&addr,recip)) return 0;
+
+  i = byte_rchr(addr.s,addr.len,'@');
+  if (i == addr.len) {
+    if (!stralloc_cats(&addr,"@")) return 0;
+    if (!stralloc_cat(&addr,&envnoathost)) return 0;
+  }
+
+  while (constmap(&mappercenthack,addr.s + i + 1,addr.len - i - 1)) {
+    j = byte_rchr(addr.s,i,'%');
+    if (j == i) break;
+    addr.len = i;
+    i = j;
+    addr.s[i] = '@';
+  }
+
+  at = byte_rchr(addr.s,addr.len,'@');
+
+  if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) {
+    if (!stralloc_cat(&rwline,&addr)) return 0;
+    if (!stralloc_0(&rwline)) return 0;
+    return 1;
+  }
+
+  for (i = 0;i <= addr.len;++i)
+    if (!i || (i == at + 1) || (i == addr.len) || ((i > at) && (addr.s[i] == '.')))
+      if (x = constmap(&mapvdoms,addr.s + i,addr.len - i)) {
+        if (!*x) break;
+        if (!stralloc_cats(&rwline,x)) return 0;
+        if (!stralloc_cats(&rwline,"-")) return 0;
+        if (!stralloc_cat(&rwline,&addr)) return 0;
+        if (!stralloc_0(&rwline)) return 0;
+        return 1;
+      }
+ 
+  if (!stralloc_cat(&rwline,&addr)) return 0;
+  if (!stralloc_0(&rwline)) return 0;
+  return 2;
+}
+
+void senderadd(sa,sender,recip)
+stralloc *sa;
+char *sender;
+char *recip;
+{
+ int i;
+ int j;
+ int k;
+
+ i = str_len(sender);
+ if (i >= 4)
+   if (str_equal(sender + i - 4,"-@[]"))
+    {
+     j = byte_rchr(sender,i - 4,'@');
+     k = str_rchr(recip,'@');
+     if (recip[k] && (j + 5 <= i))
+      {
+       /* owner-@host-@[] -> owner-recipbox=reciphost@host */
+       while (!stralloc_catb(sa,sender,j)) nomem();
+       while (!stralloc_catb(sa,recip,k)) nomem();
+       while (!stralloc_cats(sa,"=")) nomem();
+       while (!stralloc_cats(sa,recip + k + 1)) nomem();
+       while (!stralloc_cats(sa,"@")) nomem();
+       while (!stralloc_catb(sa,sender + j + 1,i - 5 - j)) nomem();
+       return;
+      }
+    }
+ while (!stralloc_cats(sa,sender)) nomem();
+}
+
+
+/* this file is too long ---------------------------------------------- INFO */
+
+int getinfo(sa,dt,id)
+stralloc *sa;
+datetime_sec *dt;
+unsigned long id;
+{
+ int fdinfo;
+ struct stat st;
+ static stralloc line = {0};
+ int match;
+ substdio ss;
+ char buf[128];
+
+ fnmake_info(id);
+ fdinfo = open_read(fn.s);
+ if (fdinfo == -1) return 0;
+ if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; }
+ substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf));
+ if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; }
+ close(fdinfo);
+ if (!match) return 0;
+ if (line.s[0] != 'F') return 0;
+
+ *dt = st.st_mtime;
+ while (!stralloc_copys(sa,line.s + 1)) nomem();
+ while (!stralloc_0(sa)) nomem();
+ return 1;
+}
+
+
+/* this file is too long ------------------------------------- COMMUNICATION */
+
+substdio sstoqc; char sstoqcbuf[1024];
+substdio ssfromqc; char ssfromqcbuf[1024];
+stralloc comm_buf[CHANNELS] = { {0}, {0} };
+int comm_pos[CHANNELS];
+
+void comm_init()
+{
+ int c;
+ substdio_fdbuf(&sstoqc,write,5,sstoqcbuf,sizeof(sstoqcbuf));
+ substdio_fdbuf(&ssfromqc,read,6,ssfromqcbuf,sizeof(ssfromqcbuf));
+ for (c = 0;c < CHANNELS;++c)
+   if (ndelay_on(chanfdout[c]) == -1)
+   /* this is so stupid: NDELAY semantics should be default on write */
+     spawndied(c); /* drastic, but better than risking deadlock */
+}
+
+int comm_canwrite(c)
+int c;
+{
+ /* XXX: could allow a bigger buffer; say 10 recipients */
+ if (comm_buf[c].s && comm_buf[c].len) return 0;
+ return 1;
+}
+
+void comm_write(c,delnum,id,sender,recip)
+int c;
+int delnum;
+unsigned long id;
+char *sender;
+char *recip;
+{
+ char ch;
+ if (comm_buf[c].s && comm_buf[c].len) return;
+ 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();
+ senderadd(&comm_buf[c],sender,recip);
+ while (!stralloc_0(&comm_buf[c])) nomem();
+ while (!stralloc_cats(&comm_buf[c],recip)) nomem();
+ while (!stralloc_0(&comm_buf[c])) nomem();
+ comm_pos[c] = 0;
+}
+
+void comm_selprep(nfds,wfds)
+int *nfds;
+fd_set *wfds;
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c)
+   if (flagspawnalive[c])
+     if (comm_buf[c].s && comm_buf[c].len)
+      {
+       FD_SET(chanfdout[c],wfds);
+       if (*nfds <= chanfdout[c])
+         *nfds = chanfdout[c] + 1;
+      }
+}
+
+void comm_do(wfds)
+fd_set *wfds;
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c)
+   if (flagspawnalive[c])
+     if (comm_buf[c].s && comm_buf[c].len)
+       if (FD_ISSET(chanfdout[c],wfds))
+        {
+         int w;
+         int len;
+         len = comm_buf[c].len;
+         w = write(chanfdout[c],comm_buf[c].s + comm_pos[c],len - comm_pos[c]);
+         if (w <= 0)
+	  {
+	   if ((w == -1) && (errno == error_pipe))
+	     spawndied(c);
+	   else
+	     continue; /* kernel select() bug; can't avoid busy-looping */
+	  }
+	 else
+	  {
+	   comm_pos[c] += w;
+	   if (comm_pos[c] == len)
+	     comm_buf[c].len = 0;
+	  }
+        }
+}
+
+
+/* this file is too long ------------------------------------------ CLEANUPS */
+
+int flagcleanup; /* if 1, cleanupdir is initialized and ready */
+readsubdir cleanupdir;
+datetime_sec cleanuptime;
+
+void cleanup_init()
+{
+ flagcleanup = 0;
+ cleanuptime = now();
+}
+
+void cleanup_selprep(wakeup)
+datetime_sec *wakeup;
+{
+ if (flagcleanup) *wakeup = 0;
+ if (*wakeup > cleanuptime) *wakeup = cleanuptime;
+}
+
+void cleanup_do()
+{
+ char ch;
+ struct stat st;
+ unsigned long id;
+
+ if (!flagcleanup)
+  {
+   if (recent < cleanuptime) return;
+   readsubdir_init(&cleanupdir,"mess",pausedir);
+   flagcleanup = 1;
+  }
+
+ switch(readsubdir_next(&cleanupdir,&id))
+  {
+   case 1:
+     break;
+   case 0:
+     flagcleanup = 0;
+     cleanuptime = recent + SLEEP_CLEANUP;
+   default:
+     return;
+  }
+
+ fnmake_mess(id);
+ if (stat(fn.s,&st) == -1) return; /* probably qmail-queue deleted it */
+ if (recent <= st.st_atime + OSSIFIED) return;
+
+ fnmake_info(id);
+ if (stat(fn.s,&st) == 0) return;
+ if (errno != error_noent) return;
+ fnmake_todo(id);
+ if (stat(fn.s,&st) == 0) return;
+ if (errno != error_noent) return;
+
+ fnmake_foop(id);
+ if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; }
+ if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; }
+ if (ch != '+')
+   log3("warning: qmail-clean unable to clean up ",fn.s,"\n");
+}
+
+
+/* this file is too long ----------------------------------- PRIORITY QUEUES */
+
+prioq pqdone = {0}; /* -todo +info; HOPEFULLY -local -remote */
+prioq pqchan[CHANNELS] = { {0}, {0} };
+/* pqchan 0: -todo +info +local ?remote */
+/* pqchan 1: -todo +info ?local +remote */
+prioq pqfail = {0}; /* stat() failure; has to be pqadded again */
+
+void pqadd(id)
+unsigned long id;
+{
+ struct prioq_elt pe;
+ struct prioq_elt pechan[CHANNELS];
+ int flagchan[CHANNELS];
+ struct stat st;
+ int c;
+
+#define CHECKSTAT if (errno != error_noent) goto fail;
+
+ fnmake_info(id);
+ if (stat(fn.s,&st) == -1)
+  {
+   CHECKSTAT
+   return; /* someone yanking our chain */
+  }
+
+ fnmake_todo(id);
+ if (stat(fn.s,&st) != -1) return; /* look, ma, dad crashed writing info! */
+ CHECKSTAT
+
+ for (c = 0;c < CHANNELS;++c)
+  {
+   fnmake_chanaddr(id,c);
+   if (stat(fn.s,&st) == -1) { flagchan[c] = 0; CHECKSTAT }
+   else { flagchan[c] = 1; pechan[c].id = id; pechan[c].dt = st.st_mtime; }
+  }
+
+ for (c = 0;c < CHANNELS;++c)
+   if (flagchan[c])
+     while (!prioq_insert(&pqchan[c],&pechan[c])) nomem();
+
+ for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break;
+ if (c == CHANNELS)
+  {
+   pe.id = id; pe.dt = now();
+   while (!prioq_insert(&pqdone,&pe)) nomem();
+  }
+
+ return;
+
+ fail:
+ log3("warning: unable to stat ",fn.s,"; will try again later\n");
+ pe.id = id; pe.dt = now() + SLEEP_SYSFAIL;
+ while (!prioq_insert(&pqfail,&pe)) nomem();
+}
+
+void pqstart()
+{
+ readsubdir rs;
+ int x;
+ unsigned long id;
+
+ readsubdir_init(&rs,"info",pausedir);
+
+ while (x = readsubdir_next(&rs,&id))
+   if (x > 0)
+     pqadd(id);
+}
+
+void pqfinish()
+{
+ int c;
+ struct prioq_elt pe;
+ time_t ut[2]; /* XXX: more portable than utimbuf, but still worrisome */
+
+ for (c = 0;c < CHANNELS;++c)
+   while (prioq_min(&pqchan[c],&pe))
+    {
+     prioq_delmin(&pqchan[c]);
+     fnmake_chanaddr(pe.id,c);
+     ut[0] = ut[1] = pe.dt;
+     if (utime(fn.s,ut) == -1)
+       log3("warning: unable to utime ",fn.s,"; message will be retried too soon\n");
+    }
+}
+
+void pqrun()
+{
+ int c;
+ int i;
+ for (c = 0;c < CHANNELS;++c)
+   if (pqchan[c].p)
+     if (pqchan[c].len)
+       for (i = 0;i < pqchan[c].len;++i)
+	 pqchan[c].p[i].dt = recent;
+}
+
+
+/* this file is too long ---------------------------------------------- JOBS */
+
+struct job
+ {
+  int refs; /* if 0, this struct is unused */
+  unsigned long id;
+  int channel;
+  datetime_sec retry;
+  stralloc sender;
+  int numtodo;
+  int flaghiteof;
+  int flagdying;
+ }
+;
+
+int numjobs;
+struct job *jo;
+
+void job_init()
+{
+ int j;
+ while (!(jo = (struct job *) alloc(numjobs * sizeof(struct job)))) nomem();
+ for (j = 0;j < numjobs;++j)
+  {
+   jo[j].refs = 0;
+   jo[j].sender.s = 0;
+  }
+}
+
+int job_avail()
+{
+ int j;
+ for (j = 0;j < numjobs;++j) if (!jo[j].refs) return 1;
+ return 0;
+}
+
+int job_open(id,channel)
+unsigned long id;
+int channel;
+{
+ int j;
+ for (j = 0;j < numjobs;++j) if (!jo[j].refs) break;
+ if (j == numjobs) return -1;
+ jo[j].refs = 1;
+ jo[j].id = id;
+ jo[j].channel = channel;
+ jo[j].numtodo = 0;
+ jo[j].flaghiteof = 0;
+ return j;
+}
+
+void job_close(j)
+int j;
+{
+ struct prioq_elt pe;
+ struct stat st;
+
+ if (0 < --jo[j].refs) return;
+
+ pe.id = jo[j].id;
+ pe.dt = jo[j].retry;
+ if (jo[j].flaghiteof && !jo[j].numtodo)
+  {
+   fnmake_chanaddr(jo[j].id,jo[j].channel);
+   if (unlink(fn.s) == -1)
+    {
+     log3("warning: unable to unlink ",fn.s,"; will try again later\n");
+     pe.dt = now() + SLEEP_SYSFAIL;
+    }
+   else
+    {
+     int c;
+     for (c = 0;c < CHANNELS;++c) if (c != jo[j].channel)
+      {
+       fnmake_chanaddr(jo[j].id,c);
+       if (stat(fn.s,&st) == 0) return; /* more channels going */
+       if (errno != error_noent)
+	{
+         log3("warning: unable to stat ",fn.s,"\n");
+	 break; /* this is the only reason for HOPEFULLY */
+	}
+      }
+     pe.dt = now();
+     while (!prioq_insert(&pqdone,&pe)) nomem();
+     return;
+    }
+  }
+
+ while (!prioq_insert(&pqchan[jo[j].channel],&pe)) nomem();
+}
+
+
+/* this file is too long ------------------------------------------- BOUNCES */
+
+char *stripvdomprepend(recip)
+char *recip;
+{
+ int i;
+ char *domain;
+ int domainlen;
+ char *prepend;
+
+ i = str_rchr(recip,'@');
+ if (!recip[i]) return recip;
+ domain = recip + i + 1;
+ domainlen = str_len(domain);
+
+ for (i = 0;i <= domainlen;++i)
+   if ((i == 0) || (i == domainlen) || (domain[i] == '.'))
+     if (prepend = constmap(&mapvdoms,domain + i,domainlen - i))
+      {
+       if (!*prepend) break;
+       i = str_len(prepend);
+       if (str_diffn(recip,prepend,i)) break;
+       if (recip[i] != '-') break;
+       return recip + i + 1;
+      }
+ return recip;
+}
+
+stralloc bouncetext = {0};
+
+void addbounce(id,recip,report)
+unsigned long id;
+char *recip;
+char *report;
+{
+ int fd;
+ int pos;
+ int w;
+ while (!stralloc_copys(&bouncetext,"<")) nomem();
+ while (!stralloc_cats(&bouncetext,stripvdomprepend(recip))) nomem();
+ for (pos = 0;pos < bouncetext.len;++pos)
+   if (bouncetext.s[pos] == '\n')
+     bouncetext.s[pos] = '_';
+ while (!stralloc_cats(&bouncetext,">:\n")) nomem();
+ while (!stralloc_cats(&bouncetext,report)) nomem();
+ if (report[0])
+   if (report[str_len(report) - 1] != '\n')
+     while (!stralloc_cats(&bouncetext,"\n")) nomem();
+ for (pos = bouncetext.len - 2;pos > 0;--pos)
+   if (bouncetext.s[pos] == '\n')
+     if (bouncetext.s[pos - 1] == '\n')
+       bouncetext.s[pos] = '/';
+ while (!stralloc_cats(&bouncetext,"\n")) nomem();
+ fnmake2_bounce(id);
+ for (;;)
+  {
+   fd = open_append(fn2.s);
+   if (fd != -1) break;
+   log1("alert: unable to append to bounce message; HELP! sleeping...\n");
+   sleep(10);
+  }
+ pos = 0;
+ while (pos < bouncetext.len)
+  {
+   w = write(fd,bouncetext.s + pos,bouncetext.len - pos);
+   if (w <= 0)
+    {
+     log1("alert: unable to append to bounce message; HELP! sleeping...\n");
+     sleep(10);
+    }
+   else
+     pos += w;
+  }
+ close(fd);
+}
+
+int injectbounce(id)
+unsigned long id;
+{
+ struct qmail qqt;
+ struct stat st;
+ char *bouncesender;
+ char *bouncerecip;
+ int r;
+ int fd;
+ substdio ssread;
+ char buf[128];
+ char inbuf[128];
+ static stralloc sender = {0};
+ static stralloc quoted = {0};
+ datetime_sec birth;
+ unsigned long qp;
+
+ if (!getinfo(&sender,&birth,id)) return 0; /* XXX: print warning */
+
+ /* owner-@host-@[] -> owner-@host */
+ if (sender.len >= 5)
+   if (str_equal(sender.s + sender.len - 5,"-@[]"))
+    {
+     sender.len -= 4;
+     sender.s[sender.len - 1] = 0;
+    }
+
+ fnmake2_bounce(id);
+ fnmake_mess(id);
+ if (stat(fn2.s,&st) == -1)
+  {
+   if (errno == error_noent)
+     return 1;
+   log3("warning: unable to stat ",fn2.s,"\n");
+   return 0;
+  }
+ if (str_equal(sender.s,"#@[]"))
+   log3("triple bounce: discarding ",fn2.s,"\n");
+ else
+  {
+   if (qmail_open(&qqt) == -1)
+    { log1("warning: unable to start qmail-queue, will try later\n"); return 0; }
+   qp = qmail_qp(&qqt);
+
+   if (*sender.s) { bouncesender = ""; bouncerecip = sender.s; }
+   else { bouncesender = "#@[]"; bouncerecip = doublebounceto.s; }
+
+   while (!newfield_datemake(now())) nomem();
+   qmail_put(&qqt,newfield_date.s,newfield_date.len);
+   qmail_puts(&qqt,"From: ");
+   while (!quote(&quoted,&bouncefrom)) nomem();
+   qmail_put(&qqt,quoted.s,quoted.len);
+   qmail_puts(&qqt,"@");
+   qmail_put(&qqt,bouncehost.s,bouncehost.len);
+   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\
+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\
+" : ".\n\
+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);
+   else
+    {
+     substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
+     while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
+       qmail_put(&qqt,buf,r);
+     close(fd);
+     if (r == -1)
+       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,"Return-Path: <");
+   while (!quote2(&quoted,sender.s)) nomem();
+   qmail_put(&qqt,quoted.s,quoted.len);
+   qmail_puts(&qqt,">\n");
+
+   fd = open_read(fn.s);
+   if (fd == -1)
+     qmail_fail(&qqt);
+   else
+    {
+     substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf));
+     while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0)
+       qmail_put(&qqt,buf,r);
+     close(fd);
+     if (r == -1)
+       qmail_fail(&qqt);
+    }
+
+   qmail_from(&qqt,bouncesender);
+   qmail_to(&qqt,bouncerecip);
+   if (*qmail_close(&qqt))
+    { log1("warning: trouble injecting bounce message, will try later\n"); return 0; }
+
+   strnum2[fmt_ulong(strnum2,id)] = 0;
+   log2("bounce msg ",strnum2);
+   strnum2[fmt_ulong(strnum2,qp)] = 0;
+   log3(" qp ",strnum2,"\n");
+  }
+ if (unlink(fn2.s) == -1)
+  {
+   log3("warning: unable to unlink ",fn2.s,"\n");
+   return 0;
+  }
+ return 1;
+}
+
+
+/* this file is too long ---------------------------------------- DELIVERIES */
+
+struct del
+ {
+  int used;
+  int j;
+  unsigned long delid;
+  seek_pos mpos;
+  stralloc recip;
+ }
+;
+
+unsigned long masterdelid = 1;
+unsigned int concurrency[CHANNELS] = { 10, 20 };
+unsigned int concurrencyused[CHANNELS] = { 0, 0 };
+struct del *d[CHANNELS];
+stralloc dline[CHANNELS];
+char delbuf[2048];
+
+void del_status()
+{
+  int c;
+
+  log1("status:");
+  for (c = 0;c < CHANNELS;++c) {
+    strnum2[fmt_ulong(strnum2,(unsigned long) concurrencyused[c])] = 0;
+    strnum3[fmt_ulong(strnum3,(unsigned long) concurrency[c])] = 0;
+    log2(chanstatusmsg[c],strnum2);
+    log2("/",strnum3);
+  }
+  if (flagexitasap) log1(" exitasap");
+  log1("\n");
+}
+
+void del_init()
+{
+ int c;
+ int i;
+ for (c = 0;c < CHANNELS;++c)
+  {
+   flagspawnalive[c] = 1;
+   while (!(d[c] = (struct del *) alloc(concurrency[c] * sizeof(struct del))))
+     nomem();
+   for (i = 0;i < concurrency[c];++i)
+    { d[c][i].used = 0; d[c][i].recip.s = 0; }
+   dline[c].s = 0;
+   while (!stralloc_copys(&dline[c],"")) nomem();
+  }
+ del_status();
+}
+
+int del_canexit()
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c)
+   if (flagspawnalive[c]) /* if dead, nothing we can do about its jobs */
+     if (concurrencyused[c]) return 0;
+ return 1;
+}
+
+int del_avail(c)
+int c;
+{
+  return flagspawnalive[c] && comm_canwrite(c) && (concurrencyused[c] < concurrency[c]);
+}
+
+void del_start(j,mpos,recip)
+int j;
+seek_pos mpos;
+char *recip;
+{
+ int i;
+ int c;
+
+ c = jo[j].channel;
+ if (!flagspawnalive[c]) return;
+ if (!comm_canwrite(c)) return;
+
+ for (i = 0;i < concurrency[c];++i) if (!d[c][i].used) break;
+ if (i == concurrency[c]) return;
+
+ if (!stralloc_copys(&d[c][i].recip,recip)) { nomem(); return; }
+ if (!stralloc_0(&d[c][i].recip)) { nomem(); return; }
+ d[c][i].j = j; ++jo[j].refs;
+ d[c][i].delid = masterdelid++;
+ d[c][i].mpos = mpos;
+ d[c][i].used = 1; ++concurrencyused[c];
+
+ comm_write(c,i,jo[j].id,jo[j].sender.s,recip);
+
+ strnum2[fmt_ulong(strnum2,d[c][i].delid)] = 0;
+ strnum3[fmt_ulong(strnum3,jo[j].id)] = 0;
+ log2("starting delivery ",strnum2);
+ log3(": msg ",strnum3,tochan[c]);
+ logsafe(recip);
+ log1("\n");
+ del_status();
+}
+
+void markdone(c,id,pos)
+int c;
+unsigned long id;
+seek_pos pos;
+{
+ struct stat st;
+ int fd;
+ fnmake_chanaddr(id,c);
+ for (;;)
+  {
+   fd = open_write(fn.s);
+   if (fd == -1) break;
+   if (fstat(fd,&st) == -1) { close(fd); break; }
+   if (seek_set(fd,pos) == -1) { close(fd); break; }
+   if (write(fd,"D",1) != 1) { close(fd); break; }
+   /* further errors -> double delivery without us knowing about it, oh well */
+   close(fd);
+   return;
+  }
+ log3("warning: trouble marking ",fn.s,"; message will be delivered twice!\n");
+}
+
+void del_dochan(c)
+int c;
+{
+ int r;
+ char ch;
+ int i;
+ int delnum;
+ r = read(chanfdin[c],delbuf,sizeof(delbuf));
+ if (r == -1) return;
+ if (r == 0) { spawndied(c); return; }
+ for (i = 0;i < r;++i)
+  {
+   ch = delbuf[i];
+   while (!stralloc_append(&dline[c],&ch)) nomem();
+   if (dline[c].len > REPORTMAX)
+     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 > 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[2] == 'Z')
+	 if (jo[d[c][delnum].j].flagdying)
+	  {
+	   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[2])
+	{
+	 case 'K':
+	   log3("delivery ",strnum3,": success: ");
+	   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 + 3);
+	   log1("\n");
+	   break;
+	 case 'D':
+	   log3("delivery ",strnum3,": failure: ");
+	   logsafe(dline[c].s + 3);
+	   log1("\n");
+	   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;
+	 default:
+	   log3("delivery ",strnum3,": report mangled, will defer\n");
+	}
+       job_close(d[c][delnum].j);
+       d[c][delnum].used = 0; --concurrencyused[c];
+       del_status();
+      }
+     dline[c].len = 0;
+    }
+  }
+}
+
+void del_selprep(nfds,rfds)
+int *nfds;
+fd_set *rfds;
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c)
+   if (flagspawnalive[c])
+    {
+     FD_SET(chanfdin[c],rfds);
+     if (*nfds <= chanfdin[c])
+       *nfds = chanfdin[c] + 1;
+    }
+}
+
+void del_do(rfds)
+fd_set *rfds;
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c)
+   if (flagspawnalive[c])
+     if (FD_ISSET(chanfdin[c],rfds))
+       del_dochan(c);
+}
+
+
+/* this file is too long -------------------------------------------- PASSES */
+
+struct
+ {
+  unsigned long id; /* if 0, need a new pass */
+  int j; /* defined if id; job number */
+  int fd; /* defined if id; reading from {local,remote} */
+  seek_pos mpos; /* defined if id; mark position */
+  substdio ss;
+  char buf[128];
+ }
+pass[CHANNELS];
+
+void pass_init()
+{
+ int c;
+ for (c = 0;c < CHANNELS;++c) pass[c].id = 0;
+}
+
+void pass_selprep(wakeup)
+datetime_sec *wakeup;
+{
+ int c;
+ struct prioq_elt pe;
+ if (flagexitasap) return;
+ for (c = 0;c < CHANNELS;++c)
+   if (pass[c].id)
+     if (del_avail(c))
+      { *wakeup = 0; return; }
+ if (job_avail())
+   for (c = 0;c < CHANNELS;++c)
+     if (!pass[c].id)
+       if (prioq_min(&pqchan[c],&pe))
+         if (*wakeup > pe.dt)
+           *wakeup = pe.dt;
+ if (prioq_min(&pqfail,&pe))
+   if (*wakeup > pe.dt)
+     *wakeup = pe.dt;
+ if (prioq_min(&pqdone,&pe))
+   if (*wakeup > pe.dt)
+     *wakeup = pe.dt;
+}
+
+static datetime_sec squareroot(x) /* result^2 <= x < (result + 1)^2 */
+datetime_sec x; /* assuming: >= 0 */
+{
+ datetime_sec y;
+ datetime_sec yy;
+ datetime_sec y21;
+ int j;
+
+ y = 0; yy = 0;
+ for (j = 15;j >= 0;--j)
+  {
+   y21 = (y << (j + 1)) + (1 << (j + j));
+   if (y21 <= x - yy) { y += (1 << j); yy += y21; }
+  }
+ return y;
+}
+
+datetime_sec nextretry(birth,c)
+datetime_sec birth;
+int c;
+{
+ int n;
+
+ if (birth > recent) n = 0;
+ else n = squareroot(recent - birth); /* no need to add fuzz to recent */
+ n += chanskip[c];
+ return birth + n * n;
+}
+
+void pass_dochan(c)
+int c;
+{
+ datetime_sec birth;
+ struct prioq_elt pe;
+ static stralloc line = {0};
+ int match;
+
+ if (flagexitasap) return;
+
+ if (!pass[c].id)
+  {
+   if (!job_avail()) return;
+   if (!prioq_min(&pqchan[c],&pe)) return;
+   if (pe.dt > recent) return;
+   fnmake_chanaddr(pe.id,c);
+
+   prioq_delmin(&pqchan[c]);
+   pass[c].mpos = 0;
+   pass[c].fd = open_read(fn.s);
+   if (pass[c].fd == -1) goto trouble;
+   if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; }
+   pass[c].id = pe.id;
+   substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf));
+   pass[c].j = job_open(pe.id,c);
+   jo[pass[c].j].retry = nextretry(birth,c);
+   jo[pass[c].j].flagdying = (recent > birth + lifetime);
+   while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem();
+  }
+
+ if (!del_avail(c)) return;
+
+ if (getln(&pass[c].ss,&line,&match,'\0') == -1)
+  {
+   fnmake_chanaddr(pass[c].id,c);
+   log3("warning: trouble reading ",fn.s,"; will try again later\n");
+   close(pass[c].fd);
+   job_close(pass[c].j);
+   pass[c].id = 0;
+   return;
+  }
+ if (!match)
+  {
+   close(pass[c].fd);
+   jo[pass[c].j].flaghiteof = 1;
+   job_close(pass[c].j);
+   pass[c].id = 0;
+   return;
+  }
+ switch(line.s[0])
+  {
+   case 'T':
+     ++jo[pass[c].j].numtodo;
+     del_start(pass[c].j,pass[c].mpos,line.s + 1);
+     break;
+   case 'D':
+     break;
+   default:
+     fnmake_chanaddr(pass[c].id,c);
+     log3("warning: unknown record type in ",fn.s,"!\n");
+     close(pass[c].fd);
+     job_close(pass[c].j);
+     pass[c].id = 0;
+     return;
+  }
+
+ pass[c].mpos += line.len;
+ return;
+
+ trouble:
+ log3("warning: trouble opening ",fn.s,"; will try again later\n");
+ pe.dt = recent + SLEEP_SYSFAIL;
+ while (!prioq_insert(&pqchan[c],&pe)) nomem();
+}
+
+void messdone(id)
+unsigned long id;
+{
+ char ch;
+ int c;
+ struct prioq_elt pe;
+ struct stat st;
+
+ for (c = 0;c < CHANNELS;++c)
+  {
+   fnmake_chanaddr(id,c);
+   if (stat(fn.s,&st) == 0) return; /* false alarm; consequence of HOPEFULLY */
+   if (errno != error_noent)
+    {
+     log3("warning: unable to stat ",fn.s,"; will try again later\n");
+     goto fail;
+    }
+  }
+
+ fnmake_todo(id);
+ if (stat(fn.s,&st) == 0) return;
+ if (errno != error_noent)
+  {
+   log3("warning: unable to stat ",fn.s,"; will try again later\n");
+   goto fail;
+  }
+ 
+ fnmake_info(id);
+ if (stat(fn.s,&st) == -1)
+  {
+   if (errno == error_noent) return;
+   log3("warning: unable to stat ",fn.s,"; will try again later\n");
+   goto fail;
+  }
+ 
+ /* -todo +info -local -remote ?bounce */
+ if (!injectbounce(id))
+   goto fail; /* injectbounce() produced error message */
+
+ strnum3[fmt_ulong(strnum3,id)] = 0;
+ log3("end msg ",strnum3,"\n");
+
+ /* -todo +info -local -remote -bounce */
+ fnmake_info(id);
+ if (unlink(fn.s) == -1)
+  {
+   log3("warning: unable to unlink ",fn.s,"; will try again later\n");
+   goto fail;
+  }
+
+ /* -todo -info -local -remote -bounce; we can relax */
+ fnmake_foop(id);
+ if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; }
+ if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; }
+ if (ch != '+')
+   log3("warning: qmail-clean unable to clean up ",fn.s,"\n");
+
+ return;
+
+ fail:
+ pe.id = id; pe.dt = now() + SLEEP_SYSFAIL;
+ while (!prioq_insert(&pqdone,&pe)) nomem();
+}
+
+void pass_do()
+{
+ int c;
+ struct prioq_elt pe;
+
+ for (c = 0;c < CHANNELS;++c) pass_dochan(c);
+ if (prioq_min(&pqfail,&pe))
+   if (pe.dt <= recent)
+    {
+     prioq_delmin(&pqfail);
+     pqadd(pe.id);
+    }
+ if (prioq_min(&pqdone,&pe))
+   if (pe.dt <= recent)
+    {
+     prioq_delmin(&pqdone);
+     messdone(pe.id);
+    }
+}
+
+
+/* this file is too long ---------------------------------------------- TODO */
+
+datetime_sec nexttodorun;
+DIR *tododir; /* if 0, have to opendir again */
+stralloc todoline = {0};
+char todobuf[SUBSTDIO_INSIZE];
+char todobufinfo[512];
+char todobufchan[CHANNELS][1024];
+
+void todo_init()
+{
+ tododir = 0;
+ nexttodorun = now();
+ trigger_set();
+}
+
+void todo_selprep(nfds,rfds,wakeup)
+int *nfds;
+fd_set *rfds;
+datetime_sec *wakeup;
+{
+ if (flagexitasap) return;
+ trigger_selprep(nfds,rfds);
+ if (tododir) *wakeup = 0;
+ if (*wakeup > nexttodorun) *wakeup = nexttodorun;
+}
+
+void todo_do(rfds)
+fd_set *rfds;
+{
+ struct stat st;
+ substdio ss; int fd;
+ substdio ssinfo; int fdinfo;
+ substdio sschan[CHANNELS];
+ int fdchan[CHANNELS];
+ int flagchan[CHANNELS];
+ struct prioq_elt pe;
+ char ch;
+ int match;
+ unsigned long id;
+ unsigned int len;
+ direntry *d;
+ int c;
+ unsigned long uid;
+ unsigned long pid;
+
+ fd = -1;
+ fdinfo = -1;
+ for (c = 0;c < CHANNELS;++c) fdchan[c] = -1;
+
+ if (flagexitasap) return;
+
+ if (!tododir)
+  {
+   if (!trigger_pulled(rfds))
+     if (recent < nexttodorun)
+       return;
+   trigger_set();
+   tododir = opendir("todo");
+   if (!tododir)
+    {
+     pausedir("todo");
+     return;
+    }
+   nexttodorun = recent + SLEEP_TODO;
+  }
+
+ d = readdir(tododir);
+ if (!d)
+  {
+   closedir(tododir);
+   tododir = 0;
+   return;
+  }
+ if (str_equal(d->d_name,".")) return;
+ if (str_equal(d->d_name,"..")) return;
+ len = scan_ulong(d->d_name,&id);
+ if (!len || d->d_name[len]) return;
+
+ fnmake_todo(id);
+
+ fd = open_read(fn.s);
+ if (fd == -1) { log3("warning: unable to open ",fn.s,"\n"); return; }
+
+ fnmake_mess(id);
+ /* just for the statistics */
+ if (stat(fn.s,&st) == -1)
+  { log3("warning: unable to stat ",fn.s,"\n"); goto fail; }
+
+ for (c = 0;c < CHANNELS;++c)
+  {
+   fnmake_chanaddr(id,c);
+   if (unlink(fn.s) == -1) if (errno != error_noent)
+    { log3("warning: unable to unlink ",fn.s,"\n"); goto fail; }
+  }
+
+ fnmake_info(id);
+ if (unlink(fn.s) == -1) if (errno != error_noent)
+  { log3("warning: unable to unlink ",fn.s,"\n"); goto fail; }
+
+ fdinfo = open_excl(fn.s);
+ if (fdinfo == -1)
+  { log3("warning: unable to create ",fn.s,"\n"); goto fail; }
+
+ strnum3[fmt_ulong(strnum3,id)] = 0;
+ log3("new msg ",strnum3,"\n");
+
+ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0;
+
+ substdio_fdbuf(&ss,read,fd,todobuf,sizeof(todobuf));
+ substdio_fdbuf(&ssinfo,write,fdinfo,todobufinfo,sizeof(todobufinfo));
+
+ uid = 0;
+ pid = 0;
+
+ for (;;)
+  {
+   if (getln(&ss,&todoline,&match,'\0') == -1)
+    {
+     /* perhaps we're out of memory, perhaps an I/O error */
+     fnmake_todo(id);
+     log3("warning: trouble reading ",fn.s,"\n"); goto fail;
+    }
+   if (!match) break;
+
+   switch(todoline.s[0])
+    {
+     case 'u':
+       scan_ulong(todoline.s + 1,&uid);
+       break;
+     case 'p':
+       scan_ulong(todoline.s + 1,&pid);
+       break;
+     case 'F':
+       if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1)
+	{
+	 fnmake_info(id);
+         log3("warning: trouble writing to ",fn.s,"\n"); goto fail;
+	}
+       log2("info msg ",strnum3);
+       strnum2[fmt_ulong(strnum2,(unsigned long) st.st_size)] = 0;
+       log2(": bytes ",strnum2);
+       log1(" from <"); logsafe(todoline.s + 1);
+       strnum2[fmt_ulong(strnum2,pid)] = 0;
+       log2("> qp ",strnum2);
+       strnum2[fmt_ulong(strnum2,uid)] = 0;
+       log2(" uid ",strnum2);
+       log1("\n");
+       break;
+     case 'T':
+       switch(rewrite(todoline.s + 1))
+	{
+	 case 0: nomem(); goto fail;
+	 case 2: c = 1; break;
+	 default: c = 0; break;
+        }
+       if (fdchan[c] == -1)
+	{
+	 fnmake_chanaddr(id,c);
+	 fdchan[c] = open_excl(fn.s);
+	 if (fdchan[c] == -1)
+          { log3("warning: unable to create ",fn.s,"\n"); goto fail; }
+	 substdio_fdbuf(&sschan[c]
+	   ,write,fdchan[c],todobufchan[c],sizeof(todobufchan[c]));
+	 flagchan[c] = 1;
+	}
+       if (substdio_bput(&sschan[c],rwline.s,rwline.len) == -1)
+        {
+	 fnmake_chanaddr(id,c);
+         log3("warning: trouble writing to ",fn.s,"\n"); goto fail;
+        }
+       break;
+     default:
+       fnmake_todo(id);
+       log3("warning: unknown record type in ",fn.s,"\n"); goto fail;
+    }
+  }
+
+ close(fd); fd = -1;
+
+ fnmake_info(id);
+ if (substdio_flush(&ssinfo) == -1)
+  { log3("warning: trouble writing to ",fn.s,"\n"); goto fail; }
+ if (fsync(fdinfo) == -1)
+  { log3("warning: trouble fsyncing ",fn.s,"\n"); goto fail; }
+ close(fdinfo); fdinfo = -1;
+
+ for (c = 0;c < CHANNELS;++c)
+   if (fdchan[c] != -1)
+    {
+     fnmake_chanaddr(id,c);
+     if (substdio_flush(&sschan[c]) == -1)
+      { log3("warning: trouble writing to ",fn.s,"\n"); goto fail; }
+     if (fsync(fdchan[c]) == -1)
+      { log3("warning: trouble fsyncing ",fn.s,"\n"); goto fail; }
+     close(fdchan[c]); fdchan[c] = -1;
+    }
+
+ fnmake_todo(id);
+ if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; }
+ if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; }
+ if (ch != '+')
+  {
+   log3("warning: qmail-clean unable to clean up ",fn.s,"\n");
+   return;
+  }
+
+ pe.id = id; pe.dt = now();
+ for (c = 0;c < CHANNELS;++c)
+   if (flagchan[c])
+     while (!prioq_insert(&pqchan[c],&pe)) nomem();
+
+ for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break;
+ if (c == CHANNELS)
+   while (!prioq_insert(&pqdone,&pe)) nomem();
+
+ return;
+
+ fail:
+ if (fd != -1) close(fd);
+ if (fdinfo != -1) close(fdinfo);
+ for (c = 0;c < CHANNELS;++c)
+   if (fdchan[c] != -1) close(fdchan[c]);
+}
+
+
+/* this file is too long ---------------------------------------------- MAIN */
+
+int getcontrols() { if (control_init() == -1) return 0;
+ if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0;
+ if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0;
+ if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0;
+ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0;
+ if (control_rldef(&bouncefrom,"control/bouncefrom",0,"MAILER-DAEMON") != 1) return 0;
+ if (control_rldef(&bouncehost,"control/bouncehost",1,"bouncehost") != 1) return 0;
+ if (control_rldef(&doublebouncehost,"control/doublebouncehost",1,"doublebouncehost") != 1) return 0;
+ if (control_rldef(&doublebounceto,"control/doublebounceto",0,"postmaster") != 1) return 0;
+ if (!stralloc_cats(&doublebounceto,"@")) return 0;
+ if (!stralloc_cat(&doublebounceto,&doublebouncehost)) return 0;
+ if (!stralloc_0(&doublebounceto)) return 0;
+ if (control_readfile(&locals,"control/locals",1) != 1) return 0;
+ if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0;
+ switch(control_readfile(&percenthack,"control/percenthack",0))
+  {
+   case -1: return 0;
+   case 0: if (!constmap_init(&mappercenthack,"",0,0)) return 0; break;
+   case 1: if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) return 0; break;
+  }
+ switch(control_readfile(&vdoms,"control/virtualdomains",0))
+  {
+   case -1: return 0;
+   case 0: if (!constmap_init(&mapvdoms,"",0,1)) return 0; break;
+   case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) return 0; break;
+  }
+ return 1; }
+
+stralloc newlocals = {0};
+stralloc newvdoms = {0};
+
+void regetcontrols()
+{
+ int r;
+
+ if (control_readfile(&newlocals,"control/locals",1) != 1)
+  { log1("alert: unable to reread control/locals\n"); return; }
+ r = control_readfile(&newvdoms,"control/virtualdomains",0);
+ if (r == -1)
+  { log1("alert: unable to reread control/virtualdomains\n"); return; }
+
+ constmap_free(&maplocals);
+ constmap_free(&mapvdoms);
+
+ while (!stralloc_copy(&locals,&newlocals)) nomem();
+ while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem();
+
+ if (r)
+  {
+   while (!stralloc_copy(&vdoms,&newvdoms)) nomem();
+   while (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) nomem();
+  }
+ else
+   while (!constmap_init(&mapvdoms,"",0,1)) nomem();
+}
+
+void reread()
+{
+ if (chdir(auto_qmail) == -1)
+  {
+   log1("alert: unable to reread controls: unable to switch to home directory\n");
+   return;
+  }
+ regetcontrols();
+ while (chdir("queue") == -1)
+  {
+   log1("alert: unable to switch back to queue directory; HELP! sleeping...\n");
+   sleep(10);
+  }
+}
+
+void main()
+{
+ int fd;
+ datetime_sec wakeup;
+ fd_set rfds;
+ fd_set wfds;
+ int nfds;
+ struct timeval tv;
+ int c;
+
+ if (chdir(auto_qmail) == -1)
+  { log1("alert: cannot start: unable to switch to home directory\n"); _exit(111); }
+ if (!getcontrols())
+  { log1("alert: cannot start: unable to read controls\n"); _exit(111); }
+ if (chdir("queue") == -1)
+  { log1("alert: cannot start: unable to switch to queue directory\n"); _exit(111); }
+ sig_pipeignore();
+ sig_termcatch(sigterm);
+ sig_alarmcatch(sigalrm);
+ sig_hangupcatch(sighup);
+ sig_childdefault();
+ umask(077);
+
+ fd = open_write("lock/sendmutex");
+ if (fd == -1)
+  { log1("alert: cannot start: unable to open mutex\n"); _exit(111); }
+ if (lock_exnb(fd) == -1)
+  { log1("alert: cannot start: qmail-send is already running\n"); _exit(111); }
+
+ numjobs = 0;
+ for (c = 0;c < CHANNELS;++c)
+  {
+   char ch, ch1;
+   int u;
+   int r;
+   do
+     r = read(chanfdin[c],&ch,1);
+   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];
+  }
+
+ fnmake_init();
+
+ comm_init();
+
+ pqstart();
+ job_init();
+ del_init();
+ pass_init();
+ todo_init();
+ cleanup_init();
+
+ while (!flagexitasap || !del_canexit())
+  {
+   recent = now();
+
+   if (flagrunasap) { flagrunasap = 0; pqrun(); }
+   if (flagreadasap) { flagreadasap = 0; reread(); }
+
+   wakeup = recent + SLEEP_FOREVER;
+   FD_ZERO(&rfds);
+   FD_ZERO(&wfds);
+   nfds = 1;
+
+   comm_selprep(&nfds,&wfds);
+   del_selprep(&nfds,&rfds);
+   pass_selprep(&wakeup);
+   todo_selprep(&nfds,&rfds,&wakeup);
+   cleanup_selprep(&wakeup);
+
+   if (wakeup <= recent) tv.tv_sec = 0;
+   else tv.tv_sec = wakeup - recent + SLEEP_FUZZ;
+   tv.tv_usec = 0;
+
+   if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) == -1)
+     if (errno == error_intr)
+       ;
+     else
+       log1("warning: trouble in select\n");
+   else
+    {
+     recent = now();
+
+     comm_do(&wfds);
+     del_do(&rfds);
+     todo_do(&rfds);
+     pass_do();
+     cleanup_do();
+    }
+  }
+ pqfinish();
+ log1("status: exiting\n");
+ _exit(0);
+}
diff -urN qmail-1.03/qmail-showctl.c qmail-1.03-with-plesk-8.6/qmail-showctl.c
--- qmail-1.03/qmail-showctl.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-showctl.c	2008-08-26 03:06:46.000000000 +0200
@@ -15,6 +15,7 @@
 #include "auto_patrn.h"
 #include "auto_spawn.h"
 #include "auto_split.h"
+#include "spf.h"
 
 stralloc me = {0};
 int meok;
@@ -257,6 +258,10 @@
 
   do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 ");
   do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ","");
+  do_int("spfbehavior","0","The SPF behavior is ","");
+  do_str("spfexp",0,SPF_DEFEXP,"The SPF default explanation is: 550 ");
+  do_str("spfguess",0,"","The guess SPF rules are: ");
+  do_str("spfrules",0,"","The local SPF rules are: ");
   do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds");
   do_int("timeoutremote","1200","SMTP client data timeout is "," seconds");
   do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds");
@@ -292,6 +297,10 @@
     if (str_equal(d->d_name,"rcpthosts")) continue;
     if (str_equal(d->d_name,"smtpgreeting")) continue;
     if (str_equal(d->d_name,"smtproutes")) continue;
+    if (str_equal(d->d_name,"spfbehavior")) continue;
+    if (str_equal(d->d_name,"spfexp")) continue;
+    if (str_equal(d->d_name,"spfguess")) continue;
+    if (str_equal(d->d_name,"spfrules")) continue;
     if (str_equal(d->d_name,"timeoutconnect")) continue;
     if (str_equal(d->d_name,"timeoutremote")) continue;
     if (str_equal(d->d_name,"timeoutsmtpd")) continue;
diff -urN qmail-1.03/qmail-smtpd.8 qmail-1.03-with-plesk-8.6/qmail-smtpd.8
--- qmail-1.03/qmail-smtpd.8	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-smtpd.8	2008-08-26 03:06:46.000000000 +0200
@@ -14,6 +14,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 
@@ -49,6 +58,19 @@
 .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 clientcrl.pem
+A list of Certificate Revocation Lists (CRLs). If present it
+should contain the CRLs of the CAs in 
+.I clientca.pem 
+and client certs will be checked for revocation.
+
 .TP 5
 .I databytes
 Maximum number of bytes allowed in a message,
@@ -76,6 +98,18 @@
 .B DATABYTES
 is set, it overrides
 .IR databytes .
+
+.TP 5
+.I dhparam1024.pem
+If these 1024 bit DH parameters are provided,
+.B qmail-smtpd
+will use them for TLS sessions instead of generating one on-the-fly 
+(which is very timeconsuming).
+.TP 5
+.I dhparam512.pem
+512 bit counterpart for 
+.B dhparam1024.pem. 
+
 .TP 5
 .I localiphost
 Replacement host name for local IP addresses.
@@ -151,6 +185,19 @@
 
 Envelope recipient addresses without @ signs are
 always allowed through.
+
+.TP 5
+.I rsa512.pem
+If this 512 bit RSA key is provided,
+.B qmail-smtpd
+will use it for TLS sessions instead of generating 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 +216,58 @@
 .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.
+.TP 5
+.I spfbehavior
+Set to a value between 1 and 6 to enable SPF checks; 0 to disable.
+1 selects 'annotate-only' mode, where
+.B qmail-smtpd
+will annotate incoming email with
+.B Received-SPF
+fields, but will not reject any messages.  2 will produce temporary
+failures on DNS lookup problems so you can make sure you always have
+meaningful Received-SPF headers.  3 selects 'reject' mode,
+where incoming mail will be rejected if the SPF record says 'fail'.  4
+selects a more stricter rejection mode, which is like 'reject' mode,
+except that incoming mail will also be rejected when the SPF record
+says 'softfail'.  5 will also reject when the SPF record says 'neutral',
+and 6 if no SPF records are available at all (or a syntax error was
+encountered). The contents of this file are overridden by the value of
+the
+.B SPFBEHAVIOR
+environment variable, if set.
+Default: 0.
+.TP 5
+.I spfexp
+You can add a line with a an SPF explanation that will be shown to the
+sender in case of a reject. It will override the default one. You can
+use SPF macro expansion.
+.TP 5
+.I spfguess
+You can add a line with SPF rules that will be checked if a sender
+domain doesn't have a SPF record. The local rules will also be used
+in this case.
+.TP 5
+.I spfrules
+You can add a line with SPF rules that will be checked before other SPF
+rules would fail.  This can be used to always allow certain machines to
+send certain mails.
 .SH "SEE ALSO"
 tcp-env(1),
 tcp-environ(5),
diff -urN qmail-1.03/qmail-smtpd.c qmail-1.03-with-plesk-8.6/qmail-smtpd.c
--- qmail-1.03/qmail-smtpd.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail-smtpd.c	2008-08-26 03:06:46.000000000 +0200
@@ -19,18 +19,53 @@
 #include "env.h"
 #include "now.h"
 #include "exit.h"
+#include <stdlib.h>
+#include <string.h>
 #include "rcpthosts.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "wait.h"
+#include "fd.h"
+#include "spf.h"
+#include "qmail-spp.h"
+
+int spp_val;
+
+#define USE_SMTPAUTH
+//#define SMTPAUTH_NETSCAPE_WORKAROUND
+#define USE_OLD_GREETING
+#define USE_NEW_GREETING
 
+#define AUTHCRAM
 #define MAXHOPS 100
 unsigned int databytes = 0;
 int timeout = 1200;
+unsigned int spfbehavior = 0;
+int rcptcounter = 0;
+int maxrcpt = -1;
+
+const char *protocol = "SMTP";
+
+#ifdef TLS
+# include "tls.h"
+# include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+void smtp_tls(char* arg);
+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;
@@ -40,7 +75,7 @@
 substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf);
 
 void flush() { substdio_flush(&ssout); }
-void out(s) char *s; { substdio_puts(&ssout,s); }
+void out(s) const 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); }
@@ -50,28 +85,41 @@
 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"); }
+#ifndef TLS
 void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
-void err_unimpl() { out("502 unimplemented (#5.5.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_unimpl(char* arg) { out("502 unimplemented (#5.5.1)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
+void err_relay() { out("553 we don't relay (#5.7.1)\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_noop(char* arg) { out("250 ok\r\n"); }
+void err_vrfy(char* arg) { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
 
 
 stralloc greeting = {0};
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
 
 void smtp_greet(code) char *code;
 {
   substdio_puts(&ssout,code);
   substdio_put(&ssout,greeting.s,greeting.len);
 }
-void smtp_help()
+void smtp_help(char* arg)
 {
   out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
 }
-void smtp_quit()
+void smtp_quit(char* arg)
 {
   smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
 }
@@ -81,6 +129,9 @@
 char *remoteinfo;
 char *local;
 char *relayclient;
+#ifdef USE_SMTPAUTH
+char *plesk_smtp_auth;
+#endif
 
 stralloc helohost = {0};
 char *fakehelo; /* pointer into helohost, or 0 */
@@ -97,11 +148,20 @@
 stralloc bmf = {0};
 struct constmap mapbmf;
 
+#ifdef USE_SMTPAUTH
+static unsigned char authenticated=0;
+#endif
+
 void setup()
 {
   char *x;
   unsigned long u;
  
+#ifdef USE_SMTPAUTH
+  extern struct commands smtpcommands[];
+  struct commands	*p = smtpcommands;
+#endif
+
   if (control_init() == -1) die_control();
   if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1)
     die_control();
@@ -109,8 +169,10 @@
   if (liphostok == -1) die_control();
   if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
   if (timeout <= 0) timeout = 1;
-
+  if (control_readint(&maxrcpt,"control/maxrcpt") == -1) die_control();
+  
   if (rcpthosts_init() == -1) die_control();
+  if (spp_init() == -1) die_control();
 
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
   if (bmfok == -1) die_control();
@@ -122,6 +184,19 @@
   if (x) { scan_ulong(x,&u); databytes = u; }
   if (!(databytes + 1)) --databytes;
  
+  if (control_readint(&spfbehavior,"control/spfbehavior") == -1)
+    die_control();
+  x = env_get("SPFBEHAVIOR");
+  if (x) { scan_ulong(x,&u); spfbehavior = u; }
+
+  if (control_readline(&spflocal,"control/spfrules") == -1) die_control();
+  if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+  if (control_readline(&spfguess,"control/spfguess") == -1) die_control();
+  if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+  if (control_rldef(&spfexp,"control/spfexp",0,SPF_DEFEXP) == -1)
+    die_control();
+  if (!stralloc_0(&spfexp)) die_nomem();
+
   remoteip = env_get("TCPREMOTEIP");
   if (!remoteip) remoteip = "unknown";
   local = env_get("TCPLOCALHOST");
@@ -131,6 +206,22 @@
   if (!remotehost) remotehost = "unknown";
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
+
+#ifdef USE_SMTPAUTH
+  if(relayclient)
+	authenticated = 1;
+  if(!(plesk_smtp_auth = env_get("SMTPAUTH")))
+	for(;p->text; p++)
+		if(!strcmp(p->text, "auth")) {
+			p->fun = err_unimpl;
+			break;
+		}
+#endif
+
+#ifdef TLS
+  if (env_get("SMTPS")) { smtps = 1; tls_init(); }
+  else
+#endif
   dohelo(remotehost);
 }
 
@@ -211,64 +302,197 @@
 int addrallowed()
 {
   int r;
+  if (env_get("SUBMISSION")) return 0; /* SUBMISSION is set if this is a
+                                          submission port (usually 587)
+                                          as per RFC2476, so only accept
+                                          if user has authenticated */
   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 addrrelay()
+{
+  int j;
+  j = addr.len;
+  while(--j >= 0)
+    if (addr.s[j] == '@') break;
+  if (j < 0) j = addr.len;
+  while(--j >= 0) {
+    if (addr.s[j] == '@') return 1;
+    if (addr.s[j] == '%') return 1;
+    if (addr.s[j] == '!') return 1;
+  }
+  return 0;
+}
+
 
 int seenmail = 0;
 int flagbarf; /* defined if seenmail */
+int flagbarfspf;
+int allowed;
+stralloc spfbarfmsg = {0};
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
 
 void smtp_helo(arg) char *arg;
 {
+  if(!spp_helo(arg)) return;
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
 }
 void smtp_ehlo(arg) char *arg;
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  if(!spp_helo(arg)) return;
+  smtp_greet("250-");
+#ifdef USE_SMTPAUTH
+  if(plesk_smtp_auth && !authenticated) {
+
+#ifdef USE_OLD_GREETING
+#ifdef SMTPAUTH_NETSCAPE_WORKAROUND
+  out("\r\n250-AUTH=LOGIN CRAM-MD5");
+#else
+  out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+#endif
+#endif
+
+#ifdef USE_NEW_GREETING
+#ifdef SMTPAUTH_NETSCAPE_WORKAROUND
+  out("\r\n250-AUTH LOGIN CRAM-MD5");
+#else
+  out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+#endif
+#endif
+  }
+
+#endif
+#ifdef TLS
+  if (!ssl) out("\r\n250-STARTTLS");
+#endif
+  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
 }
-void smtp_rset()
+void smtp_rset(char* arg)
 {
+  spp_rset();
   seenmail = 0;
   out("250 flushed\r\n");
 }
 void smtp_mail(arg) char *arg;
 {
+  int r;
+
+  rcptcounter = 0;
   if (!addrparse(arg)) { err_syntax(); return; }
+  if (!(spp_val = spp_mail())) return;
+  if (spp_val == 1)
   flagbarf = bmfcheck();
+
+  flagbarfspf = 0;
+  if (spfbehavior && !relayclient)
+     {
+      switch(r = spfcheck()) {
+      case SPF_OK: env_put2("SPFRESULT","pass"); break;
+      case SPF_NONE: env_put2("SPFRESULT","none"); break;
+      case SPF_UNKNOWN: env_put2("SPFRESULT","unknown"); break;
+      case SPF_NEUTRAL: env_put2("SPFRESULT","neutral"); break;
+      case SPF_SOFTFAIL: env_put2("SPFRESULT","softfail"); break;
+      case SPF_FAIL: env_put2("SPFRESULT","fail"); break;
+      case SPF_ERROR: env_put2("SPFRESULT","error"); break;
+      }
+      switch (r) {
+      case SPF_NOMEM:
+        die_nomem();
+      case SPF_ERROR:
+        if (spfbehavior < 2) break;
+       out("451 SPF lookup failure (#4.3.0)\r\n");
+       return;
+      case SPF_NONE:
+      case SPF_UNKNOWN:
+        if (spfbehavior < 6) break;
+      case SPF_NEUTRAL:
+        if (spfbehavior < 5) break;
+      case SPF_SOFTFAIL:
+        if (spfbehavior < 4) break;
+      case SPF_FAIL:
+        if (spfbehavior < 3) break;
+        if (!spfexplanation(&spfbarfmsg)) die_nomem();
+        if (!stralloc_0(&spfbarfmsg)) die_nomem();
+        flagbarfspf = 1;
+     }
+    }
+   else
+     env_unset("SPFRESULT");
+
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
   out("250 ok\r\n");
 }
+void err_spf() {
+  int i,j;
+
+  for(i = 0; i < spfbarfmsg.len; i = j + 1) {
+     j = byte_chr(spfbarfmsg.s + i, spfbarfmsg.len - i, '\n') + i;
+     if (j < spfbarfmsg.len) {
+       out("550-");
+       spfbarfmsg.s[j] = 0;
+       out(spfbarfmsg.s);
+       spfbarfmsg.s[j] = '\n';
+       out("\r\n");
+     } else {
+       out("550 ");
+       out(spfbarfmsg.s);
+       out(" (#5.7.1)\r\n");
+     }
+  }
+}
+
+int checkrcptcount() { 
+  if (maxrcpt == -1) {return 0;} 
+  else if (rcptcounter > maxrcpt) {return 1;} 
+  else {return 0;} 
+} 
+
 void smtp_rcpt(arg) char *arg; {
   if (!seenmail) { err_wantmail(); return; }
+  rcptcounter++;
+  if (checkrcptcount() == 1) {err_syntax(); return; } 
   if (!addrparse(arg)) { err_syntax(); return; }
+  if (addrrelay()) { err_relay(); return; }
   if (flagbarf) { err_bmf(); return; }
+  if (flagbarfspf) { err_spf(); return; }
+  if (!relayclient) allowed = addrallowed();
+  if (!(spp_val = spp_rcpt(allowed))) return;
+  if (spp_val == 1) {
   if (relayclient) {
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
     if (!stralloc_0(&addr)) die_nomem();
   }
   else
-    if (!addrallowed()) { err_nogateway(); return; }
+    if (!allowed) { err_nogateway(); return; }
+  }
+  spp_rcpt_accepted();
+    
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
   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();
@@ -316,8 +540,8 @@
         if (flagmaybex) if (pos == 7) ++*hops;
         if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0;
         if (flagmaybey) if (pos == 1) flaginheader = 0;
+        ++pos;
       }
-      ++pos;
       if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; }
     }
     switch(state) {
@@ -351,6 +575,25 @@
   }
 }
 
+void spfreceived()
+{
+  stralloc sa = {0};
+  stralloc rcvd_spf = {0};
+
+  if (!spfbehavior || relayclient) return;
+
+  if (!stralloc_copys(&rcvd_spf, "Received-SPF: ")) die_nomem();
+  if (!spfinfo(&sa)) die_nomem();
+  if (!stralloc_cat(&rcvd_spf, &sa)) die_nomem();
+  if (!stralloc_append(&rcvd_spf, "\n")) die_nomem();
+  if (bytestooverflow) {
+    bytestooverflow -= rcvd_spf.len;
+    if (bytestooverflow <= 0) qmail_fail(&qqt);
+  }
+  qmail_put(&qqt,rcvd_spf.s,rcvd_spf.len);
+}
+
+
 char accept_buf[FMT_ULONG];
 void acceptmessage(qp) unsigned long qp;
 {
@@ -365,20 +608,24 @@
   out("\r\n");
 }
 
-void smtp_data() {
+void smtp_data(char* arg) {
   int hops;
   unsigned long qp;
   char *qqx;
  
   if (!seenmail) { err_wantmail(); return; }
   if (!rcptto.len) { err_wantrcpt(); return; }
+  if (!spp_data()) 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,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
+  spfreceived();
+  qmail_put(&qqt,sppheaders.s,sppheaders.len); /* set in qmail-spp.c */
+  spp_rset();
   blast(&hops);
   hops = (hops >= MAXHOPS);
   if (hops) qmail_fail(&qqt);
@@ -394,28 +641,658 @@
   out("\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(0);
+  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) {
+    FILE *in = fopen("control/rsa512.pem", "r");
+    if (in) {
+      RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
+      fclose(in);
+      if (rsa) return rsa;
+    }
+  }
+  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 1024;
+  if (keylen == 512) {
+    FILE *in = fopen("control/dhparam512.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  if (keylen == 1024) {
+    FILE *in = fopen("control/dhparam1024.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  return DH_generate_parameters(keylen, DH_GENERATOR_2, 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 CLIENTCRL "control/clientcrl.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 standard 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_cats(&proto, ")")
+        || !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};
+  X509_STORE *store;
+  X509_LOOKUP *lookup;
+
+  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);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+  /* crl checking */
+  store = SSL_CTX_get_cert_store(ctx);
+  if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
+      (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
+    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
+                                X509_V_FLAG_CRL_CHECK_ALL);
+#endif
+
+  /* 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 public 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", 0) == -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_tmp_dh_callback(myssl, tmp_dh_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, "(")
+    || !stralloc_cats(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted) SMTP")) 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
+
+#ifdef USE_SMTPAUTH
+/* static unsigned char authenticated=0; */
+static unsigned char *base64_alphabet =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+static int unbase64(ch) int ch; {
+  int i;
+  if (ch == '=') return 0;
+  for (i = 0; i < 64; i++)
+    if (ch == base64_alphabet[i])
+      return i;
+  return 0;
+}
+static int base64_dec_buffer(str,dst,len) const char *str;void *dst;int len;
+{
+  int i, j, l;
+  unsigned char input[4], output[3], *result = (char *)dst;
+  if (str == 0)
+    return 0;
+  l = str_len(str);
+  if (dst == 0 || l > len)
+    return (l / 4) * 3;
+  memset(dst,0,len);
+  for (i=j=0; i<l; i +=4) {
+    input[0] = unbase64(str[i]);
+    input[1] = unbase64(str[i+1]);
+    input[2] = unbase64(str[i+2]);
+    input[3] = unbase64(str[i+3]);
+    output[0] = (input[0] << 2) | (input[1] >> 4);
+    output[1] = (input[1] << 4) | (input[2] >> 2);
+    output[2] = (input[2] << 6) | (input[3]);
+    result[j] = output[0];
+    if (str[i+1] == '=') return j+1;
+    result[j+1]=output[1];
+    if (str[i+2] == '=') return j+2;
+    result[j+2]=output[2];
+    j += 3;
+  }
+  return j;
+}
+static char **smtpauth_argv;
+static char *auth_argv[4];
+static stralloc smtpauth = {0};
+static char smtpauthlogin[65];
+static char smtpauthpass[65];
+static char smtpauthtimestamp[65];
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+
+void base64encode(stralloc *input, stralloc *output)
+{
+int	a=0,b=0,c=0;
+int	i, j;
+char	d, e, f, g;
+
+	if (input->len == 0)	return;
+
+	for (j=i=0; i< input->len ; i += 3)
+	{
+		a=input->s[i];
+		b= i+1 < input->len ? input->s[i+1]:0;
+		c= i+2 < input->len ? input->s[i+2]:0;
+
+		d=base64_alphabet[ a >> 2 ];
+		e=base64_alphabet[ ((a & 3 ) << 4) | (b >> 4)];
+		f=base64_alphabet[ ((b & 15) << 2) | (c >> 6)];
+		g=base64_alphabet[ c & 63 ];
+		if (i + 1 >= input->len) f='=';
+		if (i + 2 >= input->len) g='=';
+		stralloc_append(output,&d);
+		stralloc_append(output,&e);
+		stralloc_append(output,&f);
+		stralloc_append(output,&g);
+	}
+}
+
+static int smtpauth_getl(void) {
+  int i;
+  if (!stralloc_copys(&smtpauth, "")) return -1;
+  for (;;) {
+    if (!stralloc_readyplus(&smtpauth,1)) return -1;
+    i = substdio_get(&ssin, smtpauth.s + smtpauth.len, 1);
+    if (i != 1) return i;
+    if (smtpauth.s[smtpauth.len] == '\n') break;
+    ++smtpauth.len;
+  }
+  if (smtpauth.len > 0) if (smtpauth.s[smtpauth.len-1] == '\r') --smtpauth.len;
+  smtpauth.s[smtpauth.len] = 0;
+  return smtpauth.len;
+}
+
+static void smtpauth_authenticate(void)
+{
+  int st, pid, fds[2];
+  
+    if (pipe(fds)) {
+      out("535 pipe failure\r\n");
+      flush();
+      _exit(0);
+    }
+    /* spawn external program
+
+    external program should return '0' if it was successful,
+
+    submit: /bin/checkpassword /bin/true
+  
+    */
+    switch ((pid=fork())) {
+      case -1: die_nomem();
+      case 0: close(fds[1]);
+        fd_copy(3,fds[0]);
+        flush();
+        execvp(auth_argv[1], auth_argv+1);
+        die_nomem();
+    };
+    close(fds[0]);
+    write(fds[1], smtpauthlogin, str_len(smtpauthlogin)+1);
+    write(fds[1], smtpauthpass, str_len(smtpauthpass)+1);
+    if (str_len(smtpauthtimestamp))
+    {
+          write(fds[1], smtpauthtimestamp, str_len(smtpauthtimestamp)+1);
+    }
+    close(fds[1]);
+    wait_pid(&st, pid);
+    if (wait_exitcode(st) == 0) {
+      out("235 go ahead\r\n");
+      flush();
+      relayclient="";
+      authenticated=1;
+      return;
+    }
+    sleep(2);
+    out("535 auth failure\r\n"); 
+    flush(); 
+    return;
+}
+
+void smtp_auth(arg) char *arg; {
+  int ret,i,toolong,start;
+  char *helper;
+  /* netscape 4.5 sends AUTH LOGIN <base64encodedusername>
+     microsoft outlook express sends AUTH LOGIN
+
+     idea is simple
+
+     use an external program to test authority
+     if success, set 'RELAYCLIENT'
+     otherwise, let them know nicely (hangup)
+
+     note, i really don't like djb's coding style even though i'm using it here.
+     i think using spaces for tabs is bad.
+                                                -mrs.brisby@nimh.org
+  */
+  /* Here i've added support for other auth types.
+  
+  						-brush@elysium.pl	*/
+ // if (!authenticated)
+ // {
+    if ((ret=strncasecmp(arg,"login",5))==0)
+    {
+      while (arg && *arg && *arg != ' ') arg++;
+
+      /* pass over the space */
+      while (arg && *arg && *arg == ' ') arg++;
+
+      if (arg && *arg) {
+        /* here's the base64 encoded login */
+        base64_dec_buffer(arg, smtpauthlogin, sizeof(smtpauthlogin));
+      } else {
+        out("334 VXNlcm5hbWU6\r\n"); /* b64 <- 'Username:' */
+        flush();
+        if (smtpauth_getl() > 0)
+          base64_dec_buffer(smtpauth.s, smtpauthlogin, sizeof(smtpauthlogin));
+        else
+          die_read();
+      }
+      out("334 UGFzc3dvcmQ6\r\n"); /* b64 <- 'Password:' */
+      flush();
+      if (smtpauth_getl() > 0)
+        base64_dec_buffer(smtpauth.s, smtpauthpass, sizeof(smtpauthpass));
+      else
+        die_read();
+      smtpauthtimestamp[0]=0;
+      auth_argv[1]=smtpauth_argv[1];	/* change checkpass prg */
+      auth_argv[2]=smtpauth_argv[2];	/* change checkpass prg */
+      auth_argv[3]=NULL;			/* change checkpass prg */
+      smtpauth_authenticate();  
+      return;
+    }
+    else if ((ret=strncasecmp(arg,"plain",5))==0)  
+    {
+      // check for not obligatory argument - initial-response, rfc2554
+      // AUTH mechanism [initial-response]
+      int init_response_is_used;
+	  int len;
+
+	  // CHECK FOR initial-response
+	  i = 5;
+	  len = strlen(&arg[i]); // first 5 chars is plain check chars after ...
+	  while ((0 < len) && (' ' == arg[i])) {i++; len--;}
+      // (len >= 4) means that auth_id\0user_id\0passwd should be specified, auth_id can be empty
+	  init_response_is_used = (len >= 4);
+	  start = i;
+
+	  if (init_response_is_used) {
+		// DECODE base64 string
+        char buff[sizeof(smtpauthlogin)+sizeof(smtpauthlogin)+sizeof(smtpauthpass)+2];
+        len = base64_dec_buffer(&arg[start], buff, sizeof(buff));
+		stralloc_copyb(&smtpauth, buff, len);
+      } else {
+	    // ASK FOR auth line auth_id\0user_id\0passwd, auth_id can be empty 
+        out("334 ok. go on.\r\n");
+        flush();
+      }
+
+      if (init_response_is_used || (smtpauth_getl() > 0))
+      {
+		// SKIP auth_id and first null delimiter
+		i=0;
+        for (;0!=smtpauth.s[i] && i<sizeof(smtpauthlogin) && i<smtpauth.len;i++);
+		if (0==smtpauth.s[i] && i<smtpauth.len)
+			i++;
+
+		// READ user_id
+        toolong=1;
+		start = i;
+        for (;i<(sizeof(smtpauthlogin)+start) && i<smtpauth.len;i++)
+        {
+          smtpauthlogin[i-start]=smtpauth.s[i];
+          if(smtpauth.s[i]==0)
+          {
+            toolong=0;
+            break;
+          }
+        }
+        start=i;
+        if (toolong==1)
+        {
+          out("535 malformed input\r\n"); 
+          flush(); 
+          return;
+        }
+
+		// READ passwd
+        toolong=1;
+        i++;
+        start=i;
+        for (; i<(sizeof(smtpauthpass)+start) && i<smtpauth.len;i++)
+        {
+          smtpauthpass[i-start]=smtpauth.s[i];
+          if(smtpauth.s[i]==0)
+          {
+            toolong=0;
+            break;
+          }
+        }
+		if (i<(sizeof(smtpauthpass)+start) && (i == smtpauth.len)) {
+		  // auth string may haven't NULL char at the end, it is normal
+          smtpauthpass[i-start]=0;
+          toolong=0;
+		}
+
+        start=i;
+        if (toolong==1)
+        {
+          out("535 malformed input\r\n"); 
+          flush(); 
+          return;
+        }
+        smtpauthtimestamp[0]=0;
+        auth_argv[1]=smtpauth_argv[1];		/* change checkpass prg */
+        auth_argv[2]=smtpauth_argv[2];		/* change checkpass prg */
+        auth_argv[3]=NULL;			/* change checkpass prg */
+        smtpauth_authenticate();
+        return;
+      }
+      else
+      {
+        die_read();
+      }
+    }
+    else if ((ret=strncasecmp(arg,"cram-md5",8))==0)  
+    {
+      int r;
+      static stralloc me = {0};
+      static stralloc greet = {0};
+      static stralloc greetenc = {0};
+      char *s;
+      r = control_readline(&me,"control/me");
+      if (r != 1) 
+      { out("535 internal server error\r\n"); flush(); _exit(0);
+      }
+      for (r=0;r<me.len;r++)
+      {
+        if (me.s[r]=='\n' || me.s[r]=='\r')
+        {
+          me.s[r]=0;
+          break;
+        }
+      }
+      me.s[me.len]=0; // obscure fix but it works
+      s = unique;
+      s += fmt_uint(s,getpid());
+      *s++ = '.';
+      s += fmt_ulong(s,(unsigned long) now());
+      *s++ = '@';
+      *s++ = 0;
+      if (greet.len)
+      {
+	for (i=0;i<greet.len;i++)
+	{
+	  greet.s[i]=0;
+	}
+        greet.len=0;
+      }
+      stralloc_append(&greet,"<");
+      stralloc_cats(&greet,unique);
+      stralloc_cats(&greet,me.s);
+      stralloc_cats(&greet,">");
+      greet.s[greet.len]=0;	// obscure fix but it works
+      stralloc_readyplus(&greet,3);
+      if (greetenc.len)
+      {
+	for (i=0;i<greetenc.len;i++)
+	{
+	  greetenc.s[i]=0;
+	}
+        greetenc.len=0;
+      }
+      flush();
+      base64encode(&greet,&greetenc);
+      greetenc.s[greetenc.len]=0; // obscure fix but it works
+      out("334 ");
+      out(greetenc.s);
+      out("\r\n");
+      flush();
+      if (smtpauth_getl() > 0)
+      {
+        s=calloc((size_t) strlen(smtpauth.s),(size_t)1);
+        base64_dec_buffer(smtpauth.s, s, strlen(smtpauth.s));
+      }
+      helper=strtok(s," ");
+      if(helper!=NULL)
+      {
+        strncpy (smtpauthlogin,helper,64);
+      }
+      else
+      {
+        out("535 malformed input\r\n"); 
+        return;
+      }
+      helper=strtok(NULL," ");
+      if(helper!=NULL)
+      {
+        strncpy (smtpauthtimestamp,helper,64);
+      }
+      else
+      {
+        out("535 malformed input\r\n"); 
+        return;
+      }
+      strncpy (smtpauthpass,greet.s,64);
+      auth_argv[1]=smtpauth_argv[3];	/* change checkpass prg */
+      auth_argv[2]=smtpauth_argv[4];	/* change checkpass prg */
+      auth_argv[3]=NULL;		/* change checkpass prg */
+      smtpauth_authenticate();
+      return;
+    }
+    else
+    {
+      out("504 auth type not supported\r\n"); 
+      flush();
+      return;
+    }
+ // }
+ // else
+ // {
+ //     out("503 you are already authenticated\r\n"); 
+ //     flush(); 
+ //     return;
+ // }
+}
+#endif
+
 struct commands smtpcommands[] = {
   { "rcpt", smtp_rcpt, 0 }
 , { "mail", smtp_mail, 0 }
 , { "data", smtp_data, flush }
+#ifdef USE_SMTPAUTH
+, { "auth", smtp_auth, flush }
+#endif
 , { "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;
 {
+#ifdef USE_SMTPAUTH
+  smtpauth_argv = argv;
+#endif
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
   if (ipme_init() != 1) die_ipme();
+  if (spp_connect()) {
   smtp_greet("220 ");
   out(" ESMTP\r\n");
+  }
   if (commands(&ssin,&smtpcommands) == 0) die_read();
   die_nomem();
 }
diff -urN qmail-1.03/qmail-smtpd.c.orig qmail-1.03-with-plesk-8.6/qmail-smtpd.c.orig
--- qmail-1.03/qmail-smtpd.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-smtpd.c.orig	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,1285 @@
+#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 <stdlib.h>
+#include <string.h>
+#include "rcpthosts.h"
+#include "timeoutread.h"
+#include "timeoutwrite.h"
+#include "commands.h"
+#include "wait.h"
+#include "fd.h"
+#include "spf.h"
+#include "qmail-spp.h"
+
+int spp_val;
+
+#define USE_SMTPAUTH
+//#define SMTPAUTH_NETSCAPE_WORKAROUND
+#define USE_OLD_GREETING
+#define USE_NEW_GREETING
+
+#define AUTHCRAM
+#define MAXHOPS 100
+unsigned int databytes = 0;
+int timeout = 1200;
+unsigned int spfbehavior = 0;
+
+const char *protocol = "SMTP";
+
+#ifdef TLS
+# include "tls.h"
+# include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+void smtp_tls(char* arg);
+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) const 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"); }
+#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_unimpl(char* arg) { out("502 unimplemented (#5.5.1)\r\n"); }
+void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
+void err_relay() { out("553 we don't relay (#5.7.1)\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(char* arg) { out("250 ok\r\n"); }
+void err_vrfy(char* arg) { out("252 send some mail, i'll try my best\r\n"); }
+void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
+
+
+stralloc greeting = {0};
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
+
+void smtp_greet(code) char *code;
+{
+  substdio_puts(&ssout,code);
+  substdio_put(&ssout,greeting.s,greeting.len);
+}
+void smtp_help(char* arg)
+{
+  out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n");
+}
+void smtp_quit(char* arg)
+{
+  smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
+}
+
+char *remoteip;
+char *remotehost;
+char *remoteinfo;
+char *local;
+char *relayclient;
+#ifdef USE_SMTPAUTH
+char *plesk_smtp_auth;
+#endif
+
+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;
+
+#ifdef USE_SMTPAUTH
+static unsigned char authenticated=0;
+#endif
+
+void setup()
+{
+  char *x;
+  unsigned long u;
+ 
+#ifdef USE_SMTPAUTH
+  extern struct commands smtpcommands[];
+  struct commands	*p = smtpcommands;
+#endif
+
+  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 (spp_init() == -1) die_control();
+
+  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();
+ 
+  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;
+ 
+  if (control_readint(&spfbehavior,"control/spfbehavior") == -1)
+    die_control();
+  x = env_get("SPFBEHAVIOR");
+  if (x) { scan_ulong(x,&u); spfbehavior = u; }
+
+  if (control_readline(&spflocal,"control/spfrules") == -1) die_control();
+  if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+  if (control_readline(&spfguess,"control/spfguess") == -1) die_control();
+  if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+  if (control_rldef(&spfexp,"control/spfexp",0,SPF_DEFEXP) == -1)
+    die_control();
+  if (!stralloc_0(&spfexp)) die_nomem();
+
+  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");
+
+#ifdef USE_SMTPAUTH
+  if(relayclient)
+	authenticated = 1;
+  if(!(plesk_smtp_auth = env_get("SMTPAUTH")))
+	for(;p->text; p++)
+		if(!strcmp(p->text, "auth")) {
+			p->fun = err_unimpl;
+			break;
+		}
+#endif
+
+#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 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 addrallowed()
+{
+  int r;
+  if (env_get("SUBMISSION")) return 0; /* SUBMISSION is set if this is a
+                                          submission port (usually 587)
+                                          as per RFC2476, so only accept
+                                          if user has authenticated */
+  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 addrrelay()
+{
+  int j;
+  j = addr.len;
+  while(--j >= 0)
+    if (addr.s[j] == '@') break;
+  if (j < 0) j = addr.len;
+  while(--j >= 0) {
+    if (addr.s[j] == '@') return 1;
+    if (addr.s[j] == '%') return 1;
+    if (addr.s[j] == '!') return 1;
+  }
+  return 0;
+}
+
+
+int seenmail = 0;
+int flagbarf; /* defined if seenmail */
+int flagbarfspf;
+int allowed;
+stralloc spfbarfmsg = {0};
+stralloc mailfrom = {0};
+stralloc rcptto = {0};
+
+void smtp_helo(arg) char *arg;
+{
+  if(!spp_helo(arg)) return;
+  smtp_greet("250 "); out("\r\n");
+  seenmail = 0; dohelo(arg);
+}
+void smtp_ehlo(arg) char *arg;
+{
+  if(!spp_helo(arg)) return;
+  smtp_greet("250-");
+#ifdef USE_SMTPAUTH
+  if(plesk_smtp_auth && !authenticated) {
+
+#ifdef USE_OLD_GREETING
+#ifdef SMTPAUTH_NETSCAPE_WORKAROUND
+  out("\r\n250-AUTH=LOGIN CRAM-MD5");
+#else
+  out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+#endif
+#endif
+
+#ifdef USE_NEW_GREETING
+#ifdef SMTPAUTH_NETSCAPE_WORKAROUND
+  out("\r\n250-AUTH LOGIN CRAM-MD5");
+#else
+  out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+#endif
+#endif
+  }
+
+#endif
+#ifdef TLS
+  if (!ssl) out("\r\n250-STARTTLS");
+#endif
+  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  seenmail = 0; dohelo(arg);
+}
+void smtp_rset(char* arg)
+{
+  spp_rset();
+  seenmail = 0;
+  out("250 flushed\r\n");
+}
+void smtp_mail(arg) char *arg;
+{
+  int r;
+
+  if (!addrparse(arg)) { err_syntax(); return; }
+  if (!(spp_val = spp_mail())) return;
+  if (spp_val == 1)
+  flagbarf = bmfcheck();
+
+  flagbarfspf = 0;
+  if (spfbehavior && !relayclient)
+     {
+      switch(r = spfcheck()) {
+      case SPF_OK: env_put2("SPFRESULT","pass"); break;
+      case SPF_NONE: env_put2("SPFRESULT","none"); break;
+      case SPF_UNKNOWN: env_put2("SPFRESULT","unknown"); break;
+      case SPF_NEUTRAL: env_put2("SPFRESULT","neutral"); break;
+      case SPF_SOFTFAIL: env_put2("SPFRESULT","softfail"); break;
+      case SPF_FAIL: env_put2("SPFRESULT","fail"); break;
+      case SPF_ERROR: env_put2("SPFRESULT","error"); break;
+      }
+      switch (r) {
+      case SPF_NOMEM:
+        die_nomem();
+      case SPF_ERROR:
+        if (spfbehavior < 2) break;
+       out("451 SPF lookup failure (#4.3.0)\r\n");
+       return;
+      case SPF_NONE:
+      case SPF_UNKNOWN:
+        if (spfbehavior < 6) break;
+      case SPF_NEUTRAL:
+        if (spfbehavior < 5) break;
+      case SPF_SOFTFAIL:
+        if (spfbehavior < 4) break;
+      case SPF_FAIL:
+        if (spfbehavior < 3) break;
+        if (!spfexplanation(&spfbarfmsg)) die_nomem();
+        if (!stralloc_0(&spfbarfmsg)) die_nomem();
+        flagbarfspf = 1;
+     }
+    }
+   else
+     env_unset("SPFRESULT");
+
+  seenmail = 1;
+  if (!stralloc_copys(&rcptto,"")) die_nomem();
+  if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
+  if (!stralloc_0(&mailfrom)) die_nomem();
+  out("250 ok\r\n");
+}
+void err_spf() {
+  int i,j;
+
+  for(i = 0; i < spfbarfmsg.len; i = j + 1) {
+     j = byte_chr(spfbarfmsg.s + i, spfbarfmsg.len - i, '\n') + i;
+     if (j < spfbarfmsg.len) {
+       out("550-");
+       spfbarfmsg.s[j] = 0;
+       out(spfbarfmsg.s);
+       spfbarfmsg.s[j] = '\n';
+       out("\r\n");
+     } else {
+       out("550 ");
+       out(spfbarfmsg.s);
+       out(" (#5.7.1)\r\n");
+     }
+  }
+}
+void smtp_rcpt(arg) char *arg; {
+  if (!seenmail) { err_wantmail(); return; }
+  if (!addrparse(arg)) { err_syntax(); return; }
+  if (addrrelay()) { err_relay(); return; }
+  if (flagbarf) { err_bmf(); return; }
+  if (flagbarfspf) { err_spf(); return; }
+  if (!relayclient) allowed = addrallowed();
+  if (!(spp_val = spp_rcpt(allowed))) return;
+  if (spp_val == 1) {
+  if (relayclient) {
+    --addr.len;
+    if (!stralloc_cats(&addr,relayclient)) die_nomem();
+    if (!stralloc_0(&addr)) die_nomem();
+  }
+  else
+    if (!allowed) { err_nogateway(); return; }
+  }
+  spp_rcpt_accepted();
+    
+  if (!stralloc_cats(&rcptto,"T")) die_nomem();
+  if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
+  if (!stralloc_0(&rcptto)) die_nomem();
+  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;
+{
+  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);
+  }
+}
+
+void spfreceived()
+{
+  stralloc sa = {0};
+  stralloc rcvd_spf = {0};
+
+  if (!spfbehavior || relayclient) return;
+
+  if (!stralloc_copys(&rcvd_spf, "Received-SPF: ")) die_nomem();
+  if (!spfinfo(&sa)) die_nomem();
+  if (!stralloc_cat(&rcvd_spf, &sa)) die_nomem();
+  if (!stralloc_append(&rcvd_spf, "\n")) die_nomem();
+  if (bytestooverflow) {
+    bytestooverflow -= rcvd_spf.len;
+    if (bytestooverflow <= 0) qmail_fail(&qqt);
+  }
+  qmail_put(&qqt,rcvd_spf.s,rcvd_spf.len);
+}
+
+
+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(char* arg) {
+  int hops;
+  unsigned long qp;
+  char *qqx;
+ 
+  if (!seenmail) { err_wantmail(); return; }
+  if (!rcptto.len) { err_wantrcpt(); return; }
+  if (!spp_data()) 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);
+  spfreceived();
+  qmail_put(&qqt,sppheaders.s,sppheaders.len); /* set in qmail-spp.c */
+  spp_rset();
+  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");
+}
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+  if (ssl) err_unimpl(0);
+  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) {
+    FILE *in = fopen("control/rsa512.pem", "r");
+    if (in) {
+      RSA *rsa = PEM_read_RSAPrivateKey(in, NULL, NULL, NULL);
+      fclose(in);
+      if (rsa) return rsa;
+    }
+  }
+  return RSA_generate_key(keylen, RSA_F4, NULL, NULL);
+}
+
+DH *tmp_dh_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 1024;
+  if (keylen == 512) {
+    FILE *in = fopen("control/dhparam512.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  if (keylen == 1024) {
+    FILE *in = fopen("control/dhparam1024.pem", "r");
+    if (in) {
+      DH *dh = PEM_read_DHparams(in, NULL, NULL, NULL);
+      fclose(in);
+      if (dh) return dh;
+    }
+  }
+  return DH_generate_parameters(keylen, DH_GENERATOR_2, 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 CLIENTCRL "control/clientcrl.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 standard 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_cats(&proto, ")")
+        || !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};
+  X509_STORE *store;
+  X509_LOOKUP *lookup;
+
+  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);
+
+#if OPENSSL_VERSION_NUMBER >= 0x00907000L
+  /* crl checking */
+  store = SSL_CTX_get_cert_store(ctx);
+  if ((lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file())) &&
+      (X509_load_crl_file(lookup, CLIENTCRL, X509_FILETYPE_PEM) == 1))
+    X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
+                                X509_V_FLAG_CRL_CHECK_ALL);
+#endif
+
+  /* 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 public 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_tmp_dh_callback(myssl, tmp_dh_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, "(")
+    || !stralloc_cats(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted) SMTP")) 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
+
+#ifdef USE_SMTPAUTH
+/* static unsigned char authenticated=0; */
+static unsigned char *base64_alphabet =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+static int unbase64(ch) int ch; {
+  int i;
+  if (ch == '=') return 0;
+  for (i = 0; i < 64; i++)
+    if (ch == base64_alphabet[i])
+      return i;
+  return 0;
+}
+static int base64_dec_buffer(str,dst,len) const char *str;void *dst;int len;
+{
+  int i, j, l;
+  unsigned char input[4], output[3], *result = (char *)dst;
+  if (str == 0)
+    return 0;
+  l = str_len(str);
+  if (dst == 0 || l > len)
+    return (l / 4) * 3;
+  memset(dst,0,len);
+  for (i=j=0; i<l; i +=4) {
+    input[0] = unbase64(str[i]);
+    input[1] = unbase64(str[i+1]);
+    input[2] = unbase64(str[i+2]);
+    input[3] = unbase64(str[i+3]);
+    output[0] = (input[0] << 2) | (input[1] >> 4);
+    output[1] = (input[1] << 4) | (input[2] >> 2);
+    output[2] = (input[2] << 6) | (input[3]);
+    result[j] = output[0];
+    if (str[i+1] == '=') return j+1;
+    result[j+1]=output[1];
+    if (str[i+2] == '=') return j+2;
+    result[j+2]=output[2];
+    j += 3;
+  }
+  return j;
+}
+static char **smtpauth_argv;
+static char *auth_argv[4];
+static stralloc smtpauth = {0};
+static char smtpauthlogin[65];
+static char smtpauthpass[65];
+static char smtpauthtimestamp[65];
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+
+void base64encode(stralloc *input, stralloc *output)
+{
+int	a=0,b=0,c=0;
+int	i, j;
+char	d, e, f, g;
+
+	if (input->len == 0)	return;
+
+	for (j=i=0; i< input->len ; i += 3)
+	{
+		a=input->s[i];
+		b= i+1 < input->len ? input->s[i+1]:0;
+		c= i+2 < input->len ? input->s[i+2]:0;
+
+		d=base64_alphabet[ a >> 2 ];
+		e=base64_alphabet[ ((a & 3 ) << 4) | (b >> 4)];
+		f=base64_alphabet[ ((b & 15) << 2) | (c >> 6)];
+		g=base64_alphabet[ c & 63 ];
+		if (i + 1 >= input->len) f='=';
+		if (i + 2 >= input->len) g='=';
+		stralloc_append(output,&d);
+		stralloc_append(output,&e);
+		stralloc_append(output,&f);
+		stralloc_append(output,&g);
+	}
+}
+
+static int smtpauth_getl(void) {
+  int i;
+  if (!stralloc_copys(&smtpauth, "")) return -1;
+  for (;;) {
+    if (!stralloc_readyplus(&smtpauth,1)) return -1;
+    i = substdio_get(&ssin, smtpauth.s + smtpauth.len, 1);
+    if (i != 1) return i;
+    if (smtpauth.s[smtpauth.len] == '\n') break;
+    ++smtpauth.len;
+  }
+  if (smtpauth.len > 0) if (smtpauth.s[smtpauth.len-1] == '\r') --smtpauth.len;
+  smtpauth.s[smtpauth.len] = 0;
+  return smtpauth.len;
+}
+
+static void smtpauth_authenticate(void)
+{
+  int st, pid, fds[2];
+  
+    if (pipe(fds)) {
+      out("535 pipe failure\r\n");
+      flush();
+      _exit(0);
+    }
+    /* spawn external program
+
+    external program should return '0' if it was successful,
+
+    submit: /bin/checkpassword /bin/true
+  
+    */
+    switch ((pid=fork())) {
+      case -1: die_nomem();
+      case 0: close(fds[1]);
+        fd_copy(3,fds[0]);
+        flush();
+        execvp(auth_argv[1], auth_argv+1);
+        die_nomem();
+    };
+    close(fds[0]);
+    write(fds[1], smtpauthlogin, str_len(smtpauthlogin)+1);
+    write(fds[1], smtpauthpass, str_len(smtpauthpass)+1);
+    if (str_len(smtpauthtimestamp))
+    {
+          write(fds[1], smtpauthtimestamp, str_len(smtpauthtimestamp)+1);
+    }
+    close(fds[1]);
+    wait_pid(&st, pid);
+    if (wait_exitcode(st) == 0) {
+      out("235 go ahead\r\n");
+      flush();
+      relayclient="";
+      authenticated=1;
+      return;
+    }
+    sleep(2);
+    out("535 auth failure\r\n"); 
+    flush(); 
+    return;
+}
+
+void smtp_auth(arg) char *arg; {
+  int ret,i,toolong,start;
+  char *helper;
+  /* netscape 4.5 sends AUTH LOGIN <base64encodedusername>
+     microsoft outlook express sends AUTH LOGIN
+
+     idea is simple
+
+     use an external program to test authority
+     if success, set 'RELAYCLIENT'
+     otherwise, let them know nicely (hangup)
+
+     note, i really don't like djb's coding style even though i'm using it here.
+     i think using spaces for tabs is bad.
+                                                -mrs.brisby@nimh.org
+  */
+  /* Here i've added support for other auth types.
+  
+  						-brush@elysium.pl	*/
+ // if (!authenticated)
+ // {
+    if ((ret=strncasecmp(arg,"login",5))==0)
+    {
+      while (arg && *arg && *arg != ' ') arg++;
+
+      /* pass over the space */
+      while (arg && *arg && *arg == ' ') arg++;
+
+      if (arg && *arg) {
+        /* here's the base64 encoded login */
+        base64_dec_buffer(arg, smtpauthlogin, sizeof(smtpauthlogin));
+      } else {
+        out("334 VXNlcm5hbWU6\r\n"); /* b64 <- 'Username:' */
+        flush();
+        if (smtpauth_getl() > 0)
+          base64_dec_buffer(smtpauth.s, smtpauthlogin, sizeof(smtpauthlogin));
+        else
+          die_read();
+      }
+      out("334 UGFzc3dvcmQ6\r\n"); /* b64 <- 'Password:' */
+      flush();
+      if (smtpauth_getl() > 0)
+        base64_dec_buffer(smtpauth.s, smtpauthpass, sizeof(smtpauthpass));
+      else
+        die_read();
+      smtpauthtimestamp[0]=0;
+      auth_argv[1]=smtpauth_argv[1];	/* change checkpass prg */
+      auth_argv[2]=smtpauth_argv[2];	/* change checkpass prg */
+      auth_argv[3]=NULL;			/* change checkpass prg */
+      smtpauth_authenticate();  
+      return;
+    }
+    else if ((ret=strncasecmp(arg,"plain",5))==0)  
+    {
+      // check for not obligatory argument - initial-response, rfc2554
+      // AUTH mechanism [initial-response]
+      int init_response_is_used;
+	  int len;
+
+	  // CHECK FOR initial-response
+	  i = 5;
+	  len = strlen(&arg[i]); // first 5 chars is plain check chars after ...
+	  while ((0 < len) && (' ' == arg[i])) {i++; len--;}
+      // (len >= 4) means that auth_id\0user_id\0passwd should be specified, auth_id can be empty
+	  init_response_is_used = (len >= 4);
+	  start = i;
+
+	  if (init_response_is_used) {
+		// DECODE base64 string
+        char buff[sizeof(smtpauthlogin)+sizeof(smtpauthlogin)+sizeof(smtpauthpass)+2];
+        len = base64_dec_buffer(&arg[start], buff, sizeof(buff));
+		stralloc_copyb(&smtpauth, buff, len);
+      } else {
+	    // ASK FOR auth line auth_id\0user_id\0passwd, auth_id can be empty 
+        out("334 ok. go on.\r\n");
+        flush();
+      }
+
+      if (init_response_is_used || (smtpauth_getl() > 0))
+      {
+		// SKIP auth_id and first null delimiter
+		i=0;
+        for (;0!=smtpauth.s[i] && i<sizeof(smtpauthlogin) && i<smtpauth.len;i++);
+		if (0==smtpauth.s[i] && i<smtpauth.len)
+			i++;
+
+		// READ user_id
+        toolong=1;
+		start = i;
+        for (;i<(sizeof(smtpauthlogin)+start) && i<smtpauth.len;i++)
+        {
+          smtpauthlogin[i-start]=smtpauth.s[i];
+          if(smtpauth.s[i]==0)
+          {
+            toolong=0;
+            break;
+          }
+        }
+        start=i;
+        if (toolong==1)
+        {
+          out("535 malformed input\r\n"); 
+          flush(); 
+          return;
+        }
+
+		// READ passwd
+        toolong=1;
+        i++;
+        start=i;
+        for (; i<(sizeof(smtpauthpass)+start) && i<smtpauth.len;i++)
+        {
+          smtpauthpass[i-start]=smtpauth.s[i];
+          if(smtpauth.s[i]==0)
+          {
+            toolong=0;
+            break;
+          }
+        }
+		if (i<(sizeof(smtpauthpass)+start) && (i == smtpauth.len)) {
+		  // auth string may haven't NULL char at the end, it is normal
+          smtpauthpass[i-start]=0;
+          toolong=0;
+		}
+
+        start=i;
+        if (toolong==1)
+        {
+          out("535 malformed input\r\n"); 
+          flush(); 
+          return;
+        }
+        smtpauthtimestamp[0]=0;
+        auth_argv[1]=smtpauth_argv[1];		/* change checkpass prg */
+        auth_argv[2]=smtpauth_argv[2];		/* change checkpass prg */
+        auth_argv[3]=NULL;			/* change checkpass prg */
+        smtpauth_authenticate();
+        return;
+      }
+      else
+      {
+        die_read();
+      }
+    }
+    else if ((ret=strncasecmp(arg,"cram-md5",8))==0)  
+    {
+      int r;
+      static stralloc me = {0};
+      static stralloc greet = {0};
+      static stralloc greetenc = {0};
+      char *s;
+      r = control_readline(&me,"control/me");
+      if (r != 1) 
+      { out("535 internal server error\r\n"); flush(); _exit(0);
+      }
+      for (r=0;r<me.len;r++)
+      {
+        if (me.s[r]=='\n' || me.s[r]=='\r')
+        {
+          me.s[r]=0;
+          break;
+        }
+      }
+      me.s[me.len]=0; // obscure fix but it works
+      s = unique;
+      s += fmt_uint(s,getpid());
+      *s++ = '.';
+      s += fmt_ulong(s,(unsigned long) now());
+      *s++ = '@';
+      *s++ = 0;
+      if (greet.len)
+      {
+	for (i=0;i<greet.len;i++)
+	{
+	  greet.s[i]=0;
+	}
+        greet.len=0;
+      }
+      stralloc_append(&greet,"<");
+      stralloc_cats(&greet,unique);
+      stralloc_cats(&greet,me.s);
+      stralloc_cats(&greet,">");
+      greet.s[greet.len]=0;	// obscure fix but it works
+      stralloc_readyplus(&greet,3);
+      if (greetenc.len)
+      {
+	for (i=0;i<greetenc.len;i++)
+	{
+	  greetenc.s[i]=0;
+	}
+        greetenc.len=0;
+      }
+      flush();
+      base64encode(&greet,&greetenc);
+      greetenc.s[greetenc.len]=0; // obscure fix but it works
+      out("334 ");
+      out(greetenc.s);
+      out("\r\n");
+      flush();
+      if (smtpauth_getl() > 0)
+      {
+        s=calloc((size_t) strlen(smtpauth.s),(size_t)1);
+        base64_dec_buffer(smtpauth.s, s, strlen(smtpauth.s));
+      }
+      helper=strtok(s," ");
+      if(helper!=NULL)
+      {
+        strncpy (smtpauthlogin,helper,64);
+      }
+      else
+      {
+        out("535 malformed input\r\n"); 
+        return;
+      }
+      helper=strtok(NULL," ");
+      if(helper!=NULL)
+      {
+        strncpy (smtpauthtimestamp,helper,64);
+      }
+      else
+      {
+        out("535 malformed input\r\n"); 
+        return;
+      }
+      strncpy (smtpauthpass,greet.s,64);
+      auth_argv[1]=smtpauth_argv[3];	/* change checkpass prg */
+      auth_argv[2]=smtpauth_argv[4];	/* change checkpass prg */
+      auth_argv[3]=NULL;		/* change checkpass prg */
+      smtpauth_authenticate();
+      return;
+    }
+    else
+    {
+      out("504 auth type not supported\r\n"); 
+      flush();
+      return;
+    }
+ // }
+ // else
+ // {
+ //     out("503 you are already authenticated\r\n"); 
+ //     flush(); 
+ //     return;
+ // }
+}
+#endif
+
+struct commands smtpcommands[] = {
+  { "rcpt", smtp_rcpt, 0 }
+, { "mail", smtp_mail, 0 }
+, { "data", smtp_data, flush }
+#ifdef USE_SMTPAUTH
+, { "auth", smtp_auth, flush }
+#endif
+, { "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;
+{
+#ifdef USE_SMTPAUTH
+  smtpauth_argv = argv;
+#endif
+  sig_pipeignore();
+  if (chdir(auto_qmail) == -1) die_control();
+  setup();
+  if (ipme_init() != 1) die_ipme();
+  if (spp_connect()) {
+  smtp_greet("220 ");
+  out(" ESMTP\r\n");
+  }
+  if (commands(&ssin,&smtpcommands) == 0) die_read();
+  die_nomem();
+}
diff -urN qmail-1.03/qmail-spp.c qmail-1.03-with-plesk-8.6/qmail-spp.c
--- qmail-1.03/qmail-spp.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-spp.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2004-2005 Pawel Foremski <pjf@asn.pl>
+ *
+ * This program is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation; either 
+ * version 2 of the License, or (at your option) any later 
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *** Note
+ *
+ * This is the core of qmail-spp patch for qmail
+ *
+ * Why I made it a separate file? Because I wanted qmail-spp to apply more
+ * cleanly on heavily patched qmail sources and to make it bit simpler to
+ * maintain, so don't treat it as a library.
+ *
+ * "..." comments marks places where code for other SMTP commands should be
+ * added, if needed.
+ *
+ */
+
+#include "readwrite.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "control.h"
+#include "str.h"
+#include "byte.h"
+#include "env.h"
+#include "exit.h"
+#include "wait.h"
+#include "fork.h"
+#include "fd.h"
+#include "fmt.h"
+#include "getln.h"
+
+/* stuff needed from qmail-smtpd */
+extern void flush();
+extern void out();
+extern void die_nomem();
+extern stralloc addr;
+/* *** */
+
+stralloc sppheaders = {0};
+static int spprun = 0;
+static int sppfok = 0;
+static int sppret;
+static stralloc sppf = {0};
+static stralloc plugins_dummy = {0}, plugins_connect = {0}, plugins_helo = {0}, plugins_mail = {0},
+                plugins_rcpt = {0}, plugins_data = {0}, plugins_auth = {0}; /* ... */
+static stralloc error_mail = {0}, error_rcpt = {0}, error_data = {0}; /* ... */
+static stralloc sppmsg = {0};
+static char rcptcountstr[FMT_ULONG];
+static unsigned long rcptcount;
+static substdio ssdown;
+static char downbuf[128];
+
+static void err_spp(s1, s2) char *s1, *s2; { out("451 qmail-spp failure: "); out(s1); out(": "); out(s2); out(" (#4.3.0)\r\n"); }
+
+int spp_init()
+{
+  int i, len = 0;
+  stralloc *plugins_to;
+  char *x, *conffile = "control/smtpplugins";
+
+  if (!env_get("NOSPP")) {
+    spprun = 1;
+    plugins_to = &plugins_dummy;
+    x = env_get("SPPCONFFILE");
+    if (x && *x) conffile = x;
+    sppfok = control_readfile(&sppf, conffile, 0);
+    if (sppfok != 1) return -1;
+    for (i = 0; i < sppf.len; i += len) {
+      len = str_len(sppf.s + i) + 1;
+      if (sppf.s[i] == '[')
+        switch (sppf.s[i + 1]) {
+          case 'c': plugins_to = &plugins_connect; break;
+          case 'h': plugins_to = &plugins_helo; break;
+          case 'm': plugins_to = &plugins_mail; break;
+          case 'r': plugins_to = &plugins_rcpt; break;
+          case 'd': plugins_to = &plugins_data; break;
+          case 'a': plugins_to = &plugins_auth; break;
+          /* ... */
+          default: plugins_to = &plugins_dummy;
+        }
+      else
+        if (!stralloc_catb(plugins_to, sppf.s + i, len)) die_nomem();
+    }
+  }
+
+  return 0;
+}
+
+void sppout() { if (sppmsg.len) out(sppmsg.s); out("\r\n"); }
+
+int spp(plugins, addrenv) stralloc *plugins; char *addrenv;
+{
+  static int pipes[2];
+  static int i, pid, wstat, match, last;
+  static stralloc data = {0};
+  static char *(args[4]);
+  static stralloc *errors_to;
+
+  if (!spprun) return 1;
+  if (addrenv) if (!env_put2(addrenv, addr.s)) die_nomem();
+  last = 0;
+
+  for (i = 0; i < plugins->len; i += str_len(plugins->s + i) + 1) {
+    if (plugins->s[i] == ':')
+      { args[0] = "/bin/sh"; args[1] = "-c"; args[2] = plugins->s + i + 1; args[3] = 0; }
+    else
+      { args[0] = plugins->s + i; args[1] = 0; }
+
+    if (pipe(pipes) == -1)
+      { err_spp(plugins->s + i, "can't pipe()"); return 0; }
+
+    switch (pid = vfork()) {
+      case -1:
+        err_spp(plugins->s + i, "vfork() failed");
+        return 0;
+      case 0:
+        close(0); close(pipes[0]); fd_move(1, pipes[1]);
+        execv(*args, args);
+        _exit(120);
+    }
+
+    close(pipes[1]);
+    substdio_fdbuf(&ssdown, read, pipes[0], downbuf, sizeof(downbuf));
+    do {
+      if (getln(&ssdown, &data, &match, '\n') == -1) die_nomem();
+      if (data.len > 1) {
+        data.s[data.len - 1] = 0;
+        switch (data.s[0]) {
+          case 'H':
+            if (!stralloc_catb(&sppheaders, data.s + 1, data.len - 2)) die_nomem();
+            if (!stralloc_append(&sppheaders, "\n")) die_nomem();
+            break;
+          case 'C':
+            if (addrenv) {
+              if (!stralloc_copyb(&addr, data.s + 1, data.len - 1)) die_nomem();
+              if (!env_put2(addrenv, addr.s)) die_nomem();
+            }
+            break;
+          case 'S': if (!env_put(data.s + 1)) die_nomem(); break;
+          case 'U': if (!env_unset(data.s + 1)) die_nomem(); break;
+          case 'A': spprun = 0;
+          case 'O':
+          case 'N':
+          case 'D': last = 1; match = 0; break;
+          case 'E':
+          case 'R': last = 1; match = 0;
+          case 'P': out(data.s + 1); out("\r\n"); break;
+          case 'L':
+            switch (data.s[1]) {
+              case 'M': errors_to = &error_mail; break;
+              case 'R': errors_to = &error_rcpt; break;
+              case 'D': errors_to = &error_data; break;
+              /* ... */
+              default: errors_to = 0;
+            }
+            if (errors_to) {
+              if (!stralloc_catb(errors_to, data.s + 2, data.len - 3)) die_nomem();
+              if (!stralloc_catb(errors_to, "\r\n", 2)) die_nomem();
+            }
+            break;
+        }
+      }
+    } while (match);
+
+    close(pipes[0]);
+    if (wait_pid(&wstat,pid) == -1) { err_spp(plugins->s + i, "wait_pid() failed"); return 0; }
+    if (wait_crashed(wstat)) { err_spp(plugins->s + i, "child crashed"); return 0; }
+    if (wait_exitcode(wstat) == 120) { err_spp(plugins->s + i, "can't execute"); return 0; }
+
+    if (last)
+      switch (*data.s) {
+        case 'E': return 0;
+        case 'A':
+        case 'N': return 1;
+        case 'O': return 2;
+        case 'R':
+        case 'D': flush(); _exit(0);
+      }
+  }
+
+  return 1;
+}
+
+int spp_errors(errors) stralloc *errors;
+{
+  if (!errors->len) return 1;
+  if (!stralloc_0(errors)) die_nomem();
+  out(errors->s);
+  return 0;
+}
+
+int spp_connect() { return spp(&plugins_connect, 0); }
+
+int spp_helo(arg) char *arg;
+{
+  if (!env_put2("SMTPHELOHOST", arg)) die_nomem();
+  return spp(&plugins_helo, 0);
+}
+
+void spp_rset()
+{ 
+  if (!stralloc_copys(&sppheaders, "")) die_nomem();
+  if (!stralloc_copys(&error_mail, "")) die_nomem();
+  if (!stralloc_copys(&error_rcpt, "")) die_nomem();
+  if (!stralloc_copys(&error_data, "")) die_nomem();
+  /* ... */
+  rcptcount = 0;
+}
+
+int spp_mail()
+{
+  if (!spp_errors(&error_mail)) return 0;
+  rcptcount = 0;
+  return spp(&plugins_mail, "SMTPMAILFROM");
+}
+
+int spp_rcpt(allowed) int allowed;
+{
+  if (!spp_errors(&error_rcpt)) return 0;
+  rcptcountstr[fmt_ulong(rcptcountstr, rcptcount)] = 0;
+  if (!env_put2("SMTPRCPTCOUNT", rcptcountstr)) die_nomem();
+  if (!env_put2("SMTPRCPTHOSTSOK", allowed ? "1" : "0")) die_nomem();
+  sppret = spp(&plugins_rcpt, "SMTPRCPTTO");
+  return sppret;
+}
+
+void spp_rcpt_accepted() { rcptcount++; }
+
+int spp_data()
+{
+  if (!spp_errors(&error_data)) return 0;
+  return spp(&plugins_data, 0);
+}
+
+int spp_auth(method, user) char *method, *user;
+{
+  if (!env_put2("SMTPAUTHMETHOD", method)) die_nomem();
+  if (!env_put2("SMTPAUTHUSER", user)) die_nomem();
+  return spp(&plugins_auth, 0);
+}
+
+/* ... */
diff -urN qmail-1.03/qmail-spp.h qmail-1.03-with-plesk-8.6/qmail-spp.h
--- qmail-1.03/qmail-spp.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail-spp.h	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,14 @@
+#ifndef QMAIL_SPP_H
+#define QMAIL_SPP_H
+
+extern stralloc sppheaders;
+extern int spp_init();
+extern int spp_connect();
+extern int spp_helo();
+extern void spp_rset();
+extern int spp_mail();
+extern int spp_rcpt();
+extern int spp_data();
+extern int spp_auth();
+
+#endif
Binary files qmail-1.03/qmail-spp.o and qmail-1.03-with-plesk-8.6/qmail-spp.o differ
diff -urN qmail-1.03/qmail.c qmail-1.03-with-plesk-8.6/qmail.c
--- qmail-1.03/qmail.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail.c	2008-09-07 01:44:49.000000000 +0200
@@ -6,28 +6,49 @@
 #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;
 {
   int pim[2];
   int pie[2];
+  int pierr[2];
+  
+  setup_qqargs();
 
   if (pipe(pim) == -1) return -1;
   if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
- 
+  if (pipe(pierr) == -1) { 
+    close(pim[0]); close(pim[1]); 
+    close(pie[0]); close(pie[1]); 
+    close(pierr[0]); close(pierr[1]); 
+    return -1; 
+  }
+
   switch(qq->pid = vfork()) {
     case -1:
+      close(pierr[0]); close(pierr[1]);
       close(pim[0]); close(pim[1]);
       close(pie[0]); close(pie[1]);
       return -1;
     case 0:
       close(pim[1]);
       close(pie[1]);
+      close(pierr[0]); /* we want to receive data */
       if (fd_move(0,pim[0]) == -1) _exit(120);
       if (fd_move(1,pie[0]) == -1) _exit(120);
+      if (fd_move(4,pierr[1]) == -1) _exit(120);
       if (chdir(auto_qmail) == -1) _exit(61);
       execv(*binqqargs,binqqargs);
       _exit(120);
@@ -35,6 +56,7 @@
 
   qq->fdm = pim[1]; close(pim[0]);
   qq->fde = pie[1]; close(pie[0]);
+  qq->fderr = pierr[0]; close(pierr[1]);
   substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
   qq->flagerr = 0;
   return 0;
@@ -82,10 +104,22 @@
 {
   int wstat;
   int exitcode;
+  int match;
+  char ch;
+  static char errstr[256];
+  int len = 0;
 
   qmail_put(qq,"",1);
   if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
   close(qq->fde);
+  substdio_fdbuf(&qq->ss,read,qq->fderr,qq->buf,sizeof(qq->buf));
+  while( substdio_bget(&qq->ss,&ch,1) && len < 255){
+    errstr[len]=ch;
+    len++;
+  }
+  if (len > 0) errstr[len]='\0'; /* add str-term */
+
+  close(qq->fderr);
 
   if (wait_pid(&wstat,qq->pid) != qq->pid)
     return "Zqq waitpid surprise (#4.3.0)";
@@ -118,8 +152,11 @@
     case 81: return "Zqq internal bug (#4.3.0)";
     case 120: return "Zunable to exec qq (#4.3.0)";
     default:
+      if (exitcode == 82 && len > 2){
+        return errstr;
+      }
       if ((exitcode >= 11) && (exitcode <= 40))
-	return "Dqq permanent problem (#5.3.0)";
+        return "Dqq permanent problem (#5.3.0)";
       return "Zqq temporary problem (#4.3.0)";
   }
 }
diff -urN qmail-1.03/qmail.c-pre-simscan qmail-1.03-with-plesk-8.6/qmail.c-pre-simscan
--- qmail-1.03/qmail.c-pre-simscan	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail.c-pre-simscan	2008-09-07 01:34:57.000000000 +0200
@@ -0,0 +1,136 @@
+#include "substdio.h"
+#include "readwrite.h"
+#include "wait.h"
+#include "exit.h"
+#include "fork.h"
+#include "fd.h"
+#include "qmail.h"
+#include "auto_qmail.h"
+#include "env.h"
+
+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;
+{
+  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; }
+
+  switch(qq->pid = vfork()) {
+    case -1:
+      close(pim[0]); close(pim[1]);
+      close(pie[0]); close(pie[1]);
+      return -1;
+    case 0:
+      close(pim[1]);
+      close(pie[1]);
+      if (fd_move(0,pim[0]) == -1) _exit(120);
+      if (fd_move(1,pie[0]) == -1) _exit(120);
+      if (chdir(auto_qmail) == -1) _exit(61);
+      execv(*binqqargs,binqqargs);
+      _exit(120);
+  }
+
+  qq->fdm = pim[1]; close(pim[0]);
+  qq->fde = pie[1]; close(pie[0]);
+  substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf));
+  qq->flagerr = 0;
+  return 0;
+}
+
+unsigned long qmail_qp(qq) struct qmail *qq;
+{
+  return qq->pid;
+}
+
+void qmail_fail(qq) struct qmail *qq;
+{
+  qq->flagerr = 1;
+}
+
+void qmail_put(qq,s,len) struct qmail *qq; char *s; int len;
+{
+  if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1;
+}
+
+void qmail_puts(qq,s) struct qmail *qq; char *s;
+{
+  if (!qq->flagerr) if (substdio_puts(&qq->ss,s) == -1) qq->flagerr = 1;
+}
+
+void qmail_from(qq,s) struct qmail *qq; char *s;
+{
+  if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
+  close(qq->fdm);
+  substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf));
+  qmail_put(qq,"F",1);
+  qmail_puts(qq,s);
+  qmail_put(qq,"",1);
+}
+
+void qmail_to(qq,s) struct qmail *qq; char *s;
+{
+  qmail_put(qq,"T",1);
+  qmail_puts(qq,s);
+  qmail_put(qq,"",1);
+}
+
+char *qmail_close(qq)
+struct qmail *qq;
+{
+  int wstat;
+  int exitcode;
+
+  qmail_put(qq,"",1);
+  if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1;
+  close(qq->fde);
+
+  if (wait_pid(&wstat,qq->pid) != qq->pid)
+    return "Zqq waitpid surprise (#4.3.0)";
+  if (wait_crashed(wstat))
+    return "Zqq crashed (#4.3.0)";
+  exitcode = wait_exitcode(wstat);
+
+  switch(exitcode) {
+    case 115: /* compatibility */
+    case 11: return "Denvelope address too long for qq (#5.1.3)";
+    case 31: return "Dmail server permanently rejected message (#5.3.0)";
+    case 51: return "Zqq out of memory (#4.3.0)";
+    case 52: return "Zqq timeout (#4.3.0)";
+    case 53: return "Zqq write error or disk full (#4.3.0)";
+    case 0: if (!qq->flagerr) return ""; /* fall through */
+    case 54: return "Zqq read error (#4.3.0)";
+    case 55: return "Zqq unable to read configuration (#4.3.0)";
+    case 56: return "Zqq trouble making network connection (#4.3.0)";
+    case 61: return "Zqq trouble in home directory (#4.3.0)";
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 62: return "Zqq trouble creating files in queue (#4.3.0)";
+    case 71: return "Zmail server temporarily rejected message (#4.3.0)";
+    case 72: return "Zconnection to mail server timed out (#4.4.1)";
+    case 73: return "Zconnection to mail server rejected (#4.4.1)";
+    case 74: return "Zcommunication with mail server failed (#4.4.2)";
+    case 91: /* fall through */
+    case 81: return "Zqq internal bug (#4.3.0)";
+    case 120: return "Zunable to exec qq (#4.3.0)";
+    default:
+      if ((exitcode >= 11) && (exitcode <= 40))
+	return "Dqq permanent problem (#5.3.0)";
+      return "Zqq temporary problem (#4.3.0)";
+  }
+}
diff -urN qmail-1.03/qmail.h qmail-1.03-with-plesk-8.6/qmail.h
--- qmail-1.03/qmail.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/qmail.h	2008-09-07 01:27:21.000000000 +0200
@@ -8,6 +8,7 @@
   unsigned long pid;
   int fdm;
   int fde;
+  int fderr;
   substdio ss;
   char buf[1024];
 } ;
diff -urN qmail-1.03/qmail.h.rej qmail-1.03-with-plesk-8.6/qmail.h.rej
--- qmail-1.03/qmail.h.rej	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmail.h.rej	2008-09-07 01:41:27.000000000 +0200
@@ -0,0 +1,16 @@
+***************
+*** 8,13 ****
+    unsigned long pid;
+    int fdm;
+    int fde;
+    substdio ss;
+    char buf[1024];
+  } ;
+--- 8,14 ----
+    unsigned long pid;
+    int fdm;
+    int fde;
++   int fderr;
+    substdio ss;
+    char buf[1024];
+  } ;
diff -urN qmail-1.03/qmailqueue-patch qmail-1.03-with-plesk-8.6/qmailqueue-patch
--- qmail-1.03/qmailqueue-patch	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/qmailqueue-patch	2002-04-23 15:27:58.000000000 +0200
@@ -0,0 +1,72 @@
+From: Bruce Guenter <bguenter-djb-qmail@qcc.sk.ca>
+To: qmail@list.cr.yp.to
+Subject: QMAILQUEUE patch for qmail-1.03
+Date: Mon, 25 Jan 1999 15:37:21 -0600
+
+Greetings.
+
+Appended is a patch to qmail-1.03 that causes any program that would run
+qmail-queue to look for an environment variable QMAILQUEUE.  If it is
+present, it is used in place of the string "bin/qmail-queue" when
+running qmail-queue.  This could be used, for example, to add a program
+into the qmail-smtpd->qmail-queue pipeline that could do filtering,
+rewrite broken headers, etc. (this is my planned usage for it).
+
+This has undergone virtually no testing, but it looks so simple that it
+almost has to be correct.  No warranties, etc.  Note that the chdir to
+/var/qmail is always done before exec'ing the program.
+
+Does this look like a reasonable thing to do?
+-- 
+Bruce Guenter, QCC Communications Corp.  EMail: bruce.guenter@qcc.sk.ca
+Phone: (306)249-0220               WWW: http://www.qcc.sk.ca/~bguenter/
+
+diff -u qmail-1.03-orig/Makefile qmail-1.03/Makefile
+--- qmail-1.03-orig/Makefile	Mon Jun 15 04:53:16 1998
++++ qmail-1.03/Makefile	Tue Jan 19 10:52:24 1999
+@@ -1483,12 +1483,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
+diff -u qmail-1.03-orig/qmail.c qmail-1.03/qmail.c
+--- qmail-1.03-orig/qmail.c	Mon Jun 15 04:53:16 1998
++++ qmail-1.03/qmail.c	Tue Jan 19 09:57:36 1999
+@@ -6,14 +6,25 @@
+ #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;
+ {
+   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/spawn.c qmail-1.03-with-plesk-8.6/spawn.c
--- qmail-1.03/spawn.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/spawn.c	2008-08-26 03:06:46.000000000 +0200
@@ -5,6 +5,7 @@
 #include "substdio.h"
 #include "byte.h"
 #include "str.h"
+#include "alloc.h"
 #include "stralloc.h"
 #include "select.h"
 #include "exit.h"
@@ -63,7 +64,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 +74,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 +157,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 +206,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 +242,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/spf.c qmail-1.03-with-plesk-8.6/spf.c
--- qmail-1.03/spf.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/spf.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,878 @@
+#include "stralloc.h"
+#include "strsalloc.h"
+#include "alloc.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "ipme.h"
+#include "str.h"
+#include "fmt.h"
+#include "scan.h"
+#include "byte.h"
+#include "now.h"
+#include "dns.h"
+#include "case.h"
+#include "spf.h"
+
+#define SPF_EXT    -1
+#define SPF_SYNTAX -2
+
+#define WSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n')
+#define NXTOK(b, p, a) do { (b) = (p); \
+          while((p) < (a)->len && !WSPACE((a)->s[(p)])) ++(p); \
+          while((p) < (a)->len && WSPACE((a)->s[(p)])) (a)->s[(p)++] = 0; \
+        } while(0)
+
+/* this table and macro came from wget more or less */
+/* and was in turn stolen by me from libspf as is :) */
+const static unsigned char urlchr_table[256] =
+{
+  1,  1,  1,  1,   1,  1,  1,  1,   /* NUL SOH STX ETX  EOT ENQ ACK BEL */
+  1,  1,  1,  1,   1,  1,  1,  1,   /* BS  HT  LF  VT   FF  CR  SO  SI  */
+  1,  1,  1,  1,   1,  1,  1,  1,   /* DLE DC1 DC2 DC3  DC4 NAK SYN ETB */
+  1,  1,  1,  1,   1,  1,  1,  1,   /* CAN EM  SUB ESC  FS  GS  RS  US  */
+  1,  0,  1,  1,   0,  1,  1,  0,   /* SP  !   "   #    $   %   &   '   */
+  0,  0,  0,  1,   0,  0,  0,  1,   /* (   )   *   +    ,   -   .   /   */
+  0,  0,  0,  0,   0,  0,  0,  0,   /* 0   1   2   3    4   5   6   7   */
+  0,  0,  1,  1,   1,  1,  1,  1,   /* 8   9   :   ;    <   =   >   ?   */
+  1,  0,  0,  0,   0,  0,  0,  0,   /* @   A   B   C    D   E   F   G   */
+  0,  0,  0,  0,   0,  0,  0,  0,   /* H   I   J   K    L   M   N   O   */
+  0,  0,  0,  0,   0,  0,  0,  0,   /* P   Q   R   S    T   U   V   W   */
+  0,  0,  0,  1,   1,  1,  1,  0,   /* X   Y   Z   [    \   ]   ^   _   */
+  1,  0,  0,  0,   0,  0,  0,  0,   /* `   a   b   c    d   e   f   g   */
+  0,  0,  0,  0,   0,  0,  0,  0,   /* h   i   j   k    l   m   n   o   */
+  0,  0,  0,  0,   0,  0,  0,  0,   /* p   q   r   s    t   u   v   w   */
+  0,  0,  0,  1,   1,  1,  1,  1,   /* x   y   z   {    |   }   ~   DEL */
+
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+  1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,   1,  1,  1,  1,
+};
+
+
+extern stralloc addr;
+extern stralloc helohost;
+extern char *remoteip;
+extern char *local;
+
+extern stralloc spflocal;
+extern stralloc spfguess;
+extern stralloc spfexp;
+
+static stralloc sender_fqdn = {0};
+static stralloc explanation = {0};
+static stralloc expdomain = {0};
+static stralloc errormsg = {0};
+static char *received;
+
+static int recursion;
+static struct ip_address ip;
+
+static void hdr_pass() { received = "pass (%{xr}: %{xs} designates %{i} as permitted sender)"; };
+static void hdr_softfail() { received = "softfail (%{xr}: transitioning %{xs} does not designate %{i} as permitted sender)"; };
+static void hdr_fail() { received = "fail (%{xr}: %{xs} does not designate %{i} as permitted sender)"; };
+static void hdr_unknown() { received = "unknown (%{xr}: domain at %{d} does not designate permitted sender hosts)"; };
+static void hdr_neutral() { received = "neutral (%{xr}: %{i} is neither permitted nor denied by %{xs})"; };
+static void hdr_none() { received = "none (%{xr}: domain at %{d} does not designate permitted sender hosts)"; };
+static void hdr_unknown_msg(e) char *e; { stralloc_copys(&errormsg, e); received = "unknown (%{xr}: %{xe})"; };
+static void hdr_ext(e) char *e; { stralloc_copys(&errormsg, e); received = "unknown %{xe} (%{xr}: %{xs} uses mechanism not recognized by this client)"; };
+static void hdr_syntax() { received = "unknown (%{xr}: parse error in %{xs})"; };
+static void hdr_error(e) char *e; { stralloc_copys(&errormsg, e); received = "error (%{xr}: error in processing during lookup of %{d}: %{xe})"; };
+static void hdr_dns() { hdr_error("DNS problem"); }
+
+
+static int matchip(struct ip_address *net, int mask, struct ip_address *ip)
+{
+	int j;
+	int bytemask;
+
+	for (j = 0; j < 4 && mask > 0; ++j) {
+		if (mask > 8) bytemask = 8; else bytemask = mask;
+		mask -= bytemask;
+
+		if ((net->d[j] ^ ip->d[j]) & (0x100 - (1 << (8 - bytemask))))
+			return 0;
+	}
+	return 1;
+}
+
+static int getipmask(char *mask, int ipv6) {
+	unsigned long r;
+	int pos;
+
+	if (!mask) return 32;
+
+	pos = scan_ulong(mask, &r);
+	if (!pos || (mask[pos] && !(mask[pos] == '/' && ipv6))) return -1;
+	if (r > 32) return -1;
+
+	return r;
+}
+
+int spfget(stralloc *spf, stralloc *domain)
+{
+	strsalloc ssa = {0};
+	int j;
+	int begin, pos, i;
+	int r = SPF_NONE;
+
+	spf->len = 0;
+
+	switch(dns_txt(&ssa, domain)) {
+		case DNS_MEM: return SPF_NOMEM;
+		case DNS_SOFT: hdr_dns(); return SPF_ERROR;
+		case DNS_HARD: return SPF_NONE;
+	}
+
+	for (j = 0;j < ssa.len;++j) {
+		pos = 0;
+
+		NXTOK(begin, pos, &ssa.sa[j]);
+		if (str_len(ssa.sa[j].s + begin) < 6) continue;
+		if (!byte_equal(ssa.sa[j].s + begin,6,"v=spf1")) continue;
+		if (ssa.sa[j].s[begin + 6]) {
+			/* check for subversion */
+			if (ssa.sa[j].s[begin + 6] != '.') continue;
+			for(i = begin + 7;;++i)
+				if (!(ssa.sa[j].s[i] >= '0' && ssa.sa[j].s[i] <= '9')) break;
+			if (i == (begin + 7)) continue;
+			if (ssa.sa[j].s[i]) continue;
+		}
+
+		if (spf->len > 0) {
+			spf->len = 0;
+			hdr_unknown_msg("Multiple SPF records returned");
+			r = SPF_UNKNOWN;
+			break;
+		}
+		if (!stralloc_0(&ssa.sa[j])) return SPF_NOMEM;
+		if (!stralloc_copys(spf,ssa.sa[j].s + pos)) return SPF_NOMEM;
+		r = SPF_OK;
+	}
+
+	for (j = 0;j < ssa.len;++j)
+		alloc_free(ssa.sa[j].s);
+	alloc_free(ssa.sa);
+	return r;
+}
+
+static int spf_ptr(char *spec, char *mask);
+
+int spfsubst(stralloc *expand, char *spec, char *domain)
+{
+	static char hexdigits[] = "0123456789abcdef";
+	stralloc sa = {0};
+	char ch;
+	int digits = -1;
+	int urlencode = 0;
+	int reverse = 0;
+	int start = expand->len;
+	int i, pos;
+	char *split = ".";
+
+	if (!stralloc_readyplus(&sa,0)) return 0;
+
+	if (*spec == 'x') { i = 1; ++spec; } else i = 0;
+	ch = *spec++;
+	if (!ch) { alloc_free(sa.s); return 1; }
+	if (ch >= 'A' && ch <= 'Z') { ch += 32; urlencode = 1; }
+	if (i) ch -= 32;
+	while(*spec >= '0' && *spec <= '9') {
+		if (digits < 0) digits = 0;
+		if (digits >= 1000000) { digits = 10000000; continue; }
+		digits = (digits * 10) + (*spec - '0');
+		spec++;
+	}
+
+	while((*spec >= 'a' && *spec <= 'z') || (*spec >= 'A' && *spec <= 'Z')) {
+		if (*spec == 'r') reverse = 1;
+		spec++;
+	}
+
+	if (*spec) split = spec;
+
+	switch(ch) {
+		case 'l':
+			pos = byte_rchr(addr.s, addr.len, '@');
+			if (pos < addr.len) {
+				if (!stralloc_copyb(&sa, addr.s, pos)) return 0;
+			} else
+				if (!stralloc_copys(&sa, "postmaster")) return 0;
+			break;
+		case 's':
+			if (!stralloc_copys(&sa, addr.s)) return 0;
+			break;
+		case 'o':
+			pos = byte_rchr(addr.s, addr.len, '@') + 1;
+			if (pos > addr.len) break;
+			if (!stralloc_copys(&sa, addr.s + pos)) return 0;
+			break;
+		case 'd':
+			if (!stralloc_copys(&sa, domain)) return 0;
+			break;
+		case 'i':
+			if (!stralloc_ready(&sa, IPFMT)) return 0;
+			sa.len = ip_fmt(sa.s, &ip);
+			break;
+		case 't':
+			if (!stralloc_ready(&sa, FMT_ULONG)) return 0;
+			sa.len = fmt_ulong(sa.s, (unsigned long)now());
+			break;
+		case 'p':
+			if (!sender_fqdn.len)
+				spf_ptr(domain, 0);
+			if (sender_fqdn.len) {
+				if (!stralloc_copy(&sa, &sender_fqdn)) return 0;
+			} else
+				if (!stralloc_copys(&sa, "unknown")) return 0;
+			break;
+		case 'v': 
+			if (!stralloc_copys(&sa, "in-addr")) return 0;
+			break;
+		case 'h':
+			if (!stralloc_copys(&sa, helohost.s)) return 0; /* FIXME: FQDN? */
+			break;
+		case 'E':
+			if (errormsg.len && !stralloc_copy(&sa, &errormsg)) return 0;
+			break;
+		case 'R':
+			if (!stralloc_copys(&sa, local)) return 0;
+			break;
+		case 'S':
+			if (expdomain.len > 0) {
+				if (!stralloc_copys(&sa, "SPF record at ")) return 0;
+				if (!stralloc_cats(&sa, expdomain.s)) return 0;
+			} else {
+				if (!stralloc_copys(&sa, "local policy")) return 0;
+			}
+			break;
+	}
+
+	if (reverse) {
+		for(pos = 0; digits; ++pos) {
+			pos += byte_cspn(sa.s + pos, sa.len - pos, split);
+			if (pos >= sa.len) break;
+			if (!--digits) break;
+		}
+
+		for(; pos > 0; pos = i - 1) {
+			i = byte_rcspn(sa.s, pos, split) + 1;
+			if (i > pos) i = 0;
+			if (!stralloc_catb(expand, sa.s + i, pos - i)) return 0;
+			if (i > 0 && !stralloc_append(expand, ".")) return 0;
+		}
+	} else {
+		for(pos = sa.len; digits; --pos) {
+			i = byte_rcspn(sa.s, pos, split) + 1;
+			if (i > pos) { pos = 0; break; }
+			pos = i;
+			if (!--digits) break;
+		}
+
+		if (!stralloc_catb(expand, sa.s + pos, sa.len - pos)) return 0;
+		if (split[0] != '.' || split[1])
+			for(pos = 0; pos < expand->len; pos++) {
+				pos += byte_cspn(expand->s + pos, expand->len - pos, split);
+				if (pos < expand->len)
+					expand->s[pos] = '.';
+			}
+	}
+
+	if (urlencode) {
+		stralloc_copyb(&sa, expand->s + start, expand->len - start);
+		expand->len = start;
+
+		for(pos = 0; pos < sa.len; ++pos) {
+			ch = sa.s[pos];
+			if (urlchr_table[(unsigned char)ch]) {
+				if (!stralloc_readyplus(expand, 3)) return 0;
+				expand->s[expand->len++] = '%';
+				expand->s[expand->len++] = hexdigits[(unsigned char)ch >> 4];
+				expand->s[expand->len++] = hexdigits[(unsigned char)ch & 15];
+			} else
+				if (!stralloc_append(expand, &ch)) return 0;
+		}
+	}
+
+	alloc_free(sa.s);
+	return 1;
+}
+
+int spfexpand(stralloc *sa, char *spec, char *domain)
+{
+	char *p;
+	char append;
+	int pos;
+
+	if (!stralloc_readyplus(sa, 0)) return 0;
+	sa->len = 0;
+
+	for(p = spec; *p; p++) {
+		append = *p;
+		if (*p == '%') {
+			p++;
+			switch(*p) {
+				case '%': break;
+				case '_': append = ' '; break;
+				case '-': if (!stralloc_cats(sa, "%20")) return 0; continue;
+				case '{':
+					pos = str_chr(p, '}');
+					if (p[pos] != '}') { p--; break; }
+					p[pos] = 0;
+					if (!spfsubst(sa, p + 1, domain)) return 0;
+					p += pos;
+					continue;
+				default: p--;
+			}
+		}
+		if (!stralloc_append(sa, &append)) return 0;
+	}
+
+	return 1;
+}
+
+static int spflookup(stralloc *domain);
+
+static int spf_include(char *spec, char *mask)
+{
+	stralloc sa = {0};
+	int r;
+
+	if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+	r = spflookup(&sa);
+	alloc_free(sa.s);
+
+	switch(r) {
+		case SPF_NONE:
+			hdr_unknown();
+			r = SPF_UNKNOWN;
+			break;
+		case SPF_SYNTAX:
+			r = SPF_UNKNOWN;
+			break;
+		case SPF_NEUTRAL:
+		case SPF_SOFTFAIL:
+		case SPF_FAIL:
+			r = SPF_NONE;
+			break;
+	}
+
+	return r;
+}
+
+static int spf_a(char *spec, char *mask)
+{
+	stralloc sa = {0};
+	ipalloc ia = {0};
+	int ipmask = getipmask(mask, 1);
+	int r;
+	int j;
+
+	if (ipmask < 0) return SPF_SYNTAX;
+
+	if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+	switch(dns_ip(&ia, &sa)) {
+		case DNS_MEM: return SPF_NOMEM;
+		case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+		case DNS_HARD: r = SPF_NONE; break;
+		default:
+			r = SPF_NONE;
+			for(j = 0; j < ia.len; ++j)
+				if (matchip(&ia.ix[j].ip, ipmask, &ip)) {
+					r = SPF_OK;
+					break;
+				}
+	}
+
+	alloc_free(sa.s);
+	alloc_free(ia.ix);
+	return r;
+}
+
+static int spf_mx(char *spec, char *mask)
+{
+	stralloc sa = {0};
+	ipalloc ia = {0};
+	int ipmask = getipmask(mask, 1);
+	int random = now() + (getpid() << 16);
+	int r;
+	int j;
+
+	if (ipmask < 0) return SPF_SYNTAX;
+
+	if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+	switch(dns_mxip(&ia, &sa, random)) {
+		case DNS_MEM: return SPF_NOMEM;
+		case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+		case DNS_HARD: r = SPF_NONE; break;
+		default:
+			r = SPF_NONE;
+			for(j = 0; j < ia.len; ++j)
+				if (matchip(&ia.ix[j].ip, ipmask, &ip)) {
+					r = SPF_OK;
+					break;
+				}
+	}
+
+	alloc_free(sa.s);
+	alloc_free(ia.ix);
+	return r;
+}
+
+static int spf_ptr(char *spec, char *mask)
+{
+	strsalloc ssa = {0};
+	ipalloc ia = {0};
+	int len = str_len(spec);
+	int r;
+	int j, k;
+	int pos;
+
+	/* we didn't find host with the matching ip before */
+	if (sender_fqdn.len == 7 && str_equal(sender_fqdn.s, "unknown"))
+		return SPF_NONE;
+
+	/* the hostname found will probably be the same as before */
+	while (sender_fqdn.len) {
+		pos = sender_fqdn.len - len;
+		if (pos < 0) break;
+		if (pos > 0 && sender_fqdn.s[pos - 1] != '.') break;
+		if (case_diffb(sender_fqdn.s + pos, len, spec)) break;
+
+		return SPF_OK;
+	}
+
+	/* ok, either it's the first test or it's a very weird setup */
+
+	if (!stralloc_readyplus(&ssa, 0)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+	switch(dns_ptr(&ssa, &ip)) {
+		case DNS_MEM: return SPF_NOMEM;
+		case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+		case DNS_HARD: r = SPF_NONE; break;
+		default:
+			r = SPF_NONE;
+			for(j = 0; j < ssa.len; ++j) {
+				switch(dns_ip(&ia, &ssa.sa[j])) {
+					case DNS_MEM: return SPF_NOMEM;
+					case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+					case DNS_HARD: break;
+					default:
+						for(k = 0; k < ia.len; ++k)
+							if (matchip(&ia.ix[k].ip, 32, &ip)) {
+								if (!sender_fqdn.len)
+									if (!stralloc_copy(&sender_fqdn, &ssa.sa[j])) return SPF_NOMEM;
+
+								pos = ssa.sa[j].len - len;
+								if (pos < 0) continue;
+								if (pos > 0 && ssa.sa[j].s[pos - 1] != '.') continue;
+								if (case_diffb(ssa.sa[j].s + pos, len, spec)) continue;
+
+								stralloc_copy(&sender_fqdn, &ssa.sa[j]);
+								r = SPF_OK;
+								break;
+							}
+				}
+
+				if (r == SPF_ERROR) break;
+			}
+	}
+
+	for(j = 0;j < ssa.len;++j)
+		alloc_free(ssa.sa[j].s);
+
+	alloc_free(ssa.sa);
+	alloc_free(ia.ix);
+
+	if (!sender_fqdn.len)
+		if (!stralloc_copys(&sender_fqdn, "unknown")) return SPF_NOMEM;
+
+	return r;
+}
+
+static int spf_ip(char *spec, char *mask)
+{
+	struct ip_address net;
+	int ipmask = getipmask(mask, 0);
+
+	if (ipmask < 0) return SPF_SYNTAX;
+	if (!ip_scan(spec, &net)) return SPF_SYNTAX;
+
+	if (matchip(&net, ipmask, &ip)) return SPF_OK;
+
+	return SPF_NONE;
+}
+
+static int spf_exists(char *spec, char *mask)
+{
+	stralloc sa = {0};
+	ipalloc ia = {0};
+	int r;
+
+	if (!stralloc_copys(&sa, spec)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&ia, 0)) return SPF_NOMEM;
+
+	switch(dns_ip(&ia, &sa)) {
+		case DNS_MEM: return SPF_NOMEM;
+		case DNS_SOFT: hdr_dns(); r = SPF_ERROR; break;
+		case DNS_HARD: r = SPF_NONE; break;
+		default: r = SPF_OK;
+	}
+
+	alloc_free(sa.s);
+	alloc_free(ia.ix);
+	return r;
+}
+
+static struct mechanisms {
+  char *mechanism;
+  int (*func)(char *spec, char *mask);
+  unsigned int takes_spec  : 1;
+  unsigned int takes_mask  : 1;
+  unsigned int expands     : 1;
+  unsigned int filldomain  : 1;
+  int defresult            : 4;
+} mechanisms[] = {
+  { "all",      0,          0,0,0,0,SPF_OK   }
+, { "include",  spf_include,1,0,1,0,0        }
+, { "a",        spf_a,      1,1,1,1,0        }
+, { "mx",       spf_mx,     1,1,1,1,0        }
+, { "ptr",      spf_ptr,    1,0,1,1,0        }
+, { "ip4",      spf_ip,     1,1,0,0,0        }
+, { "ip6",      0,          1,1,0,0,SPF_NONE }
+, { "exists",   spf_exists, 1,0,1,0,0        }
+, { "extension",0,          1,1,0,0,SPF_EXT  }
+, { 0,          0,          1,1,0,0,SPF_EXT  }
+};
+
+static int spfmech(char *mechanism, char *spec, char *mask, char *domain)
+{
+	struct mechanisms *mech;
+	stralloc sa = {0};
+	int r;
+	int pos;
+
+	for(mech = mechanisms; mech->mechanism; mech++)
+		if (str_equal(mech->mechanism, mechanism)) break;
+
+	if (mech->takes_spec && !spec && mech->filldomain) spec = domain;
+	if (!mech->takes_spec != !spec) return SPF_SYNTAX;
+	if (!mech->takes_mask && mask) return SPF_SYNTAX;
+	if (!mech->func) return mech->defresult;
+
+	if (!stralloc_readyplus(&sa, 0)) return SPF_NOMEM;
+	if (mech->expands && spec != domain) {
+		if (!spfexpand(&sa, spec, domain)) return SPF_NOMEM;
+		for (pos = 0; (sa.len - pos) > 255;) {
+			pos += byte_chr(sa.s + pos, sa.len - pos, '.');
+			if (pos < sa.len) pos++;
+		}
+		sa.len -= pos;
+		if (pos > 0) byte_copy(sa.s, sa.len, sa.s + pos);
+		stralloc_0(&sa);
+		spec = sa.s;
+	}
+
+	r = mech->func(spec, mask);
+
+	alloc_free(sa.s);
+	return r;
+}
+
+static struct default_aliases {
+  char *alias;
+  int defret;
+} default_aliases[] = {
+  { "allow",   SPF_OK }
+, { "pass",    SPF_OK }
+, { "deny",    SPF_FAIL }
+, { "softdeny",SPF_SOFTFAIL }
+, { "fail",    SPF_FAIL }
+, { "softfail",SPF_SOFTFAIL }
+, { "unknown", SPF_NEUTRAL }
+, { 0,         SPF_UNKNOWN }
+};
+
+static int spflookup(stralloc *domain)
+{
+	stralloc spf = {0};
+	stralloc sa = {0};
+	struct default_aliases *da;
+	int main = !recursion;
+	int local_pos = -1;
+	int r, q;
+	int begin, pos;
+	int i;
+	int prefix;
+	int done;
+	int guessing = 0;
+	char *p;
+
+	if (!stralloc_readyplus(&spf, 0)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&sa, 0)) return SPF_NOMEM;
+
+	/* fallthrough result */
+	if (main) hdr_none();
+
+redirect:
+	if (++recursion > 20) {
+		alloc_free(spf.s);
+		alloc_free(sa.s);
+		hdr_unknown_msg("Maximum nesting level exceeded, possible loop");
+		return SPF_SYNTAX;
+	}
+
+	if (!stralloc_0(domain)) return SPF_NOMEM;
+	if (!stralloc_copy(&expdomain, domain)) return SPF_NOMEM;
+
+	r = spfget(&spf, domain);
+	if (r == SPF_NONE) {
+		if (!main) { alloc_free(spf.s); return r; }
+
+		if (spfguess.len) {
+			/* try to guess */
+			guessing = 1;
+			if (!stralloc_copys(&spf, spfguess.s)) return SPF_NOMEM;
+			if (!stralloc_append(&spf, " ")) return SPF_NOMEM;
+		} else
+			spf.len = 0;
+
+		/* append local rulest */
+		if (spflocal.len) {
+			local_pos = spf.len;
+			if (!stralloc_cats(&spf, spflocal.s)) return SPF_NOMEM;
+		}
+		if (!stralloc_0(&spf)) return SPF_NOMEM;
+
+		expdomain.len = 0;
+	} else if (r == SPF_OK) {
+		if (!stralloc_0(&spf)) return SPF_NOMEM;
+		if (main) hdr_neutral();
+		r = SPF_NEUTRAL;
+
+		/* try to add local rules before fail all mechs */
+		if (main && spflocal.len) {
+			pos = 0;
+			p = (char *) 0;
+			while(pos < spf.len) {
+				NXTOK(begin, pos, &spf);
+				if (!spf.s[begin]) continue;
+
+				if (p && spf.s[begin] != *p) p = (char *) 0;
+				if (!p && (spf.s[begin] == '-' || spf.s[begin] == '~' ||
+				           spf.s[begin] == '?')) p = &spf.s[begin];
+
+				if (p && p > spf.s && str_equal(spf.s + begin + 1, "all")) {
+					/* ok, we can insert the local rules at p */
+					local_pos = p - spf.s;
+
+					stralloc_readyplus(&spf, spflocal.len);
+					p = spf.s + local_pos;
+					byte_copyr(p + spflocal.len, spf.len - local_pos, p);
+					byte_copy(p, spflocal.len, spflocal.s);
+					spf.len += spflocal.len;
+
+					pos += spflocal.len;
+					break;
+				}
+			}
+
+			if (pos >= spf.len) pos = spf.len - 1;
+			for(i = 0; i < pos; i++)
+				if (!spf.s[i]) spf.s[i] = ' ';
+		}
+	} else {
+		alloc_free(spf.s);
+		return r;
+	}
+
+	pos = 0;
+	done = 0;
+	while(pos < spf.len) {
+		NXTOK(begin, pos, &spf);
+		if (!spf.s[begin]) continue;
+
+		/* in local ruleset? */
+		if (!done && local_pos >= 0 && begin >= local_pos) {
+			if (begin < (local_pos + spflocal.len))
+				expdomain.len = 0;
+			else
+				if (!stralloc_copy(&expdomain, domain))
+					return SPF_NOMEM;
+		}
+
+		for (p = spf.s + begin;*p;++p)
+			if (*p == ':' || *p == '/' || *p == '=') break;
+
+		if (*p == '=') {
+			*p++ = 0;
+
+			/* modifiers are simply handled here */
+			if (str_equal(spf.s + begin, "redirect")) {
+				if (done) continue;
+
+				if (!spfexpand(&sa, p, domain->s)) return SPF_NOMEM;
+				stralloc_copy(domain, &sa);
+
+				hdr_unknown();
+				r = SPF_UNKNOWN;
+
+				goto redirect;
+			} else if (str_equal(spf.s + begin, "default")) {
+				if (done) continue;
+
+				for(da = default_aliases; da->alias; ++da)
+					if (str_equal(da->alias, p)) break;
+
+				r = da->defret;
+			} else if (str_equal(spf.s + begin, "exp")) {
+				strsalloc ssa = {0};
+
+				if (!main) continue;
+
+				if (!stralloc_copys(&sa, p)) return SPF_NOMEM;
+				switch(dns_txt(&ssa, &sa)) {
+					case DNS_MEM: return SPF_NOMEM;
+					case DNS_SOFT: continue; /* FIXME... */
+					case DNS_HARD: continue;
+				}
+
+				explanation.len = 0;
+				for(i = 0; i < ssa.len; i++) {
+					if (!stralloc_cat(&explanation, &ssa.sa[i])) return SPF_NOMEM;
+					if (i < (ssa.len - 1))
+						if (!stralloc_append(&explanation, "\n")) return SPF_NOMEM;
+
+					alloc_free(ssa.sa[i].s);
+				}
+				if (!stralloc_0(&explanation)) return SPF_NOMEM;
+			} /* and unknown modifiers are ignored */
+		} else if (!done) {
+			if (!stralloc_copys(&sa, spf.s + begin)) return SPF_NOMEM;
+			if (!stralloc_0(&sa)) return SPF_NOMEM;
+
+			switch(spf.s[begin]) {
+				case '-': begin++; prefix = SPF_FAIL; break;
+				case '~': begin++; prefix = SPF_SOFTFAIL; break;
+				case '+': begin++; prefix = SPF_OK; break;
+				case '?': begin++; prefix = SPF_NEUTRAL; break;
+				default: prefix = SPF_OK;
+			}
+
+			if (*p == '/') {
+				*p++ = 0;
+				q = spfmech(spf.s + begin, 0, p, domain->s);
+			} else {
+				if (*p) *p++ = 0;
+				i = str_chr(p, '/');
+				if (p[i] == '/') {
+					p[i++] = 0;
+					q = spfmech(spf.s + begin, p, p + i, domain->s);
+				} else if (i > 0)
+					q = spfmech(spf.s + begin, p, 0, domain->s);
+				else
+					q = spfmech(spf.s + begin, 0, 0, domain->s);
+			}
+
+			if (q == SPF_OK) q = prefix;
+
+			switch(q) {
+				case SPF_OK: hdr_pass(); break;
+				case SPF_NEUTRAL: hdr_neutral(); break;
+				case SPF_SYNTAX: hdr_syntax(); break;
+				case SPF_SOFTFAIL: hdr_softfail(); break;
+				case SPF_FAIL: hdr_fail(); break;
+				case SPF_EXT: hdr_ext(sa.s); break;
+				case SPF_ERROR:
+					if (!guessing)
+						break;
+					if (local_pos >= 0 && begin >= local_pos)
+						break;
+					hdr_none();
+					q = SPF_NONE;
+					break;
+				case SPF_NONE: continue;
+			}
+
+			r = q;
+			done = 1; /* we're done, no more mechanisms */
+		}
+	}
+
+	/* we fell through, no local rule applied */
+	if (!done && !stralloc_copy(&expdomain, domain)) return SPF_NOMEM;
+
+	alloc_free(spf.s);
+	alloc_free(sa.s);
+	return r;
+}
+
+int spfcheck()
+{
+	stralloc domain = {0};
+	int pos;
+	int r;
+
+	pos = byte_rchr(addr.s, addr.len, '@') + 1;
+	if (pos < addr.len) {
+		if (!stralloc_copys(&domain, addr.s + pos)) return SPF_NOMEM;
+	} else {
+		pos = str_rchr(helohost.s, '@');
+		if (helohost.s[pos]) {
+			if (!stralloc_copys(&domain, helohost.s + pos + 1)) return SPF_NOMEM;
+		} else
+			if (!stralloc_copys(&domain, helohost.s)) return SPF_NOMEM;
+	}
+	if (!stralloc_copys(&explanation, spfexp.s)) return SPF_NOMEM;
+	if (!stralloc_0(&explanation)) return SPF_NOMEM;
+	recursion = 0;
+
+	if (!remoteip || !ip_scan(remoteip, &ip)) {
+		hdr_unknown_msg("No IP address in conversation");
+		return SPF_UNKNOWN;
+	}
+
+	if (!stralloc_readyplus(&expdomain, 0)) return SPF_NOMEM;
+	if (!stralloc_readyplus(&errormsg, 0)) return SPF_NOMEM;
+	expdomain.len = 0;
+	errormsg.len = 0;
+	sender_fqdn.len = 0;
+	received = (char *) 0;
+
+	if ((ip.d[0] == 127 && ip.d[1] == 0 && ip.d[2] == 0 && ip.d[3] == 1) || ipme_is(&ip))
+		{ hdr_pass(); r = SPF_OK; }
+	else
+		r = spflookup(&domain);
+
+	if (r < 0) r = SPF_UNKNOWN;
+
+	alloc_free(domain.s);
+	return r;
+}
+
+int spfexplanation(sa)
+stralloc *sa;
+{
+	return spfexpand(sa, explanation.s, expdomain.s);
+}
+
+int spfinfo(sa)
+stralloc *sa;
+{
+	stralloc tmp = {0};
+	if (!stralloc_copys(&tmp, received)) return 0;
+	if (!stralloc_0(&tmp)) return 0;
+	if (!spfexpand(sa, tmp.s, expdomain.s)) return 0;
+	alloc_free(tmp.s);
+	return 1;
+}
diff -urN qmail-1.03/spf.h qmail-1.03-with-plesk-8.6/spf.h
--- qmail-1.03/spf.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/spf.h	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,20 @@
+#ifndef SPF_H
+#define SPF_H
+
+#define SPF_OK       0
+#define SPF_NONE     1
+#define SPF_UNKNOWN  2
+#define SPF_NEUTRAL  3
+#define SPF_SOFTFAIL 4
+#define SPF_FAIL     5
+#define SPF_ERROR    6
+#define SPF_NOMEM    7
+
+#define SPF_DEFEXP   "See http://spf.pobox.com/" \
+                     "why.html?sender=%{S}&ip=%{I}&receiver=%{xR}"
+
+extern int spfcheck();
+extern int spfexplanation();
+extern int spfinfo();
+
+#endif
diff -urN qmail-1.03/spfquery.c qmail-1.03-with-plesk-8.6/spfquery.c
--- qmail-1.03/spfquery.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/spfquery.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,84 @@
+#include "substdio.h"
+#include "subfd.h"
+#include "stralloc.h"
+#include "alloc.h"
+#include "spf.h"
+#include "exit.h"
+
+void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); }
+void die_usage() { die(100,"fatal: invalid usage\nusage: spfquery <sender-ip> <sender-helo/ehlo> <envelope-from> [<local rules>] [<best guess rules>]\n"); }
+void die_nomem() { die(111,"fatal: out of memory\n"); }
+
+stralloc addr = {0};
+stralloc helohost = {0};
+char *remoteip;
+char *local;
+
+stralloc spflocal = {0};
+stralloc spfguess = {0};
+stralloc spfexp = {0};
+
+void main(argc,argv)
+int argc;
+char **argv;
+{
+	stralloc sa = {0};
+	int r;
+
+	if (argc < 4) die_usage();
+
+	remoteip = (char *)strdup(argv[1]);
+	local = "localhost";
+
+	if (!stralloc_copys(&helohost, argv[2])) die_nomem();
+	if (!stralloc_0(&helohost)) die_nomem();
+
+	if (!stralloc_copys(&addr, argv[3])) die_nomem();
+	if (!stralloc_0(&addr)) die_nomem();
+
+	if (argc > 4) {
+		if (!stralloc_copys(&spflocal, argv[4])) die_nomem();
+		if (spflocal.len && !stralloc_0(&spflocal)) die_nomem();
+	}
+
+	if (argc > 5) {
+		if (!stralloc_copys(&spfguess, argv[5])) die_nomem();
+		if (spfguess.len && !stralloc_0(&spfguess)) die_nomem();
+	}
+
+	if (argc > 6) {
+		if (!stralloc_copys(&spfexp, argv[6])) die_nomem();
+	} else
+		if (!stralloc_copys(&spfexp, SPF_DEFEXP)) die_nomem();
+	if (spfexp.len && !stralloc_0(&spfexp)) die_nomem();
+
+	dns_init(0);
+	r = spfcheck();
+	if (r == SPF_NOMEM) die_nomem();
+
+	substdio_puts(subfdout,"result=");
+	switch(r) {
+		case SPF_OK: substdio_puts(subfdout,"pass"); break;
+		case SPF_NONE: substdio_puts(subfdout,"none"); break;
+		case SPF_UNKNOWN: substdio_puts(subfdout,"unknown"); break;
+		case SPF_NEUTRAL: substdio_puts(subfdout,"neutral"); break;
+		case SPF_SOFTFAIL: substdio_puts(subfdout,"softfail"); break;
+		case SPF_FAIL: substdio_puts(subfdout,"fail"); break;
+		case SPF_ERROR: substdio_puts(subfdout,"error"); break;
+	}
+
+	if (r == SPF_FAIL) {
+		substdio_puts(subfdout,": ");
+		if (!spfexplanation(&sa)) die_nomem();
+		substdio_put(subfdout,sa.s,sa.len);
+	}
+
+	substdio_putsflush(subfdout,"\n");
+
+	substdio_puts(subfdout,"Received-SPF: ");
+	if (!spfinfo(&sa)) die_nomem();
+	substdio_put(subfdout,sa.s,sa.len);
+	substdio_putsflush(subfdout,"\n");
+
+	_exit(0);
+}
diff -urN qmail-1.03/ssl.lib qmail-1.03-with-plesk-8.6/ssl.lib
--- qmail-1.03/ssl.lib	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/ssl.lib	2008-08-26 03:08:06.000000000 +0200
@@ -0,0 +1 @@
+-lssl -lcrypto
diff -urN qmail-1.03/ssl_timeoutio.c qmail-1.03-with-plesk-8.6/ssl_timeoutio.c
--- qmail-1.03/ssl_timeoutio.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/ssl_timeoutio.c	2008-08-26 03:06:45.000000000 +0200
@@ -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/ssl_timeoutio.h qmail-1.03-with-plesk-8.6/ssl_timeoutio.h
--- qmail-1.03/ssl_timeoutio.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/ssl_timeoutio.h	2008-08-26 03:06:45.000000000 +0200
@@ -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/str.h qmail-1.03-with-plesk-8.6/str.h
--- qmail-1.03/str.h	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/str.h	2008-08-26 03:06:46.000000000 +0200
@@ -2,6 +2,7 @@
 #define STR_H
 
 extern unsigned int str_copy();
+extern unsigned int str_copyb();
 extern int str_diff();
 extern int str_diffn();
 extern unsigned int str_len();
diff -urN qmail-1.03/str_cpyb.c qmail-1.03-with-plesk-8.6/str_cpyb.c
--- qmail-1.03/str_cpyb.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/str_cpyb.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,18 @@
+#include "str.h"
+
+unsigned int str_copyb(s,t,max)
+register char *s;
+register char *t;
+unsigned int max;
+{
+  register int len;
+
+  len = 0;
+  while (max-- > 0) {
+    if (!(*s = *t)) return len; ++s; ++t; ++len;
+    if (!(*s = *t)) return len; ++s; ++t; ++len;
+    if (!(*s = *t)) return len; ++s; ++t; ++len;
+    if (!(*s = *t)) return len; ++s; ++t; ++len;
+  }
+  return len;
+}
diff -urN qmail-1.03/strerr_sys.c qmail-1.03-with-plesk-8.6/strerr_sys.c
--- qmail-1.03/strerr_sys.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/strerr_sys.c	2008-08-26 03:06:45.000000000 +0200
@@ -1,7 +1,7 @@
 #include "error.h"
 #include "strerr.h"
 
-struct strerr strerr_sys;
+struct strerr strerr_sys = { 0, 0, 0, 0 };
 
 void strerr_sysinit()
 {
diff -urN qmail-1.03/strsalloc.c qmail-1.03-with-plesk-8.6/strsalloc.c
--- qmail-1.03/strsalloc.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/strsalloc.c	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,7 @@
+#include "alloc.h"
+#include "gen_allocdefs.h"
+#include "stralloc.h"
+#include "strsalloc.h"
+
+GEN_ALLOC_readyplus(strsalloc,stralloc,sa,len,a,i,n,x,10,strsalloc_readyplus)
+GEN_ALLOC_append(strsalloc,stralloc,sa,len,a,i,n,x,10,strsalloc_readyplus,strsalloc_append)
diff -urN qmail-1.03/strsalloc.h qmail-1.03-with-plesk-8.6/strsalloc.h
--- qmail-1.03/strsalloc.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/strsalloc.h	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,12 @@
+#ifndef STRSALLOC_H
+#define STRSALLOC_H
+
+#include "stralloc.h"
+
+#include "gen_alloc.h"
+
+GEN_ALLOC_typedef(strsalloc,stralloc,sa,len,a)
+extern int strsalloc_readyplus();
+extern int strsalloc_append();
+
+#endif
diff -urN qmail-1.03/tcp-env.c qmail-1.03-with-plesk-8.6/tcp-env.c
--- qmail-1.03/tcp-env.c	1998-06-15 12:53:16.000000000 +0200
+++ qmail-1.03-with-plesk-8.6/tcp-env.c	2008-08-26 03:06:46.000000000 +0200
@@ -10,6 +10,7 @@
 #include "scan.h"
 #include "subgetopt.h"
 #include "ip.h"
+#include "strsalloc.h"
 #include "dns.h"
 #include "byte.h"
 #include "remoteinfo.h"
@@ -30,10 +31,13 @@
 
 char temp[IPFMT + FMT_ULONG];
 
+char *localhost = "localhost";
+
 void main(argc,argv)
 int argc;
 char *argv[];
 {
+ strsalloc ssa = {0};
  int dummy;
  char *proto;
  int opt;
@@ -70,23 +74,32 @@
    temp[fmt_ulong(temp,localport)] = 0;
    if (!env_put2("TCPLOCALPORT",temp)) die();
 
+   if (localport == 465)
+      if (!env_put2("SMTPS","true")) die();
+
    byte_copy(&iplocal,4,&salocal.sin_addr);
    temp[ip_fmt(temp,&iplocal)] = 0;
    if (!env_put2("TCPLOCALIP",temp)) die();
-
-   switch(dns_ptr(&localname,&iplocal))
-    {
-     case DNS_MEM: die();
-     case DNS_SOFT:
-       if (!stralloc_copys(&localname,"softdnserror")) die();
-     case 0:
-       if (!stralloc_0(&localname)) die();
-       case_lowers(localname.s);
-       if (!env_put2("TCPLOCALHOST",localname.s)) die();
-       break;
-     default:
-       if (!env_unset("TCPLOCALHOST")) die();
-    }
+   
+   if (!strncmp(temp, "127.0.0.1", 10)) {
+   		if (!env_put2("TCPLOCALHOST", localhost)) die();
+   } else {
+
+	   switch(dns_ptr(&ssa,&iplocal))
+	    {
+	     case DNS_MEM: die();
+	     case DNS_SOFT:
+	       if (!stralloc_copys(&localname,"softdnserror")) die();
+	     case 0:
+	       if (!stralloc_copy(&localname,&ssa.sa[0])) die();
+	       if (!stralloc_0(&localname)) die();
+	       case_lowers(localname.s);
+	       if (!env_put2("TCPLOCALHOST",localname.s)) die();
+	       break;
+	     default:
+	       if (!env_unset("TCPLOCALHOST")) die();
+	    }
+	}
 
    dummy = sizeof(saremote);
    if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die();
@@ -98,20 +111,26 @@
    byte_copy(&ipremote,4,&saremote.sin_addr);
    temp[ip_fmt(temp,&ipremote)] = 0;
    if (!env_put2("TCPREMOTEIP",temp)) die();
-
-   switch(dns_ptr(&remotename,&ipremote))
-    {
-     case DNS_MEM: die();
-     case DNS_SOFT:
-       if (!stralloc_copys(&remotename,"softdnserror")) die();
-     case 0:
-       if (!stralloc_0(&remotename)) die();
-       case_lowers(remotename.s);
-       if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
-       break;
-     default:
-       if (!env_unset("TCPREMOTEHOST")) die();
-    }
+   
+   if (!strncmp(temp, "127.0.0.1", 10)) {
+   		if (!env_put2("TCPREMOTEHOST", localhost)) die();
+   } else {   
+   
+	   switch(dns_ptr(&ssa,&ipremote))
+	    {
+	     case DNS_MEM: die();
+	     case DNS_SOFT:
+	       if (!stralloc_copys(&remotename,"softdnserror")) die();
+	     case 0:
+	       if (!stralloc_copy(&remotename,&ssa.sa[0])) die();
+	       if (!stralloc_0(&remotename)) die();
+	       case_lowers(remotename.s);
+	       if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
+	       break;
+	     default:
+	       if (!env_unset("TCPREMOTEHOST")) die();
+	    }
+	}
 
    if (!env_unset("TCPREMOTEINFO")) die();
    if (flagremoteinfo)
diff -urN qmail-1.03/tcp-env.c.orig qmail-1.03-with-plesk-8.6/tcp-env.c.orig
--- qmail-1.03/tcp-env.c.orig	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/tcp-env.c.orig	2008-08-26 03:06:46.000000000 +0200
@@ -0,0 +1,132 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include "sig.h"
+#include "stralloc.h"
+#include "str.h"
+#include "env.h"
+#include "fmt.h"
+#include "scan.h"
+#include "subgetopt.h"
+#include "ip.h"
+#include "dns.h"
+#include "byte.h"
+#include "remoteinfo.h"
+#include "exit.h"
+#include "case.h"
+
+void die() { _exit(111); }
+
+struct sockaddr_in salocal;
+unsigned long localport;
+struct ip_address iplocal;
+stralloc localname = {0};
+
+struct sockaddr_in saremote;
+unsigned long remoteport;
+struct ip_address ipremote;
+stralloc remotename = {0};
+
+char temp[IPFMT + FMT_ULONG];
+
+void main(argc,argv)
+int argc;
+char *argv[];
+{
+ int dummy;
+ char *proto;
+ int opt;
+ int flagremoteinfo;
+ unsigned long timeout;
+
+ sig_pipeignore();
+
+ flagremoteinfo = 1;
+ timeout = 30;
+ while ((opt = sgopt(argc,argv,"rRt:")) != sgoptdone)
+   switch(opt)
+    {
+     case 'r': flagremoteinfo = 1; break;
+     case 'R': flagremoteinfo = 0; break;
+     case 't': scan_ulong(sgoptarg,&timeout); break;
+    }
+
+ argv += sgoptind;
+ argc -= sgoptind;
+
+ if (argc < 1) die();
+ if (!env_init()) die();
+
+ proto = env_get("PROTO");
+ if (!proto || str_diff(proto,"TCP"))
+  {
+   if (!env_put("PROTO=TCP")) die();
+
+   dummy = sizeof(salocal);
+   if (getsockname(0,(struct sockaddr *) &salocal,&dummy) == -1) die();
+
+   localport = ntohs(salocal.sin_port);
+   temp[fmt_ulong(temp,localport)] = 0;
+   if (!env_put2("TCPLOCALPORT",temp)) die();
+
+   if (localport == 465)
+      if (!env_put2("SMTPS","true")) die();
+
+   byte_copy(&iplocal,4,&salocal.sin_addr);
+   temp[ip_fmt(temp,&iplocal)] = 0;
+   if (!env_put2("TCPLOCALIP",temp)) die();
+
+   switch(dns_ptr(&localname,&iplocal))
+    {
+     case DNS_MEM: die();
+     case DNS_SOFT:
+       if (!stralloc_copys(&localname,"softdnserror")) die();
+     case 0:
+       if (!stralloc_0(&localname)) die();
+       case_lowers(localname.s);
+       if (!env_put2("TCPLOCALHOST",localname.s)) die();
+       break;
+     default:
+       if (!env_unset("TCPLOCALHOST")) die();
+    }
+
+   dummy = sizeof(saremote);
+   if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die();
+
+   remoteport = ntohs(saremote.sin_port);
+   temp[fmt_ulong(temp,remoteport)] = 0;
+   if (!env_put2("TCPREMOTEPORT",temp)) die();
+
+   byte_copy(&ipremote,4,&saremote.sin_addr);
+   temp[ip_fmt(temp,&ipremote)] = 0;
+   if (!env_put2("TCPREMOTEIP",temp)) die();
+
+   switch(dns_ptr(&remotename,&ipremote))
+    {
+     case DNS_MEM: die();
+     case DNS_SOFT:
+       if (!stralloc_copys(&remotename,"softdnserror")) die();
+     case 0:
+       if (!stralloc_0(&remotename)) die();
+       case_lowers(remotename.s);
+       if (!env_put2("TCPREMOTEHOST",remotename.s)) die();
+       break;
+     default:
+       if (!env_unset("TCPREMOTEHOST")) die();
+    }
+
+   if (!env_unset("TCPREMOTEINFO")) die();
+   if (flagremoteinfo)
+    {
+     char *rinfo;
+     rinfo = remoteinfo_get(&ipremote,remoteport,&iplocal,localport,(int) timeout);
+     if (rinfo)
+       if (!env_put2("TCPREMOTEINFO",rinfo)) die();
+    }
+  }
+
+ sig_pipedefault();
+ execvp(*argv,argv);
+ die();
+}
diff -urN qmail-1.03/tls.c qmail-1.03-with-plesk-8.6/tls.c
--- qmail-1.03/tls.c	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/tls.c	2008-08-26 03:06:45.000000000 +0200
@@ -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); }
+
+#include <string.h>
+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/tls.h qmail-1.03-with-plesk-8.6/tls.h
--- qmail-1.03/tls.h	1970-01-01 01:00:00.000000000 +0100
+++ qmail-1.03-with-plesk-8.6/tls.h	2008-08-26 03:06:45.000000000 +0200
@@ -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

