stralloc cmds = {0};
stralloc messline = {0};
stralloc foo = {0};
+stralloc qsender = {0};
+stralloc tmpline = {0};
+char *verhhost = (char *)0;
+char *verhlocal = (char *)0;
+int flagheader,flagdobody;
+unsigned int i;
+
+int verhline(sa)
+stralloc *sa;
+/* substitutes ##L => recipient local, ##H => recipient host if VERP sender */
+/* returns 0 normally, -1 on out-of-memory */
+{
+ register char *cp;
+ char *cpnext,*cpafter;
+
+ if (!verhlocal) return 0; /* no VERP SENDER */
+ cp = sa->s;
+ cpnext = sa->s;
+ cpafter = cp + sa->len;
+ tmpline.len = 0; /* clear */
+ for (;;) {
+ while (cp < cpafter && *cp++ != '#');
+ if (cp + 1 < cpafter && *cp == '#') { /* found '##' */
+ cp++;
+ if (*cp == 'L') { /* ##L */
+ if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+ cp++;
+ cpnext = cp;
+ if (!stralloc_cats(&tmpline,verhlocal)) return -1;
+ } else if (*cp == 'H') { /* ##H */
+ if (!stralloc_catb(&tmpline,cpnext,cp - cpnext - 2)) return -1;
+ cp++;
+ cpnext = cp;
+ if (!stralloc_cats(&tmpline,verhhost)) return -1;
+ }
+ }
+ if (cp >= cpafter) {
+ if (tmpline.len) { /* true if we've done any substitutions */
+ if (!stralloc_catb(&tmpline,cpnext,cpafter - cpnext)) return -1;
+ if (!stralloc_copy(sa,&tmpline)) return -1;
+ }
+ return 0;
+ }
+ }
+}
char buf[1024];
char outbuf[1024];
char host[64];
char *s;
int loop;
+ int match;
struct stat st;
int fd;
substdio ss;
if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail;
if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail;
- switch(substdio_copy(&ssout,&ss))
- {
- case -2: tryunlinktmp(); _exit(4);
- case -3: goto fail;
- }
+ flagheader = 1;
+ flagdobody = 0;
+ do { /* for VERH */
+ if (getln(&ss,&messline,&match,'\n') != 0)
+ { tryunlinktmp(); _exit(4); }
+ if (flagheader) {
+ if (match && messline.len == 1) {
+ flagheader = 0;
+ if (!flagdobody) verhlocal = (char *)0;
+ }
+ if (messline.s[0] == '#') { /* continue in body */
+ flagdobody = 1; /* remove leading '#' */
+ for (i = 1; i < messline.len; i++)
+ messline.s[i - 1] = messline.s[i];
+ messline.len--; /* always >= 1 from \n */
+ }
+ }
+ if (verhlocal)
+ if (verhline(&messline) == -1) goto fail;
+ if (substdio_put(&ssout,messline.s,messline.len) == -1) goto fail;
+ } while (match);
if (substdio_flush(&ssout) == -1) goto fail;
if (fsync(fd) == -1) goto fail;
substdio_fdbuf(&ss,read,0,buf,sizeof(buf));
substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf));
+ flagheader = 1;
+ flagdobody = 0;
if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs;
if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs;
if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs;
if (!match && !messline.len) break;
if (gfrom(messline.s,messline.len))
if (substdio_bput(&ssout,">",1)) goto writeerrs;
+ if (flagheader) {
+ if (match && messline.len == 1) {
+ if (!flagdobody) verhlocal = (char *)0;
+ flagheader = 0;
+ }
+ if (messline.s[0] == '#') { /* continue in body */
+ flagdobody = 1; /* remove leading '#' */
+ for (i = 1; i < messline.len; i++)
+ messline.s[i - 1] = messline.s[i];
+ messline.len--;
+ }
+ }
+ if (verhlocal)
+ if (verhline(&messline) == -1) goto writeerrs;
if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs;
if (!match)
{
if (qmail_open(&qqt) == -1) temp_fork();
mailforward_qp = qmail_qp(&qqt);
qmail_put(&qqt,dtline.s,dtline.len);
+ flagheader = 1;
do
{
if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; }
+ if (flagheader) {
+ if (match && messline.len == 1) {
+ flagheader = 0;
+ if (!flagdobody) verhlocal = (char *)0;
+ }
+ if (messline.s[0] == '#') { /* continue in body */
+ flagdobody = 1; /* remove leading '#' */
+ for (i = 1; i < messline.len; i++)
+ messline.s[i - 1] = messline.s[i];
+ messline.len--;
+ }
+ }
+ if (verhlocal)
+ if (verhline(&messline) == -1) { qmail_fail(&qqt); break; }
qmail_put(&qqt,messline.s,messline.len);
}
while (match);
datetime_sec starttime;
int flagforwardonly;
char *x;
+ char *cplast;
umask(077);
sig_pipeignore();
if (!env_put2("SENDER",sender)) temp_nomem();
- if (!quote2(&foo,sender)) temp_nomem();
+ if (!quote2(&qsender,sender)) temp_nomem();
if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem();
- if (!stralloc_cat(&rpline,&foo)) temp_nomem();
+ if (!stralloc_cat(&rpline,&qsender)) temp_nomem();
for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '\n') rpline.s[i] = '_';
if (!stralloc_cats(&rpline,">\n")) temp_nomem();
if (!stralloc_0(&foo)) temp_nomem();
if (!env_put2("RPLINE",foo.s)) temp_nomem();
+ i = byte_rchr(qsender.s,qsender.len,'@'); /* for VERH */
+ if (i != qsender.len) { /* got @ */
+ cplast = qsender.s + i;
+ *cplast = '\0';
+ if (qsender.s[i = str_rchr(qsender.s,'=')]) { /* got = */
+ qsender.s[i] = '\0';
+ cplast = qsender.s + i;
+ verhhost = qsender.s + i + 1;
+ i = str_rchr(qsender.s,'-');
+ if (qsender.s[i] == '-') {
+ for (;;) {
+ if (case_starts(qsender.s + i + 1,"return-")) {
+ verhlocal = qsender.s + i + 9 + str_chr(qsender.s + i + 8,'-');
+ /* here to avoid work if not VERP */
+ /* verhhost not used if verhlocal=0 */
+ for (x = verhlocal; x < cplast; x++)
+ if (*x == '\n') *x = '_'; /* \n would ruin */
+ break;
+ }
+ j = byte_rchr(qsender.s,i,'-');
+ if (j == i) break;
+ i = j;
+ }
+ }
+ }
+ }
+
if (!stralloc_copys(&ufline,"From ")) temp_nomem();
if (*sender)
{