+static int stuffline(struct query *ctl, char *buf)
+/* ship a line to the given control block's output sink (SMTP server or MDA) */
+{
+ int n;
+
+ /* fix message lines that have only \n termination (for qmail) */
+ if (ctl->forcecr)
+ {
+ char *cp = buf + strlen(buf) - 1;
+
+ if (*cp == '\n' && (cp == buf || cp[-1] != '\r'))
+ {
+ *cp++ = '\r';
+ *cp++ = '\n';
+ *cp++ = '\0';
+ }
+ }
+
+ /*
+ * SMTP byte-stuffing. We only do this if the protocol does *not*
+ * use .<CR><LF> as EOM. If it does, the server will already have
+ * decorated any . lines it sends back up.
+ */
+ if (!protocol->delimited && *buf == '.')
+ if (sinkfp && ctl->mda)
+ fputs(".", sinkfp);
+ else if (ctl->smtp_socket != -1)
+ SockWrite(ctl->smtp_socket, buf, 1);
+
+ /* we may need to strip carriage returns */
+ if (ctl->stripcr)
+ {
+ char *sp, *tp;
+
+ for (sp = tp = buf; *sp; sp++)
+ if (*sp != '\r')
+ *tp++ = *sp;
+ *tp = '\0';
+ }
+
+ n = 0;
+ if (ctl->mda)
+ n = fwrite(buf, 1, strlen(buf), sinkfp);
+ else if (ctl->smtp_socket != -1)
+ n = SockWrite(ctl->smtp_socket, buf, strlen(buf));
+
+ return(n);
+}
+
+static int readheaders(sock, len, ctl, realname, num)
+/* read message headers and ship to SMTP or MDA */