+
+ for (;;) {
+ if (p >= l) goto trunc;
+ if (!*p) break;
+ else if (*p++ != 'T') {
+ syslog(LOG_ERR, "corrupt envelope (no recipient marker)");
+ return (-1);
+ }
+ if (p >= l) goto trunc;
+ if (e->nrcpt < NRCPT) e->rcpt[e->nrcpt++] = p;
+ for (;;) {
+ if (p >= l) goto trunc;
+ else if (!*p++) break;
+ }
+ }
+ return (0);
+
+ /* Failed to reach the final terminator; maybe there's more. This isn't a
+ * very bad situation.
+ */
+trunc:
+ e->f |= EF_TRUNC;
+ return (0);
+}
+
+static void real(void)
+{
+ const char *qmq =
+ strenv("QMAIL_CHECKSPAM_QUEUE", "/var/qmail/bin/qmail-queue");
+ execlp(qmq, qmq, (char *)0);
+ syslog(LOG_ERR, "failed to exec %s: %m", qmq);
+ exit(56);
+}
+
+static int split(int *fd_m, int *fd_e)
+{
+ pid_t kid;
+ int pm[2], pe[2];
+
+ if (pipe(pm) || pipe(pe)) return (-1);
+ if ((kid = fork()) < 0) return (-1);
+ if (kid) {
+ dup2(pm[0], 0); close(pm[0]); close(pm[1]);
+ dup2(pe[0], 1); close(pe[0]); close(pe[1]);
+ real();
+ } else {
+ close(pm[0]); *fd_m = pm[1];
+ close(pe[0]); *fd_e = pe[1];
+ }
+ return (0);
+}
+
+static int writemsg(struct message *m, int fd_m, int shovelp)
+{
+ if (message_write(fd_m, m) < 0) {
+ syslog(LOG_ERR, "failed to write message body: %m");
+ return (-1);
+ }
+ if (shovelp && shovel(0, fd_m, "message body"))
+ return (-1);
+ close(fd_m);
+ return (0);
+}
+
+static int writeenv(struct envelope *e, int fd_e)
+{
+ if (safewrite(fd_e, e->buf, e->n) < 0) {
+ syslog(LOG_ERR, "failed to write envelope: %m");
+ return (-1);
+ }
+ if ((e->f & EF_TRUNC) && shovel(1, fd_e, "envelope"))
+ return (-1);
+ close(fd_e);
+ return (0);
+}
+
+static void logenv(struct envelope *e)
+{
+ size_t i;
+
+ syslog(LOG_NOTICE, "sender = %s", e->send);
+ for (i = 0; i < e->nrcpt; i++)
+ syslog(LOG_NOTICE, "recipient %lu = %s", (unsigned long)i, e->rcpt[i]);