#include "seek.h"
#include "substdio.h"
#include "getln.h"
+#include "strerr.h"
#include "subfd.h"
#include "sgetopt.h"
#include "alloc.h"
#include "gfrom.h"
#include "auto_patrn.h"
-void err(s) char *s; { substdio_putsflush(subfderr,s); }
-void soft() { _exit(111); }
-void hard() { _exit(100); }
-
-void temp_childcrashed() { err("Aack, child crashed. (#4.3.0)\n"); soft(); }
-void temp_rewind() { err("Unable to rewind message. (#4.3.0)\n"); soft(); }
-void temp_fork() { err("Unable to fork. (#4.3.0)\n"); soft(); }
-void temp_read() { err("Error while reading message. (#4.3.0)\n"); soft(); }
-void temp_write() { err("Error while writing message. (#4.3.0)\n"); soft(); }
-void temp_child() { err("Temporary error in forwarding message. (#4.3.0)\n"); soft(); }
-void temp_maildirtimeout() { err("Timeout on maildir delivery. (#4.3.0)\n"); soft(); }
-void temp_maildir() { err("Temporary error on maildir delivery. (#4.3.0)\n"); soft(); }
-void temp_nomaildir() { err("Unable to chdir to maildir. (#4.2.1)\n"); soft(); }
-void temp_open(fn) char *fn; { err("Unable to open "); err(fn); err(". (#4.2.1)\n"); soft(); }
-
-void temp_blankline() { err("Uh-oh: first line of .qmail file is blank. (#4.2.1)\n"); soft(); }
-void temp_fofile() { err("Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)\n"); soft(); }
-void temp_foprog() { err("Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)\n"); soft(); }
-void temp_nomem() { err("Out of memory. (#4.3.0)\n"); soft(); }
-void temp_chdir() { err("Unable to switch to home directory. (#4.3.0)\n"); soft(); }
-void temp_homestat() { err("Unable to stat home directory. (#4.3.0)\n"); soft(); }
-void temp_homesticky() { err("Home directory is sticky: user is editing his .qmail file. (#4.2.1)\n"); soft(); }
-void temp_homewritable() { err("Uh-oh: home directory is writable. (#4.7.0)\n"); soft(); }
-void temp_qmwritable() { err("Uh-oh: .qmail file is writable. (#4.7.0)\n"); soft(); }
-void temp_nfsqmail() { err("Temporary error trying to open .qmail file. (#4.3.0)\n"); soft(); }
-void temp_denyqmail() { err("Permission error trying to open .qmail file. (#4.3.0)\n"); soft(); }
-void temp_slowlock() { err("File has been locked for 30 seconds straight. (#4.3.0)\n"); soft(); }
-
-void bounce_childperm() { err("Permanent error in forwarding message. (#5.2.4)\n"); hard(); }
-void bounce_loop() { err("This message is looping: it already has my Delivered-To line. (#5.4.6)\n"); hard(); }
-void bounce_ext() { err("Sorry, no mailbox here by that name. (#5.1.1)\n"); hard(); }
-void usage() { err("qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty\n"); hard(); }
-
-void warn_homesticky() { err("Warning: home directory is sticky.\n"); }
+void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); }
+
+void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); }
+void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); }
+void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); }
+void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); }
+void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); }
+void temp_slowlock()
+{ strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); }
+void temp_qmail(fn) char *fn;
+{ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); }
int flagdoit;
int flag99;
char *sender;
char *aliasempty;
-stralloc dashext = {0};
+stralloc safeext = {0};
stralloc ufline = {0};
stralloc rpline = {0};
stralloc envrecip = {0};
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;
temp_fork();
case 0:
maildir_child(fn);
- soft();
+ _exit(111);
}
wait_pid(&wstat,child);
switch(wait_exitcode(wstat))
{
case 0: break;
- case 2: temp_nomaildir();
- case 3: temp_maildirtimeout();
- case 4: temp_read();
- default: temp_maildir();
+ case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)");
+ case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)");
+ case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)");
+ default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)");
}
}
-void slowlock() { temp_slowlock(); }
-
void mailfile(fn)
char *fn;
{
if (seek_begin(0) == -1) temp_rewind();
fd = open_append(fn);
- if (fd == -1) temp_open(fn);
+ if (fd == -1)
+ strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)");
- sig_alarmcatch(slowlock);
+ sig_alarmcatch(temp_slowlock);
alarm(30);
flaglocked = (lock_ex(fd) != -1);
alarm(0);
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;
for (;;)
{
if (getln(&ss,&messline,&match,'\n') != 0)
- { if (flaglocked) seek_trunc(fd,pos); close(fd); temp_read(); }
+ {
+ strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0);
+ if (flaglocked) seek_trunc(fd,pos); close(fd);
+ _exit(111);
+ }
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)
{
return;
writeerrs:
+ strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0);
if (flaglocked) seek_trunc(fd,pos);
close(fd);
- temp_write();
+ _exit(111);
}
void mailprogram(prog)
case -1:
temp_fork();
case 0:
- args[0] = "sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
+ args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0;
sig_pipedefault();
- execvp(*args,args);
- if (errno == error_txtbsy) { err("Text busy. (#4.3.0)\n"); soft(); }
- if (errno == error_nomem) { err("Out of memory. (#4.3.0)\n"); soft(); }
- if (errno == error_io) { err("I/O error. (#4.3.0)\n"); soft(); }
- if (error_temp(errno)) { err("Temporary error. (#4.3.0)\n"); soft(); }
- err("Unable to execute "); err(*args); err(" (#5.2.4)\n");
- hard();
+ execv(*args,args);
+ strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)");
}
wait_pid(&wstat,child);
switch(wait_exitcode(wstat))
{
case 100:
- case 64: case 65: case 70: case 76: case 77: case 78: case 112: hard();
+ case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100);
case 0: break;
case 99: flag99 = 1; break;
- default: soft();
+ default: _exit(111);
}
}
char **recips;
{
struct qmail qqt;
+ char *qqx;
substdio ss;
int 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);
qmail_from(&qqt,ueo.s);
while (*recips) qmail_to(&qqt,*recips++);
- switch(qmail_close(&qqt))
- {
- case QMAIL_TOOLONG: bounce_childperm();
- case QMAIL_READ: temp_read();
- case 0: return;
- default: temp_child();
- }
+ qqx = qmail_close(&qqt);
+ if (!*qqx) return;
+ strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,".");
}
void bouncexf()
break;
if (messline.len == dtline.len)
if (!str_diffn(messline.s,dtline.s,dtline.len))
- bounce_loop();
+ strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)");
}
}
{
struct stat st;
- if (stat(".",&st) == -1) temp_homestat();
- if (st.st_mode & auto_patrn) temp_homewritable();
+ if (stat(".",&st) == -1)
+ strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)");
+ if (st.st_mode & auto_patrn)
+ strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)");
if (st.st_mode & 01000)
- if (flagdoit) temp_homesticky(); else warn_homesticky();
+ if (flagdoit)
+ strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)");
+ else
+ strerr_warn1("Warning: home directory is sticky.",0);
}
int qmeox(dashowner)
struct stat st;
if (!stralloc_copys(&qme,".qmail")) temp_nomem();
- if (!stralloc_cat(&qme,&dashext)) temp_nomem();
+ if (!stralloc_cats(&qme,dash)) temp_nomem();
+ if (!stralloc_cat(&qme,&safeext)) temp_nomem();
if (!stralloc_cats(&qme,dashowner)) temp_nomem();
if (!stralloc_0(&qme)) temp_nomem();
if (stat(qme.s,&st) == -1)
{
- if (error_temp(errno)) temp_nfsqmail();
+ if (error_temp(errno)) temp_qmail(qme.s);
return -1;
}
return 0;
}
-int qmeopen(cutable)
+int qmeexists(fd,cutable)
+int *fd;
int *cutable;
{
- int fd;
- struct stat st;
- int i;
+ struct stat st;
- i = dashext.len;
- for (;;)
- {
- if (!stralloc_copys(&qme,".qmail")) temp_nomem();
- if (!stralloc_catb(&qme,dashext.s,i)) temp_nomem();
- if (i < dashext.len) if (!stralloc_cats(&qme,"-default")) temp_nomem();
- if (!stralloc_0(&qme)) temp_nomem();
- fd = open_read(qme.s);
- if (fd == -1)
- {
- if (error_temp(errno)) temp_nfsqmail();
- if (errno == error_perm) temp_denyqmail();
- if (errno == error_acces) temp_denyqmail();
+ if (!stralloc_0(&qme)) temp_nomem();
+
+ *fd = open_read(qme.s);
+ if (*fd == -1) {
+ if (error_temp(errno)) temp_qmail(qme.s);
+ if (errno == error_perm) temp_qmail(qme.s);
+ if (errno == error_acces) temp_qmail(qme.s);
+ return 0;
+ }
+
+ if (fstat(*fd,&st) == -1) temp_qmail(qme.s);
+ if ((st.st_mode & S_IFMT) == S_IFREG) {
+ if (st.st_mode & auto_patrn)
+ strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)");
+ *cutable = !!(st.st_mode & 0100);
+ return 1;
+ }
+ close(*fd);
+ return 0;
+}
+
+/* "" "": "" */
+/* "-/" "": "-/" "-/default" */
+/* "-/" "a": "-/a" "-/default" */
+/* "-/" "a-": "-/a-" "-/a-default" "-/default" */
+/* "-/" "a-b": "-/a-b" "-/a-default" "-/default" */
+/* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" */
+/* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" */
+
+void qmesearch(fd,cutable)
+int *fd;
+int *cutable;
+{
+ int i;
+
+ if (!stralloc_copys(&qme,".qmail")) temp_nomem();
+ if (!stralloc_cats(&qme,dash)) temp_nomem();
+ if (!stralloc_cat(&qme,&safeext)) temp_nomem();
+ if (qmeexists(fd,cutable)) {
+ if (safeext.len >= 7) {
+ i = safeext.len - 7;
+ if (!byte_diff("default",7,safeext.s + i))
+ if (i <= str_len(ext)) /* paranoia */
+ if (!env_put2("DEFAULT",ext + i)) temp_nomem();
}
- else
- {
- if (fstat(fd,&st) == -1) temp_nfsqmail();
- if ((st.st_mode & S_IFMT) == S_IFREG)
- {
- if (st.st_mode & auto_patrn) temp_qmwritable();
- *cutable = !!(st.st_mode & 0100);
- return fd;
+ return;
+ }
+
+ for (i = safeext.len;i >= 0;--i)
+ if (!i || (safeext.s[i - 1] == '-')) {
+ if (!stralloc_copys(&qme,".qmail")) temp_nomem();
+ if (!stralloc_cats(&qme,dash)) temp_nomem();
+ if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem();
+ if (!stralloc_cats(&qme,"default")) temp_nomem();
+ if (qmeexists(fd,cutable)) {
+ if (i <= str_len(ext)) /* paranoia */
+ if (!env_put2("DEFAULT",ext + i)) temp_nomem();
+ return;
}
- close(fd);
}
- if (!i) return -1;
- do
- if (dashext.s[--i] == '-') break;
- while (i);
- }
+
+ *fd = -1;
}
unsigned long count_file = 0;
char **recips;
datetime_sec starttime;
int flagforwardonly;
- char *extx;
+ char *x;
+ char *cplast;
umask(077);
sig_pipeignore();
{
case 'n': flagdoit = 0; break;
case 'N': flagdoit = 1; break;
- case '?':
default:
- hard();
+ usage();
}
argc -= optind;
argv += optind;
if (*argv) usage();
if (homedir[0] != '/') usage();
- if (chdir(homedir) == -1) temp_chdir();
+ if (chdir(homedir) == -1)
+ strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)");
checkhome();
if (!env_put2("HOST",host)) temp_nomem();
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)
{
if (!stralloc_0(&foo)) temp_nomem();
if (!env_put2("UFLINE",foo.s)) temp_nomem();
- if (!stralloc_copys(&dashext,dash)) temp_nomem();
- if (!stralloc_cats(&dashext,ext)) temp_nomem();
- for (i = 0;i < dashext.len;++i)
- if (dashext.s[i] == '.')
- dashext.s[i] = ':';
- case_lowerb(dashext.s,dashext.len);
-
- extx = ext;
- if (!env_put2("EXT",extx)) temp_nomem();
- extx += str_chr(extx,'-'); if (*extx) ++extx;
- if (!env_put2("EXT2",extx)) temp_nomem();
- extx += str_chr(extx,'-'); if (*extx) ++extx;
- if (!env_put2("EXT3",extx)) temp_nomem();
- extx += str_chr(extx,'-'); if (*extx) ++extx;
- if (!env_put2("EXT4",extx)) temp_nomem();
+ x = ext;
+ if (!env_put2("EXT",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT2",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT3",x)) temp_nomem();
+ x += str_chr(x,'-'); if (*x) ++x;
+ if (!env_put2("EXT4",x)) temp_nomem();
+
+ if (!stralloc_copys(&safeext,ext)) temp_nomem();
+ case_lowerb(safeext.s,safeext.len);
+ for (i = 0;i < safeext.len;++i)
+ if (safeext.s[i] == '.')
+ safeext.s[i] = ':';
+
+ i = str_len(host);
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST2",foo.s)) temp_nomem();
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST3",foo.s)) temp_nomem();
+ i = byte_rchr(host,i,'.');
+ if (!stralloc_copyb(&foo,host,i)) temp_nomem();
+ if (!stralloc_0(&foo)) temp_nomem();
+ if (!env_put2("HOST4",foo.s)) temp_nomem();
flagforwardonly = 0;
- fd = qmeopen(&flagforwardonly);
- if (fd == -1) if (*dash) bounce_ext();
+ qmesearch(&fd,&flagforwardonly);
+ if (fd == -1)
+ if (*dash)
+ strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
if (!stralloc_copys(&ueo,sender)) temp_nomem();
if (str_diff(sender,""))
{
case 0: /* k == i */
if (i) break;
- temp_blankline();
+ strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)");
case '#':
break;
case '.':
case '/':
++count_file;
- if (flagforwardonly) temp_fofile();
+ if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)");
if (cmds.s[k - 1] == '/')
if (flagdoit) maildir(cmds.s + i);
else sayit("maildir ",cmds.s + i,k - i);
break;
case '|':
++count_program;
- if (flagforwardonly) temp_foprog();
+ if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)");
if (flagdoit) mailprogram(cmds.s + i + 1);
else sayit("program ",cmds.s + i + 1,k - i - 1);
break;