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 #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.