diff -ruN sendmail-8.11.0.orig/sendmail/deliver.c sendmail-8.11.0/sendmail/deliver.c --- sendmail-8.11.0.orig/sendmail/deliver.c Wed Jul 19 22:21:35 2000 +++ sendmail-8.11.0/sendmail/deliver.c Fri Jul 21 13:31:48 2000 @@ -1454,6 +1454,39 @@ *pvp++ = NULL; /* + ** This is the place add an Envelope-To header, if the + ** option was set and we're delivering locally. + **/ + if (EnvToHeader) { + + HDR *h; + + /* Clear header if already present */ + for(h = e->e_header; h != NULL; h = h->h_link) { + if (strcasecmp(h->h_field, EnvToHeader) != 0) + continue; + clrbitmap(h->h_mflags); + h->h_flags |= H_ACHECK; + } + } + if (EnvToHeader && bitnset(M_LOCALMAILER, m->m_flags) && + !bitnset(M_MUSER, m->m_flags)) { + + extern void getenvto __P((ADDRESS *, char ***, int)); + extern void makeheader __P((char *, char **, char **)); + char **envto; + char *s = NULL; + + /* Now construct new header */ + getenvto(tochain, &envto, 0); + makeheader(EnvToHeader, envto, &s); + + addheader(EnvToHeader, s ? s : "UNKNOWN", 0, &e->e_header); + if (s) free(s); + free(envto); + } + + /* ** Call the mailer. ** The argument vector gets built, pipes ** are created as necessary, and we fork & exec as diff -ruN sendmail-8.11.0.orig/sendmail/headers.c sendmail-8.11.0/sendmail/headers.c --- sendmail-8.11.0.orig/sendmail/headers.c Wed Jul 19 20:08:31 2000 +++ sendmail-8.11.0/sendmail/headers.c Fri Jul 21 13:05:18 2000 @@ -1874,3 +1874,68 @@ } return modified; } + + /* +** MAKEHEADER -- create a multiline header +** +** Parameters: +** h -- initial headername +** p -- array of pointers to addresses +** s -- pointer to put new data in +** +** Side effects: +** removes <> from addresses +** +** Returns: +** void +*/ +void +makeheader(h, p, s) + char *h; + char **p; + char **s; +{ + char *a; + int len, alen, slen; + int sz; + int donl; + + *s = NULL; + if (*p == NULL) return; + + len = strlen(h) + 2; + + while((a = *p++) != NULL) { + + alen = strlen(a); + if (*a == '<') { + a++; + alen -= 2; + } + + slen = *s ? strlen(*s) : 0; + sz = slen + alen + 1 + (slen ? 1 : 0); + + donl = 0; + if (len + alen > 75 && slen > 0) { + donl = 1; + sz += 2; + } + *s = realloc(*s, sz); + if (*s == NULL) { + syserr("!Out of memory!!"); + /* exit(EX_UNAVAILABLE); */ + } + if (slen == 0) + (*s)[0] = 0; + else + strcat(*s, ","); + if (donl) { + strcat(*s, "\n\t"); + len = 8; + } + strncat(*s, a, alen); + (*s)[sz - 1] = 0; + len += alen + 1; + } +} diff -ruN sendmail-8.11.0.orig/sendmail/queue.c sendmail-8.11.0/sendmail/queue.c --- sendmail-8.11.0.orig/sendmail/queue.c Fri Jul 14 07:55:51 2000 +++ sendmail-8.11.0/sendmail/queue.c Fri Jul 21 13:34:26 2000 @@ -102,6 +102,9 @@ MCI mcibuf; char tf[MAXPATHLEN]; char buf[MAXLINE]; + char **addr_ptr, **ptr; + extern void getenvto __P((ADDRESS *, char ***, int)); + /* ** Create control file. @@ -370,6 +373,11 @@ continue; printctladdr(q, tfp); + getenvto(q, &addr_ptr, 0); + ptr = addr_ptr; + while (*ptr) + fprintf(tfp, "Y%s\n", *ptr++); + free(addr_ptr); if (q->q_orcpt != NULL) fprintf(tfp, "Q%s\n", denlstring(q->q_orcpt, TRUE, FALSE)); @@ -1823,6 +1831,8 @@ { register FILE *qfp; ADDRESS *ctladdr; + ADDRESS *addr; + ADDRESS *envto = NULL; struct stat st; char *bp; int qfver = 0; @@ -1982,6 +1992,14 @@ orcpt = newstr(&bp[1]); break; + case 'Y': /* original envelope-to */ + addr = setctluser(&bp[1], qfver); + addr->q_dups = envto; + addr->q_flags |= (QENVTO|QS_DONTSEND); + addr->q_flags &= ~(QPRIMARY); + envto = addr; + break; + case 'R': /* specify recipient */ p = bp; qflags = 0; @@ -2019,14 +2037,20 @@ q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e); if (q != NULL) { - q->q_alias = ctladdr; + if (envto) { + q->q_alias = envto; + envto->q_alias = ctladdr; + } else + q->q_alias = ctladdr; if (qfver >= 1) q->q_flags &= ~Q_PINGFLAGS; q->q_flags |= qflags; q->q_orcpt = orcpt; (void) recipient(q, &e->e_sendqueue, 0, e); + if (envto) q->q_flags &= ~(QENVTO); } orcpt = NULL; + envto = NULL; break; case 'E': /* specify error recipient */ diff -ruN sendmail-8.11.0.orig/sendmail/readcf.c sendmail-8.11.0/sendmail/readcf.c --- sendmail-8.11.0.orig/sendmail/readcf.c Wed Jul 12 18:44:09 2000 +++ sendmail-8.11.0/sendmail/readcf.c Fri Jul 21 13:13:08 2000 @@ -1709,6 +1709,10 @@ # endif /* _FFR_TLS_1 */ # define O_RANDFILE 0xc1 { "RandFile", O_RANDFILE, OI_NONE }, +# define O_ETRNPROG 0xc2 + { "EtrnProg", O_ETRNPROG, OI_NONE }, +# define O_ENVTOHEADER 0xc3 + { "EnvelopeToHeader", O_ENVTOHEADER, OI_NONE }, { NULL, '\0', OI_NONE } }; @@ -2943,6 +2947,16 @@ QueueFileMode = atooct(val) & 0777; break; #endif /* _FFR_QUEUE_FILE_MODE */ + + case O_ETRNPROG: + if (EtrnProg) free(EtrnProg); + EtrnProg = newstr(val); + break; + + case O_ENVTOHEADER: + if (EnvToHeader) free(EnvToHeader); + EnvToHeader = newstr(val); + break; default: if (tTd(37, 1)) diff -ruN sendmail-8.11.0.orig/sendmail/recipient.c sendmail-8.11.0/sendmail/recipient.c --- sendmail-8.11.0.orig/sendmail/recipient.c Thu Jun 29 03:48:51 2000 +++ sendmail-8.11.0/sendmail/recipient.c Fri Jul 21 13:16:46 2000 @@ -21,7 +21,82 @@ static void includetimeout __P((void)); static ADDRESS *self_reference __P((ADDRESS *)); -/* + + /* +** GETENVTO -- Walk up the q_alias tree to find the envelope recipient. +** +** Parameters: +** Address and a char ***pointer to envto data. +** The char *** pointer is confusing. Example usage: +** +** char **addr_ptrs; +** +** getenvto(address, &addr_ptrs, 0); +** +** Returns: +** The char ***envto pointer contains the recipients. +** +** Side Effects: +** None other. +*/ + +void +getenvto(a, envtop, level) + ADDRESS *a; + char ***envtop; + int level; +{ + ADDRESS *q; + char **envto; + char **tmp; + int sz; + + /* + ** Initialize envtop if needed. + **/ + if (level == 0) { + *envtop = (char **)xalloc(sizeof(char **)); + **envtop = NULL; + } + envto = *envtop; + + if (level > 10) return; /* Should never happen */ + + for (q = a; q; q = q->q_alias) { + /* + ** Perhaps we need to recurse if we + ** have a q_dups pointer. + **/ + if (q->q_dups) + getenvto (q->q_dups, &envto, level + 1); + + /* + ** If this address is QENVTO flagged, add + ** it to the envto string. + */ + if (q->q_flags & QENVTO) { + + /* Check if already present */ + for(tmp = envto; *tmp; tmp++) + if (strcmp(*tmp, q->q_paddr) == 0) + break; + if (*tmp) continue; + + /* Extend the array. */ + sz = tmp - envto; + envto = realloc(envto, (sz + 2) * sizeof(char **)); + if (envto == NULL) { + syserr("!Out of memory!!"); + /* exit(EX_UNAVAILABLE); */ + } + tmp = envto + sz; + *tmp++ = q->q_paddr; + *tmp = NULL; + } + } + *envtop = envto; +} + /* ** SENDTOLIST -- Designate a send list. ** ** The parameter is a comma-separated list of people to send to. @@ -341,8 +416,11 @@ e->e_to = a->q_paddr; m = a->q_mailer; errno = 0; - if (aliaslevel == 0) + if (aliaslevel == 0) { a->q_flags |= QPRIMARY; + if (!initialdontsend) + a->q_flags |= QENVTO; + } if (tTd(26, 1)) { dprintf("\nrecipient (%d): ", aliaslevel); @@ -525,6 +603,14 @@ q->q_state = a->q_state; q->q_flags |= a->q_flags; } + /* + ** If the address gets merged with another + ** address because they are the same, still + ** keep a pointer to it to track it later. + */ + a->q_dups = q->q_dups; + q->q_dups = a; + a = q; goto done; } diff -ruN sendmail-8.11.0.orig/sendmail/sendmail.h sendmail-8.11.0/sendmail/sendmail.h --- sendmail-8.11.0.orig/sendmail/sendmail.h Tue Jul 18 04:24:47 2000 +++ sendmail-8.11.0/sendmail/sendmail.h Fri Jul 21 13:19:58 2000 @@ -187,6 +187,7 @@ struct address *q_alias; /* address this results from */ char *q_owner; /* owner of q_alias */ struct address *q_tchain; /* temporary use chain */ + struct address *q_dups; /* Pointer to duplicates. */ char *q_orcpt; /* ORCPT parameter from RCPT TO: line */ char *q_status; /* status code for DSNs */ char *q_rstatus; /* remote status message for DSNs */ @@ -214,6 +215,7 @@ #define QDELIVERED 0x00001000 /* DSN: successful final delivery */ #define QDELAYED 0x00002000 /* DSN: message delayed */ #define QALIAS 0x00004000 /* expanded alias */ +#define QENVTO 0x00100000 /* Original envelope recipient */ #define QTHISPASS 0x40000000 /* temp: address set this pass */ #define QRCPTOK 0x80000000 /* recipient() processed address */ @@ -1805,6 +1807,9 @@ EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */ EXTERN char **ExternalEnviron; /* input environment */ /* saved user environment */ +EXTERN char *EtrnProg; /* program to be run on ETRN */ +EXTERN char *EnvToHeader; /* name of Envelope-To header */ + EXTERN BITMAP256 DontBlameSendmail; /* DontBlameSendmail bits */ #if SFIO EXTERN Sfio_t *InChannel; /* input connection */ diff -ruN sendmail-8.11.0.orig/sendmail/srvrsmtp.c sendmail-8.11.0/sendmail/srvrsmtp.c --- sendmail-8.11.0.orig/sendmail/srvrsmtp.c Wed Jul 19 22:21:35 2000 +++ sendmail-8.11.0/sendmail/srvrsmtp.c Fri Jul 21 13:21:34 2000 @@ -162,6 +162,37 @@ # define RIC_INPARENT 1 /* still in parent process */ # define RIC_TEMPFAIL 2 /* temporary failure occurred */ +static int +doetrnprog(e, node) + ENVELOPE *e; + char *node; +{ + pid_t pid; + int i, st; + char *clientaddr; + + clientaddr = macvalue(macid("{client_addr}", NULL), e); + + (void) blocksignal(SIGCHLD); + + if ((pid = dofork()) < 0) { + (void) releasesignal(SIGCHLD); + return -1; + } + if (pid == 0) { + if ((pid = dofork()) < 0) + exit(1); + if (pid > 0) exit(0); + for(i = 255; i >= 0; i--) + close(i); + execl(EtrnProg, EtrnProg, clientaddr, node, NULL); + exit(1); + } + st = waitfor(pid); + (void) releasesignal(SIGCHLD); + return WEXITSTATUS(st); +} + void smtp(nullserver, d_flags, e) char *volatile nullserver; @@ -2131,6 +2162,15 @@ "%.100s: ETRN %s", CurSmtpClient, shortenstring(p, MAXSHORTSTR)); + + if (EtrnProg != NULL) { + if (doetrnprog(e, p) != 0) { + message("451 ETRN cannot fork"); + break; + } + message("250 Queuing for node %s started", p); + break; + } id = p; if (*id == '@')