diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/EXTTODO work/netqmail-1.06/EXTTODO
--- tmp/netqmail-1.06/EXTTODO	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/EXTTODO	2016-05-06 14:30:29.000000000 -0500
@@ -0,0 +1,114 @@
+EXTTODO by Claudio Jeker <jeker@n-r-g.com> and 
+Andre Oppermann <opi@nrg4u.com>
+(c) 1998,1999,2000,2001,2002 Internet Business Solutions Ltd.
+
+The EXTTODO patch is a part of the qmail-ldap patch.
+This patches for qmail come with NO WARRANTY.
+
+These patches are under the BSD license.
+
+RELEASE: 5. Jan. 2003
+
+EXTTODO:
+======================
+
+TOC:
+ WHAT DOES IT DO
+ INSTALL
+ CONFIG FILES
+ SETUP
+ BIG PICTURE
+
+NEWS:
+ 
+ This is the first release of the EXTTODO patch.
+
+================================================================================
+
+WHAT DOES IT DO
+
+ The exttodo patch addresses a problem known as the silly qmail (queue)
+ problem. This problem is found only on system with high injection rates.
+
+ qmail with a big local and remote concurrency could deliver a tremendous 
+ amount of messages but normally this can not be achieved because qmail-send
+ becomes a bottleneck on those high volumes servers.
+ qmail-send preprocesses all new messages before distributing them for local
+ or remote delivering. In one run qmail-send does one todo run but has the 
+ ability to close multiple jobs. Because of this layout qmail-send can not 
+ feed all the new available (local/remote) delivery slots and therefor it is 
+ not possible to achieve the maximum throughput.
+ This would be a minor problem if one qmail-send run could be done in extreme
+ short time but because of many file system calls (fsync and (un)link) a todo
+ run is expensive and throttles the throughput.
+
+ The exttodo patch tries to solve the problem by moving the todo routine into 
+ an external program. This reduces the run time in qmail-send.
+
+ exttodo adds a new program to qmail called qmail-todo. qmail-todo prepares
+ incoming messages for local and remote delivering (by creating info/<messid>
+ local/<messid> and remote/<messid> and removing todo/<messid>). See also
+ INTERNALS. As next qmail-todo transmits the <messid> to qmail-send which will
+ add this message into the priority queue which schedules the message for 
+ delivery. 
+
+INSTALL
+
+ To enable the exttodo patch you need to define EXTERNAL_TODO while compiling
+ qmail(-ldap) this can be done with the -D flag of cc (e.g. cc -DEXTERNAL_TODO).
+
+ NOTE: the exttodo patch can also be used on qmail systems without the 
+ qmail-ldap patch.
+ 
+================================================================================
+
+CONFIG FILES
+
+ No additional control files are used or needed.
+
+================================================================================
+
+SETUP
+
+ qmail-todo will be started by qmail-start and therefor no additional setup
+ is needed.
+
+ To verify that exttodo is running just check if qmail-todo is running.
+
+================================================================================
+
+BIG PICTURE
+
+               +-------+   +-------+
+               | clean |   | clean |
+               +--0-1--+   +--0-1--+       +-----------+
+         trigger  ^ |         ^ |        +->0,1 lspawn |
+            |     | v         | v       /  +-----------+
+ +-------+  v  +--2-3--+   +--5-6--+   /
+ |       |  |  |       0<--7     1,2<-+
+ | queue |--+--| todo  |   | send  |
+ |       |  |  |       1-->8     3,4<-+
+ +-------+     +-------+   +---0---+   \
+                               |        \  +-----------+
+                               v         +->0,1 rspwan |
+                           +---0---+       +-----------+
+                           | logger|
+                           +-------+
+
+Communication between qmail-send and qmail-todo
+
+todo -> send:
+   D[LRB]<mesgid>\0
+          Start delivery for new message with id <messid>.
+          the character L, R or B defines the type
+          of delivery, local, remote or both respectively.
+   L<string>\0
+          Dump string to the logger without adding additional \n or similar.
+send -> todo:
+   H      Got a SIGHUP reread ~/control/locals and ~/control/virtualdomains
+   X      Quit ASAP.
+
+qmail-todo sends "\0" terminated messages whereas qmail-send just send one
+character to qmail-todo.
+
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/EXTTODO-INFO work/netqmail-1.06/EXTTODO-INFO
--- tmp/netqmail-1.06/EXTTODO-INFO	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/EXTTODO-INFO	2016-05-06 14:30:29.000000000 -0500
@@ -0,0 +1,11 @@
+Files modified:
+Makefile
+EXTTODO
+FILES
+TARGETS
+qmail-send.c
+qmail-todo.c
+qmail-start.c
+hier.c
+install-big.c
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/FILES work/netqmail-1.06/FILES
--- tmp/netqmail-1.06/FILES	2007-11-30 14:22:54.000000000 -0600
+++ work/netqmail-1.06/FILES	2016-05-06 14:30:29.000000000 -0500
@@ -432,3 +432,4 @@
 tcp-environ.5
 constmap.h
 constmap.c
+qmail-todo.c
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/FILES.auth work/netqmail-1.06/FILES.auth
--- tmp/netqmail-1.06/FILES.auth	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/FILES.auth	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,27 @@
+The qmail-smtpd Auth patch modifies the following QMAIL 1.03 files:
+
+= TARGETS
+= Makefile
+= qmail-smtpd.c
+= qmail-smtpd.8
+= qmail-remote.c
+= qmail-remote.8
+= qmail-showctl.c
+= qmail-control.9
+
+Added files:
+
++ base64.c
++ base64.h
++ case_startb.c
++ hmac_md5.h
++ hmac_md5.c
++ global.h
++ md5.h
++ md5c.c
+
+Informational files:
+
+% install_auth.sh  (Installation shell script)
+% LICENSE.authentication (some sort of ...)
+% README.auth
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/FILES~ work/netqmail-1.06/FILES~
--- tmp/netqmail-1.06/FILES~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/FILES~	2007-11-30 14:22:54.000000000 -0600
@@ -0,0 +1,434 @@
+BLURB
+BLURB2
+BLURB3
+BLURB4
+README
+FAQ
+INSTALL
+INSTALL.alias
+INSTALL.ctl
+INSTALL.ids
+INSTALL.maildir
+INSTALL.mbox
+INSTALL-1.03
+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
+idedit.c
+conf-break
+auto_break.h
+conf-spawn
+auto_spawn.h
+chkspawn.c
+conf-split
+auto_split.h
+conf-patrn
+auto_patrn.h
+conf-users
+conf-groups
+auto_uids.h
+auto_usera.h
+extra.h
+addresses.5
+except.1
+bouncesaying.1
+condredirect.1
+dot-qmail.9
+envelopes.5
+forgeries.7
+forward.1
+maildir2mbox.1
+maildirmake.1
+maildirwatch.1
+mailsubj.1
+mbox.5
+preline.1
+qbiff.1
+qmail-clean.8
+qmail-command.8
+qmail-control.9
+qmail-getpw.9
+qmail-header.5
+qmail-inject.8
+qmail-limits.9
+qmail-local.8
+qmail-log.5
+qmail-lspawn.8
+qmail-newmrh.9
+qmail-newu.9
+qmail-pop3d.8
+qmail-popup.8
+qmail-pw2u.9
+qmail-qmqpc.8
+qmail-qmqpd.8
+qmail-qmtpd.8
+qmail-qread.8
+qmail-qstat.8
+qmail-queue.8
+qmail-remote.8
+qmail-rspawn.8
+qmail-send.9
+qmail-showctl.8
+qmail-smtpd.8
+qmail-start.9
+qmail-tcpok.8
+qmail-tcpto.8
+qmail-users.9
+qmail.7
+qreceipt.1
+splogger.8
+tcp-env.1
+config.sh
+config-fast.sh
+qmail-clean.c
+qmail-getpw.c
+qmail-inject.c
+qmail-local.c
+qmail-lspawn.c
+qmail-newmrh.c
+qmail-newu.c
+qmail-pop3d.c
+qmail-popup.c
+qmail-pw2u.c
+qmail-qmqpc.c
+qmail-qmqpd.c
+qmail-qmtpd.c
+qmail-qread.c
+qmail-qstat.sh
+qmail-queue.c
+qmail-remote.c
+qmail-rspawn.c
+qmail-send.c
+qmail-showctl.c
+qmail-smtpd.c
+qmail-start.c
+qmail-tcpok.c
+qmail-tcpto.c
+spawn.c
+dnscname.c
+dnsfq.c
+dnsip.c
+dnsmxip.c
+dnsptr.c
+hostname.c
+ipmeprint.c
+tcp-env.c
+sendmail.c
+qreceipt.c
+qsmhook.c
+qbiff.c
+forward.c
+preline.c
+predate.c
+except.c
+bouncesaying.c
+condredirect.c
+maildirmake.c
+maildir2mbox.c
+maildirwatch.c
+splogger.c
+qail.sh
+elq.sh
+pinq.sh
+qmail-upq.sh
+datemail.sh
+mailsubj.sh
+qlx.h
+rcpthosts.h
+rcpthosts.c
+commands.h
+commands.c
+dnsdoe.h
+dnsdoe.c
+fmtqfn.h
+fmtqfn.c
+gfrom.h
+gfrom.c
+myctime.h
+myctime.c
+newfield.h
+newfield.c
+qsutil.h
+qsutil.c
+readsubdir.h
+readsubdir.c
+received.h
+received.c
+tcpto.h
+tcpto.c
+tcpto_clean.c
+trigger.h
+trigger.c
+triggerpull.h
+triggerpull.c
+trynpbg1.c
+trysyslog.c
+conf-cc
+conf-ld
+home.sh
+home+df.sh
+proc.sh
+proc+df.sh
+binm1.sh
+binm2.sh
+binm3.sh
+binm1+df.sh
+binm2+df.sh
+binm3+df.sh
+find-systype.sh
+make-compile.sh
+make-load.sh
+make-makelib.sh
+trycpp.c
+warn-auto.sh
+auto-str.c
+auto-int.c
+auto-int8.c
+auto-gid.c
+auto-uid.c
+hier.c
+install.c
+instcheck.c
+install-big.c
+alloc.3
+alloc.h
+alloc.c
+alloc_re.c
+case.3
+case.h
+case_diffb.c
+case_diffs.c
+case_lowerb.c
+case_lowers.c
+case_starts.c
+cdb.3
+cdb.h
+cdb_hash.c
+cdb_seek.c
+cdb_unpack.c
+cdbmake.h
+cdbmake_add.c
+cdbmake_hash.c
+cdbmake_pack.c
+cdbmss.h
+cdbmss.c
+coe.3
+coe.h
+coe.c
+fd.h
+fd_copy.3
+fd_copy.c
+fd_move.3
+fd_move.c
+fifo_make.3
+fifo.h
+fifo.c
+trymkffo.c
+fork.h1
+fork.h2
+tryvfork.c
+now.3
+now.h
+now.c
+open.h
+open_append.c
+open_excl.c
+open_read.c
+open_trunc.c
+open_write.c
+seek.h
+seek_cur.c
+seek_end.c
+seek_set.c
+seek_trunc.c
+conf-qmail
+auto_qmail.h
+qmail.h
+qmail.c
+gen_alloc.h
+gen_allocdefs.h
+stralloc.3
+stralloc.h
+stralloc_eady.c
+stralloc_pend.c
+stralloc_copy.c
+stralloc_opyb.c
+stralloc_opys.c
+stralloc_cat.c
+stralloc_catb.c
+stralloc_cats.c
+stralloc_arts.c
+strerr.h
+strerr_sys.c
+strerr_die.c
+substdio.h
+substdio.c
+substdi.c
+substdo.c
+substdio_copy.c
+subfd.h
+subfderr.c
+subfdouts.c
+subfdout.c
+subfdins.c
+subfdin.c
+readwrite.h
+exit.h
+timeoutconn.h
+timeoutconn.c
+timeoutread.h
+timeoutread.c
+timeoutwrite.h
+timeoutwrite.c
+remoteinfo.h
+remoteinfo.c
+uint32.h1
+uint32.h2
+tryulong32.c
+wait.3
+wait.h
+wait_pid.c
+wait_nohang.c
+trywaitp.c
+sig.h
+sig_alarm.c
+sig_block.c
+sig_catch.c
+sig_pause.c
+sig_pipe.c
+sig_child.c
+sig_term.c
+sig_hup.c
+sig_misc.c
+sig_bug.c
+trysgact.c
+trysgprm.c
+env.3
+env.h
+env.c
+envread.c
+byte.h
+byte_chr.c
+byte_copy.c
+byte_cr.c
+byte_diff.c
+byte_rchr.c
+byte_zero.c
+str.h
+str_chr.c
+str_cpy.c
+str_diff.c
+str_diffn.c
+str_len.c
+str_rchr.c
+str_start.c
+lock.h
+lock_ex.c
+lock_exnb.c
+lock_un.c
+tryflock.c
+getln.3
+getln.h
+getln.c
+getln2.3
+getln2.c
+sgetopt.3
+sgetopt.h
+sgetopt.c
+subgetopt.3
+subgetopt.h
+subgetopt.c
+error.3
+error_str.3
+error_temp.3
+error.h
+error.c
+error_str.c
+error_temp.c
+fmt.h
+fmt_str.c
+fmt_strn.c
+fmt_uint.c
+fmt_uint0.c
+fmt_ulong.c
+scan.h
+scan_ulong.c
+scan_8long.c
+slurpclose.h
+slurpclose.c
+quote.h
+quote.c
+hfield.h
+hfield.c
+headerbody.h
+headerbody.c
+token822.h
+token822.c
+control.h
+control.c
+datetime.3
+datetime.h
+datetime.c
+datetime_un.c
+prioq.h
+prioq.c
+date822fmt.h
+date822fmt.c
+dns.h
+dns.c
+trylsock.c
+tryrsolv.c
+ip.h
+ip.c
+ipalloc.h
+ipalloc.c
+select.h1
+select.h2
+trysysel.c
+ndelay.h
+ndelay.c
+ndelay_off.c
+direntry.3
+direntry.h1
+direntry.h2
+trydrent.c
+prot.h
+prot.c
+chkshsgr.c
+warn-shsgr
+tryshsgr.c
+ipme.h
+ipme.c
+trysalen.c
+maildir.5
+maildir.h
+maildir.c
+tcp-environ.5
+constmap.h
+constmap.c
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/LICENSE.authentication work/netqmail-1.06/LICENSE.authentication
--- tmp/netqmail-1.06/LICENSE.authentication	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/LICENSE.authentication	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,43 @@
+AUTHOR
+======
+
+Author:
+	Dr. Erwin Hoffmann - FEHCom Germany
+Web-Site: 	
+	http://www.fehcom.de/qmail.html
+E-Mail: 	
+	feh@fehcom.de
+
+
+LICENSE
+=======
+
+qmail AUTHENTICATION is free software.
+This includes:
+	You can download and use qmail AUTHENTICATION (and parts of it) as you like.
+	You can modify the source code without notification to or permission by the author.
+Please check:
+	http://www.cr.yp.to/softwarelaw.html
+
+
+DEPENDENCIES
+============
+
+qmail AUTHENTICATION patches (modifies) parts of the qmail-1.03 source files.
+It should only be applied against the source as supplied by D.J. Bernstein.
+
+
+FITNESS
+=======
+
+The Author does not guarantee a specific fitness of qmail AUTHENTICATION.
+If you use qmail AUTHENTICATION, it's on your own risk.
+
+
+DISTRIBUTION
+============
+
+qmail AUTHENTICATION may be included in ports and packages under the following conditions:
+	The port/package has to show the current version number of qmail AUTHENTICATION.
+	All files (namely this) have to be included.
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/Makefile work/netqmail-1.06/Makefile
--- tmp/netqmail-1.06/Makefile	2007-11-30 14:22:54.000000000 -0600
+++ work/netqmail-1.06/Makefile	2016-05-06 14:32:04.000000000 -0500
@@ -1,5 +1,7 @@
 # Don't edit Makefile! Use conf-* for configuration.
 
+DEFINES=-DEXTERNAL_TODO # use to enable external todo
+
 SHELL=/bin/sh
 
 default: it
@@ -136,6 +138,18 @@
 compile auto_usera.c
 	./compile auto_usera.c
 
+base64.o: \
+compile base64.c base64.h stralloc.h substdio.h str.h
+	./compile base64.c
+
+md5c.o : \
+compile md5c.c md5.h
+	./compile md5c.c
+
+hmac_md5.o : \
+compile hmac_md5.c hmac_md5.h global.h
+	./compile hmac_md5.c
+
 binm1: \
 binm1.sh conf-qmail
 	cat binm1.sh \
@@ -703,7 +717,7 @@
 
 hier.o: \
 compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h
-	./compile hier.c
+	./compile $(DEFINES) hier.c
 
 home: \
 home.sh conf-qmail
@@ -755,7 +769,7 @@
 install-big.o: \
 compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \
 fifo.h
-	./compile install-big.c
+	./compile $(DEFINES) install-big.c
 
 install.o: \
 compile install.c substdio.h strerr.h error.h open.h readwrite.h \
@@ -808,7 +822,7 @@
 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 qmail-todo update_tmprsadh
 
 load: \
 make-load warn-auto.sh systype
@@ -1441,12 +1455,16 @@
 load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \
 timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \
 ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \
-substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib
+substdio.a error.a str.a fs.a auto_qmail.o \
+base64.o md5c.o hmac_md5.o \
+dns.lib socket.lib
 	./load qmail-remote control.o constmap.o timeoutread.o \
 	timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \
+	tls.o ssl_timeoutio.o -L/usr/local/ssl/lib -lssl -lcrypto \
 	ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \
 	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
-	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
+	base64.o md5c.o hmac_md5.o \
+	str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib`
 
 qmail-remote.0: \
 qmail-remote.8
@@ -1509,7 +1527,7 @@
 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
+	./compile $(DEFINES) qmail-send.c
 
 qmail-showctl: \
 load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
@@ -1536,12 +1554,13 @@
 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
+fs.a auto_qmail.o base64.o socket.lib
 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
 	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+	tls.o ssl_timeoutio.o ndelay.a -L/usr/local/ssl/lib -lssl -lcrypto \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o base64.o  `cat \
 	socket.lib`
 
 qmail-smtpd.0: \
@@ -1553,7 +1572,7 @@
 substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
 error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
 substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
-exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h base64.h
 	./compile qmail-smtpd.c
 
 qmail-start: \
@@ -1574,7 +1593,7 @@
 
 qmail-start.o: \
 compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h
-	./compile qmail-start.c
+	./compile $(DEFINES) qmail-start.c
 
 qmail-tcpok: \
 load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \
@@ -1606,6 +1625,20 @@
 fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h
 	./compile qmail-tcpto.c
 
+qmail-todo: \
+load qmail-todo.o control.o constmap.o trigger.o fmtqfn.o now.o \
+readsubdir.o case.a ndelay.a getln.a sig.a open.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+	./load qmail-todo control.o constmap.o trigger.o fmtqfn.o now.o \
+	readsubdir.o case.a ndelay.a getln.a sig.a open.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+
+qmail-todo.o: \
+compile alloc.h auto_qmail.h byte.h constmap.h control.h direntry.h error.h \
+exit.h fmt.h fmtqfn.h getln.h open.h ndelay.h now.h readsubdir.h readwrite.h \
+scan.h select.h str.h stralloc.h substdio.h trigger.h
+	./compile $(DEFINES) qmail-todo.c
+
 qmail-upq: \
 warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
 	cat warn-auto.sh qmail-upq.sh \
@@ -1827,7 +1860,8 @@
 ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
 ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
 prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
-maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c \
+update_tmprsadh
 	shar -m `cat FILES` > shar
 	chmod 400 shar
 
@@ -2108,6 +2142,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 +2186,26 @@
 wait_pid.o: \
 compile wait_pid.c error.h haswaitp.h
 	./compile wait_pid.c
+
+cert cert-req: \
+Makefile-cert
+	@$(MAKE) -sf $< $@
+
+Makefile-cert: \
+conf-qmail conf-users conf-groups Makefile-cert.mk
+	@cat Makefile-cert.mk \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
+
+update_tmprsadh: \
+conf-qmail conf-users conf-groups update_tmprsadh.sh
+	@cat update_tmprsadh.sh\
+	| sed s}UGQMAILD}"`head -2 conf-users|tail -1`:`head -1 conf-groups`"}g \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	> $@
+	chmod 755 update_tmprsadh 
+
+tmprsadh: \
+update_tmprsadh
+	echo "Creating new temporary RSA and DH parameters"
+	./update_tmprsadh
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/Makefile-cert.mk work/netqmail-1.06/Makefile-cert.mk
--- tmp/netqmail-1.06/Makefile-cert.mk	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/Makefile-cert.mk	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,21 @@
+cert-req: req.pem
+cert cert-req: QMAIL/control/clientcert.pem
+	@:
+
+QMAIL/control/clientcert.pem: QMAIL/control/servercert.pem
+	ln -s $< $@
+
+QMAIL/control/servercert.pem:
+	PATH=$$PATH:/usr/local/ssl/bin \
+		openssl req -new -x509 -nodes -days 366 -out $@ -keyout $@
+	chmod 640 $@
+	chown `head -2 conf-users | tail -1`:`head -1 conf-groups` $@
+
+req.pem:
+	PATH=$$PATH:/usr/local/ssl/bin openssl req \
+		-new -nodes -out $@ -keyout QMAIL/control/servercert.pem
+	chmod 640 QMAIL/control/servercert.pem
+	chown `head -2 conf-users | tail -1`:`head -1 conf-groups` QMAIL/control/servercert.pem
+	@echo
+	@echo "Send req.pem to your CA to obtain signed_req.pem, and do:"
+	@echo "cat signed_req.pem >> QMAIL/control/servercert.pem"
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/Makefile~ work/netqmail-1.06/Makefile~
--- tmp/netqmail-1.06/Makefile~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/Makefile~	2016-05-06 14:30:29.000000000 -0500
@@ -0,0 +1,2157 @@
+# Don't edit Makefile! Use conf-* for configuration.
+
+DEFINES=-DEXTERNAL_TODO # use to enable external todo
+
+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_diff.o: \
+compile byte_diff.c byte.h
+	./compile byte_diff.c
+
+byte_rchr.o: \
+compile byte_rchr.c byte.h
+	./compile byte_rchr.c
+
+byte_zero.o: \
+compile byte_zero.c byte.h
+	./compile byte_zero.c
+
+case.a: \
+makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
+case_starts.o
+	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
+	case_lowers.o case_starts.o
+
+case_diffb.o: \
+compile case_diffb.c case.h
+	./compile case_diffb.c
+
+case_diffs.o: \
+compile case_diffs.c case.h
+	./compile case_diffs.c
+
+case_lowerb.o: \
+compile case_lowerb.c case.h
+	./compile case_lowerb.c
+
+case_lowers.o: \
+compile case_lowers.c case.h
+	./compile case_lowers.c
+
+case_starts.o: \
+compile case_starts.c case.h
+	./compile case_starts.c
+
+cdb.a: \
+makelib cdb_hash.o cdb_unpack.o cdb_seek.o
+	./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o
+
+cdb_hash.o: \
+compile cdb_hash.c cdb.h uint32.h
+	./compile cdb_hash.c
+
+cdb_seek.o: \
+compile cdb_seek.c cdb.h uint32.h
+	./compile cdb_seek.c
+
+cdb_unpack.o: \
+compile cdb_unpack.c cdb.h uint32.h
+	./compile cdb_unpack.c
+
+cdbmake.a: \
+makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o
+	./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \
+	cdbmake_add.o
+
+cdbmake_add.o: \
+compile cdbmake_add.c cdbmake.h 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 ip.o stralloc.a \
+alloc.a error.a fs.a str.a
+	( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \
+	ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \
+	-lresolv `cat socket.lib` ) >/dev/null 2>&1 \
+	&& echo -lresolv || exit 0 ) > dns.lib
+	rm -f tryrsolv.o tryrsolv
+
+dns.o: \
+compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \
+stralloc.h gen_alloc.h dns.h case.h
+	./compile dns.c
+
+dnscname: \
+load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnscname.o: \
+compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h
+	./compile dnscname.c
+
+dnsdoe.o: \
+compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h
+	./compile dnsdoe.c
+
+dnsfq: \
+load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsfq.o: \
+compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+	./compile dnsfq.c
+
+dnsip: \
+load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsip.o: \
+compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h
+	./compile dnsip.c
+
+dnsmxip: \
+load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a  `cat \
+	dns.lib` `cat socket.lib`
+
+dnsmxip.o: \
+compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \
+gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \
+now.h datetime.h exit.h
+	./compile dnsmxip.c
+
+dnsptr: \
+load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \
+substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a  `cat dns.lib` `cat \
+	socket.lib`
+
+dnsptr.o: \
+compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \
+str.h scan.h dns.h dnsdoe.h ip.h exit.h
+	./compile dnsptr.c
+
+dot-qmail.0: \
+dot-qmail.5
+	nroff -man dot-qmail.5 > dot-qmail.0
+
+dot-qmail.5: \
+dot-qmail.9 conf-break conf-spawn
+	cat dot-qmail.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> dot-qmail.5
+
+elq: \
+warn-auto.sh elq.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh elq.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> elq
+	chmod 755 elq
+
+env.a: \
+makelib env.o envread.o
+	./makelib env.a env.o envread.o
+
+env.o: \
+compile env.c str.h alloc.h env.h
+	./compile env.c
+
+envelopes.0: \
+envelopes.5
+	nroff -man envelopes.5 > envelopes.0
+
+envread.o: \
+compile envread.c env.h str.h
+	./compile envread.c
+
+error.a: \
+makelib error.o error_str.o error_temp.o
+	./makelib error.a error.o error_str.o error_temp.o
+
+error.o: \
+compile error.c error.h
+	./compile error.c
+
+error_str.o: \
+compile error_str.c error.h
+	./compile error_str.c
+
+error_temp.o: \
+compile error_temp.c error.h
+	./compile error_temp.c
+
+except: \
+load except.o strerr.a error.a substdio.a str.a wait.a
+	./load except strerr.a error.a substdio.a str.a wait.a 
+
+except.0: \
+except.1
+	nroff -man except.1 > except.0
+
+except.o: \
+compile except.c fork.h strerr.h wait.h error.h exit.h
+	./compile except.c
+
+fd.a: \
+makelib fd_copy.o fd_move.o
+	./makelib fd.a fd_copy.o fd_move.o
+
+fd_copy.o: \
+compile fd_copy.c fd.h
+	./compile fd_copy.c
+
+fd_move.o: \
+compile fd_move.c fd.h
+	./compile fd_move.c
+
+fifo.o: \
+compile fifo.c hasmkffo.h fifo.h
+	./compile fifo.c
+
+find-systype: \
+find-systype.sh auto-ccld.sh
+	cat auto-ccld.sh find-systype.sh > find-systype
+	chmod 755 find-systype
+
+fmt_str.o: \
+compile fmt_str.c fmt.h
+	./compile fmt_str.c
+
+fmt_strn.o: \
+compile fmt_strn.c fmt.h
+	./compile fmt_strn.c
+
+fmt_uint.o: \
+compile fmt_uint.c fmt.h
+	./compile fmt_uint.c
+
+fmt_uint0.o: \
+compile fmt_uint0.c fmt.h
+	./compile fmt_uint0.c
+
+fmt_ulong.o: \
+compile fmt_ulong.c fmt.h
+	./compile fmt_ulong.c
+
+fmtqfn.o: \
+compile fmtqfn.c fmtqfn.h fmt.h auto_split.h
+	./compile fmtqfn.c
+
+forgeries.0: \
+forgeries.7
+	nroff -man forgeries.7 > forgeries.0
+
+fork.h: \
+compile load tryvfork.c fork.h1 fork.h2
+	( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \
+	2>&1 \
+	&& cat fork.h2 || cat fork.h1 ) > fork.h
+	rm -f tryvfork.o tryvfork
+
+forward: \
+load forward.o qmail.o strerr.a alloc.a fd.a wait.a sig.a env.a \
+substdio.a error.a str.a fs.a auto_qmail.o
+	./load forward qmail.o strerr.a alloc.a fd.a wait.a sig.a \
+	env.a substdio.a error.a str.a fs.a auto_qmail.o 
+
+forward.0: \
+forward.1
+	nroff -man forward.1 > forward.0
+
+forward.o: \
+compile forward.c sig.h readwrite.h exit.h env.h qmail.h substdio.h \
+strerr.h substdio.h fmt.h
+	./compile forward.c
+
+fs.a: \
+makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \
+scan_ulong.o scan_8long.o
+	./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \
+	fmt_ulong.o scan_ulong.o scan_8long.o
+
+getln.a: \
+makelib getln.o getln2.o
+	./makelib getln.a getln.o getln2.o
+
+getln.o: \
+compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h
+	./compile getln.c
+
+getln2.o: \
+compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h
+	./compile getln2.c
+
+getopt.a: \
+makelib subgetopt.o sgetopt.o
+	./makelib getopt.a subgetopt.o sgetopt.o
+
+gfrom.o: \
+compile gfrom.c str.h gfrom.h
+	./compile gfrom.c
+
+hasflock.h: \
+tryflock.c compile load
+	( ( ./compile tryflock.c && ./load tryflock ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASFLOCK 1 || exit 0 ) > hasflock.h
+	rm -f tryflock.o tryflock
+
+hasmkffo.h: \
+trymkffo.c compile load
+	( ( ./compile trymkffo.c && ./load trymkffo ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASMKFIFO 1 || exit 0 ) > hasmkffo.h
+	rm -f trymkffo.o trymkffo
+
+hasnpbg1.h: \
+trynpbg1.c compile load open.h open.a fifo.h fifo.o select.h
+	( ( ./compile trynpbg1.c \
+	&& ./load trynpbg1 fifo.o open.a && ./trynpbg1 ) \
+	>/dev/null 2>&1 \
+	&& echo \#define HASNAMEDPIPEBUG1 1 || exit 0 ) > \
+	hasnpbg1.h
+	rm -f trynpbg1.o trynpbg1
+
+hassalen.h: \
+trysalen.c compile
+	( ./compile trysalen.c >/dev/null 2>&1 \
+	&& echo \#define HASSALEN 1 || exit 0 ) > hassalen.h
+	rm -f trysalen.o
+
+hassgact.h: \
+trysgact.c compile load
+	( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h
+	rm -f trysgact.o trysgact
+
+hassgprm.h: \
+trysgprm.c compile load
+	( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h
+	rm -f trysgprm.o trysgprm
+
+hasshsgr.h: \
+chkshsgr warn-shsgr tryshsgr.c compile load
+	./chkshsgr || ( cat warn-shsgr; exit 1 )
+	( ( ./compile tryshsgr.c \
+	&& ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \
+	&& echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \
+	hasshsgr.h
+	rm -f tryshsgr.o tryshsgr
+
+haswaitp.h: \
+trywaitp.c compile load
+	( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \
+	2>&1 \
+	&& echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h
+	rm -f trywaitp.o trywaitp
+
+headerbody.o: \
+compile headerbody.c stralloc.h gen_alloc.h substdio.h getln.h \
+hfield.h headerbody.h
+	./compile headerbody.c
+
+hfield.o: \
+compile hfield.c hfield.h
+	./compile hfield.c
+
+hier.o: \
+compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h
+	./compile $(DEFINES) 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 $(DEFINES) install-big.c
+
+install.o: \
+compile install.c substdio.h strerr.h error.h open.h readwrite.h \
+exit.h
+	./compile install.c
+
+instcheck: \
+load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \
+strerr.a substdio.a error.a str.a fs.a
+	./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \
+	auto_uids.o strerr.a substdio.a error.a str.a fs.a 
+
+instcheck.o: \
+compile instcheck.c strerr.h error.h readwrite.h exit.h
+	./compile instcheck.c
+
+ip.o: \
+compile ip.c fmt.h scan.h ip.h
+	./compile ip.c
+
+ipalloc.o: \
+compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \
+gen_alloc.h
+	./compile ipalloc.c
+
+ipme.o: \
+compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \
+stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h
+	./compile ipme.c
+
+ipmeprint: \
+load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \
+error.a str.a fs.a socket.lib
+	./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a  `cat socket.lib`
+
+ipmeprint.o: \
+compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \
+ipalloc.h ip.h gen_alloc.h exit.h
+	./compile ipmeprint.c
+
+it: \
+qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \
+qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \
+predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \
+qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \
+qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \
+qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \
+dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \
+forward preline condredirect bouncesaying except maildirmake \
+maildir2mbox maildirwatch qail elq pinq idedit install-big install \
+instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \
+binm3 binm3+df qmail-todo
+
+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 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 \
+	lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a auto_qmail.o  `cat dns.lib` `cat socket.lib`
+
+qmail-remote.0: \
+qmail-remote.8
+	nroff -man qmail-remote.8 > qmail-remote.0
+
+qmail-remote.o: \
+compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \
+subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \
+alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \
+gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \
+tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h
+	./compile qmail-remote.c
+
+qmail-rspawn: \
+load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \
+seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \
+auto_qmail.o auto_uids.o auto_spawn.o
+	./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \
+	sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \
+	substdio.a error.a str.a auto_qmail.o auto_uids.o \
+	auto_spawn.o 
+
+qmail-rspawn.0: \
+qmail-rspawn.8
+	nroff -man qmail-rspawn.8 > qmail-rspawn.0
+
+qmail-rspawn.o: \
+compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \
+tcpto.h
+	./compile qmail-rspawn.c
+
+qmail-send: \
+load qmail-send.o qsutil.o control.o constmap.o newfield.o prioq.o \
+trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
+datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
+lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
+auto_split.o env.a
+	./load qmail-send qsutil.o control.o constmap.o newfield.o \
+	prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
+	qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
+	wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
+	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
+
+qmail-send.0: \
+qmail-send.8
+	nroff -man qmail-send.8 > qmail-send.0
+
+qmail-send.8: \
+qmail-send.9 conf-break conf-spawn
+	cat qmail-send.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-send.8
+
+qmail-send.o: \
+compile qmail-send.c readwrite.h sig.h direntry.h control.h select.h \
+open.h seek.h exit.h lock.h ndelay.h now.h datetime.h getln.h \
+substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \
+scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \
+qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \
+fmtqfn.h readsubdir.h direntry.h
+	./compile $(DEFINES) qmail-send.c
+
+qmail-showctl: \
+load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \
+alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \
+auto_patrn.o auto_spawn.o auto_split.o
+	./load qmail-showctl auto_uids.o control.o open.a getln.a \
+	stralloc.a alloc.a substdio.a error.a str.a fs.a \
+	auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \
+	auto_split.o 
+
+qmail-showctl.0: \
+qmail-showctl.8
+	nroff -man qmail-showctl.8 > qmail-showctl.0
+
+qmail-showctl.o: \
+compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \
+str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \
+auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \
+auto_split.h
+	./compile qmail-showctl.c
+
+qmail-smtpd: \
+load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
+timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
+date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
+open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
+fs.a auto_qmail.o socket.lib
+	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
+	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
+	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
+	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
+	socket.lib`
+
+qmail-smtpd.0: \
+qmail-smtpd.8
+	nroff -man qmail-smtpd.8 > qmail-smtpd.0
+
+qmail-smtpd.o: \
+compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \
+substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \
+error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \
+substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \
+exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h
+	./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 $(DEFINES) 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-todo: \
+load qmail-todo.o control.o constmap.o trigger.o fmtqfn.o now.o \
+readsubdir.o case.a ndelay.a getln.a sig.a open.a stralloc.a alloc.a \
+substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+	./load qmail-todo control.o constmap.o trigger.o fmtqfn.o now.o \
+	readsubdir.o case.a ndelay.a getln.a sig.a open.a stralloc.a \
+	alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_split.o
+
+qmail-todo.o: \
+compile alloc.h auto_qmail.h byte.h constmap.h control.h direntry.h error.h \
+exit.h fmt.h fmtqfn.h getln.h open.h ndelay.h now.h readsubdir.h readwrite.h \
+scan.h select.h str.h stralloc.h substdio.h trigger.h
+	./compile $(DEFINES) qmail-todo.c
+
+qmail-upq: \
+warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split
+	cat warn-auto.sh qmail-upq.sh \
+	| sed s}QMAIL}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPLIT}"`head -1 conf-split`"}g \
+	> qmail-upq
+	chmod 755 qmail-upq
+
+qmail-users.0: \
+qmail-users.5
+	nroff -man qmail-users.5 > qmail-users.0
+
+qmail-users.5: \
+qmail-users.9 conf-break conf-spawn
+	cat qmail-users.9 \
+	| sed s}QMAILHOME}"`head -1 conf-qmail`"}g \
+	| sed s}BREAK}"`head -1 conf-break`"}g \
+	| sed s}SPAWN}"`head -1 conf-spawn`"}g \
+	> qmail-users.5
+
+qmail.0: \
+qmail.7
+	nroff -man qmail.7 > qmail.0
+
+qmail.o: \
+compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \
+qmail.h substdio.h auto_qmail.h
+	./compile qmail.c
+
+qreceipt: \
+load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \
+getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a substdio.a error.a \
+str.a auto_qmail.o
+	./load qreceipt headerbody.o hfield.o quote.o token822.o \
+	qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \
+	substdio.a error.a str.a auto_qmail.o 
+
+qreceipt.0: \
+qreceipt.1
+	nroff -man qreceipt.1 > qreceipt.0
+
+qreceipt.o: \
+compile qreceipt.c sig.h env.h substdio.h stralloc.h gen_alloc.h \
+subfd.h substdio.h getln.h alloc.h str.h hfield.h token822.h \
+gen_alloc.h error.h gen_alloc.h gen_allocdefs.h headerbody.h exit.h \
+open.h quote.h qmail.h substdio.h
+	./compile qreceipt.c
+
+qsmhook: \
+load qsmhook.o sig.a case.a fd.a wait.a getopt.a env.a stralloc.a \
+alloc.a substdio.a error.a str.a
+	./load qsmhook sig.a case.a fd.a wait.a getopt.a env.a \
+	stralloc.a alloc.a substdio.a error.a str.a 
+
+qsmhook.o: \
+compile qsmhook.c fd.h stralloc.h gen_alloc.h readwrite.h sgetopt.h \
+subgetopt.h wait.h env.h byte.h str.h alloc.h exit.h fork.h case.h \
+subfd.h substdio.h error.h substdio.h sig.h
+	./compile qsmhook.c
+
+qsutil.o: \
+compile qsutil.c stralloc.h gen_alloc.h readwrite.h substdio.h \
+qsutil.h
+	./compile qsutil.c
+
+quote.o: \
+compile quote.c stralloc.h gen_alloc.h str.h quote.h
+	./compile quote.c
+
+rcpthosts.o: \
+compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \
+constmap.h stralloc.h gen_alloc.h rcpthosts.h
+	./compile rcpthosts.c
+
+readsubdir.o: \
+compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \
+auto_split.h
+	./compile readsubdir.c
+
+received.o: \
+compile received.c fmt.h qmail.h substdio.h now.h datetime.h \
+datetime.h date822fmt.h received.h
+	./compile received.c
+
+remoteinfo.o: \
+compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \
+timeoutread.h timeoutwrite.h remoteinfo.h
+	./compile remoteinfo.c
+
+scan_8long.o: \
+compile scan_8long.c scan.h
+	./compile scan_8long.c
+
+scan_ulong.o: \
+compile scan_ulong.c scan.h
+	./compile scan_ulong.c
+
+seek.a: \
+makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o
+	./makelib seek.a seek_cur.o seek_end.o seek_set.o \
+	seek_trunc.o
+
+seek_cur.o: \
+compile seek_cur.c seek.h
+	./compile seek_cur.c
+
+seek_end.o: \
+compile seek_end.c seek.h
+	./compile seek_end.c
+
+seek_set.o: \
+compile seek_set.c seek.h
+	./compile seek_set.c
+
+seek_trunc.o: \
+compile seek_trunc.c seek.h
+	./compile seek_trunc.c
+
+select.h: \
+compile trysysel.c select.h1 select.h2
+	( ./compile trysysel.c >/dev/null 2>&1 \
+	&& cat select.h2 || cat select.h1 ) > select.h
+	rm -f trysysel.o trysysel
+
+sendmail: \
+load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \
+auto_qmail.o
+	./load sendmail env.a getopt.a alloc.a substdio.a error.a \
+	str.a auto_qmail.o 
+
+sendmail.o: \
+compile sendmail.c sgetopt.h subgetopt.h substdio.h subfd.h \
+substdio.h alloc.h auto_qmail.h exit.h env.h str.h
+	./compile sendmail.c
+
+setup: \
+it man
+	./install
+
+sgetopt.o: \
+compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \
+subgetopt.h
+	./compile sgetopt.c
+
+shar: \
+FILES BLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias \
+INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL.vsm \
+REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE \
+THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL \
+PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem \
+PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood \
+PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README \
+BIN.Makefile BIN.setup idedit.c conf-break auto_break.h conf-spawn \
+auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \
+auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \
+addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 \
+envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 \
+maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \
+qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \
+qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \
+qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \
+qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \
+qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \
+qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \
+qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \
+qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \
+qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \
+qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \
+qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \
+qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \
+qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \
+qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \
+dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \
+sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \
+except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \
+maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \
+datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h \
+commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c \
+myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \
+readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c \
+tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \
+trynpbg1.c trysyslog.c conf-cc conf-ld home.sh home+df.sh proc.sh \
+proc+df.sh binm1.sh binm2.sh binm3.sh binm1+df.sh binm2+df.sh \
+binm3+df.sh find-systype.sh make-compile.sh make-load.sh \
+make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c \
+auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \
+install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \
+case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \
+cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \
+cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \
+coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \
+fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \
+open.h open_append.c open_excl.c open_read.c open_trunc.c \
+open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \
+conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h \
+stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \
+stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \
+stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c \
+substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h \
+subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h \
+exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c \
+timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 \
+uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c \
+trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \
+sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \
+trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \
+byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \
+str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \
+str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \
+getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \
+subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \
+error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \
+fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \
+slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \
+headerbody.h headerbody.c token822.h token822.c control.h control.c \
+datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \
+date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \
+ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \
+ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \
+prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \
+maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c
+	shar -m `cat FILES` > shar
+	chmod 400 shar
+
+sig.a: \
+makelib sig_alarm.o sig_block.o sig_catch.o sig_pause.o sig_pipe.o \
+sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o
+	./makelib sig.a sig_alarm.o sig_block.o sig_catch.o \
+	sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o \
+	sig_bug.o sig_misc.o
+
+sig_alarm.o: \
+compile sig_alarm.c sig.h
+	./compile sig_alarm.c
+
+sig_block.o: \
+compile sig_block.c sig.h hassgprm.h
+	./compile sig_block.c
+
+sig_bug.o: \
+compile sig_bug.c sig.h
+	./compile sig_bug.c
+
+sig_catch.o: \
+compile sig_catch.c sig.h hassgact.h
+	./compile sig_catch.c
+
+sig_child.o: \
+compile sig_child.c sig.h
+	./compile sig_child.c
+
+sig_hup.o: \
+compile sig_hup.c sig.h
+	./compile sig_hup.c
+
+sig_misc.o: \
+compile sig_misc.c sig.h
+	./compile sig_misc.c
+
+sig_pause.o: \
+compile sig_pause.c sig.h hassgprm.h
+	./compile sig_pause.c
+
+sig_pipe.o: \
+compile sig_pipe.c sig.h
+	./compile sig_pipe.c
+
+sig_term.o: \
+compile sig_term.c sig.h
+	./compile sig_term.c
+
+slurpclose.o: \
+compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \
+error.h
+	./compile slurpclose.c
+
+socket.lib: \
+trylsock.c compile load
+	( ( ./compile trylsock.c && \
+	./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \
+	&& echo -lsocket -lnsl || exit 0 ) > socket.lib
+	rm -f trylsock.o trylsock
+
+spawn.o: \
+compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \
+stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \
+auto_qmail.h auto_uids.h auto_spawn.h
+	./chkspawn
+	./compile spawn.c
+
+splogger: \
+load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib
+	./load splogger substdio.a error.a str.a fs.a  `cat \
+	syslog.lib` `cat socket.lib`
+
+splogger.0: \
+splogger.8
+	nroff -man splogger.8 > splogger.0
+
+splogger.o: \
+compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \
+scan.h fmt.h
+	./compile splogger.c
+
+str.a: \
+makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \
+str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \
+byte_cr.o byte_zero.o
+	./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \
+	str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \
+	byte_diff.o byte_copy.o byte_cr.o byte_zero.o
+
+str_chr.o: \
+compile str_chr.c str.h
+	./compile str_chr.c
+
+str_cpy.o: \
+compile str_cpy.c str.h
+	./compile str_cpy.c
+
+str_diff.o: \
+compile str_diff.c str.h
+	./compile str_diff.c
+
+str_diffn.o: \
+compile str_diffn.c str.h
+	./compile str_diffn.c
+
+str_len.o: \
+compile str_len.c str.h
+	./compile str_len.c
+
+str_rchr.o: \
+compile str_rchr.c str.h
+	./compile str_rchr.c
+
+str_start.o: \
+compile str_start.c str.h
+	./compile str_start.c
+
+stralloc.a: \
+makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \
+stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \
+stralloc_catb.o stralloc_arts.o
+	./makelib stralloc.a stralloc_eady.o stralloc_pend.o \
+	stralloc_copy.o stralloc_opys.o stralloc_opyb.o \
+	stralloc_cat.o stralloc_cats.o stralloc_catb.o \
+	stralloc_arts.o
+
+stralloc_arts.o: \
+compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_arts.c
+
+stralloc_cat.o: \
+compile stralloc_cat.c byte.h stralloc.h gen_alloc.h
+	./compile stralloc_cat.c
+
+stralloc_catb.o: \
+compile stralloc_catb.c stralloc.h gen_alloc.h byte.h
+	./compile stralloc_catb.c
+
+stralloc_cats.o: \
+compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_cats.c
+
+stralloc_copy.o: \
+compile stralloc_copy.c byte.h stralloc.h gen_alloc.h
+	./compile stralloc_copy.c
+
+stralloc_eady.o: \
+compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+	./compile stralloc_eady.c
+
+stralloc_opyb.o: \
+compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h
+	./compile stralloc_opyb.c
+
+stralloc_opys.o: \
+compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h
+	./compile stralloc_opys.c
+
+stralloc_pend.o: \
+compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \
+gen_allocdefs.h
+	./compile stralloc_pend.c
+
+strerr.a: \
+makelib strerr_sys.o strerr_die.o
+	./makelib strerr.a strerr_sys.o strerr_die.o
+
+strerr_die.o: \
+compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h
+	./compile strerr_die.c
+
+strerr_sys.o: \
+compile strerr_sys.c error.h strerr.h
+	./compile strerr_sys.c
+
+subfderr.o: \
+compile subfderr.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfderr.c
+
+subfdin.o: \
+compile subfdin.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdin.c
+
+subfdins.o: \
+compile subfdins.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdins.c
+
+subfdout.o: \
+compile subfdout.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdout.c
+
+subfdouts.o: \
+compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h
+	./compile subfdouts.c
+
+subgetopt.o: \
+compile subgetopt.c subgetopt.h
+	./compile subgetopt.c
+
+substdi.o: \
+compile substdi.c substdio.h byte.h error.h
+	./compile substdi.c
+
+substdio.a: \
+makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \
+subfdouts.o subfdin.o subfdins.o substdio_copy.o
+	./makelib substdio.a substdio.o substdi.o substdo.o \
+	subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \
+	substdio_copy.o
+
+substdio.o: \
+compile substdio.c substdio.h
+	./compile substdio.c
+
+substdio_copy.o: \
+compile substdio_copy.c substdio.h
+	./compile substdio_copy.c
+
+substdo.o: \
+compile substdo.c substdio.h str.h byte.h error.h
+	./compile substdo.c
+
+syslog.lib: \
+trysyslog.c compile load
+	( ( ./compile trysyslog.c && \
+	./load trysyslog -lgen ) >/dev/null 2>&1 \
+	&& echo -lgen || exit 0 ) > syslog.lib
+	rm -f trysyslog.o trysyslog
+
+systype: \
+find-systype trycpp.c
+	./find-systype > systype
+
+tcp-env: \
+load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \
+timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \
+stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib
+	./load tcp-env dns.o remoteinfo.o timeoutread.o \
+	timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \
+	sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \
+	str.a fs.a  `cat dns.lib` `cat socket.lib`
+
+tcp-env.0: \
+tcp-env.1
+	nroff -man tcp-env.1 > tcp-env.0
+
+tcp-env.o: \
+compile tcp-env.c sig.h stralloc.h gen_alloc.h str.h env.h fmt.h \
+scan.h subgetopt.h ip.h dns.h byte.h remoteinfo.h exit.h case.h
+	./compile tcp-env.c
+
+tcp-environ.0: \
+tcp-environ.5
+	nroff -man tcp-environ.5 > tcp-environ.0
+
+tcpto.o: \
+compile tcpto.c tcpto.h open.h lock.h seek.h now.h datetime.h ip.h \
+byte.h datetime.h readwrite.h
+	./compile tcpto.c
+
+tcpto_clean.o: \
+compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h
+	./compile tcpto_clean.c
+
+timeoutconn.o: \
+compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \
+byte.h timeoutconn.h
+	./compile timeoutconn.c
+
+timeoutread.o: \
+compile timeoutread.c timeoutread.h select.h error.h readwrite.h
+	./compile timeoutread.c
+
+timeoutwrite.o: \
+compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h
+	./compile timeoutwrite.c
+
+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
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/README.auth work/netqmail-1.06/README.auth
--- tmp/netqmail-1.06/README.auth	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/README.auth	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,154 @@
+README qmail SMTP Authentication
+================================
+
+Scope:
+------
+
+This patch supports RFC 2554 "SMTP Service Extension for Authentication" and 
+RFC 4409 "Message Submission for Mail" for 
+
+* qmail-smtpd and
+* qmail-remote
+
+and supports commonly the AUTH methods
+
+- CRAM-MD5
+- LOGIN (unsecure)
+- PLAIN (unsecure)
+
+Additionally, RFC 1870 is honoured ("SMTP Service Extension for Message Size Declaration").
+For more technical details see: http://www.fehcom.de/qmail/docu/smtpauth.html.
+
+
+Installation:
+-------------
+
+* Untar the source in the qmail-1.03 home direcotry.
+* Run ./install_auth.
+* Re-make qmail.
+
+
+Setup for qmail-smtpd:
+----------------------
+
+1. Prereqs:
+
+In order to use SMTP Authentication you have to use a 'Pluggable Authentication Module'
+PAM to be called by qmail-smtpd; typically
+
+	/var/qmail/bin/qmail-smtpd /bin/checkpassword true 2>&1
+
+Since qmail-smtpd does not run as root, checkpassword has to be made sticky.
+There is no need to include additionally the hostname in the call.
+In order to compute the CRAM-MD5 challenge, qmail-smtpd uses the 'tcplocalhost' information.
+
+2. Invocation:
+
+In order activate SMTP authentication, you need to provide the environment
+variable 'SMTPAUTH' to qmail-smtpd.
+
+Possible choices:
+	
+	a) SMTPAUTH=""; 	qmail-smtpd supports auth of type PLAIN and/or LOGIN.
+	b) SMTPAUTH="+cram";	qmail-smtpd will additionally annonce CRAM-MD5,
+				this requires a CRAM-MD5 supporting PAM.
+	c) SMTPAUTH="cram";	qmail-smtpd will only annonce CRAM-MD5.
+	d) SMTPAUTH="!";	this instructs qmail-smtpd to require (any type) authentication for this connection.
+				This behavior is equivalent to the Submission feaure.
+	e) SMTPAUTH="!cram";	same as d) but now CRAM-MD5 is the only method instead.
+
+
+Setup for qmail-remote:
+-----------------------
+
+SMTP Authentication with qmail-remote is faclitated by two means:
+
+a) SMTP Authentication by sender/sending domain as provided in the 'Mail From:'
+
+The control file 'authsenders' which works similar to 'control/smtproutes'
+but with additional authentication information (username + password):
+
+    @example.com:relay.example.com|user|passwd
+    info@example.com:relay.example.com:26|infouser|infopasswd
+    :mailrelay.example.com:587|e=mc2|testpass
+
+Note: The choice of the AUTH method depends on the capabilities of the server.
+
+b) SMTP Authentication by recipient domain: 
+
+The control file 'smtproutes' is enhanced with the authentication information:
+
+    authdomain.com:mx.authdomain.com:125|myuserid|mypassword
+    :mailrelay.example.com:587|e=mc2|testpass
+
+
+Historical Notes:
+-----------------
+
+SMTP authentication for qmail-smtpd was initially provided by Krysztof Dabrowski (version 0.31):
+
+
+Changes wrt. Krysztof Dabrowski's patch:
+
+* Avoid the 'hostname' in the call of the PAM.
+* Confirm to Dan Bernstein's checkpassword interface even for CRAM-MD5.
+* Doesn't close FD 2; thus not inhibiting logging to STDERR.
+* Fixed bugs in base64.c.
+* Modified unconditional close of FD 3 in order to sustain reading of 'control/morecpthosts.cdb'.
+* Evaluation of the (informational) Mail From: < > Auth=username.
+* Additional support for the advertised "Size" via 'Mail From: <return-path> SIZE=123456780' (RFC 1870).
+* RFC 3848 conformance for Received header in case of SMTP Auth (keyword ESMTPA).
+* Added SMTPAUTH environment variable.
+* The particular Submission feature has been removed; obsolete.
+
+
+SMTP authentication for qmail-remote is taken from Bjoern Kalkbrenner.
+
+Changes wrt. Bjoern Kalkbrenner's patch (version 0.0.1 / 20020715):
+
+* Uniform, modular support for LOGIN and PLAIN.
+* Added 'Mail From: < > Auth=username' information in provisionally XTEXT format.
+* Added CRAM-MD5 support.
+* Added authentication by recipient domain.
+
+
+Release Notes:
+--------------
+
+Version:	Notes:					Date:
+-------------------------------------------------------------------
+0.5.9		qmail-smtpd AUTH (only)			25.3.2008
+0.6.9		qmail-authentication			1.2.2010
+0.7.0		Based on qmail-authentication 0.69
+		including now CRAM-MD5 support
+		for qmail-remote			31.7.2010
+0.7.1		cosmetics for qmail-remote		5.8.2010
+0.7.2		authorization-id = authentication-id
+		for qmail-remote;
+		added SMTPAUTH environment variable 
+		for qmail-smtpd; backport from SC 2.7	29.4.2012
+0.7.3		Fixed missing AUTH for qmai-smtpd announcement.
+		Improved SUBMISSION port handling.	2.5.2012
+0.7.4		Fixed missing 250 statements for AUTH.
+		Changed SMTPAUTH settings for cram-md5 	18.5.2012
+0.7.5		Fixed bug in qmail-remote not respecting
+		announced AUTH types. Tx. Callum Gibson.
+		Added '432' server code evaluation for
+	 	AUTH password expired in qmail-remote. 	23.10.2012
+0.7.6		Fixed order of SMTP commands (tx roberto).
+							02.02.2013
+0.8.0		Added authentication by recipient domain
+		for qmail-remote.
+		Removed SUBMISSION port feature for
+		qmail-smtpd.				22.03.2013
+0.8.1		Added SMTPAUTH="!+crom" feature.	24.03.2013
+0.8.2		Bug fix: qmail-smtpd ACCEPTS auth commands
+		even if SMTPAUTH="-". (tx chris).	21.01.2015
+0.8.3		Fixed bug in MD5 calculation for AMD64.
+		Fixed 'die_nomem' bug in qmail-smtpd.	23.08.2015
+
+
+
+Erwin Hoffmann - Hoehn 2015-08-23 (www.fehcom.de)
+
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/TARGETS work/netqmail-1.06/TARGETS
--- tmp/netqmail-1.06/TARGETS	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/TARGETS	2016-05-06 14:32:39.000000000 -0500
@@ -10,6 +10,7 @@
 qmail.o
 quote.o
 now.o
+base64.o
 gfrom.o
 myctime.o
 slurpclose.o
@@ -168,6 +169,8 @@
 constmap.o
 timeoutread.o
 timeoutwrite.o
+tls.o
+ssl_timeoutio.o
 timeoutconn.o
 tcpto.o
 dns.o
@@ -182,6 +185,8 @@
 qmail-remote
 qmail-rspawn.o
 tcpto_clean.o
+md5c.o
+hmac_md5.o
 qmail-rspawn
 direntry.h
 qmail-clean.o
@@ -320,6 +325,7 @@
 binm2+df
 binm3
 binm3+df
+Makefile-cert
 it
 qmail-local.0
 qmail-lspawn.0
@@ -385,3 +391,6 @@
 man
 setup
 check
+update_tmprsadh
+qmail-todo.o
+qmail-todo
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/TARGETS~ work/netqmail-1.06/TARGETS~
--- tmp/netqmail-1.06/TARGETS~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/TARGETS~	2016-05-06 14:30:29.000000000 -0500
@@ -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
+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
+qmail-todo.o
+qmail-todo
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/base64.c work/netqmail-1.06/base64.c
--- tmp/netqmail-1.06/base64.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/base64.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,124 @@
+#include "base64.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "str.h"
+
+static char *b64alpha =
+  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define B64PAD '='
+
+/* returns 0 ok, 1 illegal, -1 problem */
+
+int b64decode(in,l,out)
+const unsigned char *in;
+int l;
+stralloc *out; /* not null terminated */
+{
+  int p = 0;
+  int n;
+  unsigned int x;
+  int i, j;
+  char *s;
+  unsigned char b[3];
+
+  if (l == 0)
+  {
+    if (!stralloc_copys(out,"")) return -1;
+    return 0;
+  }
+
+  while(in[l-1] == B64PAD) {
+    p ++;
+    l--;
+  }
+
+  n = (l + p) / 4;
+  i = (n * 3) - p;
+  if (!stralloc_ready(out,i)) return -1;
+  out->len = i;
+  s = out->s;
+
+  for(i = 0; i < n - 1 ; i++) {
+    x = 0;
+    for(j = 0; j < 4; j++) {
+      if(in[j] >= 'A' && in[j] <= 'Z')
+        x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+      else if(in[j] >= 'a' && in[j] <= 'z')
+        x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+      else if(in[j] >= '0' && in[j] <= '9')
+        x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+      else if(in[j] == '+')
+        x = (x << 6) + 62;
+      else if(in[j] == '/')
+        x = (x << 6) + 63;
+      else if(in[j] == '=')
+        x = (x << 6);
+    }
+
+    s[2] = (unsigned char)(x & 255); x >>= 8;
+    s[1] = (unsigned char)(x & 255); x >>= 8;
+    s[0] = (unsigned char)(x & 255); x >>= 8;
+    s += 3; in += 4;
+  }
+
+  x = 0;
+  for(j = 0; j < 4; j++) {
+    if(in[j] >= 'A' && in[j] <= 'Z')
+      x = (x << 6) + (unsigned int)(in[j] - 'A' + 0);
+    else if(in[j] >= 'a' && in[j] <= 'z')
+      x = (x << 6) + (unsigned int)(in[j] - 'a' + 26);
+    else if(in[j] >= '0' && in[j] <= '9')
+      x = (x << 6) + (unsigned int)(in[j] - '0' + 52);
+    else if(in[j] == '+')
+      x = (x << 6) + 62;
+    else if(in[j] == '/')
+      x = (x << 6) + 63;
+    else if(in[j] == '=')
+      x = (x << 6);
+  }
+
+  b[2] = (unsigned char)(x & 255); x >>= 8;
+  b[1] = (unsigned char)(x & 255); x >>= 8;
+  b[0] = (unsigned char)(x & 255); x >>= 8;
+
+  for(i = 0; i < 3 - p; i++)
+    s[i] = b[i];
+
+  return 0;
+}
+
+int b64encode(in,out)
+stralloc *in;
+stralloc *out; /* not null terminated */
+{
+  unsigned char a, b, c;
+  int i;
+  char *s;
+
+  if (in->len == 0)
+  {
+    if (!stralloc_copys(out,"")) return -1;
+    return 0;
+  }
+
+  i = in->len / 3 * 4 + 4;   
+  if (!stralloc_ready(out,i)) return -1;
+  s = out->s;
+
+  for (i = 0;i < in->len;i += 3) {
+    a = in->s[i];
+    b = i + 1 < in->len ? in->s[i + 1] : 0;
+    c = i + 2 < in->len ? in->s[i + 2] : 0;
+
+    *s++ = b64alpha[a >> 2];
+    *s++ = b64alpha[((a & 3 ) << 4) | (b >> 4)];
+
+    if (i + 1 >= in->len) *s++ = B64PAD;
+    else *s++ = b64alpha[((b & 15) << 2) | (c >> 6)];
+
+    if (i + 2 >= in->len) *s++ = B64PAD;
+    else *s++ = b64alpha[c & 63];
+  }
+  out->len = s - out->s;
+  return 0;
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/base64.h work/netqmail-1.06/base64.h
--- tmp/netqmail-1.06/base64.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/base64.h	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,7 @@
+#ifndef BASE64_H
+#define BASE64_H
+
+extern int b64decode();
+extern int b64encode();
+
+#endif
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/case_startb.c work/netqmail-1.06/case_startb.c
--- tmp/netqmail-1.06/case_startb.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/case_startb.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,21 @@
+#include "case.h"
+
+int case_startb(s,len,t)
+register char *s;
+unsigned int len;
+register char *t;
+{
+  register unsigned char x;
+  register unsigned char y;
+
+  for (;;) {
+    y = *t++ - 'A';
+    if (y <= 'Z' - 'A') y += 'a'; else y += 'A';
+    if (!y) return 1;
+    if (!len) return 0;
+    --len;
+    x = *s++ - 'A';
+    if (x <= 'Z' - 'A') x += 'a'; else x += 'A';
+    if (x != y) return 0;
+  }
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/conf-cc work/netqmail-1.06/conf-cc
--- tmp/netqmail-1.06/conf-cc	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/conf-cc	2016-05-06 14:30:55.000000000 -0500
@@ -1,3 +1,3 @@
-cc -O2
+cc -O2 -DTLS=20151215 -I/usr/local/ssl/include
 
 This will be used to compile .c files.
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/dns.c work/netqmail-1.06/dns.c
--- tmp/netqmail-1.06/dns.c	2007-11-30 14:22:54.000000000 -0600
+++ work/netqmail-1.06/dns.c	2016-05-06 14:30:55.000000000 -0500
@@ -19,10 +19,12 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }
 
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;
+static u_long saveresoptions;
 
 static int numanswers;
 static char name[MAXDNAME];
@@ -43,18 +45,33 @@
  errno = 0;
  if (!stralloc_copy(&glue,domain)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+  if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+   responsebuflen = PACKETSZ+1;
+  else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+     (responselen > 0 && (((HEADER *)response.buf)->tc)))
+  {
+   if (responsebuflen < 65536)
+    if (alloc_re(&response.buf, responsebuflen, 65536))
+     responsebuflen = 65536;
+    else return DNS_MEM;
+    saveresoptions = _res.options;
+    _res.options |= RES_USEVC;
+    responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+    _res.options = saveresoptions;
+  }
  if (responselen <= 0)
   {
    if (errno == ECONNREFUSED) return DNS_SOFT;
    if (h_errno == TRY_AGAIN) return DNS_SOFT;
    return DNS_HARD;
   }
- if (responselen >= sizeof(response))
-   responselen = sizeof(response);
  responseend = response.buf + responselen;
  responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
  while (n-- > 0)
   {
    i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -64,7 +81,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
@@ -267,12 +284,11 @@
 int pref;
 {
  int r;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
 
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
@@ -291,9 +307,16 @@
    ix.ip = ip;
    ix.pref = pref;
    if (r == DNS_SOFT) return DNS_SOFT;
-   if (r == 1)
+   if (r == 1) {
+#ifdef IX_FQDN
+     ix.fqdn = glue.s;
+#endif
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
   }
+  }
+#ifdef IX_FQDN
+ glue.s = 0;
+#endif
  return 0;
 }
 
@@ -313,7 +336,7 @@
 {
  int r;
  struct mx { stralloc sa; unsigned short p; } *mx;
- struct ip_mx ix;
+ struct ip_mx ix = {0};
  int nummx;
  int i;
  int j;
@@ -325,7 +348,6 @@
  if (!stralloc_copy(&glue,sa)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
  if (glue.s[0]) {
-   ix.pref = 0;
    if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)])
     {
      if (!ipalloc_append(ia,&ix)) return DNS_MEM;
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/dns.c~ work/netqmail-1.06/dns.c~
--- tmp/netqmail-1.06/dns.c~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/dns.c~	2016-05-06 14:30:37.000000000 -0500
@@ -0,0 +1,415 @@
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <errno.h>
+extern int res_query();
+extern int res_search();
+#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;
+
+ 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;
+     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)
+     if (!ipalloc_append(ia,&ix)) return DNS_MEM;
+  }
+ 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;
+ 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]) {
+   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;
+     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 --speed-large-files --minimal -Nru tmp/netqmail-1.06/extra.h work/netqmail-1.06/extra.h
--- tmp/netqmail-1.06/extra.h	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/extra.h	2016-05-06 14:33:21.000000000 -0500
@@ -1,7 +1,7 @@
 #ifndef EXTRA_H
 #define EXTRA_H
 
-#define QUEUE_EXTRA ""
-#define QUEUE_EXTRALEN 0
+#define QUEUE_EXTRA "Tlog\0"
+#define QUEUE_EXTRALEN 5
 
 #endif
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/global.h work/netqmail-1.06/global.h
--- tmp/netqmail-1.06/global.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/global.h	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,51 @@
+/* GLOBAL.H - RSAREF types and constants */
+
+#include <string.h>
+#include "uint32.h"
+
+/* Copyright (C) RSA Laboratories, a division of RSA Data Security,
+     Inc., created 1991. All rights reserved.
+ */
+
+#ifndef _GLOBAL_H_
+#define _GLOBAL_H_ 1
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+     function argument prototyping.
+   The following makes PROTOTYPES default to 1 if it has not already been
+     defined as 0 with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#define PROTOTYPES 1
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+#ifdef UINT32_H
+#define UINT4 uint32
+#endif
+
+#ifndef NULL_PTR
+#define NULL_PTR ((POINTER)0)
+#endif
+
+#ifndef UNUSED_ARG
+#define UNUSED_ARG(x) x = *(&x);
+#endif
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+     returns an empty list.  
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+#endif /* end _GLOBAL_H_ */
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/hier.c work/netqmail-1.06/hier.c
--- tmp/netqmail-1.06/hier.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/hier.c	2016-05-06 14:30:55.000000000 -0500
@@ -108,6 +108,9 @@
   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);
+#ifdef EXTERNAL_TODO
+  c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711);
+#endif
   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);
@@ -143,6 +146,9 @@
   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);
+#ifdef TLS
+  c(auto_qmail,"bin","update_tmprsadh",auto_uido,auto_gidq,0755);
+#endif
 
   c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644);
   c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644);
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/hier.c~ work/netqmail-1.06/hier.c~
--- tmp/netqmail-1.06/hier.c~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/hier.c~	2016-05-06 14:30:29.000000000 -0500
@@ -0,0 +1,255 @@
+#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);
+#ifdef EXTERNAL_TODO
+  c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711);
+#endif
+  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 --speed-large-files --minimal -Nru tmp/netqmail-1.06/hmac_md5.c work/netqmail-1.06/hmac_md5.c
--- tmp/netqmail-1.06/hmac_md5.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/hmac_md5.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,76 @@
+#include "global.h"
+#include "md5.h"
+
+/*
+** Function: hmac_md5
+*/
+
+void hmac_md5(text, text_len, key, key_len, digest)
+unsigned char*  text;                /* pointer to data stream */
+int             text_len;            /* length of data stream */
+unsigned char*  key;                 /* pointer to authentication key */
+int             key_len;             /* length of authentication key */
+unsigned char   *digest;              /* caller digest to be filled in */
+
+{
+        MD5_CTX context;
+        unsigned char k_ipad[65];    /* inner padding -
+                                      * key XORd with ipad
+                                      */
+        unsigned char k_opad[65];    /* outer padding -
+                                      * key XORd with opad
+                                      */
+        unsigned char tk[16];
+        int i;
+        /* if key is longer than 64 bytes reset it to key=MD5(key) */
+        if (key_len > 64) {
+
+                MD5_CTX      tctx;
+
+                MD5Init(&tctx);
+                MD5Update(&tctx, key, key_len);
+                MD5Final(tk, &tctx);
+
+                key = tk;
+                key_len = 16;
+        }
+
+        /*
+         * the HMAC_MD5 transform looks like:
+         *
+         * MD5(K XOR opad, MD5(K XOR ipad, text))
+         *
+         * where K is an n byte key
+         * ipad is the byte 0x36 repeated 64 times
+         * opad is the byte 0x5c repeated 64 times
+         * and text is the data being protected
+         */
+
+        /* start out by storing key in pads */
+        bzero( k_ipad, sizeof k_ipad);
+        bzero( k_opad, sizeof k_opad);
+        bcopy( key, k_ipad, key_len);
+        bcopy( key, k_opad, key_len);
+
+        /* XOR key with ipad and opad values */
+        for (i=0; i<64; i++) {
+                k_ipad[i] ^= 0x36;
+                k_opad[i] ^= 0x5c;
+        }
+        /*
+         * perform inner MD5
+         */
+        MD5Init(&context);                   /* init context for 1st pass */
+        MD5Update(&context, k_ipad, 64);      /* start with inner pad */
+        MD5Update(&context, text, text_len); /* then text of datagram */
+        MD5Final(digest, &context);          /* finish up 1st pass */
+        /*
+         * perform outer MD5
+         */
+        MD5Init(&context);                   /* init context for 2nd
+                                              * pass */
+        MD5Update(&context, k_opad, 64);     /* start with outer pad */
+        MD5Update(&context, digest, 16);     /* then results of 1st
+                                              * hash */
+        MD5Final(digest, &context);          /* finish up 2nd pass */
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/hmac_md5.h work/netqmail-1.06/hmac_md5.h
--- tmp/netqmail-1.06/hmac_md5.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/hmac_md5.h	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,11 @@
+
+/* prototypes */
+
+void hmac_md5( unsigned char* text, int text_len, unsigned char* key, int key_len, unsigned char* digest);
+
+/* pointer to data stream */
+/* length of data stream */
+/* pointer to authentication key */
+/* length of authentication key */
+/* caller digest to be filled in */
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/install-big.c work/netqmail-1.06/install-big.c
--- tmp/netqmail-1.06/install-big.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/install-big.c	2016-05-06 14:30:29.000000000 -0500
@@ -108,6 +108,9 @@
   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);
+#ifdef EXTERNAL_TODO
+  c(auto_qmail,"bin","qmail-todo",auto_uido,auto_gidq,0711);
+#endif
   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);
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/ipalloc.h work/netqmail-1.06/ipalloc.h
--- tmp/netqmail-1.06/ipalloc.h	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/ipalloc.h	2016-05-06 14:30:55.000000000 -0500
@@ -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 --speed-large-files --minimal -Nru tmp/netqmail-1.06/md5.h work/netqmail-1.06/md5.h
--- tmp/netqmail-1.06/md5.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/md5.h	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,49 @@
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.  
+                                                                    
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.  
+                                                                    
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.  
+ */
+
+#ifndef _MD5_H_
+#define _MD5_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/md5c.c work/netqmail-1.06/md5c.c
--- tmp/netqmail-1.06/md5c.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/md5c.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,334 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+   rights reserved.
+
+   License to copy and use this software is granted provided that it
+   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+   Algorithm" in all material mentioning or referencing this software
+   or this function.
+
+   License is also granted to make and use derivative works provided
+   that such works are identified as "derived from the RSA Data
+   Security, Inc. MD5 Message-Digest Algorithm" in all material
+   mentioning or referencing the derived work.  
+                                                                    
+   RSA Data Security, Inc. makes no representations concerning either
+   the merchantability of this software or the suitability of this
+   software for any particular purpose. It is provided "as is"
+   without express or implied warranty of any kind.  
+                                                                    
+   These notices must be retained in any copies of any part of this
+   documentation and/or software.  
+ */
+
+#include "global.h"
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+  ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+  ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+   Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+    (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+    (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+    (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+    (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+    (a) = ROTATE_LEFT ((a), (s)); \
+    (a) += (b); \
+  }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context;                                        /* context */
+{
+  context->count[0] = context->count[1] = 0;
+
+  /* Load magic initialization constants.
+   */
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+     operation, processing another message block, and updating the
+     context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context;                                        /* context */
+unsigned char *input;                                /* input block */
+unsigned int inputLen;                     /* length of input block */
+{
+  unsigned int i, index, partLen;
+
+  /* Compute number of bytes mod 64 */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+      < ((UINT4)inputLen << 3))
+    context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+  
+  partLen = 64 - index;
+  
+  /* Transform as many times as possible.
+   */
+  if (inputLen >= partLen) {
+    MD5_memcpy
+      ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+    MD5Transform (context->state, context->buffer);
+  
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD5Transform (context->state, &input[i]);
+    
+    index = 0;
+  }
+  else
+    i = 0;
+  
+  /* Buffer remaining input */
+  MD5_memcpy 
+    ((POINTER)&context->buffer[index], (POINTER)&input[i],
+     inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+     the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16];                         /* message digest */
+MD5_CTX *context;                                       /* context */
+{
+  unsigned char bits[8];
+  unsigned int index, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+   */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (index < 56) ? (56 - index) : (120 - index);
+  MD5Update (context, PADDING, padLen);
+  
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+  
+  /* Zeroize sensitive information.
+   */
+  MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+  
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+  /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+  
+  /* Zeroize sensitive information.
+   */
+  MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+     a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+    output[j] = (unsigned char)(input[i] & 0xff);
+    output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+    output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+    output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+     a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+  unsigned int i;
+  
+  for (i = 0; i < len; i++)
+    output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+  unsigned int i;
+  
+  for (i = 0; i < len; i++)
+    ((char *)output)[i] = (char)value;
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-control.9 work/netqmail-1.06/qmail-control.9
--- tmp/netqmail-1.06/qmail-control.9	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-control.9	2016-05-06 14:30:55.000000000 -0500
@@ -40,14 +40,18 @@
 .ta 5c 10c
 control	default	used by
 
+.I authsender	\fR(none)	\fRqmail-remote
 .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 dh2048.pem	\fR(none)	\fRqmail-smtpd
 .I doublebouncehost	\fIme	\fRqmail-send
 .I doublebounceto	\fRpostmaster	\fRqmail-send
 .I envnoathost	\fIme	\fRqmail-send
@@ -61,11 +65,17 @@
 .I qmqpservers	\fR(none)	\fRqmail-qmqpc
 .I queuelifetime	\fR604800	\fRqmail-send
 .I rcpthosts	\fR(none)	\fRqmail-smtpd
+.I rsa2048.pem	\fR(none)	\fRqmail-smtpd
+.I servercert.pem	\fR(none)	\fRqmail-smtpd
 .I smtpgreeting	\fIme	\fRqmail-smtpd
 .I smtproutes	\fR(none)	\fRqmail-remote
 .I timeoutconnect	\fR60	\fRqmail-remote
 .I timeoutremote	\fR1200	\fRqmail-remote
 .I timeoutsmtpd	\fR1200	\fRqmail-smtpd
+.I tlsclients	\fR(none)	\fRqmail-smtpd
+.I tlsclientciphers	\fR(none)	\fRqmail-remote
+.I tlshosts/FQDN.pem	\fR(none)	\fRqmail-remote
+.I tlsserverciphers	\fR(none)	\fRqmail-smtpd
 .I virtualdomains	\fR(none)	\fRqmail-send
 .fi
 .RE
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-remote.8 work/netqmail-1.06/qmail-remote.8
--- tmp/netqmail-1.06/qmail-remote.8	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-remote.8	2016-05-06 14:30:55.000000000 -0500
@@ -53,6 +53,7 @@
 and does not follow the
 .B getopt
 standard.
+
 .SH TRANSPARENCY
 End-of-file in SMTP is encoded as dot CR LF.
 A dot at the beginning of a line is encoded as dot dot.
@@ -100,6 +101,73 @@
 After this letter comes a human-readable description of
 what happened.
 
+.B qmail-remote
+may use SMTP Authenticaton of type CRAM-MD4, PLAIN, or LOGIN
+(in this order) to connect to remote hosts.
+The following reports are provided:
+.TP 5
+K
+no supported AUTH method found, continuing without authentication.
+.TP 5
+Z
+Connected to 
+.I host
+but authentication was rejected (AUTH PLAIN).
+.TP 5
+Z
+Connected to 
+.I host 
+but unable to base64encode (plain).
+.TP 5
+Z
+Connected to 
+.I host
+but authentication was rejected (plain)."
+.TP 5
+Z
+Connected to
+.I host
+but authentication was rejected (AUTH LOGIN).
+.TP 5
+Z
+Connected to 
+.I host
+but unable to base64encode user.
+.TP 5
+Z
+Connected to 
+.I host 
+but authentication was rejected (username).
+.TP 5
+Z
+Connected to 
+.I host 
+but unable to base64encode pass.
+.TP 5
+Z
+Connected to
+.I host
+but authentication was rejected (AUTH CRAM-MD5).
+Z
+Connected to 
+.I host
+but unable to base64decode challenge.
+.TP 5
+Z
+Connected to 
+.I host
+but unable to base64encode username+digest.
+.TP 5
+Z
+Connected to 
+.I host 
+but password expired.
+.TP 5
+Z
+Connected to 
+.I host 
+but authentication was rejected (username+digest).
+.PP
 The recipient reports will always be printed in the same order as
 .BR qmail-remote 's
 .I recip
@@ -114,6 +182,55 @@
 always exits zero.
 .SH "CONTROL FILES"
 .TP 5
+.I authsenders
+Authenticated sender.
+For each
+.I sender 
+included in 
+.IR authsenders :
+.I sender\fB:\fIrelay\fB:\fIport\fB|\fIuser\fB|\fIpassword 
+.B qmail-remote
+will try SMTP Authentication 
+of type CRAM-MD5, LOGIN, or PLAIN 
+with the provided user name
+.I user 
+and password
+.I password 
+(the authentication information) 
+and eventually relay the 
+mail through
+.I relay
+on port
+.IR port .
+The use of 
+.I relay
+and 
+.I port 
+follows the same rules as for
+.IR smtproutes 
+Note: In case
+.I sender
+is empty, 
+.B qmail-remote
+will try to deliver each outgoing mail 
+SMTP authenticated. If the authentication
+information is missing, the mail is 
+delivered none-authenticated.
+.I authsenders
+can be constructed as follows:
+
+.EX
+   @example.com|generic|passwd
+   .subdomain.example.com|other|otherpw
+   mail@example.com|test|testpass
+   info@example.com:smtp.example.com:26|other|otherpw
+   :mailrelay.example.com:587|e=mc2|testpass
+.EE
+.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.
@@ -123,12 +240,24 @@
 otherwise
 .B qmail-remote
 refuses to run.
+
+.TP 5
+.I notlshosts/<FQDN>
+.B qmail-remote
+will not try TLS on servers for which this file exists
+.RB ( <FQDN>
+is the fully-qualified domain name of the server). 
+.IR (tlshosts/<FQDN>.pem 
+takes precedence over this file however).
+
 .TP 5
 .I smtproutes
 Artificial SMTP routes.
 Each route has the form
 .IR domain\fB:\fIrelay ,
-without any extra spaces.
+or 
+.IR domain\fB:\fIrelay\fB|\fIuser\fB|\fIpassword
+in case of authenticated routes without any extra spaces.
 If
 .I domain
 matches
@@ -149,6 +278,7 @@
 
 .EX
    inside.af.mil:firewall.af.mil:26
+  :submission.myrelay.com:587|myuserid|mypasswd
 .EE
 
 .I relay
@@ -156,6 +286,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:
 
@@ -177,11 +309,15 @@
 The
 .B qmail
 system does not protect you if you create an artificial
-mail loop between machines.
+mail loop between machines. 
 However,
 you are always safe using
 .I smtproutes
 if you do not accept mail from the network.
+Note:   
+.I authsender 
+routes have precedence over
+.IR smtproutes .
 .TP 5
 .I timeoutconnect
 Number of seconds
@@ -195,6 +331,33 @@
 .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 TLS authentication from servers for which this file 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. The file contains the trusted CA certificates.
+
+.B WARNING:
+this option may cause mail to be delayed, bounced, doublebounced, or lost.
+
+.TP 5
+.I tlshosts/exhaustivelist
+if this file exists
+no TLS will be tried on hosts other than those for which a file
+.B tlshosts/<FQDN>.pem
+exists.
+
 .SH "SEE ALSO"
 addresses(5),
 envelopes(5),
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-remote.c work/netqmail-1.06/qmail-remote.c
--- tmp/netqmail-1.06/qmail-remote.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-remote.c	2016-05-06 14:33:40.000000000 -0500
@@ -28,6 +28,7 @@
 #include "timeoutconn.h"
 #include "timeoutread.h"
 #include "timeoutwrite.h"
+#include "base64.h"
 
 #define HUGESMTPTEXT 5000
 
@@ -44,10 +45,31 @@
 stralloc host = {0};
 stralloc sender = {0};
 
+stralloc authsenders = {0};
+struct constmap mapauthsenders;
+stralloc user = {0};
+stralloc pass = {0};
+stralloc auth = {0};
+stralloc plain = {0};
+stralloc chal  = {0};
+stralloc slop  = {0};
+char *authsender;
+
 saa reciplist = {0};
 
 struct ip_address partner;
 
+#ifdef TLS
+# include <sys/stat.h>
+# include "tls.h"
+# include "ssl_timeoutio.h"
+# include <openssl/x509v3.h>
+# define EHLO 1
+
+int tls_init();
+const char *ssl_err_str = 0;
+#endif 
+
 void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
 void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
 void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
@@ -86,6 +108,12 @@
 it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
 zerodie(); }
 
+void err_authprot() {
+  out("Kno supported AUTH method found, continuing without authentication.\n");
+  zero();
+  substdio_flush(subfdoutsmall);
+}
+
 void outhost()
 {
   char x[IPFMT];
@@ -99,6 +127,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 +141,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_error_str();
+  } else
+#endif
   r = timeoutread(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -117,6 +154,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_error_str();
+  } else
+#endif 
   r = timeoutwrite(timeout,smtpfd,buf,len);
   if (r <= 0) dropped();
   return r;
@@ -163,6 +206,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 +281,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 +293,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,30 +345,425 @@
   substdio_flush(&smtpto);
 }
 
-stralloc recip = {0};
+#ifdef TLS
+char *partner_fqdn = 0;
 
-void smtp()
+# 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()
 {
-  unsigned long code;
-  int flagbother;
   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) == 0) 
+      servercert = tmp.s;
+    else {
+      if (!stralloc_copys(&tmp, "control/notlshosts/")
+        || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
+        temp_nomem();
+      if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
+	  (stat(tmp.s, &st) == 0)) {
+         alloc_free(tmp.s);
+         return 0;
+      }
+      alloc_free(tmp.s);
+    }
+  }
  
-  if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
- 
-  substdio_puts(&smtpto,"HELO ");
-  substdio_put(&smtpto,helohost.s,helohost.len);
-  substdio_puts(&smtpto,"\r\n");
-  substdio_flush(&smtpto);
-  if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
- 
+  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");
+  }
+
+  /* POODLE vulnerability */
+  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+  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 response, 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_fd(myssl, smtpfd);
+
+  /* read the response 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_error_str());
+
+  if (servercert) {
+    X509 *peercert;
+    STACK_OF(GENERAL_NAME) *gens;
+    int found_gen_dns = 0;
+
+    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){
+          found_gen_dns = 1;
+          if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
+        }
+      }
+      sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    }
+
+    /* no SubjectAltName of type DNS found, look up commonName */
+    if (!found_gen_dns) {
+      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 mailfrom()
+{
   substdio_puts(&smtpto,"MAIL FROM:<");
   substdio_put(&smtpto,sender.s,sender.len);
   substdio_puts(&smtpto,">\r\n");
   substdio_flush(&smtpto);
+}
+
+stralloc xuser = {0};
+
+int xtext(sa,s,len)
+stralloc *sa;
+char *s;
+int len;
+{
+  int i;
+
+  if(!stralloc_copys(sa,"")) temp_nomem();
+  
+  for (i = 0; i < len; i++) {
+    if (s[i] == '=') {
+      if (!stralloc_cats(sa,"+3D")) temp_nomem();
+    } else if (s[i] == '+') {  
+        if (!stralloc_cats(sa,"+2B")) temp_nomem(); 
+    } else if ((int) s[i] < 33 || (int) s[i] > 126) {
+        if (!stralloc_cats(sa,"+3F")) temp_nomem(); /* ok. not correct */
+    } else if (!stralloc_catb(sa,s+i,1)) {
+        temp_nomem();
+    }
+  }
+
+  return sa->len;
+}
+
+void mailfrom_xtext()
+{
+  if (!xtext(&xuser,user.s,user.len)) temp_nomem();
+  substdio_puts(&smtpto,"MAIL FROM:<");
+  substdio_put(&smtpto,sender.s,sender.len);
+  substdio_puts(&smtpto,"> AUTH=");
+  substdio_put(&smtpto,xuser.s,xuser.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+}
+
+int mailfrom_plain()
+{
+  substdio_puts(&smtpto,"AUTH PLAIN\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH PLAIN)."); return -1; }
+
+  if (!stralloc_cat(&plain,&user)) temp_nomem(); /* <authorization-id> */
+  if (!stralloc_0(&plain)) temp_nomem();
+  if (!stralloc_cat(&plain,&user)) temp_nomem(); /* <authentication-id> */
+  if (!stralloc_0(&plain)) temp_nomem();
+  if (!stralloc_cat(&plain,&pass)) temp_nomem(); /* password */
+  if (b64encode(&plain,&auth)) quit("ZConnected to "," but unable to base64encode (plain).");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (plain)."); return 1; }
+  
+  return 0;
+}
+
+int mailfrom_login()
+{
+  substdio_puts(&smtpto,"AUTH LOGIN\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)."); return -1; }
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&user,&auth)) quit("ZConnected to "," but unable to base64encode user.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username).");
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&pass,&auth)) quit("ZConnected to "," but unable to base64encode pass.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (password)."); return 1; }
+}
+
+int mailfrom_cram()
+{
+  int j;
+  unsigned char h;
+  unsigned char digest[16];
+  unsigned char digascii[33];
+  static char hextab[]="0123456789abcdef";
+
+  substdio_puts(&smtpto,"AUTH CRAM-MD5\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH CRAM-MD5)."); return -1; }
+
+  if (str_chr(smtptext.s+4,' ')) { 			/* Challenge */
+    if(!stralloc_copys(&slop,"")) temp_nomem();
+    if (!stralloc_copyb(&slop,smtptext.s+4,smtptext.len-5)) temp_nomem();
+    if (b64decode(slop.s,slop.len,&chal)) quit("ZConnected to "," but unable to base64decode challenge.");
+  }
+   
+  hmac_md5(chal.s,chal.len,pass.s,pass.len,digest);
+
+  for (j = 0;j < 16;j++)				/* HEX => ASCII */
+  {
+    digascii[2*j] = hextab[digest[j] >> 4];  
+    digascii[2*j+1] = hextab[digest[j] & 0xf]; 
+  }
+  digascii[32]=0;
+
+  slop.len = 0;
+  if (!stralloc_copys(&slop,"")) temp_nomem();
+  if (!stralloc_cat(&slop,&user)) temp_nomem();		 /* user-id */
+  if (!stralloc_cats(&slop," ")) temp_nomem();
+  if (!stralloc_catb(&slop,digascii,32)) temp_nomem();   /* digest */ 
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&slop,&auth)) quit("ZConnected to "," but unable to base64encode username+digest.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (username+digest)."); return 1; } 
+}
+
+void smtp_auth()
+{
+  int i, j; 
+
+  for (i = 0; i + 8 < smtptext.len; i += str_chr(smtptext.s+i,'\n')+1)
+    if (!str_diffn(smtptext.s+i+4,"AUTH",4)) {  
+      if (j = str_chr(smtptext.s+i+8,'C') > 0)
+        if (case_starts(smtptext.s+i+8+j,"CRAM"))
+          if (mailfrom_cram() >= 0) return;
+
+      if (j = str_chr(smtptext.s+i+8,'P') > 0)
+        if (case_starts(smtptext.s+i+8+j,"PLAIN")) 
+          if (mailfrom_plain() >= 0) return;
+
+      if (j = str_chr(smtptext.s+i+8,'L') > 0)
+        if (case_starts(smtptext.s+i+8+j,"LOGIN")) 
+          if (mailfrom_login() >= 0) return;
+
+      err_authprot();
+      mailfrom();
+    }
+}
+
+void smtp()
+{
+  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
+
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but greeting failed");
+  if (code != 220) quit("ZConnected to "," but greeting failed");
+
+#ifdef EHLO
+# ifdef TLS
+  if (!smtps)
+# endif
+  code = ehlo();
+
+# ifdef TLS
+  if (tls_init())
+    /* RFC2487 says we should issue EHLO (even if we might not need
+     * extensions); at the same time, it does not prohibit a server
+     * to reject the EHLO and make us fallback to HELO */
+    code = ehlo();
+# endif
+
+  if (code == 250) {
+    /* add EHLO response checks here */
+
+    /* and if EHLO failed, use HELO */
+  } else {
+#endif
+
+  if (smtpcode() != 250) {
+    substdio_puts(&smtpto,"HELO ");
+    substdio_put(&smtpto,helohost.s,helohost.len);
+    substdio_puts(&smtpto,"\r\n");
+    substdio_flush(&smtpto);
+    code = smtpcode();
+    if (code >= 500) quit("DConnected to "," but my name was rejected");
+    if (code != 250) quit("ZConnected to "," but my name was rejected");
+  }
+
+#ifdef EHLO
+  }
+#endif
+
+  if (user.len && pass.len)
+    smtp_auth();
+  else
+    mailfrom();
+
   code = smtpcode();
   if (code >= 500) quit("DConnected to "," but sender was rejected");
   if (code >= 400) quit("ZConnected to "," but sender was rejected");
- 
+
   flagbother = 0;
   for (i = 0;i < reciplist.len;++i) {
     substdio_puts(&smtpto,"RCPT TO:<");
@@ -324,48 +850,102 @@
     case 1:
       if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
   }
+  
+  switch(control_readfile(&authsenders,"control/authsenders",0)) {
+    case -1:
+       temp_control();
+    case 0:
+      if (!constmap_init(&mapauthsenders,"",0,1)) temp_nomem(); break;
+    case 1:
+      if (!constmap_init(&mapauthsenders,authsenders.s,authsenders.len,1)) temp_nomem(); break;
+  }
 }
 
-void main(argc,argv)
+int main(argc,argv)
 int argc;
 char **argv;
 {
   static ipalloc ip = {0};
-  int i;
+  int i, j;
   unsigned long random;
   char **recips;
   unsigned long prefme;
   int flagallaliases;
   int flagalias;
   char *relayhost;
- 
+   
   sig_pipeignore();
   if (argc < 4) perm_usage();
   if (chdir(auto_qmail) == -1) temp_chdir();
   getcontrols();
  
- 
   if (!stralloc_copys(&host,argv[1])) temp_nomem();
- 
+
+  authsender = 0;
   relayhost = 0;
-  for (i = 0;i <= host.len;++i)
-    if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
-      if (relayhost = constmap(&maproutes,host.s + i,host.len - i))
+
+  addrmangle(&sender,argv[2],&flagalias,0);
+
+  for (i = 0;i <= sender.len;++i)
+    if ((i == 0) || (i == sender.len) || (sender.s[i] == '.') || (sender.s[i] == '@'))
+      if (authsender = constmap(&mapauthsenders,sender.s + i,sender.len - i))
         break;
-  if (relayhost && !*relayhost) relayhost = 0;
- 
-  if (relayhost) {
-    i = str_chr(relayhost,':');
-    if (relayhost[i]) {
-      scan_ulong(relayhost + i + 1,&port);
-      relayhost[i] = 0;
+
+  if (authsender && !*authsender) authsender = 0;
+
+  if (authsender) {
+    i = str_chr(authsender,'|');
+    if (authsender[i]) {
+      j = str_chr(authsender + i + 1,'|');
+      if (authsender[j]) {
+        authsender[i] = 0;
+        authsender[i + j + 1] = 0;
+        if (!stralloc_copys(&user,"")) temp_nomem();
+        if (!stralloc_copys(&user,authsender + i + 1)) temp_nomem();
+        if (!stralloc_copys(&pass,"")) temp_nomem();
+        if (!stralloc_copys(&pass,authsender + i + j + 2)) temp_nomem();
+      }
     }
-    if (!stralloc_copys(&host,relayhost)) temp_nomem();
+    i = str_chr(authsender,':');
+    if (authsender[i]) {
+      scan_ulong(authsender + i + 1,&port);
+      authsender[i] = 0;
+    }
+
+    if (!stralloc_copys(&relayhost,authsender)) temp_nomem();
+    if (!stralloc_copys(&host,authsender)) temp_nomem();
+
   }
+  else {					/* default smtproutes -- authenticated */
+    for (i = 0;i <= host.len;++i)
+      if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
+        if (relayhost = constmap(&maproutes,host.s + i,host.len - i))
+          break;
 
+    if (relayhost && !*relayhost) relayhost = 0;
+
+    if (relayhost) {
+      i = str_chr(relayhost,'|');
+      if (relayhost[i]) {
+        j = str_chr(relayhost + i + 1,'|');
+        if (relayhost[j]) {
+          relayhost[i] = 0;
+          relayhost[i + j + 1] = 0;
+          if (!stralloc_copys(&user,"")) temp_nomem();
+          if (!stralloc_copys(&user,relayhost + i + 1)) temp_nomem();
+          if (!stralloc_copys(&pass,"")) temp_nomem();
+          if (!stralloc_copys(&pass,relayhost + i + j + 2)) temp_nomem();
+        }
+      }
+      i = str_chr(relayhost,':');
+      if (relayhost[i]) {
+        scan_ulong(relayhost + i + 1,&port);
+        relayhost[i] = 0;
+      }
+      if (!stralloc_copys(&host,relayhost)) temp_nomem();
+    }
+  }
 
-  addrmangle(&sender,argv[2],&flagalias,0);
- 
   if (!saa_readyplus(&reciplist,0)) temp_nomem();
   if (ipme_init() != 1) temp_oserr();
  
@@ -417,6 +997,9 @@
     if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
       tcpto_err(&ip.ix[i].ip,0);
       partner = ip.ix[i].ip;
+#ifdef TLS
+      partner_fqdn = ip.ix[i].fqdn;
+#endif
       smtp(); /* does not return */
     }
     tcpto_err(&ip.ix[i].ip,errno == error_timeout);
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-remote.c~ work/netqmail-1.06/qmail-remote.c~
--- tmp/netqmail-1.06/qmail-remote.c~	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/qmail-remote.c~	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,1010 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "sig.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "subfd.h"
+#include "scan.h"
+#include "case.h"
+#include "error.h"
+#include "auto_qmail.h"
+#include "control.h"
+#include "dns.h"
+#include "alloc.h"
+#include "quote.h"
+#include "ip.h"
+#include "ipalloc.h"
+#include "ipme.h"
+#include "gen_alloc.h"
+#include "gen_allocdefs.h"
+#include "str.h"
+#include "now.h"
+#include "exit.h"
+#include "constmap.h"
+#include "tcpto.h"
+#include "readwrite.h"
+#include "timeoutconn.h"
+#include "timeoutread.h"
+#include "timeoutwrite.h"
+#include "base64.h"
+
+#define HUGESMTPTEXT 5000
+
+#define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */
+unsigned long port = PORT_SMTP;
+
+GEN_ALLOC_typedef(saa,stralloc,sa,len,a)
+GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus)
+static stralloc sauninit = {0};
+
+stralloc helohost = {0};
+stralloc routes = {0};
+struct constmap maproutes;
+stralloc host = {0};
+stralloc sender = {0};
+
+stralloc authsenders = {0};
+struct constmap mapauthsenders;
+stralloc user = {0};
+stralloc pass = {0};
+stralloc auth = {0};
+stralloc plain = {0};
+stralloc chal  = {0};
+stralloc slop  = {0};
+char *authsender;
+
+saa reciplist = {0};
+
+struct ip_address partner;
+
+#ifdef TLS
+# include <sys/stat.h>
+# include "tls.h"
+# include "ssl_timeoutio.h"
+# include <openssl/x509v3.h>
+# define EHLO 1
+
+int tls_init();
+const char *ssl_err_str = 0;
+#endif 
+
+void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); }
+void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); }
+void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); }
+void outsafe(sa) stralloc *sa; { int i; char ch;
+for (i = 0;i < sa->len;++i) {
+ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?';
+if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } }
+
+void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); }
+void temp_oserr() { out("Z\
+System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); }
+void temp_noconn() { out("Z\
+Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); }
+void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); }
+void temp_dnscanon() { out("Z\
+CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); }
+void temp_dns() { out("Z\
+Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie(); }
+void temp_chdir() { out("Z\
+Unable to switch to home directory. (#4.3.0)\n"); zerodie(); }
+void temp_control() { out("Z\
+Unable to read control files. (#4.3.0)\n"); zerodie(); }
+void perm_partialline() { out("D\
+SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); }
+void perm_usage() { out("D\
+I (qmail-remote) was invoked improperly. (#5.3.5)\n"); zerodie(); }
+void perm_dns() { out("D\
+Sorry, I couldn't find any host named ");
+outsafe(&host);
+out(". (#5.1.2)\n"); zerodie(); }
+void perm_nomx() { out("D\
+Sorry, I couldn't find a mail exchanger or IP address. (#5.4.4)\n");
+zerodie(); }
+void perm_ambigmx() { out("D\
+Sorry. Although I'm listed as a best-preference MX or A for that host,\n\
+it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n");
+zerodie(); }
+
+void err_authprot() {
+  out("Kno supported AUTH method found, continuing without authentication.\n");
+  zero();
+  substdio_flush(subfdoutsmall);
+}
+
+void outhost()
+{
+  char x[IPFMT];
+  if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0);
+}
+
+int flagcritical = 0;
+
+void dropped() {
+  out("ZConnected to ");
+  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();
+}
+
+int timeoutconnect = 60;
+int smtpfd;
+int timeout = 1200;
+
+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_error_str();
+  } else
+#endif
+  r = timeoutread(timeout,smtpfd,buf,len);
+  if (r <= 0) dropped();
+  return r;
+}
+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_error_str();
+  } else
+#endif 
+  r = timeoutwrite(timeout,smtpfd,buf,len);
+  if (r <= 0) dropped();
+  return r;
+}
+
+char inbuf[1024];
+substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf);
+char smtptobuf[1024];
+substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf);
+char smtpfrombuf[128];
+substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf);
+
+stralloc smtptext = {0};
+
+void get(ch)
+char *ch;
+{
+  substdio_get(&smtpfrom,ch,1);
+  if (*ch != '\r')
+    if (smtptext.len < HUGESMTPTEXT)
+     if (!stralloc_append(&smtptext,ch)) temp_nomem();
+}
+
+unsigned long smtpcode()
+{
+  unsigned char ch;
+  unsigned long code;
+
+  if (!stralloc_copys(&smtptext,"")) temp_nomem();
+
+  get(&ch); code = ch - '0';
+  get(&ch); code = code * 10 + (ch - '0');
+  get(&ch); code = code * 10 + (ch - '0');
+  for (;;) {
+    get(&ch);
+    if (ch != '-') break;
+    while (ch != '\n') get(&ch);
+    get(&ch);
+    get(&ch);
+    get(&ch);
+  }
+  while (ch != '\n') get(&ch);
+
+  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; 
+  if (smtptext.s) if (smtptext.len) {
+    out("Remote host said: ");
+    for (i = 0;i < smtptext.len;++i)
+      if (!smtptext.s[i]) smtptext.s[i] = '?';
+    if (substdio_put(subfdoutsmall,smtptext.s,smtptext.len) == -1) _exit(0);
+    smtptext.len = 0;
+  }
+}
+
+void quit(prepend,append)
+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);
+  outhost();
+  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();
+}
+
+void blast()
+{
+  int r;
+  char ch;
+
+  for (;;) {
+    r = substdio_get(&ssin,&ch,1);
+    if (r == 0) break;
+    if (r == -1) temp_read();
+    if (ch == '.')
+      substdio_put(&smtpto,".",1);
+    while (ch != '\n') {
+      substdio_put(&smtpto,&ch,1);
+      r = substdio_get(&ssin,&ch,1);
+      if (r == 0) perm_partialline();
+      if (r == -1) temp_read();
+    }
+    substdio_put(&smtpto,"\r\n",2);
+  }
+ 
+  flagcritical = 1;
+  substdio_put(&smtpto,".\r\n",3);
+  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) == 0) 
+      servercert = tmp.s;
+    else {
+      if (!stralloc_copys(&tmp, "control/notlshosts/")
+        || !stralloc_catb(&tmp, partner_fqdn, str_len(partner_fqdn)+1))
+        temp_nomem();
+      if ((stat("control/tlshosts/exhaustivelist", &st) == 0) ||
+	  (stat(tmp.s, &st) == 0)) {
+         alloc_free(tmp.s);
+         return 0;
+      }
+      alloc_free(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");
+  }
+
+  /* POODLE vulnerability */
+  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+  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 response, 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_fd(myssl, smtpfd);
+
+  /* read the response 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_error_str());
+
+  if (servercert) {
+    X509 *peercert;
+    STACK_OF(GENERAL_NAME) *gens;
+    int found_gen_dns = 0;
+
+    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){
+          found_gen_dns = 1;
+          if (match_partner(gn->d.ia5->data, gn->d.ia5->length)) break;
+        }
+      }
+      sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    }
+
+    /* no SubjectAltName of type DNS found, look up commonName */
+    if (!found_gen_dns) {
+      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 mailfrom()
+{
+  substdio_puts(&smtpto,"MAIL FROM:<");
+  substdio_put(&smtpto,sender.s,sender.len);
+  substdio_puts(&smtpto,">\r\n");
+  substdio_flush(&smtpto);
+}
+
+stralloc xuser = {0};
+
+int xtext(sa,s,len)
+stralloc *sa;
+char *s;
+int len;
+{
+  int i;
+
+  if(!stralloc_copys(sa,"")) temp_nomem();
+  
+  for (i = 0; i < len; i++) {
+    if (s[i] == '=') {
+      if (!stralloc_cats(sa,"+3D")) temp_nomem();
+    } else if (s[i] == '+') {  
+        if (!stralloc_cats(sa,"+2B")) temp_nomem(); 
+    } else if ((int) s[i] < 33 || (int) s[i] > 126) {
+        if (!stralloc_cats(sa,"+3F")) temp_nomem(); /* ok. not correct */
+    } else if (!stralloc_catb(sa,s+i,1)) {
+        temp_nomem();
+    }
+  }
+
+  return sa->len;
+}
+
+void mailfrom_xtext()
+{
+  if (!xtext(&xuser,user.s,user.len)) temp_nomem();
+  substdio_puts(&smtpto,"MAIL FROM:<");
+  substdio_put(&smtpto,sender.s,sender.len);
+  substdio_puts(&smtpto,"> AUTH=");
+  substdio_put(&smtpto,xuser.s,xuser.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+}
+
+int mailfrom_plain()
+{
+  substdio_puts(&smtpto,"AUTH PLAIN\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH PLAIN)."); return -1; }
+
+  if (!stralloc_cat(&plain,&user)) temp_nomem(); /* <authorization-id> */
+  if (!stralloc_0(&plain)) temp_nomem();
+  if (!stralloc_cat(&plain,&user)) temp_nomem(); /* <authentication-id> */
+  if (!stralloc_0(&plain)) temp_nomem();
+  if (!stralloc_cat(&plain,&pass)) temp_nomem(); /* password */
+  if (b64encode(&plain,&auth)) quit("ZConnected to "," but unable to base64encode (plain).");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (plain)."); return 1; }
+  
+  return 0;
+}
+
+int mailfrom_login()
+{
+  substdio_puts(&smtpto,"AUTH LOGIN\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH LOGIN)."); return -1; }
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&user,&auth)) quit("ZConnected to "," but unable to base64encode user.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) quit("ZConnected to "," but authentication was rejected (username).");
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&pass,&auth)) quit("ZConnected to "," but unable to base64encode pass.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (password)."); return 1; }
+}
+
+int mailfrom_cram()
+{
+  int j;
+  unsigned char h;
+  unsigned char digest[16];
+  unsigned char digascii[33];
+  static char hextab[]="0123456789abcdef";
+
+  substdio_puts(&smtpto,"AUTH CRAM-MD5\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() != 334) { quit("ZConnected to "," but authentication was rejected (AUTH CRAM-MD5)."); return -1; }
+
+  if (str_chr(smtptext.s+4,' ')) { 			/* Challenge */
+    if(!stralloc_copys(&slop,"")) temp_nomem();
+    if (!stralloc_copyb(&slop,smtptext.s+4,smtptext.len-5)) temp_nomem();
+    if (b64decode(slop.s,slop.len,&chal)) quit("ZConnected to "," but unable to base64decode challenge.");
+  }
+   
+  hmac_md5(chal.s,chal.len,pass.s,pass.len,digest);
+
+  for (j = 0;j < 16;j++)				/* HEX => ASCII */
+  {
+    digascii[2*j] = hextab[digest[j] >> 4];  
+    digascii[2*j+1] = hextab[digest[j] & 0xf]; 
+  }
+  digascii[32]=0;
+
+  slop.len = 0;
+  if (!stralloc_copys(&slop,"")) temp_nomem();
+  if (!stralloc_cat(&slop,&user)) temp_nomem();		 /* user-id */
+  if (!stralloc_cats(&slop," ")) temp_nomem();
+  if (!stralloc_catb(&slop,digascii,32)) temp_nomem();   /* digest */ 
+
+  if (!stralloc_copys(&auth,"")) temp_nomem();
+  if (b64encode(&slop,&auth)) quit("ZConnected to "," but unable to base64encode username+digest.");
+  substdio_put(&smtpto,auth.s,auth.len);
+  substdio_puts(&smtpto,"\r\n");
+  substdio_flush(&smtpto);
+  if (smtpcode() == 235) { mailfrom_xtext(); return 0; }
+  else if (smtpcode() == 432) { quit("ZConnected to "," but password expired."); return 1; }
+  else { quit("ZConnected to "," but authentication was rejected (username+digest)."); return 1; } 
+}
+
+void smtp_auth()
+{
+  int i, j; 
+
+  for (i = 0; i + 8 < smtptext.len; i += str_chr(smtptext.s+i,'\n')+1)
+    if (!str_diffn(smtptext.s+i+4,"AUTH",4)) {  
+      if (j = str_chr(smtptext.s+i+8,'C') > 0)
+        if (case_starts(smtptext.s+i+8+j,"CRAM"))
+          if (mailfrom_cram() >= 0) return;
+
+      if (j = str_chr(smtptext.s+i+8,'P') > 0)
+        if (case_starts(smtptext.s+i+8+j,"PLAIN")) 
+          if (mailfrom_plain() >= 0) return;
+
+      if (j = str_chr(smtptext.s+i+8,'L') > 0)
+        if (case_starts(smtptext.s+i+8+j,"LOGIN")) 
+          if (mailfrom_login() >= 0) return;
+
+      err_authprot();
+      mailfrom();
+    }
+}
+
+void smtp()
+{
+  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
+
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but greeting failed");
+  if (code != 220) quit("ZConnected to "," but greeting failed");
+
+#ifdef EHLO
+# ifdef TLS
+  if (!smtps)
+# endif
+  code = ehlo();
+
+# ifdef TLS
+  if (tls_init())
+    /* RFC2487 says we should issue EHLO (even if we might not need
+     * extensions); at the same time, it does not prohibit a server
+     * to reject the EHLO and make us fallback to HELO */
+    code = ehlo();
+# endif
+
+  if (code == 250) {
+    /* add EHLO response checks here */
+
+    /* and if EHLO failed, use HELO */
+  } else {
+#endif
+
+  if (smtpcode() != 250) {
+    substdio_puts(&smtpto,"HELO ");
+    substdio_put(&smtpto,helohost.s,helohost.len);
+    substdio_puts(&smtpto,"\r\n");
+    substdio_flush(&smtpto);
+    code = smtpcode();
+    if (code >= 500) quit("DConnected to "," but my name was rejected");
+    if (code != 250) quit("ZConnected to "," but my name was rejected");
+  }
+
+#ifdef EHLO
+  }
+#endif
+
+  if (user.len && pass.len)
+    smtp_auth();
+  else
+    mailfrom();
+
+  code = smtpcode();
+  if (code >= 500) quit("DConnected to "," but sender was rejected");
+  if (code >= 400) quit("ZConnected to "," but sender was rejected");
+
+  flagbother = 0;
+  for (i = 0;i < reciplist.len;++i) {
+    substdio_puts(&smtpto,"RCPT TO:<");
+    substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len);
+    substdio_puts(&smtpto,">\r\n");
+    substdio_flush(&smtpto);
+    code = smtpcode();
+    if (code >= 500) {
+      out("h"); outhost(); out(" does not like recipient.\n");
+      outsmtptext(); zero();
+    }
+    else if (code >= 400) {
+      out("s"); outhost(); out(" does not like recipient.\n");
+      outsmtptext(); zero();
+    }
+    else {
+      out("r"); zero();
+      flagbother = 1;
+    }
+  }
+  if (!flagbother) quit("DGiving up on ","");
+ 
+  substdio_putsflush(&smtpto,"DATA\r\n");
+  code = smtpcode();
+  if (code >= 500) quit("D"," failed on DATA command");
+  if (code >= 400) quit("Z"," failed on DATA command");
+ 
+  blast();
+  code = smtpcode();
+  flagcritical = 0;
+  if (code >= 500) quit("D"," failed after I sent the message");
+  if (code >= 400) quit("Z"," failed after I sent the message");
+  quit("K"," accepted message");
+}
+
+stralloc canonhost = {0};
+stralloc canonbox = {0};
+
+void addrmangle(saout,s,flagalias,flagcname)
+stralloc *saout; /* host has to be canonical, box has to be quoted */
+char *s;
+int *flagalias;
+int flagcname;
+{
+  int j;
+ 
+  *flagalias = flagcname;
+ 
+  j = str_rchr(s,'@');
+  if (!s[j]) {
+    if (!stralloc_copys(saout,s)) temp_nomem();
+    return;
+  }
+  if (!stralloc_copys(&canonbox,s)) temp_nomem();
+  canonbox.len = j;
+  if (!quote(saout,&canonbox)) temp_nomem();
+  if (!stralloc_cats(saout,"@")) temp_nomem();
+ 
+  if (!stralloc_copys(&canonhost,s + j + 1)) temp_nomem();
+  if (flagcname)
+    switch(dns_cname(&canonhost)) {
+      case 0: *flagalias = 0; break;
+      case DNS_MEM: temp_nomem();
+      case DNS_SOFT: temp_dnscanon();
+      case DNS_HARD: ; /* alias loop, not our problem */
+    }
+
+  if (!stralloc_cat(saout,&canonhost)) temp_nomem();
+}
+
+void getcontrols()
+{
+  if (control_init() == -1) temp_control();
+  if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control();
+  if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1)
+    temp_control();
+  if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1)
+    temp_control();
+  switch(control_readfile(&routes,"control/smtproutes",0)) {
+    case -1:
+      temp_control();
+    case 0:
+      if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break;
+    case 1:
+      if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break;
+  }
+  
+  switch(control_readfile(&authsenders,"control/authsenders",0)) {
+    case -1:
+       temp_control();
+    case 0:
+      if (!constmap_init(&mapauthsenders,"",0,1)) temp_nomem(); break;
+    case 1:
+      if (!constmap_init(&mapauthsenders,authsenders.s,authsenders.len,1)) temp_nomem(); break;
+  }
+}
+
+int main(argc,argv)
+int argc;
+char **argv;
+{
+  static ipalloc ip = {0};
+  int i, j;
+  unsigned long random;
+  char **recips;
+  unsigned long prefme;
+  int flagallaliases;
+  int flagalias;
+  char *relayhost;
+   
+  sig_pipeignore();
+  if (argc < 4) perm_usage();
+  if (chdir(auto_qmail) == -1) temp_chdir();
+  getcontrols();
+ 
+  if (!stralloc_copys(&host,argv[1])) temp_nomem();
+
+  authsender = 0;
+  relayhost = 0;
+
+  addrmangle(&sender,argv[2],&flagalias,0);
+
+  for (i = 0;i <= sender.len;++i)
+    if ((i == 0) || (i == sender.len) || (sender.s[i] == '.') || (sender.s[i] == '@'))
+      if (authsender = constmap(&mapauthsenders,sender.s + i,sender.len - i))
+        break;
+
+  if (authsender && !*authsender) authsender = 0;
+
+  if (authsender) {
+    i = str_chr(authsender,'|');
+    if (authsender[i]) {
+      j = str_chr(authsender + i + 1,'|');
+      if (authsender[j]) {
+        authsender[i] = 0;
+        authsender[i + j + 1] = 0;
+        if (!stralloc_copys(&user,"")) temp_nomem();
+        if (!stralloc_copys(&user,authsender + i + 1)) temp_nomem();
+        if (!stralloc_copys(&pass,"")) temp_nomem();
+        if (!stralloc_copys(&pass,authsender + i + j + 2)) temp_nomem();
+      }
+    }
+    i = str_chr(authsender,':');
+    if (authsender[i]) {
+      scan_ulong(authsender + i + 1,&port);
+      authsender[i] = 0;
+    }
+
+    if (!stralloc_copys(&relayhost,authsender)) temp_nomem();
+    if (!stralloc_copys(&host,authsender)) temp_nomem();
+
+  }
+  else {					/* default smtproutes -- authenticated */
+    for (i = 0;i <= host.len;++i)
+      if ((i == 0) || (i == host.len) || (host.s[i] == '.'))
+        if (relayhost = constmap(&maproutes,host.s + i,host.len - i))
+          break;
+
+    if (relayhost && !*relayhost) relayhost = 0;
+
+    if (relayhost) {
+      i = str_chr(relayhost,'|');
+      if (relayhost[i]) {
+        j = str_chr(relayhost + i + 1,'|');
+        if (relayhost[j]) {
+          relayhost[i] = 0;
+          relayhost[i + j + 1] = 0;
+          if (!stralloc_copys(&user,"")) temp_nomem();
+          if (!stralloc_copys(&user,relayhost + i + 1)) temp_nomem();
+          if (!stralloc_copys(&pass,"")) temp_nomem();
+          if (!stralloc_copys(&pass,relayhost + i + j + 2)) temp_nomem();
+        }
+      }
+      i = str_chr(relayhost,':');
+      if (relayhost[i]) {
+        scan_ulong(relayhost + i + 1,&port);
+        relayhost[i] = 0;
+      }
+      if (!stralloc_copys(&host,relayhost)) temp_nomem();
+    }
+  }
+
+  if (!saa_readyplus(&reciplist,0)) temp_nomem();
+  if (ipme_init() != 1) temp_oserr();
+ 
+  flagallaliases = 1;
+  recips = argv + 3;
+  while (*recips) {
+    if (!saa_readyplus(&reciplist,1)) temp_nomem();
+    reciplist.sa[reciplist.len] = sauninit;
+    addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost);
+    if (!flagalias) flagallaliases = 0;
+    ++reciplist.len;
+    ++recips;
+  }
+
+ 
+  random = now() + (getpid() << 16);
+  switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) {
+    case DNS_MEM: temp_nomem();
+    case DNS_SOFT: temp_dns();
+    case DNS_HARD: perm_dns();
+    case 1:
+      if (ip.len <= 0) temp_dns();
+  }
+ 
+  if (ip.len <= 0) perm_nomx();
+ 
+  prefme = 100000;
+  for (i = 0;i < ip.len;++i)
+    if (ipme_is(&ip.ix[i].ip))
+      if (ip.ix[i].pref < prefme)
+        prefme = ip.ix[i].pref;
+ 
+  if (relayhost) prefme = 300000;
+  if (flagallaliases) prefme = 500000;
+ 
+  for (i = 0;i < ip.len;++i)
+    if (ip.ix[i].pref < prefme)
+      break;
+ 
+  if (i >= ip.len)
+    perm_ambigmx();
+ 
+  for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) {
+    if (tcpto(&ip.ix[i].ip)) continue;
+ 
+    smtpfd = socket(AF_INET,SOCK_STREAM,0);
+    if (smtpfd == -1) temp_oserr();
+ 
+    if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) {
+      tcpto_err(&ip.ix[i].ip,0);
+      partner = ip.ix[i].ip;
+#ifdef TLS
+      partner_fqdn = ip.ix[i].fqdn;
+#endif
+      smtp(); /* does not return */
+    }
+    tcpto_err(&ip.ix[i].ip,errno == error_timeout);
+    close(smtpfd);
+  }
+  
+  temp_noconn();
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-send.c work/netqmail-1.06/qmail-send.c
--- tmp/netqmail-1.06/qmail-send.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-send.c	2016-05-06 14:30:29.000000000 -0500
@@ -1215,6 +1215,7 @@
 
 /* this file is too long ---------------------------------------------- TODO */
 
+#ifndef EXTERNAL_TODO
 datetime_sec nexttodorun;
 DIR *tododir; /* if 0, have to opendir again */
 stralloc todoline = {0};
@@ -1438,6 +1439,143 @@
    if (fdchan[c] != -1) close(fdchan[c]);
 }
 
+#endif
+
+/* this file is too long ------------------------------------- EXTERNAL TODO */
+
+#ifdef EXTERNAL_TODO
+stralloc todoline = {0};
+char todobuf[2048];
+int todofdin;
+int todofdout;
+int flagtodoalive;
+
+void tododied() { log1("alert: oh no! lost qmail-todo connection! dying...\n");
+ flagexitasap = 1; flagtodoalive = 0; }
+
+void todo_init()
+{
+  todofdout = 7;
+  todofdin = 8;
+  flagtodoalive = 1;
+  /* sync with external todo */
+  if (write(todofdout, "S", 1) != 1) tododied();
+  
+  return;
+}
+
+void todo_selprep(nfds,rfds,wakeup)
+int *nfds;
+fd_set *rfds;
+datetime_sec *wakeup;
+{
+  if (flagexitasap) {
+    if (flagtodoalive) {
+      write(todofdout, "X", 1);
+    }
+  }
+  if (flagtodoalive) {
+    FD_SET(todofdin,rfds);
+    if (*nfds <= todofdin)
+      *nfds = todofdin + 1;
+  }
+}
+
+void todo_del(char* s)
+{
+ int flagchan[CHANNELS];
+ struct prioq_elt pe;
+ unsigned long id;
+ unsigned int len;
+ int c;
+
+ for (c = 0;c < CHANNELS;++c) flagchan[c] = 0;
+ switch(*s++) {
+  case 'L':
+    flagchan[0] = 1;
+    break;
+  case 'R':
+    flagchan[1] = 1;
+    break;
+  case 'B':
+    flagchan[0] = 1;
+    flagchan[1] = 1;
+    break;
+  case 'X':
+    break;
+  default:
+    log1("warning: qmail-send unable to understand qmail-todo\n");
+    return;
+ }
+ 
+ len = scan_ulong(s,&id);
+ if (!len || s[len]) {
+  log1("warning: qmail-send unable to understand qmail-todo\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;
+}
+
+void todo_do(rfds)
+fd_set *rfds;
+{
+  int r;
+  char ch;
+  int i;
+  
+  if (!flagtodoalive) return;
+  if (!FD_ISSET(todofdin,rfds)) return;
+
+  r = read(todofdin,todobuf,sizeof(todobuf));
+  if (r == -1) return;
+  if (r == 0) {
+    if (flagexitasap)
+      flagtodoalive = 0;
+    else
+      tododied();
+    return;
+  }
+  for (i = 0;i < r;++i) {
+    ch = todobuf[i];
+    while (!stralloc_append(&todoline,&ch)) nomem();
+    if (todoline.len > REPORTMAX)
+      todoline.len = REPORTMAX;
+      /* qmail-todo is responsible for keeping it short */
+    if (!ch && (todoline.len > 1)) {
+      switch (todoline.s[0]) {
+	case 'D':
+	  if (flagexitasap) break;
+	  todo_del(todoline.s + 1);
+	  break;
+	case 'L':
+	  log1(todoline.s + 1);
+	  break;
+	case 'X':
+	  if (flagexitasap)
+	    flagtodoalive = 0;
+	  else
+	    tododied();
+	  break;
+	default:
+	  log1("warning: qmail-send unable to understand qmail-todo: report mangled\n");
+	  break;
+      }
+      todoline.len = 0;
+    }
+  }
+}
+
+#endif
 
 /* this file is too long ---------------------------------------------- MAIN */
 
@@ -1504,6 +1642,9 @@
    log1("alert: unable to reread controls: unable to switch to home directory\n");
    return;
   }
+#ifdef EXTERNAL_TODO
+ write(todofdout, "H", 1);
+#endif
  regetcontrols();
  while (chdir("queue") == -1)
   {
@@ -1568,8 +1709,12 @@
  todo_init();
  cleanup_init();
 
+#ifdef EXTERNAL_TODO
+ while (!flagexitasap || !del_canexit() || flagtodoalive)
+#else
  while (!flagexitasap || !del_canexit())
-  {
+#endif
+ {
    recent = now();
 
    if (flagrunasap) { flagrunasap = 0; pqrun(); }
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-showctl.c work/netqmail-1.06/qmail-showctl.c
--- tmp/netqmail-1.06/qmail-showctl.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-showctl.c	2016-05-06 14:30:55.000000000 -0500
@@ -214,6 +214,7 @@
     _exit(111);
   }
 
+  do_lst("authsenders","No authenticated SMTP sender.","Authenicated SMTP sender: ","");
   do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM.");
   do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is ");
   do_str("bouncehost",1,"bouncehost","Bounce host name is ");
@@ -265,8 +266,7 @@
   while (d = readdir(dir)) {
     if (str_equal(d->d_name,".")) continue;
     if (str_equal(d->d_name,"..")) continue;
-    if (str_equal(d->d_name,"bouncefrom")) continue;
-    if (str_equal(d->d_name,"bouncehost")) continue;
+    if (str_equal(d->d_name,"authsenders")) continue;
     if (str_equal(d->d_name,"badmailfrom")) continue;
     if (str_equal(d->d_name,"bouncefrom")) continue;
     if (str_equal(d->d_name,"bouncehost")) continue;
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-smtpd.8 work/netqmail-1.06/qmail-smtpd.8
--- tmp/netqmail-1.06/qmail-smtpd.8	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-smtpd.8	2016-05-06 14:30:55.000000000 -0500
@@ -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 
@@ -23,7 +32,30 @@
 header fields.
 
 .B qmail-smtpd
-supports ESMTP, including the 8BITMIME and PIPELINING options.
+supports ESMTP, including the 8BITMIME, DATA, PIPELINING, SIZE, and AUTH options.
+.B qmail-smtpd
+includes a \'MAIL FROM:\' parameter parser and obeys \'Auth\' and \'Size\' advertisements.
+.B qmail-smtpd
+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types. It invokes
+.IR checkprogram ,
+which reads on file descriptor 3 the username, a 0 byte, the password
+or CRAM-MD5 digest/response derived from the SMTP client,
+another 0 byte, a CRAM-MD5 challenge (if applicable to the AUTH type),
+and a final 0 byte.
+.I checkprogram
+invokes
+.I subprogram
+upon successful authentication, which should in turn return 0 to
+.BR qmail-smtpd ,
+effectively setting the environment variables $RELAYCLIENT and $TCPREMOTEINFO
+(any supplied value replaced with the authenticated username).
+.B qmail-smtpd
+will reject the authentication attempt if it receives a nonzero return
+value from
+.I checkprogram
+or
+.IR subprogram .
+
 .SH TRANSPARENCY
 .B qmail-smtpd
 converts the SMTP newline convention into the UNIX newline convention
@@ -49,6 +81,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 +121,18 @@
 .B DATABYTES
 is set, it overrides
 .IR databytes .
+
+.TP 5
+.I dh2048.pem
+If these 2048 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 dh2048.pem
+2048 bit counterpart for 
+.B dh2048.pem. 
+
 .TP 5
 .I localiphost
 Replacement host name for local IP addresses.
@@ -151,6 +208,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. 
+Should contain both the certificate and the private key. Certifying Authority
+(CA) and intermediate certificates can be added at the end of the file.
+
 .TP 5
 .I smtpgreeting
 SMTP greeting message.
@@ -169,6 +239,84 @@
 .B qmail-smtpd
 will wait for each new buffer of data from the remote SMTP client.
 Default: 1200.
+
+.SH "ENVIRONMENT VARIABLES READ"
+Environment variables may be defined globally in the
+.B qmail-smtpd
+startup script and/or individually as part of the
+.B tcpserver's
+cdb database.
+The environment variables may be quoted ("variable", or 'variable') and
+in case of global use, have to be exported.
+.B qmail-smtpd
+supports the following legacy environment variables, typically
+provided by
+.B tcpserver
+or
+.B sslserver
+or
+.BR tcp-env :
+.IR TCPREMOTEIP ,
+.IR TCPREMOTEHOST
+.IR TCPREMOTEINFO
+and
+.IR TCPLOCALPORT
+as well as
+.IR RELAYCLIENT .
+
+.B qmail-smtpd
+may use the following environment variables for SMTP authentication:
+.TP 5
+.IR SMTPAUTH
+is used to enable SMTP Authentication for the AUTH types
+LOGIN and PLAIN.
+In case
+.TP 5
+.IR SMTPAUTH='+cram'
+is defined,
+.B qmail-smtpd
+honors LOGIN, PLAIN, and additionally CRAM-MD5 authentication.
+Simply 
+.TP 5
+.IR SMTPAUTH='cram'
+restricts authentication just to CRAM-MD5.
+If however
+.TP 5
+.IR SMTPAUTH='!'
+starts with an exclamation mark, AUTH is required. 
+You can enforce 'Submission' using this option 
+and binding
+.B qmail-smtpd
+to the SUBMISSION port \'587'\.
+In particular,
+.TP 5
+.IR SMTPAUTH='!cram'
+may be useful.
+In opposite, if
+.TP 5
+.IR SMTPAUTH='-'
+starts with a dash, AUTH is disabled for particular
+connections.
+
+Note: The use of 'cram' requires a CRAM-MD5 enabled PAM.
+
+.TP 5
+.I tlsclients
+A list of email addresses. When relay rules would reject an incoming message,
+.B qmail-smtpd
+can allow it if the client presents a certificate that can be verified against
+the CA list in
+.I clientca.pem
+and the certificate email address is in
+.IR tlsclients .
+
+.TP 5
+.I tlsserverciphers
+A set of OpenSSL cipher strings. Multiple ciphers contained in a
+string should be separated by a colon. If the environment variable
+.B TLSCIPHERS
+is set to such a string, it takes precedence.
+
 .SH "SEE ALSO"
 tcp-env(1),
 tcp-environ(5),
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-smtpd.c work/netqmail-1.06/qmail-smtpd.c
--- tmp/netqmail-1.06/qmail-smtpd.c	2007-11-30 14:22:54.000000000 -0600
+++ work/netqmail-1.06/qmail-smtpd.c	2016-05-06 14:30:55.000000000 -0500
@@ -23,14 +23,35 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "wait.h"
+
+#define AUTHSLEEP 5
 
 #define MAXHOPS 100
 unsigned int databytes = 0;
 int timeout = 1200;
 
+const char *protocol = "SMTP";
+
+#ifdef TLS
+#include <sys/stat.h>
+#include "tls.h"
+#include "ssl_timeoutio.h"
+
+void tls_init();
+int tls_verify();
+void tls_nogateway();
+int ssl_rfd = -1, ssl_wfd = -1; /* SSL_get_Xfd() are broken */
+#endif
+
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
   int r;
+#ifdef TLS
+  if (ssl && fd == ssl_wfd)
+    r = ssl_timeoutwrite(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
   r = timeoutwrite(timeout,fd,buf,len);
   if (r <= 0) _exit(1);
   return r;
@@ -49,8 +70,18 @@
 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_size() { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); }
 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(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
 void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); }
@@ -59,6 +90,17 @@
 void err_vrfy(arg) 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"); }
 
+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+int err_authabrt() { out("501 auth exchange canceled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
+void err_authfail() { out("535 authentication failed (#5.7.1)\r\n"); }
+void err_submission() { out("530 Authorization required (#5.7.1) \r\n"); }
 
 stralloc greeting = {0};
 
@@ -76,11 +118,14 @@
   smtp_greet("221 "); out("\r\n"); flush(); _exit(0);
 }
 
+/* char *protocol; */
 char *remoteip;
 char *remotehost;
 char *remoteinfo;
 char *local;
+char *localport;
 char *relayclient;
+char *auth;
 
 stralloc helohost = {0};
 char *fakehelo; /* pointer into helohost, or 0 */
@@ -91,6 +136,7 @@
   fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0;
 }
 
+int smtpauth = 0;
 int liphostok = 0;
 stralloc liphost = {0};
 int bmfok = 0;
@@ -109,7 +155,6 @@
   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();
 
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
@@ -122,19 +167,36 @@
   if (x) { scan_ulong(x,&u); databytes = u; }
   if (!(databytes + 1)) --databytes;
  
+  protocol = "SMTP";
   remoteip = env_get("TCPREMOTEIP");
   if (!remoteip) remoteip = "unknown";
   local = env_get("TCPLOCALHOST");
   if (!local) local = env_get("TCPLOCALIP");
   if (!local) local = "unknown";
+  localport = env_get("TCPLOCALPORT");
+  if (!localport) localport = "0";
   remotehost = env_get("TCPREMOTEHOST");
   if (!remotehost) remotehost = "unknown";
   remoteinfo = env_get("TCPREMOTEINFO");
   relayclient = env_get("RELAYCLIENT");
+  auth = env_get("SMTPAUTH");
+  if (auth) {
+    smtpauth = 1;
+    case_lowers(auth);
+    if (!case_diffs(auth,"-")) smtpauth = 0;
+    if (!case_diffs(auth,"!")) smtpauth = 11;
+    if (case_starts(auth,"cram")) smtpauth = 2;
+    if (case_starts(auth,"+cram")) smtpauth = 3;
+    if (case_starts(auth,"!cram")) smtpauth = 12;
+    if (case_starts(auth,"!+cram")) smtpauth = 13;
+  }
+#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)
@@ -213,33 +275,118 @@
   int r;
   r = rcpthosts(addr.s,str_len(addr.s));
   if (r == -1) die_control();
+#ifdef TLS
+  if (r == 0) if (tls_verify()) r = -2;
+#endif
   return r;
 }
 
-
+char *auth;
+int seenauth = 0;
 int seenmail = 0;
 int flagbarf; /* defined if seenmail */
+int flagsize;
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
+stralloc fuser = {0};
+stralloc mfparms = {0};
+
+int mailfrom_size(arg) char *arg;
+{
+  long r;
+  unsigned long sizebytes = 0;
+
+  scan_ulong(arg,&r);
+  sizebytes = r;
+  if (databytes) if (sizebytes > databytes) return 1;
+  return 0;
+}
+
+void mailfrom_auth(arg,len) 
+char *arg; 
+int len;
+{
+  if (!stralloc_copys(&fuser,"")) die_nomem();
+  if (case_starts(arg,"<>")) { if (!stralloc_cats(&fuser,"unknown")) die_nomem(); }
+  else 
+    while (len) {
+      if (*arg == '+') {
+        if (case_starts(arg,"+3D")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"=")) die_nomem(); }
+        if (case_starts(arg,"+2B")) { arg=arg+2; len=len-2; if (!stralloc_cats(&fuser,"+")) die_nomem(); }
+      }
+      else
+        if (!stralloc_catb(&fuser,arg,1)) die_nomem();
+      arg++; len--;
+    }
+  if(!stralloc_0(&fuser)) die_nomem();
+  if (!remoteinfo) {
+    remoteinfo = fuser.s;
+    if (!env_unset("TCPREMOTEINFO")) die_read();
+    if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+  }
+}
+
+void mailfrom_parms(arg) char *arg;
+{
+  int i;
+  int len;
+
+    len = str_len(arg);
+    if (!stralloc_copys(&mfparms,"")) die_nomem();
+    i = byte_chr(arg,len,'>');
+    if (i > 4 && i < len) {
+      while (len) {
+        arg++; len--; 
+        if (*arg == ' ' || *arg == '\0' ) {
+           if (case_starts(mfparms.s,"SIZE=")) if (mailfrom_size(mfparms.s+5)) { flagsize = 1; return; }
+           if (case_starts(mfparms.s,"AUTH=")) mailfrom_auth(mfparms.s+5,mfparms.len-5);  
+           if (!stralloc_copys(&mfparms,"")) die_nomem();
+        }
+        else
+          if (!stralloc_catb(&mfparms,arg,1)) die_nomem(); 
+      }
+    }
+}
 
 void smtp_helo(arg) char *arg;
 {
   smtp_greet("250 "); out("\r\n");
   seenmail = 0; dohelo(arg);
 }
+/* ESMTP extensions are published here */
 void smtp_ehlo(arg) char *arg;
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  char size[FMT_ULONG];
+#ifdef TLS
+  struct stat st;
+#endif
+  size[fmt_ulong(size,(unsigned int) databytes)] = 0;
+  smtp_greet("250-"); 
+#ifdef TLS
+  if (!ssl && (stat("control/servercert.pem",&st) == 0))
+    out("\r\n250-STARTTLS");
+#endif
+  out("\r\n250-PIPELINING\r\n250-8BITMIME\r\n");
+  if (smtpauth == 1 || smtpauth == 11) out("250-AUTH LOGIN PLAIN\r\n");
+  if (smtpauth == 2 || smtpauth == 12) out("250-AUTH CRAM-MD5\r\n");
+  if (smtpauth == 3 || smtpauth == 13) out("250-AUTH LOGIN PLAIN CRAM-MD5\r\n");
+  out("250 SIZE "); out(size); out("\r\n");
   seenmail = 0; dohelo(arg);
 }
 void smtp_rset(arg) char *arg;
 {
-  seenmail = 0;
+  seenmail = 0; seenauth = 0; 
+  mailfrom.len = 0; rcptto.len = 0;
   out("250 flushed\r\n");
 }
 void smtp_mail(arg) char *arg;
 {
+  if (smtpauth)
+    if (smtpauth > 10 && !seenauth) { err_submission(); return; }
   if (!addrparse(arg)) { err_syntax(); return; }
+  flagsize = 0;
+  mailfrom_parms(arg);
+  if (flagsize) { err_size(); return; }
   flagbarf = bmfcheck();
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
@@ -269,6 +416,11 @@
 {
   int r;
   flush();
+#ifdef TLS
+  if (ssl && fd == ssl_rfd)
+    r = ssl_timeoutread(timeout, ssl_rfd, ssl_wfd, ssl, buf, len);
+  else
+#endif
   r = timeoutread(timeout,fd,buf,len);
   if (r == -1) if (errno == error_timeout) die_alarm();
   if (r <= 0) die_read();
@@ -277,6 +429,9 @@
 
 char ssinbuf[1024];
 substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf);
+#ifdef TLS
+void flush_io() { ssin.p = 0; flush(); }
+#endif
 
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
@@ -378,7 +533,7 @@
   qp = qmail_qp(&qqt);
   out("354 go ahead\r\n");
  
-  received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo);
+  received(&qqt,protocol,local,remoteip,remotehost,remoteinfo,fakehelo);
   blast(&hops);
   hops = (hops >= MAXHOPS);
   if (hops) qmail_fail(&qqt);
@@ -388,28 +543,497 @@
   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 (databytes) if (!bytestooverflow) { err_size(); return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");
 }
 
+/* this file is too long ----------------------------------------- SMTP AUTH */
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0};   /* input from SMTP client */
+static stralloc user = {0};     /* authorization user-id */
+static stralloc pass = {0};     /* plain passwd or digest */
+static stralloc resp = {0};     /* b64 response */
+static stralloc chal = {0};     /* plain challenge */
+static stralloc slop = {0};     /* b64 challenge */
+
+char **childargs;
+char ssauthbuf[512];
+substdio ssauth = SUBSTDIO_FDBUF(safewrite,3,ssauthbuf,sizeof(ssauthbuf));
+
+int authgetl(void) {
+  int i;
+
+  if (!stralloc_copys(&authin,"")) die_nomem();
+  for (;;) {
+    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+    i = substdio_get(&ssin,authin.s + authin.len,1);
+    if (i != 1) die_read();
+    if (authin.s[authin.len] == '\n') break;
+    ++authin.len;
+  }
+
+  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+  authin.s[authin.len] = 0;
+  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+  if (authin.len == 0) { return err_input(); }
+  return authin.len;
+}
+
+int authenticate(void)
+{
+  int child;
+  int wstat;
+  int pi[2];
+
+  if (!stralloc_0(&user)) die_nomem();
+  if (!stralloc_0(&pass)) die_nomem();
+  if (!stralloc_0(&chal)) die_nomem();
+
+  if (pipe(pi) == -1) return err_pipe();
+  switch(child = fork()) {
+    case -1:
+      return err_fork();
+    case 0:
+      close(pi[1]);
+      if(fd_copy(3,pi[0]) == -1) return err_pipe();
+      sig_pipedefault();
+        execvp(*childargs, childargs);
+      _exit(1);
+  }
+  close(pi[0]);
+
+  substdio_fdbuf(&ssauth,write,pi[1],ssauthbuf,sizeof ssauthbuf);
+  if (substdio_put(&ssauth,user.s,user.len) == -1) return err_write();
+  if (substdio_put(&ssauth,pass.s,pass.len) == -1) return err_write();
+  if (smtpauth == 2 || smtpauth == 3 || smtpauth == 12 || smtpauth == 13)  
+    if (substdio_put(&ssauth,chal.s,chal.len) == -1) return err_write();
+  if (substdio_flush(&ssauth) == -1) return err_write();
+
+  close(pi[1]);
+  if (!stralloc_copys(&chal,"")) die_nomem();
+  if (!stralloc_copys(&slop,"")) die_nomem();
+  byte_zero(ssauthbuf,sizeof ssauthbuf);
+  if (wait_pid(&wstat,child) == -1) return err_child();
+  if (wait_crashed(wstat)) return err_child();
+  if (wait_exitcode(wstat)) { sleep(AUTHSLEEP); return 1; } /* no */
+  return 0; /* yes */
+}
+
+int auth_login(arg) char *arg;
+{
+  int r;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+  }
+  else {
+    out("334 VXNlcm5hbWU6\r\n"); flush();       /* Username: */
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+  }
+  if (r == -1) die_nomem();
+
+  out("334 UGFzc3dvcmQ6\r\n"); flush();         /* Password: */
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+  if (r == -1) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+int auth_plain(arg) char *arg;
+{
+  int r, id = 0;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&resp) == 1) return err_input();
+  }
+  else {
+    out("334 \r\n"); flush();
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+  }
+  if (r == -1 || !stralloc_0(&resp)) die_nomem();
+  while (resp.s[id]) id++;                       /* "authorize-id\0userid\0passwd\0" */
+
+  if (resp.len > id + 1)
+    if (!stralloc_copys(&user,resp.s + id + 1)) die_nomem();
+  if (resp.len > id + user.len + 2)
+    if (!stralloc_copys(&pass,resp.s + id + user.len + 2)) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+int auth_cram()
+{
+  int i, r;
+  char *s;
+
+  s = unique;                                           /* generate challenge */
+  s += fmt_uint(s,getpid());
+  *s++ = '.';
+  s += fmt_ulong(s,(unsigned long) now());
+  *s++ = '@';
+  *s++ = 0;
+  if (!stralloc_copys(&chal,"<")) die_nomem();
+  if (!stralloc_cats(&chal,unique)) die_nomem();
+  if (!stralloc_cats(&chal,local)) die_nomem();
+  if (!stralloc_cats(&chal,">")) die_nomem();
+  if (b64encode(&chal,&slop) < 0) die_nomem();
+  if (!stralloc_0(&slop)) die_nomem();
+
+  out("334 ");                                          /* "334 base64_challenge \r\n" */
+  out(slop.s);
+  out("\r\n");
+  flush();
+
+  if (authgetl() < 0) return -1;                        /* got response */
+  if (r = b64decode(authin.s,authin.len,&resp) == 1) return err_input();
+  if (r == -1 || !stralloc_0(&resp)) die_nomem();
+
+  i = str_rchr(resp.s,' ');
+  s = resp.s + i;
+  while (*s == ' ') ++s;
+  resp.s[i] = 0;
+  if (!stralloc_copys(&user,resp.s)) die_nomem();       /* userid */
+  if (!stralloc_copys(&pass,s)) die_nomem();            /* digest */
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+struct authcmd {
+  char *text;
+  int (*fun)();
+} authcmds[] = {
+  { "login",auth_login }
+, { "plain",auth_plain }
+, { "cram-md5",auth_cram }
+, { 0,err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+/* forcetls patch */
+#ifdef TLS
+  char *forcetls=env_get("FORCETLS");
+  if (!forcetls || (forcetls && strcmp(forcetls, "0")!=0))
+  {
+    if (!ssl)
+    {
+      out("538 auth not available without TLS (#5.3.3)\r\n");
+      flush();
+      die_read();
+    }
+  }
+#endif
+/* END forcetls patch */
+
+  int i;
+  char *cmd = arg;
+
+  if (!smtpauth || !*childargs) { out("503 auth not available (#5.3.3)\r\n"); return; }
+  if (seenauth) { err_authd(); return; }
+  if (seenmail) { err_authmail(); return; }
+
+  if (!stralloc_copys(&user,"")) die_nomem();
+  if (!stralloc_copys(&pass,"")) die_nomem();
+  if (!stralloc_copys(&resp,"")) die_nomem();
+  if (!stralloc_copys(&chal,"")) die_nomem();
+
+  i = str_chr(cmd,' ');
+  arg = cmd + i;
+  while (*arg == ' ') ++arg;
+  cmd[i] = 0;
+
+  for (i = 0;authcmds[i].text;++i)
+    if (case_equals(authcmds[i].text,cmd)) break;
+
+  switch (authcmds[i].fun(arg)) {
+    case 0:
+      seenauth = 1;
+      protocol = "ESMTPA";
+      relayclient = "";
+      remoteinfo = user.s;
+      if (!env_unset("TCPREMOTEINFO")) die_read();
+      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+      if (!env_put2("RELAYCLIENT",relayclient)) die_nomem();
+      out("235 ok, go ahead (#2.0.0)\r\n");
+      break;
+    case 1:
+      err_authfail(user.s,authcmds[i].text);
+  }
+}
+
+
+/* this file is too long --------------------------------------------- GO ON */
+
+#ifdef TLS
+stralloc proto = {0};
+int ssl_verified = 0;
+const char *ssl_verify_err = 0;
+
+void smtp_tls(char *arg)
+{
+  if (ssl) err_unimpl();
+  else if (*arg) out("501 Syntax error (no parameters allowed) (#5.5.4)\r\n");
+  else tls_init();
+}
+
+RSA *tmp_rsa_cb(SSL *ssl, int export, int keylen)
+{
+  if (!export) keylen = 2048;
+  if (keylen == 2048) {
+    FILE *in = fopen("control/rsa2048.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 = 2048;
+  if (keylen == 2048) {
+    FILE *in = fopen("control/dh2048.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_error_str();
+    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();
+      protocol = proto.s;
+      relayclient = "";
+      /* also inform qmail-queue */
+      if (!env_put("RELAYCLIENT=")) die_nomem();
+    }
+
+    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; }
+
+  /* POODLE vulnerability */
+  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
+
+  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
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+  /* support ECDH */
+  SSL_CTX_set_ecdh_auto(ctx,1);
+#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_error_str();
+    ssl_free(myssl); tls_out("connection failed", err); die_read();
+  }
+  ssl = myssl;
+
+  /* populate the protocol string, used in Received */
+  if (!stralloc_copys(&proto, "ESMTPS (")
+    || !stralloc_cats(&proto, SSL_get_cipher(ssl))
+    || !stralloc_cats(&proto, " encrypted)")) die_nomem();
+  if (!stralloc_0(&proto)) die_nomem();
+  protocol = proto.s;
+
+  /* have to discard the pre-STARTTLS HELO/EHLO argument, if any */
+  dohelo(remotehost);
+}
+
+# undef SERVERCERT
+# undef CLIENTCA
+
+#endif
+
 struct commands smtpcommands[] = {
   { "rcpt", smtp_rcpt, 0 }
 , { "mail", smtp_mail, 0 }
 , { "data", smtp_data, flush }
+, { "auth", smtp_auth, flush }
 , { "quit", smtp_quit, flush }
 , { "helo", smtp_helo, flush }
 , { "ehlo", smtp_ehlo, flush }
 , { "rset", smtp_rset, 0 }
 , { "help", smtp_help, flush }
+#ifdef TLS
+, { "starttls", smtp_tls, flush_io }
+#endif
 , { "noop", err_noop, flush }
 , { "vrfy", err_vrfy, flush }
 , { 0, err_unimpl, flush }
 } ;
 
-void main()
+void main(argc,argv)
+int argc;
+char **argv;
 {
+  childargs = argv + 1;
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-start.c work/netqmail-1.06/qmail-start.c
--- tmp/netqmail-1.06/qmail-start.c	1998-06-15 05:53:16.000000000 -0500
+++ work/netqmail-1.06/qmail-start.c	2016-05-06 14:30:29.000000000 -0500
@@ -8,6 +8,9 @@
 char *(qcargs[]) = { "qmail-clean", 0 };
 char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 };
 char *(qrargs[]) = { "qmail-rspawn", 0 };
+#ifdef EXTERNAL_TODO
+char *(qtargs[]) = { "qmail-todo", 0};
+#endif
 
 void die() { _exit(111); }
 
@@ -18,13 +21,28 @@
 int pi4[2];
 int pi5[2];
 int pi6[2];
+#ifdef EXTERNAL_TODO
+int pi7[2];
+int pi8[2];
+int pi9[2];
+int pi10[2];
+#endif
 
-void close23456() { close(2); close(3); close(4); close(5); close(6); }
+void close23456() { 
+  close(2); close(3); close(4); close(5); close(6); 
+#ifdef EXTERNAL_TODO
+  close(7); close(8);
+#endif
+}
 
 void closepipes() {
   close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]);
   close(pi3[0]); close(pi3[1]); close(pi4[0]); close(pi4[1]);
   close(pi5[0]); close(pi5[1]); close(pi6[0]); close(pi6[1]);
+#ifdef EXTERNAL_TODO
+  close(pi7[0]); close(pi7[1]); close(pi8[0]); close(pi8[1]);
+	close(pi9[0]); close(pi9[1]); close(pi10[0]); close(pi10[1]);
+#endif
 }
 
 void main(argc,argv)
@@ -40,6 +58,10 @@
   if (fd_copy(4,0) == -1) die();
   if (fd_copy(5,0) == -1) die();
   if (fd_copy(6,0) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (fd_copy(7,0) == -1) die();
+  if (fd_copy(8,0) == -1) die();
+#endif
 
   if (argv[1]) {
     qlargs[1] = argv[1];
@@ -70,6 +92,12 @@
   if (pipe(pi4) == -1) die();
   if (pipe(pi5) == -1) die();
   if (pipe(pi6) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (pipe(pi7) == -1) die();
+  if (pipe(pi8) == -1) die();
+  if (pipe(pi9) == -1) die();
+  if (pipe(pi10) == -1) die();
+#endif
  
   switch(fork()) {
     case -1: die();
@@ -105,6 +133,34 @@
       execvp(*qcargs,qcargs);
       die();
   }
+
+#ifdef EXTERNAL_TODO
+  switch(fork()) {
+    case -1: die();
+    case 0:
+      if (prot_uid(auto_uids) == -1) die();
+      if (fd_copy(0,pi7[0]) == -1) die();
+      if (fd_copy(1,pi8[1]) == -1) die();
+      close23456();
+      if (fd_copy(2,pi9[1]) == -1) die();
+      if (fd_copy(3,pi10[0]) == -1) die();
+      closepipes();
+      execvp(*qtargs,qtargs);
+      die();
+  }
+
+  switch(fork()) {
+    case -1: die();
+    case 0:
+      if (prot_uid(auto_uidq) == -1) die();
+      if (fd_copy(0,pi9[0]) == -1) die();
+      if (fd_copy(1,pi10[1]) == -1) die();
+      close23456();
+      closepipes();
+      execvp(*qcargs,qcargs);
+      die();
+  }
+#endif
  
   if (prot_uid(auto_uids) == -1) die();
   if (fd_copy(0,1) == -1) die();
@@ -114,6 +170,10 @@
   if (fd_copy(4,pi4[0]) == -1) die();
   if (fd_copy(5,pi5[1]) == -1) die();
   if (fd_copy(6,pi6[0]) == -1) die();
+#ifdef EXTERNAL_TODO
+  if (fd_copy(7,pi7[1]) == -1) die();
+  if (fd_copy(8,pi8[0]) == -1) die();
+#endif
   closepipes();
   execvp(*qsargs,qsargs);
   die();
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/qmail-todo.c work/netqmail-1.06/qmail-todo.c
--- tmp/netqmail-1.06/qmail-todo.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/qmail-todo.c	2016-05-06 14:30:29.000000000 -0500
@@ -0,0 +1,688 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "alloc.h"
+#include "auto_qmail.h"
+#include "byte.h"
+#include "constmap.h"
+#include "control.h"
+#include "direntry.h"
+#include "error.h"
+#include "exit.h"
+#include "fmt.h"
+#include "fmtqfn.h"
+#include "getln.h"
+#include "open.h"
+#include "ndelay.h"
+#include "now.h"
+#include "readsubdir.h"
+#include "readwrite.h"
+#include "scan.h"
+#include "select.h"
+#include "str.h"
+#include "stralloc.h"
+#include "substdio.h"
+#include "trigger.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_SYSFAIL 123
+
+stralloc percenthack = {0};
+struct constmap mappercenthack;
+stralloc locals = {0};
+struct constmap maplocals;
+stralloc vdoms = {0};
+struct constmap mapvdoms;
+stralloc envnoathost = {0};
+
+char strnum[FMT_ULONG];
+
+/* XXX not good, if qmail-send.c changes this has to be updated */
+#define CHANNELS 2
+char *chanaddr[CHANNELS] = { "local/", "remote/" };
+
+datetime_sec recent;
+
+void log1(char *x);
+void log3(char* x, char* y, char* z);
+
+int flagstopasap = 0;
+void sigterm(void)
+{
+  if (flagstopasap == 0)
+    log1("status: qmail-todo stop processing asap\n");
+  flagstopasap = 1;
+}
+
+int flagreadasap = 0; void sighup(void) { flagreadasap = 1; }
+int flagsendalive = 1; void senddied(void) { flagsendalive = 0; }
+
+void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); }
+void pausedir(dir) char *dir;
+{ log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); }
+
+void cleandied()
+{ 
+  log1("alert: qmail-todo: oh no! lost qmail-clean connection! dying...\n");
+  flagstopasap = 1;
+}
+
+
+/* this file is not so long ------------------------------------- FILENAMES */
+
+stralloc fn = {0};
+
+void fnmake_init(void)
+{
+ while (!stralloc_ready(&fn,FMTQFN)) nomem();
+}
+
+void fnmake_info(unsigned long id) { fn.len = fmtqfn(fn.s,"info/",id,1); }
+void fnmake_todo(unsigned long id) { fn.len = fmtqfn(fn.s,"todo/",id,0); }
+void fnmake_mess(unsigned long id) { fn.len = fmtqfn(fn.s,"mess/",id,1); }
+void fnmake_chanaddr(unsigned long id, int c)
+{ fn.len = fmtqfn(fn.s,chanaddr[c],id,1); }
+
+
+/* this file is not so 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(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;
+}
+
+/* this file is not so long --------------------------------- COMMUNICATION */
+
+substdio sstoqc; char sstoqcbuf[1024];
+substdio ssfromqc; char ssfromqcbuf[1024];
+stralloc comm_buf = {0};
+int comm_pos;
+int fdout = -1;
+int fdin = -1;
+
+void comm_init(void)
+{
+ substdio_fdbuf(&sstoqc,write,2,sstoqcbuf,sizeof(sstoqcbuf));
+ substdio_fdbuf(&ssfromqc,read,3,ssfromqcbuf,sizeof(ssfromqcbuf));
+
+ fdout = 1; /* stdout */
+ fdin = 0;  /* stdin */
+ if (ndelay_on(fdout) == -1)
+ /* this is so stupid: NDELAY semantics should be default on write */
+   senddied(); /* drastic, but better than risking deadlock */
+
+ while (!stralloc_ready(&comm_buf,1024)) nomem();
+}
+
+int comm_canwrite(void)
+{
+ /* XXX: could allow a bigger buffer; say 10 recipients */
+ /* XXX: returns true if there is something in the buffer */
+ if (!flagsendalive) return 0;
+ if (comm_buf.s && comm_buf.len) return 1;
+ return 0;
+}
+
+void log1(char* x)
+{
+  int pos;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"L")) goto fail;
+  if (!stralloc_cats(&comm_buf,x)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void log3(char* x, char *y, char *z)
+{
+  int pos;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"L")) goto fail;
+  if (!stralloc_cats(&comm_buf,x)) goto fail;
+  if (!stralloc_cats(&comm_buf,y)) goto fail;
+  if (!stralloc_cats(&comm_buf,z)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void comm_write(unsigned long id, int local, int remote)
+{
+  int pos;
+  char *s;
+  
+  if(local && remote) s="B";
+  else if(local) s="L";
+  else if(remote) s="R";
+  else s="X";
+  
+  pos = comm_buf.len;
+  strnum[fmt_ulong(strnum,id)] = 0;
+  if (!stralloc_cats(&comm_buf,"D")) goto fail;
+  if (!stralloc_cats(&comm_buf,s)) goto fail;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+static int issafe(char ch)
+{
+ if (ch == '%') return 0; /* general principle: allman's code is crap */
+ if (ch < 33) return 0;
+ if (ch > 126) return 0;
+ return 1;
+}
+
+void comm_info(unsigned long id, unsigned long size, char* from, unsigned long pid, unsigned long uid)
+{
+  int pos;
+  int i;
+  
+  pos = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,"Linfo msg ")) goto fail;
+  strnum[fmt_ulong(strnum,id)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf,": bytes ")) goto fail;
+  strnum[fmt_ulong(strnum,size)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf," from <")) goto fail;
+  i = comm_buf.len;
+  if (!stralloc_cats(&comm_buf,from)) goto fail;
+  for (;i < comm_buf.len;++i)
+    if (comm_buf.s[i] == '\n')
+      comm_buf.s[i] = '/';
+    else
+      if (!issafe(comm_buf.s[i]))
+	comm_buf.s[i] = '_';
+  if (!stralloc_cats(&comm_buf,"> qp ")) goto fail;
+  strnum[fmt_ulong(strnum,pid)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf," uid ")) goto fail;
+  strnum[fmt_ulong(strnum,uid)] = 0;
+  if (!stralloc_cats(&comm_buf,strnum)) goto fail;
+  if (!stralloc_cats(&comm_buf,"\n")) goto fail;
+  if (!stralloc_0(&comm_buf)) goto fail;
+  return;
+  
+fail:
+  /* either all or nothing */
+  comm_buf.len = pos;
+}
+
+void comm_exit(void)
+{
+  int w;
+  
+  /* if it fails exit, we have already stoped */
+  if (!stralloc_cats(&comm_buf,"X")) _exit(1);
+  if (!stralloc_0(&comm_buf)) _exit(1);
+}
+
+void comm_selprep(int *nfds, fd_set *wfds, fd_set *rfds)
+{
+  if (flagsendalive) {
+    if (flagstopasap && comm_canwrite() == 0)
+      comm_exit();
+    if (comm_canwrite()) {
+      FD_SET(fdout,wfds);
+      if (*nfds <= fdout)
+	*nfds = fdout + 1;
+    }
+    FD_SET(fdin,rfds);
+    if (*nfds <= fdin)
+      *nfds = fdin + 1;
+  }
+}
+
+void comm_do(fd_set *wfds, fd_set *rfds)
+{
+  /* first write then read */
+  if (flagsendalive)
+    if (comm_canwrite())
+      if (FD_ISSET(fdout,wfds)) {
+	int w;
+	int len;
+	len = comm_buf.len;
+	w = write(fdout,comm_buf.s + comm_pos,len - comm_pos);
+	if (w <= 0) {
+	  if ((w == -1) && (errno == error_pipe))
+	    senddied();
+	} else {
+	  comm_pos += w;
+	  if (comm_pos == len) {
+	    comm_buf.len = 0;
+	    comm_pos = 0;
+	  }
+	}
+      }
+  if (flagsendalive)
+    if (FD_ISSET(fdin,rfds)) {
+      /* there are only two messages 'H' and 'X' */
+      char c;
+      int r;
+      r = read(fdin, &c, 1);
+      if (r <= 0) {
+	if ((r == -1) && (errno != error_intr))
+	  senddied();
+      } else {
+	switch(c) {
+	  case 'H':
+	    sighup();
+	    break;
+	  case 'X':
+	    sigterm();
+	    break;
+	  default:
+	    log1("warning: qmail-todo: qmail-send speaks an obscure dialect\n");
+	    break;
+	}
+      }
+    }
+}
+
+/* this file is not so 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(void)
+{
+ tododir = 0;
+ nexttodorun = now();
+ trigger_set();
+}
+
+void todo_selprep(int *nfds, fd_set *rfds, datetime_sec *wakeup)
+{
+ if (flagstopasap) return;
+ trigger_selprep(nfds,rfds);
+ if (tododir) *wakeup = 0;
+ if (*wakeup > nexttodorun) *wakeup = nexttodorun;
+}
+
+void todo_do(fd_set *rfds)
+{
+ struct stat st;
+ substdio ss; int fd;
+ substdio ssinfo; int fdinfo;
+ substdio sschan[CHANNELS];
+ int fdchan[CHANNELS];
+ int flagchan[CHANNELS];
+ 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 (flagstopasap) 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: qmail-todo: unable to open ",fn.s,"\n"); return; }
+
+ fnmake_mess(id);
+ /* just for the statistics */
+ if (stat(fn.s,&st) == -1)
+  { log3("warning: qmail-todo: 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: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; }
+  }
+
+ fnmake_info(id);
+ if (unlink(fn.s) == -1) if (errno != error_noent)
+  { log3("warning: qmail-todo: unable to unlink ",fn.s,"\n"); goto fail; }
+
+ fdinfo = open_excl(fn.s);
+ if (fdinfo == -1)
+  { log3("warning: qmail-todo: unable to create ",fn.s,"\n"); goto fail; }
+
+ strnum[fmt_ulong(strnum,id)] = 0;
+ log3("new msg ",strnum,"\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: qmail-todo: 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: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail;
+	}
+	comm_info(id, (unsigned long) st.st_size, todoline.s + 1, pid, uid);
+       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: qmail-todo: 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: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail;
+        }
+       break;
+     default:
+       fnmake_todo(id);
+       log3("warning: qmail-todo: unknown record type in ",fn.s,"\n"); goto fail;
+    }
+  }
+
+ close(fd); fd = -1;
+
+ fnmake_info(id);
+ if (substdio_flush(&ssinfo) == -1)
+  { log3("warning: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; }
+ if (fsync(fdinfo) == -1)
+  { log3("warning: qmail-todo: 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: qmail-todo: trouble writing to ",fn.s,"\n"); goto fail; }
+     if (fsync(fdchan[c]) == -1)
+      { log3("warning: qmail-todo: 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;
+  }
+
+ comm_write(id, flagchan[0], flagchan[1]);
+ 
+ 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(void)
+{
+ if (control_init() == -1) return 0;
+ if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) 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(void)
+{
+ int r;
+
+ if (control_readfile(&newlocals,"control/locals",1) != 1)
+  { log1("alert: qmail-todo: unable to reread control/locals\n"); return; }
+ r = control_readfile(&newvdoms,"control/virtualdomains",0);
+ if (r == -1)
+  { log1("alert: qmail-todo: 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(void)
+{
+ if (chdir(auto_qmail) == -1)
+  {
+   log1("alert: qmail-todo: unable to reread controls: unable to switch to home directory\n");
+   return;
+  }
+ regetcontrols();
+ while (chdir("queue") == -1)
+  {
+   log1("alert: qmail-todo: unable to switch back to queue directory; HELP! sleeping...\n");
+   sleep(10);
+  }
+}
+
+void main()
+{
+ datetime_sec wakeup;
+ fd_set rfds;
+ fd_set wfds;
+ int nfds;
+ struct timeval tv;
+ int r;
+ char c;
+
+ if (chdir(auto_qmail) == -1)
+  { log1("alert: qmail-todo: cannot start: unable to switch to home directory\n"); _exit(111); }
+ if (!getcontrols())
+  { log1("alert: qmail-todo: cannot start: unable to read controls\n"); _exit(111); }
+ if (chdir("queue") == -1)
+  { log1("alert: qmail-todo: cannot start: unable to switch to queue directory\n"); _exit(111); }
+ sig_pipeignore();
+ umask(077);
+
+ fnmake_init();
+
+ todo_init();
+ comm_init();
+ 
+ do {
+   r = read(fdin, &c, 1);
+   if ((r == -1) && (errno != error_intr))
+     _exit(100); /* read failed probably qmail-send died */
+ } while (r =! 1); /* we assume it is a 'S' */
+ 
+ for (;;)
+  {
+   recent = now();
+
+   if (flagreadasap) { flagreadasap = 0; reread(); }
+   if (!flagsendalive) {
+     /* qmail-send finaly exited, so do the same. */
+     if (flagstopasap) _exit(0);
+     /* qmail-send died. We can not log and we can not work therefor _exit(1). */
+     _exit(1);
+   }
+
+   wakeup = recent + SLEEP_FOREVER;
+   FD_ZERO(&rfds);
+   FD_ZERO(&wfds);
+   nfds = 1;
+
+   todo_selprep(&nfds,&rfds,&wakeup);
+   comm_selprep(&nfds,&wfds,&rfds);
+
+   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: qmail-todo: trouble in select\n");
+   else
+    {
+     recent = now();
+
+     todo_do(&rfds);
+     comm_do(&wfds, &rfds);
+    }
+  }
+  /* NOTREACHED */
+}
+
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/ssl_timeoutio.c work/netqmail-1.06/ssl_timeoutio.c
--- tmp/netqmail-1.06/ssl_timeoutio.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/ssl_timeoutio.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,95 @@
+#include "select.h"
+#include "error.h"
+#include "ndelay.h"
+#include "now.h"
+#include "ssl_timeoutio.h"
+
+int ssl_timeoutio(int (*fun)(),
+  int t, int rfd, int wfd, SSL *ssl, char *buf, int len)
+{
+  int n;
+  const datetime_sec end = (datetime_sec)t + now();
+
+  do {
+    fd_set fds;
+    struct timeval tv;
+
+    const int r = buf ? fun(ssl, buf, len) : fun(ssl);
+    if (r > 0) return r;
+
+    t = end - now();
+    if (t < 0) break;
+    tv.tv_sec = (time_t)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(int 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(int 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(int 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(int 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(int 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 --speed-large-files --minimal -Nru tmp/netqmail-1.06/ssl_timeoutio.h work/netqmail-1.06/ssl_timeoutio.h
--- tmp/netqmail-1.06/ssl_timeoutio.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/ssl_timeoutio.h	2016-05-06 14:30:55.000000000 -0500
@@ -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(int t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutaccept(int t, int rfd, int wfd, SSL *ssl);
+int ssl_timeoutrehandshake(int t, int rfd, int wfd, SSL *ssl);
+
+int ssl_timeoutread(int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+int ssl_timeoutwrite(int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+int ssl_timeoutio(
+  int (*fun)(), int t, int rfd, int wfd, SSL *ssl, char *buf, int len);
+
+#endif
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/tls.c work/netqmail-1.06/tls.c
--- tmp/netqmail-1.06/tls.c	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/tls.c	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,25 @@
+#include "exit.h"
+#include "error.h"
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+int smtps = 0;
+SSL *ssl = NULL;
+
+void ssl_free(SSL *myssl) { SSL_shutdown(myssl); SSL_free(myssl); }
+void ssl_exit(int status) { if (ssl) ssl_free(ssl); _exit(status); }
+
+const char *ssl_error()
+{
+  int r = ERR_get_error();
+  if (!r) return NULL;
+  SSL_load_error_strings();
+  return ERR_error_string(r, NULL);
+}
+const char *ssl_error_str()
+{
+  const char *err = ssl_error();
+  if (err) return err;
+  if (!errno) return 0;
+  return (errno == error_timeout) ? "timed out" : error_str(errno);
+}
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/tls.h work/netqmail-1.06/tls.h
--- tmp/netqmail-1.06/tls.h	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/tls.h	2016-05-06 14:30:55.000000000 -0500
@@ -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_error_str();
+
+#endif
diff --speed-large-files --minimal -Nru tmp/netqmail-1.06/update_tmprsadh.sh work/netqmail-1.06/update_tmprsadh.sh
--- tmp/netqmail-1.06/update_tmprsadh.sh	1969-12-31 18:00:00.000000000 -0600
+++ work/netqmail-1.06/update_tmprsadh.sh	2016-05-06 14:30:55.000000000 -0500
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Update temporary RSA and DH keys
+# Frederik Vermeulen 2004-05-31 GPL
+
+umask 0077 || exit 0
+
+export PATH="$PATH:/usr/local/bin/ssl:/usr/sbin"
+
+openssl genrsa -out QMAIL/control/rsa2048.new 2048 &&
+chmod 600 QMAIL/control/rsa2048.new &&
+chown UGQMAILD QMAIL/control/rsa2048.new &&
+mv -f QMAIL/control/rsa2048.new QMAIL/control/rsa2048.pem
+
+openssl dhparam -2 -out QMAIL/control/dh2048.new 2048 &&
+chmod 600 QMAIL/control/dh2048.new &&
+chown UGQMAILD QMAIL/control/dh2048.new &&
+mv -f QMAIL/control/dh2048.new QMAIL/control/dh2048.pem
