#include <unistd.h>
#include "umpf.h"
+#define MAIL_LEN 65536
int curbufsize;
}
last = c;
}
- free(buf);
+ //free(buf);
return l;
}
{
char* buf;
struct email* b;
- int c;
+ int c, fd, cannot_save = 0;
+ int will_save = 0;
int i = 0;
- int curbufsize = BUFSIZE;
+ int j = 0;
+ int curbufsize = MAIL_LEN;
+ char* tmpfile;
+ int res;
+
+ buf = xmalloc(MAIL_LEN);
+ b = xmalloc(sizeof(struct email));
+ b->body = buf;
+ b->tmpfile = NULL;
+ b->fd = -1;
- buf = xmalloc(BUFSIZE);
+ /* read mail body, if it is too big, try to make tmp file */
while ((c = getchar()) != EOF){
buf[i++] = c;
-
- if (i >= curbufsize - 1)
- buf = xrealloc(buf, curbufsize *= 2);
+ if (i >= curbufsize - 1) {
+ if (cannot_save) {
+ buf = xrealloc(buf, curbufsize *= 2);
+ continue;
+ }
+ tmpfile = xstrdup("/tmp/umpf.XXXXXX");
+ fd = mkstemp(tmpfile);
+ /* cannot create tmpfile, try to continue reading */
+ if (fd < 0) {
+ buf = xrealloc(buf, curbufsize *= 2);
+ cannot_save = 1;
+ free(tmpfile);
+ continue;
+ } else {
+ will_save = 1;
+ b->body = NULL;
+ b->tmpfile = tmpfile;
+ b->fd = fd;
+ break;
+ }
+ }
}
-
- b = xmalloc(sizeof(struct email));
- b->body = buf;
b->body_len = i;
+ /* save rest of the body to the tmpfile */
+ if (will_save) {
+ while ((c = getchar()) != EOF){
+ buf[j++] = c;
+ b->body_len++;
+ if (j >= MAIL_LEN) {
+ j = 0;
+ res = write(fd, buf, MAIL_LEN);
+ if (res < MAIL_LEN) {
+ int missing = MAIL_LEN - res;
+ curbufsize = 2*b->body_len;
+ buf = xrealloc(buf, curbufsize);
+ // no point to check length here
+ read(fd, buf, b->body_len - missing);
+ unlink(b->tmpfile);
+ b->tmpfile = NULL;
+ b->fd = -1;
+ b->body = buf;
+ break;
+ }
+ }
+ }
+ /* could not write all the body to the tmpfile, try to read
+ the rest */
+ if (b->body) {
+ while ((c = getchar()) != EOF){
+ buf[j++] = c;
+ b->body_len++;
+ if (i >= curbufsize - 1) {
+ buf = xrealloc(buf, curbufsize *= 2);
+ }
+ }
+ }
+ }
return b;
}
write_char_to_mailbox('\n', fd);
/* body */
/* FIXME: do not forget change Content-Length */
- for (pc = email->body; pc < email->body + email->body_len; pc++){
- write_char_to_mailbox(*pc, fd);
- if (*pc == '\n'){
- if ((pc + 5 < email->body + email->body_len)
+ if (email->body) {
+ for (pc = email->body; pc < email->body + email->body_len; pc++){
+ write_char_to_mailbox(*pc, fd);
+ if (*pc == '\n'){
+ if ((pc + 5 < email->body + email->body_len)
+ && pc[1] == 'F' && pc[2] == 'r'
+ && pc[3] == 'o' && pc[4] == 'm'
+ && pc[5] == ' ')
+ write_char_to_mailbox('>', fd);
+ }
+ }
+ } else {
+ int i;
+ char buf[MAIL_LEN];
+ for(i = 0; i < email->body_len; i+=MAIL_LEN) {
+ int len = MAIL_LEN;
+ if (i >= email->body_len)
+ len = len - (i - email->body_len);
+ read(email->fd, buf, len); //FIXME: check it?
+ for (pc = buf; pc < buf + len; pc++) {
+ write_char_to_mailbox(*pc, fd);
+ if (*pc == '\n'){
+ if ((pc + 5 < email->body + email->body_len)
&& pc[1] == 'F' && pc[2] == 'r'
&& pc[3] == 'o' && pc[4] == 'm'
&& pc[5] == ' ')
- write_char_to_mailbox('>', fd);
+ write_char_to_mailbox('>', fd);
+ }
}
- }
+ }
+ }
flush_mbox_buffer(fd);
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
+#include <stdarg.h>
#include "cond.tab.h"
#include "umpf.h"
#define INT_TO_STRING_LEN ((sizeof(int)*4*CHAR_BIT)/10 + 6)
+static void __attribute__ ((noreturn))
+bye(int code, char* msg, ...)
+{
+ va_list args;
+
+ if (current_body->tmpfile)
+ unlink(current_body->tmpfile);
+
+ if (msg) {
+ va_start(args, msg);
+ vfprintf(stderr, msg, args);
+ fputc('\n', stderr);
+ va_end(args);
+ }
+ exit(code);
+}
+
static void
clear_var(int var)
{
modify_headers(current_headers, hash);
em.headers = copy_headers(current_headers);
- em.body_len = current_body->body_len;
- em.body = xmalloc(em.body_len);
- memcpy(em.body, current_body->body, em.body_len);
+ em.body_len = current_body->body_len;
+ em.fd = current_body->fd;
+ if (current_body->body) {
+ em.body = xmalloc(em.body_len);
+ memcpy(em.body, current_body->body, em.body_len);
+ em.tmpfile = NULL;
+ } else {
+ em.tmpfile = xstrdup(current_body->tmpfile);
+ em.body = NULL;
+ }
return em;
}
+static void
+destroy_email(struct email em)
+{
+ if (em.body)
+ free(em.body);
+ if(em.tmpfile)
+ free(em.tmpfile);
+}
+
static void
do_string_ternary_op(struct code* p)
{
res = deliver_local_email(where, &em);
- if (!copy)
- exit(-res);
+ destroy_email(em);
+
+ if (!copy) {
+ if (res)
+ bye(-res, "%m");
+ else
+ bye(0, NULL);
+ }
}
void
case OPC_CALL_EXT:
break;
case OPC_DISCARD:
- exit(0);
+ bye(0, NULL);
break;
}}
deliver(default_mailbox, 0, hash);