Bugzilla #401 + #402
authorTom Kistner <tom@duncanthrax.net>
Mon, 30 Oct 2006 22:06:33 +0000 (22:06 +0000)
committerTom Kistner <tom@duncanthrax.net>
Mon, 30 Oct 2006 22:06:33 +0000 (22:06 +0000)
src/OS/os.h-Linux
src/src/dk.c
src/src/transport.c

index 285e8d28f84ef2d341f2bfce993a66ca09ee243d..5b731eaa1144761d0c32274e9c5b6dd7c65c45e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/OS/os.h-Linux,v 1.3 2005/02/17 10:04:41 ph10 Exp $ */
+/* $Cambridge: exim/src/OS/os.h-Linux,v 1.4 2006/10/30 22:06:33 tom Exp $ */
 
 /* Exim: OS-specific C header file for Linux */
 
@@ -7,6 +7,7 @@
 #define HAVE_MMAP
 #define HAVE_BSD_GETLOADAVG
 #define HAVE_SYS_STATVFS_H
+#define HAVE_LINUX_SENDFILE
 #define NO_IP_VAR_H
 #define SIG_IGN_WORKS
 
index ddab48b748fdf24c875847a9e06ea766ee940b59..9ed82382b98d47ed40b9a4728b5bff03de900ed1 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/dk.c,v 1.10 2006/07/06 14:28:04 ph10 Exp $ */
+/* $Cambridge: exim/src/src/dk.c,v 1.11 2006/10/30 22:06:33 tom Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -242,7 +242,7 @@ uschar *dk_exim_sign(int dk_fd,
   uschar *headers = NULL;
   int headers_len;
   int dk_canon_int = DK_CANON_SIMPLE;
-  char c;
+  char buf[4096];
   int seen_lf = 0;
   int seen_lfdot = 0;
   uschar sig[1024];
@@ -271,40 +271,46 @@ uschar *dk_exim_sign(int dk_fd,
     goto CLEANUP;
   }
 
-  while((sread = read(dk_fd,&c,1)) > 0) {
+  while((sread = read(dk_fd,&buf,4096)) > 0) {
+    int pos = 0;
+    char c;
 
-    if ((c == '.') && seen_lfdot) {
-      /* escaped dot, write "\n.", continue */
-      dk_message(dk_context, CUS "\n.", 2);
-      seen_lf = 0;
-      seen_lfdot = 0;
-      continue;
-    }
+    while (pos < sread) {
+      c = buf[pos++];
 
-    if (seen_lfdot) {
-      /* EOM, write "\n" and break */
-      dk_message(dk_context, CUS "\n", 1);
-      break;
-    }
+      if ((c == '.') && seen_lfdot) {
+        /* escaped dot, write "\n.", continue */
+        dk_message(dk_context, CUS "\n.", 2);
+        seen_lf = 0;
+        seen_lfdot = 0;
+        continue;
+      }
 
-    if ((c == '.') && seen_lf) {
-      seen_lfdot = 1;
-      continue;
-    }
+      if (seen_lfdot) {
+        /* EOM, write "\n" and break */
+        dk_message(dk_context, CUS "\n", 1);
+        break;
+      }
 
-    if (seen_lf) {
-      /* normal lf, just send it */
-      dk_message(dk_context, CUS "\n", 1);
-      seen_lf = 0;
-    }
+      if ((c == '.') && seen_lf) {
+        seen_lfdot = 1;
+        continue;
+      }
 
-    if (c == '\n') {
-      seen_lf = 1;
-      continue;
-    }
+      if (seen_lf) {
+        /* normal lf, just send it */
+        dk_message(dk_context, CUS "\n", 1);
+        seen_lf = 0;
+      }
 
-    /* write the char */
-    dk_message(dk_context, CUS &c, 1);
+      if (c == '\n') {
+        seen_lf = 1;
+        continue;
+      }
+
+      /* write the char */
+      dk_message(dk_context, CUS &c, 1);
+    }
   }
 
   /* Handle failed read above. */
index e6ad3c0c44b0c4ca94fe924c07b1314070e520e1..03d73f9ba28751a5b860991c137c591c3c74a1b4 100644 (file)
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/transport.c,v 1.16 2006/10/30 16:41:04 ph10 Exp $ */
+/* $Cambridge: exim/src/src/transport.c,v 1.17 2006/10/30 22:06:33 tom Exp $ */
 
 /*************************************************
 *     Exim - an Internet mail transport agent    *
@@ -13,6 +13,9 @@ transports. */
 
 #include "exim.h"
 
+#ifdef HAVE_LINUX_SENDFILE
+#include <sys/sendfile.h>
+#endif
 
 /* Structure for keeping list of addresses that have been added to
 Envelope-To:, in order to avoid duplication. */
@@ -983,10 +986,11 @@ dk_transport_write_message(address_item *addr, int fd, int options,
   int sread = 0;
   int wwritten = 0;
   uschar *dk_signature = NULL;
+  off_t size = 0;
 
-  (void)string_format(dk_spool_name, 256, "%s/input/%s/%s-K",
-          spool_directory, message_subdir, message_id);
-  dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_EXCL, SPOOL_MODE);
+  (void)string_format(dk_spool_name, 256, "%s/input/%s/%s-%d-K",
+          spool_directory, message_subdir, message_id, (int)getpid());
+  dk_fd = Uopen(dk_spool_name, O_RDWR|O_CREAT|O_TRUNC, SPOOL_MODE);
   if (dk_fd < 0)
     {
     /* Can't create spool file. Ugh. */
@@ -1052,9 +1056,35 @@ dk_transport_write_message(address_item *addr, int fd, int options,
       }
     }
 
-  /* Rewind file and send it down the original fd. */
+  /* Fetch file positition (the size) */
+  size = lseek(dk_fd,0,SEEK_CUR);
+
+  /* Rewind file */
   lseek(dk_fd, 0, SEEK_SET);
 
+#ifdef HAVE_LINUX_SENDFILE
+  /* We can use sendfile() to shove the file contents
+     to the socket. However only if we don't use TLS,
+     in which case theres another layer of indirection
+     before the data finally hits the socket. */
+  if (tls_active != fd)
+    {
+    ssize_t copied = 0;
+    off_t offset = 0;
+    while((copied >= 0) && (offset<size))
+      {
+      copied = sendfile(fd, dk_fd, &offset, (size - offset));
+      }
+    if (copied < 0)
+      {
+      save_errno = errno;
+      rc = FALSE;
+      }
+    goto CLEANUP;
+    }
+#endif
+
+  /* Send file down the original fd */
   while((sread = read(dk_fd,sbuf,2048)) > 0)
     {
     char *p = sbuf;
@@ -1087,7 +1117,6 @@ dk_transport_write_message(address_item *addr, int fd, int options,
     goto CLEANUP;
     }
 
-
   CLEANUP:
   /* unlink -K file */
   (void)close(dk_fd);