#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
+#include <time.h>
#include <unistd.h>
int mbox_write_pos;
int mbox_write_err;
-static void
+void
new_header(char* buf, struct list* h)
{
char* p;
new->value = xstrdup("");
else {
*p = 0;
- new->value = xstrdup(p+1);
+ if (*(p + 1) == ' ')
+ new->value = xstrdup(p + 2);
+ else
+ new->value = xstrdup(p + 1);
p = strrchr(new->value, '\n');
if (p && !*(p+1))
*p = 0;
list_add_last(h, &new->car);
}
+int gmc_pos;
+char gmc_buf[BUFSIZE];
+int gmc_init;
+int gmc_read;
+int gmc_unget;
+
+static int
+give_me_char(int fd)
+{
+ if (! gmc_init) {
+ gmc_pos = 0;
+ gmc_read = read(fd, gmc_buf, BUFSIZE);
+ gmc_init = 1;
+ gmc_unget = EOF;
+ curr_email_len = 0;
+ }
+
+ if (gmc_unget != EOF) {
+ int a = gmc_unget;
+ gmc_unget = EOF;
+ curr_email_len++;
+ return a;
+ }
+
+ if (! gmc_read) {
+ gmc_init = 0;
+ return EOF;
+ }
+
+ if (gmc_pos < gmc_read) {
+ curr_email_len++;
+ return gmc_buf[gmc_pos++];
+ } else {
+ gmc_pos = 0;
+ gmc_read = read(fd, gmc_buf, BUFSIZE);
+ if (! gmc_read) {
+ gmc_init = 0;
+ return EOF;
+ }
+ else {
+ curr_email_len++;
+ return gmc_buf[gmc_pos++];
+ }
+ }
+}
+
+static void
+unget_me(int c)
+{
+ gmc_unget = c;
+ curr_email_len--;
+}
+
struct list*
-make_hlist(void)
+make_hlist(int fd)
{
struct list* l = xmalloc(sizeof(struct list));
char* buf;
buf = xmalloc(BUFSIZE);
curbufsize = BUFSIZE;
- while ((c = getchar()) != EOF){
+ while ((c = give_me_char(fd)) != EOF){
if (c == '\r')
continue;
if (c == '\n'){
if (last == '\n')
break;
- if ((c = getchar()) != ' ' && c != '\t'){
+ if ((c = give_me_char(fd)) != ' ' && c != '\t'){
if (c != EOF)
- ungetc(c, stdin);
+ unget_me(c);
buf[i] = 0;
new_header(buf, l);
i = 0;
}
struct email*
-get_body(void)
+get_body(int rfd)
{
char* buf;
struct email* b;
b->fd = -1;
/* read mail body, if it is too big, try to make tmp file */
- while ((c = getchar()) != EOF){
+ while ((c = give_me_char(rfd)) != EOF){
buf[i++] = c;
if (i >= curbufsize - 1) {
tmpfile = xstrdup("/tmp/umpf.XXXXXX");
fd = mkstemp(tmpfile);
/* cannot create tmpfile, try to continue reading */
if (fd < 0)
- bye(EX_TEMPFAIL, "%m");
+ bye(EX_TEMPFAIL, "Cannot create temporary file: %m");
else {
will_save = 1;
b->body = NULL;
res = write(fd, buf, MAIL_LEN);
if (res < MAIL_LEN) {
unlink(b->tmpfile);
- bye(EX_TEMPFAIL, "%m");
+ bye(EX_TEMPFAIL, "Cannot write to remporary file: %m");
}
break;
}
/* save rest of the body to the tmpfile */
if (will_save) {
int j = 0;
- while ((c = getchar()) != EOF){
+ while ((c = give_me_char(rfd)) != EOF){
buf[j++] = c;
b->body_len++;
if (j >= MAIL_LEN) {
res = write(fd, buf, MAIL_LEN);
if (res < MAIL_LEN) {
unlink(b->tmpfile);
- bye(EX_TEMPFAIL, "%m");
+ bye(EX_TEMPFAIL, "Cannot write to temporary file: %m");
}
}
}
res = write(fd, buf, j);
if (res < j) {
unlink(b->tmpfile);
- bye(EX_TEMPFAIL, "%m");
+ bye(EX_TEMPFAIL, "Cannot write to temporary file: %m");
}
}
return b;
mbox_write_buf[mbox_write_pos++] = c;
}
+int email_pos;
+int headers_sent;
+int email_opened;
+
+void
+open_email(void)
+{
+ email_pos = 0;
+ headers_sent = 0;
+ email_opened = 1;
+}
+
+char*
+read_email(struct email* em)
+{
+ char* buf;
+ int r, pos;
+
+ if (! email_opened) {
+ chars_written = 0;
+ return NULL;
+ }
+
+ if (! headers_sent) {
+ struct hlist* ph;
+ int curbufsize = BUFSIZE;
+ buf = xmalloc(BUFSIZE);
+ pos = 0;
+
+ LIST_FOREACH(ph, em->headers){
+ int needed = strlen(ph->name) + strlen(ph->value) + 4;
+ if (curbufsize < pos + needed)
+ buf = xrealloc(buf, curbufsize*=2);
+ strcpy(buf + pos, ph->name);
+ pos += strlen(ph->name);
+ buf[pos++] = ':';
+ buf[pos++] = ' ';
+ strcpy(buf + pos, ph->value);
+ pos += strlen(ph->value);
+ buf[pos++] = '\n';
+
+ }
+ buf[pos++] = '\n';
+ headers_sent = 1;
+ chars_written = pos;
+ return buf;
+ }
+
+ if (em->body) {
+ buf = xstrdup(em->body);
+ chars_written = em->body_len;
+ //printf("%d: %s\n", em->body_len, em->body);
+ email_opened = 0;
+ return buf;
+ }
+
+ if (! email_pos)
+ lseek(em->fd, 0, SEEK_SET);
+
+ buf = xmalloc(MAIL_LEN + 1);
+ r = read(em->fd, buf, MAIL_LEN);
+ if (r < MAIL_LEN)
+ email_opened = 0;
+ chars_written = r;
+
+ return buf;
+}
+
+int
+write_email_to_fd(int fd, struct email* email)
+{
+ char* buf;
+ int wr;
+
+ open_email();
+ do {
+ buf = read_email(email);
+ wr = write(fd, buf, chars_written);
+ if (wr < chars_written)
+ return 1;
+ } while (chars_written);
+
+ return 0;
+}
+
/* try to copy e-mail to mailbox, if it fails,
truncate mailbox to the original size */
static int
mbox_write_err = 0;
mbox_write_pos = 0;
- /* headers */
+ /* From line */
struct hlist* ph;
+ int i, len;
+ char* fromline;
+ char* from = NULL;
+ time_t t;
+ time(&t);
+ char* date = ctime(&t);
+ int datelen = strlen(date);
+
+ LIST_FOREACH(ph, email->headers) {
+ if (!strcasecmp(ph->name, "From")) {
+ from = ph->value;
+ break;
+ }
+ }
+ len = 5 + datelen + 1;
+ if (from)
+ len += strlen(from);
+
+ fromline = xmalloc(len);
+ if (from)
+ sprintf(fromline, "From %s %s", from, date);
+ else
+ sprintf(fromline, "From %s", date);
+
+ len = strlen(fromline);
+ for (i = 0; i < len; i++)
+ write_char_to_mailbox(fromline[i], fd);
+
+ /* headers */
char* pc;
LIST_FOREACH(ph, email->headers){
for (pc = ph->name; *pc; pc++)
write_char_to_mailbox(*pc, fd);
write_char_to_mailbox(':', fd);
+ write_char_to_mailbox(' ', fd);
for (pc = ph->value; *pc; pc++)
write_char_to_mailbox(*pc, fd);
write_char_to_mailbox('\n', fd);
}
write_char_to_mailbox('\n', fd);
- /* body */
- /* FIXME: do not forget change Content-Length */
if (email->body) {
for (pc = email->body; pc < email->body + email->body_len; pc++){
write_char_to_mailbox(*pc, fd);
return 0;
}
-int
-write_email_to_fd(int fd, struct email* email)
-{
- int written;
-
- /* headers */
- struct hlist* ph;
- LIST_FOREACH(ph, email->headers){
- written = write(fd, ph->name, strlen(ph->name));
- if (written < (ssize_t) strlen(ph->name))
- return 1;
- written = write(fd, ":", 1);
- if (written < 1)
- return 1;
- written = write(fd, ph->value, strlen(ph->value));
- if (written < (ssize_t) strlen(ph->value))
- return 1;
- written = write(fd, "\n", 1);
- if (written < 1)
- return 1;
- }
- written = write(fd, "\n", 1);
- if (written < 1)
- return 1;
-
- /* body */
- if (email->body) {
- written = write(fd, email->body, email->body_len);
- if (written < email->body_len)
- return 1;
- } else {
- char buf[MAIL_LEN];
- int i;
- 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?
- write(fd, buf, len);
- }
- }
-
- return 0;
-}
-
int
deliver_local_email(char* folder, struct email* email)
{