diff -u -r zmailer-2.99.49p3/ChangeLog zmailer-2.99.49p4/ChangeLog
--- zmailer-2.99.49p3/ChangeLog Thu Jul  3 15:22:01 1997
+++ zmailer-2.99.49p4/ChangeLog Fri Jul  4 20:28:03 1997
@@ -1,3 +1,41 @@
+Fri Jul  4 14:54:02 1997  Matti Aarnio  <[email protected]>
+
+       * Makefile.in
+           Version 2.99.49p4
+
+       * router/rfc822.c:
+           Nuke headers: "Bcc:", "Return-Path:", "X-Orcpt:", "X-Envid:",
+                         and respective "Resent-*:" variants
+
+       * router/libdb/bsdbtree.c:
+           If the db can not be opened ( open_btree() returns NULL ),
+           don't crash on it..
+
+       * scheduler/msgerror.c:
+           In case the report we are composing does have "NOTIFY=NEVER"
+           in effect, but no valid recipients exist, ignore any such
+           NOTIFY value, and return the message in full -- to the system
+           postmaster...
+
+       * transports/mailbox/mailbox.c:
+           Found a bug in let_buffer[] reuse -- it was an "automatic"
+           variable, that it, stack reclaimed it at will when needed,
+           and of course were able to corrupt it!
+           I also enlarged the  let_buffer[]  size to be of reasonable
+           size -- 16k to 64k depending on your BUFSIZ value.
+
+       * transports/mailbox/mailbox.c:
+           Add headers "X-Orcpt:" and "X-Envid:" to the message when
+           storing it into a file.  For a pipe the data is passed in
+           envelope variables.  (I got rather fed up with spams this
+           morning, and decided to add a bit more trace as to whom
+           the message has been sent originally..)
+
+       * transports/smtp/smtp.c:
+           Accept non rfc-821 behaviour of the remote server by treating
+           non-conformant reply of form:  "NNN<CRLF>" the same as
+           conformant reply of form: "NNN<SP><CRLF>".
+
Sun Jun 29 21:36:43 1997  Matti Aarnio  <[email protected]>

       * Makefile.in:
@@ -70,7 +108,8 @@

       * router/libdb/headers.c:
           Allow   "Reply-To:" and "Resent-Reply-To:" to have value: "<>"
-           (sigh...)
+           (sigh...  It is against RFC-822, but I see such usage few times
+            each day...)

       * scheduler/msgerror.c, transports/errormail/errormail.c,
         transports/fuzzyalias/fuzzyalias.c, transports/mailbox/mailbox.c:
diff -u -r zmailer-2.99.49p3/Makefile zmailer-2.99.49p4/Makefile
--- zmailer-2.99.49p3/Makefile  Thu Jul  3 16:58:58 1997
+++ zmailer-2.99.49p4/Makefile  Fri Jul  4 20:29:16 1997
@@ -3,7 +3,7 @@

MAJORVERSION = 2
MINORVERSION = 99
-PATCHLEVEL =   49p3
+PATCHLEVEL =   49p4

srcdir = .

diff -u -r zmailer-2.99.49p3/Makefile.in zmailer-2.99.49p4/Makefile.in
--- zmailer-2.99.49p3/Makefile.in       Thu Jul  3 16:58:51 1997
+++ zmailer-2.99.49p4/Makefile.in       Fri Jul  4 14:54:18 1997
@@ -2,7 +2,7 @@

MAJORVERSION = 2
MINORVERSION = 99
-PATCHLEVEL =   49p3
+PATCHLEVEL =   49p4

srcdir = @srcdir@
VPATH = @srcdir@
diff -u -r zmailer-2.99.49p3/README.SPAM zmailer-2.99.49p4/README.SPAM
--- zmailer-2.99.49p3/README.SPAM       Sun Jun 15 17:13:05 1997
+++ zmailer-2.99.49p4/README.SPAM       Fri Jul  4 20:36:10 1997
@@ -1,4 +1,4 @@
-19970615/mea
+19970615/[email protected]

       SPAM is an increasing problem, and one aspect of it is
       unauthorized email relaying thru various smtp servers.
diff -u -r zmailer-2.99.49p3/proto/db/smtp-policy.src zmailer-2.99.49p4/proto/db/smtp-policy.src
--- zmailer-2.99.49p3/proto/db/smtp-policy.src  Sun Jun 15 02:40:10 1997
+++ zmailer-2.99.49p4/proto/db/smtp-policy.src  Fri Jul  4 18:36:11 1997
@@ -203,7 +203,7 @@
#| Some source users we reject always: (frequent spammers..)
#| (see comment above about Anti-SPAM databases)
#|
-friend@                        = _buld_mail
-friends@               = _buld_mail
+friend@                        = _bulk_mail
+friends@               = _bulk_mail

#----------------------------------
diff -u -r zmailer-2.99.49p3/router/libdb/bsdbtree.c zmailer-2.99.49p4/router/libdb/bsdbtree.c
--- zmailer-2.99.49p3/router/libdb/bsdbtree.c   Tue Jun 10 18:31:26 1997
+++ zmailer-2.99.49p4/router/libdb/bsdbtree.c   Fri Jul  4 20:14:35 1997
@@ -2,7 +2,7 @@
 *     Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
 *     This will be free software, but only when it is finished.
 *
- *     Copyright 1996 Matti Aarnio
+ *     Copyright 1996-1997 Matti Aarnio
 */

/* LINTLIBRARY */
@@ -112,6 +112,8 @@
reopen:
               db = open_btree(sip, O_RDONLY, "search_btree");
       }
+       if (db == NULL)
+         return NULL; /* Huh! */
       key.data = (char*)sip->key;
       key.size = strlen(sip->key) + 1;
       rc = (db->get)(db, &key, &val, 0);
diff -u -r zmailer-2.99.49p3/router/rfc822.c zmailer-2.99.49p4/router/rfc822.c
--- zmailer-2.99.49p3/router/rfc822.c   Mon May 26 20:49:00 1997
+++ zmailer-2.99.49p4/router/rfc822.c   Fri Jul  4 14:55:55 1997
@@ -1531,31 +1531,22 @@
               if (ph == e->e_eHeaders)
                       return PERR_NORECIPIENTS;
       }
-       dprintf("Nuke Bcc headers if any\n");
-       oh = NULL;
-       for (h = e->e_headers; h != NULL; oh = h, h = h->h_next) {
-         if (h->h_descriptor->hdr_name == NULL)
-           continue;
-         if ((h->h_descriptor->class == normal
-              && CISTREQ(h->h_descriptor->hdr_name,"bcc"))
-             || (h->h_descriptor->class == Resent
-                 && CISTREQ(h->h_descriptor->hdr_name, "resent-bcc"))) {
-           if (oh == NULL)
-             e->e_headers = h->h_next;
-           else
-             oh->h_next = h->h_next;
-         }
-       }

-       dprintf("Nuke Return-Path headers if any\n");
+       dprintf("Nuke Bcc/Return-Path/X-Orcpt/X-Envid headers, if any\n");
       oh = NULL;
       for (h = e->e_headers; h != NULL; oh = h, h = h->h_next) {
         if (h->h_descriptor->hdr_name == NULL)
           continue;
-         if ((h->h_descriptor->class == normal
-              && CISTREQ(h->h_descriptor->hdr_name,"return-path"))
-             || (h->h_descriptor->class == Resent
-                 && CISTREQ(h->h_descriptor->hdr_name,"resent-return-path"))){
+         if ((h->h_descriptor->class == normal &&
+              (CISTREQ(h->h_descriptor->hdr_name,"bcc") ||
+               CISTREQ(h->h_descriptor->hdr_name,"return-path") ||
+               CISTREQ(h->h_descriptor->hdr_name,"x-orcpt")     ||
+               CISTREQ(h->h_descriptor->hdr_name,"x-envid")        ))
+             || (h->h_descriptor->class == Resent &&
+                 (CISTREQ(h->h_descriptor->hdr_name,"resent-BCC")         ||
+                  CISTREQ(h->h_descriptor->hdr_name,"resent-return-path") ||
+                  CISTREQ(h->h_descriptor->hdr_name,"resent-x-orcpt")     ||
+                  CISTREQ(h->h_descriptor->hdr_name,"resent-x-envid")    ))) {
           if (oh == NULL)
             e->e_headers = h->h_next;
           else
diff -u -r zmailer-2.99.49p3/scheduler/msgerror.c zmailer-2.99.49p4/scheduler/msgerror.c
--- zmailer-2.99.49p3/scheduler/msgerror.c      Sun Jun 29 21:21:55 1997
+++ zmailer-2.99.49p4/scheduler/msgerror.c      Fri Jul  4 13:06:15 1997
@@ -69,13 +69,14 @@
       }
}

-static void scnotaryreport __((FILE *, struct not *, int *));
+static void scnotaryreport __((FILE *, struct not *, int *, int));

static void    /* There is notaryreport() on transporters also.. */
-scnotaryreport(errfp,notary,haserrsp)
+scnotaryreport(errfp,notary,haserrsp,notifyrespectflg)
       FILE *errfp;
       struct not *notary;
       int *haserrsp;
+       int notifyrespectflg;
{
       char *rcpt, *action, *status, *diagstr, *wtt;
       char *cp;
@@ -90,6 +91,10 @@
         return; /* XX: ?? call into here should not happen.. */
       }

+       if ((notary->notifyflgs & NOT_NEVER) && (notifyrespectflg >= 0))
+         return; /* We ignore this recipient, because so has been
+                    asked, and this is not a double-fault... */
+
       rcpt     = notary->not;
       if (*rcpt == 0)
         return;       /* XX: ?? eh, well.. we should not be called.. */
@@ -522,8 +527,7 @@
               if (*d) *d++ = 0;
               continue;
             }
-             if (notaries[notarycnt].notifyflgs & NOT_NEVER)
-               continue; /* Don't report on this recipient! */
+             /* Report conditional testing in the latter phases */
           }
           while (isascii(*cp) && isspace(*cp))
             ++cp;
@@ -580,6 +584,9 @@
       for (i = 0; i < notarycnt; ++i) {
         /* Scan to the start of the message text */
         const char *ccp, *s;
+         if ((notaries[i].notifyflgs & NOT_NEVER) && (no_error_report >= 0))
+           continue;
+         /* Report is not outright rejected, or this is double fault */
         fprintf(errfp, "<%s>: ", notaries[i].rcpntp);
         ccp = notaries[i].message;
         if (strchr(ccp, '\r')) {
@@ -615,7 +622,7 @@

       /* Now scan 'em all again for IETF-NOTARY */
       for (i = 0; i < notarycnt; ++i) {
-         scnotaryreport(errfp, &notaries[i],&has_errors);
+         scnotaryreport(errfp, &notaries[i],&has_errors,no_error_report);
         if (notaries[i].not != NULL)
           free(notaries[i].not);
       }
@@ -664,8 +671,10 @@
             fseek(fp, (off_t)0, SEEK_SET);
           }
         }
-         if (has_errors && !never_full_content &&
-             (!cfp->dsnretmode || CISTREQN(cfp->dsnretmode,"FULL",4))) {
+         if (has_errors &&
+             ((no_error_report < 0) ||
+              (!never_full_content &&
+               (!cfp->dsnretmode || CISTREQN(cfp->dsnretmode,"FULL",4))))) {
           /* Copy out the rest (=body) with somewhat more efficient method */

           while ((n = fread(buf, sizeof buf[0], sizeof buf, fp)) > 0)
diff -u -r zmailer-2.99.49p3/transports/mailbox/mailbox.c zmailer-2.99.49p4/transports/mailbox/mailbox.c
--- zmailer-2.99.49p3/transports/mailbox/mailbox.c      Mon Jun 30 09:06:54 1997
+++ zmailer-2.99.49p4/transports/mailbox/mailbox.c      Fri Jul  4 19:39:57 1997
@@ -274,6 +274,7 @@
FILE *verboselog = NULL;
#if !(defined(HAVE_MMAP) && defined(TA_USE_MMAP))
int   readalready = 0;         /* does buffer contain valid message data? */
+char  let_buffer[8*BUFSIZ];
#endif
uid_t currenteuid;             /* the current euid */
extern int nobody;             /* safe uid for file/program delivery */
@@ -1516,6 +1517,16 @@
           append_header(rp,"Apparently-To: <%s>", rp->addr->link->user);
         }
       }
+       if (rp->orcpt) {
+         char **hdrs = has_header(rp,"X-Orcpt:");
+         if (hdrs) delete_header(rp,hdrs);
+         append_header(rp,"X-Orcpt: %s", rp->orcpt);
+       }
+       if (dp->envid) {
+         char **hdrs = has_header(rp,"X-Envid:");
+         if (hdrs) delete_header(rp,hdrs);
+         append_header(rp,"X-Envid: %s", dp->envid);
+       }


       if (*fromuser == 0)
@@ -1551,14 +1562,7 @@
       }
       lastch = appendlet(dp, rp, fp, file, is_mime);

-       for (;;) {
-         errno = 0;
-         fflush(fp); /* HP-UX 9.x barfs when flushing to the PIPE,
-                        but apparently it does not set ferror() ! */
-         if (errno == EINTR)
-           continue;
-         break;
-       }
+       fflush(fp);

       mw = 1;
       if (lastch < -128 || ferror(fp)) {
@@ -1571,14 +1575,7 @@
                     mw, file, strerror(err));
#ifdef HAVE_FTRUNCATE
         /* XX: should I really do this? */
-         for (;;) {
-           errno = 0;
-           fflush(fp); /* HP-UX 9.x barfs when flushing to the PIPE,
-                          but apparently it does not set ferror() ! */
-           if (errno == EINTR)
-             continue;
-           break;
-         }
+         fflush(fp);
         if (eofindex >= 0)
           ftruncate(FILENO(fp), (off_t)eofindex);
#endif
@@ -1616,14 +1613,8 @@
           --len;
           len = (buf[len]!='\n') + (len == 1 ? buf[0]!='\n' : 1);
           err = (len > 0 && (fwrite("\n\n", 1, len, fp) != len));
-           for (;;) {
-             errno = 0;
-             fflush(fp); /* HP-UX 9.x barfs when flushing to the PIPE,
-                            but apparently it does not set ferror() ! */
-             if (errno == EINTR)
-               continue;
-             break;
-           }
+           fflush(fp);
+
           if (!err) err = ferror(fp);
           if (err) {
             notaryreport(NULL,NULL,NULL,NULL);
@@ -1631,14 +1622,7 @@
                        "cleansing of \"%s\" failed", file);
#ifdef HAVE_FTRUNCATE
             /* XX: should I really do this? */
-             for (;;) {
-               errno = 0;
-               fflush(fp); /* HP-UX 9.x barfs when flushing to the PIPE,
-                              but apparently it does not set ferror() ! */
-               if (errno == EINTR)
-                 continue;
-               break;
-             }
+             fflush(fp);
             if (eofindex >= 0)
               ftruncate(FILENO(fp), (off_t)eofindex);
#endif /* HAVE_FTRUNCATE */
@@ -1647,6 +1631,7 @@
#endif
             fclose(fp);
             fp = NULL;
+
             goto time_reset;
           }
         }
@@ -1660,14 +1645,7 @@
         }
       }

-       for (;;) {
-         errno = 0;
-         fflush(fp); /* HP-UX 9.x barfs when flushing to the PIPE,
-                        but apparently it does not set ferror() ! */
-         if (errno == EINTR)
-           continue;
-         break;
-       }
+       fflush(fp);
       if (ferror(fp)) {
         mw=3;
         goto write_failure;
@@ -1691,12 +1669,12 @@
         fprintf(logfp,
                 "%s: %ld + %ld : %s (pid %d user %s)\n",
                 dp->logident, eofindex,
-                 ftell(fp) - eofindex, file,
+                 (fp ? ftell(fp): 0) - eofindex, file,
                 getpid(), rp->addr->user);
#if 0
         fprintf(logfp, "%s: %ld + %ld : %s\n",
                 dp->logident, eofindex,
-                 ftell(fp) - eofindex, file);
+                 (fp ? ftell(fp): 0) - eofindex, file);
#endif
         fflush(logfp);
       }
@@ -2223,8 +2201,6 @@
       const char *s; /* message body start */

#if !(defined(HAVE_MMAP) && defined(TA_USE_MMAP))
-       char buffer[BUFSIZ+1];
-       const char *bufend = buffer+BUFSIZ;
       register int i;
       register int bufferfull;
       char iobuf[BUFSIZ]; /* For setvbuf(mfp) */
@@ -2246,7 +2222,7 @@
         /* Split it to lines.. */
         if (readalready > 0) {
           int linelen, readidx = 0;
-           const char *s0 = buffer, *s;
+           const char *s0 = let_buffer, *s;
           while (readidx < readalready) {
             s = s0;
             linelen = 0;
@@ -2278,13 +2254,14 @@
         /* We really can't use the 'let_buffer' cache here */
         readalready = 0;
         i = 0;
-         while ((i = cfgets(buffer, BUFSIZ, mfp)) != EOF) {
+         while ((i = cfgets(let_buffer, sizeof(let_buffer), mfp)) != EOF) {
           /* It MAY be malformed -- if it has a BUFSIZ length
              line in it, IT CAN'T BE MIME  :-/                */
-           if (i == BUFSIZ && buffer[BUFSIZ-1] != '\n')
+           if (i == sizeof(let_buffer) &&
+               let_buffer[sizeof(let_buffer)-1] != '\n')
             ismime = 0;
           /* Ok, write the line */
-           if (writemimeline(&WS, buffer, i) != i) {
+           if (writemimeline(&WS, let_buffer, i) != i) {
             DIAGNOSTIC(rp, file, EX_IOERR, "write to \"%s\" failed", file);
             MFPCLOSE;
             return -256;
@@ -2302,7 +2279,7 @@

         /* can we use cache of message body data ? */
         if (readalready != 0) {
-           if (writebuf(&WS, buffer, readalready) != readalready) {
+           if (writebuf(&WS, let_buffer, readalready) != readalready) {
             DIAGNOSTIC(rp, file, EX_IOERR,
                        "write to \"%s\" failed", file);
             return -256;
@@ -2316,7 +2293,7 @@
         lseek(mfd, dp->msgbodyoffset, SEEK_SET);
         bufferfull = 0;
         while (1) {
-           i = read(mfd, buffer, BUFSIZ);
+           i = read(mfd, let_buffer, sizeof(let_buffer));
           if (i == 0)
             break;
           if (i < 0) {
@@ -2325,7 +2302,7 @@
             readalready = 0;
             return -256;
           }
-           if (writebuf(&WS, buffer, i) != i) {
+           if (writebuf(&WS, let_buffer, i) != i) {
             DIAGNOSTIC(rp, file, EX_IOERR, "write to \"%s\" failed", file);
             readalready = 0;
             return -256;
diff -u -r zmailer-2.99.49p3/transports/smtp/smtp.c zmailer-2.99.49p4/transports/smtp/smtp.c
--- zmailer-2.99.49p3/transports/smtp/smtp.c    Thu Jul  3 10:51:27 1997
+++ zmailer-2.99.49p4/transports/smtp/smtp.c    Fri Jul  4 21:27:03 1997
@@ -3514,7 +3514,8 @@
         return EX_TEMPFAIL;
       }
       *--cp = '\0';   /* kill the LF */
-       if (cp - buf < 5) {
+       if ((cp - buf) < 4) {
+         /* A '354<CRLR>' could be treated as ok... */
         sprintf(SS->remotemsg, "smtp; 500 (SMTP response '%s' unexpected!)", buf);
         time(&endtime);
         notary_setxdelay((int)(endtime-starttime));
@@ -3533,7 +3534,7 @@
         --cp;
       *++cp = '\0';
       for (i = 0; i < 4; ++i)         /* can't happen, right? wrong... */
-         if (buf[i] == ' ')
+         if (buf[i] == ' ' || buf[i] == '\r')
           break;
       if (i == 4) --i;
       ch = buf[i];
@@ -3553,6 +3554,9 @@


       dflag = 0;
+
+       if (response >= 400)
+         notaryreport(NULL,FAILED,NULL,NULL);

       rc = code_to_status(response, &status);