Commit f24df125 f24df125b4a5f7e29eee39e89127871a38856281 by Sergey Poznyakoff

Fixes in stream subsystem. Rewrite and optimize maidag lmtp mode using streams.

* libmailutils/file_stream.c (mu_fd_stream_create): Mark stream as
open, do not call mu_stream_open explicitly.
* libmailutils/message_stream.c (mu_stream_to_message): Bugfixes,
wrong owner given to mu_envelope_set_ calls.
* libmailutils/stream.c (_MU_STR_FLUSH_ALL)
(_MU_STR_FLUSH_KEEP): New macros for _stream_flush_buffer.
(_stream_flush_buffer): Change the meaning of the last argument.
All callers updated.
(mu_stream_seek): Fix operation with MU_SEEK_END.
Call _mu_stream_cleareof on success.
(mu_stream_read): Call _stream_flush_buffer in buffered mode.
(mu_stream_getdelim, mu_stream_readdelim): Call _stream_flush_buffer.
* libmailutils/streamcpy.c (mu_stream_copy): Reset size if mu_stream_seek
fails.
* libmailutils/temp_file_stream.c (mu_temp_file_stream_create): Set
full buffering mode by default.

* maidag/mailtmp.c: Remove.
* maidag/Makefile.am (maidag_SOURCES): Remove mailtmp.c
* po/POTFILES.in: Likewise.
* maidag/deliver.c (make_tmp): Rewrite.  Return mu_mailbox_t.
All callers changed.
* maidag/lmtp.c (lmtp_transcript): Remove static.
(lmpt_transcript): New function.
(lmtp_reply): Use mu_stream_t instead of FILE.
(xlatnl): Remove.  Superseded by mu_rtrim_cset and family.
(mtmp, mbox): Remove globals.
(mesg): New global.
(cfun_unknown, cfun_mail_from, cfun_rcpt_to)
(dot_temp_fail, dot_deliver, cfun_rset)
(cfun_lhlo, cfun_quit, cfun_help): Use mu_stream_t instead of FILE.
(cfun_data): Rewrite.
(cfun_dot): Remove.
(to_fgets): Rewrite using mu_stream_t.
(lmtp_loop): Change signature. Rewrite using mu_stream_t.
(lmtp_connection, maidag_lmtp_server): Update accordingly.
* maidag/maidag.c (maidag_transcript): New global.
(options, parse_opt): New option --transcript.
* maidag/maidag.h (maidag_transcript): New extern.
(mail_tmp_begin, mail_tmp_add_line, mail_tmp_finish)
(mail_tmp_destroy): Remove.
1 parent 6b7badca
...@@ -390,15 +390,11 @@ mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags) ...@@ -390,15 +390,11 @@ mu_fd_stream_create (mu_stream_t *pstream, char *filename, int fd, int flags)
390 struct _mu_file_stream *fstr; 390 struct _mu_file_stream *fstr;
391 int rc = _mu_file_stream_create (&fstr, 391 int rc = _mu_file_stream_create (&fstr,
392 sizeof (struct _mu_file_stream), 392 sizeof (struct _mu_file_stream),
393 filename, fd, flags); 393 filename, fd, flags|_MU_STR_OPEN);
394 if (rc == 0) 394 if (rc == 0)
395 { 395 {
396 mu_stream_t stream = (mu_stream_t) fstr; 396 mu_stream_t stream = (mu_stream_t) fstr;
397 mu_stream_set_buffer (stream, mu_buffer_full, 0); 397 mu_stream_set_buffer (stream, mu_buffer_full, 0);
398 rc = mu_stream_open (stream);
399 if (rc)
400 mu_stream_unref (stream);
401 else
402 *pstream = stream; 398 *pstream = stream;
403 } 399 }
404 return rc; 400 return rc;
......
...@@ -414,8 +414,8 @@ mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg) ...@@ -414,8 +414,8 @@ mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg)
414 return rc; 414 return rc;
415 } 415 }
416 416
417 mu_envelope_set_date (env, _env_msg_date, msg); 417 mu_envelope_set_date (env, _env_msg_date, draftstream);
418 mu_envelope_set_sender (env, _env_msg_sender, msg); 418 mu_envelope_set_sender (env, _env_msg_sender, draftstream);
419 mu_message_set_envelope (msg, env, draftstream); 419 mu_message_set_envelope (msg, env, draftstream);
420 420
421 mu_body_create (&body, msg); 421 mu_body_create (&body, msg);
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
34 34
35 size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ; 35 size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ;
36 36
37 #define _MU_STR_FLUSH_ALL 0x01
38 #define _MU_STR_FLUSH_KEEP 0x02
39
37 #define _stream_event(stream, code, n, p) \ 40 #define _stream_event(stream, code, n, p) \
38 do \ 41 do \
39 { \ 42 { \
...@@ -167,7 +170,7 @@ _stream_buffer_full_p (struct _mu_stream *stream) ...@@ -167,7 +170,7 @@ _stream_buffer_full_p (struct _mu_stream *stream)
167 } 170 }
168 171
169 static int 172 static int
170 _stream_flush_buffer (struct _mu_stream *stream, int all) 173 _stream_flush_buffer (struct _mu_stream *stream, int flags)
171 { 174 {
172 int rc; 175 int rc;
173 char *start, *end; 176 char *start, *end;
...@@ -215,7 +218,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) ...@@ -215,7 +218,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
215 if (wrsize == 0) 218 if (wrsize == 0)
216 break; 219 break;
217 } 220 }
218 if ((all && wrsize) || wrsize == stream->level) 221 if (((flags & _MU_STR_FLUSH_ALL) && wrsize) ||
222 wrsize == stream->level)
219 { 223 {
220 rc = _stream_write_unbuffered (stream, 224 rc = _stream_write_unbuffered (stream,
221 stream->buffer, 225 stream->buffer,
...@@ -234,9 +238,10 @@ _stream_flush_buffer (struct _mu_stream *stream, int all) ...@@ -234,9 +238,10 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
234 stream->level = stream->pos = wrsize; 238 stream->level = stream->pos = wrsize;
235 return 0; 239 return 0;
236 } 240 }
241 _stream_clrflag (stream, _MU_STR_DIRTY);
237 } 242 }
238 243
239 _stream_clrflag (stream, _MU_STR_DIRTY); 244 if (!(flags & _MU_STR_FLUSH_KEEP))
240 stream->pos = stream->level = 0; 245 stream->pos = stream->level = 0;
241 return 0; 246 return 0;
242 } 247 }
...@@ -400,8 +405,8 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -400,8 +405,8 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
400 case MU_SEEK_END: 405 case MU_SEEK_END:
401 rc = mu_stream_size (stream, &size); 406 rc = mu_stream_size (stream, &size);
402 if (rc) 407 if (rc)
403 return mu_stream_seterr (stream, rc, 1); 408 return rc;
404 offset += size + stream->pos; 409 offset += size;
405 break; 410 break;
406 411
407 default: 412 default:
...@@ -414,7 +419,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -414,7 +419,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
414 || offset < stream->offset 419 || offset < stream->offset
415 || offset > stream->offset + stream->level)) 420 || offset > stream->offset + stream->level))
416 { 421 {
417 if ((rc = _stream_flush_buffer (stream, 1))) 422 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
418 return rc; 423 return rc;
419 rc = stream->seek (stream, offset, &stream->offset); 424 rc = stream->seek (stream, offset, &stream->offset);
420 if (rc == ESPIPE) 425 if (rc == ESPIPE)
...@@ -426,6 +431,8 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -426,6 +431,8 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
426 else if (stream->buftype != mu_buffer_none) 431 else if (stream->buftype != mu_buffer_none)
427 stream->pos = offset - stream->offset; 432 stream->pos = offset - stream->offset;
428 433
434 _mu_stream_cleareof (stream);
435
429 if (pres) 436 if (pres)
430 *pres = stream->offset + stream->pos; 437 *pres = stream->offset + stream->pos;
431 return 0; 438 return 0;
...@@ -469,7 +476,7 @@ _stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres) ...@@ -469,7 +476,7 @@ _stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres)
469 { 476 {
470 for (pos = 0;;) 477 for (pos = 0;;)
471 { 478 {
472 if ((rc = _stream_flush_buffer (stream, 1))) 479 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
473 return rc; 480 return rc;
474 if (stream->pos == stream->level) 481 if (stream->pos == stream->level)
475 { 482 {
...@@ -693,10 +700,15 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread) ...@@ -693,10 +700,15 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
693 { 700 {
694 char *bufp = buf; 701 char *bufp = buf;
695 size_t nbytes = 0; 702 size_t nbytes = 0;
703 int rc;
704
705 if ((rc = _stream_flush_buffer (stream,
706 _MU_STR_FLUSH_ALL|_MU_STR_FLUSH_KEEP)))
707 return rc;
708
696 while (size) 709 while (size)
697 { 710 {
698 size_t n; 711 size_t n;
699 int rc;
700 712
701 if (stream->pos == stream->level) 713 if (stream->pos == stream->level)
702 { 714 {
...@@ -824,7 +836,12 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size, ...@@ -824,7 +836,12 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
824 rc = _stream_readdelim (stream, buf, size, delim, pread); 836 rc = _stream_readdelim (stream, buf, size, delim, pread);
825 } 837 }
826 else 838 else
839 {
840 if ((rc = _stream_flush_buffer (stream,
841 _MU_STR_FLUSH_ALL|_MU_STR_FLUSH_KEEP)))
842 return rc;
827 rc = _stream_scandelim (stream, buf, size, delim, pread); 843 rc = _stream_scandelim (stream, buf, size, delim, pread);
844 }
828 return rc; 845 return rc;
829 } 846 }
830 847
...@@ -850,6 +867,10 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize, ...@@ -850,6 +867,10 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
850 _stream_init (stream); 867 _stream_init (stream);
851 } 868 }
852 869
870 if ((rc = _stream_flush_buffer (stream,
871 _MU_STR_FLUSH_ALL|_MU_STR_FLUSH_KEEP)))
872 return rc;
873
853 if (lineptr == NULL || n == 0) 874 if (lineptr == NULL || n == 0)
854 { 875 {
855 char *new_lineptr; 876 char *new_lineptr;
...@@ -997,7 +1018,7 @@ mu_stream_flush (mu_stream_t stream) ...@@ -997,7 +1018,7 @@ mu_stream_flush (mu_stream_t stream)
997 return MU_ERR_NOT_OPEN; 1018 return MU_ERR_NOT_OPEN;
998 _stream_init (stream); 1019 _stream_init (stream);
999 } 1020 }
1000 rc = _stream_flush_buffer (stream, 1); 1021 rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL);
1001 if (rc) 1022 if (rc)
1002 return rc; 1023 return rc;
1003 if ((stream->flags & _MU_STR_WRT) && stream->flush) 1024 if ((stream->flags & _MU_STR_WRT) && stream->flush)
...@@ -1031,6 +1052,7 @@ int ...@@ -1031,6 +1052,7 @@ int
1031 mu_stream_size (mu_stream_t stream, mu_off_t *psize) 1052 mu_stream_size (mu_stream_t stream, mu_off_t *psize)
1032 { 1053 {
1033 int rc; 1054 int rc;
1055 mu_off_t size;
1034 1056
1035 if (!(stream->flags & _MU_STR_OPEN)) 1057 if (!(stream->flags & _MU_STR_OPEN))
1036 { 1058 {
...@@ -1040,7 +1062,13 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) ...@@ -1040,7 +1062,13 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
1040 } 1062 }
1041 if (!stream->size) 1063 if (!stream->size)
1042 return mu_stream_seterr (stream, ENOSYS, 0); 1064 return mu_stream_seterr (stream, ENOSYS, 0);
1043 rc = stream->size (stream, psize); 1065 rc = stream->size (stream, &size);
1066 if (rc == 0)
1067 {
1068 if (stream->buftype != mu_buffer_none && stream->offset == size)
1069 size += stream->level;
1070 *psize = size;
1071 }
1044 return mu_stream_seterr (stream, rc, rc != 0); 1072 return mu_stream_seterr (stream, rc, rc != 0);
1045 } 1073 }
1046 1074
...@@ -1118,7 +1146,7 @@ mu_stream_truncate (mu_stream_t stream, mu_off_t size) ...@@ -1118,7 +1146,7 @@ mu_stream_truncate (mu_stream_t stream, mu_off_t size)
1118 { 1146 {
1119 int rc; 1147 int rc;
1120 1148
1121 if ((rc = _stream_flush_buffer (stream, 1))) 1149 if ((rc = _stream_flush_buffer (stream, _MU_STR_FLUSH_ALL)))
1122 return rc; 1150 return rc;
1123 return stream->truncate (stream, size); 1151 return stream->truncate (stream, size);
1124 } 1152 }
......
...@@ -72,6 +72,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, ...@@ -72,6 +72,7 @@ mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size,
72 case EACCES: 72 case EACCES:
73 mu_stream_clearerr (src); 73 mu_stream_clearerr (src);
74 case ENOSYS: 74 case ENOSYS:
75 size = 0;
75 break; 76 break;
76 77
77 default: 78 default:
......
...@@ -66,7 +66,10 @@ mu_temp_file_stream_create (mu_stream_t *pstream, const char *dir) ...@@ -66,7 +66,10 @@ mu_temp_file_stream_create (mu_stream_t *pstream, const char *dir)
66 if (rc) 66 if (rc)
67 mu_stream_unref (stream); 67 mu_stream_unref (stream);
68 else 68 else
69 {
70 mu_stream_set_buffer (stream, mu_buffer_full, 0);
69 *pstream = stream; 71 *pstream = stream;
70 } 72 }
73 }
71 return 0; 74 return 0;
72 } 75 }
......
...@@ -26,7 +26,6 @@ maidag_SOURCES=\ ...@@ -26,7 +26,6 @@ maidag_SOURCES=\
26 lmtp.c\ 26 lmtp.c\
27 maidag.c\ 27 maidag.c\
28 maidag.h\ 28 maidag.h\
29 mailtmp.c\
30 mailquota.c\ 29 mailquota.c\
31 python.c\ 30 python.c\
32 sieve.c\ 31 sieve.c\
......
...@@ -19,26 +19,110 @@ ...@@ -19,26 +19,110 @@
19 19
20 #include "maidag.h" 20 #include "maidag.h"
21 21
22 void 22 static mu_mailbox_t
23 make_tmp (const char *from, mu_mailbox_t *mbox) 23 make_tmp (const char *from)
24 { 24 {
25 struct mail_tmp *mtmp;
26 char *buf = NULL;
27 size_t n = 0;
28 int rc; 25 int rc;
26 mu_stream_t in, out;
27 char *buf = NULL;
28 size_t size = 0, n;
29 mu_mailbox_t mbox;
29 30
30 if (mail_tmp_begin (&mtmp, from)) 31 rc = mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_READ);
32 if (rc)
33 {
34 mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create",
35 "MU_STDIN_FD", rc);
31 exit (EX_TEMPFAIL); 36 exit (EX_TEMPFAIL);
37 }
32 38
33 while (getline (&buf, &n, stdin) > 0) 39 rc = mu_temp_file_stream_create (&out, NULL);
34 if ((rc = mail_tmp_add_line (mtmp, buf, strlen (buf)))) 40 if (rc)
35 break; 41 {
42 maidag_error (_("unable to open temporary file: %s"), mu_strerror (rc));
43 exit (EX_TEMPFAIL);
44 }
45
46 rc = mu_stream_getline (in, &buf, &size, &n);
47 if (rc)
48 {
49 maidag_error (_("read error: %s"), mu_strerror (rc));
50 mu_stream_destroy (&in);
51 mu_stream_destroy (&out);
52 exit (EX_TEMPFAIL);
53 }
54 if (n == 0)
55 {
56 maidag_error (_("unexpected EOF on input"));
57 mu_stream_destroy (&in);
58 mu_stream_destroy (&out);
59 exit (EX_TEMPFAIL);
60 }
61
62 if (n >= 5 && memcmp (buf, "From ", 5))
63 {
64 struct mu_auth_data *auth = NULL;
65 if (!from)
66 {
67 auth = mu_get_auth_by_uid (getuid ());
68 if (auth)
69 from = auth->name;
70 }
71 if (from)
72 {
73 time_t t;
74
75 time (&t);
76 mu_stream_printf (out, "From %s %s", from, ctime (&t));
77 }
78 else
79 {
80 maidag_error (_("cannot determine sender address"));
81 mu_stream_destroy (&in);
82 mu_stream_destroy (&out);
83 exit (EX_TEMPFAIL);
84 }
85 if (auth)
86 mu_auth_data_free (auth);
87 }
88
89 mu_stream_write (out, buf, n, NULL);
36 free (buf); 90 free (buf);
37 if (rc == 0) 91
38 rc = mail_tmp_finish (mtmp, mbox); 92 rc = mu_stream_copy (out, in, 0, NULL);
39 mail_tmp_destroy (&mtmp); 93
94 mu_stream_destroy (&in);
95 if (rc)
96 {
97 maidag_error (_("copy error: %s"), mu_strerror (rc));
98 mu_stream_destroy (&out);
99 exit (EX_TEMPFAIL);
100 }
101
102 mu_stream_flush (out);
103 if ((rc = mu_mailbox_create (&mbox, "mbox:/dev/null"))
104 || (rc = mu_mailbox_open (mbox, MU_STREAM_READ))
105 || (rc = mu_mailbox_set_stream (mbox, out)))
106 {
107 maidag_error (_("error opening temporary file: %s"),
108 mu_strerror (rc));
109 mu_stream_destroy (&out);
110 exit (EX_TEMPFAIL);
111 }
112
113 rc = mu_mailbox_messages_count (mbox, &n);
40 if (rc) 114 if (rc)
115 {
116 errno = rc;
117 maidag_error (_("error creating temporary message: %s"),
118 mu_strerror (rc));
119 mu_stream_destroy (&out);
41 exit (EX_TEMPFAIL); 120 exit (EX_TEMPFAIL);
121 }
122
123 /* FIXME: mu_stream_unref (out); But mu_mailbox_set_stream
124 steals the reference */
125 return mbox;
42 } 126 }
43 127
44 int 128 int
...@@ -65,9 +149,7 @@ mda (mu_mailbox_t mbx, char *username) ...@@ -65,9 +149,7 @@ mda (mu_mailbox_t mbx, char *username)
65 int 149 int
66 maidag_stdio_delivery (int argc, char **argv) 150 maidag_stdio_delivery (int argc, char **argv)
67 { 151 {
68 mu_mailbox_t mbox; 152 mu_mailbox_t mbox = make_tmp (sender_address);
69
70 make_tmp (sender_address, &mbox);
71 153
72 if (multiple_delivery) 154 if (multiple_delivery)
73 multiple_delivery = argc > 1; 155 multiple_delivery = argc > 1;
......
...@@ -53,6 +53,7 @@ int lmtp_mode; ...@@ -53,6 +53,7 @@ int lmtp_mode;
53 int url_option; 53 int url_option;
54 char *lmtp_url_string; 54 char *lmtp_url_string;
55 int reuse_lmtp_address = 1; 55 int reuse_lmtp_address = 1;
56 int maidag_transcript;
56 57
57 const char *program_version = "maidag (" PACKAGE_STRING ")"; 58 const char *program_version = "maidag (" PACKAGE_STRING ")";
58 static char doc[] = 59 static char doc[] =
...@@ -72,6 +73,7 @@ static char args_doc[] = N_("[recipient...]"); ...@@ -72,6 +73,7 @@ static char args_doc[] = N_("[recipient...]");
72 #define LMTP_OPTION 258 73 #define LMTP_OPTION 258
73 #define FOREGROUND_OPTION 260 74 #define FOREGROUND_OPTION 260
74 #define URL_OPTION 261 75 #define URL_OPTION 261
76 #define TRANSCRIPT_OPTION 262
75 77
76 static struct argp_option options[] = 78 static struct argp_option options[] =
77 { 79 {
...@@ -94,6 +96,8 @@ static struct argp_option options[] = ...@@ -94,6 +96,8 @@ static struct argp_option options[] =
94 N_("enable debugging"), GRID + 1 }, 96 N_("enable debugging"), GRID + 1 },
95 { "stderr", STDERR_OPTION, NULL, 0, 97 { "stderr", STDERR_OPTION, NULL, 0,
96 N_("log to standard error"), GRID + 1 }, 98 N_("log to standard error"), GRID + 1 },
99 { "transcript", TRANSCRIPT_OPTION, NULL, 0,
100 N_("enable session transcript"), GRID + 1 },
97 #undef GRID 101 #undef GRID
98 102
99 #define GRID 2 103 #define GRID 2
...@@ -212,6 +216,10 @@ parse_opt (int key, char *arg, struct argp_state *state) ...@@ -212,6 +216,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
212 mu_argp_node_list_new (lst, "listen", arg); 216 mu_argp_node_list_new (lst, "listen", arg);
213 break; 217 break;
214 218
219 case TRANSCRIPT_OPTION:
220 maidag_transcript = 1;
221 break;
222
215 case 'r': 223 case 'r':
216 case 'f': 224 case 'f':
217 if (sender_address != NULL) 225 if (sender_address != NULL)
......
...@@ -142,6 +142,7 @@ extern char *lmtp_url_string; ...@@ -142,6 +142,7 @@ extern char *lmtp_url_string;
142 extern int reuse_lmtp_address; 142 extern int reuse_lmtp_address;
143 extern mu_list_t lmtp_groups; 143 extern mu_list_t lmtp_groups;
144 extern mu_acl_t maidag_acl; 144 extern mu_acl_t maidag_acl;
145 extern int maidag_transcript;
145 146
146 void close_fds (void); 147 void close_fds (void);
147 int switch_user_id (struct mu_auth_data *auth, int user); 148 int switch_user_id (struct mu_auth_data *auth, int user);
...@@ -160,12 +161,6 @@ int deliver (mu_message_t msg, char *name, char **errp); ...@@ -160,12 +161,6 @@ int deliver (mu_message_t msg, char *name, char **errp);
160 int sieve_test (struct mu_auth_data *auth, mu_message_t msg); 161 int sieve_test (struct mu_auth_data *auth, mu_message_t msg);
161 int check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest); 162 int check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest);
162 163
163 struct mail_tmp;
164 int mail_tmp_begin (struct mail_tmp **pmtmp, const char *from);
165 int mail_tmp_add_line (struct mail_tmp *mtmp, char *buf, size_t buflen);
166 int mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox);
167 void mail_tmp_destroy (struct mail_tmp **pmtmp);
168
169 enum maidag_forward_result 164 enum maidag_forward_result
170 { 165 {
171 maidag_forward_none, 166 maidag_forward_none,
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2009, 2010 Free
3 Software Foundation, Inc.
4
5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 GNU Mailutils is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Mailutils; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 MA 02110-1301 USA */
19
20 #include "maidag.h"
21
22 struct mail_tmp
23 {
24 mu_stream_t stream;
25 size_t line;
26 char *tempfile;
27 const char *from;
28 int had_nl;
29 };
30
31 int
32 mail_tmp_begin (struct mail_tmp **pmtmp, const char *from)
33 {
34 int status;
35 struct mail_tmp *mtmp = malloc (sizeof *mtmp);
36
37 if (!mtmp)
38 return ENOMEM;
39
40 memset (mtmp, 0, sizeof *mtmp);
41
42 mtmp->tempfile = mu_tempname (NULL);
43 if ((status = mu_file_stream_create (&mtmp->stream, mtmp->tempfile,
44 MU_STREAM_RDWR)))
45 {
46 free (mtmp);
47 maidag_error (_("unable to open temporary file: %s"),
48 mu_strerror (status));
49 return status;
50 }
51
52 mtmp->from = from;
53 *pmtmp = mtmp;
54 return 0;
55 }
56
57 int
58 mail_tmp_add_line (struct mail_tmp *mtmp, char *buf, size_t buflen)
59 {
60 int status = 0;
61
62 mtmp->line++;
63 if (mtmp->line == 1)
64 {
65 const char *from = mtmp->from;
66
67 if (buflen >= 5 && memcmp (buf, "From ", 5))
68 {
69 struct mu_auth_data *auth = NULL;
70 if (!from)
71 {
72 auth = mu_get_auth_by_uid (getuid ());
73 if (auth)
74 from = auth->name;
75 }
76 if (from)
77 {
78 time_t t;
79 char *envs;
80
81 time (&t);
82 asprintf (&envs, "From %s %s", from, ctime (&t));
83 status = mu_stream_write (mtmp->stream,
84 envs,
85 strlen (envs), NULL);
86 free (envs);
87 }
88 else
89 {
90 maidag_error (_("cannot determine sender address"));
91 return EINVAL;
92 }
93 if (auth)
94 mu_auth_data_free (auth);
95 }
96 }
97 else if (buflen >= 5 && !memcmp (buf, "From ", 5))
98 {
99 static char *escape = ">";
100 status = mu_stream_write (mtmp->stream, escape, 1, NULL);
101 }
102
103 if (!status)
104 status = mu_stream_write (mtmp->stream, buf, buflen, NULL);
105
106 if (status)
107 {
108 maidag_error (_("error writing temporary file: %s"),
109 mu_strerror (status));
110 mu_stream_destroy (&mtmp->stream);
111 }
112 mtmp->had_nl = buf[buflen-1] == '\n';
113 return status;
114 }
115
116 int
117 mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox)
118 {
119 int status;
120 static char *newline = "\n";
121 size_t n;
122
123 if (!mtmp->had_nl)
124 status = mu_stream_write (mtmp->stream, newline, 1, NULL);
125
126 status = mu_stream_write (mtmp->stream, newline, 1, NULL);
127 unlink (mtmp->tempfile);
128 free (mtmp->tempfile);
129 mtmp->tempfile = NULL;
130
131 if (status)
132 {
133 errno = status;
134 maidag_error (_("error writing temporary file: %s"),
135 mu_strerror (status));
136 mu_stream_destroy (&mtmp->stream);
137 return status;
138 }
139
140 mu_stream_flush (mtmp->stream);
141 if ((status = mu_mailbox_create (mbox, "mbox:/dev/null"))
142 || (status = mu_mailbox_open (*mbox, MU_STREAM_READ))
143 || (status = mu_mailbox_set_stream (*mbox, mtmp->stream)))
144 {
145 maidag_error (_("error opening temporary file: %s"),
146 mu_strerror (status));
147 mu_stream_destroy (&mtmp->stream);
148 return status;
149 }
150
151 status = mu_mailbox_messages_count (*mbox, &n);
152 if (status)
153 {
154 errno = status;
155 maidag_error (_("error creating temporary message: %s"),
156 mu_strerror (status));
157 mu_stream_destroy (&mtmp->stream);
158 return status;
159 }
160
161 mtmp->stream = NULL;
162 mtmp->line = 0;
163
164 return status;
165
166 }
167
168 void
169 mail_tmp_destroy (struct mail_tmp **pmtmp)
170 {
171 struct mail_tmp *mtmp = *pmtmp;
172
173 if (mtmp)
174 {
175 if (mtmp->tempfile)
176 {
177 unlink (mtmp->tempfile);
178 free (mtmp->tempfile);
179 }
180 mu_stream_destroy (&mtmp->stream);
181 free (*pmtmp);
182 *pmtmp = NULL;
183 }
184 }
185
186
187
...@@ -90,7 +90,6 @@ maidag/deliver.c ...@@ -90,7 +90,6 @@ maidag/deliver.c
90 maidag/lmtp.c 90 maidag/lmtp.c
91 maidag/maidag.c 91 maidag/maidag.c
92 maidag/mailquota.c 92 maidag/mailquota.c
93 maidag/mailtmp.c
94 maidag/script.c 93 maidag/script.c
95 94
96 mail/alias.c 95 mail/alias.c
......