diff -ruN sendmail-8.9.2.orig/src/deliver.c sendmail-8.9.2/src/deliver.c --- sendmail-8.9.2.orig/src/deliver.c Tue Dec 29 18:42:23 1998 +++ sendmail-8.9.2/src/deliver.c Wed Jan 13 12:36:14 1999 @@ -1256,6 +1256,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", &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.9.2.orig/src/headers.c sendmail-8.9.2/src/headers.c --- sendmail-8.9.2.orig/src/headers.c Tue Dec 29 18:42:15 1998 +++ sendmail-8.9.2/src/headers.c Wed Jan 13 12:36:14 1999 @@ -1687,3 +1687,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.9.2.orig/src/queue.c sendmail-8.9.2/src/queue.c --- sendmail-8.9.2.orig/src/queue.c Tue Dec 29 18:42:23 1998 +++ sendmail-8.9.2/src/queue.c Wed Jan 13 12:36:14 1999 @@ -79,7 +79,9 @@ MCI mcibuf; char tf[MAXQFNAME]; char buf[MAXLINE]; + char **addr_ptr, **ptr; extern void printctladdr __P((ADDRESS *, FILE *)); + extern void getenvto __P((ADDRESS *, char ***, int)); /* ** Create control file. @@ -293,6 +295,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)); @@ -1555,6 +1562,8 @@ { register FILE *qfp; ADDRESS *ctladdr; + ADDRESS *addr; + ADDRESS *envto = NULL; struct stat st; char *bp; int qfver = 0; @@ -1699,6 +1708,14 @@ orcpt = newstr(&bp[1]); break; + case 'Y': /* original envelope-to */ + addr = setctluser(&bp[1], qfver); + addr->q_dups = envto; + addr->q_flags |= (QENVTO|QDONTSEND); + addr->q_flags &= ~(QPRIMARY); + envto = addr; + break; + case 'R': /* specify recipient */ p = bp; qflags = 0; @@ -1736,14 +1753,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.9.2.orig/src/readcf.c sendmail-8.9.2/src/readcf.c --- sendmail-8.9.2.orig/src/readcf.c Tue Dec 29 18:42:22 1998 +++ sendmail-8.9.2/src/readcf.c Wed Jan 13 12:39:14 1999 @@ -1527,6 +1527,10 @@ #define O_CONTROLSOCKET 0xa9 { "ControlSocketName", O_CONTROLSOCKET, FALSE }, #endif +#define O_ETRNPROG 0xaa + { "EtrnProg", O_ETRNPROG, FALSE }, +#define O_ENVTOHEADER 0xab + { "EnvelopeToHeader", O_ENVTOHEADER, FALSE }, { NULL, '\0', FALSE } }; @@ -2465,6 +2469,16 @@ ControlSocketName = newstr(val); break; #endif + + 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.9.2.orig/src/recipient.c sendmail-8.9.2/src/recipient.c --- sendmail-8.9.2.orig/src/recipient.c Tue Dec 29 18:42:15 1998 +++ sendmail-8.9.2/src/recipient.c Wed Jan 13 12:36:14 1999 @@ -17,7 +17,82 @@ # include "sendmail.h" # include -/* + + /* +** 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. @@ -222,8 +297,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)) { printf("\nrecipient (%d): ", aliaslevel); @@ -325,6 +403,14 @@ } else if (bitset(QSELFREF, q->q_flags)) q->q_flags |= a->q_flags & ~QDONTSEND; + /* + ** 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.9.2.orig/src/sendmail.h sendmail-8.9.2/src/sendmail.h --- sendmail-8.9.2.orig/src/sendmail.h Tue Dec 29 18:42:19 1998 +++ sendmail-8.9.2/src/sendmail.h Wed Jan 13 12:36:14 1999 @@ -162,6 +162,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 */ @@ -191,6 +192,7 @@ # define QEXPANDED 0x00020000 /* DSN: undergone list expansion */ # define QDELIVERED 0x00040000 /* DSN: successful final delivery */ # define QDELAYED 0x00080000 /* DSN: message delayed */ +# define QENVTO 0x00100000 /* Original envelope recipient */ # define QTHISPASS 0x40000000 /* temp: address set this pass */ # define QRCPTOK 0x80000000 /* recipient() processed address */ @@ -1289,6 +1291,8 @@ EXTERN char **ExternalEnviron; /* input environment */ EXTERN char *UserEnviron[MAXUSERENVIRON + 1]; /* saved user environment */ +EXTERN char *EtrnProg; /* program to be run on ETRN */ +EXTERN char *EnvToHeader; /* name of Envelope-To header */ EXTERN int MaxMimeHeaderLength; /* maximum MIME header length */ EXTERN int MaxMimeFieldLength; /* maximum MIME field length */ diff -ruN sendmail-8.9.2.orig/src/srvrsmtp.c sendmail-8.9.2/src/srvrsmtp.c --- sendmail-8.9.2.orig/src/srvrsmtp.c Tue Dec 29 18:42:21 1998 +++ sendmail-8.9.2/src/srvrsmtp.c Wed Jan 13 12:36:14 1999 @@ -107,6 +107,37 @@ #define MAXVRFYCOMMANDS 6 /* max VRFY/EXPN commands before slowdown */ #define MAXETRNCOMMANDS 8 /* max ETRN commands before slowdown */ +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, e) char *nullserver; @@ -949,6 +980,16 @@ "%.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 == '@')