changeset 174:8a565328fa73

Instead of reading 1 line at a time in mlmmj-send everytime we send the mail, mmap it once, and pass the pointer to the send function which writes one line at a time with proper \n -> \r\n and '.' -> '..' conversion.
author mmj
date Sat, 05 Jun 2004 23:49:11 +1000
parents c91c37f083a6
children b26303f1b442
files src/mail-functions.c src/mlmmj-send.c
diffstat 2 files changed, 58 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/src/mail-functions.c	Sat Jun 05 23:48:07 2004 +1000
+++ b/src/mail-functions.c	Sat Jun 05 23:49:11 2004 +1000
@@ -6,8 +6,6 @@
  * Public License as described at http://www.gnu.org/licenses/gpl.txt
  */
 
-#include "mail-functions.h"
-#include "wrappers.h"
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -17,9 +15,10 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
-#include <sys/stat.h>
 #include <fcntl.h>
 
+#include "mail-functions.h"
+#include "wrappers.h"
 #include "log_error.h"
 
 /* "HELO \r\n " has length 7 */
@@ -101,63 +100,31 @@
 }
 
 
-int write_mailbody_from_fd(int sockfd, int fd)
+int write_mailbody_from_map(int sockfd, char *mapstart, size_t size)
 {
-	char buf[WRITE_BUFSIZE+3];
-	size_t len, bytes_written;
-	char *bufp;
-	int full_line = 1;  /* true, if last write included a newline */
-	
-	/* Zero the buffer */
-	memset(buf, 0, sizeof(buf));
-	
-	/* Read from beginning of the file */
-
-	if(lseek(fd, 0L, SEEK_SET) < 0) {
-		log_error(LOG_ARGS, "lseek() failed");
-		return errno;
-	}
-	
-	/* keep writing chunks of line (max WRITE_BUFSIZE) */
-	for(;;) {
-		bufp = buf+1;
-
-		len = read(fd, bufp, WRITE_BUFSIZE);
-
-		if(len == 0)
-			return 0;
+	char *cur, *next;
+	char newlinebuf[3];
+	size_t len;
 			
-		if(len < 0) {
-			if (errno == EINTR) {
-				continue;
-			} else {
-				return errno;
-			}
-		}
-
-		/* fix "dot lines" */
-		if(full_line && (bufp[0] == '.')) {
-			*(--bufp) = '.';
-			len++;
+	for(next = cur = mapstart; next < mapstart + size; next++) {
+		if(*next == '\n') {
+			if(writen(sockfd, cur, next - cur) < 0) {
+				log_error(LOG_ARGS, "Could not write mail");
+				return -1;
 		}
-
-		/* fix newlines */
-		if((len > 0) && (bufp[len-1] == '\n')) {
-			bufp[len-1] = '\r';
-			bufp[len] = '\n';
-			bufp[len+1] = 0;
-			len++;
-			full_line = 1;
-		} else {
-			full_line = 0;
+			newlinebuf[0] = '\r';
+			newlinebuf[1] = '\n';
+			len = 2;
+			if(*(next+1) == '.') {
+				newlinebuf[2] = '.';
+				len = 3;
 		}
-
-#if 0
-		fprintf(stderr, "write_mailbody_from_file = [%s]\n", bufp);
-#endif
-		bytes_written = writen(sockfd, bufp, len);
-		if(bytes_written < 0 )
-			return errno;
+			if(writen(sockfd, newlinebuf, len) < 0) {
+				log_error(LOG_ARGS, "Could not write mail");
+				return -1;
+			}
+			cur = next + 1;
+		}
 	}
 
 	return 0;
--- a/src/mlmmj-send.c	Sat Jun 05 23:48:07 2004 +1000
+++ b/src/mlmmj-send.c	Sat Jun 05 23:49:11 2004 +1000
@@ -11,7 +11,6 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
-#include <strings.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/types.h>
@@ -21,6 +20,7 @@
 #include <libgen.h>
 #include <syslog.h>
 #include <stdarg.h>
+#include <sys/mman.h>
 
 #include "mlmmj-send.h"
 #include "mlmmj.h"
@@ -141,7 +141,7 @@
 }
 
 int send_mail(int sockfd, const char *from, const char *to,
-	      const char *replyto, int mailfd,
+	      const char *replyto, char *mailmap, size_t mailsize,
 	      const char *listdir, const char *mlmmjbounce)
 {
 	int retval = 0;
@@ -206,7 +206,7 @@
 		}
 	}
 
-	retval = write_mailbody_from_fd(sockfd, mailfd);
+	retval = write_mailbody_from_map(sockfd, mailmap, mailsize);
 	if(retval) {
 		log_error(LOG_ARGS, "Could not write mailbody\n");
 		return retval;
@@ -279,9 +279,9 @@
 }
 
 int send_mail_many(int sockfd, const char *from, const char *replyto,
-		   int mailfd, int subfd, const char *listaddr,
-		   const char *archivefilename, const char *listdir,
-		   const char *mlmmjbounce)
+		   char *mailmap, size_t mailsize, int subfd,
+		   const char *listaddr, const char *archivefilename,
+		   const char *listdir, const char *mlmmjbounce)
 {
 	int sendres = 0, addrfd;
 	char *bounceaddr, *addr, *index, *dirname, *addrfilename;
@@ -291,12 +291,12 @@
 		chomp(addr);
 		if(from)
 			sendres = send_mail(sockfd, from, addr, replyto,
-					    mailfd, listdir, NULL);
+					    mailmap, mailsize, listdir, NULL);
 		else {
 			bounceaddr = bounce_from_adr(addr, listaddr,
 						     archivefilename);
 			sendres = send_mail(sockfd, bounceaddr, addr, replyto,
-				  mailfd, listdir, mlmmjbounce);
+				  mailmap, mailsize, listdir, mlmmjbounce);
 			free(bounceaddr);
 		}
 		if(sendres && listaddr && archivefilename) {
@@ -378,9 +378,10 @@
 	char *replyto = NULL, *bounceaddr = NULL, *to_addr = NULL;
 	char *relayhost = NULL, *archivefilename = NULL, *tmpstr;
 	char *listctrl = NULL, *subddirname = NULL, *listdir = NULL;
-	char *mlmmjbounce = NULL, *bindir;
+	char *mlmmjbounce = NULL, *bindir, *mailmap;
 	DIR *subddir;
 	struct dirent *dp;
+	struct stat st;
 	
 	log_set_name(argv[0]);
 
@@ -463,6 +464,17 @@
 		exit(EXIT_FAILURE);
 	}
 
+	if(fstat(mailfd, &st) < 0) {
+		log_error(LOG_ARGS, "Could not stat mailfd");
+		exit(EXIT_FAILURE);
+	}
+
+	mailmap = mmap(0, st.st_size, PROT_READ, MAP_SHARED, mailfd, 0);
+	if(mailmap == (void *)-1) {
+		log_error(LOG_ARGS, "Could not mmap mailfd");
+		exit(EXIT_FAILURE);
+	}
+
 	switch(listctrl[0]) {
 	case '1': /* A single mail is to be sent, do nothing */
 		break;
@@ -504,8 +516,8 @@
 	switch(listctrl[0]) {
 	case '1': /* A single mail is to be sent */
 		initsmtp(&sockfd, relayhost);
-		sendres = send_mail(sockfd, bounceaddr, to_addr,
-				replyto, mailfd, listdir, NULL);
+		sendres = send_mail(sockfd, bounceaddr, to_addr, replyto,
+				mailmap, st.st_size, listdir, NULL);
 		endsmtp(&sockfd);
 		if(sendres) {
 			/* error, so keep it in the queue */
@@ -546,16 +558,17 @@
 		break;
 	case '2': /* Moderators */
 		initsmtp(&sockfd, relayhost);
-		if(send_mail_many(sockfd, bounceaddr, NULL, mailfd, subfd,
-			       NULL, NULL, listdir, NULL))
+		if(send_mail_many(sockfd, bounceaddr, NULL, mailmap, st.st_size,
+				subfd, NULL, NULL, listdir, NULL))
 			close(sockfd);
 		else
 			endsmtp(&sockfd);
 		break;
 	case '3': /* resending earlier failed mails */
 		initsmtp(&sockfd, relayhost);
-		if(send_mail_many(sockfd, NULL, NULL, mailfd, subfd,
-				listaddr, mailfilename, listdir, mlmmjbounce))
+		if(send_mail_many(sockfd, NULL, NULL, mailmap, st.st_size,
+				subfd, listaddr, mailfilename, listdir,
+				mlmmjbounce))
 			close(sockfd);
 		else
 			endsmtp(&sockfd);
@@ -588,9 +601,9 @@
 			free(subfilename);
 
 			initsmtp(&sockfd, relayhost);
-			sendres = send_mail_many(sockfd, NULL, NULL, mailfd,
-					subfd, listaddr, archivefilename,
-					listdir, mlmmjbounce);
+			sendres = send_mail_many(sockfd, NULL, NULL, mailmap,
+					st.st_size, subfd, listaddr,
+					archivefilename, listdir, mlmmjbounce);
 			if (sendres) {
 				/* If send_mail_many() failed we close the
 				 * connection to the mail server in a brutal
@@ -606,12 +619,14 @@
 		break;
 	}
 	
+	munmap(mailmap, st.st_size);
+	close(mailfd);
+	
 	if(archive) {
 		rename(mailfilename, archivefilename);
 		free(archivefilename);
 	} else if(deletewhensent)
 		unlink(mailfilename);
 
-	close(mailfd);
 	return EXIT_SUCCESS;
 }