dma: factor out mail handling code
authorSimon Schubert <corecode@dragonflybsd.org>
Thu, 27 Aug 2009 11:52:43 +0000 (13:52 +0200)
committerSimon Schubert <corecode@dragonflybsd.org>
Thu, 27 Aug 2009 21:08:45 +0000 (23:08 +0200)
libexec/dma/Makefile
libexec/dma/dma.c
libexec/dma/dma.h
libexec/dma/mail.c [new file with mode: 0644]

index 8d0c09f..42e0044 100644 (file)
@@ -7,7 +7,8 @@ DPADD=  ${LIBSSL} ${LIBCRYPTO}
 LDADD=  -lssl -lcrypto
 
 PROG=  dma
-SRCS=  base64.c conf.c crypto.c net.c dma.c aliases_scan.l aliases_parse.y spool.c local.c util.c
+SRCS=  aliases_parse.y aliases_scan.l base64.c conf.c crypto.c
+SRCS+= dma.c local.c mail.c net.c spool.c util.c 
 MAN=   dma.8
 
 BINOWN= root
index ca9e9c1..bf22e8e 100644 (file)
@@ -184,76 +184,6 @@ out:
        return (-1);
 }
 
-static int
-readmail(struct queue *queue, const char *sender, int nodot)
-{
-       char line[1000];        /* by RFC2822 */
-       size_t linelen;
-       size_t error;
-       int had_headers = 0;
-       int had_from = 0;
-       int had_messagid = 0;
-       int had_date = 0;
-
-       error = fprintf(queue->mailf,
-               "Received: from %s (uid %d)\n"
-               "\t(envelope-from %s)\n"
-               "\tid %s\n"
-               "\tby %s (%s)\n"
-               "\t%s\n",
-               username, getuid(),
-               sender,
-               queue->id,
-               hostname(), VERSION,
-               rfc822date());
-       if ((ssize_t)error < 0)
-               return (-1);
-
-       while (!feof(stdin)) {
-               if (fgets(line, sizeof(line), stdin) == NULL)
-                       break;
-               linelen = strlen(line);
-               if (linelen == 0 || line[linelen - 1] != '\n') {
-                       errno = EINVAL;         /* XXX mark permanent errors */
-                       return (-1);
-               }
-               if (!had_headers) {
-                       if (strprefixcmp(line, "Date:") == 0)
-                               had_date = 1;
-                       else if (strprefixcmp(line, "Message-Id:") == 0)
-                               had_messagid = 1;
-                       else if (strprefixcmp(line, "From:") == 0)
-                               had_from = 1;
-               }
-               if (strcmp(line, "\n") == 0 && !had_headers) {
-                       had_headers = 1;
-                       while (!had_date || !had_messagid || !had_from) {
-                               if (!had_date) {
-                                       had_date = 1;
-                                       snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
-                               } else if (!had_messagid) {
-                                       /* XXX better msgid, assign earlier and log? */
-                                       had_messagid = 1;
-                                       snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n",
-                                                queue->id, hostname());
-                               } else if (!had_from) {
-                                       had_from = 1;
-                                       snprintf(line, sizeof(line), "From: <%s>\n", sender);
-                               }
-                               if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
-                                       return (-1);
-                       }
-                       strcpy(line, "\n");
-               }
-               if (!nodot && linelen == 2 && line[0] == '.')
-                       break;
-               if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
-                       return (-1);
-       }
-
-       return (0);
-}
-
 static struct qitem *
 go_background(struct queue *queue)
 {
@@ -317,101 +247,6 @@ retit:
 }
 
 static void
-bounce(struct qitem *it, const char *reason)
-{
-       struct queue bounceq;
-       struct qitem *bit;
-       char line[1000];
-       size_t pos;
-       int error;
-
-       /* Don't bounce bounced mails */
-       if (it->sender[0] == 0) {
-               syslog(LOG_INFO, "can not bounce a bounce message, discarding");
-               exit(1);
-       }
-
-       LIST_INIT(&bounceq.queue);
-       if (add_recp(&bounceq, it->sender, "", 1) != 0)
-               goto fail;
-
-       if (newspoolf(&bounceq, "") != 0)
-               goto fail;
-
-       syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id);
-       setlogident("%s", bounceq.id);
-
-       error = fprintf(bounceq.mailf,
-               "Received: from MAILER-DAEMON\n"
-               "\tid %s\n"
-               "\tby %s (%s)\n"
-               "\t%s\n"
-               "X-Original-To: <%s>\n"
-               "From: MAILER-DAEMON <>\n"
-               "To: %s\n"
-               "Subject: Mail delivery failed\n"
-               "Message-Id: <%s@%s>\n"
-               "Date: %s\n"
-               "\n"
-               "This is the %s at %s.\n"
-               "\n"
-               "There was an error delivering your mail to <%s>.\n"
-               "\n"
-               "%s\n"
-               "\n"
-               "%s\n"
-               "\n",
-               bounceq.id,
-               hostname(), VERSION,
-               rfc822date(),
-               it->addr,
-               it->sender,
-               bounceq.id, hostname(),
-               rfc822date(),
-               VERSION, hostname(),
-               it->addr,
-               reason,
-               config->features & FULLBOUNCE ?
-                   "Original message follows." :
-                   "Message headers follow.");
-       if (error < 0)
-               goto fail;
-
-       if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0)
-               goto fail;
-       if (config->features & FULLBOUNCE) {
-               while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) {
-                       if (fwrite(line, 1, pos, bounceq.mailf) != pos)
-                               goto fail;
-               }
-       } else {
-               while (!feof(it->mailf)) {
-                       if (fgets(line, sizeof(line), it->mailf) == NULL)
-                               break;
-                       if (line[0] == '\n')
-                               break;
-                       if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1)
-                               goto fail;
-               }
-       }
-
-       if (linkspool(&bounceq, "") != 0)
-               goto fail;
-       /* bounce is safe */
-
-       delqueue(it);
-
-       bit = go_background(&bounceq);
-       deliver(bit);
-       /* NOTREACHED */
-
-fail:
-       syslog(LOG_CRIT, "error creating bounce: %m");
-       delqueue(it);
-       exit(1);
-}
-
-static void
 deliver(struct qitem *it)
 {
        int error;
@@ -462,7 +297,7 @@ bounce:
        /* NOTREACHED */
 }
 
-static void
+void
 run_queue(struct queue *queue)
 {
        struct qitem *it;
@@ -509,7 +344,6 @@ int
 main(int argc, char **argv)
 {
        char *sender = NULL;
-       struct qitem *it;
        struct queue queue;
        struct queue lqueue;
        int i, ch;
@@ -674,8 +508,7 @@ skipopts:
        if (config->features & DEFER)
                return (0);
 
-       it = go_background(&queue);
-       deliver(it);
+       run_queue(&queue);
 
        /* NOTREACHED */
        return (0);
index 70e5f03..04cd28e 100644 (file)
@@ -175,6 +175,7 @@ int base64_decode(const char *, void *);
 
 /* dma.c */
 int add_recp(struct queue *, const char *, const char *, int);
+void run_queue(struct queue *);
 
 /* spool.c */
 int newspoolf(struct queue *, const char *);
@@ -187,6 +188,10 @@ void dropspool(struct queue *, struct qitem *);
 /* local.c */
 int deliver_local(struct qitem *, const char **errmsg);
 
+/* mail.c */
+void bounce(struct qitem *, const char *);
+int readmail(struct queue *, const char *, int);
+
 /* util.c */
 const char *hostname(void);
 void setlogident(const char *, ...);
diff --git a/libexec/dma/mail.c b/libexec/dma/mail.c
new file mode 100644 (file)
index 0000000..d11f465
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2008 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "dma.h"
+
+void
+bounce(struct qitem *it, const char *reason)
+{
+       struct queue bounceq;
+       char line[1000];
+       size_t pos;
+       int error;
+
+       /* Don't bounce bounced mails */
+       if (it->sender[0] == 0) {
+               syslog(LOG_INFO, "can not bounce a bounce message, discarding");
+               exit(1);
+       }
+
+       LIST_INIT(&bounceq.queue);
+       if (add_recp(&bounceq, it->sender, "", 1) != 0)
+               goto fail;
+
+       if (newspoolf(&bounceq, "") != 0)
+               goto fail;
+
+       syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id);
+       setlogident("%s", bounceq.id);
+
+       error = fprintf(bounceq.mailf,
+               "Received: from MAILER-DAEMON\n"
+               "\tid %s\n"
+               "\tby %s (%s)\n"
+               "\t%s\n"
+               "X-Original-To: <%s>\n"
+               "From: MAILER-DAEMON <>\n"
+               "To: %s\n"
+               "Subject: Mail delivery failed\n"
+               "Message-Id: <%s@%s>\n"
+               "Date: %s\n"
+               "\n"
+               "This is the %s at %s.\n"
+               "\n"
+               "There was an error delivering your mail to <%s>.\n"
+               "\n"
+               "%s\n"
+               "\n"
+               "%s\n"
+               "\n",
+               bounceq.id,
+               hostname(), VERSION,
+               rfc822date(),
+               it->addr,
+               it->sender,
+               bounceq.id, hostname(),
+               rfc822date(),
+               VERSION, hostname(),
+               it->addr,
+               reason,
+               config->features & FULLBOUNCE ?
+                   "Original message follows." :
+                   "Message headers follow.");
+       if (error < 0)
+               goto fail;
+
+       if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0)
+               goto fail;
+       if (config->features & FULLBOUNCE) {
+               while ((pos = fread(line, 1, sizeof(line), it->mailf)) > 0) {
+                       if (fwrite(line, 1, pos, bounceq.mailf) != pos)
+                               goto fail;
+               }
+       } else {
+               while (!feof(it->mailf)) {
+                       if (fgets(line, sizeof(line), it->mailf) == NULL)
+                               break;
+                       if (line[0] == '\n')
+                               break;
+                       if (fwrite(line, strlen(line), 1, bounceq.mailf) != 1)
+                               goto fail;
+               }
+       }
+
+       if (linkspool(&bounceq, "") != 0)
+               goto fail;
+       /* bounce is safe */
+
+       delqueue(it);
+
+       run_queue(&bounceq);
+       /* NOTREACHED */
+
+fail:
+       syslog(LOG_CRIT, "error creating bounce: %m");
+       delqueue(it);
+       exit(1);
+}
+
+int
+readmail(struct queue *queue, const char *sender, int nodot)
+{
+       char line[1000];        /* by RFC2822 */
+       size_t linelen;
+       size_t error;
+       int had_headers = 0;
+       int had_from = 0;
+       int had_messagid = 0;
+       int had_date = 0;
+
+       error = fprintf(queue->mailf,
+               "Received: from %s (uid %d)\n"
+               "\t(envelope-from %s)\n"
+               "\tid %s\n"
+               "\tby %s (%s)\n"
+               "\t%s\n",
+               username, getuid(),
+               sender,
+               queue->id,
+               hostname(), VERSION,
+               rfc822date());
+       if ((ssize_t)error < 0)
+               return (-1);
+
+       while (!feof(stdin)) {
+               if (fgets(line, sizeof(line), stdin) == NULL)
+                       break;
+               linelen = strlen(line);
+               if (linelen == 0 || line[linelen - 1] != '\n') {
+                       errno = EINVAL;         /* XXX mark permanent errors */
+                       return (-1);
+               }
+               if (!had_headers) {
+                       if (strprefixcmp(line, "Date:") == 0)
+                               had_date = 1;
+                       else if (strprefixcmp(line, "Message-Id:") == 0)
+                               had_messagid = 1;
+                       else if (strprefixcmp(line, "From:") == 0)
+                               had_from = 1;
+               }
+               if (strcmp(line, "\n") == 0 && !had_headers) {
+                       had_headers = 1;
+                       while (!had_date || !had_messagid || !had_from) {
+                               if (!had_date) {
+                                       had_date = 1;
+                                       snprintf(line, sizeof(line), "Date: %s\n", rfc822date());
+                               } else if (!had_messagid) {
+                                       /* XXX better msgid, assign earlier and log? */
+                                       had_messagid = 1;
+                                       snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n",
+                                                queue->id, hostname());
+                               } else if (!had_from) {
+                                       had_from = 1;
+                                       snprintf(line, sizeof(line), "From: <%s>\n", sender);
+                               }
+                               if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
+                                       return (-1);
+                       }
+                       strcpy(line, "\n");
+               }
+               if (!nodot && linelen == 2 && line[0] == '.')
+                       break;
+               if (fwrite(line, strlen(line), 1, queue->mailf) != 1)
+                       return (-1);
+       }
+
+       return (0);
+}