summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacek Masiulaniec <jacekm@cvs.openbsd.org>2010-04-21 17:50:29 +0000
committerJacek Masiulaniec <jacekm@cvs.openbsd.org>2010-04-21 17:50:29 +0000
commita52dbb97255938d67eae8ab413b242f7ec736bcd (patch)
tree132d4eabd632532db2f74255759f6e696946396e
parent1686f386c3cf839be61354349c3106ff2114a5eb (diff)
Fix pathetic performance when submitting large mails via /usr/sbin/sendmail,
caused by realloc() abuse.
-rw-r--r--usr.sbin/smtpd/enqueue.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/usr.sbin/smtpd/enqueue.c b/usr.sbin/smtpd/enqueue.c
index 9062e0b410a..cbaf2f1420a 100644
--- a/usr.sbin/smtpd/enqueue.c
+++ b/usr.sbin/smtpd/enqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: enqueue.c,v 1.32 2010/01/11 21:43:37 jacekm Exp $ */
+/* $OpenBSD: enqueue.c,v 1.33 2010/04/21 17:50:28 jacekm Exp $ */
/*
* Copyright (c) 2005 Henning Brauer <henning@bulabula.org>
@@ -47,7 +47,7 @@ void usage(void);
void sighdlr(int);
int main(int, char *[]);
void build_from(char *, struct passwd *);
-int parse_message(FILE *, int, int, struct buf *);
+int parse_message(FILE *, int, int, FILE *);
void parse_addr(char *, size_t, int);
void parse_addr_terminal(int);
char *qualify_addr(char *);
@@ -129,7 +129,7 @@ enqueue(int argc, char *argv[])
int i, ch, tflag = 0, noheader;
char *fake_from = NULL;
struct passwd *pw;
- struct buf *body;
+ FILE *fp;
bzero(&msg, sizeof(msg));
time(&timestamp);
@@ -191,17 +191,17 @@ enqueue(int argc, char *argv[])
signal(SIGALRM, sighdlr);
alarm(300);
+ fp = tmpfile();
+ if (fp == NULL)
+ err(1, "tmpfile");
+ noheader = parse_message(stdin, fake_from == NULL, tflag, fp);
+
if ((msg.fd = open_connection()) == -1)
errx(1, "server too busy");
/* init session */
- msg.pcb = client_init(msg.fd, open("/dev/null", O_RDONLY), "localhost",
- verbose);
-
- /* parse message */
- if ((body = buf_dynamic(0, SIZE_T_MAX)) == NULL)
- err(1, "buf_dynamic failed");
- noheader = parse_message(stdin, fake_from == NULL, tflag, body);
+ rewind(fp);
+ msg.pcb = client_init(msg.fd, fileno(fp), "localhost", verbose);
/* set envelope from */
client_sender(msg.pcb, "%s", msg.from);
@@ -232,9 +232,6 @@ enqueue(int argc, char *argv[])
if (noheader)
client_printf(msg.pcb, "\n");
- client_printf(msg.pcb, "%.*s", buf_size(body), body->buf);
- buf_free(body);
-
alarm(0);
event_init();
session_socket_blockmode(msg.fd, BM_NONBLOCK);
@@ -325,7 +322,7 @@ build_from(char *fake_from, struct passwd *pw)
}
int
-parse_message(FILE *fin, int get_from, int tflag, struct buf *body)
+parse_message(FILE *fin, int get_from, int tflag, FILE *fout)
{
char *buf;
size_t len;
@@ -339,6 +336,8 @@ parse_message(FILE *fin, int get_from, int tflag, struct buf *body)
err(1, "fgetln");
if (buf == NULL && feof(fin))
break;
+ if (buf == NULL || len < 1)
+ err(1, "fgetln weird");
/* account for \r\n linebreaks */
if (len >= 2 && buf[len - 2] == '\r' && buf[len - 1] == '\n')
@@ -347,9 +346,6 @@ parse_message(FILE *fin, int get_from, int tflag, struct buf *body)
if (len == 1 && buf[0] == '\n') /* end of header */
header_done = 1;
- if (buf == NULL || len < 1)
- err(1, "fgetln weird");
-
if (!WSP(buf[0])) { /* whitespace -> continuation */
if (cur == HDR_FROM)
parse_addr_terminal(1);
@@ -369,10 +365,11 @@ parse_message(FILE *fin, int get_from, int tflag, struct buf *body)
header_seen = 1;
if (cur != HDR_BCC) {
- if (buf_add(body, buf, len) < 0)
- err(1, "buf_add failed");
- if (buf[len - 1] != '\n' && buf_add(body, "\n", 1) < 0)
- err(1, "buf_add failed");
+ fprintf(fout, "%.*s", (int)len, buf);
+ if (buf[len - 1] != '\n')
+ fputc('\n', fout);
+ if (ferror(fout))
+ err(1, "write error");
}
/*