[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

fuzzy.tar.gz



Hello zmailer users,

attached are files to improve the zmailer.

The changes are:

- Care for Errors-To header
- Handle some hpux oddities
- Added Return-Receipt-To handling
- Fixed YP handling (e.g. no more memory faults)
- Close /dev/ksyms after reading it will enable more than 10 smtpservers
  because Solaris-2.x will not allow more than 10 processes opening /dev/ksyms
- Added new channel fuzzy will return an errormail showing possible alternative
  recipients. Add this channel to scheduler.conf like the error channel.

Greets, Sven
--
The only limits are in your mind !

diff -c -r orig/zmailer-2.99.39/config.h.in zmailer-2.99.39/config.h.in
*** orig/zmailer-2.99.39/config.h.in	Thu Aug 22 22:13:02 1996
--- zmailer-2.99.39/config.h.in	Tue Oct 29 17:28:03 1996
***************
*** 390,392 ****
--- 390,394 ----
  
  /* If the  sprintf() returns a char pointer ? */
  #undef SPRINTF_CHAR
+ 
+ #define HAVE_YP
diff -c -r orig/zmailer-2.99.39/configure zmailer-2.99.39/configure
*** orig/zmailer-2.99.39/configure	Thu Sep 12 21:01:37 1996
--- zmailer-2.99.39/configure	Tue Oct 29 17:45:22 1996
***************
*** 6643,6649 ****
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
--- 6643,6650 ----
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	transports/fuzzyalias/Makefile \
!     utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
***************
*** 6742,6748 ****
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
--- 6743,6750 ----
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	transports/fuzzyalias/Makefile \
!     utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
diff -c -r orig/zmailer-2.99.39/configure.in zmailer-2.99.39/configure.in
*** orig/zmailer-2.99.39/configure.in	Thu Sep 12 21:01:12 1996
--- zmailer-2.99.39/configure.in	Tue Oct 29 17:28:03 1996
***************
*** 1089,1095 ****
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
--- 1089,1096 ----
  	transports/Makefile		transports/smtp/Makefile	\
  	transports/mailbox/Makefile	transports/hold/Makefile	\
  	transports/libta/Makefile	transports/sm/Makefile		\
! 	transports/errormail/Makefile	transports/fuzzyalias/Makefile \
!     utils/makendbm/Makefile		\
  	support/vacation/Makefile	compat/Makefile			\
  	compat/rmail/Makefile		compat/sendmail/Makefile	\
  	lib/Makefile			libc/Makefile			\
diff -c -r orig/zmailer-2.99.39/include/ta.h zmailer-2.99.39/include/ta.h
*** orig/zmailer-2.99.39/include/ta.h	Fri Oct 25 19:28:00 1996
--- zmailer-2.99.39/include/ta.h	Tue Oct 29 17:28:03 1996
***************
*** 75,80 ****
--- 75,84 ----
  	long		*offset;	/* array of indices into contents */
  	struct address	*senders;	/* list of sender addresses */
  	struct rcpt	*recipients;	/* list of selected recipients */
+ 	char		*erroraddr;	/* [Thomas Knott]
+ 					 * "Errors-To"-Header:
+ 					 *     return address for error msgs
+ 					 */
  	int		rcpnts_total;	/* number of recipients, total */
  	int		rcpnts_remaining;/* .. how many yet to deliver */
  	int		rcpnts_failed  ;/* .. how many failed ones */
diff -c -r orig/zmailer-2.99.39/libc/strsignal.c zmailer-2.99.39/libc/strsignal.c
*** orig/zmailer-2.99.39/libc/strsignal.c	Fri Aug 30 10:15:02 1996
--- zmailer-2.99.39/libc/strsignal.c	Tue Oct 29 17:55:31 1996
***************
*** 42,48 ****
  #endif	/* HAVE_SYS_SIGLIST */
  
  #ifndef HAVE_STRSIGNAL
! #ifndef HAVE_EXTERN_SYS_SIGLIST
  extern const char *sys_siglist[];
  #endif
  
--- 42,48 ----
  #endif	/* HAVE_SYS_SIGLIST */
  
  #ifndef HAVE_STRSIGNAL
! #ifdef HAVE_EXTERN_SYS_SIGLIST
  extern const char *sys_siglist[];
  #endif
  
diff -c -r orig/zmailer-2.99.39/libresolv/Makefile.in zmailer-2.99.39/libresolv/Makefile.in
*** orig/zmailer-2.99.39/libresolv/Makefile.in	Wed Jul 31 11:20:43 1996
--- zmailer-2.99.39/libresolv/Makefile.in	Tue Oct 29 17:28:04 1996
***************
*** 76,82 ****
  #	  # (just another kludge due to Sun Solaris 2 ..)
  RANLIB= @RANLIB@
  DEFS=	@CFLAGS@ @DSPRINTF_TYPE@
! LOCDEFS= #-DUSE_OPTIONS_H
  
  AROBJS= ${ARPREF} ${OBJS} ${ARSUFF}
  
--- 76,82 ----
  #	  # (just another kludge due to Sun Solaris 2 ..)
  RANLIB= @RANLIB@
  DEFS=	@CFLAGS@ @DSPRINTF_TYPE@
! LOCDEFS= -DUSELOOPBACK #-DUSE_OPTIONS_H
  
  AROBJS= ${ARPREF} ${OBJS} ${ARSUFF}
  
diff -c -r orig/zmailer-2.99.39/router/rfc822.c zmailer-2.99.39/router/rfc822.c
*** orig/zmailer-2.99.39/router/rfc822.c	Fri Oct 25 18:42:45 1996
--- zmailer-2.99.39/router/rfc822.c	Tue Oct 29 17:28:04 1996
***************
*** 1536,1542 ****
  	if (h == NULL)
  	  FindHeader("to",!e->e_resent);
  	if (h == NULL) {
! #if 1
  		dprintf("No 'To:' -header, creating our own\n");
  		InsertHeader(h, mkToHeader(e,"unlisted-recipients:; (no To-header on input)"));
  #else
--- 1536,1547 ----
  	if (h == NULL)
  	  FindHeader("to",!e->e_resent);
  	if (h == NULL) {
! /* [Thomas Knott]
!  * Wenn kein "To:"-Header in der Mail angegeben wurde, dann soll
!  * einer aus den Informationen in der Enveloppe erzeugt werden
!  * (#else-Fall).
!  */
! #if 0
  		dprintf("No 'To:' -header, creating our own\n");
  		InsertHeader(h, mkToHeader(e,"unlisted-recipients:; (no To-header on input)"));
  #else
diff -c -r orig/zmailer-2.99.39/router/shliaise.c zmailer-2.99.39/router/shliaise.c
*** orig/zmailer-2.99.39/router/shliaise.c	Fri Oct 25 18:01:22 1996
--- zmailer-2.99.39/router/shliaise.c	Tue Oct 29 17:28:04 1996
***************
*** 224,236 ****
  		v_set(DEFER, "");
  		if (addrtokens == NULL)
  			s_value = NULL;
! 		else if (s_rewrite(name, addrtokens, (u_char *)NULL) != 0) {
  			if (s_value != NULL) {
  				s_free_tree(s_value);
  				s_value = NULL;
  			}
  			if (deferit
! 			    && s_rewrite(DEFERHDR, addrtokens, (u_char *)NULL)
  			    && s_value != NULL) {
  				s_free_tree(s_value);
  				s_value = NULL;
--- 224,242 ----
  		v_set(DEFER, "");
  		if (addrtokens == NULL)
  			s_value = NULL;
! 		/* [Thomas Knott]
! 		 * Den Funktionen "intramachine", "null", "internet" in
! 		 * crossbar.cf, die das Rewriten von Headern durchfuehren,
! 		 * wird der Headername als zusaetzlicher Parameter
! 		 * uebergeben.
! 		 */
! 		else if (s_rewrite(name, addrtokens, h->h_pname) != 0) {
  			if (s_value != NULL) {
  				s_free_tree(s_value);
  				s_value = NULL;
  			}
  			if (deferit
! 			    && s_rewrite(DEFERHDR, addrtokens, h->h_pname)
  			    && s_value != NULL) {
  				s_free_tree(s_value);
  				s_value = NULL;
diff -c -r orig/zmailer-2.99.39/router/libdb/bind.c zmailer-2.99.39/router/libdb/bind.c
*** orig/zmailer-2.99.39/router/libdb/bind.c	Thu Aug  8 19:57:47 1996
--- zmailer-2.99.39/router/libdb/bind.c	Tue Oct 29 17:28:04 1996
***************
*** 198,205 ****
  	 * Turn down the resolver's retry count.
  	 * The default (4) will cause the router to fall
  	 * hopelessly behind in the face of broken DNS data.
! 	 */
  	_res.retry   = 2;
  	if (sip->subtype == NULL || *(sip->subtype) == '\0') {
  	  fprintf(stderr, "search_res: missing subtype to BIND query!\n");
  	  return NULL;
--- 198,209 ----
  	 * Turn down the resolver's retry count.
  	 * The default (4) will cause the router to fall
  	 * hopelessly behind in the face of broken DNS data.
! 	 *
! 	 * [Thomas Knott]
! 	 * Die Defaultwerte aus der Resolver-Library sind fuer unsere
! 	 * Zwecke gerade richtig.
  	_res.retry   = 2;
+ 	 */
  	if (sip->subtype == NULL || *(sip->subtype) == '\0') {
  	  fprintf(stderr, "search_res: missing subtype to BIND query!\n");
  	  return NULL;
***************
*** 420,428 ****
  	} else if (nmx == 0)
  		return NULL;
  	/* discard MX RRs with a value >= that of localdomain */
  	if (maxpref >= 0) {
  		for (n = 0; n < nmx; ++n) {
! 			if (((int)mx[n].pref >= maxpref) && (mx[n].host != NULL)) {
  				free((char *)mx[n].host);
  				mx[n].host = NULL;
  			}
--- 424,440 ----
  	} else if (nmx == 0)
  		return NULL;
  	/* discard MX RRs with a value >= that of localdomain */
+ 	/* [Thomas Knott]
+ 	 * Aber den eigenen Rechnernamen nicht!
+ 	 * Wird in der Funktion "deliver" in standard.cf gebraucht, die ent-
+ 	 * scheidet, ob Mail am lokalen Rechner ausgeliefert wird oder nicht.
+ 	 */
  	if (maxpref >= 0) {
  		for (n = 0; n < nmx; ++n) {
! 			if (((int)mx[n].pref >= maxpref)
! 				    && (mx[n].host != NULL)
! 				    && (localhost != NULL)
! 				    && !(CISTREQ(mx[n].host, localhost))) {
  				free((char *)mx[n].host);
  				mx[n].host = NULL;
  			}
diff -c -r orig/zmailer-2.99.39/router/libdb/yp.c zmailer-2.99.39/router/libdb/yp.c
*** orig/zmailer-2.99.39/router/libdb/yp.c	Mon Jul 15 21:09:31 1996
--- zmailer-2.99.39/router/libdb/yp.c	Tue Oct 29 17:28:04 1996
***************
*** 80,86 ****
  	  if (valptr[vallen] == '\n') {
  	    valptr[vallen] = '\0';
  	  }
! 	  return newstring((u_char *) valptr);
  	case YPERR_KEY:
  	  /* occasionally the terminating NULL is included in the key (lose!)
  	     so if we failed for "key not found" then try again with the NULL
--- 80,86 ----
  	  if (valptr[vallen] == '\n') {
  	    valptr[vallen] = '\0';
  	  }
!       return newstring((u_char *)strnsave(valptr, vallen));
  	case YPERR_KEY:
  	  /* occasionally the terminating NULL is included in the key (lose!)
  	     so if we failed for "key not found" then try again with the NULL
diff -c -r orig/zmailer-2.99.39/smtpserver/loadaver.c zmailer-2.99.39/smtpserver/loadaver.c
*** orig/zmailer-2.99.39/smtpserver/loadaver.c	Wed Jul 10 17:07:29 1996
--- zmailer-2.99.39/smtpserver/loadaver.c	Tue Oct 29 17:28:04 1996
***************
*** 72,97 ****
  };
  static unsigned long avenrun_offset = 0;
  static int kd_inited = 0;
- static kvm_t *kd;
  
! static void
  machine_init()
  {
  	kd_inited = 1;
! 	kd = kvm_open(NULL, NULL, NULL, O_RDONLY, "(loadaver)");
  	if (kd == NULL) return;
  
  	if (kvm_nlist (kd, nlst) < 0) {
  	  kvm_close(kd);
! 	  kd = NULL;
! 	  return;
  	}
  	if (nlst[0].n_type == 0) { /* It wasn't found.. Our only! */
  	  kvm_close(kd);
! 	  kd = NULL;
! 	  return;
  	}
  	avenrun_offset = nlst[0].n_value; /* 0:th offset */
  }
  
  /*
--- 72,111 ----
  };
  static unsigned long avenrun_offset = 0;
  static int kd_inited = 0;
  
! /* [Thomas Knott]
!  * Unter Solaris-2.x wird bei kvm_open ein open auf /dev/ksyms gemacht.
!  * Der Treiber fuer /dev/ksyms laesst aber nur eine bestimmte Anzahl von
!  * offenen Filedeskriptoren (ca. 10) zu.
!  *
!  * In der originalen Version wird beim Start des Prozesses ein kvm_open
!  * gemacht und erst am Ende des Prozesses ein kvm_close. Aus diesem Grund
!  * koennten nie mehr als 10 "smtpserver"-Prozesse gleichzeitig laufen.
!  *
!  * Die nachfolgenden Funktionen wurden deshalb so abgeaendert, dass sobald
!  * der Filedeskriptor auf /dev/ksyms nicht mehr benoetigt wird, kvm_close
!  * aufegrufen wird.
!  */
! static int
  machine_init()
  {
+     kvm_t   *kd;
+ 
  	kd_inited = 1;
! 	kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
  	if (kd == NULL) return;
  
  	if (kvm_nlist (kd, nlst) < 0) {
  	  kvm_close(kd);
! 	  return 0;
  	}
  	if (nlst[0].n_type == 0) { /* It wasn't found.. Our only! */
  	  kvm_close(kd);
! 	  return 0;
  	}
  	avenrun_offset = nlst[0].n_value; /* 0:th offset */
+     kvm_close(kd);
+     return 1;
  }
  
  /*
***************
*** 106,123 ****
   *
   */
  static int
! getkval (offset, ptr, size, refstr)
  unsigned long offset;
  int *ptr;
  int size;
- char *refstr;
  {
!   if (kvm_read (kd, offset, (char *) ptr, size) != size) {
!     fprintf(stderr,
! 	      "top: kvm_read for %s: %s\n", refstr, sys_errlist[errno]);
!       return 0;
!   }
!   return 1;
  }
  
  int loadavg_current()
--- 120,138 ----
   *
   */
  static int
! getkval (offset, ptr, size)
  unsigned long offset;
  int *ptr;
  int size;
  {
!   kvm_t *kd;
!   int   ret;
! 
!   kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
!   ret = kvm_read (kd, offset, (char *) ptr, size);
!   kvm_close(kd);
! 
!   return (ret == size);
  }
  
  int loadavg_current()
***************
*** 124,139 ****
  {
  	long avenrun[3];
  
! 	if (!kd_inited) machine_init();
! 	if (kd == NULL) return 0;	/* No point.. */
  
  	/* get load average array */
! 	if (getkval(avenrun_offset,
! 		    (int *) avenrun, sizeof(avenrun),
! 		    "avenrun") == 0) {
! 	  kvm_close(kd);
  	  return 0; /* Failed.. */
  	}
  	return (int)(avenrun[0] >> 8); /* a fixed-point decimal number */
  }
  
--- 139,154 ----
  {
  	long avenrun[3];
  
! 	if (!kd_inited) {
!         if (machine_init() == 0)
!             return 0;
!     }
  
  	/* get load average array */
! 	if (getkval(avenrun_offset, (int *) avenrun, sizeof(avenrun)) == 0) {
  	  return 0; /* Failed.. */
  	}
+ 
  	return (int)(avenrun[0] >> 8); /* a fixed-point decimal number */
  }
  
diff -c -r orig/zmailer-2.99.39/smtpserver/smtpserver.c zmailer-2.99.39/smtpserver/smtpserver.c
*** orig/zmailer-2.99.39/smtpserver/smtpserver.c	Fri Oct 25 20:46:53 1996
--- zmailer-2.99.39/smtpserver/smtpserver.c	Tue Oct 29 16:35:36 1996
***************
*** 2776,2792 ****
  	void *s1, *s2, *s3; /* XX: Propably not portable.. */
  {
  	char *s = inbuf+3+strlen(status)+1;
  
  	printf("%03d-%s ", code < 0 ? -code : code,status);
  	if (logfp != NULL)
  	  fprintf(logfp, "%dw\t%03d-%s ", pid, code,status);
! 	if (((int)(rfc821_error_ptr - s)) < 200)
! 	  while (s < rfc821_error_ptr) {
! 	    ++s;
! 	    putc(' ',stdout);
! 	    if (logfp != NULL)
! 	      putc(' ',logfp);
! 	  }
  	printf("^\n");
  	if (logfp != NULL)
  	  fprintf(logfp,"^\n");
--- 2776,2792 ----
  	void *s1, *s2, *s3; /* XX: Propably not portable.. */
  {
  	char *s = inbuf+3+strlen(status)+1;
+ 	int maxcnt = 200;
  
  	printf("%03d-%s ", code < 0 ? -code : code,status);
  	if (logfp != NULL)
  	  fprintf(logfp, "%dw\t%03d-%s ", pid, code,status);
! 	while (s < rfc821_error_ptr && --maxcnt >= 0) {
! 	  ++s;
! 	  putc(' ',stdout);
! 	  if (logfp != NULL)
! 	    putc(' ',logfp);
! 	}
  	printf("^\n");
  	if (logfp != NULL)
  	  fprintf(logfp,"^\n");
diff -c -r orig/zmailer-2.99.39/transports/Makefile.in zmailer-2.99.39/transports/Makefile.in
*** orig/zmailer-2.99.39/transports/Makefile.in	Tue Jul 30 23:25:18 1996
--- zmailer-2.99.39/transports/Makefile.in	Tue Oct 29 17:28:05 1996
***************
*** 3,9 ****
  @SET_MAKE@
  CPPDEP=	@CPPDEP@
  
! SUBDIRS = errormail mailbox hold sm smtp
  
  all:
  	cd libta ; $(MAKE) $(MFLAGS)
--- 3,11 ----
  @SET_MAKE@
  CPPDEP=	@CPPDEP@
  
! # [Thomas Knott]
! # Neuer MTA "fuzzyalias"
! SUBDIRS = errormail fuzzyalias mailbox hold sm smtp
  
  all:
  	cd libta ; $(MAKE) $(MFLAGS)
diff -c -r orig/zmailer-2.99.39/transports/errormail/errormail.c zmailer-2.99.39/transports/errormail/errormail.c
*** orig/zmailer-2.99.39/transports/errormail/errormail.c	Fri Oct 25 21:55:50 1996
--- zmailer-2.99.39/transports/errormail/errormail.c	Wed Oct 30 14:43:09 1996
***************
*** 219,225 ****
  
  	rp = dp->recipients;
  
! 	fprintf(mfp, "to <%s>\n",rp->addr->link->user);
  
  	/* copy error message file itself */
  	if ((mailshare = getzenv("MAILSHARE")) == NULL)
--- 219,229 ----
  
  	rp = dp->recipients;
  
! 	/* [Thomas Knott]
! 	 * If "Errors-To"-Header exists , then use it to send the error mail
! 	 */
! 	fprintf(mfp, "to <%s>\n",
! 		(dp->erroraddr != NULL) ? dp->erroraddr : rp->addr->link->user);
  
  	/* copy error message file itself */
  	if ((mailshare = getzenv("MAILSHARE")) == NULL)
***************
*** 246,252 ****
  	  fputs("env-end\n",mfp);
  
  	  /* copy To: from error return address */
! 	  fprintf(mfp, "To: <%s>\n", rp->addr->link->user);
  
  	  while (fgets(buf,sizeof(buf)-1,efp) != NULL) {
  	    if (strncmp(buf,"HDR",3)==0) {
--- 250,263 ----
  	  fputs("env-end\n",mfp);
  
  	  /* copy To: from error return address */
! 	  /* [Thomas Knott]
! 	   * If "Errors-To"-Header exists then use it
! 	   * else use the "from"-Enveloppe address.
! 	   */
! 	  fprintf(mfp, "To: %s\n",
! 	  	(dp->erroraddr != NULL) ? dp->erroraddr :
! 		(*rp->addr->link->user != '\0') ? rp->addr->link->user :
! 			"postmaster");
  
  	  while (fgets(buf,sizeof(buf)-1,efp) != NULL) {
  	    if (strncmp(buf,"HDR",3)==0) {
diff -c -r orig/zmailer-2.99.39/transports/libta/ctlopen.c zmailer-2.99.39/transports/libta/ctlopen.c
*** orig/zmailer-2.99.39/transports/libta/ctlopen.c	Fri Oct 25 20:21:35 1996
--- zmailer-2.99.39/transports/libta/ctlopen.c	Wed Oct 30 14:44:11 1996
***************
*** 529,534 ****
--- 529,540 ----
  	  case _CF_VERBOSE:
  	    d.verbose = s+2;
  	    break;
+ 	  /* [Thomas Knott]
+ 	   * Remember "Errors-To"-Header in erroraddr if given
+ 	   */
+ 	  case _CF_ERRORADDR:
+ 	    d.erroraddr = s+2;
+ 	    break;
  	  default:		/* We don't use them all... */
  	    break;
  	  }
diff -c -r orig/zmailer-2.99.39/transports/libta/writeheaders.c zmailer-2.99.39/transports/libta/writeheaders.c
*** orig/zmailer-2.99.39/transports/libta/writeheaders.c	Wed Jul 31 08:10:11 1996
--- zmailer-2.99.39/transports/libta/writeheaders.c	Tue Oct 29 17:28:05 1996
***************
*** 37,42 ****
--- 37,46 ----
  
  	if (!msgheaders) return -1;
  
+ 	/* [Thomas Knott]
+ 	 * Error-Flag des Filedescriptors fp loeschen (HP-UX)
+ 	 */
+ 	clearerr(fp);
  	while (*msgheaders && !ferror(fp)) {
  		int linelen = strlen(*msgheaders);
  		if (fwrite(*msgheaders,1,linelen,fp) != linelen)
diff -c -r orig/zmailer-2.99.39/transports/mailbox/mailbox.c zmailer-2.99.39/transports/mailbox/mailbox.c
*** orig/zmailer-2.99.39/transports/mailbox/mailbox.c	Sat Oct 26 13:28:33 1996
--- zmailer-2.99.39/transports/mailbox/mailbox.c	Tue Oct 29 17:28:05 1996
***************
*** 167,172 ****
--- 167,178 ----
  #define MAILMODE        0600    /* prevent snoopers from looking at mail */
  #define	NONUIDSTR	"6963"	/* X:magic nonsense uid if nobody uid is bad */
  
+ /* [Thomas Knott]
+  * Formular fuer die Rueckmeldung bei "Return-Receipt-To" im Directory
+  * $MAILVAR/forms/
+  */
+ #define RETURN_RECEIPT_FORM	"return-receipt"
+ 
  /*
   * The following is stuck in for reference only.  You could add
   * alternate spool directories to the list (they are checked in
***************
*** 284,289 ****
--- 290,301 ----
  extern int writebuf __((FILE *fp, char *buf, int len, int *lastchp));
  extern int writemimeline __((FILE *fp, char *buf, int len, int *lastchp));
  
+ /* [Thomas Knott]
+  * Funktions-Prototypen fuer "Return-Receipt-To"
+  */
+ static void return_receipt __((struct ctldesc *dp, char *retrecptaddr));
+ static char *find_return_receipt_hdr __((struct rcpt *rp));
+ 
  extern int  qp_to_8bit   __((struct rcpt *rp));
  extern int  qptext_check __((struct rcpt *rp));
  
***************
*** 784,790 ****
  	FILE *fp;
  	int hasdir;
  	struct stat st, s2;
! 	char *file = NULL, *cp, *at, *plus;
  	int ismbox = 0, i;
  #if	defined(HAVE_SOCKET)
  	struct biffer *nbp = NULL;
--- 796,803 ----
  	FILE *fp;
  	int hasdir;
  	struct stat st, s2;
!     /* [Thomas Knott]: retrecptaddr fuer "Return-Receipt-To" */
! 	char *file = NULL, *cp, *at, *plus, *retrecptaddr;
  	int ismbox = 0, i;
  #if	defined(HAVE_SOCKET)
  	struct biffer *nbp = NULL;
***************
*** 1247,1252 ****
--- 1260,1272 ----
  	  if (nbp != NULL) /* putmail() has produced a DIAGNOSTIC */
  	    nbp->offset = -1;
  #endif	/* BIFF || RBIFF */
+ 
+ 	/* [Thomas Knott]
+ 	 * "Return-Receipt-To"-Header suchen und - wenn vorhanden - auswerten.
+ 	 */
+ 	if ((retrecptaddr = find_return_receipt_hdr(rp)) != NULL)
+ 		return_receipt(dp, retrecptaddr);
+ 
  	return;
  }
  
***************
*** 1313,1320 ****
  	if (*fromuser == 0 ||
  	    strcmp(rp->addr->link->channel, "error") == 0)
  	  fromuser = "postmaster";
! 	if (fprintf(fp, "%s%s  %s",
! 		    FROM_,fromuser,timestring) == EOF
  	    || writeheaders(rp,fp,"\n",convert_qp,0) < 0) {
  	  notaryreport(rp->addr->link->user, "failed",
  		       "4.2.2 (Write to user's mailbox failed)",
--- 1333,1346 ----
  	if (*fromuser == 0 ||
  	    strcmp(rp->addr->link->channel, "error") == 0)
  	  fromuser = "postmaster";
! 	/* [Thomas Knott]
! 	 * Unter HP-UX liefert "fprintf" im Fehlerfall nicht EOF sondern
! 	 * einen negativen Wert => Ersetzen von "fprintf" durch "fwrite".
! 	 */
! 	if (fwrite(FROM_, 1, strlen(FROM_), fp) < strlen(FROM_)
! 	    || fwrite(fromuser, 1, strlen(fromuser), fp) < strlen(fromuser)
! 	    || fwrite(" ", 1, 1, fp) < 1
! 	    || fwrite(timestring, 1, strlen(timestring), fp) < strlen(timestring)
  	    || writeheaders(rp,fp,"\n",convert_qp,0) < 0) {
  	  notaryreport(rp->addr->link->user, "failed",
  		       "4.2.2 (Write to user's mailbox failed)",
***************
*** 1333,1339 ****
  	}
  	lastch = appendlet(dp, rp, fp, file, is_mime);
  
! 	if (lastch == EOF || ferror(fp) || fflush(fp) == EOF) {
        write_failure:
  	  notaryreport(NULL,NULL,NULL,NULL);
  	  DIAGNOSTIC3(rp, EX_IOERR,
--- 1359,1368 ----
  	}
  	lastch = appendlet(dp, rp, fp, file, is_mime);
  
! 	/* [Thomas Knott]
! 	 * Unter HP-UX liefert ein "fflush" auf eine Pipe einen Fehler!
! 	 */
! 	if (lastch == EOF || ferror(fp)) {
        write_failure:
  	  notaryreport(NULL,NULL,NULL,NULL);
  	  DIAGNOSTIC3(rp, EX_IOERR,
***************
*** 1349,1354 ****
--- 1378,1384 ----
  	  fp = NULL;
  	  goto time_reset;
  	}
+ 	fflush(fp);
  
  	/*
  	 * Determine how many newlines to append to the previous text.
***************
*** 1368,1376 ****
  	if (len == 1 || len == 2) {
  	  --len;
  	  len = (buf[len]!='\n') + (len == 1 ? buf[0]!='\n' : 1);
! 	  if (len > 0 && (fwrite("\n\n", 1, len, fp) != len
! 			  || fflush(fp) == EOF)) {
! 
  	    notaryreport(NULL,NULL,NULL,NULL);
  	    DIAGNOSTIC(rp, EX_IOERR,
  		       "cleansing of \"%s\" failed", file);
--- 1398,1407 ----
  	if (len == 1 || len == 2) {
  	  --len;
  	  len = (buf[len]!='\n') + (len == 1 ? buf[0]!='\n' : 1);
! 	  /* [Thomas Knott]
! 	   * Unter HP-UX liefert ein "fflush" auf eine Pipe einen Fehler!
! 	   */
! 	  if (len > 0 && (fwrite("\n\n", 1, len, fp) != len)) {
  	    notaryreport(NULL,NULL,NULL,NULL);
  	    DIAGNOSTIC(rp, EX_IOERR,
  		       "cleansing of \"%s\" failed", file);
***************
*** 1384,1389 ****
--- 1415,1421 ----
  	    fp = NULL;
  	    goto time_reset;
  	  }
+ 	  fflush(fp);
  	}
  
  	/* End of the file, and MMDF-style ? */
***************
*** 2361,2364 ****
--- 2393,2535 ----
  	}
  	if (!is_mime) cte = 0;
  	return cte;
+ }
+ 
+ static char *
+ find_return_receipt_hdr (rp)
+     struct rcpt *rp;
+ {
+     char **ptr, *hdr;
+ 
+     for (ptr = *(rp->newmsgheader); *ptr != NULL; ptr++) {
+         if (strncasecmp(*ptr, "Return-Receipt-To:", 18) == 0)
+             break;
+     }
+ 
+     if (*ptr == NULL)
+         return (NULL);
+ 
+     hdr = *ptr + 18;
+     while (*hdr != '\0' && isspace(*hdr))
+         hdr++;
+ 
+     return(hdr);
+ }
+ 
+ static void
+ return_receipt (dp, retrecptaddr)
+ 	struct ctldesc *dp;
+ 	char *retrecptaddr;
+ {
+ 	char buf[BUFSIZ];
+ 	char **cpp, *mailshare, *mfpath;
+ 	FILE *mfp, *efp;
+ 	struct rcpt *rp;
+ 	int n;
+ 	char lastchar;
+ 	char *boundarystr = buildboundary("return-receipt");
+ 
+ 	char *dfltform[] = {
+ 		"From: The Post Office <postmaster>",
+ 		"Subject: Returned mail: Return receipt",
+ 		"MIME-Version: 1.0",
+ 		"Content-Type: multipart/report; report-type=delivery-status;",
+ 		"",
+ 		"Your mail message has been delivered properly to the following recipients:",
+ 		NULL
+ 	};
+ 
+ 	if ((mfp = mail_open(MSG_RFC822)) == NULL) {
+ 	  for (rp = dp->recipients; rp != NULL; rp = rp->next)
+ 	    DIAGNOSTIC(rp, EX_TEMPFAIL, "mail_open failure", 0);
+ 	  warning("Cannot open mail file!");
+ 	  return;
+ 	}
+ 	fprintf(mfp, "channel error\n");
+ 
+ 	rp = dp->recipients;
+ 
+ 	/* copy To: from return-receipt address */
+ 	fprintf(mfp, "To: %s\n", retrecptaddr);
+ 
+ 	/* copy error message file itself */
+ 	if ((mailshare = getzenv("MAILSHARE")) == NULL)
+ 	  mailshare = MAILSHARE;
+ 
+ 	mfpath = emalloc(3+strlen(mailshare)+strlen(FORMSDIR)
+ 				 +strlen(RETURN_RECEIPT_FORM));
+ 	sprintf(mfpath, "%s/%s/%s", mailshare, FORMSDIR, RETURN_RECEIPT_FORM);
+ 
+ 	if ((efp = fopen(mfpath, "r")) != NULL) {
+ 	  int inhdr = 1;
+ 	  buf[sizeof(buf)-1] = 0;
+ 	  while (fgets(buf,sizeof(buf)-1,efp) != NULL) {
+ 	    if (strncmp(buf,"HDR",3)==0) {
+ 	      fputs(buf+4,mfp);
+ 	    } else if (strncmp(buf,"SUB",3)==0) {
+ 	      fputs(buf+4,mfp);
+ 	    } else {
+ 	      if (inhdr) {
+ 		inhdr = 0;
+ 		fprintf(mfp,"MIME-Version: 1.0\n");
+ 		fprintf(mfp,"Content-Type: multipart/report; report-type=delivery-status;\n");
+ 		fprintf(mfp,"\tboundary=\"%s\"\n\n\n",boundarystr);
+ 		fprintf(mfp, "--%s\n", boundarystr);
+ 		fprintf(mfp, "Content-Type: text/plain\n");
+ 	      }
+ 	      fputs(buf,mfp);
+ 	    }
+ 	  } /* ... while() ends.. */
+ 	  fclose(efp);
+ 	} else {
+ 	  for (cpp = &dfltform[0]; *cpp != NULL; ++cpp)
+ 	    if (*cpp == 0) {
+ 	      fprintf(mfp, "\tboundary=\"%s\"\n\n\n",boundarystr);
+ 	      fprintf(mfp, "--%s\n", boundarystr);
+ 	      fprintf(mfp, "Content-Type: text/plain\n");
+ 	    } else
+ 	      fprintf(mfp, "%s\n", *cpp);
+ 	}
+ 	/* print out errors in standard format */
+ 	for (rp = dp->recipients; rp != NULL; rp = rp->next) {
+ 	  fprintf(mfp, "\t%s\n", rp->addr->user);
+ 	}
+ 	fprintf(mfp, "\n--%s\n", boundarystr);
+ 	fprintf(mfp, "Content-Type: message/delivery-status\n\n");
+ 
+ 	/* XX: print out errors in IETF-NOTARY format as well! */
+ 	fprintf(mfp, "Original-MTS-Type: INET\n");
+ 	if (dp->envid != NULL)
+ 	  fprintf(mfp, "Original-Envelope-Id: %s\n",dp->envid);
+ 	fprintf(mfp, "Final-MTS-Type: INET\n");
+ 	fprintf(mfp, "Final-MTA: %s\n\n", mydomain() );
+ 
+ 	for (rp = dp->recipients; rp != NULL; rp = rp->next) {
+ 	  fprintf(mfp, "Rcpt: %s\n", rp->addr->user);
+ 	  fprintf(mfp, "Action: delivered\n");
+ 	  fprintf(mfp, "Status: 250 (%s)\n", rp->addr->host );
+ 	  if (rp->orcpt != NULL)
+ 	    fprintf(mfp, "Original-Rcpt: %s\n",rp->orcpt);
+ 	  fprintf(mfp, "\n");
+ 	}
+ 
+ 	fprintf(mfp, "--%s\n", boundarystr);
+ 	fprintf(mfp, "Content-Type: message/rfc822\n\n");
+ 
+ 	/* XX: Skip over the delivery envelope lines! */
+ 
+ 	rp = dp->recipients;
+ 	/* write the (new) headers with local "Received:"-line.. */
+ 	writeheaders(rp,mfp,"\n",0,0);
+ 
+ 	fprintf(mfp, "--%s--\n", boundarystr);
+ 	if (ferror(mfp)) {
+ 	  mail_abort(mfp);
+ 	  n = EX_IOERR;
+ 	} else if (mail_close(mfp) == EOF)
+ 	  n = EX_IOERR;
+ 	else
+ 	  n = EX_OK;
+ 	for (rp = dp->recipients; rp != NULL; rp = rp->next)
+ 	  DIAGNOSTIC(rp, n, (char *)NULL, 0);
  }
diff -c -r orig/zmailer-2.99.39/utils/makendbm/makendbm.c zmailer-2.99.39/utils/makendbm/makendbm.c
*** orig/zmailer-2.99.39/utils/makendbm/makendbm.c	Thu Sep 12 19:49:12 1996
--- zmailer-2.99.39/utils/makendbm/makendbm.c	Tue Oct 29 18:21:26 1996
***************
*** 24,30 ****
  #define PROG "makendbm"
  
  #include <errno.h>	/* This (usually) defines the following 3.. */
!      /* extern int errno;
  	extern char *sys_errlist[];
  	extern int sys_nerr; */
  
--- 24,30 ----
  #define PROG "makendbm"
  
  #include <errno.h>	/* This (usually) defines the following 3.. */
!       /* extern int errno;
  	extern char *sys_errlist[];
  	extern int sys_nerr; */
  

fuzzy channel

# Expansion of the local-part of a locally delivered address is done here.
#
# We check (in order):
#
#	":include:" or "|" or "/" prefix
#	aliases entry (mapping to a list of addresses)
#	$HOME/.forward file entry (mapping to a list of addresses)
#	$MAILVAR/lists directory entry (mapping to a list of addresses)
#	-request or -owner suffix (mapping to owner of mailing list file)
#   -group (mapping to a group of people specified in file /etc/group)
#
# If we get all the way through, we give up.

provide aliases

# Define the YP mail.aliases database
if [ -x /usr/bin/ypwhich ] && /usr/bin/ypwhich>/dev/null 2>&1; then
	relation -lt yp,mail.aliases ypaliases
else
	ypaliases () { return 1 }
fi

# Define the netaliases database (xaliases)
if [ -f $MAILSHARE/db/netaliases.dir ]; then
	case "$DBTYPE" in
	ndbm|dbm)
		relation -lmt $DBTYPE -f $MAILSHARE/db/netaliases xaliases ;;
	*)
		xaliases () { return 1 } ;;
	esac
else
	xaliases () { return 1 }
fi

# Define the Sendmail aliases database
if [ -f $MAILVAR/db/aliases ]; then
	case "$DBTYPE" in
	ndbm|dbm)
		[ -f $MAILSHARE/db/aliases.dir ] || $MAILBIN/zmailer newaliases
		relation -lmt $DBTYPE -f $MAILSHARE/db/aliases aliases
		;;
	*)
		[ -f $MAILVAR/db/aliases.idx ] || $MAILBIN/zmailer newaliases
		relation -limt ordered,$MAILVAR/db/aliases.dat \
			-f $MAILVAR/db/aliases.idx aliases
		;;
	esac
else
	aliases () { return 1 }
fi

# define a function to look up aliases in the following order:
#   1. netaliases
#   2. Sendmail aliases
#   3. YP aliases
lookupaliases (user) {
	local a

	a=$(xaliases "$user") ||
		a=$(aliases "$user") ||
		a=$(ypaliases "$user") ||
		return 1

	echo "$a"
	return 0
}

# if the file $MAILVAR/db/filter exists, it contains a list of programms
# which are allowed to pipe to in a user's .forward file
if [ -f $MAILVAR/db/filter ]; then
	relation -mt unordered -f $MAILVAR/db/filter filterdb
else
	filterdb () { return 1 }
fi

# If the 'm' option was NOT specified on the aliases relation,
# presumably whatever creates new aliases will poke us (using SIGURG).
trap "db flush aliases ; log flushed aliases" 16


# Usage: routeuser (channel host user attributes)
#
# This is where local alias expansion is controlled.
routeuser (quad) {
	local attr user lcuser host priv a mxh key

	attr=$(attributes $quad)
	user="$(user $quad)"
    lcuser="$(recase -l "$user")"
	host="$(host $quad)"
    priv=$(get $attr privilege)

	case "$(get $attr type)" in
	sender)
        return (($quad))
        ;;
    expandsender)
        a=$(homedirectory "$user")/.forward && [ -f $a ] &&
        return (($quad))
        ;;
    esac

	# get rid of the attribute tag for alias loop prevention
	a=$quad
	mxh=$(setf $(last $a) ())
	key="$(elements $a)"

	case "$(channel $quad)" in
	local)	;;	# this is the normal case, below
	*)	return (($quad))
		;;
	esac

    $(expansions "$key"-file) ||
    ssift "$user" in
    :include:(.*)
        db add expansions "$key"-file ""
        [ -f "\1" ] && priv=$(getpriv $priv "\1" include) &&
        defer='' &&
        return $(listaddresses -e root -c 'file expansion' < "\1" |
             maprrouter $(newattribute $attr privilege $priv) "\1" fileincl "")
            ;;
    [|/].*	return (($quad)) ;;
    tfiss

    # alias expansion
    $(expansions "$key"-alias) ||
    a=$(lookupaliases "$user") &&
        db add expansions "$key"-alias "" &&
        priv=$(filepriv $MAILVAR/db/aliases $(db owner aliases)) &&
        return $(echo $a | listaddresses -e root -c 'alias expansion' |
              maprrouter $(newattribute $attr privilege $priv) "$user" "$user" "")

    # expand the  user's .forward file
    $(expansions "$key"-user) ||
    [ "$(recase -l "$DOT_FORWARD_FILE")" != "ignore" ] &&
        a="$(homedirectory "$user")/.forward" && [ -f "$a" ] &&
        db add expansions "$key"-user "" &&
        priv=$(getpriv $priv "$a" .forward) &&
        return $(listaddresses -e "$user" -c "$a file expansion" < "$a" |
             maprrouter $(newattribute $attr privilege $priv) "$a" "$user" "$DOT_FORWARD_FILE")

    # check in the mailing list directory
    $(expansions "$key"-list) ||
    a="$MAILVAR/lists/$lcuser" &&
    [ -f "$a" ] && db add expansions "$key"-list "" &&
    priv=$(getpriv $priv "$a" maillist) &&
    return $(listaddresses -E "$user-owner" -e "$lcuser"-owner -c "$a file expansion" < "$a" |
         maprrouter $(newattribute $attr privilege $priv sender "$lcuser"-owner) "$a" "$user" "")

    # local user with no alias and no .forward file

    # turn *-owner and *-request into the owner of a mailing list file
    # turn *-group into members listed in /etc/group
    case "$lcuser" in
    *-owner)
        a="$MAILVAR/lists/$(basename "$lcuser" -owner)" &&
            [ -f "$a" ] &&
            return $(rrouter "$(uid2login $(filepriv "$a"))" "$user" $attr)
        ;;
    *-request)
        a="$MAILVAR/lists/$(basename "$lcuser" -request)" &&
            [ -f "$a" ] &&
            return $(rrouter "$(uid2login $(filepriv "$a"))" "$user" $attr)
        ;;
    *-group)
        a="$(groupmembers $(basename "$lcuser" -group))" &&
            db add expansions "$key" group &&
            return $(echo $a |
                listaddresses -e postmaster -c "$lcuser expansion" |
                maprrouter $(newattribute $attr sender postmaster) "$lcuser" "$user" "")
        ;;
    esac

	case "$user" in
	uid#*)	return $(rrouter postmaster "$user" $attr)
		;;
	esac

	# give users with mixed case letters a chance...
	if [ x$(login2uid "$user") != x$NOBODY -o x$(login2uid "$lcuser") != x$NOBODY ]
	then
		return (($quad))
	fi

	[ "$FUZZYMATCH" = "yes" ] && return (((fuzzy nosuchuser "$user" $attr)))

	return (((error nosuchuser "$user" $attr)))
}

# Usage: getpriv <present privilege> <filename> <filename type>
#
# Determine the privileges associated with addresses coming from the filename.
# The type value is one of .forward, maillist, or include.  Setting
# private='' ensures that noone can access (modulo a small window) information
# through the mailer (e.g., by sending mail to addresses taken from a
# protected file and waiting excitedly for the informative bounce messages)
# that they couldn't access otherwise.  If private='.forward maillist' then
# people stop complainig about the former behaviour...
getpriv (priv, file, type) {
	for ptype in $private
	do
		if [ $type = $ptype ]; then
			filepriv "$file"
			return $?
		fi
	done
	runas $priv filepriv "$file"
}

# Usage: newattribute <oldattribute> <key1> <value1> [ <key2> <value2> ] ...
#
# Returns a new attribute list symbol with the <keyN> <valueN>
# attributes added to the contents of the <oldattribute> list.
newattribute (oldattribute) {
	local a null value
	a=$(gensym)
	eval $a=\$$oldattribute
	while [ "$#" != 0 ];
	do
		value=$(get $a "$1")
		if [ x"$value" != x"$2" ]; then
			null=$(setf $(get $a "$1") "$2")
		fi
		shift ; shift
	done
	echo $a
}

# Usage: maprrouter <newattributes> <what-is-being-expanded>
#
# This function applies the rrouter function to each address read from
# stdin, passing the <newattributes> parameter.  In case of error, the
# localpart parameter is used as appropriate descriptive text.  The
# return value is the concatenation of the return values of the rrouter
# invocations.
#
# If fwdchk = "yes" then do some security checks for a user's .forward file:
#	- only allow mail to programs listed in $MAILVAR/db/filter
#	- allow mail forwarding to max. one nonlocal user
# Returns user's local mailbox if security check fails.
maprrouter (attribute, localpart, origaddr, fwdchk) {
	local shh al fwdnonlocal tmp a

	al=()
	fwdnonlocal=''
	while read address
	do
		case "$address" in
		'')	case $#al in
			0)	al=(((error expansion "$localpart"))) ;;
			*)	shh=(((error expansion "$localpart")))
				shh=$(setf $(cdr $(last $al)) $shh)
				;;
			esac
			continue
			;;
		esac

		defer=''
		shh=$(rrouter "$address" "$origaddr" $attribute)
		[ "$defer" ] &&
			shh=(((hold "$defer" "$address" $attribute)))
		defer=''

		if [ "$(recase -l "$fwdchk")" = "restricted" ]; then
			tmp=$(car $(car $shh))
			case "$(channel $tmp)" in
			local)
				ssift "$(user $tmp)" in
				\|(.+)
					a="\1"
					set $a
					if $(filterdb "$1"); then
						: mail to program allowed
					else
						echo "$origaddr: Mail to program $1 not allowed" >> $LOGDIR/forwards
						return (((local - "$origaddr" "$attribute")))
					fi
					;;
				tfiss
				;;
			smtp)
				if [ "$fwdnonlocal" ]; then
					echo "$origaddr: Too many forwards to nonlocal users" >> $LOGDIR/forwards
					return (((local - "$origaddr" "$attribute")))
				fi

				fwdnonlocal=true
				;;
			esac
		fi

		case $#al in
		0)	al=$shh
			;;
		*)	shh=$(setf $(cdr $(last $al)) $shh)
			;;
		esac
	done

	return $al
}