diff -u /usr/src/qmail-src/qmail-1.03/Makefile qmail-jb-1.03+smtp-virscan/Makefile
--- /usr/src/qmail-src/qmail-1.03/Makefile	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/Makefile	Wed Jan 14 14:16:35 2004
@@ -136,6 +136,10 @@
 compile auto_usera.c
 	./compile auto_usera.c
 
+base64.o: \
+compile base64.c base64.h stralloc.h substdio.h str.h
+	./compile base64.c
+
 binm1: \
 binm1.sh conf-qmail
 	cat binm1.sh \
@@ -217,9 +221,9 @@
 
 case.a: \
 makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \
-case_starts.o
+case_starts.o case_startb.o
 	./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \
-	case_lowers.o case_starts.o
+	case_lowers.o case_starts.o case_startb.o
 
 case_diffb.o: \
 compile case_diffb.c case.h
@@ -237,6 +241,10 @@
 compile case_lowers.c case.h
 	./compile case_lowers.c
 
+case_startb.o: \
+compile case_startb.c case.h
+	./compile case_startb.c
+
 case_starts.o: \
 compile case_starts.c case.h
 	./compile case_starts.c
@@ -1483,12 +1491,12 @@
 trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \
 datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \
 lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \
-auto_split.o
+auto_split.o env.a
 	./load qmail-send qsutil.o control.o constmap.o newfield.o \
 	prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \
 	qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \
 	wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \
-	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o 
+	substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a
 
 qmail-send.0: \
 qmail-send.8
@@ -1535,14 +1543,14 @@
 load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \
 timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \
 date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \
-open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \
-fs.a auto_qmail.o socket.lib
+open.a sig.a case.a env.a stralloc.a strerr.a alloc.a substdio.a error.a str.a \
+fs.a auto_qmail.o base64.o socket.lib dns.o dns.lib
 	./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \
 	timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \
 	received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \
 	datetime.a getln.a open.a sig.a case.a env.a stralloc.a \
-	alloc.a substdio.a error.a str.a fs.a auto_qmail.o  `cat \
-	socket.lib`
+	alloc.a strerr.a substdio.a error.a str.a fs.a auto_qmail.o base64.o  `cat \
+	socket.lib` dns.o `cat dns.lib`
 
 qmail-smtpd.0: \
 qmail-smtpd.8
@@ -1553,7 +1561,8 @@
 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 wait.h \
+fd.h base64.h
 	./compile qmail-smtpd.c
 
 qmail-start: \
diff -u /usr/src/qmail-src/qmail-1.03/TARGETS qmail-jb-1.03+smtp-virscan/TARGETS
--- /usr/src/qmail-src/qmail-1.03/TARGETS	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/TARGETS	Wed Nov 19 14:03:40 2003
@@ -250,6 +250,7 @@
 qmail-qmtpd.o
 rcpthosts.o
 qmail-qmtpd
+base64.o
 qmail-smtpd.o
 qmail-smtpd
 sendmail.o
Only in qmail-jb-1.03+smtp-virscan/: base64.c
Only in qmail-jb-1.03+smtp-virscan/: base64.h
diff -u /usr/src/qmail-src/qmail-1.03/binm1+df.sh qmail-jb-1.03+smtp-virscan/binm1+df.sh
--- /usr/src/qmail-src/qmail-1.03/binm1+df.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm1+df.sh	Wed Nov 19 14:00:49 2003
@@ -5,7 +5,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|dot-forward .forward
 |preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/binm1.sh qmail-jb-1.03+smtp-virscan/binm1.sh
--- /usr/src/qmail-src/qmail-1.03/binm1.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm1.sh	Wed Nov 19 14:00:49 2003
@@ -4,7 +4,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start \
 '|preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/binm2+df.sh qmail-jb-1.03+smtp-virscan/binm2+df.sh
--- /usr/src/qmail-src/qmail-1.03/binm2+df.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm2+df.sh	Wed Nov 19 14:00:49 2003
@@ -5,7 +5,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using SVR4 binmail interface: /bin/mail -r
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|dot-forward .forward
 |preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/binm2.sh qmail-jb-1.03+smtp-virscan/binm2.sh
--- /usr/src/qmail-src/qmail-1.03/binm2.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm2.sh	Wed Nov 19 14:00:49 2003
@@ -4,7 +4,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using SVR4 binmail interface: /bin/mail -r
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start \
 '|preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/binm3+df.sh qmail-jb-1.03+smtp-virscan/binm3+df.sh
--- /usr/src/qmail-src/qmail-1.03/binm3+df.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm3+df.sh	Wed Nov 19 14:00:49 2003
@@ -5,7 +5,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using V7 binmail interface: /bin/mail -f
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|dot-forward .forward
 |preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/binm3.sh qmail-jb-1.03+smtp-virscan/binm3.sh
--- /usr/src/qmail-src/qmail-1.03/binm3.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/binm3.sh	Wed Nov 19 14:00:49 2003
@@ -4,7 +4,7 @@
 # Using binmail to deliver messages to /var/spool/mail/$USER by default.
 # Using V7 binmail interface: /bin/mail -f
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start \
 '|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \
 splogger qmail
Only in qmail-jb-1.03+smtp-virscan/: case_startb.c
Only in qmail-jb-1.03+smtp-virscan/: case_startb.o
diff -u /usr/src/qmail-src/qmail-1.03/conf-groups qmail-jb-1.03+smtp-virscan/conf-groups
--- /usr/src/qmail-src/qmail-1.03/conf-groups	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/conf-groups	Wed Nov 19 14:00:49 2003
@@ -1,5 +1,5 @@
 qmail
-nofiles
+nogroup
 
 These are the qmail groups. The second group should not have access to
 any files, but it must be usable for processes; this requirement
diff -u /usr/src/qmail-src/qmail-1.03/config-fast.sh qmail-jb-1.03+smtp-virscan/config-fast.sh
--- /usr/src/qmail-src/qmail-1.03/config-fast.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/config-fast.sh	Wed Nov 19 14:00:49 2003
@@ -1,29 +1,29 @@
 fqdn="$1"
 echo Your fully qualified host name is "$fqdn".
 
-echo Putting "$fqdn" into control/me...
+echo Putting "$fqdn" into QMAIL/control/me...
 echo "$fqdn" > QMAIL/control/me
 chmod 644 QMAIL/control/me
 
 ( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | (
   read ddom
-  echo Putting "$ddom" into control/defaultdomain...
+  echo Putting "$ddom" into QMAIL/control/defaultdomain...
   echo "$ddom" > QMAIL/control/defaultdomain
   chmod 644 QMAIL/control/defaultdomain
 ) )
 
 ( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | (
   read pdom
-  echo Putting "$pdom" into control/plusdomain...
+  echo Putting "$pdom" into QMAIL/control/plusdomain...
   echo "$pdom" > QMAIL/control/plusdomain
   chmod 644 QMAIL/control/plusdomain
 ) )
 
-echo Putting "$fqdn" into control/locals...
+echo Putting "$fqdn" into QMAIL/control/locals...
 echo "$fqdn" >> QMAIL/control/locals
 chmod 644 QMAIL/control/locals
 
-echo Putting "$fqdn" into control/rcpthosts...
+echo Putting "$fqdn" into QMAIL/control/rcpthosts...
 echo "$fqdn" >> QMAIL/control/rcpthosts
 chmod 644 QMAIL/control/rcpthosts
 echo "Now qmail will refuse to accept SMTP messages except to $fqdn."
diff -u /usr/src/qmail-src/qmail-1.03/config.sh qmail-jb-1.03+smtp-virscan/config.sh
--- /usr/src/qmail-src/qmail-1.03/config.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/config.sh	Wed Nov 19 14:00:49 2003
@@ -6,18 +6,18 @@
       if read fqdn
       then
         echo Your host\'s fully qualified name in DNS is "$fqdn".
-	echo Putting "$fqdn" into control/me...
+	echo Putting "$fqdn" into QMAIL/control/me ...
 	echo "$fqdn" > QMAIL/control/me
 	chmod 644 QMAIL/control/me
 	( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | (
 	  read ddom
-	  echo Putting "$ddom" into control/defaultdomain...
+	  echo Putting "$ddom" into QMAIL/control/defaultdomain ...
 	  echo "$ddom" > QMAIL/control/defaultdomain
 	  chmod 644 QMAIL/control/defaultdomain
 	) )
 	( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | (
 	  read pdom
-	  echo Putting "$pdom" into control/plusdomain...
+	  echo Putting "$pdom" into QMAIL/control/plusdomain ...
 	  echo "$pdom" > QMAIL/control/plusdomain
 	  chmod 644 QMAIL/control/plusdomain
 	) )
@@ -34,7 +34,7 @@
 	    ./dnsptr "$localip" 2>/dev/null | (
 	      if read local
 	      then
-		echo Adding "$local" to control/locals...
+		echo Adding "$local" to QMAIL/control/locals...
 		echo "$local" >> QMAIL/control/locals
 	      else
 		echo PTR lookup failed. I assume this address has no DNS name.
@@ -54,11 +54,11 @@
 	echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!'
       else
         echo Sorry, I couldn\'t find your host\'s canonical name in DNS.
-        echo You will have to set up control/me yourself.
+        echo You will have to set up QMAIL/control/me yourself.
       fi
     )
   else
     echo Sorry, I couldn\'t find your hostname.
-    echo You will have to set up control/me yourself.
+    echo You will have to set up QMAIL/control/me yourself.
   fi
 )
Only in qmail-jb-1.03+smtp-virscan/: contrib
diff -u /usr/src/qmail-src/qmail-1.03/datemail.sh qmail-jb-1.03+smtp-virscan/datemail.sh
--- /usr/src/qmail-src/qmail-1.03/datemail.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/datemail.sh	Wed Nov 19 14:00:49 2003
@@ -1 +1 @@
-exec QMAIL/bin/predate QMAIL/bin/sendmail ${1+"$@"}
+exec /usr/sbin/predate /usr/sbin/sendmail ${1+"$@"}
Only in qmail-jb-1.03+smtp-virscan/: debian
diff -u /usr/src/qmail-src/qmail-1.03/dns.c qmail-jb-1.03+smtp-virscan/dns.c
--- /usr/src/qmail-src/qmail-1.03/dns.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/dns.c	Wed Nov 19 14:00:49 2003
@@ -21,10 +21,12 @@
 static unsigned short getshort(c) unsigned char *c;
 { unsigned short u; u = c[0]; return (u << 8) + c[1]; }
 
-static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response;
+static struct { unsigned char *buf; } response;
+static int responsebuflen = 0;
 static int responselen;
 static unsigned char *responseend;
 static unsigned char *responsepos;
+static u_long saveresoptions;
 
 static int numanswers;
 static char name[MAXDNAME];
@@ -45,18 +47,33 @@
  errno = 0;
  if (!stralloc_copy(&glue,domain)) return DNS_MEM;
  if (!stralloc_0(&glue)) return DNS_MEM;
- responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response));
+ if (!responsebuflen)
+  if (response.buf = (unsigned char *)alloc(PACKETSZ+1))
+   responsebuflen = PACKETSZ+1;
+  else return DNS_MEM;
+
+ responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+ if ((responselen >= responsebuflen) ||
+     (responselen > 0 && (((HEADER *)response.buf)->tc)))
+  {
+   if (responsebuflen < 65536)
+    if (alloc_re(&response.buf, responsebuflen, 65536))
+     responsebuflen = 65536;
+    else return DNS_MEM;
+    saveresoptions = _res.options;
+    _res.options |= RES_USEVC;
+    responselen = lookup(glue.s,C_IN,type,response.buf,responsebuflen);
+    _res.options = saveresoptions;
+  }
  if (responselen <= 0)
   {
    if (errno == ECONNREFUSED) return DNS_SOFT;
    if (h_errno == TRY_AGAIN) return DNS_SOFT;
    return DNS_HARD;
   }
- if (responselen >= sizeof(response))
-   responselen = sizeof(response);
  responseend = response.buf + responselen;
  responsepos = response.buf + sizeof(HEADER);
- n = ntohs(response.hdr.qdcount);
+ n = ntohs(((HEADER *)response.buf)->qdcount);
  while (n-- > 0)
   {
    i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME);
@@ -66,7 +83,7 @@
    if (i < QFIXEDSZ) return DNS_SOFT;
    responsepos += QFIXEDSZ;
   }
- numanswers = ntohs(response.hdr.ancount);
+ numanswers = ntohs(((HEADER *)response.buf)->ancount);
  return 0;
 }
 
diff -u /usr/src/qmail-src/qmail-1.03/elq.sh qmail-jb-1.03+smtp-virscan/elq.sh
--- /usr/src/qmail-src/qmail-1.03/elq.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/elq.sh	Wed Nov 19 14:00:49 2003
@@ -1 +1 @@
-QMAIL/bin/maildir2mbox && exec elm ${1+"$@"}
+/usr/bin/maildir2mbox && exec elm ${1+"$@"}
diff -u /usr/src/qmail-src/qmail-1.03/home+df.sh qmail-jb-1.03+smtp-virscan/home+df.sh
--- /usr/src/qmail-src/qmail-1.03/home+df.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/home+df.sh	Wed Nov 19 14:00:49 2003
@@ -4,6 +4,6 @@
 # Using dot-forward to support sendmail-style ~/.forward files.
 # Using qmail-local to deliver messages to ~/Mailbox by default.
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|dot-forward .forward
 ./Mailbox' splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/home.sh qmail-jb-1.03+smtp-virscan/home.sh
--- /usr/src/qmail-src/qmail-1.03/home.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/home.sh	Wed Nov 19 14:00:49 2003
@@ -3,5 +3,5 @@
 # Using splogger to send the log through syslog.
 # Using qmail-local to deliver messages to ~/Mailbox by default.
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start ./Mailbox splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/install.c qmail-jb-1.03+smtp-virscan/install.c
--- /usr/src/qmail-src/qmail-1.03/install.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/install.c	Wed Nov 19 14:00:49 2003
@@ -33,7 +33,9 @@
 int gid;
 int mode;
 {
-  if (chdir(home) == -1)
+    if (fchdir(fdsourcedir) == -1)
+	        strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
+    if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
   if (mkdir(subdir,0700) == -1)
     if (errno != error_exist)
@@ -51,6 +53,8 @@
 int gid;
 int mode;
 {
+  if (fchdir(fdsourcedir) == -1)
+	      strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
   if (fifo_make(fifo,0700) == -1)
@@ -127,6 +131,8 @@
 {
   int fdout;
 
+  if (fchdir(fdsourcedir) == -1)
+	      strerr_die2sys(111,FATAL,"unable to switch back to source directory: ");
   if (chdir(home) == -1)
     strerr_die4sys(111,FATAL,"unable to switch to ",home,": ");
 
diff -u /usr/src/qmail-src/qmail-1.03/mailsubj.sh qmail-jb-1.03+smtp-virscan/mailsubj.sh
--- /usr/src/qmail-src/qmail-1.03/mailsubj.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/mailsubj.sh	Wed Nov 19 14:00:49 2003
@@ -4,4 +4,4 @@
   echo To: ${1+"$@"}
   echo ''
   cat
-) | QMAIL/bin/qmail-inject
+) | /usr/sbin/qmail-inject
Only in qmail-jb-1.03+smtp-virscan/: msg00151.txt
Only in qmail-jb-1.03+smtp-virscan/: netscape-progress.patch
diff -u /usr/src/qmail-src/qmail-1.03/pinq.sh qmail-jb-1.03+smtp-virscan/pinq.sh
--- /usr/src/qmail-src/qmail-1.03/pinq.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/pinq.sh	Wed Nov 19 14:00:49 2003
@@ -1 +1 @@
-QMAIL/bin/maildir2mbox && exec pine ${1+"$@"}
+/usr/bin/maildir2mbox && exec pine ${1+"$@"}
Only in qmail-jb-1.03+smtp-virscan/: pop3-supplementarygroups.diff
diff -u /usr/src/qmail-src/qmail-1.03/proc+df.sh qmail-jb-1.03+smtp-virscan/proc+df.sh
--- /usr/src/qmail-src/qmail-1.03/proc+df.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/proc+df.sh	Wed Nov 19 14:00:49 2003
@@ -4,6 +4,6 @@
 # Using dot-forward to support sendmail-style ~/.forward files.
 # Using procmail to deliver messages to /var/spool/mail/$USER by default.
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|dot-forward .forward
 |preline procmail' splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/proc.sh qmail-jb-1.03+smtp-virscan/proc.sh
--- /usr/src/qmail-src/qmail-1.03/proc.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/proc.sh	Wed Nov 19 14:00:49 2003
@@ -3,5 +3,5 @@
 # Using splogger to send the log through syslog.
 # Using procmail to deliver messages to /var/spool/mail/$USER by default.
 
-exec env - PATH="QMAIL/bin:$PATH" \
+exec \
 qmail-start '|preline procmail' splogger qmail
diff -u /usr/src/qmail-src/qmail-1.03/qail.sh qmail-jb-1.03+smtp-virscan/qail.sh
--- /usr/src/qmail-src/qmail-1.03/qail.sh	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qail.sh	Wed Nov 19 14:00:49 2003
@@ -1 +1 @@
-QMAIL/bin/maildir2mbox && exec Mail ${1+"$@"}
+/usr/bin/maildir2mbox && exec Mail ${1+"$@"}
diff -u /usr/src/qmail-src/qmail-1.03/qmail-control.9 qmail-jb-1.03+smtp-virscan/qmail-control.9
--- /usr/src/qmail-src/qmail-1.03/qmail-control.9	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-control.9	Wed Nov 19 14:33:39 2003
@@ -55,6 +55,7 @@
 .I idhost	\fIme	\fRqmail-inject
 .I localiphost	\fIme	\fRqmail-smtpd
 .I locals	\fIme	\fRqmail-send
+.I mfcheck	\fR0	\fRqmail-smtpd
 .I morercpthosts	\fR(none)	\fRqmail-smtpd
 .I percenthack	\fR(none)	\fRqmail-send
 .I plusdomain	\fIme	\fRqmail-inject
Only in qmail-jb-1.03+smtp-virscan/: qmail-link-sync.patch
diff -u /usr/src/qmail-src/qmail-1.03/qmail-local.c qmail-jb-1.03+smtp-virscan/qmail-local.c
--- /usr/src/qmail-src/qmail-1.03/qmail-local.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-local.c	Wed Nov 19 14:00:49 2003
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "env.h"
@@ -128,6 +129,9 @@
  if (close(fd) == -1) goto fail; /* NFS dorks */
 
  if (link(fntmptph,fnnewtph) == -1) goto fail;
+ if ((fd = open(fnnewtph, O_RDONLY)) < 0 ||
+     fsync(fd) < 0 || close(fd) < 0) goto fail;
+   
    /* if it was error_exist, almost certainly successful; i hate NFS */
  tryunlinktmp(); _exit(0);
 
diff -u /usr/src/qmail-src/qmail-1.03/qmail-lspawn.c qmail-jb-1.03+smtp-virscan/qmail-lspawn.c
--- /usr/src/qmail-src/qmail-1.03/qmail-lspawn.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-lspawn.c	Wed Nov 19 14:00:49 2003
@@ -139,7 +139,7 @@
   }
 
  if (pipe(pi) == -1) _exit(QLX_SYS);
- args[0] = "bin/qmail-getpw";
+ args[0] = "/usr/sbin/qmail-getpw";
  args[1] = local;
  args[2] = 0;
  switch(gpwpid = vfork())
@@ -191,7 +191,7 @@
    x = nughde.s;
    xlen = nughde.len;
 
-   args[0] = "bin/qmail-local";
+   args[0] = "/usr/sbin/qmail-local";
    args[1] = "--";
    args[2] = x;
    n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n;
diff -u /usr/src/qmail-src/qmail-1.03/qmail-pop3d.c qmail-jb-1.03+smtp-virscan/qmail-pop3d.c
--- /usr/src/qmail-src/qmail-1.03/qmail-pop3d.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-pop3d.c	Wed Nov 19 14:00:49 2003
@@ -267,7 +267,11 @@
  
   fd = open_read(m[i].fn);
   if (fd == -1) { err_nosuch(); return; }
-  okay();
+  /* okay(); */
+  puts("+OK ");
+  put(strnum,fmt_ulong(strnum,m[i].size));
+  puts(" octets\r\n");
+  flush();
   substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
   blast(&ssmsg,limit);
   close(fd);
diff -u /usr/src/qmail-src/qmail-1.03/qmail-queue.c qmail-jb-1.03+smtp-virscan/qmail-queue.c
--- /usr/src/qmail-src/qmail-1.03/qmail-queue.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-queue.c	Wed Nov 19 14:00:49 2003
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 #include "readwrite.h"
 #include "sig.h"
 #include "exit.h"
@@ -155,6 +156,7 @@
 {
  unsigned int len;
  char ch;
+ int fd;
 
  sig_blocknone();
  umask(033);
@@ -183,7 +185,7 @@
  todofn = fnnum("todo/",0);
  intdfn = fnnum("intd/",0);
 
- if (link(pidfn,messfn) == -1) die(64);
+ if (link(pidfn,messfn) == -1) die(64); 
  if (unlink(pidfn) == -1) die(63);
  flagmademess = 1;
 
@@ -248,6 +250,8 @@
  if (fsync(intdfd) == -1) die_write();
 
  if (link(intdfn,todofn) == -1) die(66);
+ if ((fd = open(todofn, O_RDONLY)) < 0 ||
+     fsync(fd) < 0 || close(fd) < 0) die(66); 
 
  triggerpull();
  die(0);
Only in qmail-jb-1.03+smtp-virscan/: qmail-smtpd-bmtpatch.diff
diff -u /usr/src/qmail-src/qmail-1.03/qmail-smtpd.8 qmail-jb-1.03+smtp-virscan/qmail-smtpd.8
--- /usr/src/qmail-src/qmail-1.03/qmail-smtpd.8	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-smtpd.8	Wed Nov 19 14:33:39 2003
@@ -3,6 +3,11 @@
 qmail-smtpd \- receive mail via SMTP
 .SH SYNOPSIS
 .B qmail-smtpd
+[
+.I hostname
+.I checkprogram
+.I subprogram
+]
 .SH DESCRIPTION
 .B qmail-smtpd
 receives mail messages via the Simple Mail Transfer Protocol (SMTP)
@@ -23,7 +28,29 @@
 header fields.
 
 .B qmail-smtpd
-supports ESMTP, including the 8BITMIME and PIPELINING options.
+supports ESMTP, including the 8BITMIME, PIPELINING, and AUTH options.
+
+.B qmail-smtpd
+can accept LOGIN, PLAIN, and CRAM-MD5 AUTH types.  It invokes
+.IR checkprogram ,
+which reads on file descriptor 3 the username, a 0 byte, the password
+or challenge derived from
+.IR hostname ,
+another 0 byte, a CRAM-MD5 response (if applicable to the AUTH type),
+and a final 0 byte.
+.I checkprogram
+invokes
+.I subprogram
+upon successful authentication, which should in turn return 0 to
+.BR qmail-smtpd ,
+effectively setting the environment variables RELAYCLIENT and TCPREMOTEINFO
+(any supplied value replaced with the authenticated username).
+.B qmail-smtpd
+will reject the authentication attempt if it receives a nonzero return
+value from
+.I checkprogram
+or
+.IR subprogram .
 .SH TRANSPARENCY
 .B qmail-smtpd
 converts the SMTP newline convention into the UNIX newline convention
@@ -97,6 +124,12 @@
 This is done before
 .IR rcpthosts .
 .TP 5
+.I mfcheck
+If set,
+.B qmail-smtpd
+tries to resolve the domain of the envelope from address.  It can be
+handy when you want to filter out spamhosts.
+.TP 5
 .I morercpthosts
 Extra allowed RCPT domains.
 If
@@ -177,3 +210,6 @@
 qmail-newmrh(8),
 qmail-queue(8),
 qmail-remote(8)
+.SH "HISTORY"
+The patch enabling the ESMTP AUTH option is not part of the standard
+qmail-1.03 distribution.
diff -u /usr/src/qmail-src/qmail-1.03/qmail-smtpd.c qmail-jb-1.03+smtp-virscan/qmail-smtpd.c
--- /usr/src/qmail-src/qmail-1.03/qmail-smtpd.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail-smtpd.c	Wed Jan 14 18:43:59 2004
@@ -23,10 +23,16 @@
 #include "timeoutread.h"
 #include "timeoutwrite.h"
 #include "commands.h"
+#include "dns.h"
+#include "strerr.h"
+#include "wait.h"
+#include "fd.h"
 
+#undef AUTHCRAM
 #define MAXHOPS 100
 unsigned int databytes = 0;
 int timeout = 1200;
+unsigned int mfchk = 0;
 
 int safewrite(fd,buf,len) int fd; char *buf; int len;
 {
@@ -49,7 +55,10 @@
 void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); }
 void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); }
 
-void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
+void err_bmf() { out("553 badmailfrom - see http://www.rb-hosting.de/spamblock.php (#5.7.1)\r\n"); }
+void err_bmt() { out("553 badmailto - see http://www.rb-hosting.de/spamblock.php (#5.7.1)\r\n"); }
+void err_hmf() { out("553 sorry, your envelope sender domain must exist (#5.7.1)\r\n"); }
+void err_smf() { out("451 DNS temporary failure (#4.3.0)\r\n"); }
 void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
 void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
 void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
@@ -59,6 +68,15 @@
 void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); }
 void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); }
 
+int err_child() { out("454 oops, problem with child and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_fork() { out("454 oops, child won't start and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_pipe() { out("454 oops, unable to open pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+int err_write() { out("454 oops, unable to write pipe and I can't auth (#4.3.0)\r\n"); return -1; }
+void err_authd() { out("503 you're already authenticated (#5.5.0)\r\n"); }
+void err_authmail() { out("503 no auth during mail transaction (#5.5.0)\r\n"); }
+int err_noauth() { out("504 auth type unimplemented (#5.5.1)\r\n"); return -1; }
+int err_authabrt() { out("501 auth exchange cancelled (#5.0.0)\r\n"); return -1; }
+int err_input() { out("501 malformed auth input (#5.5.4)\r\n"); return -1; }
 
 stralloc greeting = {0};
 
@@ -96,6 +114,13 @@
 int bmfok = 0;
 stralloc bmf = {0};
 struct constmap mapbmf;
+int bmtok = 0;
+stralloc bmt = {0};
+struct constmap mapbmt;
+int tarpitcount = 0;
+int tarpitdelay = 5;
+int sigsok = 0;
+stralloc sigs = {0};
 
 void setup()
 {
@@ -110,13 +135,34 @@
   if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control();
   if (timeout <= 0) timeout = 1;
 
+  if (control_readint(&tarpitcount,"control/tarpitcount") == -1) die_control();
+  if (tarpitcount < 0) tarpitcount = 0;
+  x = env_get("TARPITCOUNT");
+  if (x) { scan_ulong(x,&u); tarpitcount = u; };
+  if (control_readint(&tarpitdelay,"control/tarpitdelay") == -1) die_control();
+  if (tarpitdelay < 0) tarpitdelay = 0;
+  x = env_get("TARPITDELAY");
+  if (x) { scan_ulong(x,&u); tarpitdelay = u; };
+
   if (rcpthosts_init() == -1) die_control();
 
+  if (control_readint(&mfchk,"control/mfcheck") == -1) die_control();
+  x = env_get("MFCHECK");
+  if (x) { scan_ulong(x,&u); mfchk = u; }
+
   bmfok = control_readfile(&bmf,"control/badmailfrom",0);
   if (bmfok == -1) die_control();
   if (bmfok)
     if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem();
  
+  bmtok = control_readfile(&bmt,"control/badmailto",0);
+  if (bmtok == -1) die_control();
+  if (bmtok)
+    if (!constmap_init(&mapbmt,bmt.s,bmt.len,0)) die_nomem();
+ 
+  sigsok = control_readfile(&sigs,"control/signatures",0);
+  if (sigsok == -1) die_control();
+
   if (control_readint(&databytes,"control/databytes") == -1) die_control();
   x = env_get("DATABYTES");
   if (x) { scan_ulong(x,&u); databytes = u; }
@@ -208,6 +254,49 @@
   return 0;
 }
 
+int bmtcheck()
+{
+  int j;
+  if (!bmtok) return 0;
+  if (constmap(&mapbmt,addr.s,addr.len - 1)) return 1;
+  j = byte_rchr(addr.s,addr.len,'@');
+  if (j < addr.len)
+    if (constmap(&mapbmt,addr.s + j,addr.len - j - 1)) return 1;
+  return 0;
+}
+
+int mfcheck()
+{
+  stralloc sa = {0};
+  ipalloc ia = {0};
+  unsigned int random;
+  int j;
+
+  if (!mfchk) return 0;
+  random = now() + (getpid() << 16);
+  j = byte_rchr(addr.s,addr.len,'@') + 1;
+  if (j < addr.len) {
+    stralloc_copys(&sa, addr.s + j);
+    dns_init(0);
+    j = dns_mxip(&ia,&sa,random);
+    if (j < 0) return j;
+  }
+  return 0;
+}
+
+int sigscheck(stralloc *line) {
+  int i, j;
+
+  j = 0;
+  for (i = 0; i < sigs.len; i++) if (!sigs.s[i]) {
+    if (i-j < line->len)
+      if (!str_diffn(line->s,sigs.s+j,i-j))
+	return 1;
+    j = i+1;
+  }
+  return 0;
+}
+
 int addrallowed()
 {
   int r;
@@ -219,8 +308,10 @@
 
 int seenmail = 0;
 int flagbarf; /* defined if seenmail */
+int bmtbarf; /* defined if seenmail */
 stralloc mailfrom = {0};
 stralloc rcptto = {0};
+int rcptcount;
 
 void smtp_helo(arg) char *arg;
 {
@@ -229,7 +320,15 @@
 }
 void smtp_ehlo(arg) char *arg;
 {
-  smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
+  smtp_greet("250-");
+#ifdef AUTHCRAM
+  out("\r\n250-AUTH LOGIN CRAM-MD5 PLAIN");
+  out("\r\n250-AUTH=LOGIN CRAM-MD5 PLAIN");
+#else
+  out("\r\n250-AUTH LOGIN PLAIN");
+  out("\r\n250-AUTH=LOGIN PLAIN");
+#endif
+  out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n");
   seenmail = 0; dohelo(arg);
 }
 void smtp_rset()
@@ -241,16 +340,34 @@
 {
   if (!addrparse(arg)) { err_syntax(); return; }
   flagbarf = bmfcheck();
+  switch(mfcheck()) {
+    case DNS_HARD: err_hmf(); return;
+    case DNS_SOFT: err_smf(); return;
+    case DNS_MEM: die_nomem();
+  }
   seenmail = 1;
   if (!stralloc_copys(&rcptto,"")) die_nomem();
   if (!stralloc_copys(&mailfrom,addr.s)) die_nomem();
   if (!stralloc_0(&mailfrom)) die_nomem();
+  rcptcount = 0;
   out("250 ok\r\n");
 }
 void smtp_rcpt(arg) char *arg; {
   if (!seenmail) { err_wantmail(); return; }
   if (!addrparse(arg)) { err_syntax(); return; }
-  if (flagbarf) { err_bmf(); return; }
+  bmtbarf = bmtcheck();
+  // if (flagbarf) { err_bmf(); return; }
+  // if (bmtbarf) { err_bmt(); return; }
+  if (flagbarf) {
+    strerr_warn4("qmail-smtpd: badmailfrom: ",mailfrom.s," at ",remoteip,0);
+    err_bmf();
+    return;
+  }
+  if (bmtbarf) {
+    strerr_warn4("qmail-smtpd: badmailto: ",addr.s," at ",remoteip,0);
+    err_bmt();
+    return;
+  }
   if (relayclient) {
     --addr.len;
     if (!stralloc_cats(&addr,relayclient)) die_nomem();
@@ -261,6 +378,7 @@
   if (!stralloc_cats(&rcptto,"T")) die_nomem();
   if (!stralloc_cats(&rcptto,addr.s)) die_nomem();
   if (!stralloc_0(&rcptto)) die_nomem();
+  if (tarpitcount && ++rcptcount >= tarpitcount) while (sleep(tarpitdelay)); 
   out("250 ok\r\n");
 }
 
@@ -281,9 +399,131 @@
 struct qmail qqt;
 unsigned int bytestooverflow = 0;
 
+int linespastheader;		/* =0 after boundary is found in body, */
+                                /* until blank line */
+char linetype;
+int flagexecutable;
+
+stralloc line = {0};
+stralloc content = {0};
+stralloc boundary = {0};
+int boundary_start;
+
+/*
+
+def put(ch):
+    line.append(ch)
+    if ch == '\n':
+        if linepastheader == 0:
+            if line.beginswith('Content-Type:'):
+                content = 
+
+ put() puts characters into the queue.  We remember those characters
+   and form them into a line.  When we get a newline, we examine the
+   line.  If we're currently in a header (0 linespastheader), we look
+   for Content-Type.  If we're at the newline that ends a header, we
+   look to see if the content is multipart.  If it is, then we push
+   the current boundary, remember the boundary, otherwise we set the
+   boundary to the empty string.  Set the linespastheader to 1.  When
+   linespastheader is 1, and the boundary is empty, scan the line for
+   signatures.  If the boundary is non-empty, look for a match against
+   the boundary.  If it matches and is followed by two dashes, pop the
+   boundary, otherwise set linespastheader to 0.
+*/
+
 void put(ch)
 char *ch;
 {
+  char *cp, *cpstart, *cpafter;
+  unsigned int len;
+
+  if (line.len < 1024)
+    if (!stralloc_catb(&line,ch,1)) die_nomem();
+
+  if (*ch == '\n') {
+    if (linespastheader == 0) {
+      if (line.len == 1) {
+	linespastheader = 1;	
+	if (content.len) {			/* MIME header */
+	  cp = content.s;
+	  len = content.len;
+	  while (len && (*cp == ' ' || *cp == '\t')) { ++cp; --len; }
+	  cpstart = cp;
+	  if (len && *cp == '"') {			/* might be commented */
+	    ++cp; --len; cpstart = cp;
+	    while (len && *cp != '"') { ++cp; --len; }
+	  } else {
+	    while (len && *cp != ' ' && *cp != '\t' && *cp != ';') {
+	      ++cp; --len;
+	    }
+	  }
+
+	  cpafter = content.s+content.len;
+	  while((cp += byte_chr(cp,cpafter-cp,';')) != cpafter) {
+	    ++cp;
+	    while (cp < cpafter && (*cp == ' ' || *cp == '\t')) ++cp;
+	    if (case_startb(cp,cpafter - cp,"boundary=")) {
+	      cp += 9;			/* after boundary= */
+	      if (cp < cpafter && *cp == '"') {
+		++cp;
+		cpstart = cp;
+		while (cp < cpafter && *cp != '"') ++cp;
+	      } else {
+		cpstart = cp;
+		while (cp < cpafter &&
+		   *cp != ';' && *cp != ' ' && *cp != '\t') ++cp;
+	      }
+	      /* push the current boundary.  Append a null and remember start. */
+	      if (!stralloc_0(&boundary)) die_nomem();
+	      boundary_start = boundary.len;
+	      if (!stralloc_cats(&boundary,"--")) die_nomem();
+	      if (!stralloc_catb(&boundary,cpstart,cp-cpstart))
+		      die_nomem();
+	      break;
+	    }
+	  }
+	}
+      } else { /* non-blank header line */
+	if ((*line.s == ' ' || *line.s == '\t')) {
+	  switch(linetype) {
+	    case 'C': if (!stralloc_catb(&content,line.s,line.len-1)) die_nomem(); break;
+	    default: break;
+	  }
+	} else {
+	  if (case_startb(line.s,line.len,"content-type:")) {
+	    if (!stralloc_copyb(&content,line.s+13,line.len-14)) die_nomem();
+	    linetype = 'C';
+	  } else {
+	    linetype = ' ';
+	  }
+	}
+      }
+    } else {      /* non-header line */
+      if (boundary.len-boundary_start && *line.s == '-' && line.len > (boundary.len-boundary_start) &&
+	  !str_diffn(line.s,boundary.s+boundary_start,boundary.len-boundary_start)) { /* matches a boundary */
+	if (line.len > boundary.len-boundary_start + 2 &&
+            line.s[boundary.len-boundary_start+0] == '-' &&
+            line.s[boundary.len-boundary_start+1] == '-') {
+	  /* XXXX - pop the boundary here */
+	  if (boundary_start) boundary.len = boundary_start - 1;
+	  boundary_start = boundary.len;
+	  while(boundary_start--) if (!boundary.s[boundary_start]) break;
+	  boundary_start++;
+	  linespastheader = 2;
+	} else {
+	  linespastheader = 0;
+	}
+      } else if (linespastheader == 1) { /* first line -- match a signature? */
+	if (sigscheck(&line)) {
+	  flagexecutable = 1;
+	  qmail_fail(&qqt);
+	}
+	linespastheader = 2;
+      }
+    }
+    line.len = 0;
+  }
+
   if (bytestooverflow)
     if (!--bytestooverflow)
       qmail_fail(&qqt);
@@ -374,6 +614,12 @@
   if (!rcptto.len) { err_wantrcpt(); return; }
   seenmail = 0;
   if (databytes) bytestooverflow = databytes + 1;
+  boundary.len = 0;
+  boundary_start = 0;
+  content.len = 0;
+  linespastheader = 0;
+  flagexecutable = 0;
+  linetype = ' ';
   if (qmail_open(&qqt) == -1) { err_qqt(); return; }
   qp = qmail_qp(&qqt);
   out("354 go ahead\r\n");
@@ -389,15 +635,236 @@
   if (!*qqx) { acceptmessage(qp); return; }
   if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; }
   if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; }
+  if (flagexecutable) { 
+	out("552 executable content - see http://www.rb-hosting.de/spamblock.php (#5.3.4)\r\n");
+	strerr_warn6("qmail-smtpd: executable content: from ",mailfrom.s," to " rcptto.s," at ",remoteip,0);
+	//strerr_warn4("qmail-smtpd: executable content: from ",mailfrom.s," at ",remoteip,0);
+  return; }
   if (*qqx == 'D') out("554 "); else out("451 ");
   out(qqx + 1);
   out("\r\n");
 }
 
+
+char unique[FMT_ULONG + FMT_ULONG + 3];
+static stralloc authin = {0};
+static stralloc user = {0};
+static stralloc pass = {0};
+static stralloc resp = {0};
+static stralloc slop = {0};
+char *hostname;
+char **childargs;
+substdio ssup;
+char upbuf[128];
+int authd = 0;
+
+int authgetl(void) {
+  int i;
+
+  if (!stralloc_copys(&authin, "")) die_nomem();
+
+  for (;;) {
+    if (!stralloc_readyplus(&authin,1)) die_nomem(); /* XXX */
+    i = substdio_get(&ssin,authin.s + authin.len,1);
+    if (i != 1) die_read();
+    if (authin.s[authin.len] == '\n') break;
+    ++authin.len;
+  }
+
+  if (authin.len > 0) if (authin.s[authin.len - 1] == '\r') --authin.len;
+  authin.s[authin.len] = 0;
+
+  if (*authin.s == '*' && *(authin.s + 1) == 0) { return err_authabrt(); }
+  if (authin.len == 0) { return err_input(); }
+  return authin.len;
+}
+
+int authenticate(void)
+{
+  int child;
+  int wstat;
+  int pi[2];
+
+  if (!stralloc_0(&user)) die_nomem();
+  if (!stralloc_0(&pass)) die_nomem();
+  if (!stralloc_0(&resp)) die_nomem();
+
+  if (fd_copy(2,1) == -1) return err_pipe();
+  close(3);
+  if (pipe(pi) == -1) return err_pipe();
+  if (pi[0] != 3) return err_pipe();
+  switch(child = fork()) {
+    case -1:
+      return err_fork();
+    case 0:
+      close(pi[1]);
+      sig_pipedefault();
+      execvp(*childargs, childargs);
+      _exit(1);
+  }
+  close(pi[0]);
+
+  substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf);
+  if (substdio_put(&ssup,user.s,user.len) == -1) return err_write();
+  if (substdio_put(&ssup,pass.s,pass.len) == -1) return err_write();
+  if (substdio_put(&ssup,resp.s,resp.len) == -1) return err_write();
+  if (substdio_flush(&ssup) == -1) return err_write();
+
+  close(pi[1]);
+  byte_zero(pass.s,pass.len);
+  byte_zero(upbuf,sizeof upbuf);
+  if (wait_pid(&wstat,child) == -1) return err_child();
+  if (wait_crashed(wstat)) return err_child();
+  if (wait_exitcode(wstat)) { sleep(5); return 1; } /* no */
+  return 0; /* yes */
+}
+
+int auth_login(arg) char *arg;
+{
+  int r;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&user) == 1) return err_input();
+  }
+  else {
+    out("334 VXNlcm5hbWU6\r\n"); flush(); /* Username: */
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&user) == 1) return err_input();
+  }
+  if (r == -1) die_nomem();
+
+  out("334 UGFzc3dvcmQ6\r\n"); flush(); /* Password: */
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&pass) == 1) return err_input();
+  if (r == -1) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();  
+}
+
+int auth_plain(arg) char *arg;
+{
+  int r, id = 0;
+
+  if (*arg) {
+    if (r = b64decode(arg,str_len(arg),&slop) == 1) return err_input();
+  }
+  else {
+    out("334 \r\n"); flush();
+    if (authgetl() < 0) return -1;
+    if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  }
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+  while (slop.s[id]) id++; /* ignore authorize-id */
+
+  if (slop.len > id + 1)
+    if (!stralloc_copys(&user,slop.s + id + 1)) die_nomem();
+  if (slop.len > id + user.len + 2)
+    if (!stralloc_copys(&pass,slop.s + id + user.len + 2)) die_nomem();
+
+  if (!user.len || !pass.len) return err_input();
+  return authenticate();
+}
+
+#ifdef AUTHCRAM
+int auth_cram()
+{
+  int i, r;
+  char *s;
+
+  s = unique;
+  s += fmt_uint(s,getpid());
+  *s++ = '.';
+  s += fmt_ulong(s,(unsigned long) now());
+  *s++ = '@';
+  *s++ = 0;
+
+  if (!stralloc_copys(&pass,"<")) die_nomem();
+  if (!stralloc_cats(&pass,unique)) die_nomem();
+  if (!stralloc_cats(&pass,hostname)) die_nomem();
+  if (!stralloc_cats(&pass,">")) die_nomem();
+  if (b64encode(&pass,&slop) < 0) die_nomem();
+  if (!stralloc_0(&slop)) die_nomem();
+
+  out("334 ");
+  out(slop.s);
+  out("\r\n");
+  flush();
+
+  if (authgetl() < 0) return -1;
+  if (r = b64decode(authin.s,authin.len,&slop) == 1) return err_input();
+  if (r == -1 || !stralloc_0(&slop)) die_nomem();
+
+  i = str_chr(slop.s,' ');
+  s = slop.s + i;
+  while (*s == ' ') ++s;
+  slop.s[i] = 0;
+  if (!stralloc_copys(&user,slop.s)) die_nomem();
+  if (!stralloc_copys(&resp,s)) die_nomem();
+
+  if (!user.len || !resp.len) return err_input();
+  return authenticate();
+}
+#endif
+
+struct authcmd {
+  char *text;
+  int (*fun)();
+} authcmds[] = {
+  { "login", auth_login }
+, { "plain", auth_plain }
+#ifdef AUTHCRAM
+, { "cram-md5", auth_cram }
+#endif
+, { 0, err_noauth }
+};
+
+void smtp_auth(arg)
+char *arg;
+{
+  int i;
+  char *cmd = arg;
+
+  if (!hostname || !*childargs)
+  {
+    out("503 auth not available (#5.3.3)\r\n");
+    return;
+  }
+  if (authd) { err_authd(); return; }
+  if (seenmail) { err_authmail(); return; }
+
+  if (!stralloc_copys(&user,"")) die_nomem();
+  if (!stralloc_copys(&pass,"")) die_nomem();
+  if (!stralloc_copys(&resp,"")) die_nomem();
+
+  i = str_chr(cmd,' ');   
+  arg = cmd + i;
+  while (*arg == ' ') ++arg;
+  cmd[i] = 0;
+
+  for (i = 0;authcmds[i].text;++i)
+    if (case_equals(authcmds[i].text,cmd)) break;
+
+  switch (authcmds[i].fun(arg)) {
+    case 0:
+      authd = 1;
+      relayclient = "";
+      remoteinfo = user.s;
+      if (!env_unset("TCPREMOTEINFO")) die_read();
+      if (!env_put2("TCPREMOTEINFO",remoteinfo)) die_nomem();
+      out("235 ok, go ahead (#2.0.0)\r\n");
+      break;
+    case 1:
+      out("535 authorization failed (#5.7.0)\r\n");
+  }
+}
+
 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 }
@@ -408,8 +875,13 @@
 , { 0, err_unimpl, flush }
 } ;
 
-void main()
+void main(argc,argv)
+int argc;
+char **argv;
 {
+  hostname = argv[1];
+  childargs = argv + 2;
+
   sig_pipeignore();
   if (chdir(auto_qmail) == -1) die_control();
   setup();
diff -u /usr/src/qmail-src/qmail-1.03/qmail.c qmail-jb-1.03+smtp-virscan/qmail.c
--- /usr/src/qmail-src/qmail-1.03/qmail.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/qmail.c	Wed Nov 19 14:00:49 2003
@@ -6,14 +6,25 @@
 #include "fd.h"
 #include "qmail.h"
 #include "auto_qmail.h"
+#include "env.h"
 
-static char *binqqargs[2] = { "bin/qmail-queue", 0 } ;
+static char *binqqargs[2] = { 0, 0 } ;
+
+static void setup_qqargs()
+{
+  if(!binqqargs[0])
+    binqqargs[0] = env_get("QMAILQUEUE");
+  if(!binqqargs[0])
+    binqqargs[0] = "bin/qmail-queue";
+}
 
 int qmail_open(qq)
 struct qmail *qq;
 {
   int pim[2];
   int pie[2];
+
+  setup_qqargs();
 
   if (pipe(pim) == -1) return -1;
   if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; }
Only in qmail-jb-1.03+smtp-virscan/: qmailqueue-patch
diff -u /usr/src/qmail-src/qmail-1.03/sendmail.c qmail-jb-1.03+smtp-virscan/sendmail.c
--- /usr/src/qmail-src/qmail-1.03/sendmail.c	Mon Jun 15 12:53:16 1998
+++ qmail-jb-1.03+smtp-virscan/sendmail.c	Wed Nov 19 14:00:49 2003
@@ -19,7 +19,7 @@
   _exit(100);
 }
 
-char *smtpdarg[] = { "bin/qmail-smtpd", 0 };
+char *smtpdarg[] = { "/usr/sbin/qmail-smtpd", 0 };
 void smtpd()
 {
   if (!env_get("PROTO")) {
@@ -37,7 +37,7 @@
   _exit(111);
 }
 
-char *qreadarg[] = { "bin/qmail-qread", 0 };
+char *qreadarg[] = { "/usr/sbin/qmail-qread", 0 };
 void mailq()
 {
   execv(*qreadarg,qreadarg);
@@ -113,7 +113,7 @@
   if (!qiargv) nomem();
  
   arg = qiargv;
-  *arg++ = "bin/qmail-inject";
+  *arg++ = "/usr/sbin/qmail-inject";
   *arg++ = (flagh ? "-H" : "-a");
   if (sender) {
     *arg++ = "-f";

