diff -ruN --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/deliver.c sendmail-8.12.0.Beta10/sendmail/deliver.c --- sendmail-8.12.0.Beta10.orig/sendmail/deliver.c Wed May 23 04:14:36 2001 +++ sendmail-8.12.0.Beta10/sendmail/deliver.c Fri Jun 15 02:01:28 2001 @@ -1672,6 +1672,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 --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/headers.c sendmail-8.12.0.Beta10/sendmail/headers.c --- sendmail-8.12.0.Beta10.orig/sendmail/headers.c Thu May 10 03:16:10 2001 +++ sendmail-8.12.0.Beta10/sendmail/headers.c Fri Jun 15 02:01:28 2001 @@ -1898,3 +1898,68 @@ } return retlen; } + + /* +** 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 --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/queue.c sendmail-8.12.0.Beta10/sendmail/queue.c --- sendmail-8.12.0.Beta10.orig/sendmail/queue.c Fri Jun 15 01:57:39 2001 +++ sendmail-8.12.0.Beta10/sendmail/queue.c Fri Jun 15 02:03:58 2001 @@ -303,6 +303,9 @@ char tf[MAXPATHLEN]; char dfname[MAXPATHLEN]; char buf[MAXLINE]; + char **addr_ptr, **ptr; + extern void getenvto __P((ADDRESS *, char ***, int)); + /* ** Create control file. @@ -622,6 +625,11 @@ false)); 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) (void) sm_io_fprintf(tfp, SM_TIME_DEFAULT, "Q%s\n", denlstring(q->q_orcpt, true, @@ -3426,6 +3434,8 @@ { register SM_FILE_T *qfp; ADDRESS *ctladdr; + ADDRESS *addr; + ADDRESS *envto = NULL; struct stat st, stf; char *bp; int qfver = 0; @@ -3837,6 +3847,14 @@ orcpt = sm_rpool_strdup_x(e->e_rpool, &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; @@ -3883,14 +3901,20 @@ true); 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 'S': /* sender */ diff -ruN --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/readcf.c sendmail-8.12.0.Beta10/sendmail/readcf.c --- sendmail-8.12.0.Beta10.orig/sendmail/readcf.c Thu May 24 05:28:32 2001 +++ sendmail-8.12.0.Beta10/sendmail/readcf.c Fri Jun 15 02:07:50 2001 @@ -2037,6 +2037,10 @@ # define O_SOFTBOUNCE 0xd0 { "SoftBounce", O_SOFTBOUNCE, OI_NONE }, #endif /* _FFR_SOFT_BOUNCE */ +#define O_ETRNPROG 0xd1 + { "EtrnProg", O_ETRNPROG, OI_NONE }, +#define O_ENVTOHEADER 0xd2 + { "EnvelopeToHeader", O_ENVTOHEADER, OI_NONE }, { NULL, '\0', OI_NONE } }; @@ -3428,6 +3432,16 @@ SoftBounce = atobool(val); break; #endif /* _FFR_SOFT_BOUNCE */ + + 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 --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/recipient.c sendmail-8.12.0.Beta10/sendmail/recipient.c --- sendmail-8.12.0.Beta10.orig/sendmail/recipient.c Tue May 15 02:02:36 2001 +++ sendmail-8.12.0.Beta10/sendmail/recipient.c Fri Jun 15 02:11:41 2001 @@ -135,7 +135,82 @@ return ret; } -/* + + /* +** 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. @@ -468,8 +543,11 @@ e->e_to = new->q_paddr; m = new->q_mailer; errno = 0; - if (aliaslevel == 0) + if (aliaslevel == 0) { new->q_flags |= QPRIMARY; + if (!initialdontsend) + a->q_flags |= QENVTO; + } if (tTd(26, 1)) { sm_dprintf("\nrecipient (%d): ", aliaslevel); @@ -693,6 +771,14 @@ q->q_state = new->q_state; q->q_flags |= new->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. + */ + new->q_dups = q->q_dups; + q->q_dups = new; + new = q; goto done; } diff -ruN --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/sendmail.h sendmail-8.12.0.Beta10/sendmail/sendmail.h --- sendmail-8.12.0.Beta10.orig/sendmail/sendmail.h Sun May 20 15:55:04 2001 +++ sendmail-8.12.0.Beta10/sendmail/sendmail.h Fri Jun 15 02:14:59 2001 @@ -222,6 +222,7 @@ #if PIPELINING struct address *q_pchain; /* chain for pipelining */ #endif /* PIPELINING */ + 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 */ @@ -255,6 +256,7 @@ #define QBYTRACE 0x00008000 /* DeliverBy: trace */ #define QBYNDELAY 0x00010000 /* DeliverBy: notify, delay */ #define QBYNRELAY 0x00020000 /* DeliverBy: notify, relayed */ +#define QENVTO 0x00100000 /* Original envelope recipient */ #define QTHISPASS 0x40000000 /* temp: address set this pass */ #define QRCPTOK 0x80000000 /* recipient() processed address */ @@ -2147,6 +2149,8 @@ EXTERN char *UnixFromLine; /* UNIX From_ line (old $l macro) */ EXTERN char **ExternalEnviron; /* saved user (input) environment */ EXTERN char **SaveArgv; /* argument vector for re-execing */ +EXTERN char *EtrnProg; /* program to be run on ETRN */ +EXTERN char *EnvToHeader; /* name of Envelope-To header */ EXTERN BITMAP256 DontBlameSendmail; /* DontBlameSendmail bits */ EXTERN SM_FILE_T *InChannel; /* input connection */ EXTERN SM_FILE_T *OutChannel; /* output connection */ diff -ruN --exclude=obj.* --exclude=*.orig sendmail-8.12.0.Beta10.orig/sendmail/srvrsmtp.c sendmail-8.12.0.Beta10/sendmail/srvrsmtp.c --- sendmail-8.12.0.Beta10.orig/sendmail/srvrsmtp.c Fri Jun 15 01:57:39 2001 +++ sendmail-8.12.0.Beta10/sendmail/srvrsmtp.c Fri Jun 15 02:01:28 2001 @@ -258,6 +258,37 @@ } +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; @@ -2248,6 +2279,15 @@ sm_syslog(LOG_INFO, e->e_id, "%.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 == '#')