Commit 55e0fbee 55e0fbee9e680aa2572284e0ed265d28b3400558 by Sergey Poznyakoff

* Makefile.am, configure.ac: Add maidag.

* frm/common.c, imap4d/sync.c, libsieve/runtime.c,
mh/scan.c: Update declaration of observable actions  .
* imap4d/select.c, imap4d/status.c, mh/anno.c, mh/forw.c,
mh/repl.c: Use mu_mailbox_sync instead of
mu_mailbox_save_attributes.
* include/mailutils/mailbox.h (mu_mailbox_sync): New function.
(mu_mailbox_save_attributes): Deprecated.
* include/mailutils/message.h (mu_message_get_qid)
(mu_message_set_qid): New functions.
* include/mailutils/observer.h (MU_EVT_MESSAGE_APPEND): New event.
(mu_observer_set_action_data): New function. Registers
action-specific data.
(mu_observable_notify): Get call-specific data as the third
argument.
* include/mailutils/types.hin (mu_message_qid_t): New data type.
* libproto/imap/folder.c, libproto/imap/mbox.c,
libproto/include/amd.h, libproto/maildir/mbox.c,
libproto/mailer/sendmail.c, libproto/mailer/smtp.c,
libproto/mbox/mboxscan.c, libproto/mh/mbox.c,
libproto/nntp/mbox.c, libproto/pop/mbox.c, mailbox/folder.c,
mailbox/mailer.c : Update calls to mu_observable_notify.
* libproto/include/mailbox0.h (struct _mu_mailbox): Rename
_save_attributes to _sync.
* mailbox/amd.c: Likewise
(_quick_get_message): New member.
(MAILBOX_NOTIFY): Remove.
* libproto/include/message0.h (struct _mu_message): New member
_get_qid.
* libproto/include/observer0.h (struct _mu_observer): New member
_action_data.
* libproto/mbox/mbox.c: Implement mbox_message_qid. Update calls
to mu_observable_notify.
(mbox_append_message): Report MU_EVT_MESSAGE_APPEND
* mailbox/observer.c (mu_observer_destroy): Call _destroy with
_action_data as its third argument.
(mu_observer_action, mu_observable_notify): Takes third argument
(call data)
(mu_observer_set_action, mu_observer_set_destroy): Update signature.
(mu_observer_set_action_data): New function.

* libproto/mbox/mbox0.h, mail.local/main.c: Minor change.

* mail.local/Makefile.am (mail_local_LDADD): Add MU_LIB_MAILER

* mailbox/file_stream.c (_file_open): Fix handling of
MU_STREAM_APPEND. Remove assertion.

* mailbox/mailbox.c (mu_mailbox_quick_get_message): New function
(mu_mailbox_sync): New function
(mu_mailbox_get_size): Implement brute-force approach in case the
mailbox does not provide a method.

* mailbox/message.c (mu_message_get_qid, mu_message_set_qid): New
function.

* maildag/: New directory. A general-purpose mail delivery agent.
* maildag/deliver.c: New file.
* maildag/lmtp.c: New file.
* maildag/maidag.c: New file.
* maildag/maidag.h: New file.
* maildag/mailtmp.c: New file.
* maildag/mailquota.c: New file.
* maildag/script.c: New file.
* maildag/util.c: New file.
* maildag/Makefile.am: New file.
* maildag/.cvsignore: New file.
1 parent 60ae1cd2
1 2007-11-10 Sergey Poznyakoff <gray@gnu.org.ua>
2
3 * Makefile.am, configure.ac: Add maidag.
4 * frm/common.c, imap4d/sync.c, libsieve/runtime.c,
5 mh/scan.c: Update declaration of observable actions.
6 * imap4d/select.c, imap4d/status.c, mh/anno.c, mh/forw.c,
7 mh/repl.c: Use mu_mailbox_sync instead of
8 mu_mailbox_save_attributes.
9 * include/mailutils/mailbox.h (mu_mailbox_sync): New function
10 (mu_mailbox_save_attributes): Deprecated.
11 * include/mailutils/message.h (mu_message_get_qid)
12 (mu_message_set_qid): New functions.
13 * include/mailutils/observer.h (MU_EVT_MESSAGE_APPEND): New event.
14 (mu_observer_set_action_data): New function. Registers
15 action-specific data.
16 (mu_observable_notify): Get call-specific data as the third
17 argument.
18 * include/mailutils/types.hin (mu_message_qid_t): New data type.
19 * libproto/imap/folder.c, libproto/imap/mbox.c,
20 libproto/include/amd.h, libproto/maildir/mbox.c,
21 libproto/mailer/sendmail.c, libproto/mailer/smtp.c,
22 libproto/mbox/mboxscan.c, libproto/mh/mbox.c,
23 libproto/nntp/mbox.c, libproto/pop/mbox.c, mailbox/folder.c,
24 mailbox/mailer.c : Update calls to mu_observable_notify.
25 * libproto/include/mailbox0.h (struct _mu_mailbox): Rename
26 _save_attributes to _sync.
27 * mailbox/amd.c: Likewise.
28 (_quick_get_message): New member.
29 (MAILBOX_NOTIFY): Remove.
30 * libproto/include/message0.h (struct _mu_message): New member
31 _get_qid.
32 * libproto/include/observer0.h (struct _mu_observer): New member
33 _action_data.
34 * libproto/mbox/mbox.c: Implement mbox_message_qid. Update calls
35 to mu_observable_notify.
36 (mbox_append_message): Report MU_EVT_MESSAGE_APPEND.
37 * mailbox/observer.c (mu_observer_destroy): Call _destroy with
38 _action_data as its third argument.
39 (mu_observer_action, mu_observable_notify): Takes third argument
40 (call data)
41 (mu_observer_set_action, mu_observer_set_destroy): Update signature.
42 (mu_observer_set_action_data): New function.
43
44 * libproto/mbox/mbox0.h, mail.local/main.c: Minor change
45
46 * mail.local/Makefile.am (mail_local_LDADD): Add MU_LIB_MAILER
47
48 * mailbox/file_stream.c (_file_open): Fix handling of
49 MU_STREAM_APPEND. Remove assertion.
50
51 * mailbox/mailbox.c (mu_mailbox_quick_get_message): New function
52 (mu_mailbox_sync): New function.
53 (mu_mailbox_get_size): Implement brute-force approach in case the
54 mailbox does not provide a method.
55
56 * mailbox/message.c (mu_message_get_qid, mu_message_set_qid): New
57 function.
58
59 * maildag/: New directory. A general-purpose mail delivery agent.
60 * maildag/deliver.c: New file.
61 * maildag/lmtp.c: New file.
62 * maildag/maidag.c: New file.
63 * maildag/maidag.h: New file.
64 * maildag/mailtmp.c: New file.
65 * maildag/mailquota.c: New file.
66 * maildag/script.c: New file.
67 * maildag/util.c: New file.
68 * maildag/Makefile.am: New file.
69 * maildag/.cvsignore: New file.
70
1 2007-11-08 Sergey Poznyakoff <gray@gnu.org.ua> 71 2007-11-08 Sergey Poznyakoff <gray@gnu.org.ua>
2 72
3 * mailbox/cfg_lexer.c: Do not use obstack. 73 * mailbox/cfg_lexer.c: Do not use obstack.
......
...@@ -39,6 +39,7 @@ SUBDIRS = \ ...@@ -39,6 +39,7 @@ SUBDIRS = \
39 frm\ 39 frm\
40 pop3d\ 40 pop3d\
41 imap4d\ 41 imap4d\
42 maidag\
42 mail\ 43 mail\
43 sieve\ 44 sieve\
44 scripts\ 45 scripts\
......
...@@ -1169,6 +1169,7 @@ AC_CONFIG_FILES([Makefile ...@@ -1169,6 +1169,7 @@ AC_CONFIG_FILES([Makefile
1169 libproto/include/Makefile 1169 libproto/include/Makefile
1170 libsieve/Makefile 1170 libsieve/Makefile
1171 libsieve/extensions/Makefile 1171 libsieve/extensions/Makefile
1172 maidag/Makefile
1172 mail/Makefile 1173 mail/Makefile
1173 mail/testsuite/Makefile 1174 mail/testsuite/Makefile
1174 mail.local/Makefile 1175 mail.local/Makefile
......
...@@ -421,7 +421,7 @@ static size_t msg_index; /* Index (1-based) of the current ...@@ -421,7 +421,7 @@ static size_t msg_index; /* Index (1-based) of the current
421 /* Observable action is being called on discovery of each message. */ 421 /* Observable action is being called on discovery of each message. */
422 /* FIXME: The format of the display is poorly done, please correct. */ 422 /* FIXME: The format of the display is poorly done, please correct. */
423 static int 423 static int
424 action (mu_observer_t o, size_t type) 424 action (mu_observer_t o, size_t type, void *data, void *action_data)
425 { 425 {
426 int status; 426 int status;
427 427
......
...@@ -49,7 +49,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags) ...@@ -49,7 +49,7 @@ imap4d_select0 (struct imap4d_command *command, char *arg, int flags)
49 currently selected mailbox without doing an expunge. */ 49 currently selected mailbox without doing an expunge. */
50 if (mbox) 50 if (mbox)
51 { 51 {
52 mu_mailbox_save_attributes (mbox); 52 mu_mailbox_sync (mbox);
53 mu_mailbox_close (mbox); 53 mu_mailbox_close (mbox);
54 mu_mailbox_destroy (&mbox); 54 mu_mailbox_destroy (&mbox);
55 /* Destroy the old uid table. */ 55 /* Destroy the old uid table. */
......
...@@ -77,7 +77,7 @@ imap4d_status (struct imap4d_command *command, char *arg) ...@@ -77,7 +77,7 @@ imap4d_status (struct imap4d_command *command, char *arg)
77 77
78 /* We may be opening the current mailbox, so make sure the attributes are 78 /* We may be opening the current mailbox, so make sure the attributes are
79 preserved */ 79 preserved */
80 mu_mailbox_save_attributes (mbox); 80 mu_mailbox_sync (mbox);
81 81
82 status = mu_mailbox_create_default (&smbox, mailbox_name); 82 status = mu_mailbox_create_default (&smbox, mailbox_name);
83 if (status == 0) 83 if (status == 0)
......
...@@ -276,7 +276,7 @@ imap4d_sync_flags (size_t msgno) ...@@ -276,7 +276,7 @@ imap4d_sync_flags (size_t msgno)
276 static int mailbox_corrupt; 276 static int mailbox_corrupt;
277 277
278 static int 278 static int
279 action (mu_observer_t observer, size_t type) 279 action (mu_observer_t observer, size_t type, void *data, void *action_data)
280 { 280 {
281 switch (type) 281 switch (type)
282 { 282 {
......
...@@ -52,13 +52,18 @@ extern int mu_mailbox_uidvalidity (mu_mailbox_t, unsigned long *); ...@@ -52,13 +52,18 @@ extern int mu_mailbox_uidvalidity (mu_mailbox_t, unsigned long *);
52 extern int mu_mailbox_uidnext (mu_mailbox_t, size_t *); 52 extern int mu_mailbox_uidnext (mu_mailbox_t, size_t *);
53 53
54 /* Messages. */ 54 /* Messages. */
55 extern int mu_mailbox_get_message (mu_mailbox_t, size_t msgno, mu_message_t *); 55 extern int mu_mailbox_get_message (mu_mailbox_t, size_t msgno,
56 mu_message_t *);
57 extern int mu_mailbox_quick_get_message(mu_mailbox_t, mu_message_qid_t,
58 mu_message_t *);
56 extern int mu_mailbox_append_message (mu_mailbox_t, mu_message_t); 59 extern int mu_mailbox_append_message (mu_mailbox_t, mu_message_t);
57 extern int mu_mailbox_messages_count (mu_mailbox_t, size_t *); 60 extern int mu_mailbox_messages_count (mu_mailbox_t, size_t *);
58 extern int mu_mailbox_messages_recent (mu_mailbox_t, size_t *); 61 extern int mu_mailbox_messages_recent (mu_mailbox_t, size_t *);
59 extern int mu_mailbox_message_unseen (mu_mailbox_t, size_t *); 62 extern int mu_mailbox_message_unseen (mu_mailbox_t, size_t *);
60 extern int mu_mailbox_expunge (mu_mailbox_t); 63 extern int mu_mailbox_expunge (mu_mailbox_t);
61 extern int mu_mailbox_save_attributes (mu_mailbox_t); 64 extern int mu_mailbox_sync (mu_mailbox_t);
65 extern int mu_mailbox_save_attributes (mu_mailbox_t)
66 __attribute__ ((deprecated));
62 67
63 /* Update and scanning. */ 68 /* Update and scanning. */
64 extern int mu_mailbox_get_size (mu_mailbox_t, mu_off_t *size); 69 extern int mu_mailbox_get_size (mu_mailbox_t, mu_off_t *size);
......
...@@ -29,89 +29,102 @@ extern "C" { ...@@ -29,89 +29,102 @@ extern "C" {
29 /* A message is considered to be a container for: 29 /* A message is considered to be a container for:
30 mu_header_t, mu_body_t, and its mu_attribute_t. */ 30 mu_header_t, mu_body_t, and its mu_attribute_t. */
31 31
32 extern int mu_message_create (mu_message_t *, void *owner); 32 extern int mu_message_create (mu_message_t *, void *owner);
33 extern void mu_message_destroy (mu_message_t *, void *owner); 33 extern void mu_message_destroy (mu_message_t *, void *owner);
34 34
35 extern int mu_message_create_copy (mu_message_t *to, mu_message_t from); 35 extern int mu_message_create_copy (mu_message_t *to, mu_message_t from);
36 36
37 extern void * mu_message_get_owner (mu_message_t); 37 extern void * mu_message_get_owner (mu_message_t);
38 extern int mu_message_is_modified (mu_message_t); 38 extern int mu_message_is_modified (mu_message_t);
39 extern int mu_message_clear_modified (mu_message_t); 39 extern int mu_message_clear_modified (mu_message_t);
40 extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *); 40 extern int mu_message_get_mailbox (mu_message_t, mu_mailbox_t *);
41 extern int mu_message_set_mailbox (mu_message_t, mu_mailbox_t, void *); 41 extern int mu_message_set_mailbox (mu_message_t, mu_mailbox_t, void *);
42 42
43 extern int mu_message_ref (mu_message_t); 43 extern int mu_message_ref (mu_message_t);
44 #define mu_message_unref(msg) mu_message_destroy (&msg, NULL) 44 #define mu_message_unref(msg) mu_message_destroy (&msg, NULL)
45 45
46 extern int mu_message_get_envelope (mu_message_t, mu_envelope_t *); 46 extern int mu_message_get_envelope (mu_message_t, mu_envelope_t *);
47 extern int mu_message_set_envelope (mu_message_t, mu_envelope_t, void *); 47 extern int mu_message_set_envelope (mu_message_t, mu_envelope_t, void *);
48 48
49 extern int mu_message_get_header (mu_message_t, mu_header_t *); 49 extern int mu_message_get_header (mu_message_t, mu_header_t *);
50 extern int mu_message_set_header (mu_message_t, mu_header_t, void *); 50 extern int mu_message_set_header (mu_message_t, mu_header_t, void *);
51 51
52 extern int mu_message_get_body (mu_message_t, mu_body_t *); 52 extern int mu_message_get_body (mu_message_t, mu_body_t *);
53 extern int mu_message_set_body (mu_message_t, mu_body_t, void *); 53 extern int mu_message_set_body (mu_message_t, mu_body_t, void *);
54 54
55 extern int mu_message_get_stream (mu_message_t, mu_stream_t *); 55 extern int mu_message_get_stream (mu_message_t, mu_stream_t *);
56 extern int mu_message_set_stream (mu_message_t, mu_stream_t, void *); 56 extern int mu_message_set_stream (mu_message_t, mu_stream_t, void *);
57 57
58 extern int mu_message_get_attribute (mu_message_t, mu_attribute_t *); 58 extern int mu_message_get_attribute (mu_message_t, mu_attribute_t *);
59 extern int mu_message_set_attribute (mu_message_t, mu_attribute_t, void *); 59 extern int mu_message_set_attribute (mu_message_t, mu_attribute_t, void *);
60 60
61 extern int mu_message_get_observable (mu_message_t, mu_observable_t *); 61 extern int mu_message_get_observable (mu_message_t, mu_observable_t *);
62 62
63 extern int mu_message_is_multipart (mu_message_t, int *); 63 extern int mu_message_is_multipart (mu_message_t, int *);
64 extern int mu_message_set_is_multipart (mu_message_t, 64 extern int mu_message_set_is_multipart (mu_message_t,
65 int (*_is_multipart) (mu_message_t, int *), 65 int (*_is_multipart) (mu_message_t,
66 void *); 66 int *),
67 void *);
67 68
68 extern int mu_message_size (mu_message_t, size_t *); 69 extern int mu_message_size (mu_message_t, size_t *);
69 extern int mu_message_set_size (mu_message_t, 70 extern int mu_message_set_size (mu_message_t,
70 int (*_size) (mu_message_t, size_t *), 71 int (*_size) (mu_message_t, size_t *),
71 void *owner); 72 void *owner);
72 73
73 extern int mu_message_lines (mu_message_t, size_t *); 74 extern int mu_message_lines (mu_message_t, size_t *);
74 extern int mu_message_set_lines (mu_message_t, 75 extern int mu_message_set_lines (mu_message_t,
75 int (*_lines) (mu_message_t, size_t *), 76 int (*_lines) (mu_message_t, size_t *),
76 void *owner); 77 void *owner);
77 78
78 extern int mu_message_get_num_parts (mu_message_t, size_t *nparts); 79 extern int mu_message_get_num_parts (mu_message_t, size_t *nparts);
79 extern int mu_message_set_get_num_parts (mu_message_t, 80 extern int mu_message_set_get_num_parts (mu_message_t,
80 int (*_get_num_parts) (mu_message_t, 81 int (*_get_num_parts) (mu_message_t,
81 size_t *), 82 size_t *),
82 void *owner); 83 void *owner);
83 84
84 extern int mu_message_get_part (mu_message_t, size_t, mu_message_t *); 85 extern int mu_message_get_part (mu_message_t, size_t, mu_message_t *);
85 extern int mu_message_set_get_part (mu_message_t, 86 extern int mu_message_set_get_part (mu_message_t,
86 int (*_get_part) (mu_message_t, size_t, 87 int (*_get_part) (mu_message_t, size_t,
87 mu_message_t *), 88 mu_message_t *),
88 void *owner); 89 void *owner);
89 90
90 extern int mu_message_get_uidl (mu_message_t, char *, size_t, size_t *); 91 extern int mu_message_get_uidl (mu_message_t, char *, size_t, size_t *);
91 extern int mu_message_set_uidl (mu_message_t, 92 extern int mu_message_set_uidl (mu_message_t,
92 int (*_get_uidl) (mu_message_t, char *, 93 int (*_get_uidl) (mu_message_t,
93 size_t, size_t *), 94 char *,
94 void *owner); 95 size_t, size_t *),
95 extern int mu_message_get_uid (mu_message_t, size_t *); 96 void *owner);
96 extern int mu_message_set_uid (mu_message_t, 97
97 int (*_get_uid) (mu_message_t, size_t *), 98 extern int mu_message_get_uid (mu_message_t, size_t *);
98 void *owner); 99 extern int mu_message_set_uid (mu_message_t,
99 100 int (*_get_uid) (mu_message_t,
101 size_t *),
102 void *owner);
103
104 extern int mu_message_get_qid (mu_message_t, mu_message_qid_t *);
105 extern int mu_message_set_qid (mu_message_t,
106 int (*_get_qid) (mu_message_t,
107 mu_message_qid_t *),
108 void *owner);
109
100 /* misc functions */ 110 /* misc functions */
101 extern int mu_message_create_attachment (const char *content_type, 111 extern int mu_message_create_attachment (const char *content_type,
102 const char *encoding, 112 const char *encoding,
103 const char *filename, 113 const char *filename,
104 mu_message_t *newmsg); 114 mu_message_t *newmsg);
105 extern int mu_message_save_attachment (mu_message_t msg, 115 extern int mu_message_save_attachment (mu_message_t msg,
106 const char *filename, void **data); 116 const char *filename, void **data);
107 extern int mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg, void **data); 117 extern int mu_message_encapsulate (mu_message_t msg, mu_message_t *newmsg,
108 extern int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg, void **data); 118 void **data);
109 119 extern int mu_message_unencapsulate (mu_message_t msg, mu_message_t *newmsg,
110 extern int mu_message_get_attachment_name (mu_message_t, char *name, size_t bufsz, size_t* sz); 120 void **data);
121
122 extern int mu_message_get_attachment_name (mu_message_t, char *name,
123 size_t bufsz, size_t* sz);
111 extern int mu_message_aget_attachment_name (mu_message_t, char **name); 124 extern int mu_message_aget_attachment_name (mu_message_t, char **name);
112 125
113 extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, 126 extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket,
114 mu_debug_t debug, const char *toname); 127 mu_debug_t debug, const char *toname);
115 128
116 129
117 extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg); 130 extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg);
......
...@@ -24,36 +24,42 @@ ...@@ -24,36 +24,42 @@
24 #ifdef __cplusplus 24 #ifdef __cplusplus
25 extern "C" { 25 extern "C" {
26 #endif 26 #endif
27 27 /* Call data type: */
28 #define MU_EVT_MAILBOX_DESTROY 0x001 28 #define MU_EVT_MAILBOX_DESTROY 0x001 /* mu_mailbox_t */
29 #define MU_EVT_FOLDER_DESTROY 0x002 29 #define MU_EVT_FOLDER_DESTROY 0x002 /* mu_folder_t */
30 #define MU_EVT_MAILER_DESTROY 0x004 30 #define MU_EVT_MAILER_DESTROY 0x004 /* mu_mailer_t */
31 #define MU_EVT_MESSAGE_DESTROY 0x008 31 #define MU_EVT_MESSAGE_DESTROY 0x008 /* mu_message_t */
32 #define MU_EVT_MESSAGE_ADD 0x010 32 #define MU_EVT_MESSAGE_ADD 0x010 /* size_t *: FIXME */
33 #define MU_EVT_MAILBOX_PROGRESS 0x020 33 #define MU_EVT_MAILBOX_PROGRESS 0x020 /* NULL: FIXME? */
34 #define MU_EVT_AUTHORITY_FAILED 0x030 34 #define MU_EVT_AUTHORITY_FAILED 0x030 /* NULL */
35 #define MU_EVT_MAILBOX_CORRUPT 0x040 35 #define MU_EVT_MAILBOX_CORRUPT 0x040 /* mu_mailbox_t */
36 #define MU_EVT_MAILER_MESSAGE_SENT 0x080 36 #define MU_EVT_MAILER_MESSAGE_SENT 0x080 /* mu_message_t */
37 37 #define MU_EVT_MESSAGE_APPEND 0x100 /* mu_message_qid_t: FIXME */
38
38 #define MU_OBSERVER_NO_CHECK 1 39 #define MU_OBSERVER_NO_CHECK 1
39 40
40 extern int mu_observer_create (mu_observer_t *, void *owner); 41 extern int mu_observer_create (mu_observer_t *, void *owner);
41 extern void mu_observer_destroy (mu_observer_t *, void *owner); 42 extern void mu_observer_destroy (mu_observer_t *, void *owner);
42 extern void * mu_observer_get_owner (mu_observer_t); 43 extern void * mu_observer_get_owner(mu_observer_t);
43 extern int mu_observer_action (mu_observer_t, size_t type); 44 extern int mu_observer_action (mu_observer_t, size_t type, void *data);
44 extern int mu_observer_set_action (mu_observer_t, 45 extern int mu_observer_set_action (mu_observer_t,
45 int (*_action) (mu_observer_t, size_t), 46 int (*_action) (mu_observer_t,
46 void *owner); 47 size_t, void *, void *),
48 void *owner);
49 extern int mu_observer_set_action_data (mu_observer_t, void *data,
50 void *owner);
47 extern int mu_observer_set_destroy (mu_observer_t, 51 extern int mu_observer_set_destroy (mu_observer_t,
48 int (*_destroy) (mu_observer_t), void *owner); 52 int (*_destroy) (mu_observer_t, void *),
53 void *owner);
49 extern int mu_observer_set_flags (mu_observer_t, int flags); 54 extern int mu_observer_set_flags (mu_observer_t, int flags);
50 55
51 extern int mu_observable_create (mu_observable_t *, void *owner); 56 extern int mu_observable_create (mu_observable_t *, void *owner);
52 extern void mu_observable_destroy (mu_observable_t *, void *owner); 57 extern void mu_observable_destroy (mu_observable_t *, void *owner);
53 extern void * mu_observable_get_owner (mu_observable_t); 58 extern void * mu_observable_get_owner (mu_observable_t);
54 extern int mu_observable_attach (mu_observable_t, size_t type, mu_observer_t observer); 59 extern int mu_observable_attach (mu_observable_t, size_t type,
60 mu_observer_t observer);
55 extern int mu_observable_detach (mu_observable_t, mu_observer_t observer); 61 extern int mu_observable_detach (mu_observable_t, mu_observer_t observer);
56 extern int mu_observable_notify (mu_observable_t, int type); 62 extern int mu_observable_notify (mu_observable_t, int type, void *data);
57 63
58 #ifdef __cplusplus 64 #ifdef __cplusplus
59 } 65 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail 1 /* GNU Mailutils -- a suite of utilities for electronic mail -*- c -*-
2 Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001, 2005, 2007 Free Software Foundation, Inc.
3 3
4 This library is free software; you can redistribute it and/or 4 This library is free software; you can redistribute it and/or
...@@ -99,6 +99,7 @@ typedef struct _mu_url *mu_url_t; ...@@ -99,6 +99,7 @@ typedef struct _mu_url *mu_url_t;
99 typedef struct _mu_wicket *mu_wicket_t; 99 typedef struct _mu_wicket *mu_wicket_t;
100 typedef void *mu_transport_t; 100 typedef void *mu_transport_t;
101 typedef struct _mu_assoc *mu_assoc_t; 101 typedef struct _mu_assoc *mu_assoc_t;
102 typedef char *mu_message_qid_t;
102 103
103 #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001 104 #define MU_FOLDER_ATTRIBUTE_DIRECTORY 0x001
104 #define MU_FOLDER_ATTRIBUTE_FILE 0x002 105 #define MU_FOLDER_ATTRIBUTE_FILE 0x002
......
...@@ -2527,7 +2527,8 @@ imap_parse (f_imap_t f_imap) ...@@ -2527,7 +2527,8 @@ imap_parse (f_imap_t f_imap)
2527 { 2527 {
2528 mu_observable_t observable = NULL; 2528 mu_observable_t observable = NULL;
2529 mu_folder_get_observable (f_imap->folder, &observable); 2529 mu_folder_get_observable (f_imap->folder, &observable);
2530 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED); 2530 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED,
2531 NULL);
2531 status = MU_ERR_AUTH_FAILURE; 2532 status = MU_ERR_AUTH_FAILURE;
2532 } 2533 }
2533 else if (strncasecmp (remainder, "LIST", 4) == 0) 2534 else if (strncasecmp (remainder, "LIST", 4) == 0)
......
...@@ -798,12 +798,13 @@ imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif) ...@@ -798,12 +798,13 @@ imap_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int notif)
798 798
799 for (i = msgno; i <= count; i++) 799 for (i = msgno; i <= count; i++)
800 { 800 {
801 if (mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_ADD) != 0) 801 size_t tmp = i;
802 if (mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_ADD,
803 &tmp) != 0)
802 break; 804 break;
803 if (((i + 1) % 100) == 0) 805 if ((i + 1) % 100 == 0)
804 { 806 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_PROGRESS,
805 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_PROGRESS); 807 NULL);
806 }
807 } 808 }
808 return 0; 809 return 0;
809 } 810 }
......
...@@ -20,13 +20,17 @@ ...@@ -20,13 +20,17 @@
20 #define MAX_OPEN_STREAMS 16 20 #define MAX_OPEN_STREAMS 16
21 21
22 /* Notifications ADD_MESG. */ 22 /* Notifications ADD_MESG. */
23 #define DISPATCH_ADD_MSG(mbox,mhd) \ 23 #define DISPATCH_ADD_MSG(mbox,mhd,n) \
24 do \ 24 do \
25 { \ 25 { \
26 int bailing = 0; \ 26 int bailing = 0; \
27 mu_monitor_unlock (mbox->monitor); \ 27 mu_monitor_unlock (mbox->monitor); \
28 if (mbox->observable) \ 28 if (mbox->observable) \
29 bailing = mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD); \ 29 { \
30 size_t tmp = (n); \
31 bailing = mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, \
32 &tmp); \
33 } \
30 if (bailing != 0) \ 34 if (bailing != 0) \
31 { \ 35 { \
32 if (pcount) \ 36 if (pcount) \
......
...@@ -55,7 +55,7 @@ struct _mu_mailbox ...@@ -55,7 +55,7 @@ struct _mu_mailbox
55 55
56 int (*_open) (mu_mailbox_t, int); 56 int (*_open) (mu_mailbox_t, int);
57 int (*_close) (mu_mailbox_t); 57 int (*_close) (mu_mailbox_t);
58 58
59 /* messages */ 59 /* messages */
60 int (*_get_message) (mu_mailbox_t, size_t, mu_message_t *); 60 int (*_get_message) (mu_mailbox_t, size_t, mu_message_t *);
61 int (*_append_message) (mu_mailbox_t, mu_message_t); 61 int (*_append_message) (mu_mailbox_t, mu_message_t);
...@@ -63,7 +63,7 @@ struct _mu_mailbox ...@@ -63,7 +63,7 @@ struct _mu_mailbox
63 int (*_messages_recent) (mu_mailbox_t, size_t *); 63 int (*_messages_recent) (mu_mailbox_t, size_t *);
64 int (*_message_unseen) (mu_mailbox_t, size_t *); 64 int (*_message_unseen) (mu_mailbox_t, size_t *);
65 int (*_expunge) (mu_mailbox_t); 65 int (*_expunge) (mu_mailbox_t);
66 int (*_save_attributes) (mu_mailbox_t); 66 int (*_sync) (mu_mailbox_t);
67 int (*_uidvalidity) (mu_mailbox_t, unsigned long *); 67 int (*_uidvalidity) (mu_mailbox_t, unsigned long *);
68 int (*_uidnext) (mu_mailbox_t, size_t *); 68 int (*_uidnext) (mu_mailbox_t, size_t *);
69 int (*_get_property) (mu_mailbox_t, mu_property_t *); 69 int (*_get_property) (mu_mailbox_t, mu_property_t *);
...@@ -73,11 +73,9 @@ struct _mu_mailbox ...@@ -73,11 +73,9 @@ struct _mu_mailbox
73 73
74 int (*_get_size) (mu_mailbox_t, mu_off_t *); 74 int (*_get_size) (mu_mailbox_t, mu_off_t *);
75 75
76 int (*_quick_get_message) (mu_mailbox_t, mu_message_qid_t, mu_message_t *);
76 }; 77 };
77 78
78 #define MAILBOX_NOTIFY(mbox, type) \
79 if (mbox->observer) observer_notify (mbox->observer, type)
80
81 /* Moro(?)ic kluge. */ 79 /* Moro(?)ic kluge. */
82 #define MAILBOX_DEBUG0(mbox, type, format) \ 80 #define MAILBOX_DEBUG0(mbox, type, format) \
83 if (mbox->debug) mu_debug_print (mbox->debug, type, format) 81 if (mbox->debug) mu_debug_print (mbox->debug, type, format)
......
...@@ -60,6 +60,7 @@ struct _mu_message ...@@ -60,6 +60,7 @@ struct _mu_message
60 60
61 int (*_get_uidl) (mu_message_t, char *, size_t, size_t *); 61 int (*_get_uidl) (mu_message_t, char *, size_t, size_t *);
62 int (*_get_uid) (mu_message_t, size_t *); 62 int (*_get_uid) (mu_message_t, size_t *);
63 int (*_get_qid) (mu_message_t, mu_message_qid_t *);
63 int (*_get_num_parts) (mu_message_t, size_t *); 64 int (*_get_num_parts) (mu_message_t, size_t *);
64 int (*_get_part) (mu_message_t, size_t, mu_message_t *); 65 int (*_get_part) (mu_message_t, size_t, mu_message_t *);
65 int (*_is_multipart) (mu_message_t, int *); 66 int (*_is_multipart) (mu_message_t, int *);
......
...@@ -33,8 +33,9 @@ struct _mu_observer ...@@ -33,8 +33,9 @@ struct _mu_observer
33 { 33 {
34 int flags; 34 int flags;
35 void *owner; 35 void *owner;
36 int (*_action) (mu_observer_t, size_t); 36 int (*_action) (mu_observer_t, size_t, void *, void *);
37 int (*_destroy) (mu_observer_t); 37 void *_action_data;
38 int (*_destroy) (mu_observer_t, void *data);
38 }; 39 };
39 40
40 struct _mu_observable 41 struct _mu_observable
......
...@@ -623,7 +623,7 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, ...@@ -623,7 +623,7 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount,
623 size_t i; 623 size_t i;
624 for (i = 0; i < amd->msg_count; i++) 624 for (i = 0; i < amd->msg_count; i++)
625 { 625 {
626 DISPATCH_ADD_MSG(mailbox, amd); 626 DISPATCH_ADD_MSG(mailbox, amd, i);
627 } 627 }
628 } 628 }
629 629
......
...@@ -443,7 +443,8 @@ sendmail_send_message (mu_mailer_t mailer, mu_message_t msg, mu_address_t from, ...@@ -443,7 +443,8 @@ sendmail_send_message (mu_mailer_t mailer, mu_message_t msg, mu_address_t from,
443 status = MU_ERR_PROCESS_UNKNOWN_FAILURE; 443 status = MU_ERR_PROCESS_UNKNOWN_FAILURE;
444 444
445 /* Shouldn't this notification only happen on success? */ 445 /* Shouldn't this notification only happen on success? */
446 mu_observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT); 446 mu_observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT,
447 msg);
447 } 448 }
448 default: 449 default:
449 break; 450 break;
......
...@@ -870,7 +870,8 @@ smtp_send_message (mu_mailer_t mailer, mu_message_t argmsg, mu_address_t argfrom ...@@ -870,7 +870,8 @@ smtp_send_message (mu_mailer_t mailer, mu_message_t argmsg, mu_address_t argfrom
870 if (smtp->rcpt_index <= smtp->rcpt_bcc_count) 870 if (smtp->rcpt_index <= smtp->rcpt_bcc_count)
871 goto ENV_FROM; 871 goto ENV_FROM;
872 872
873 mu_observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT); 873 mu_observable_notify (mailer->observable, MU_EVT_MAILER_MESSAGE_SENT,
874 argmsg);
874 875
875 default: 876 default:
876 break; 877 break;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
24 #endif 24 #endif
25 25
26 #include <mbox0.h> 26 #include <mbox0.h>
27 #include <mu_umaxtostr.h>
27 28
28 #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED) 29 #define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED)
29 #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2) 30 #define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2)
...@@ -41,7 +42,7 @@ static int mbox_messages_recent (mu_mailbox_t, size_t *); ...@@ -41,7 +42,7 @@ static int mbox_messages_recent (mu_mailbox_t, size_t *);
41 static int mbox_message_unseen (mu_mailbox_t, size_t *); 42 static int mbox_message_unseen (mu_mailbox_t, size_t *);
42 static int mbox_expunge0 (mu_mailbox_t, int); 43 static int mbox_expunge0 (mu_mailbox_t, int);
43 static int mbox_expunge (mu_mailbox_t); 44 static int mbox_expunge (mu_mailbox_t);
44 static int mbox_save_attributes (mu_mailbox_t); 45 static int mbox_sync (mu_mailbox_t);
45 static int mbox_uidvalidity (mu_mailbox_t, unsigned long *); 46 static int mbox_uidvalidity (mu_mailbox_t, unsigned long *);
46 static int mbox_uidnext (mu_mailbox_t, size_t *); 47 static int mbox_uidnext (mu_mailbox_t, size_t *);
47 static int mbox_scan (mu_mailbox_t, size_t, size_t *); 48 static int mbox_scan (mu_mailbox_t, size_t, size_t *);
...@@ -49,24 +50,35 @@ static int mbox_is_updated (mu_mailbox_t); ...@@ -49,24 +50,35 @@ static int mbox_is_updated (mu_mailbox_t);
49 static int mbox_get_size (mu_mailbox_t, mu_off_t *); 50 static int mbox_get_size (mu_mailbox_t, mu_off_t *);
50 51
51 /* private stuff */ 52 /* private stuff */
52 static int mbox_append_message0 (mu_mailbox_t, mu_message_t, mu_off_t *, int, int); 53 static int mbox_append_message0 (mu_mailbox_t, mu_message_t,
54 mu_off_t *, int, int);
53 static int mbox_message_uid (mu_message_t, size_t *); 55 static int mbox_message_uid (mu_message_t, size_t *);
54 static int mbox_header_fill (mu_header_t, char *, size_t, mu_off_t, size_t *); 56 static int mbox_message_qid (mu_message_t, mu_message_qid_t *);
55 static int mbox_get_body_transport (mu_stream_t, mu_transport_t *, mu_transport_t *); 57
56 static int mbox_get_transport2 (mbox_message_t, mu_transport_t *, mu_transport_t *); 58 static int mbox_header_fill (mu_header_t, char *, size_t,
59 mu_off_t, size_t *);
60 static int mbox_get_body_transport (mu_stream_t, mu_transport_t *,
61 mu_transport_t *);
62 static int mbox_get_transport2 (mbox_message_t, mu_transport_t *,
63 mu_transport_t *);
57 static int mbox_get_attr_flags (mu_attribute_t, int *); 64 static int mbox_get_attr_flags (mu_attribute_t, int *);
58 static int mbox_set_attr_flags (mu_attribute_t, int); 65 static int mbox_set_attr_flags (mu_attribute_t, int);
59 static int mbox_unset_attr_flags (mu_attribute_t, int); 66 static int mbox_unset_attr_flags (mu_attribute_t, int);
60 static int mbox_body_read (mu_stream_t, char *, size_t, mu_off_t, size_t *); 67 static int mbox_body_read (mu_stream_t, char *, size_t,
61 static int mbox_body_readline (mu_stream_t, char *, size_t, mu_off_t, size_t *); 68 mu_off_t, size_t *);
69 static int mbox_body_readline (mu_stream_t, char *, size_t,
70 mu_off_t, size_t *);
62 static int mbox_readstream (mbox_message_t, char *, size_t, 71 static int mbox_readstream (mbox_message_t, char *, size_t,
63 mu_off_t, size_t *, int, mu_off_t, mu_off_t); 72 mu_off_t, size_t *, int, mu_off_t,
73 mu_off_t);
64 static int mbox_stream_size (mu_stream_t stream, mu_off_t *psize); 74 static int mbox_stream_size (mu_stream_t stream, mu_off_t *psize);
65 75
66 static int mbox_body_size (mu_body_t, size_t *); 76 static int mbox_body_size (mu_body_t, size_t *);
67 static int mbox_body_lines (mu_body_t, size_t *); 77 static int mbox_body_lines (mu_body_t, size_t *);
68 static int mbox_envelope_sender (mu_envelope_t, char *, size_t, size_t *); 78 static int mbox_envelope_sender (mu_envelope_t, char *, size_t,
69 static int mbox_envelope_date (mu_envelope_t, char *, size_t, size_t *); 79 size_t *);
80 static int mbox_envelope_date (mu_envelope_t, char *, size_t,
81 size_t *);
70 static int mbox_tmpfile (mu_mailbox_t, char **pbox); 82 static int mbox_tmpfile (mu_mailbox_t, char **pbox);
71 83
72 /* Allocate the mbox_data_t struct(concrete mailbox), but don't do any 84 /* Allocate the mbox_data_t struct(concrete mailbox), but don't do any
...@@ -121,7 +133,7 @@ _mailbox_mbox_init (mu_mailbox_t mailbox) ...@@ -121,7 +133,7 @@ _mailbox_mbox_init (mu_mailbox_t mailbox)
121 mailbox->_messages_recent = mbox_messages_recent; 133 mailbox->_messages_recent = mbox_messages_recent;
122 mailbox->_message_unseen = mbox_message_unseen; 134 mailbox->_message_unseen = mbox_message_unseen;
123 mailbox->_expunge = mbox_expunge; 135 mailbox->_expunge = mbox_expunge;
124 mailbox->_save_attributes = mbox_save_attributes; 136 mailbox->_sync = mbox_sync;
125 mailbox->_uidvalidity = mbox_uidvalidity; 137 mailbox->_uidvalidity = mbox_uidvalidity;
126 mailbox->_uidnext = mbox_uidnext; 138 mailbox->_uidnext = mbox_uidnext;
127 139
...@@ -297,11 +309,14 @@ mbox_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount) ...@@ -297,11 +309,14 @@ mbox_scan (mu_mailbox_t mailbox, size_t msgno, size_t *pcount)
297 msgno--; /* The fist message is number "1", decrement for the C array. */ 309 msgno--; /* The fist message is number "1", decrement for the C array. */
298 for (i = msgno; i < mud->messages_count; i++) 310 for (i = msgno; i < mud->messages_count; i++)
299 { 311 {
300 if (mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_ADD) != 0) 312 size_t tmp = i;
313 if (mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_ADD,
314 &tmp) != 0)
301 break; 315 break;
302 if (((i +1) % 50) == 0) 316 if (((i +1) % 50) == 0)
303 { 317 {
304 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_PROGRESS); 318 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_PROGRESS,
319 NULL);
305 } 320 }
306 } 321 }
307 *pcount = mud->messages_count; 322 *pcount = mud->messages_count;
...@@ -328,7 +343,8 @@ mbox_is_updated (mu_mailbox_t mailbox) ...@@ -328,7 +343,8 @@ mbox_is_updated (mu_mailbox_t mailbox)
328 return 1; 343 return 1;
329 if (size < mud->size) 344 if (size < mud->size)
330 { 345 {
331 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_CORRUPT); 346 mu_observable_notify (mailbox->observable, MU_EVT_MAILBOX_CORRUPT,
347 mailbox);
332 /* And be verbose. ? */ 348 /* And be verbose. ? */
333 mu_error (_("* BAD : Mailbox corrupted, shrank in size")); 349 mu_error (_("* BAD : Mailbox corrupted, shrank in size"));
334 /* FIXME: should I crash. */ 350 /* FIXME: should I crash. */
...@@ -552,7 +568,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted) ...@@ -552,7 +568,7 @@ mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted)
552 if ((mum->attr_flags & MU_ATTRIBUTE_MODIFIED) || 568 if ((mum->attr_flags & MU_ATTRIBUTE_MODIFIED) ||
553 (mum->message && mu_message_is_modified (mum->message))) 569 (mum->message && mu_message_is_modified (mum->message)))
554 { 570 {
555 /* The message was not instanciated, probably the dirty flag was 571 /* The message was not instantiated, probably the dirty flag was
556 set by mbox_scan(), create one here. */ 572 set by mbox_scan(), create one here. */
557 if (mum->message == 0) 573 if (mum->message == 0)
558 { 574 {
...@@ -764,7 +780,7 @@ mbox_expunge (mu_mailbox_t mailbox) ...@@ -764,7 +780,7 @@ mbox_expunge (mu_mailbox_t mailbox)
764 } 780 }
765 781
766 static int 782 static int
767 mbox_save_attributes (mu_mailbox_t mailbox) 783 mbox_sync (mu_mailbox_t mailbox)
768 { 784 {
769 return mbox_expunge0 (mailbox, 0); 785 return mbox_expunge0 (mailbox, 0);
770 } 786 }
...@@ -779,6 +795,18 @@ mbox_message_uid (mu_message_t msg, size_t *puid) ...@@ -779,6 +795,18 @@ mbox_message_uid (mu_message_t msg, size_t *puid)
779 } 795 }
780 796
781 static int 797 static int
798 mbox_message_qid (mu_message_t msg, mu_message_qid_t *pqid)
799 {
800 mbox_message_t mum = mu_message_get_owner (msg);
801 char buf[UINTMAX_STRSIZE_BOUND];
802 const char *p = umaxtostr (mum->header_from, buf);
803 *pqid = strdup (p);
804 if (*pqid == NULL)
805 return ENOMEM;
806 return 0;
807 }
808
809 static int
782 mbox_get_body_transport (mu_stream_t is, mu_transport_t *pin, 810 mbox_get_body_transport (mu_stream_t is, mu_transport_t *pin,
783 mu_transport_t *pout) 811 mu_transport_t *pout)
784 { 812 {
...@@ -1150,7 +1178,8 @@ mbox_get_message (mu_mailbox_t mailbox, size_t msgno, mu_message_t *pmsg) ...@@ -1150,7 +1178,8 @@ mbox_get_message (mu_mailbox_t mailbox, size_t msgno, mu_message_t *pmsg)
1150 1178
1151 /* Set the UID. */ 1179 /* Set the UID. */
1152 mu_message_set_uid (msg, mbox_message_uid, mum); 1180 mu_message_set_uid (msg, mbox_message_uid, mum);
1153 1181 mu_message_set_qid (msg, mbox_message_qid, mum);
1182
1154 /* Attach the message to the mailbox mbox data. */ 1183 /* Attach the message to the mailbox mbox data. */
1155 mum->message = msg; 1184 mum->message = msg;
1156 mu_message_set_mailbox (msg, mailbox, mum); 1185 mu_message_set_mailbox (msg, mailbox, mum);
...@@ -1164,7 +1193,8 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -1164,7 +1193,8 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
1164 { 1193 {
1165 int status = 0; 1194 int status = 0;
1166 mbox_data_t mud = mailbox->data; 1195 mbox_data_t mud = mailbox->data;
1167 1196 mu_off_t size;
1197
1168 if (msg == NULL || mud == NULL) 1198 if (msg == NULL || mud == NULL)
1169 return EINVAL; 1199 return EINVAL;
1170 1200
...@@ -1184,7 +1214,6 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -1184,7 +1214,6 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
1184 1214
1185 default: 1215 default:
1186 { 1216 {
1187 mu_off_t size;
1188 /* Move to the end of the file, not necesary if _APPEND mode. */ 1217 /* Move to the end of the file, not necesary if _APPEND mode. */
1189 if ((status = mu_stream_size (mailbox->stream, &size)) != 0 1218 if ((status = mu_stream_size (mailbox->stream, &size)) != 0
1190 || (status = mbox_append_message0 (mailbox, msg, 1219 || (status = mbox_append_message0 (mailbox, msg,
...@@ -1197,6 +1226,14 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg) ...@@ -1197,6 +1226,14 @@ mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
1197 } 1226 }
1198 } 1227 }
1199 mu_locker_unlock (mailbox->locker); 1228 mu_locker_unlock (mailbox->locker);
1229
1230 if (mailbox->observable)
1231 {
1232 char buf[UINTMAX_STRSIZE_BOUND];
1233 mu_observable_notify (mailbox->observable, MU_EVT_MESSAGE_APPEND,
1234 umaxtostr (size, buf));
1235 }
1236
1200 return 0; 1237 return 0;
1201 } 1238 }
1202 1239
...@@ -1294,10 +1331,10 @@ write_array (mu_stream_t stream, mu_off_t *poff, int count, const char **array) ...@@ -1294,10 +1331,10 @@ write_array (mu_stream_t stream, mu_off_t *poff, int count, const char **array)
1294 } 1331 }
1295 1332
1296 1333
1297 /* FIXME: We need to escape body line that begins with "From ", this 1334 /* FIXME: Do we need to escape body line that begins with "From "? This
1298 will required to read the body by line instead of by chuncks hurting 1335 will require reading the body line by line instead of by chunks,
1299 perfomance big time when expunging. But should not this be the 1336 considerably hurting perfomance when expunging. But should not this
1300 responsability of the client ? */ 1337 be the responsibility of the client ? */
1301 static int 1338 static int
1302 mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize, 1339 mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
1303 int is_expunging, int first) 1340 int is_expunging, int first)
...@@ -1423,7 +1460,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize, ...@@ -1423,7 +1460,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
1423 do 1460 do
1424 { 1461 {
1425 status = mu_stream_readline (is, buffer, sizeof (buffer), mud->off, 1462 status = mu_stream_readline (is, buffer, sizeof (buffer), mud->off,
1426 &nread); 1463 &nread);
1427 if (status != 0) 1464 if (status != 0)
1428 { 1465 {
1429 if (status != EAGAIN) 1466 if (status != EAGAIN)
...@@ -1453,7 +1490,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize, ...@@ -1453,7 +1490,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
1453 continue; 1490 continue;
1454 1491
1455 status = mu_stream_write (mailbox->stream, buffer, nread, 1492 status = mu_stream_write (mailbox->stream, buffer, nread,
1456 *psize, &n); 1493 *psize, &n);
1457 if (status) 1494 if (status)
1458 break; 1495 break;
1459 *psize += n; 1496 *psize += n;
...@@ -1537,7 +1574,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize, ...@@ -1537,7 +1574,7 @@ mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
1537 do 1574 do
1538 { 1575 {
1539 status = mu_stream_read (is, buffer, sizeof (buffer), mud->off, 1576 status = mu_stream_read (is, buffer, sizeof (buffer), mud->off,
1540 &nread); 1577 &nread);
1541 if (status != 0) 1578 if (status != 0)
1542 { 1579 {
1543 if (status != EAGAIN) 1580 if (status != EAGAIN)
......
...@@ -122,7 +122,8 @@ struct _mbox_data ...@@ -122,7 +122,8 @@ struct _mbox_data
122 mu_mailbox_t mailbox; /* Back pointer. */ 122 mu_mailbox_t mailbox; /* Back pointer. */
123 }; 123 };
124 124
125 int mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif); 125 int mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount,
126 int do_notif);
126 #ifdef WITH_PTHREAD 127 #ifdef WITH_PTHREAD
127 void mbox_cleanup (void *arg); 128 void mbox_cleanup (void *arg);
128 #endif 129 #endif
......
...@@ -412,7 +412,11 @@ do \ ...@@ -412,7 +412,11 @@ do \
412 int bailing = 0; \ 412 int bailing = 0; \
413 mu_monitor_unlock (mbox->monitor); \ 413 mu_monitor_unlock (mbox->monitor); \
414 if (mbox->observable) \ 414 if (mbox->observable) \
415 bailing = mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD); \ 415 { \
416 size_t tmp = mud->messages_count + 1; \
417 bailing = mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD, \
418 &tmp); \
419 } \
416 if (bailing != 0) \ 420 if (bailing != 0) \
417 { \ 421 { \
418 if (pcount) \ 422 if (pcount) \
...@@ -437,7 +441,7 @@ do \ ...@@ -437,7 +441,7 @@ do \
437 mud->messages_count--; \ 441 mud->messages_count--; \
438 if (mbox->observable) \ 442 if (mbox->observable) \
439 bailing = mu_observable_notify (mbox->observable, \ 443 bailing = mu_observable_notify (mbox->observable, \
440 MU_EVT_MAILBOX_PROGRESS); \ 444 MU_EVT_MAILBOX_PROGRESS, NULL); \
441 if (bailing != 0) \ 445 if (bailing != 0) \
442 { \ 446 { \
443 if (pcount) \ 447 if (pcount) \
...@@ -517,7 +521,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) ...@@ -517,7 +521,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
517 return status; 521 return status;
518 } 522 }
519 523
520 if((status = mu_locker_lock (mailbox->locker))) 524 if ((status = mu_locker_lock (mailbox->locker)))
521 { 525 {
522 mu_monitor_unlock (mailbox->monitor); 526 mu_monitor_unlock (mailbox->monitor);
523 return status; 527 return status;
...@@ -540,7 +544,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) ...@@ -540,7 +544,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
540 544
541 stream = mailbox->stream; 545 stream = mailbox->stream;
542 while ((status = mu_stream_readline (mailbox->stream, buf, sizeof (buf), 546 while ((status = mu_stream_readline (mailbox->stream, buf, sizeof (buf),
543 total, &n)) == 0 && n != 0) 547 total, &n)) == 0 && n != 0)
544 { 548 {
545 int nl; 549 int nl;
546 total += n; 550 total += n;
...@@ -577,7 +581,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) ...@@ -577,7 +581,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
577 min_uid = mum->uid; 581 min_uid = mum->uid;
578 582
579 if (do_notif) 583 if (do_notif)
580 DISPATCH_ADD_MSG(mailbox, mud); 584 DISPATCH_ADD_MSG (mailbox, mud);
581 585
582 } 586 }
583 /* Allocate_msgs will initialize mum. */ 587 /* Allocate_msgs will initialize mum. */
...@@ -640,7 +644,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif) ...@@ -640,7 +644,7 @@ mbox_scan0 (mu_mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
640 min_uid = mum->uid; 644 min_uid = mum->uid;
641 645
642 if (do_notif) 646 if (do_notif)
643 DISPATCH_ADD_MSG(mailbox, mud); 647 DISPATCH_ADD_MSG (mailbox, mud);
644 } 648 }
645 if (pcount) 649 if (pcount)
646 *pcount = mud->messages_count; 650 *pcount = mud->messages_count;
......
...@@ -211,7 +211,7 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount, ...@@ -211,7 +211,7 @@ mh_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, size_t *pcount,
211 211
212 for (i = 0; i < amd->msg_count; i++) 212 for (i = 0; i < amd->msg_count; i++)
213 { 213 {
214 DISPATCH_ADD_MSG(mailbox, amd); 214 DISPATCH_ADD_MSG (mailbox, amd, i);
215 } 215 }
216 } 216 }
217 217
......
...@@ -446,12 +446,12 @@ nntp_mailbox_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) ...@@ -446,12 +446,12 @@ nntp_mailbox_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
446 return 0; 446 return 0;
447 for (i = msgno; i <= count; i++) 447 for (i = msgno; i <= count; i++)
448 { 448 {
449 if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0) 449 size_t tmp = i;
450 if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD,
451 &tmp) != 0)
450 break; 452 break;
451 if (((i +1) % 10) == 0) 453 if ((i +1) % 10 == 0)
452 { 454 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS, NULL);
453 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS);
454 }
455 } 455 }
456 return 0; 456 return 0;
457 } 457 }
......
...@@ -528,7 +528,7 @@ _pop_user (mu_authority_t auth) ...@@ -528,7 +528,7 @@ _pop_user (mu_authority_t auth)
528 mu_observable_t observable = NULL; 528 mu_observable_t observable = NULL;
529 mu_mailbox_get_observable (mbox, &observable); 529 mu_mailbox_get_observable (mbox, &observable);
530 CLEAR_STATE (mpd); 530 CLEAR_STATE (mpd);
531 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED); 531 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED, NULL);
532 CHECK_ERROR_CLOSE (mbox, mpd, EACCES); 532 CHECK_ERROR_CLOSE (mbox, mpd, EACCES);
533 } 533 }
534 status = pop_get_passwd (auth); 534 status = pop_get_passwd (auth);
...@@ -566,7 +566,7 @@ _pop_user (mu_authority_t auth) ...@@ -566,7 +566,7 @@ _pop_user (mu_authority_t auth)
566 mu_observable_t observable = NULL; 566 mu_observable_t observable = NULL;
567 mu_mailbox_get_observable (mbox, &observable); 567 mu_mailbox_get_observable (mbox, &observable);
568 CLEAR_STATE (mpd); 568 CLEAR_STATE (mpd);
569 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED); 569 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED, NULL);
570 return MU_ERR_AUTH_FAILURE; 570 return MU_ERR_AUTH_FAILURE;
571 } 571 }
572 mpd->state = POP_AUTH_DONE; 572 mpd->state = POP_AUTH_DONE;
...@@ -638,7 +638,7 @@ _pop_apop (mu_authority_t auth) ...@@ -638,7 +638,7 @@ _pop_apop (mu_authority_t auth)
638 mu_observable_t observable = NULL; 638 mu_observable_t observable = NULL;
639 mu_mailbox_get_observable (mbox, &observable); 639 mu_mailbox_get_observable (mbox, &observable);
640 CLEAR_STATE (mpd); 640 CLEAR_STATE (mpd);
641 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED); 641 mu_observable_notify (observable, MU_EVT_AUTHORITY_FAILED, NULL);
642 CHECK_ERROR_CLOSE (mbox, mpd, EACCES); 642 CHECK_ERROR_CLOSE (mbox, mpd, EACCES);
643 } 643 }
644 mpd->state = POP_AUTH_DONE; 644 mpd->state = POP_AUTH_DONE;
...@@ -1255,11 +1255,14 @@ pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) ...@@ -1255,11 +1255,14 @@ pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
1255 return 0; 1255 return 0;
1256 for (i = msgno; i <= count; i++) 1256 for (i = msgno; i <= count; i++)
1257 { 1257 {
1258 if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD) != 0) 1258 size_t tmp = i;
1259 if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD,
1260 &tmp) != 0)
1259 break; 1261 break;
1260 if (((i +1) % 10) == 0) 1262 if (((i +1) % 10) == 0)
1261 { 1263 {
1262 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS); 1264 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_PROGRESS,
1265 NULL);
1263 } 1266 }
1264 } 1267 }
1265 return 0; 1268 return 0;
......
...@@ -305,7 +305,7 @@ mu_sieve_disass (mu_sieve_machine_t mach) ...@@ -305,7 +305,7 @@ mu_sieve_disass (mu_sieve_machine_t mach)
305 } 305 }
306 306
307 static int 307 static int
308 _sieve_action (mu_observer_t obs, size_t type) 308 _sieve_action (mu_observer_t obs, size_t type, void *data, void *action_data)
309 { 309 {
310 mu_sieve_machine_t mach; 310 mu_sieve_machine_t mach;
311 311
......
1 .deps
2 .gdbinit
3 .libs
4 Makefile
5 Makefile.in
6 maidag
1 # Copyright (C) 2007 Free Software Foundation, Inc.
2 #
3 # GNU Mailutils is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License as
5 # published by the Free Software Foundation; either version 3, or (at
6 # your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
16 # 02110-1301 USA
17
18 INCLUDES = -I${top_srcdir} @MU_COMMON_INCLUDES@ @GUILE_INCLUDES@
19
20 sbin_PROGRAMS=maidag
21 maidag_SOURCES=\
22 deliver.c\
23 lmtp.c\
24 maidag.c\
25 maidag.h\
26 mailtmp.c\
27 mailquota.c\
28 script.c\
29 util.c
30
31 maidag_LDADD = \
32 @LIBMU_SCM@ @GUILE_LIBS@\
33 @LIBMU_SCM_DEPS@\
34 ../lib/libmuaux.la \
35 ${MU_LIB_SIEVE}\
36 ${MU_LIB_MBOX}\
37 ${MU_LIB_IMAP}\
38 ${MU_LIB_POP}\
39 ${MU_LIB_NNTP}\
40 ${MU_LIB_MH}\
41 ${MU_LIB_MAILDIR}\
42 ${MU_LIB_AUTH}\
43 ${MU_LIB_MAILER}\
44 @MU_AUTHLIBS@\
45 ${MU_LIB_MAILUTILS} \
46 @MU_COMMON_LIBRARIES@
47
48 install-exec-hook:
49 for i in $(sbin_PROGRAMS); do\
50 chown root:mail $(DESTDIR)$(sbindir)/$$i;\
51 chmod 4755 $(DESTDIR)$(sbindir)/$$i;\
52 done
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2005,
3 2007 Free 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 void
23 make_tmp (const char *from, mu_mailbox_t *mbox)
24 {
25 struct mail_tmp *mtmp;
26 char *buf = NULL;
27 size_t n = 0;
28 int rc;
29
30 if (mail_tmp_begin (&mtmp, from))
31 exit (EX_TEMPFAIL);
32
33 while (getline (&buf, &n, stdin) > 0)
34 if ((rc = mail_tmp_add_line (mtmp, buf, strlen (buf))))
35 break;
36 free (buf);
37 if (rc == 0)
38 rc = mail_tmp_finish (mtmp, mbox);
39 mail_tmp_destroy (&mtmp);
40 if (rc)
41 exit (EX_TEMPFAIL);
42 }
43
44 int
45 mda (mu_mailbox_t mbx, char *username)
46 {
47 deliver (mbx, username, NULL);
48
49 if (multiple_delivery)
50 exit_code = EX_OK;
51
52 return exit_code;
53 }
54
55 int
56 maidag_stdio_delivery (int argc, char **argv)
57 {
58 mu_mailbox_t mbox;
59
60 make_tmp (sender_address, &mbox);
61
62 if (multiple_delivery)
63 multiple_delivery = argc > 1;
64
65 #ifdef WITH_GUILE
66 if (progfile_pattern)
67 {
68 struct mda_data mda_data;
69
70 memset (&mda_data, 0, sizeof mda_data);
71 mda_data.mbox = mbox;
72 mda_data.argv = argv;
73 mda_data.progfile_pattern = progfile_pattern;
74 return prog_mda (&mda_data);
75 }
76 #endif
77
78 for (; *argv; argv++)
79 mda (mbox, *argv);
80 return exit_code;
81 }
82
83 static int biff_fd = -1;
84 static struct sockaddr_in biff_in;
85 static char *biff_user_name;
86
87 static int
88 notify_action (mu_observer_t obs, size_t type, void *data, void *action_data)
89 {
90 if (type == MU_EVT_MESSAGE_APPEND)
91 {
92 mu_message_qid_t qid = data;
93 mu_mailbox_t mbox = mu_observer_get_owner (obs);
94 mu_url_t url;
95 char *buf;
96
97 mu_mailbox_get_url (mbox, &url);
98 asprintf (&buf, "%s@%s:%s", biff_user_name,
99 qid, mu_url_to_string (url));
100 if (buf)
101 {
102 sendto (biff_fd, buf, strlen (buf), 0,
103 (struct sockaddr *)&biff_in, sizeof biff_in);
104 free (buf);
105 }
106 }
107 return 0;
108 }
109
110 static void
111 attach_notify (mu_mailbox_t mbox)
112 {
113 struct servent *sp;
114 mu_observer_t observer;
115 mu_observable_t observable;
116
117 if (biff_fd == -1)
118 {
119 if ((sp = getservbyname ("biff", "udp")) == NULL)
120 {
121 biff_fd = -2;
122 return;
123 }
124 biff_in.sin_family = AF_INET;
125 biff_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
126 biff_in.sin_port = sp->s_port;
127
128 biff_fd = socket (PF_INET, SOCK_DGRAM, 0);
129 if (biff_fd < 0)
130 {
131 biff_fd = -2;
132 return;
133 }
134 }
135
136 if (biff_fd)
137 {
138 mu_observer_create (&observer, mbox);
139 mu_observer_set_action (observer, notify_action, mbox);
140 mu_mailbox_get_observable (mbox, &observable);
141 mu_observable_attach (observable, MU_EVT_MESSAGE_APPEND, observer);
142 }
143 }
144
145 int
146 deliver (mu_mailbox_t imbx, char *name, char **errp)
147 {
148 mu_mailbox_t mbox;
149 mu_message_t msg;
150 char *path;
151 mu_url_t url = NULL;
152 mu_locker_t lock;
153 struct mu_auth_data *auth;
154 int status;
155 int failed = 0;
156
157 auth = mu_get_auth_by_name (name);
158 if (!auth)
159 {
160 mailer_err (_("%s: no such user"), name);
161 if (errp)
162 asprintf (errp, "%s: no such user", name);
163 exit_code = EX_UNAVAILABLE;
164 return EX_UNAVAILABLE;
165 }
166 if (current_uid)
167 auth->change_uid = 0;
168
169 if (!sieve_test (auth, imbx))
170 {
171 exit_code = EX_OK;
172 mu_auth_data_free (auth);
173 return 0;
174 }
175
176 if ((status = mu_mailbox_get_message (imbx, 1, &msg)) != 0)
177 {
178 mailer_err (_("Cannot get message from the temporary mailbox: %s"),
179 mu_strerror (status));
180 mu_auth_data_free (auth);
181 return EX_TEMPFAIL;
182 }
183
184 if ((status = mu_mailbox_create (&mbox, auth->mailbox)) != 0)
185 {
186 mailer_err (_("Cannot open mailbox %s: %s"),
187 auth->mailbox, mu_strerror (status));
188 mu_auth_data_free (auth);
189 return EX_TEMPFAIL;
190 }
191
192 mu_mailbox_get_url (mbox, &url);
193 path = (char*) mu_url_to_string (url);
194
195 biff_user_name = name;
196
197 /* Actually open the mailbox. Switch to the user's euid to make
198 sure the maildrop file will have right privileges, in case it
199 will be created */
200 if (switch_user_id (auth, 1))
201 return EX_TEMPFAIL;
202 status = mu_mailbox_open (mbox, MU_STREAM_APPEND|MU_STREAM_CREAT);
203 if (switch_user_id (auth, 0))
204 return EX_TEMPFAIL;
205
206 if (status != 0)
207 {
208 mailer_err (_("Cannot open mailbox %s: %s"), path, mu_strerror (status));
209 mu_mailbox_destroy (&mbox);
210 return EX_TEMPFAIL;
211 }
212
213 attach_notify (mbox);
214
215 /* FIXME: This is superfluous, as mu_mailbox_append_message takes care
216 of locking anyway. But I leave it here for the time being. */
217 mu_mailbox_get_locker (mbox, &lock);
218
219 if (lock)
220 {
221 status = mu_locker_lock (lock);
222
223 if (status)
224 {
225 mailer_err (_("Cannot lock mailbox `%s': %s"), path,
226 mu_strerror (status));
227 mu_mailbox_destroy (&mbox);
228 exit_code = EX_TEMPFAIL;
229 return EX_TEMPFAIL;
230 }
231 }
232
233 #if defined(USE_MAILBOX_QUOTAS)
234 {
235 mu_off_t n;
236 mu_off_t msg_size;
237 mu_off_t mbsize;
238
239 if ((status = mu_mailbox_get_size (mbox, &mbsize)))
240 {
241 mailer_err (_("Cannot get size of mailbox %s: %s"),
242 path, mu_strerror (status));
243 if (status == ENOSYS)
244 mbsize = 0; /* Try to continue anyway */
245 else
246 {
247 mu_mailbox_destroy (&mbox);
248 return EX_TEMPFAIL;
249 }
250 }
251
252 switch (check_quota (auth, mbsize, &n))
253 {
254 case MQUOTA_EXCEEDED:
255 mailer_err (_("%s: mailbox quota exceeded for this recipient"), name);
256 if (errp)
257 asprintf (errp, "%s: mailbox quota exceeded for this recipient",
258 name);
259 exit_code = EX_QUOTA();
260 failed++;
261 break;
262
263 case MQUOTA_UNLIMITED:
264 break;
265
266 default:
267 if ((status = mu_mailbox_get_size (imbx, &msg_size)))
268 {
269 mailer_err (_("Cannot get message size (input message %s): %s"),
270 path, mu_strerror (status));
271 exit_code = EX_UNAVAILABLE;
272 failed++;
273 }
274 else if (msg_size > n)
275 {
276 mailer_err (_("%s: message would exceed maximum mailbox size for "
277 "this recipient"),
278 name);
279 if (errp)
280 asprintf (errp,
281 "%s: message would exceed maximum mailbox size "
282 "for this recipient",
283 name);
284 exit_code = EX_QUOTA();
285 failed++;
286 }
287 break;
288 }
289 }
290 #endif
291
292 if (!failed && switch_user_id (auth, 1) == 0)
293 {
294 status = mu_mailbox_append_message (mbox, msg);
295 if (status)
296 {
297 mailer_err (_("Error writing to mailbox %s: %s"),
298 path, mu_strerror (status));
299 failed++;
300 }
301 else
302 {
303 status = mu_mailbox_sync (mbox);
304 if (status)
305 {
306 mailer_err (_("Error flushing mailbox %s: %s"),
307 path, mu_strerror (status));
308 failed++;
309 }
310 }
311 switch_user_id (auth, 0);
312 }
313
314 mu_auth_data_free (auth);
315 mu_mailbox_close (mbox);
316 mu_locker_unlock (lock);
317 mu_mailbox_destroy (&mbox);
318 return failed ? exit_code : 0;
319 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301 USA */
18
19 #include "maidag.h"
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <netdb.h>
23 #include <sys/un.h>
24 #include <sys/wait.h>
25 #include <signal.h>
26 #include <mu_umaxtostr.h>
27
28 typedef union
29 {
30 struct sockaddr sa;
31 struct sockaddr_in s_in;
32 struct sockaddr_un s_un;
33 } all_addr_t;
34
35 static int
36 lmtp_open_internal (int *pfd, mu_url_t url, const char *urlstr)
37 {
38 int fd;
39 int rc;
40 int t = 1;
41 char buffer[64];
42 all_addr_t addr;
43 int addrsize;
44 mode_t saved_umask;
45
46 rc = mu_url_get_scheme (url, buffer, sizeof buffer, NULL);
47 if (rc)
48 {
49 mu_error (_("%s: cannot get scheme from URL: %s"),
50 urlstr, mu_strerror(rc));
51 return EX_CONFIG;
52 }
53
54 memset (&addr, 0, sizeof addr);
55 if (strcmp (buffer, "file") == 0 || strcmp (buffer, "socket") == 0)
56 {
57 size_t size;
58
59 rc = mu_url_get_path (url, NULL, 0, &size);
60 if (rc)
61 {
62 mu_error (_("%s: cannot get path: %s"), urlstr, mu_strerror(rc));
63 return EX_CONFIG;
64 }
65
66 if (size > sizeof addr.s_un.sun_path - 1)
67 {
68 mu_error (_("%s: file name too long"), urlstr);
69 return EX_TEMPFAIL;
70 }
71 mu_url_get_path (url, addr.s_un.sun_path, sizeof addr.s_un.sun_path,
72 NULL);
73
74 fd = socket (PF_UNIX, SOCK_STREAM, 0);
75 if (fd < 0)
76 {
77 mu_error ("socket: %s", mu_strerror (errno));
78 return EX_TEMPFAIL;
79 }
80
81 addr.s_un.sun_family = AF_UNIX;
82 addrsize = sizeof addr.s_un;
83
84 if (reuse_lmtp_address)
85 {
86 struct stat st;
87 if (stat (addr.s_un.sun_path, &st))
88 {
89 if (errno != ENOENT)
90 {
91 mu_error (_("file %s exists but cannot be stat'd"),
92 addr.s_un.sun_path);
93 return EX_TEMPFAIL;
94 }
95 }
96 else if (!S_ISSOCK (st.st_mode))
97 {
98 mu_error (_("file %s is not a socket"),
99 addr.s_un.sun_path);
100 return EX_TEMPFAIL;
101 }
102 else
103 unlink (addr.s_un.sun_path);
104 }
105
106 }
107 else if (strcmp (buffer, "tcp") == 0)
108 {
109 size_t size;
110 long n;
111 struct hostent *hp;
112 char *path = NULL;
113 short port = 0;
114
115 rc = mu_url_get_port (url, &n);
116 if (rc)
117 {
118 mu_error (_("%s: cannot get port: %s"), urlstr, mu_strerror(rc));
119 return EX_CONFIG;
120 }
121
122 if (n == 0 || (port = n) != n)
123 {
124 mu_error (_("Port out of range: %ld"), n);
125 return EX_CONFIG;
126 }
127
128 rc = mu_url_get_host (url, NULL, 0, &size);
129 if (rc)
130 {
131 mu_error (_("%s: cannot get host: %s"), urlstr, mu_strerror(rc));
132 return EX_CONFIG;
133 }
134 path = malloc (size + 1);
135 if (!path)
136 {
137 mu_error (_("Not enough memory"));
138 return EX_TEMPFAIL;
139 }
140 mu_url_get_host (url, path, size + 1, NULL);
141
142 fd = socket (PF_INET, SOCK_STREAM, 0);
143 if (fd < 0)
144 {
145 mu_error ("socket: %s", mu_strerror (errno));
146 return EX_TEMPFAIL;
147 }
148
149 addr.s_in.sin_family = AF_INET;
150 hp = gethostbyname (path);
151 if (hp)
152 {
153 char **ap;
154 int count = 0;
155
156 addr.s_in.sin_addr.s_addr = *(unsigned long*) hp->h_addr_list[0];
157
158 for (ap = hp->h_addr_list; *ap; ap++)
159 count++;
160 if (count > 1)
161 mu_error (_("warning: %s has several IP addresses, using %s"),
162 path, inet_ntoa (addr.s_in.sin_addr));
163 }
164 else if (inet_aton (path, &addr.s_in.sin_addr) == 0)
165 {
166 mu_error ("invalid IP address: %s", path);
167 return EX_TEMPFAIL;
168 }
169 addr.s_in.sin_port = htons (port);
170 addrsize = sizeof addr.s_in;
171
172 if (reuse_lmtp_address)
173 setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t));
174 }
175 else
176 {
177 mu_error (_("%s: invalid scheme"), urlstr);
178 return EX_CONFIG;
179 }
180
181 saved_umask = umask (0117);
182 if (bind (fd, &addr.sa, addrsize) == -1)
183 {
184 mu_error ("bind: %s", strerror (errno));
185 close (fd);
186 return EXIT_FAILURE;
187 }
188 umask (saved_umask);
189 *pfd = fd;
190 return 0;
191 }
192
193 int
194 lmtp_open (int *pfd, char *urlstr)
195 {
196 mu_url_t url = NULL;
197 int rc;
198
199 rc = mu_url_create (&url, urlstr);
200 if (rc)
201 {
202 mu_error (_("%s: cannot create URL: %s"),
203 urlstr, mu_strerror (rc));
204 return EX_CONFIG;
205 }
206 rc = mu_url_parse (url);
207 if (rc)
208 {
209 mu_error (_("%s: error parsing URL: %s"),
210 urlstr, mu_strerror(rc));
211 return EX_CONFIG;
212 }
213
214 rc = lmtp_open_internal (pfd, url, urlstr);
215 mu_url_destroy (&url);
216 return rc;
217 }
218
219 size_t children;
220 static int need_cleanup = 0;
221
222 void
223 process_cleanup ()
224 {
225 pid_t pid;
226 int status;
227
228 if (need_cleanup)
229 {
230 need_cleanup = 0;
231 while ( (pid = waitpid (-1, &status, WNOHANG)) > 0)
232 --children;
233 }
234 }
235
236 RETSIGTYPE
237 lmtp_sigchld (int signo MU_ARG_UNUSED)
238 {
239 need_cleanup = 1;
240 #ifndef HAVE_SIGACTION
241 signal (signo, lmtp_sigchld);
242 #endif
243 }
244
245 void
246 lmtp_reply (FILE *fp, char *code, char *enh, char *fmt, ...)
247 {
248 va_list ap;
249 char *str;
250
251 va_start (ap, fmt);
252 vasprintf (&str, fmt, ap);
253 va_end (ap);
254
255 if (daemon_param.transcript)
256 {
257 if (enh)
258 syslog (LOG_INFO, "LMTP reply: %s %s %s", code, enh, str);
259 else
260 syslog (LOG_INFO, "LMTP reply: %s %s", code, str);
261 }
262
263 if (!str)
264 {
265 mu_error (_("Not enough memory"));
266 exit (EX_TEMPFAIL);
267 }
268
269 while (*str)
270 {
271 char *end = strchr (str, '\n');
272
273 if (end)
274 {
275 size_t len = end - str;
276 fprintf (fp, "%s-", code);
277 if (enh)
278 fprintf (fp, "%s ", enh);
279 fprintf (fp, "%.*s\r\n", len, str);
280 for (str = end; *str && *str == '\n'; str++);
281 }
282 else
283 {
284 fprintf (fp, "%s ", code);
285 if (enh)
286 fprintf (fp, "%s ", enh);
287 fprintf (fp, "%s\r\n", str);
288 str += strlen (str);
289 }
290 }
291 }
292
293 void
294 trimnl (char *arg)
295 {
296 size_t len = strlen (arg);
297 if (len > 0 && arg[len-1] == '\n')
298 arg[--len] = 0;
299 if (len > 0 && arg[len-1] == '\r')
300 arg[--len] = 0;
301 }
302
303 void
304 xlatnl (char *arg)
305 {
306 size_t len = strlen (arg);
307 if (len > 0 && arg[len-1] == '\n')
308 {
309 len--;
310 if (len > 0 && arg[len-1] == '\r')
311 {
312 arg[len-1] = '\n';
313 arg[len] = 0;
314 }
315 }
316 }
317
318
319 enum lmtp_state
320 {
321 state_none,
322
323 state_init,
324 state_lhlo,
325 state_mail,
326 state_rcpt,
327 state_data,
328 state_quit,
329 state_dot,
330
331 state_end
332 };
333
334 #define NSTATE ((int) state_end + 1)
335
336 enum lmtp_command
337 {
338 cmd_unknown,
339 cmd_lhlo,
340 cmd_mail,
341 cmd_rcpt,
342 cmd_data,
343 cmd_quit,
344 cmd_rset,
345 cmd_help,
346 cmd_dot
347 };
348
349 #define NCMD ((int)cmd_dot + 1)
350
351 #define SNO state_none
352 #define SIN state_init
353 #define SHL state_lhlo
354 #define SML state_mail
355 #define SRC state_rcpt
356 #define SDA state_data
357 #define SQT state_quit
358 #define SDT state_dot
359 #define SEN state_end
360
361 int transtab[NCMD][NSTATE] = {
362 /* state_ SNO SIN SHL SML SRC SDA SQT SDT SEN */
363 /* unkn */ { SNO, SNO, SNO, SNO, SNO, SNO, SNO, SNO, SEN },
364 /* lhlo */ { SNO, SHL, SNO, SNO, SNO, SNO, SNO, SNO, SNO },
365 /* mail */ { SNO, SNO, SML, SNO, SNO, SNO, SNO, SNO, SNO },
366 /* rcpt */ { SNO, SNO, SNO, SRC, SRC, SNO, SNO, SNO, SNO },
367 /* data */ { SNO, SNO, SNO, SNO, SDA, SNO, SNO, SNO, SNO },
368 /* quit */ { SNO, SEN, SEN, SEN, SEN, SEN, SEN, SEN, SEN },
369 /* rset */ { SNO, SIN, SIN, SIN, SIN, SIN, SIN, SIN, SNO },
370 /* help */ { SNO, SIN, SHL, SML, SRC, SDT, SQT, SDT, SEN },
371 /* dot */ { SNO, SNO, SNO, SNO, SNO, SQT, SNO, SNO, SNO },
372 };
373
374
375 /* Delivery data */
376 char *lhlo_domain; /* Sender domain */
377 char *mail_from; /* Sender address */
378 mu_list_t rcpt_list; /* Recipient addresses */
379 struct mail_tmp *mtmp; /* Temporary mail storage */
380 mu_mailbox_t mbox; /* Collected mail body */
381
382 static void
383 rcpt_to_destroy_item (void *ptr)
384 {
385 free (ptr);
386 }
387
388
389 int
390 cfun_unknown (FILE *out, char *arg)
391 {
392 lmtp_reply (out, "500", "5.5.1", "Command unrecognized");
393 return 0;
394 }
395
396
397 static void
398 add_default_domain (char *str, int len, char **pret)
399 {
400 *pret = malloc (len + 1 + strlen (lhlo_domain) + 1);
401 if (!*pret)
402 {
403 mu_error (_("Not enough memory"));
404 exit (EX_SOFTWARE);
405 }
406 memcpy (*pret, str, len);
407 (*pret)[len] = '@';
408 strcpy (*pret + len + 1, lhlo_domain);
409 }
410
411 #define MAILER_DAEMON "MAILER-DAEMON"
412
413 int
414 check_address (char *arg, int with_domain, char **pret)
415 {
416 if (strchr (arg, '@') == 0)
417 {
418 char *addr = NULL;
419 size_t addrlen = 0;
420
421 if (*arg == '<')
422 {
423 size_t len = strlen (arg);
424 if (arg[len - 1] == '>')
425 {
426 if (len == 2) /* null address */
427 {
428 if (!with_domain)
429 /* Null address is only legal in mail from */
430 return 1;
431 addr = MAILER_DAEMON;
432 addrlen = sizeof MAILER_DAEMON - 1;
433 }
434 else
435 {
436 addr = arg + 1;
437 addrlen = len - 2;
438 }
439 }
440 else
441 return 1;
442 }
443 else
444 {
445 addr = arg;
446 addrlen = strlen (arg);
447 }
448
449 if (with_domain)
450 add_default_domain (addr, addrlen, pret);
451 else
452 {
453 *pret = malloc (addrlen + 1);
454 memcpy (*pret, addr, addrlen);
455 (*pret)[addrlen] = 0;
456 }
457 }
458 else
459 {
460 mu_address_t addr;
461 int rc = mu_address_create (&addr, arg);
462 if (rc)
463 return 1;
464 if (with_domain)
465 mu_address_aget_email (addr, 1, pret);
466 else
467 mu_address_aget_local_part (addr, 1, pret);
468 mu_address_destroy (&addr);
469 }
470 return 0;
471 }
472
473
474 int
475 cfun_mail_from (FILE *out, char *arg)
476 {
477 if (*arg == 0)
478 {
479 lmtp_reply (out, "501", "5.5.2", "Oj-ej");
480 return 1;
481 }
482
483 if (check_address (arg, 1, &mail_from))
484 {
485 lmtp_reply (out, "553", "5.1.8", "Pomyliles sie");
486 return 1;
487 }
488 lmtp_reply (out, "250", "2.1.0", "Moje ty sloneczko");
489 return 0;
490 }
491
492
493 int
494 cfun_rcpt_to (FILE *out, char *arg)
495 {
496 char *user;
497 struct mu_auth_data *auth;
498
499 if (*arg == 0)
500 {
501 lmtp_reply (out, "501", "5.5.2", "Oj-ej");
502 return 1;
503 }
504
505 /* FIXME: Check if domain is OK */
506 if (check_address (arg, 0, &user))
507 {
508 lmtp_reply (out, "553", "5.1.8", "Pomyliles sie");
509 return 1;
510 }
511 auth = mu_get_auth_by_name (user);
512 if (!auth)
513 {
514 lmtp_reply (out, "550", "5.1.1", "Hm, nie znam takiego");
515 free (user);
516 return 1;
517 }
518 mu_auth_data_free (auth);
519 if (!rcpt_list)
520 {
521 mu_list_create (&rcpt_list);
522 mu_list_set_destroy_item (rcpt_list, rcpt_to_destroy_item);
523 }
524 mu_list_append (rcpt_list, user);
525 lmtp_reply (out, "250", "2.1.5", "%s bedzie uszczesliwiony", user);
526 return 0;
527 }
528
529
530 int
531 cfun_data (FILE *out, char *arg)
532 {
533 if (*arg)
534 {
535 lmtp_reply (out, "501", "5.5.2", "Co za bzdury?");
536 return 1;
537 }
538
539 if (mail_tmp_begin (&mtmp, mail_from))
540 {
541 /* FIXME: codes */
542 lmtp_reply (out, "450", "4.1.0", "Cos mi nieswojo, moze pozniej...");
543 return 1;
544 }
545 lmtp_reply (out, "354", NULL, "Jazda!");
546 return 0;
547 }
548
549
550 int
551 dot_temp_fail (void *item, void *cbdata)
552 {
553 char *name = item;
554 FILE *out = cbdata;
555 lmtp_reply (out, "450", "4.1.0", "%s: cos nawalilo, sprobuj pozniej", name);
556 return 0;
557 }
558
559 int
560 dot_deliver (void *item, void *cbdata)
561 {
562 char *name = item;
563 FILE *out = cbdata;
564 char *errp = NULL;
565
566 switch (deliver (mbox, name, &errp))
567 {
568 case 0:
569 lmtp_reply (out, "250", "2.0.0", "%s: dostarczono", name);
570 break;
571
572 case EX_UNAVAILABLE:
573 if (errp)
574 lmtp_reply (out, "553", "5.1.8", "%s", errp);
575 else
576 lmtp_reply (out, "553", "5.1.8", "%s: nie dostarczono", name);
577 break;
578
579 default:
580 if (errp)
581 lmtp_reply (out, "450", "4.1.0", "%s", errp);
582 else
583 lmtp_reply (out, "450", "4.1.0", "%s: cos nawalilo, sprobuj pozniej",
584 name);
585 break;
586 }
587 free (errp);
588 return 0;
589 }
590
591 int
592 cfun_dot (FILE *out, char *arg)
593 {
594 if (!mtmp)
595 mu_list_do (rcpt_list, dot_temp_fail, out);
596 else
597 {
598 int rc = mail_tmp_finish (mtmp, &mbox);
599 if (rc)
600 mu_list_do (rcpt_list, dot_temp_fail, out);
601 else
602 {
603 mu_list_do (rcpt_list, dot_deliver, out);
604 mail_tmp_destroy (&mtmp);
605 mu_mailbox_destroy (&mbox);
606 }
607 }
608 free (mail_from);
609 mu_list_destroy (&rcpt_list);
610 return 0;
611 }
612
613
614 int
615 cfun_rset (FILE *out, char *arg)
616 {
617 free (lhlo_domain);
618 free (mail_from);
619 mu_list_destroy (&rcpt_list);
620 mail_tmp_destroy (&mtmp);
621 mu_mailbox_destroy (&mbox);
622 lmtp_reply (out, "250", "2.0.0", "Dobrze, zapomnialem");
623 return 0;
624 }
625
626
627 char *capa_str = "ENHANCEDSTATUSCODES\n\
628 PIPELINING\n\
629 8BITMIME\n\
630 HELP";
631
632 int
633 cfun_lhlo (FILE *out, char *arg)
634 {
635 if (*arg == 0)
636 {
637 lmtp_reply (out, "501", "5.0.0", "Czy to wszystko?");
638 return 1;
639 }
640 lhlo_domain = strdup (arg);
641 lmtp_reply (out, "250", NULL, "Czolem\n");
642 lmtp_reply (out, "250", NULL, capa_str);
643 return 0;
644 }
645
646
647 int
648 cfun_quit (FILE *out, char *arg)
649 {
650 lmtp_reply (out, "221", "2.0.0", "Na razie");
651 return 0;
652 }
653
654
655 int
656 cfun_help (FILE *out, char *arg)
657 {
658 lmtp_reply (out, "200", "2.0.0", "Czlowieku, pomagaj sobie sam");
659 return 0;
660 }
661
662
663 struct command_tab
664 {
665 char *cmd_verb;
666 int cmd_len;
667 enum lmtp_command cmd_code;
668 int (*cmd_fun) (FILE *, char *);
669 } command_tab[] = {
670 #define S(s) #s, (sizeof #s - 1)
671 { S(lhlo), cmd_lhlo, cfun_lhlo },
672 { S(mail from:), cmd_mail, cfun_mail_from },
673 { S(rcpt to:), cmd_rcpt, cfun_rcpt_to },
674 { S(data), cmd_data, cfun_data },
675 { S(quit), cmd_quit, cfun_quit },
676 { S(rset), cmd_rset, cfun_rset },
677 { S(help), cmd_help, cfun_help },
678 { S(.), cmd_dot, cfun_dot },
679 { NULL, 0, cmd_unknown, cfun_unknown }
680 };
681
682 struct command_tab *
683 getcmd (char *buf, char **sp)
684 {
685 struct command_tab *cp;
686 size_t len = strlen (buf);
687 for (cp = command_tab; cp->cmd_verb; cp++)
688 {
689 if (cp->cmd_len <= len
690 && strncasecmp (cp->cmd_verb, buf, cp->cmd_len) == 0)
691 {
692 *sp = buf + cp->cmd_len;
693 return cp;
694 }
695 }
696 return cp;
697 }
698
699 int
700 lmtp_loop (FILE *in, FILE *out)
701 {
702 char buf[1024];
703 enum lmtp_state state = state_init;
704
705 setvbuf (in, NULL, _IOLBF, 0);
706 setvbuf (out, NULL, _IOLBF, 0);
707
708 lmtp_reply (out, "220", NULL, "Do uslug");
709 while (fgets (buf, sizeof buf, in))
710 {
711 if (state == state_data
712 && !(buf[0] == '.'
713 && (buf[1] == '\n' || (buf[1] == '\r' && buf[2] == '\n'))))
714 {
715 /* This is a special case */
716 if (mtmp)
717 {
718 size_t len;
719 int rc;
720
721 xlatnl (buf);
722 len = strlen (buf);
723 if ((rc = mail_tmp_add_line (mtmp, buf, len)))
724 {
725 mail_tmp_destroy (&mtmp);
726 /* Wait the dot to report the error */
727 }
728 }
729 }
730 else
731 {
732 char *sp;
733 struct command_tab *cp = getcmd (buf, &sp);
734 enum lmtp_command cmd = cp->cmd_code;
735 enum lmtp_state next_state = transtab[cmd][state];
736
737 trimnl (buf);
738
739 if (daemon_param.transcript)
740 syslog (LOG_INFO, "LMTP recieve: %s", buf);
741
742 if (next_state != state_none)
743 {
744 if (cp->cmd_fun)
745 {
746 while (*sp && isspace (*sp))
747 sp++;
748 if (cp->cmd_fun (out, sp))
749 continue;
750 }
751 state = next_state;
752 }
753 else
754 lmtp_reply (out, "503", "5.0.0", "Syntax error");
755 }
756
757 if (state == state_end)
758 break;
759 }
760 return 0;
761 }
762
763 void
764 log_connection (all_addr_t *addr, socklen_t addrlen)
765 {
766 switch (addr->sa.sa_family)
767 {
768 case PF_UNIX:
769 syslog (LOG_INFO, _("connect from socket"));
770 break;
771
772 case PF_INET:
773 syslog (LOG_INFO, _("connect from %s"), inet_ntoa (addr->s_in.sin_addr));
774 }
775 }
776
777 int
778 lmtp_daemon (char *urlstr)
779 {
780 int rc;
781 int listenfd, connfd;
782 all_addr_t addr;
783 socklen_t addrlen;
784 pid_t pid;
785
786 if (daemon_param.mode == MODE_DAEMON)
787 {
788 if (daemon (0, 0) < 0)
789 {
790 mu_error (_("Failed to become a daemon"));
791 return EX_UNAVAILABLE;
792 }
793 }
794
795 rc = lmtp_open (&listenfd, urlstr);
796 if (rc)
797 return rc;
798
799 if (listen (listenfd, 128) == -1)
800 {
801 mu_error ("listen: %s", strerror (errno));
802 close (listenfd);
803 return EX_UNAVAILABLE;
804 }
805
806 #ifdef HAVE_SIGACTION
807 {
808 struct sigaction act;
809 act.sa_handler = lmtp_sigchld;
810 sigemptyset (&act.sa_mask);
811 act.sa_flags = 0;
812 sigaction (SIGCHLD, &act, NULL);
813 }
814 #else
815 signal (SIGCHLD, lmtp_sigchld);
816 #endif
817
818 for (;;)
819 {
820 process_cleanup ();
821 if (children > daemon_param.maxchildren)
822 {
823 mu_error (_("too many children (%lu)"),
824 (unsigned long) children);
825 pause ();
826 continue;
827 }
828 addrlen = sizeof addr;
829 connfd = accept (listenfd, (struct sockaddr *)&addr, &addrlen);
830 if (connfd == -1)
831 {
832 if (errno == EINTR)
833 continue;
834 mu_error ("accept: %s", strerror (errno));
835 continue;
836 /*exit (EXIT_FAILURE);*/
837 }
838
839 log_connection (&addr, addrlen);
840
841 pid = fork ();
842 if (pid == -1)
843 syslog (LOG_ERR, "fork: %s", strerror (errno));
844 else if (pid == 0) /* Child. */
845 {
846 int status;
847
848 close (listenfd);
849 status = lmtp_loop (fdopen (connfd, "r"), fdopen (connfd, "w"));
850 exit (status);
851 }
852 else
853 {
854 ++children;
855 }
856 close (connfd);
857 }
858 }
859
860 #define DEFAULT_URL "tcp://127.0.0.1:"
861
862 int
863 maidag_lmtp_server ()
864 {
865 struct group *gr = getgrnam (lmtp_group);
866
867 if (gr == NULL)
868 {
869 mu_error (_("Error getting mail group"));
870 return EX_UNAVAILABLE;
871 }
872
873 if (setgid (gr->gr_gid) == -1)
874 {
875 mu_error (_("Error setting mail group"));
876 return EX_UNAVAILABLE;
877 }
878
879 if (lmtp_url_string)
880 return lmtp_daemon (lmtp_url_string);
881 else if (daemon_param.mode == MODE_INTERACTIVE)
882 return lmtp_loop (stdin, stdout);
883 else
884 {
885 const char *pstr = mu_umaxtostr (0, daemon_param.port);
886 char *urls = malloc (sizeof (DEFAULT_URL) + strlen (pstr));
887 if (!urls)
888 {
889 mu_error (_("Not enough memory"));
890 return EX_TEMPFAIL;
891 }
892 strcpy (urls, DEFAULT_URL);
893 strcat (urls, pstr);
894 return lmtp_daemon (urls);
895 }
896 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301 USA */
18
19 #include "maidag.h"
20
21 int multiple_delivery; /* Don't return errors when delivering to multiple
22 recipients */
23 int ex_quota_tempfail; /* Return temporary failure if mailbox quota is
24 exceeded. If this variable is not set, maidag
25 will return "service unavailable" */
26 int exit_code = EX_OK; /* Exit code to be used */
27 uid_t current_uid; /* Current user id */
28
29 char *quotadbname = NULL; /* Name of mailbox quota database */
30 char *quota_query = NULL; /* SQL query to retrieve mailbox quota */
31
32 char *sender_address = NULL;
33 char *progfile_pattern = NULL;
34 char *sieve_pattern = NULL;
35
36 int log_to_stderr = -1;
37
38 /* Debuggig options */
39 int debug_level; /* General debugging level */
40 int debug_flags; /* Mailutils debugging flags */
41 int sieve_debug_flags; /* Sieve debugging flags */
42 int sieve_enable_log; /* Enables logging of executed Sieve actions */
43 char *message_id_header; /* Use the value of this header as message
44 identifier when logging Sieve actions */
45 mu_debug_t mudebug; /* Mailutils debugging object */
46
47 /* For LMTP mode */
48 int lmtp_mode;
49 char *lmtp_url_string;
50 int reuse_lmtp_address = 1;
51 char *lmtp_group = "mail";
52
53 struct daemon_param daemon_param = {
54 MODE_INTERACTIVE, /* Start in interactive (inetd) mode */
55 20, /* Default maximum number of children */
56 0, /* No standard port */
57 600, /* Idle timeout */
58 0, /* No transcript by default */
59 NULL /* No PID file by default */
60 };
61
62 const char *program_version = "maidag (" PACKAGE_STRING ")";
63 static char doc[] =
64 N_("GNU maildag -- the mail delivery agent")
65 "\v"
66 N_("Debug flags are:\n\
67 g - guimb stack traces\n\
68 T - mailutils traces (MU_DEBUG_TRACE)\n\
69 P - network protocols (MU_DEBUG_PROT)\n\
70 t - sieve trace (MU_SIEVE_DEBUG_TRACE)\n\
71 i - sieve instructions trace (MU_SIEVE_DEBUG_INSTR)\n\
72 l - sieve action logs\n\
73 0-9 - Set mail.local debugging level\n");
74
75 static char args_doc[] = N_("[recipient...]");
76
77 #define STDERR_OPTION 256
78 #define MESSAGE_ID_HEADER_OPTION 257
79 #define LMTP_OPTION 258
80
81 static struct argp_option options[] =
82 {
83 { "from", 'f', N_("EMAIL"), 0,
84 N_("Specify the sender's name") },
85 { NULL, 'r', NULL, OPTION_ALIAS, NULL },
86 { "sieve", 'S', N_("PATTERN"), 0,
87 N_("Set name pattern for user-defined Sieve mail filters"), 0 },
88 { "message-id-header", MESSAGE_ID_HEADER_OPTION, N_("STRING"), 0,
89 N_("Identify messages by the value of this header when logging Sieve actions"), 0 },
90 #ifdef WITH_GUILE
91 { "source", 's', N_("PATTERN"), 0,
92 N_("Set name pattern for user-defined Scheme mail filters"), 0 },
93 #endif
94 { "lmtp", LMTP_OPTION, N_("URL"), OPTION_ARG_OPTIONAL,
95 N_("Operate in LMTP mode"), 0 },
96 { "debug", 'x', N_("FLAGS"), 0,
97 N_("Enable debugging"), 0 },
98 { "stderr", STDERR_OPTION, NULL, 0,
99 N_("Log to standard error"), 0 },
100 { NULL, 0, NULL, 0, NULL, 0 }
101 };
102
103 static error_t parse_opt (int key, char *arg, struct argp_state *state);
104
105 static struct argp argp = {
106 options,
107 parse_opt,
108 args_doc,
109 doc,
110 NULL,
111 NULL, NULL
112 };
113
114 static const char *argp_capa[] = {
115 "daemon",
116 "auth",
117 "common",
118 "license",
119 "logging",
120 "mailbox",
121 "mailer",
122 "sieve",
123 NULL
124 };
125
126 #define D_DEFAULT "9,s"
127
128 static void
129 set_debug_flags (const mu_cfg_locus_t *locus, const char *arg)
130 {
131 while (*arg)
132 {
133 if (isdigit (*arg))
134 debug_level = strtoul (arg, (char**)&arg, 10);
135 else
136 for (; *arg && *arg != ','; arg++)
137 {
138 switch (*arg)
139 {
140 case 'g':
141 #ifdef WITH_GUILE
142 debug_guile = 1;
143 #endif
144 break;
145
146 case 't':
147 sieve_debug_flags |= MU_SIEVE_DEBUG_TRACE;
148 break;
149
150 case 'i':
151 sieve_debug_flags |= MU_SIEVE_DEBUG_INSTR;
152 break;
153
154 case 'l':
155 sieve_enable_log = 1;
156 break;
157
158 case 'T':
159 debug_flags |= MU_DEBUG_TRACE;
160 break;
161
162 case 'P':
163 debug_flags |= MU_DEBUG_PROT;
164 break;
165
166 default:
167 if (locus)
168 mu_error (_("%s:%d: %c is not a valid debug flag"),
169 locus->file, locus->line, *arg);
170 else
171 mu_error (_("%c is not a valid debug flag"), *arg);
172 break;
173 }
174 }
175 if (*arg == ',')
176 arg++;
177 else if (locus)
178 mu_error (_("%s:%d: expected comma, but found %c"),
179 locus->file, locus->line, *arg);
180 else
181 mu_error (_("expected comma, but found %c"), *arg);
182 }
183 }
184
185 static error_t
186 parse_opt (int key, char *arg, struct argp_state *state)
187 {
188 switch (key)
189 {
190 case ARGP_KEY_INIT:
191 state->child_inputs[0] = state->input;
192 break;
193
194 case MESSAGE_ID_HEADER_OPTION:
195 message_id_header = arg;
196 break;
197
198 case LMTP_OPTION:
199 lmtp_mode = 1;
200 lmtp_url_string = arg;
201 break;
202
203 case 'r':
204 case 'f':
205 if (sender_address != NULL)
206 {
207 argp_error (state, _("Multiple --from options"));
208 return EX_USAGE;
209 }
210 sender_address = arg;
211 break;
212
213 #ifdef WITH_GUILE
214 case 's':
215 progfile_pattern = arg;
216 break;
217 #endif
218
219 case 'S':
220 sieve_pattern = arg;
221 break;
222
223 case 'x':
224 set_debug_flags (NULL, arg ? arg : D_DEFAULT);
225 break;
226
227 case STDERR_OPTION:
228 log_to_stderr = 1;
229 break;
230
231 default:
232 return ARGP_ERR_UNKNOWN;
233
234 case ARGP_KEY_ERROR:
235 exit (EX_USAGE);
236 }
237 return 0;
238 }
239
240
241
242 static int
243 cb_debug (mu_cfg_locus_t *locus, void *data, char *arg)
244 {
245 set_debug_flags (locus, arg);
246 return 0;
247 }
248
249 struct mu_cfg_param maidag_cfg_param[] = {
250 { "exit-multiple-delivery-success", mu_cfg_bool, &multiple_delivery },
251 { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail },
252 #ifdef USE_DBM
253 { "quota-db", mu_cfg_string, &quotadbname },
254 #endif
255 #ifdef USE_SQL
256 { "quota-query", mu_cfg_string, &quota_query },
257 #endif
258 { "sieve", mu_cfg_string, &sieve_pattern },
259 { "message-id-header", mu_cfg_string, &message_id_header },
260 #ifdef WITH_GUILE
261 { "source", mu_cfg_string, &progfile_pattern },
262 #endif
263 { "debug", mu_cfg_callback, NULL, cb_debug },
264 { "stderr", mu_cfg_bool, &log_to_stderr },
265 /* LMTP support */
266 { "lmtp", mu_cfg_bool, &lmtp_mode },
267 { "group", mu_cfg_string, &lmtp_group },
268 { "listen", mu_cfg_string, &lmtp_url_string },
269 { "reuse-address", mu_cfg_bool, &reuse_lmtp_address },
270 { NULL }
271 };
272
273
274 /* Logging */
275 static int
276 _mu_debug_printer (mu_debug_t unused, size_t level, const char *fmt,
277 va_list ap)
278 {
279 if (log_to_stderr)
280 {
281 fprintf (stderr, "%s: ", (level == MU_DEBUG_ERROR) ? "ERROR" : "DEBUG");
282 vfprintf (stderr, fmt, ap);
283 fputc ('\n', stderr);
284 }
285 else
286 vsyslog ((level == MU_DEBUG_ERROR) ? LOG_ERR : LOG_DEBUG, fmt, ap);
287 return 0;
288 }
289
290 static int
291 _sieve_debug_printer (void *unused, const char *fmt, va_list ap)
292 {
293 if (log_to_stderr)
294 {
295 fprintf (stderr, "DEBUG: ");
296 vfprintf (stderr, fmt, ap);
297 fputc ('\n', stderr);
298 }
299 else
300 vsyslog (LOG_DEBUG, fmt, ap);
301 return 0;
302 }
303
304 static void
305 _sieve_action_log (void *user_name,
306 const mu_sieve_locus_t *locus, size_t msgno,
307 mu_message_t msg,
308 const char *action, const char *fmt, va_list ap)
309 {
310 char *text = NULL;
311
312 if (message_id_header)
313 {
314 mu_header_t hdr = NULL;
315 char *val = NULL;
316 mu_message_get_header (msg, &hdr);
317 if (mu_header_aget_value (hdr, message_id_header, &val) == 0
318 || mu_header_aget_value (hdr, MU_HEADER_MESSAGE_ID, &val) == 0)
319 {
320 asprintf (&text, _("%s:%lu: %s on msg %s"),
321 locus->source_file,
322 (unsigned long) locus->source_line,
323 action, val);
324 free (val);
325 }
326 }
327 if (text == NULL)
328 {
329 size_t uid = 0;
330 mu_message_get_uid (msg, &uid);
331 asprintf (&text, _("%s:%lu: %s on msg uid %d"),
332 locus->source_file,
333 (unsigned long) locus->source_line,
334 action, uid);
335 }
336
337 if (fmt && strlen (fmt))
338 {
339 char *diag = NULL;
340 vasprintf (&diag, fmt, ap);
341 if (log_to_stderr)
342 fprintf (stderr, _("(user %s) %s: %s"), (char*) user_name,
343 text, diag);
344 else
345 syslog (LOG_NOTICE, _("(user %s) %s: %s"), (char*) user_name,
346 text, diag);
347 free (diag);
348 }
349 else if (log_to_stderr)
350 fprintf (stderr, _("(user %s) %s"), (char*) user_name, text);
351 else
352 syslog (LOG_NOTICE, _("(user %s) %s"), (char*) user_name, text);
353 free (text);
354 if (log_to_stderr)
355 fputc ('\n', stderr);
356 }
357
358 static int
359 _sieve_parse_error (void *user_name, const char *filename, int lineno,
360 const char *fmt, va_list ap)
361 {
362 char *text;
363 vasprintf (&text, fmt, ap);
364 if (filename)
365 {
366 char *loc;
367 asprintf (&loc, "%s:%d: ", filename, lineno);
368 if (log_to_stderr)
369 fprintf (stderr, "%s: %s", loc, text);
370 else
371 syslog (LOG_ERR, "%s: %s", loc, text);
372 free (loc);
373 }
374 else if (log_to_stderr)
375 fprintf (stderr, _("(user %s) %s"), (char*)user_name, text);
376 else
377 syslog (LOG_ERR, _("(user %s) %s"), (char*)user_name, text);
378 free (text);
379 if (log_to_stderr)
380 fputc ('\n', stderr);
381 return 0;
382 }
383
384 int
385 sieve_test (struct mu_auth_data *auth, mu_mailbox_t mbx)
386 {
387 int rc = 1;
388 char *progfile;
389
390 if (!sieve_pattern)
391 return 1;
392
393 progfile = mu_expand_path_pattern (sieve_pattern, auth->name);
394 if (access (progfile, R_OK))
395 {
396 if (debug_level > 2)
397 syslog (LOG_DEBUG, _("Access to %s failed: %m"), progfile);
398 }
399 else
400 {
401 mu_sieve_machine_t mach;
402 rc = mu_sieve_machine_init (&mach, auth->name);
403 if (rc)
404 {
405 mu_error (_("Cannot initialize sieve machine: %s"),
406 mu_strerror (rc));
407 }
408 else
409 {
410 mu_sieve_set_debug (mach, _sieve_debug_printer);
411 mu_sieve_set_debug_level (mach, mudebug, sieve_debug_flags);
412 mu_sieve_set_parse_error (mach, _sieve_parse_error);
413 if (sieve_enable_log)
414 mu_sieve_set_logger (mach, _sieve_action_log);
415
416 rc = mu_sieve_compile (mach, progfile);
417 if (rc == 0)
418 {
419 mu_attribute_t attr;
420 mu_message_t msg = NULL;
421
422 mu_mailbox_get_message (mbx, 1, &msg);
423 mu_message_get_attribute (msg, &attr);
424 mu_attribute_unset_deleted (attr);
425 if (switch_user_id (auth, 1) == 0)
426 {
427 chdir (auth->dir);
428
429 rc = mu_sieve_message (mach, msg);
430 if (rc == 0)
431 rc = mu_attribute_is_deleted (attr) == 0;
432
433 switch_user_id (auth, 0);
434 chdir ("/");
435 }
436 mu_sieve_machine_destroy (&mach);
437 }
438 }
439 }
440 free (progfile);
441 return rc;
442 }
443
444
445 int
446 main (int argc, char *argv[])
447 {
448 int arg_index;
449
450 /* Preparative work: close inherited fds, force a reasonable umask
451 and prepare a logging. */
452 close_fds ();
453 umask (0077);
454
455 /* Native Language Support */
456 mu_init_nls ();
457
458 /* Default locker settings */
459 mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY,
460 mu_locker_assign);
461 mu_locker_set_default_retry_timeout (1);
462 mu_locker_set_default_retry_count (300);
463
464 /* Default error code for command line errors */
465 mu_argp_error_code = EX_CONFIG;
466 /* Register needed modules */
467 MU_AUTH_REGISTER_ALL_MODULES ();
468
469 /* Register mailbox formats */
470 mu_register_all_formats ();
471
472 /* Register the supported mailers. */
473 mu_registrar_record (mu_sendmail_record);
474 mu_registrar_record (mu_smtp_record);
475
476 mu_argp_init (program_version, NULL);
477 mu_sieve_argp_init ();
478
479 /* Parse command line */
480 mu_argp_set_config_param (maidag_cfg_param);
481 mu_argp_parse (&argp, &argc, &argv, 0, argp_capa, &arg_index, &daemon_param);
482
483 current_uid = getuid ();
484
485 if (log_to_stderr == -1)
486 log_to_stderr = (getuid () != 0);
487
488 if (!log_to_stderr)
489 {
490 openlog ("mail.local", LOG_PID, log_facility);
491 mu_error_set_print (mu_syslog_error_printer);
492 }
493
494 if (debug_flags)
495 {
496 int rc;
497
498 if ((rc = mu_debug_create (&mudebug, NULL)))
499 {
500 mu_error (_("mu_debug_create failed: %s\n"), mu_strerror (rc));
501 exit (EX_TEMPFAIL);
502 }
503 if ((rc = mu_debug_set_level (mudebug, debug_flags)))
504 {
505 mu_error (_("mu_debug_set_level failed: %s\n"),
506 mu_strerror (rc));
507 exit (EX_TEMPFAIL);
508 }
509 if ((rc = mu_debug_set_print (mudebug, _mu_debug_printer, NULL)))
510 {
511 mu_error (_("mu_debug_set_print failed: %s\n"),
512 mu_strerror (rc));
513 exit (EX_TEMPFAIL);
514 }
515 }
516
517 argc -= arg_index;
518 argv += arg_index;
519
520 if (lmtp_mode)
521 {
522 if (argc)
523 {
524 mu_error (_("Too many arguments"));
525 return EX_USAGE;
526 }
527 return maidag_lmtp_server ();
528 }
529 else
530 {
531 if (current_uid)
532 {
533 static char *s_argv[2];
534 struct mu_auth_data *auth = mu_get_auth_by_uid (current_uid);
535
536 if (!current_uid)
537 {
538 mu_error (_("Cannot get username"));
539 return EX_UNAVAILABLE;
540 }
541
542 if (argc > 1 || (argc > 0 && strcmp (auth->name, argv[0])))
543 {
544 mu_error (_("Recipients given when running as non-root"));
545 return EX_USAGE;
546 }
547
548 s_argv[0] = auth->name;
549 argv = s_argv;
550 argc = 1;
551 }
552 return maidag_stdio_delivery (argc, argv);
553 }
554 }
555
556
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301 USA */
18
19 #if defined(HAVE_CONFIG_H)
20 # include <config.h>
21 #endif
22
23 #include <sys/types.h>
24 #include <errno.h>
25 #include <grp.h>
26 #include <netdb.h>
27 #include <pwd.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <syslog.h>
33 #include <unistd.h>
34
35 #include <arpa/inet.h>
36 #include <netinet/in.h>
37 #include <sys/socket.h>
38 #include <sys/stat.h>
39
40 #ifdef HAVE_STRINGS_H
41 # include <strings.h>
42 #endif
43
44 #ifdef HAVE_SYSEXITS_H
45 # include <sysexits.h>
46 #else
47 # define EX_OK 0 /* successful termination */
48 # define EX__BASE 64 /* base value for error messages */
49 # define EX_USAGE 64 /* command line usage error */
50 # define EX_DATAERR 65 /* data format error */
51 # define EX_NOINPUT 66 /* cannot open input */
52 # define EX_NOUSER 67 /* addressee unknown */
53 # define EX_NOHOST 68 /* host name unknown */
54 # define EX_UNAVAILABLE 69 /* service unavailable */
55 # define EX_SOFTWARE 70 /* internal software error */
56 # define EX_OSERR 71 /* system error (e.g., can't fork) */
57 # define EX_OSFILE 72 /* critical OS file missing */
58 # define EX_CANTCREAT 73 /* can't create (user) output file */
59 # define EX_IOERR 74 /* input/output error */
60 # define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
61 # define EX_PROTOCOL 76 /* remote error in protocol */
62 # define EX_NOPERM 77 /* permission denied */
63 # define EX_CONFIG 78 /* configuration error */
64 # define EX__MAX 78 /* maximum listed value */
65 #endif
66
67 #ifndef INADDR_LOOPBACK
68 # define INADDR_LOOPBAK 0x7f000001
69 #endif
70
71 #include <mailutils/attribute.h>
72 #include <mailutils/errno.h>
73 #include <mailutils/error.h>
74 #include <mailutils/list.h>
75 #include <mailutils/locker.h>
76 #include <mailutils/mailbox.h>
77 #include <mailutils/message.h>
78 #include <mailutils/mutil.h>
79 #include <mailutils/registrar.h>
80 #include <mailutils/stream.h>
81 #include <mailutils/url.h>
82 #include <mailutils/mu_auth.h>
83 #include <mailutils/libsieve.h>
84 #include <mailutils/nls.h>
85
86 #include <mu_dbm.h>
87 #include <mu_asprintf.h>
88 #include <getline.h>
89
90 #if defined (USE_DBM) || defined (USE_SQL)
91 # define USE_MAILBOX_QUOTAS 1
92 #endif
93
94 #include <mailutils/argp.h>
95 /* Debug */
96 extern int debug_level;
97 #define dbg() if (debug_level) debug
98
99 /* mailquota settings */
100 #define MQUOTA_OK 0
101 #define MQUOTA_EXCEEDED 1
102 #define MQUOTA_UNLIMITED 2
103
104 #define MAXFD 64
105 #define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE)
106
107 extern int exit_code;
108 extern int log_to_stderr;
109 extern int multiple_delivery;
110 extern int ex_quota_tempfail;
111 extern uid_t current_uid;
112 extern char *quotadbname;
113 extern char *quota_query;
114
115 extern char *sender_address;
116 extern char *progfile_pattern;
117 extern char *sieve_pattern;
118
119 extern int lmtp_mode;
120 extern char *lmtp_url_string;
121 extern int reuse_lmtp_address;
122 extern char *lmtp_group;
123 extern struct daemon_param daemon_param;
124
125 void close_fds (void);
126 int switch_user_id (struct mu_auth_data *auth, int user);
127
128 int maidag_stdio_delivery (int argc, char **argv);
129 int maidag_lmtp_server (void);
130
131 void mailer_err (char *fmt, ...);
132 void notify_biff (mu_mailbox_t mbox, char *name, size_t size);
133 void guess_retval (int ec);
134
135 int deliver (mu_mailbox_t imbx, char *name, char **errp);
136 int sieve_test (struct mu_auth_data *auth, mu_mailbox_t mbx);
137 int check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest);
138
139 #ifdef WITH_GUILE
140 struct mda_data
141 {
142 mu_mailbox_t mbox;
143 char *progfile;
144 char *progfile_pattern;
145 char **argv;
146 };
147
148 int prog_mda (struct mda_data *data);
149
150 extern int debug_guile;
151 #endif
152
153 struct mail_tmp;
154 int mail_tmp_begin (struct mail_tmp **pmtmp, const char *from);
155 int mail_tmp_add_line (struct mail_tmp *mtmp, char *buf, size_t buflen);
156 int mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox);
157 void mail_tmp_destroy (struct mail_tmp **pmtmp);
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2004,
3 2005, 2007 Free 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 #if defined (USE_MAILBOX_QUOTAS)
23
24 #define DEFRETVAL MQUOTA_UNLIMITED
25
26 mu_off_t groupquota = 5*1024*1024UL;
27 static int get_size (char *, mu_off_t *, char **);
28
29 int
30 get_size (char *str, mu_off_t *size, char **endp)
31 {
32 mu_off_t s;
33
34 s = strtol (str, &str, 0);
35 switch (*str)
36 {
37 case 0:
38 break;
39
40 case 'k':
41 case 'K':
42 s *= 1024;
43 break;
44
45 case 'm':
46 case 'M':
47 s *= 1024*1024;
48 break;
49
50 default:
51 *endp = str;
52 return -1;
53 }
54 *size = s;
55 return 0;
56 }
57
58 #define RETR_OK 0
59 #define RETR_UNLIMITED -1
60 #define RETR_FAILURE 1
61
62 int
63 fail_retrieve_quota (char *name, mu_off_t *quota)
64 {
65 mu_error (_("No quota retrieving mechanism"));
66 return RETR_FAILURE;
67 }
68
69 #ifdef USE_DBM
70 int
71 dbm_retrieve_quota (char *name, mu_off_t *quota)
72 {
73 DBM_FILE db;
74 DBM_DATUM named, contentd;
75 char buffer[64];
76 int unlimited = 0;
77 int rc;
78
79 if (!quotadbname)
80 return RETR_FAILURE;
81
82 if (mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600))
83 {
84 mu_error (_("Cannot open %s: %s"), quotadbname, mu_strerror (errno));
85 return RETR_FAILURE;
86 }
87
88 memset (&named, 0, sizeof named);
89 memset (&contentd, 0, sizeof contentd);
90 MU_DATUM_PTR (named) = name;
91 MU_DATUM_SIZE (named) = strlen (name);
92 rc = mu_dbm_fetch (db, named, &contentd);
93 if (rc || !MU_DATUM_PTR (contentd))
94 {
95 /* User not in database, try default quota */
96 memset (&named, 0, sizeof named);
97 MU_DATUM_PTR (named) = "DEFAULT";
98 MU_DATUM_SIZE (named) = strlen ("DEFAULT");
99 rc = mu_dbm_fetch (db, named, &contentd);
100 if (rc)
101 {
102 /*mu_error (_("can't fetch data: %s"), strerror (rc));*/
103 return RETR_FAILURE;
104 }
105 if (!MU_DATUM_PTR (contentd))
106 return RETR_FAILURE;
107 }
108
109 if (strncasecmp("none",
110 MU_DATUM_PTR (contentd),
111 MU_DATUM_SIZE (contentd)) == 0)
112 unlimited = 1;
113 else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1)
114 {
115 mu_error (ngettext ("Mailbox quota for `%s' is too big: %d digit",
116 "Mailbox quota for `%s' is too big: %d digits",
117 MU_DATUM_SIZE (contentd)),
118 name, MU_DATUM_SIZE (contentd));
119 *quota = groupquota;
120 }
121 else
122 {
123 char *p;
124
125 strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd));
126 buffer[MU_DATUM_SIZE (contentd)] = 0;
127 *quota = strtoul (buffer, &p, 0);
128 if (get_size (buffer, quota, &p))
129 {
130 mu_error (_("Bogus mailbox quota for `%s' (near `%s')"), name, p);
131 *quota = groupquota;
132 }
133 }
134
135 mu_dbm_close (db);
136
137 return unlimited ? RETR_UNLIMITED : RETR_OK;
138 }
139
140 # define default_retrieve_quota dbm_retrieve_quota
141 #else
142 # define default_retrieve_quota fail_retrieve_quota
143 #endif
144
145 #ifdef USE_SQL
146 #include <mailutils/sql.h>
147
148 /* FIXME: defined in auth/sql.c */
149 #include <auth/sql.h>
150
151 int
152 sql_retrieve_quota (char *name, mu_off_t *quota)
153 {
154 mu_sql_connection_t conn;
155 char *query_str;
156 int rc, status;
157 char *tmp;
158 size_t n;
159
160 query_str = mu_sql_expand_query (quota_query, name);
161 if (!query_str)
162 return RETR_FAILURE;
163
164 status = mu_sql_connection_init (&conn,
165 sql_interface,
166 mu_sql_host,
167 mu_sql_port,
168 mu_sql_user,
169 mu_sql_passwd,
170 mu_sql_db);
171
172 if (status)
173 {
174 mu_error ("%s. SQL error: %s",
175 mu_strerror (status), mu_sql_strerror (conn));
176 mu_sql_connection_destroy (&conn);
177 free (query_str);
178 return RETR_FAILURE;
179 }
180
181 status = mu_sql_connect (conn);
182
183 if (status)
184 {
185 mu_error ("%s. SQL error: %s",
186 mu_strerror (status), mu_sql_strerror (conn));
187 mu_sql_connection_destroy (&conn);
188 free (query_str);
189 return RETR_FAILURE;
190 }
191
192 status = mu_sql_query (conn, query_str);
193 free (query_str);
194
195 if (status)
196 {
197 mu_error (_("SQL Query failed: %s"),
198 (status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
199 mu_strerror (status));
200 mu_sql_connection_destroy (&conn);
201 return RETR_FAILURE;
202 }
203
204 status = mu_sql_store_result (conn);
205
206 if (status)
207 {
208 mu_error (_("Cannot store SQL result: %s"),
209 (status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
210 mu_strerror (status));
211 mu_sql_connection_destroy (&conn);
212 return RETR_FAILURE;
213 }
214
215 mu_sql_num_tuples (conn, &n);
216 if (n == 0)
217 {
218 rc = RETR_FAILURE;
219 }
220 else
221 {
222 rc = RETR_OK;
223 tmp = NULL;
224 status = mu_sql_get_column (conn, 0, 0, &tmp);
225 if (status)
226 {
227 mu_error (_("Cannot retrieve mailbox quota from SQL: %s"),
228 (status == MU_ERR_SQL) ? mu_sql_strerror (conn) :
229 mu_strerror (status));
230 rc = RETR_FAILURE;
231 }
232 else if (tmp == NULL || tmp[0] == 0 || strcasecmp (tmp, "none") == 0)
233 rc = RETR_UNLIMITED;
234 else
235 {
236 char *p;
237
238 if (get_size (tmp, quota, &p))
239 {
240 mu_error (_("Bogus mailbox quota for `%s' (near `%s')"),
241 name, p);
242 *quota = groupquota;
243 }
244 }
245 }
246
247 mu_sql_release_result (conn);
248 mu_sql_disconnect (conn);
249 mu_sql_connection_destroy (&conn);
250 return rc;
251 }
252 #endif
253
254
255 static int
256 retrieve_quota (struct mu_auth_data *auth, mu_off_t *quota)
257 {
258 if (MU_HAS_QUOTA (auth))
259 {
260 if (auth->quota == 0)
261 return RETR_UNLIMITED;
262 *quota = auth->quota;
263 return RETR_OK;
264 }
265
266 #ifdef USE_SQL
267 if (quota_query)
268 return sql_retrieve_quota (auth->name, quota);
269 #endif
270 return default_retrieve_quota (auth->name, quota);
271 }
272
273 int
274 check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
275 {
276 mu_off_t quota;
277
278 switch (retrieve_quota (auth, &quota))
279 {
280 case RETR_FAILURE:
281 return DEFRETVAL;
282
283 case RETR_UNLIMITED:
284 return MQUOTA_UNLIMITED;
285
286 case RETR_OK:
287 if (quota < size) /* Mailbox full */
288 return MQUOTA_EXCEEDED;
289
290 if (rest)
291 *rest = quota - size;
292 }
293
294 return MQUOTA_OK;
295
296 }
297
298 #endif /* USE_MAIL_QUOTA */
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2005,
3 2007 Free 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 mailer_err (_("Unable to open temporary file: %s"),
48 mu_strerror (status));
49 return status;
50 }
51
52 if ((status = mu_stream_open (mtmp->stream)))
53 {
54 free (mtmp);
55 mailer_err (_("unable to open temporary file: %s"),
56 mu_strerror (status));
57 return status;
58 }
59 mtmp->from = from;
60 *pmtmp = mtmp;
61 return 0;
62 }
63
64 int
65 mail_tmp_add_line (struct mail_tmp *mtmp, char *buf, size_t buflen)
66 {
67 int status = 0;
68
69 mtmp->line++;
70 if (mtmp->line == 1)
71 {
72 const char *from = mtmp->from;
73
74 if (buflen >= 5 && memcmp (buf, "From ", 5))
75 {
76 struct mu_auth_data *auth = NULL;
77 if (!from)
78 {
79 auth = mu_get_auth_by_uid (getuid ());
80 if (auth)
81 from = auth->name;
82 }
83 if (from)
84 {
85 time_t t;
86 char *envs;
87
88 time (&t);
89 asprintf (&envs, "From %s %s", from, ctime (&t));
90 status = mu_stream_sequential_write (mtmp->stream,
91 envs,
92 strlen (envs));
93 free (envs);
94 }
95 else
96 {
97 mailer_err (_("Cannot determine sender address"));
98 return EINVAL;
99 }
100 if (auth)
101 mu_auth_data_free (auth);
102 }
103 }
104 else if (buflen >= 5 && !memcmp (buf, "From ", 5))
105 {
106 static char *escape = ">";
107 status = mu_stream_sequential_write (mtmp->stream, escape, 1);
108 }
109
110 if (!status)
111 status = mu_stream_sequential_write (mtmp->stream, buf, buflen);
112
113 if (status)
114 {
115 mailer_err (_("Error writing temporary file: %s"), mu_strerror (status));
116 mu_stream_destroy (&mtmp->stream, mu_stream_get_owner (mtmp->stream));
117 }
118 mtmp->had_nl = buf[buflen-1] == '\n';
119 return status;
120 }
121
122 int
123 mail_tmp_finish (struct mail_tmp *mtmp, mu_mailbox_t *mbox)
124 {
125 int status;
126 static char *newline = "\n";
127 size_t n;
128
129 if (!mtmp->had_nl)
130 status = mu_stream_sequential_write (mtmp->stream, newline, 1);
131
132 status = mu_stream_sequential_write (mtmp->stream, newline, 1);
133 unlink (mtmp->tempfile);
134 free (mtmp->tempfile);
135 mtmp->tempfile = NULL;
136
137 if (status)
138 {
139 errno = status;
140 mailer_err (_("Error writing temporary file: %s"), mu_strerror (status));
141 mu_stream_destroy (&mtmp->stream, mu_stream_get_owner (mtmp->stream));
142 return status;
143 }
144
145 mu_stream_flush (mtmp->stream);
146 if ((status = mu_mailbox_create (mbox, "/dev/null"))
147 || (status = mu_mailbox_open (*mbox, MU_STREAM_READ))
148 || (status = mu_mailbox_set_stream (*mbox, mtmp->stream)))
149 {
150 mailer_err (_("Error opening temporary file: %s"), mu_strerror (status));
151 mu_stream_destroy (&mtmp->stream, mu_stream_get_owner (mtmp->stream));
152 return status;
153 }
154
155 status = mu_mailbox_messages_count (*mbox, &n);
156 if (status)
157 {
158 errno = status;
159 mailer_err (_("Error creating temporary message: %s"),
160 mu_strerror (status));
161 mu_stream_destroy (&mtmp->stream, mu_stream_get_owner (mtmp->stream));
162 return status;
163 }
164
165 mtmp->stream = NULL;
166 mtmp->line = 0;
167
168 return status;
169
170 }
171
172 void
173 mail_tmp_destroy (struct mail_tmp **pmtmp)
174 {
175 struct mail_tmp *mtmp = *pmtmp;
176
177 if (mtmp)
178 {
179 if (mtmp->tempfile)
180 {
181 unlink (mtmp->tempfile);
182 free (mtmp->tempfile);
183 }
184 mu_stream_destroy (&mtmp->stream, mu_stream_get_owner (mtmp->stream));
185 free (*pmtmp);
186 *pmtmp = NULL;
187 }
188 }
189
190
191
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2005,
3 2007 Free 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 #ifdef WITH_GUILE
23 #include <mailutils/guile.h>
24
25 int debug_guile;
26
27 SCM mda_catch_body (void *data, mu_mailbox_t mbox);
28 SCM mda_catch_handler (void *unused, SCM tag, SCM throw_args);
29 int mda_next (void *data, mu_mailbox_t mbox);
30 int mda_exit (void *data, mu_mailbox_t mbox);
31 int mda_init (void *data);
32
33 int
34 prog_mda (struct mda_data *data)
35 {
36 char *x_argv[2];
37 mu_guimb_param_t param;
38
39 x_argv[0] = "maidag";
40 x_argv[1] = NULL;
41
42 param.debug_guile = debug_guile;
43 param.mbox = data->mbox;
44 param.user_name = NULL;
45 param.init = mda_init;
46 param.catch_body = mda_catch_body;
47 param.catch_handler = mda_catch_handler;
48 param.next = mda_next;
49 param.exit = mda_exit;
50 param.data = data;
51
52 mu_process_mailbox (1, x_argv, &param);
53 return EX_UNAVAILABLE;
54 }
55
56 int
57 mda_init (void *data)
58 {
59 struct mda_data *md = data;
60 md->progfile = mu_expand_path_pattern (md->progfile_pattern, md->argv[0]);
61 return 0;
62 }
63
64 static void
65 mda_switch_to_user (struct mda_data *md)
66 {
67 struct mu_auth_data *auth = NULL;
68
69 if (md && *md->argv != NULL)
70 auth = mu_get_auth_by_name (*md->argv);
71
72 if (auth)
73 {
74 switch_user_id (auth, 1);
75 chdir (auth->dir);
76 mu_auth_data_free (auth);
77 }
78 else
79 {
80 switch_user_id (auth, 0);
81 chdir ("/");
82 }
83 }
84
85 SCM
86 mda_catch_body (void *data, mu_mailbox_t mbox)
87 {
88 struct mda_data *md = data;
89 mu_message_t mesg = NULL;
90 mu_attribute_t attr = NULL;
91
92 if (access (md->progfile, R_OK))
93 {
94 if (debug_level > 2)
95 syslog (LOG_DEBUG, _("Access to %s failed: %m"), md->progfile);
96 }
97 else
98 {
99 mda_switch_to_user (md);
100 scm_primitive_load (scm_makfrom0str (md->progfile));
101 }
102
103 mu_mailbox_get_message (mbox, 1, &mesg);
104 mu_message_get_attribute (mesg, &attr);
105 if (mu_attribute_is_deleted (attr))
106 return SCM_BOOL_F;
107
108 mda_switch_to_user (NULL);
109 mda (md->mbox, md->argv[0]);
110 return SCM_BOOL_F;
111 }
112
113 SCM
114 mda_catch_handler (void *data, SCM tag, SCM throw_args)
115 {
116 exit_code = EX_TEMPFAIL;
117 return scm_handle_by_message_noexit ("mail.local", tag, throw_args);
118 }
119
120 int
121 mda_next (void *data, mu_mailbox_t mbox)
122 {
123 struct mda_data *md = data;
124 mu_message_t mesg = NULL;
125 mu_attribute_t attr = NULL;
126
127 md->argv++;
128 if (*md->argv == NULL)
129 return 0;
130 if (md->progfile)
131 free (md->progfile);
132 md->progfile = mu_expand_path_pattern (md->progfile_pattern, *md->argv);
133
134 mu_mailbox_get_message (mbox, 1, &mesg);
135 mu_message_get_attribute (mesg, &attr);
136 mu_attribute_unset_deleted (attr);
137
138 return md->progfile != NULL;
139 }
140
141 int
142 mda_exit (void *data, mu_mailbox_t mbox)
143 {
144 return exit_code;
145 }
146
147 #endif
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 MA 02110-1301 USA */
18
19 #include "maidag.h"
20
21 void
22 close_fds ()
23 {
24 int i;
25 long fdlimit = MAXFD;
26
27 #if defined (HAVE_SYSCONF) && defined (_SC_OPEN_MAX)
28 fdlimit = sysconf (_SC_OPEN_MAX);
29 #elif defined (HAVE_GETDTABLESIZE)
30 fdlimit = getdtablesize ();
31 #endif
32
33 for (i = 3; i < fdlimit; i++)
34 close (i);
35 }
36
37 int
38 switch_user_id (struct mu_auth_data *auth, int user)
39 {
40 int rc;
41 uid_t uid;
42
43 if (!auth || auth->change_uid == 0)
44 return 0;
45
46 if (user)
47 uid = auth->uid;
48 else
49 uid = 0;
50
51 #if defined(HAVE_SETREUID)
52 rc = setreuid (0, uid);
53 #elif defined(HAVE_SETRESUID)
54 rc = setresuid (-1, uid, -1);
55 #elif defined(HAVE_SETEUID)
56 rc = seteuid (uid);
57 #else
58 # error "No way to reset user privileges?"
59 #endif
60 if (rc < 0)
61 mailer_err ("setreuid(0, %d): %s (r=%d, e=%d)",
62 uid, strerror (errno), getuid (), geteuid ());
63 return rc;
64 }
65
66 void
67 mailer_err (char *fmt, ...)
68 {
69 va_list ap;
70
71 guess_retval (errno);
72 va_start (ap, fmt);
73 if (!lmtp_mode && !log_to_stderr)
74 {
75 vfprintf (stderr, fmt, ap);
76 fputc ('\n', stderr);
77 }
78 mu_verror (fmt, ap);
79 va_end (ap);
80 }
81
82 int temp_errors[] = {
83 #ifdef EAGAIN
84 EAGAIN, /* Try again */
85 #endif
86 #ifdef EBUSY
87 EBUSY, /* Device or resource busy */
88 #endif
89 #ifdef EPROCLIM
90 EPROCLIM, /* Too many processes */
91 #endif
92 #ifdef EUSERS
93 EUSERS, /* Too many users */
94 #endif
95 #ifdef ECONNABORTED
96 ECONNABORTED, /* Software caused connection abort */
97 #endif
98 #ifdef ECONNREFUSED
99 ECONNREFUSED, /* Connection refused */
100 #endif
101 #ifdef ECONNRESET
102 ECONNRESET, /* Connection reset by peer */
103 #endif
104 #ifdef EDEADLK
105 EDEADLK, /* Resource deadlock would occur */
106 #endif
107 #ifdef EDEADLOCK
108 EDEADLOCK, /* Resource deadlock would occur */
109 #endif
110 #ifdef EFBIG
111 EFBIG, /* File too large */
112 #endif
113 #ifdef EHOSTDOWN
114 EHOSTDOWN, /* Host is down */
115 #endif
116 #ifdef EHOSTUNREACH
117 EHOSTUNREACH, /* No route to host */
118 #endif
119 #ifdef EMFILE
120 EMFILE, /* Too many open files */
121 #endif
122 #ifdef ENETDOWN
123 ENETDOWN, /* Network is down */
124 #endif
125 #ifdef ENETUNREACH
126 ENETUNREACH, /* Network is unreachable */
127 #endif
128 #ifdef ENETRESET
129 ENETRESET, /* Network dropped connection because of reset */
130 #endif
131 #ifdef ENFILE
132 ENFILE, /* File table overflow */
133 #endif
134 #ifdef ENOBUFS
135 ENOBUFS, /* No buffer space available */
136 #endif
137 #ifdef ENOMEM
138 ENOMEM, /* Out of memory */
139 #endif
140 #ifdef ENOSPC
141 ENOSPC, /* No space left on device */
142 #endif
143 #ifdef EROFS
144 EROFS, /* Read-only file system */
145 #endif
146 #ifdef ESTALE
147 ESTALE, /* Stale NFS file handle */
148 #endif
149 #ifdef ETIMEDOUT
150 ETIMEDOUT, /* Connection timed out */
151 #endif
152 #ifdef EWOULDBLOCK
153 EWOULDBLOCK, /* Operation would block */
154 #endif
155 };
156
157
158 void
159 guess_retval (int ec)
160 {
161 int i;
162 /* Temporary failures override hard errors. */
163 if (exit_code == EX_TEMPFAIL)
164 return;
165 #ifdef EDQUOT
166 if (ec == EDQUOT)
167 {
168 exit_code = EX_QUOTA();
169 return;
170 }
171 #endif
172
173 for (i = 0; i < sizeof (temp_errors)/sizeof (temp_errors[0]); i++)
174 if (temp_errors[i] == ec)
175 {
176 exit_code = EX_TEMPFAIL;
177 return;
178 }
179 exit_code = EX_UNAVAILABLE;
180 }
...@@ -35,6 +35,7 @@ mail_local_LDADD = \ ...@@ -35,6 +35,7 @@ mail_local_LDADD = \
35 ${MU_LIB_MH}\ 35 ${MU_LIB_MH}\
36 ${MU_LIB_MAILDIR}\ 36 ${MU_LIB_MAILDIR}\
37 ${MU_LIB_AUTH}\ 37 ${MU_LIB_AUTH}\
38 ${MU_LIB_MAILER}\
38 @MU_AUTHLIBS@\ 39 @MU_AUTHLIBS@\
39 ${MU_LIB_MAILUTILS} \ 40 ${MU_LIB_MAILUTILS} \
40 @MU_COMMON_LIBRARIES@ 41 @MU_COMMON_LIBRARIES@
......
...@@ -317,7 +317,8 @@ _sieve_action_log (void *user_name, ...@@ -317,7 +317,8 @@ _sieve_action_log (void *user_name,
317 { 317 {
318 char *diag = NULL; 318 char *diag = NULL;
319 vasprintf (&diag, fmt, ap); 319 vasprintf (&diag, fmt, ap);
320 syslog (LOG_NOTICE, _("(user %s) %s: %s"), (char*) user_name, text, diag); 320 syslog (LOG_NOTICE, _("(user %s) %s: %s"),
321 (char*) user_name, text, diag);
321 free (diag); 322 free (diag);
322 } 323 }
323 else 324 else
...@@ -360,7 +361,7 @@ main (int argc, char *argv[]) ...@@ -360,7 +361,7 @@ main (int argc, char *argv[])
360 361
361 /* Default locker settings */ 362 /* Default locker settings */
362 mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY, 363 mu_locker_set_default_flags (MU_LOCKER_PID|MU_LOCKER_RETRY,
363 mu_locker_assign); 364 mu_locker_assign);
364 mu_locker_set_default_retry_timeout (1); 365 mu_locker_set_default_retry_timeout (1);
365 mu_locker_set_default_retry_count (300); 366 mu_locker_set_default_retry_count (300);
366 367
......
...@@ -81,7 +81,7 @@ static int amd_messages_count (mu_mailbox_t, size_t *); ...@@ -81,7 +81,7 @@ static int amd_messages_count (mu_mailbox_t, size_t *);
81 static int amd_messages_recent (mu_mailbox_t, size_t *); 81 static int amd_messages_recent (mu_mailbox_t, size_t *);
82 static int amd_message_unseen (mu_mailbox_t, size_t *); 82 static int amd_message_unseen (mu_mailbox_t, size_t *);
83 static int amd_expunge (mu_mailbox_t); 83 static int amd_expunge (mu_mailbox_t);
84 static int amd_save_attributes (mu_mailbox_t); 84 static int amd_sync (mu_mailbox_t);
85 static int amd_uidnext (mu_mailbox_t mailbox, size_t *puidnext); 85 static int amd_uidnext (mu_mailbox_t mailbox, size_t *puidnext);
86 static int amd_uidvalidity (mu_mailbox_t, unsigned long *); 86 static int amd_uidvalidity (mu_mailbox_t, unsigned long *);
87 static int amd_scan (mu_mailbox_t, size_t, size_t *); 87 static int amd_scan (mu_mailbox_t, size_t, size_t *);
...@@ -281,7 +281,7 @@ amd_init_mailbox (mu_mailbox_t mailbox, size_t amd_size, ...@@ -281,7 +281,7 @@ amd_init_mailbox (mu_mailbox_t mailbox, size_t amd_size,
281 mailbox->_messages_recent = amd_messages_recent; 281 mailbox->_messages_recent = amd_messages_recent;
282 mailbox->_message_unseen = amd_message_unseen; 282 mailbox->_message_unseen = amd_message_unseen;
283 mailbox->_expunge = amd_expunge; 283 mailbox->_expunge = amd_expunge;
284 mailbox->_save_attributes = amd_save_attributes; 284 mailbox->_sync = amd_sync;
285 mailbox->_uidvalidity = amd_uidvalidity; 285 mailbox->_uidvalidity = amd_uidvalidity;
286 mailbox->_uidnext = amd_uidnext; 286 mailbox->_uidnext = amd_uidnext;
287 287
...@@ -862,7 +862,7 @@ amd_expunge (mu_mailbox_t mailbox) ...@@ -862,7 +862,7 @@ amd_expunge (mu_mailbox_t mailbox)
862 } 862 }
863 863
864 static int 864 static int
865 amd_save_attributes (mu_mailbox_t mailbox) 865 amd_sync (mu_mailbox_t mailbox)
866 { 866 {
867 struct _amd_data *amd = mailbox->data; 867 struct _amd_data *amd = mailbox->data;
868 struct _amd_message *mhm; 868 struct _amd_message *mhm;
......
...@@ -419,24 +419,23 @@ _file_open (mu_stream_t stream) ...@@ -419,24 +419,23 @@ _file_open (mu_stream_t stream)
419 char* filename = 0; 419 char* filename = 0;
420 int flags = 0; 420 int flags = 0;
421 421
422 assert(fs); 422 if (!fs || !fs->filename)
423 423 return EINVAL;
424
424 filename = fs->filename; 425 filename = fs->filename;
425 426
426 assert(filename);
427
428 if (fs->file) 427 if (fs->file)
429 { 428 {
430 fclose (fs->file); 429 fclose (fs->file);
431 fs->file = NULL; 430 fs->file = NULL;
432 } 431 }
433 432
434 mu_stream_get_flags(stream, &flags); 433 mu_stream_get_flags (stream, &flags);
435 434
436 /* Map the flags to the system equivalent. */ 435 /* Map the flags to the system equivalent. */
437 if (flags & MU_STREAM_WRITE && flags & MU_STREAM_READ) 436 if (flags & MU_STREAM_WRITE && flags & MU_STREAM_READ)
438 return EINVAL; 437 return EINVAL;
439 else if (flags & MU_STREAM_WRITE) 438 else if (flags & (MU_STREAM_WRITE|MU_STREAM_APPEND))
440 flg = O_WRONLY; 439 flg = O_WRONLY;
441 else if (flags & MU_STREAM_RDWR) 440 else if (flags & MU_STREAM_RDWR)
442 flg = O_RDWR; 441 flg = O_RDWR;
...@@ -453,14 +452,14 @@ _file_open (mu_stream_t stream) ...@@ -453,14 +452,14 @@ _file_open (mu_stream_t stream)
453 if (flags & MU_STREAM_CREAT) 452 if (flags & MU_STREAM_CREAT)
454 { 453 {
455 /* First see if the file already exists. */ 454 /* First see if the file already exists. */
456 fd = open(filename, flg); 455 fd = open (filename, flg);
457 if (fd == -1) 456 if (fd == -1)
458 { 457 {
459 /* Oops bail out. */ 458 /* Oops bail out. */
460 if (errno != ENOENT) 459 if (errno != ENOENT)
461 return errno; 460 return errno;
462 /* Race condition here when creating the file ??. */ 461 /* Race condition here when creating the file ??. */
463 fd = open(filename, flg|O_CREAT|O_EXCL, 0600); 462 fd = open (filename, flg|O_CREAT|O_EXCL, 0600);
464 if (fd < 0) 463 if (fd < 0)
465 return errno; 464 return errno;
466 } 465 }
...@@ -474,16 +473,15 @@ _file_open (mu_stream_t stream) ...@@ -474,16 +473,15 @@ _file_open (mu_stream_t stream)
474 473
475 /* We have to make sure that We did not open 474 /* We have to make sure that We did not open
476 a symlink. From Casper D. in bugtraq. */ 475 a symlink. From Casper D. in bugtraq. */
477 if ((flg & MU_STREAM_CREAT) || 476 if (flg & (MU_STREAM_CREAT | MU_STREAM_RDWR
478 (flg & MU_STREAM_RDWR) || 477 | MU_STREAM_WRITE | MU_STREAM_APPEND))
479 (flg & MU_STREAM_WRITE))
480 { 478 {
481 struct stat fdbuf, filebuf; 479 struct stat fdbuf, filebuf;
482 480
483 /* The next two stats should never fail. */ 481 /* The next two stats should never fail. */
484 if (fstat(fd, &fdbuf) == -1) 482 if (fstat (fd, &fdbuf) == -1)
485 return errno; 483 return errno;
486 if (lstat(filename, &filebuf) == -1) 484 if (lstat (filename, &filebuf) == -1)
487 return errno; 485 return errno;
488 486
489 /* Now check that: file and fd reference the same file, 487 /* Now check that: file and fd reference the same file,
......
...@@ -177,8 +177,9 @@ mu_folder_destroy (mu_folder_t *pfolder) ...@@ -177,8 +177,9 @@ mu_folder_destroy (mu_folder_t *pfolder)
177 /* Notify the observers. */ 177 /* Notify the observers. */
178 if (folder->observable) 178 if (folder->observable)
179 { 179 {
180 mu_observable_notify (folder->observable, MU_EVT_FOLDER_DESTROY); 180 mu_observable_notify (folder->observable, MU_EVT_FOLDER_DESTROY,
181 mu_observable_destroy (&(folder->observable), folder); 181 folder);
182 mu_observable_destroy (&folder->observable, folder);
182 } 183 }
183 if (folder->_destroy) 184 if (folder->_destroy)
184 folder->_destroy (folder); 185 folder->_destroy (folder);
......
...@@ -174,8 +174,8 @@ mu_mailbox_destroy (mu_mailbox_t *pmbox) ...@@ -174,8 +174,8 @@ mu_mailbox_destroy (mu_mailbox_t *pmbox)
174 /* Notify the observers. */ 174 /* Notify the observers. */
175 if (mbox->observable) 175 if (mbox->observable)
176 { 176 {
177 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_DESTROY); 177 mu_observable_notify (mbox->observable, MU_EVT_MAILBOX_DESTROY, mbox);
178 mu_observable_destroy (&(mbox->observable), mbox); 178 mu_observable_destroy (&mbox->observable, mbox);
179 } 179 }
180 180
181 /* Call the concrete mailbox _destroy method. So it can clean itself. */ 181 /* Call the concrete mailbox _destroy method. So it can clean itself. */
...@@ -244,7 +244,8 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge) ...@@ -244,7 +244,8 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge)
244 if (!mbox) 244 if (!mbox)
245 return EINVAL; 245 return EINVAL;
246 if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND))) 246 if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND)))
247 return EACCES; 247 return 0;
248
248 mu_mailbox_messages_count (mbox, &total); 249 mu_mailbox_messages_count (mbox, &total);
249 if (mbox->flags & MU_STREAM_APPEND) 250 if (mbox->flags & MU_STREAM_APPEND)
250 i = total; 251 i = total;
...@@ -258,10 +259,12 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge) ...@@ -258,10 +259,12 @@ mu_mailbox_flush (mu_mailbox_t mbox, int expunge)
258 mu_message_get_attribute (msg, &attr); 259 mu_message_get_attribute (msg, &attr);
259 mu_attribute_set_seen (attr); 260 mu_attribute_set_seen (attr);
260 } 261 }
262
261 if (expunge) 263 if (expunge)
262 status = mu_mailbox_expunge (mbox); 264 status = mu_mailbox_expunge (mbox);
263 else 265 else
264 status = mu_mailbox_save_attributes (mbox); 266 status = mu_mailbox_sync (mbox);
267
265 return status; 268 return status;
266 } 269 }
267 270
...@@ -285,6 +288,15 @@ mu_mailbox_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg) ...@@ -285,6 +288,15 @@ mu_mailbox_get_message (mu_mailbox_t mbox, size_t msgno, mu_message_t *pmsg)
285 } 288 }
286 289
287 int 290 int
291 mu_mailbox_quick_get_message (mu_mailbox_t mbox, mu_message_qid_t qid,
292 mu_message_t *pmsg)
293 {
294 if (mbox == NULL || mbox->_quick_get_message == NULL)
295 return MU_ERR_EMPTY_VFN;
296 return mbox->_quick_get_message (mbox, qid, pmsg);
297 }
298
299 int
288 mu_mailbox_messages_count (mu_mailbox_t mbox, size_t *num) 300 mu_mailbox_messages_count (mu_mailbox_t mbox, size_t *num)
289 { 301 {
290 if (mbox == NULL || mbox->_messages_count == NULL) 302 if (mbox == NULL || mbox->_messages_count == NULL)
...@@ -309,13 +321,24 @@ mu_mailbox_message_unseen (mu_mailbox_t mbox, size_t *num) ...@@ -309,13 +321,24 @@ mu_mailbox_message_unseen (mu_mailbox_t mbox, size_t *num)
309 } 321 }
310 322
311 int 323 int
324 mu_mailbox_sync (mu_mailbox_t mbox)
325 {
326 if (mbox == NULL || mbox->_sync == NULL)
327 return MU_ERR_EMPTY_VFN;
328 if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND)))
329 return 0;
330 return mbox->_sync (mbox);
331 }
332
333 /* Historic alias: */
334 int
312 mu_mailbox_save_attributes (mu_mailbox_t mbox) 335 mu_mailbox_save_attributes (mu_mailbox_t mbox)
313 { 336 {
314 if (mbox == NULL || mbox->_save_attributes == NULL) 337 if (mbox == NULL || mbox->_sync == NULL)
315 return MU_ERR_EMPTY_VFN; 338 return MU_ERR_EMPTY_VFN;
316 if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND))) 339 if (!(mbox->flags & (MU_STREAM_RDWR|MU_STREAM_WRITE|MU_STREAM_APPEND)))
317 return EACCES; 340 return EACCES;
318 return mbox->_save_attributes (mbox); 341 return mbox->_sync (mbox);
319 } 342 }
320 343
321 int 344 int
...@@ -347,9 +370,34 @@ mu_mailbox_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount) ...@@ -347,9 +370,34 @@ mu_mailbox_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
347 int 370 int
348 mu_mailbox_get_size (mu_mailbox_t mbox, mu_off_t *psize) 371 mu_mailbox_get_size (mu_mailbox_t mbox, mu_off_t *psize)
349 { 372 {
350 if (mbox == NULL || mbox->_get_size == NULL) 373 int status;
374 if (mbox == NULL)
351 return MU_ERR_EMPTY_VFN; 375 return MU_ERR_EMPTY_VFN;
352 return mbox->_get_size (mbox, psize); 376 if (mbox->_get_size == NULL
377 || (status = mbox->_get_size (mbox, psize)) == ENOSYS)
378 {
379 /* Fall back to brute-force method */
380 size_t i, total;
381 mu_off_t size = 0;
382
383 status = mu_mailbox_messages_count (mbox, &total);
384 if (status)
385 return status;
386 for (i = 1; i <= total; i++)
387 {
388 mu_message_t msg;
389 size_t msgsize;
390 status = mu_mailbox_get_message (mbox, i, &msg);
391 if (status)
392 return status;
393 status = mu_message_size (msg, &msgsize);
394 if (status)
395 return status;
396 size += msgsize;
397 }
398 *psize = size;
399 }
400 return status;
353 } 401 }
354 402
355 int 403 int
...@@ -408,7 +456,7 @@ mu_mailbox_set_stream (mu_mailbox_t mbox, mu_stream_t stream) ...@@ -408,7 +456,7 @@ mu_mailbox_set_stream (mu_mailbox_t mbox, mu_stream_t stream)
408 if (mbox == NULL) 456 if (mbox == NULL)
409 return MU_ERR_MBX_NULL; 457 return MU_ERR_MBX_NULL;
410 if (mbox->stream) 458 if (mbox->stream)
411 mu_stream_destroy (&(mbox->stream), mbox); 459 mu_stream_destroy (&mbox->stream, mbox);
412 mbox->stream = stream; 460 mbox->stream = stream;
413 return 0; 461 return 0;
414 } 462 }
...@@ -451,7 +499,7 @@ mu_mailbox_get_observable (mu_mailbox_t mbox, mu_observable_t *pobservable) ...@@ -451,7 +499,7 @@ mu_mailbox_get_observable (mu_mailbox_t mbox, mu_observable_t *pobservable)
451 499
452 if (mbox->observable == NULL) 500 if (mbox->observable == NULL)
453 { 501 {
454 int status = mu_observable_create (&(mbox->observable), mbox); 502 int status = mu_observable_create (&mbox->observable, mbox);
455 if (status != 0) 503 if (status != 0)
456 return status; 504 return status;
457 } 505 }
......
...@@ -157,8 +157,9 @@ mu_mailer_destroy (mu_mailer_t * pmailer) ...@@ -157,8 +157,9 @@ mu_mailer_destroy (mu_mailer_t * pmailer)
157 157
158 if (mailer->observable) 158 if (mailer->observable)
159 { 159 {
160 mu_observable_notify (mailer->observable, MU_EVT_MAILER_DESTROY); 160 mu_observable_notify (mailer->observable, MU_EVT_MAILER_DESTROY,
161 mu_observable_destroy (&(mailer->observable), mailer); 161 mailer);
162 mu_observable_destroy (&mailer->observable, mailer);
162 } 163 }
163 164
164 /* Call the object destructor. */ 165 /* Call the object destructor. */
......
...@@ -115,7 +115,8 @@ mu_message_destroy (mu_message_t *pmsg, void *owner) ...@@ -115,7 +115,8 @@ mu_message_destroy (mu_message_t *pmsg, void *owner)
115 /* FIXME: to be removed since we do not support this event. */ 115 /* FIXME: to be removed since we do not support this event. */
116 if (msg->observable) 116 if (msg->observable)
117 { 117 {
118 mu_observable_notify (msg->observable, MU_EVT_MESSAGE_DESTROY); 118 mu_observable_notify (msg->observable, MU_EVT_MESSAGE_DESTROY,
119 msg);
119 mu_observable_destroy (&(msg->observable), msg); 120 mu_observable_destroy (&(msg->observable), msg);
120 } 121 }
121 122
...@@ -649,8 +650,31 @@ mu_message_get_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pwri ...@@ -649,8 +650,31 @@ mu_message_get_uidl (mu_message_t msg, char *buffer, size_t buflen, size_t *pwri
649 } 650 }
650 651
651 int 652 int
653 mu_message_get_qid (mu_message_t msg, mu_message_qid_t *pqid)
654 {
655 if (msg == NULL)
656 return EINVAL;
657 if (!msg->_get_qid)
658 return ENOSYS;
659 return msg->_get_qid (msg, pqid);
660 }
661
662 int
663 mu_message_set_qid (mu_message_t msg,
664 int (*_get_qid) (mu_message_t, mu_message_qid_t *),
665 void *owner)
666 {
667 if (msg == NULL)
668 return EINVAL;
669 if (msg->owner != owner)
670 return EACCES;
671 msg->_get_qid = _get_qid;
672 return 0;
673 }
674
675 int
652 mu_message_set_uid (mu_message_t msg, int (*_get_uid) (mu_message_t, size_t *), 676 mu_message_set_uid (mu_message_t msg, int (*_get_uid) (mu_message_t, size_t *),
653 void *owner) 677 void *owner)
654 { 678 {
655 if (msg == NULL) 679 if (msg == NULL)
656 return EINVAL; 680 return EINVAL;
......
...@@ -49,7 +49,7 @@ mu_observer_destroy (mu_observer_t *pobserver, void *owner) ...@@ -49,7 +49,7 @@ mu_observer_destroy (mu_observer_t *pobserver, void *owner)
49 if (observer->owner == owner || observer->flags & MU_OBSERVER_NO_CHECK) 49 if (observer->owner == owner || observer->flags & MU_OBSERVER_NO_CHECK)
50 { 50 {
51 if (observer->_destroy) 51 if (observer->_destroy)
52 observer->_destroy (observer); 52 observer->_destroy (observer, observer->_action_data);
53 free (observer); 53 free (observer);
54 } 54 }
55 *pobserver = NULL; 55 *pobserver = NULL;
...@@ -63,18 +63,19 @@ mu_observer_get_owner (mu_observer_t observer) ...@@ -63,18 +63,19 @@ mu_observer_get_owner (mu_observer_t observer)
63 } 63 }
64 64
65 int 65 int
66 mu_observer_action (mu_observer_t observer, size_t type) 66 mu_observer_action (mu_observer_t observer, size_t type, void *data)
67 { 67 {
68 if (observer == NULL) 68 if (observer == NULL)
69 return EINVAL; 69 return EINVAL;
70 if (observer->_action) 70 if (observer->_action)
71 return observer->_action (observer, type); 71 return observer->_action (observer, type, data, observer->_action_data);
72 return 0; 72 return 0;
73 } 73 }
74 74
75 int 75 int
76 mu_observer_set_action (mu_observer_t observer, 76 mu_observer_set_action (mu_observer_t observer,
77 int (*_action) (mu_observer_t, size_t), void *owner) 77 int (*_action) (mu_observer_t, size_t, void *, void *),
78 void *owner)
78 { 79 {
79 if (observer == NULL) 80 if (observer == NULL)
80 return EINVAL; 81 return EINVAL;
...@@ -85,8 +86,20 @@ mu_observer_set_action (mu_observer_t observer, ...@@ -85,8 +86,20 @@ mu_observer_set_action (mu_observer_t observer,
85 } 86 }
86 87
87 int 88 int
88 mu_observer_set_destroy (mu_observer_t observer, int (*_destroy) (mu_observer_t), 89 mu_observer_set_action_data (mu_observer_t observer, void *data, void *owner)
89 void *owner) 90 {
91 if (observer == NULL)
92 return EINVAL;
93 if (observer->owner != owner)
94 return EACCES;
95 observer->_action_data = data;
96 return 0;
97 }
98
99 int
100 mu_observer_set_destroy (mu_observer_t observer,
101 int (*_destroy) (mu_observer_t, void *),
102 void *owner)
90 { 103 {
91 if (observer == NULL) 104 if (observer == NULL)
92 return EINVAL; 105 return EINVAL;
...@@ -214,7 +227,7 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer) ...@@ -214,7 +227,7 @@ mu_observable_detach (mu_observable_t observable, mu_observer_t observer)
214 } 227 }
215 228
216 int 229 int
217 mu_observable_notify (mu_observable_t observable, int type) 230 mu_observable_notify (mu_observable_t observable, int type, void *data)
218 { 231 {
219 mu_iterator_t iterator; 232 mu_iterator_t iterator;
220 event_t event = NULL; 233 event_t event = NULL;
...@@ -231,7 +244,7 @@ mu_observable_notify (mu_observable_t observable, int type) ...@@ -231,7 +244,7 @@ mu_observable_notify (mu_observable_t observable, int type)
231 mu_iterator_current (iterator, (void **)&event); 244 mu_iterator_current (iterator, (void **)&event);
232 if (event && event->type & type) 245 if (event && event->type & type)
233 { 246 {
234 status |= mu_observer_action (event->observer, type); 247 status |= mu_observer_action (event->observer, type, data);
235 } 248 }
236 } 249 }
237 mu_iterator_destroy (&iterator); 250 mu_iterator_destroy (&iterator);
......
...@@ -148,7 +148,7 @@ main (int argc, char **argv) ...@@ -148,7 +148,7 @@ main (int argc, char **argv)
148 148
149 mh_msgset_current (mbox, &msgset, 0); 149 mh_msgset_current (mbox, &msgset, 0);
150 mh_global_save_state (); 150 mh_global_save_state ();
151 mu_mailbox_save_attributes (mbox); 151 mu_mailbox_sync (mbox);
152 mu_mailbox_close (mbox); 152 mu_mailbox_close (mbox);
153 mu_mailbox_destroy (&mbox); 153 mu_mailbox_destroy (&mbox);
154 return rc; 154 return rc;
......
...@@ -469,7 +469,7 @@ main (int argc, char **argv) ...@@ -469,7 +469,7 @@ main (int argc, char **argv)
469 469
470 rc = mh_whatnow (&wh_env, initial_edit); 470 rc = mh_whatnow (&wh_env, initial_edit);
471 471
472 mu_mailbox_save_attributes (mbox); 472 mu_mailbox_sync (mbox);
473 mu_mailbox_close (mbox); 473 mu_mailbox_close (mbox);
474 mu_mailbox_destroy (&mbox); 474 mu_mailbox_destroy (&mbox);
475 return rc; 475 return rc;
......
...@@ -442,7 +442,7 @@ main (int argc, char **argv) ...@@ -442,7 +442,7 @@ main (int argc, char **argv)
442 442
443 rc = mh_whatnow (&wh_env, initial_edit); 443 rc = mh_whatnow (&wh_env, initial_edit);
444 444
445 mu_mailbox_save_attributes (mbox); 445 mu_mailbox_sync (mbox);
446 mu_mailbox_close (mbox); 446 mu_mailbox_close (mbox);
447 mu_mailbox_destroy (&mbox); 447 mu_mailbox_destroy (&mbox);
448 return rc; 448 return rc;
......
...@@ -147,9 +147,9 @@ opt_handler (int key, char *arg, void *unused, struct argp_state *state) ...@@ -147,9 +147,9 @@ opt_handler (int key, char *arg, void *unused, struct argp_state *state)
147 return 0; 147 return 0;
148 } 148 }
149 149
150 /* Observable Action this is being call at every message discover. */ 150 /* Observable Action this is called at every message discover. */
151 static int 151 static int
152 action (mu_observer_t o, size_t type) 152 action (mu_observer_t o, size_t type, void *data, void *action_data)
153 { 153 {
154 static int counter; 154 static int counter;
155 mu_mailbox_t mbox; 155 mu_mailbox_t mbox;
......
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.