Modified Files:
header.c io.c mailbox.c mailbox.h mailbox0.h mbx_unix.c message.c message.h message0.h Added Files: event.h added registrations of certain events.
Showing
10 changed files
with
435 additions
and
122 deletions
mailbox/event.h
0 → 100644
1 | /* GNU mailutils - a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000 Free Software Foundation, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Library Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This program 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 Library General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Library General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
17 | |||
18 | #ifndef _EVENT_H | ||
19 | #define _EVENT_H | ||
20 | |||
21 | #ifndef __P | ||
22 | # ifdef __STDC__ | ||
23 | # define __P(args) args | ||
24 | # else | ||
25 | # define __P(args) () | ||
26 | # endif | ||
27 | #endif /* __P */ | ||
28 | |||
29 | #ifdef _cpluscplus | ||
30 | extern "C" { | ||
31 | #endif | ||
32 | |||
33 | struct _event | ||
34 | { | ||
35 | size_t type; | ||
36 | void *arg; | ||
37 | int (*_action) __P ((size_t type, void *arg)); | ||
38 | }; | ||
39 | typedef struct _event *event_t; | ||
40 | |||
41 | #ifdef _cpluscplus | ||
42 | } | ||
43 | #endif | ||
44 | |||
45 | #endif /* _EVENT_H */ |
... | @@ -26,9 +26,11 @@ | ... | @@ -26,9 +26,11 @@ |
26 | #include <stdlib.h> | 26 | #include <stdlib.h> |
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | 28 | ||
29 | static int header_parse (header_t *h, const char *blurb, size_t len); | 29 | static int header_parse (header_t h, const char *blurb, size_t len); |
30 | static int header_read (istream_t is, char *buf, size_t buflen, | 30 | static int header_read (istream_t is, char *buf, size_t buflen, |
31 | off_t off, ssize_t *pnread); | 31 | off_t off, ssize_t *pnread); |
32 | static int header_write (ostream_t os, const char *buf, size_t buflen, | ||
33 | off_t off, ssize_t *pnwrite); | ||
32 | 34 | ||
33 | struct _hdr | 35 | struct _hdr |
34 | { | 36 | { |
... | @@ -67,9 +69,18 @@ header_init (header_t *ph, const char *blurb, size_t len, void *owner) | ... | @@ -67,9 +69,18 @@ header_init (header_t *ph, const char *blurb, size_t len, void *owner) |
67 | return ENOMEM; | 69 | return ENOMEM; |
68 | h->owner = owner; | 70 | h->owner = owner; |
69 | 71 | ||
70 | status = header_parse (&h, blurb, len); | 72 | status = header_parse (h, blurb, len); |
71 | if (status != 0) | 73 | if (status != 0) |
72 | free (h); | 74 | free (h); |
75 | |||
76 | status = istream_init (&(h->is), header_read, h); | ||
77 | if (status != 0) | ||
78 | return status; | ||
79 | |||
80 | status = ostream_init (&(h->os), header_write, h); | ||
81 | if (status != 0) | ||
82 | return status; | ||
83 | |||
73 | *ph = h; | 84 | *ph = h; |
74 | return status; | 85 | return status; |
75 | } | 86 | } |
... | @@ -109,21 +120,16 @@ header_destroy (header_t *ph, void *owner) | ... | @@ -109,21 +120,16 @@ header_destroy (header_t *ph, void *owner) |
109 | * on how to handle the case. | 120 | * on how to handle the case. |
110 | */ | 121 | */ |
111 | static int | 122 | static int |
112 | header_parse (header_t *h, const char *blurb, size_t len) | 123 | header_parse (header_t header, const char *blurb, size_t len) |
113 | { | 124 | { |
114 | header_t header; | ||
115 | char *header_end; | 125 | char *header_end; |
116 | char *header_start; | 126 | char *header_start; |
117 | char *header_start2; | 127 | char *header_start2; |
118 | struct _hdr *hdr; | 128 | struct _hdr *hdr; |
119 | 129 | ||
120 | if (h == NULL || blurb == NULL || len == 0) | 130 | if (header == NULL || blurb == NULL || len == 0) |
121 | return EINVAL; | 131 | return EINVAL; |
122 | 132 | ||
123 | header = calloc (1, sizeof (*header)); | ||
124 | if (header == NULL) | ||
125 | return ENOMEM; | ||
126 | |||
127 | header->blurb = calloc (1, len); | 133 | header->blurb = calloc (1, len); |
128 | if (header->blurb == NULL) | 134 | if (header->blurb == NULL) |
129 | { | 135 | { |
... | @@ -200,7 +206,6 @@ header_parse (header_t *h, const char *blurb, size_t len) | ... | @@ -200,7 +206,6 @@ header_parse (header_t *h, const char *blurb, size_t len) |
200 | header->hdr[header->hdr_count - 1].fv_end = header_end; | 206 | header->hdr[header->hdr_count - 1].fv_end = header_end; |
201 | } | 207 | } |
202 | } | 208 | } |
203 | *h = header; | ||
204 | return 0; | 209 | return 0; |
205 | } | 210 | } |
206 | 211 | ||
... | @@ -336,6 +341,24 @@ header_entry_value (header_t header, size_t num, char *buf, | ... | @@ -336,6 +341,24 @@ header_entry_value (header_t header, size_t num, char *buf, |
336 | } | 341 | } |
337 | 342 | ||
338 | static int | 343 | static int |
344 | header_write (ostream_t os, const char *buf, size_t buflen, | ||
345 | off_t off, ssize_t *pnwrite) | ||
346 | { | ||
347 | header_t header; | ||
348 | if (os == NULL || (header = (header_t)os->owner) == NULL) | ||
349 | return EINVAL; | ||
350 | |||
351 | (void)buf; (void)off; | ||
352 | if (buflen == 0) | ||
353 | return 0; | ||
354 | |||
355 | if (pnwrite) | ||
356 | *pnwrite = 0; | ||
357 | |||
358 | return ENOSYS; | ||
359 | } | ||
360 | |||
361 | static int | ||
339 | header_read (istream_t is, char *buf, size_t buflen, | 362 | header_read (istream_t is, char *buf, size_t buflen, |
340 | off_t off, ssize_t *pnread) | 363 | off_t off, ssize_t *pnread) |
341 | { | 364 | { |
... | @@ -365,16 +388,8 @@ header_read (istream_t is, char *buf, size_t buflen, | ... | @@ -365,16 +388,8 @@ header_read (istream_t is, char *buf, size_t buflen, |
365 | int | 388 | int |
366 | header_get_istream (header_t header, istream_t *pis) | 389 | header_get_istream (header_t header, istream_t *pis) |
367 | { | 390 | { |
368 | int err; | ||
369 | if (header == NULL || pis == NULL) | 391 | if (header == NULL || pis == NULL) |
370 | return EINVAL; | 392 | return EINVAL; |
371 | /* already done */ | ||
372 | if (header->is) | ||
373 | *pis = header->is; | ||
374 | |||
375 | err = istream_init (&(header->is), header_read, header->owner); | ||
376 | if (err != 0) | ||
377 | return err; | ||
378 | *pis = header->is; | 393 | *pis = header->is; |
379 | return 0; | 394 | return 0; |
380 | } | 395 | } |
... | @@ -384,5 +399,6 @@ rfc822_get_ostream (header_t header, ostream_t *pos) | ... | @@ -384,5 +399,6 @@ rfc822_get_ostream (header_t header, ostream_t *pos) |
384 | { | 399 | { |
385 | if (header == NULL || pos == NULL) | 400 | if (header == NULL || pos == NULL) |
386 | return EINVAL; | 401 | return EINVAL; |
402 | *pos = header->os; | ||
387 | return ENOSYS; | 403 | return ENOSYS; |
388 | } | 404 | } | ... | ... |
... | @@ -64,7 +64,7 @@ istream_destroy (istream_t *pis, void *owner) | ... | @@ -64,7 +64,7 @@ istream_destroy (istream_t *pis, void *owner) |
64 | is->ref_count--; | 64 | is->ref_count--; |
65 | if ((is->owner && is->owner == owner) || | 65 | if ((is->owner && is->owner == owner) || |
66 | (is->owner == NULL && is->ref_count <= 0)) | 66 | (is->owner == NULL && is->ref_count <= 0)) |
67 | free (pis); | 67 | free (is); |
68 | *pis = NULL; | 68 | *pis = NULL; |
69 | } | 69 | } |
70 | } | 70 | } |
... | @@ -78,7 +78,7 @@ ostream_destroy (ostream_t *pos, void *owner) | ... | @@ -78,7 +78,7 @@ ostream_destroy (ostream_t *pos, void *owner) |
78 | os->ref_count--; | 78 | os->ref_count--; |
79 | if ((os->owner && os->owner == owner) || | 79 | if ((os->owner && os->owner == owner) || |
80 | (os->owner == NULL && os->ref_count <= 0)) | 80 | (os->owner == NULL && os->ref_count <= 0)) |
81 | free (*pos); | 81 | free (os); |
82 | *pos = NULL; | 82 | *pos = NULL; |
83 | } | 83 | } |
84 | } | 84 | } | ... | ... |
... | @@ -157,19 +157,6 @@ mailbox_num_deleted (mailbox_t mbox, size_t *num) | ... | @@ -157,19 +157,6 @@ mailbox_num_deleted (mailbox_t mbox, size_t *num) |
157 | return mbox->_num_deleted (mbox, num); | 157 | return mbox->_num_deleted (mbox, num); |
158 | } | 158 | } |
159 | 159 | ||
160 | /* hook to allow some sort of "progress bar" .. I don't like it | ||
161 | * but can not find any other way yet | ||
162 | */ | ||
163 | int | ||
164 | mailbox_progress (mailbox_t mbox, int (*progress) (int, void *arg), void *arg) | ||
165 | { | ||
166 | if (mbox == NULL) | ||
167 | return EINVAL; | ||
168 | mbox->_progress = progress; | ||
169 | mbox->progress_arg = arg; | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | int | 160 | int |
174 | mailbox_is_updated (mailbox_t mbox) | 161 | mailbox_is_updated (mailbox_t mbox) |
175 | { | 162 | { |
... | @@ -217,3 +204,73 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth) | ... | @@ -217,3 +204,73 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth) |
217 | return 0; | 204 | return 0; |
218 | } | 205 | } |
219 | 206 | ||
207 | int | ||
208 | mailbox_register (mailbox_t mbox, size_t type, | ||
209 | int (*action) (size_t type, void *arg), | ||
210 | void *arg) | ||
211 | { | ||
212 | size_t i; | ||
213 | event_t event; | ||
214 | |||
215 | /* FIXME: I should check for invalid types */ | ||
216 | if (mbox == NULL || action == NULL) | ||
217 | return EINVAL; | ||
218 | |||
219 | /* find a free spot */ | ||
220 | for (i = 0; i < mbox->event_num; i++) | ||
221 | { | ||
222 | event = &(mbox->event[i]); | ||
223 | if (event->_action == NULL) | ||
224 | { | ||
225 | event->_action = action; | ||
226 | event->type = type; | ||
227 | event->arg = arg; | ||
228 | return 0; | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /* a new one */ | ||
233 | event = realloc (mbox->event, (mbox->event_num + 1) * sizeof (*event)); | ||
234 | if (event == NULL) | ||
235 | return ENOMEM; | ||
236 | |||
237 | mbox->event = event; | ||
238 | event[mbox->event_num]._action = action; | ||
239 | event[mbox->event_num].type = type; | ||
240 | event[mbox->event_num].arg = arg; | ||
241 | mbox->event_num++; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | int | ||
246 | mailbox_deregister (mailbox_t mbox, void *action) | ||
247 | { | ||
248 | size_t i; | ||
249 | event_t event; | ||
250 | |||
251 | for (i = 0; i < mbox->event_num; i++) | ||
252 | { | ||
253 | event = &(mbox->event[i]); | ||
254 | if (event->_action == action) | ||
255 | { | ||
256 | event->type = 0; | ||
257 | event->_action = NULL; | ||
258 | event->arg = NULL; | ||
259 | return 0; | ||
260 | } | ||
261 | } | ||
262 | return ENOENT; | ||
263 | } | ||
264 | |||
265 | void | ||
266 | mailbox_notification (mailbox_t mbox, size_t type) | ||
267 | { | ||
268 | size_t i; | ||
269 | event_t event; | ||
270 | for (i = 0; i < mbox->event_num; i++) | ||
271 | { | ||
272 | event = &(mbox->event[i]); | ||
273 | if ((event->_action) && (event->type & type)) | ||
274 | event->_action (type, event->arg); | ||
275 | } | ||
276 | } | ... | ... |
... | @@ -81,6 +81,17 @@ extern int mailbox_size __P ((mailbox_t, off_t size)); | ... | @@ -81,6 +81,17 @@ extern int mailbox_size __P ((mailbox_t, off_t size)); |
81 | 81 | ||
82 | extern int mailbox_get_url __P ((mailbox_t, url_t *)); | 82 | extern int mailbox_get_url __P ((mailbox_t, url_t *)); |
83 | 83 | ||
84 | /* events */ | ||
85 | #define MU_EVT_MBX_DESTROY 1 | ||
86 | #define MU_EVT_MBX_CORRUPTED 2 | ||
87 | #define MU_EVT_MBX_MSG_ADD 4 | ||
88 | #define MU_EVT_MBX_PROGRESS 8 | ||
89 | |||
90 | extern int mailbox_register __P ((mailbox_t mbox, size_t type, | ||
91 | int (*action) (size_t type, void *arg), | ||
92 | void *arg)); | ||
93 | extern int mailbox_deregister __P ((mailbox_t mbox, void *action)); | ||
94 | |||
84 | #ifdef __cplusplus | 95 | #ifdef __cplusplus |
85 | } | 96 | } |
86 | #endif | 97 | #endif | ... | ... |
... | @@ -19,6 +19,7 @@ | ... | @@ -19,6 +19,7 @@ |
19 | #define _MAILBOX0_H | 19 | #define _MAILBOX0_H |
20 | 20 | ||
21 | #include <mailbox.h> | 21 | #include <mailbox.h> |
22 | #include <event.h> | ||
22 | 23 | ||
23 | #include <sys/types.h> | 24 | #include <sys/types.h> |
24 | #include <stdio.h> | 25 | #include <stdio.h> |
... | @@ -42,8 +43,10 @@ struct _mailbox | ... | @@ -42,8 +43,10 @@ struct _mailbox |
42 | auth_t auth; | 43 | auth_t auth; |
43 | locker_t locker; | 44 | locker_t locker; |
44 | url_t url; | 45 | url_t url; |
45 | int (*_progress) __P ((int, void *arg)); | 46 | |
46 | void *progress_arg; | 47 | /* register events */ |
48 | event_t event; | ||
49 | size_t event_num; | ||
47 | 50 | ||
48 | /* Back pointer to the specific mailbox */ | 51 | /* Back pointer to the specific mailbox */ |
49 | void *data; | 52 | void *data; |
... | @@ -87,9 +90,7 @@ extern int mailbox_get_attribute __P ((mailbox_t mbox, size_t msgno, | ... | @@ -87,9 +90,7 @@ extern int mailbox_get_attribute __P ((mailbox_t mbox, size_t msgno, |
87 | attribute_t *attr)); | 90 | attribute_t *attr)); |
88 | extern int mailbox_set_attribute __P ((mailbox_t mbox, size_t msgno, | 91 | extern int mailbox_set_attribute __P ((mailbox_t mbox, size_t msgno, |
89 | attribute_t attr)); | 92 | attribute_t attr)); |
90 | extern int mailbox_progress __P ((mailbox_t mbox, | 93 | extern void mailbox_notification __P ((mailbox_t mbox, size_t type)); |
91 | int (*progress) (int, void *arg), | ||
92 | void *arg)); | ||
93 | 94 | ||
94 | 95 | ||
95 | #ifdef __cplusplus | 96 | #ifdef __cplusplus | ... | ... |
... | @@ -21,8 +21,8 @@ | ... | @@ -21,8 +21,8 @@ |
21 | #include <registrar0.h> | 21 | #include <registrar0.h> |
22 | #include <message0.h> | 22 | #include <message0.h> |
23 | #include <url0.h> | 23 | #include <url0.h> |
24 | #include <attribute.h> | ||
25 | #include <io0.h> | 24 | #include <io0.h> |
25 | #include <attribute.h> | ||
26 | #include <header.h> | 26 | #include <header.h> |
27 | #include <auth.h> | 27 | #include <auth.h> |
28 | #include <locker.h> | 28 | #include <locker.h> |
... | @@ -105,6 +105,8 @@ typedef struct _mailbox_unix_data | ... | @@ -105,6 +105,8 @@ typedef struct _mailbox_unix_data |
105 | #endif | 105 | #endif |
106 | time_t mtime; | 106 | time_t mtime; |
107 | off_t size; | 107 | off_t size; |
108 | |||
109 | int busy; | ||
108 | } *mailbox_unix_data_t; | 110 | } *mailbox_unix_data_t; |
109 | 111 | ||
110 | static int mailbox_unix_open (mailbox_t mbox, int flag); | 112 | static int mailbox_unix_open (mailbox_t mbox, int flag); |
... | @@ -129,6 +131,7 @@ static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h, | ... | @@ -129,6 +131,7 @@ static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h, |
129 | 131 | ||
130 | 132 | ||
131 | /* private stuff */ | 133 | /* private stuff */ |
134 | static int mailbox_unix_validity (mailbox_t mbox, size_t msgno); | ||
132 | static int mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, | 135 | static int mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, |
133 | off_t off, ssize_t *pnread); | 136 | off_t off, ssize_t *pnread); |
134 | static int mailbox_unix_is_from (const char *); | 137 | static int mailbox_unix_is_from (const char *); |
... | @@ -312,6 +315,8 @@ mailbox_unix_destroy (mailbox_t *pmbox) | ... | @@ -312,6 +315,8 @@ mailbox_unix_destroy (mailbox_t *pmbox) |
312 | free (mbox->data); | 315 | free (mbox->data); |
313 | } | 316 | } |
314 | free (mbox->name); | 317 | free (mbox->name); |
318 | /* free the event array */ | ||
319 | free (mbox->event); | ||
315 | /* destroy the url */ | 320 | /* destroy the url */ |
316 | if (mbox->url) | 321 | if (mbox->url) |
317 | url_destroy (&(mbox->url)); | 322 | url_destroy (&(mbox->url)); |
... | @@ -623,6 +628,10 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -623,6 +628,10 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
623 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | 628 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) |
624 | return EINVAL; | 629 | return EINVAL; |
625 | 630 | ||
631 | if (mud->busy == 1) | ||
632 | return 0; | ||
633 | mud->busy = 1; | ||
634 | |||
626 | /* FIXME: I should also block signals and check cancelstate(Pthread) | 635 | /* FIXME: I should also block signals and check cancelstate(Pthread) |
627 | since We can not afford to be intr */ | 636 | since We can not afford to be intr */ |
628 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); | 637 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); |
... | @@ -635,6 +644,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -635,6 +644,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
635 | funlockfile (mud->file); | 644 | funlockfile (mud->file); |
636 | mailbox_unix_iunlock (mbox); | 645 | mailbox_unix_iunlock (mbox); |
637 | mailbox_unix_unlock (mbox); | 646 | mailbox_unix_unlock (mbox); |
647 | mud->busy = 0; | ||
638 | return status; | 648 | return status; |
639 | } | 649 | } |
640 | mud->mtime = st.st_mtime; | 650 | mud->mtime = st.st_mtime; |
... | @@ -653,6 +663,18 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -653,6 +663,18 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
653 | mum[count - 1].body_end = ftell (mud->file); | 663 | mum[count - 1].body_end = ftell (mud->file); |
654 | mum[count - 1].body_end -= (over + 1); | 664 | mum[count - 1].body_end -= (over + 1); |
655 | body = 0; | 665 | body = 0; |
666 | /* notifications */ | ||
667 | { | ||
668 | off_t where = ftell (mud->file); | ||
669 | funlockfile (mud->file); | ||
670 | mailbox_unix_iunlock (mbox); | ||
671 | mailbox_unix_unlock (mbox); | ||
672 | mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD); | ||
673 | flockfile (mud->file); | ||
674 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); | ||
675 | mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK); | ||
676 | fseek (mud->file, where, SEEK_SET); | ||
677 | } | ||
656 | } | 678 | } |
657 | header = 1; | 679 | header = 1; |
658 | } | 680 | } |
... | @@ -665,21 +687,6 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -665,21 +687,6 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
665 | int over = strlen (buf); | 687 | int over = strlen (buf); |
666 | 688 | ||
667 | count++; | 689 | count++; |
668 | /* FIXME: This is a bad idea, we should not be allowed to | ||
669 | * jump out from the parsing this way. We sit at the mercy | ||
670 | * of this function(_progress) waiting for disaster. | ||
671 | */ | ||
672 | if (mbox->_progress) | ||
673 | { | ||
674 | /* FIXME: and its getting better, they can even bailout */ | ||
675 | if (mbox->_progress (count, mbox->progress_arg) != 0) | ||
676 | { | ||
677 | funlockfile (mud->file); | ||
678 | mailbox_unix_iunlock (mbox); | ||
679 | mailbox_unix_unlock (mbox); | ||
680 | return EINTR; | ||
681 | } | ||
682 | } | ||
683 | /* allocate space for the new message */ | 690 | /* allocate space for the new message */ |
684 | if (count > mud->messages_count) | 691 | if (count > mud->messages_count) |
685 | { | 692 | { |
... | @@ -689,6 +696,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -689,6 +696,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
689 | funlockfile (mud->file); | 696 | funlockfile (mud->file); |
690 | mailbox_unix_iunlock (mbox); | 697 | mailbox_unix_iunlock (mbox); |
691 | mailbox_unix_unlock (mbox); | 698 | mailbox_unix_unlock (mbox); |
699 | mud->busy = 0; | ||
692 | return ENOMEM; | 700 | return ENOMEM; |
693 | } | 701 | } |
694 | mud->messages_count++; | 702 | mud->messages_count++; |
... | @@ -712,6 +720,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -712,6 +720,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
712 | funlockfile (mud->file); | 720 | funlockfile (mud->file); |
713 | mailbox_unix_iunlock (mbox); | 721 | mailbox_unix_iunlock (mbox); |
714 | mailbox_unix_unlock (mbox); | 722 | mailbox_unix_unlock (mbox); |
723 | mud->busy = 0; | ||
715 | return status; | 724 | return status; |
716 | } | 725 | } |
717 | mum[count - 1].header_end = ftell (mud->file) - strlen(buf); | 726 | mum[count - 1].header_end = ftell (mud->file) - strlen(buf); |
... | @@ -733,8 +742,32 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -733,8 +742,32 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
733 | fseek (mud->file, content_length, SEEK_CUR); | 742 | fseek (mud->file, content_length, SEEK_CUR); |
734 | content_length = -1; | 743 | content_length = -1; |
735 | body = 0; | 744 | body = 0; |
745 | /* notification release all locks*/ | ||
746 | { | ||
747 | off_t where = ftell (mud->file); | ||
748 | funlockfile (mud->file); | ||
749 | mailbox_unix_iunlock (mbox); | ||
750 | mailbox_unix_unlock (mbox); | ||
751 | mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD); | ||
752 | flockfile (mud->file); | ||
753 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); | ||
754 | mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK); | ||
755 | fseek (mud->file, where, SEEK_SET); | ||
756 | } | ||
736 | } | 757 | } |
737 | } | 758 | } |
759 | /* notifications release all locks */ | ||
760 | { | ||
761 | off_t where = ftell (mud->file); | ||
762 | funlockfile (mud->file); | ||
763 | mailbox_unix_iunlock (mbox); | ||
764 | mailbox_unix_unlock (mbox); | ||
765 | mailbox_notification (mbox, MU_EVT_MBX_PROGRESS); | ||
766 | flockfile (mud->file); | ||
767 | mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK); | ||
768 | mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK); | ||
769 | fseek (mud->file, where, SEEK_SET); | ||
770 | } | ||
738 | mailbox_unix_touchlock (mbox); | 771 | mailbox_unix_touchlock (mbox); |
739 | } /* while */ | 772 | } /* while */ |
740 | status = errno; | 773 | status = errno; |
... | @@ -750,6 +783,8 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) | ... | @@ -750,6 +783,8 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs) |
750 | mailbox_unix_unlock (mbox); | 783 | mailbox_unix_unlock (mbox); |
751 | if (msgs) | 784 | if (msgs) |
752 | *msgs = count; | 785 | *msgs = count; |
786 | mud->busy = 0; | ||
787 | mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD); | ||
753 | return status; | 788 | return status; |
754 | } | 789 | } |
755 | 790 | ||
... | @@ -771,25 +806,26 @@ mailbox_unix_is_updated (mailbox_t mbox) | ... | @@ -771,25 +806,26 @@ mailbox_unix_is_updated (mailbox_t mbox) |
771 | } | 806 | } |
772 | 807 | ||
773 | static int | 808 | static int |
774 | mailbox_unix_is_valid (mailbox_t mbox, size_t msgno) | 809 | mailbox_unix_validity (mailbox_t mbox, size_t msgno) |
775 | { | 810 | { |
776 | mailbox_unix_data_t mud; | 811 | mailbox_unix_data_t mud; |
777 | if (mbox == NULL || | 812 | if (mbox == NULL || |
778 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | 813 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) |
779 | return 0; | 814 | return EINVAL; |
780 | /* valid ? */ | 815 | /* valid ? */ |
781 | return (mud->messages_count > 0 && msgno <= mud->messages_count); | 816 | return !(mud->messages_count > 0 && msgno > 0 && |
817 | msgno <= mud->messages_count); | ||
782 | } | 818 | } |
783 | 819 | ||
784 | static int | 820 | static int |
785 | mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno) | 821 | mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno) |
786 | { | 822 | { |
787 | mailbox_unix_data_t mud; | 823 | mailbox_unix_data_t mud; |
788 | 824 | int status = mailbox_unix_validity (mbox, msgno); | |
789 | if (mbox == NULL || | 825 | if (status != 0) |
790 | (mud = (mailbox_unix_data_t)mbox->data) == NULL || | 826 | return status; |
791 | ! mailbox_unix_is_valid (mbox, msgno)) | 827 | msgno--; |
792 | return 0; | 828 | mud = (mailbox_unix_data_t) mbox->data; |
793 | return attribute_is_deleted (mud->umessages[msgno].new_attr); | 829 | return attribute_is_deleted (mud->umessages[msgno].new_attr); |
794 | } | 830 | } |
795 | 831 | ||
... | @@ -797,18 +833,17 @@ static int | ... | @@ -797,18 +833,17 @@ static int |
797 | mailbox_unix_delete (mailbox_t mbox, size_t msgno) | 833 | mailbox_unix_delete (mailbox_t mbox, size_t msgno) |
798 | { | 834 | { |
799 | mailbox_unix_data_t mud; | 835 | mailbox_unix_data_t mud; |
836 | int status = mailbox_unix_validity (mbox, msgno); | ||
837 | if (status != 0) | ||
838 | return status; | ||
800 | 839 | ||
801 | if (mbox == NULL || | ||
802 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | ||
803 | return EINVAL; | ||
804 | |||
805 | /* oops out of range ? */ | ||
806 | /* if already deleted, noop */ | 840 | /* if already deleted, noop */ |
807 | if (! mailbox_unix_is_valid (mbox, msgno) || | 841 | if (mailbox_unix_is_deleted (mbox, msgno)) |
808 | mailbox_unix_is_deleted (mbox, msgno)) | ||
809 | return 0; | 842 | return 0; |
810 | 843 | ||
811 | /* Mark for deletion */ | 844 | /* Mark for deletion */ |
845 | msgno--; | ||
846 | mud = (mailbox_unix_data_t) mbox->data; | ||
812 | attribute_set_deleted (mud->umessages[msgno].new_attr); | 847 | attribute_set_deleted (mud->umessages[msgno].new_attr); |
813 | return 0; | 848 | return 0; |
814 | } | 849 | } |
... | @@ -838,17 +873,17 @@ static int | ... | @@ -838,17 +873,17 @@ static int |
838 | mailbox_unix_undelete (mailbox_t mbox, size_t msgno) | 873 | mailbox_unix_undelete (mailbox_t mbox, size_t msgno) |
839 | { | 874 | { |
840 | mailbox_unix_data_t mud; | 875 | mailbox_unix_data_t mud; |
876 | int status = mailbox_unix_validity (mbox, msgno); | ||
877 | if (status != 0) | ||
878 | return status; | ||
841 | 879 | ||
842 | if (mbox == NULL || | ||
843 | (mud = (mailbox_unix_data_t) mbox->data) == NULL) | ||
844 | return EINVAL; | ||
845 | /* oops out of range ? */ | ||
846 | /* if already undeleted, noop */ | 880 | /* if already undeleted, noop */ |
847 | if (! mailbox_unix_is_valid (mbox, msgno) || | 881 | if (! mailbox_unix_is_deleted (mbox, msgno)) |
848 | ! mailbox_unix_is_deleted (mbox, msgno)) | ||
849 | return 0; | 882 | return 0; |
850 | 883 | ||
851 | /* Mark undeletion */ | 884 | /* Mark undeletion */ |
885 | msgno--; | ||
886 | mud = (mailbox_unix_data_t) mbox->data; | ||
852 | attribute_unset_deleted (mud->umessages[msgno].new_attr); | 887 | attribute_unset_deleted (mud->umessages[msgno].new_attr); |
853 | return 0; | 888 | return 0; |
854 | } | 889 | } |
... | @@ -894,10 +929,15 @@ mailbox_unix_expunge (mailbox_t mbox) | ... | @@ -894,10 +929,15 @@ mailbox_unix_expunge (mailbox_t mbox) |
894 | if (tmpfile == NULL) | 929 | if (tmpfile == NULL) |
895 | return errno; | 930 | return errno; |
896 | 931 | ||
932 | if (mud->busy == 1) | ||
933 | return EINPROGRESS; | ||
934 | mud->busy = 1; | ||
935 | |||
897 | /* Get the lock */ | 936 | /* Get the lock */ |
898 | if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) | 937 | if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0) |
899 | { | 938 | { |
900 | fclose (tmpfile); | 939 | fclose (tmpfile); |
940 | mud->busy = 0; | ||
901 | return ENOLCK; | 941 | return ENOLCK; |
902 | } | 942 | } |
903 | 943 | ||
... | @@ -1147,6 +1187,7 @@ bailout: | ... | @@ -1147,6 +1187,7 @@ bailout: |
1147 | mailbox_unix_iunlock (mbox); | 1187 | mailbox_unix_iunlock (mbox); |
1148 | fclose (tmpfile); | 1188 | fclose (tmpfile); |
1149 | sigprocmask (SIG_UNBLOCK, &sigset, 0); | 1189 | sigprocmask (SIG_UNBLOCK, &sigset, 0); |
1190 | mud->busy = 0; | ||
1150 | return status; | 1191 | return status; |
1151 | } | 1192 | } |
1152 | 1193 | ||
... | @@ -1155,7 +1196,6 @@ mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, | ... | @@ -1155,7 +1196,6 @@ mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, |
1155 | off_t off, ssize_t *pnread) | 1196 | off_t off, ssize_t *pnread) |
1156 | { | 1197 | { |
1157 | mailbox_unix_message_t mum; | 1198 | mailbox_unix_message_t mum; |
1158 | size_t len; | ||
1159 | size_t nread = 0; | 1199 | size_t nread = 0; |
1160 | 1200 | ||
1161 | if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL) | 1201 | if (is == NULL || (mum = (mailbox_unix_message_t)is->owner) == NULL) |
... | @@ -1173,7 +1213,7 @@ mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, | ... | @@ -1173,7 +1213,7 @@ mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen, |
1173 | off_t ln = mum->body_end - (mum->body + off); | 1213 | off_t ln = mum->body_end - (mum->body + off); |
1174 | if (ln > 0) | 1214 | if (ln > 0) |
1175 | { | 1215 | { |
1176 | nread = ((size_t)ln < len) ? ln : len; | 1216 | nread = ((size_t)ln < buflen) ? ln : buflen; |
1177 | /* position the file pointer and the buffer */ | 1217 | /* position the file pointer and the buffer */ |
1178 | if (fseek (mum->file, mum->body + off, SEEK_SET) < 0) | 1218 | if (fseek (mum->file, mum->body + off, SEEK_SET) < 0) |
1179 | { | 1219 | { |
... | @@ -1202,14 +1242,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer, | ... | @@ -1202,14 +1242,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer, |
1202 | { | 1242 | { |
1203 | mailbox_unix_data_t mud; | 1243 | mailbox_unix_data_t mud; |
1204 | size_t nread = 0; | 1244 | size_t nread = 0; |
1205 | |||
1206 | if (mbox == NULL || | ||
1207 | (mud = (mailbox_unix_data_t)mbox->data) == NULL) | ||
1208 | return EINVAL; | ||
1209 | |||
1210 | /* check if valid */ | 1245 | /* check if valid */ |
1211 | if (! mailbox_unix_is_valid (mbox, msgno)) | 1246 | int status = mailbox_unix_validity (mbox, msgno); |
1212 | return EINVAL; | 1247 | if (status != 0) |
1248 | return status; | ||
1249 | |||
1250 | mud = (mailbox_unix_data_t) mbox->data; | ||
1251 | msgno--; | ||
1213 | 1252 | ||
1214 | if (buffer == NULL || len == 0) | 1253 | if (buffer == NULL || len == 0) |
1215 | { | 1254 | { |
... | @@ -1271,7 +1310,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1271,7 +1310,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1271 | mailbox_unix_is_deleted (mbox, msgno)) | 1310 | mailbox_unix_is_deleted (mbox, msgno)) |
1272 | return EINVAL; | 1311 | return EINVAL; |
1273 | 1312 | ||
1274 | mum = &(mud->umessages[msgno]); | 1313 | mum = &(mud->umessages[msgno - 1]); |
1275 | 1314 | ||
1276 | /* check if we already have it */ | 1315 | /* check if we already have it */ |
1277 | if (mum->message) | 1316 | if (mum->message) |
... | @@ -1326,14 +1365,12 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1326,14 +1365,12 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1326 | message_set_header (msg, header, mum); | 1365 | message_set_header (msg, header, mum); |
1327 | 1366 | ||
1328 | /* prepare the istream */ | 1367 | /* prepare the istream */ |
1329 | status = istream_init (&is, mailbox_unix_readstream, mum); | ||
1330 | if ((status = istream_init (&is, mailbox_unix_readstream, mum)) != 0 || | 1368 | if ((status = istream_init (&is, mailbox_unix_readstream, mum)) != 0 || |
1331 | (status = message_set_istream (msg, is, mum)) != 0) | 1369 | (status = message_set_istream (msg, is, mum)) != 0) |
1332 | { | 1370 | { |
1333 | message_destroy (&msg, mum); | 1371 | message_destroy (&msg, mum); |
1334 | return status; | 1372 | return status; |
1335 | } | 1373 | } |
1336 | message_set_istream (msg, is, mum); | ||
1337 | 1374 | ||
1338 | /* set the attribute */ | 1375 | /* set the attribute */ |
1339 | status = message_set_attribute (msg, mum->new_attr, mum); | 1376 | status = message_set_attribute (msg, mum->new_attr, mum); |
... | @@ -1351,6 +1388,9 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) | ... | @@ -1351,6 +1388,9 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg) |
1351 | return status; | 1388 | return status; |
1352 | } | 1389 | } |
1353 | 1390 | ||
1391 | /* attach the message to the mailbox unix data */ | ||
1392 | mum->message = msg; | ||
1393 | |||
1354 | if (pmsg) | 1394 | if (pmsg) |
1355 | *pmsg = msg; | 1395 | *pmsg = msg; |
1356 | return 0; | 1396 | return 0; | ... | ... |
... | @@ -31,36 +31,59 @@ static int message_read (istream_t is, char *buf, size_t buflen, | ... | @@ -31,36 +31,59 @@ static int message_read (istream_t is, char *buf, size_t buflen, |
31 | static int message_write (ostream_t os, const char *buf, size_t buflen, | 31 | static int message_write (ostream_t os, const char *buf, size_t buflen, |
32 | off_t off, ssize_t *pnwrite); | 32 | off_t off, ssize_t *pnwrite); |
33 | 33 | ||
34 | int message_clone (message_t omsg, message_t *pmsg) | 34 | int |
35 | message_clone (message_t msg) | ||
35 | { | 36 | { |
36 | int status; | 37 | int status; |
37 | FILE *file; | 38 | FILE *file; |
38 | message_t msg; | ||
39 | istream_t is; | 39 | istream_t is; |
40 | ostream_t os; | 40 | ostream_t os; |
41 | header_t header; | 41 | header_t header; |
42 | attribute_t attribute; | ||
43 | body_t body; | ||
42 | char buffer[BUFSIZ]; | 44 | char buffer[BUFSIZ]; |
43 | char *pbuf = NULL; | 45 | char *pbuf = NULL; |
44 | char *tbuf = NULL; | 46 | char *tbuf = NULL; |
45 | off_t offset = 0; | 47 | off_t offset = 0; |
46 | size_t nread = 0; | 48 | size_t nread = 0; |
47 | 49 | ||
50 | if (msg == NULL) | ||
51 | return EINVAL; | ||
52 | |||
53 | /* If is not own, then it's a floating message | ||
54 | * just bump the reference count. | ||
55 | */ | ||
56 | if (msg->owner == NULL) | ||
57 | { | ||
58 | if (msg->ref_count <= 0) | ||
59 | msg->ref_count = 1; | ||
60 | else | ||
61 | msg->ref_count++; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
48 | /* retreive the header */ | 65 | /* retreive the header */ |
49 | { | 66 | { |
50 | status = message_get_header (omsg, &header); | 67 | header = msg->header; |
51 | if (status != 0) | ||
52 | return status; | ||
53 | status = header_get_istream (header, &is); | 68 | status = header_get_istream (header, &is); |
54 | if (status != 0) | 69 | if (status != 0) |
55 | return status; | 70 | return status; |
56 | 71 | ||
57 | do { | 72 | do { |
58 | status = istream_read (is, buffer, sizeof (buffer), offset, &nread); | 73 | /* FIXME: can not afford to be non blocking here |
74 | * so we busy spin. VERY VERY BAD | ||
75 | */ | ||
76 | do { | ||
77 | status = istream_read (is, buffer, sizeof (buffer), offset, &nread); | ||
78 | } while (status == EAGAIN); | ||
79 | |||
59 | if (status != 0) | 80 | if (status != 0) |
60 | { | 81 | { |
61 | free (pbuf); | 82 | free (pbuf); |
62 | return status; | 83 | return status; |
63 | } | 84 | } |
85 | if (nread == 0) | ||
86 | break; | ||
64 | tbuf = realloc (pbuf, offset + nread); | 87 | tbuf = realloc (pbuf, offset + nread); |
65 | if (tbuf == NULL) | 88 | if (tbuf == NULL) |
66 | { | 89 | { |
... | @@ -73,7 +96,6 @@ int message_clone (message_t omsg, message_t *pmsg) | ... | @@ -73,7 +96,6 @@ int message_clone (message_t omsg, message_t *pmsg) |
73 | offset += nread; | 96 | offset += nread; |
74 | } while (nread > 0); | 97 | } while (nread > 0); |
75 | 98 | ||
76 | |||
77 | status = header_init (&header, pbuf, offset, NULL); | 99 | status = header_init (&header, pbuf, offset, NULL); |
78 | if (status != 0) | 100 | if (status != 0) |
79 | { | 101 | { |
... | @@ -81,11 +103,11 @@ int message_clone (message_t omsg, message_t *pmsg) | ... | @@ -81,11 +103,11 @@ int message_clone (message_t omsg, message_t *pmsg) |
81 | return status; | 103 | return status; |
82 | } | 104 | } |
83 | free (pbuf); | 105 | free (pbuf); |
84 | |||
85 | } | 106 | } |
86 | 107 | ||
87 | /* retrieve the body */ | 108 | /* retrieve the body */ |
88 | { | 109 | { |
110 | is = msg->is; | ||
89 | file = tmpfile (); | 111 | file = tmpfile (); |
90 | if (file == NULL) | 112 | if (file == NULL) |
91 | { | 113 | { |
... | @@ -93,44 +115,66 @@ int message_clone (message_t omsg, message_t *pmsg) | ... | @@ -93,44 +115,66 @@ int message_clone (message_t omsg, message_t *pmsg) |
93 | return errno; | 115 | return errno; |
94 | } | 116 | } |
95 | offset = 0; | 117 | offset = 0; |
96 | message_get_istream (omsg, &is); | ||
97 | do { | 118 | do { |
98 | istream_read (is, buffer, sizeof (buffer), offset, &nread); | 119 | do |
120 | { | ||
121 | status = istream_read (is, buffer, sizeof (buffer), offset, &nread); | ||
122 | } while (status == EAGAIN); | ||
123 | if (status != 0) | ||
124 | { | ||
125 | header_destroy (&header, NULL); | ||
126 | return status; | ||
127 | } | ||
99 | fwrite (buffer, sizeof (*buffer), nread, file); | 128 | fwrite (buffer, sizeof (*buffer), nread, file); |
100 | offset += nread; | 129 | offset += nread; |
101 | } while (nread > 0); | 130 | } while (nread > 0); |
102 | rewind (file); | 131 | rewind (file); |
103 | } | 132 | } |
104 | 133 | ||
105 | /* create the message */ | ||
106 | status = message_init (&msg, NULL); | ||
107 | if (status != 0) | ||
108 | return status; | ||
109 | |||
110 | /* set the header */ | ||
111 | message_set_header (msg, header, NULL); | ||
112 | |||
113 | /* set the body with the streams */ | 134 | /* set the body with the streams */ |
114 | msg->body = calloc (1, sizeof (*(msg->body))); | 135 | body = calloc (1, sizeof (*body)); |
115 | if (msg->body == NULL) | 136 | if (body == NULL) |
116 | { | 137 | { |
117 | fclose (file); | 138 | fclose (file); |
118 | message_destroy (&msg, NULL); | 139 | header_destroy (&header, NULL); |
119 | return ENOMEM; | 140 | return ENOMEM; |
120 | } | 141 | } |
121 | status = istream_init (&is, message_read, NULL); | 142 | status = istream_init (&is, message_read, NULL); |
122 | if (status != 0) | 143 | if (status != 0) |
123 | { | 144 | { |
124 | message_destroy (&msg, NULL); | 145 | fclose (file); |
146 | header_destroy (&header, NULL); | ||
125 | return status; | 147 | return status; |
126 | } | 148 | } |
127 | status = ostream_init (&os, message_write, NULL); | 149 | status = ostream_init (&os, message_write, NULL); |
128 | if (status != 0) | 150 | if (status != 0) |
129 | { | 151 | { |
130 | message_destroy (&msg, NULL); | 152 | fclose (file); |
153 | header_destroy (&header, NULL); | ||
154 | istream_destroy (&is, NULL); | ||
131 | return status; | 155 | return status; |
132 | } | 156 | } |
133 | *pmsg = msg; | 157 | |
158 | /* attribute */ | ||
159 | status = attribute_init (&attribute, NULL); | ||
160 | if (status != 0) | ||
161 | { | ||
162 | fclose (file); | ||
163 | header_destroy (&header, NULL); | ||
164 | istream_destroy (&is, NULL); | ||
165 | ostream_destroy (&os, NULL); | ||
166 | } | ||
167 | attribute_copy (attribute, msg->attribute); | ||
168 | |||
169 | /* every thing went ok */ | ||
170 | msg->header = header; | ||
171 | msg->attribute = attribute; | ||
172 | msg->is = is; | ||
173 | msg->os = os; | ||
174 | msg->body = body; | ||
175 | msg->size = offset; | ||
176 | msg->ref_count = 1; | ||
177 | msg->owner = NULL; /* orphan */ | ||
134 | return 0; | 178 | return 0; |
135 | } | 179 | } |
136 | 180 | ||
... | @@ -160,25 +204,38 @@ message_destroy (message_t *pmsg, void *owner) | ... | @@ -160,25 +204,38 @@ message_destroy (message_t *pmsg, void *owner) |
160 | if ((msg->owner && msg->owner == owner) || | 204 | if ((msg->owner && msg->owner == owner) || |
161 | (msg->owner == NULL && msg->ref_count <= 0)) | 205 | (msg->owner == NULL && msg->ref_count <= 0)) |
162 | { | 206 | { |
207 | header_t header = msg->header; | ||
208 | attribute_t attribute = msg->attribute; | ||
209 | istream_t is = msg->is; | ||
210 | ostream_t os = msg->os; | ||
211 | body_t body = msg->body; | ||
212 | |||
213 | /* notify the listeners */ | ||
214 | message_notification (msg, MU_EVT_MSG_DESTROY); | ||
163 | /* header */ | 215 | /* header */ |
164 | header_destroy (&(msg->header), owner); | 216 | header_destroy (&header, owner); |
165 | /* attribute */ | 217 | /* attribute */ |
166 | attribute_destroy (&(msg->attribute), owner); | 218 | attribute_destroy (&attribute, owner); |
167 | /* istream */ | 219 | /* istream */ |
168 | istream_destroy (&(msg->is), owner); | 220 | istream_destroy (&is, owner); |
169 | /* ostream */ | 221 | /* ostream */ |
170 | ostream_destroy (&(msg->os), owner); | 222 | ostream_destroy (&os, owner); |
171 | 223 | ||
172 | /* if sometype of floating/temporary message */ | 224 | /* if sometype of floating/temporary message */ |
173 | if (msg->body) | 225 | if (body) |
174 | { | 226 | { |
175 | body_t body = msg->body; | ||
176 | if (body->file) | 227 | if (body->file) |
177 | fclose (body->file); | 228 | fclose (body->file); |
178 | free (body->content); | 229 | free (body->content); |
179 | free (msg->body); | 230 | free (body); |
180 | } | 231 | } |
181 | free (msg); | 232 | /* check again for resurrection before free()ing |
233 | * the memory maybe it was clone, if yes we can not | ||
234 | * free the pointer. | ||
235 | * | ||
236 | */ | ||
237 | if (msg->ref_count <= 0) | ||
238 | free (msg); | ||
182 | } | 239 | } |
183 | /* loose the link */ | 240 | /* loose the link */ |
184 | *pmsg = NULL; | 241 | *pmsg = NULL; |
... | @@ -277,7 +334,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute) | ... | @@ -277,7 +334,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute) |
277 | } | 334 | } |
278 | 335 | ||
279 | int | 336 | int |
280 | message_set_attribute (message_t msg, attribute_t attribute, void *owner) | 337 | message_set_attribute (message_t msg, attribute_t attribute, void *owner) |
281 | { | 338 | { |
282 | if (msg == NULL) | 339 | if (msg == NULL) |
283 | return EINVAL; | 340 | return EINVAL; |
... | @@ -287,6 +344,73 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) | ... | @@ -287,6 +344,73 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) |
287 | return 0; | 344 | return 0; |
288 | } | 345 | } |
289 | 346 | ||
347 | int | ||
348 | message_register (message_t msg, size_t type, | ||
349 | int (*action) (size_t typ, void *arg), void *arg) | ||
350 | { | ||
351 | event_t event; | ||
352 | size_t i; | ||
353 | if (msg == NULL || action == NULL || type == 0) | ||
354 | return EINVAL; | ||
355 | |||
356 | /* find a free spot */ | ||
357 | for (i = 0; i < msg->event_num; i++) | ||
358 | { | ||
359 | event = &(msg->event[i]); | ||
360 | if (event->_action == NULL) | ||
361 | { | ||
362 | event->type = type; | ||
363 | event->_action = action; | ||
364 | event->arg = arg; | ||
365 | return 0; | ||
366 | } | ||
367 | } | ||
368 | event = realloc (msg->event, (msg->event_num + 1)*sizeof (*event)); | ||
369 | if (event == NULL) | ||
370 | return ENOMEM; | ||
371 | msg->event = event; | ||
372 | event[msg->event_num]._action = action; | ||
373 | event[msg->event_num].type = type; | ||
374 | event[msg->event_num].arg = arg; | ||
375 | msg->event_num++; | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | int | ||
380 | message_deregister (message_t msg, void *action) | ||
381 | { | ||
382 | size_t i; | ||
383 | event_t event; | ||
384 | if (msg == NULL || action == NULL) | ||
385 | return EINVAL; | ||
386 | |||
387 | for (i = 0; i < msg->event_num; i++) | ||
388 | { | ||
389 | event = &(msg->event[i]); | ||
390 | if (event->_action == action) | ||
391 | { | ||
392 | event->type = 0; | ||
393 | event->_action = NULL; | ||
394 | event->arg = NULL; | ||
395 | return 0; | ||
396 | } | ||
397 | } | ||
398 | return ENOENT; | ||
399 | } | ||
400 | |||
401 | void | ||
402 | message_notification (message_t msg, size_t type) | ||
403 | { | ||
404 | size_t i; | ||
405 | event_t event; | ||
406 | for (i = 0; i < msg->event_num; i++) | ||
407 | { | ||
408 | event = &(msg->event[i]); | ||
409 | if ((event->_action) && (event->type & type)) | ||
410 | event->_action (type, event->arg); | ||
411 | } | ||
412 | } | ||
413 | |||
290 | static int | 414 | static int |
291 | message_read (istream_t is, char *buf, size_t buflen, | 415 | message_read (istream_t is, char *buf, size_t buflen, |
292 | off_t off, ssize_t *pnread ) | 416 | off_t off, ssize_t *pnread ) | ... | ... |
... | @@ -59,8 +59,14 @@ extern int message_set_size __P ((message_t, size_t, void *owner)); | ... | @@ -59,8 +59,14 @@ extern int message_set_size __P ((message_t, size_t, void *owner)); |
59 | extern int message_get_attribute __P ((message_t, attribute_t *)); | 59 | extern int message_get_attribute __P ((message_t, attribute_t *)); |
60 | extern int message_set_attribute __P ((message_t, attribute_t, void *owner)); | 60 | extern int message_set_attribute __P ((message_t, attribute_t, void *owner)); |
61 | 61 | ||
62 | extern int message_clone __P ((message_t, message_t *)); | 62 | extern int message_clone __P ((message_t)); |
63 | 63 | ||
64 | /* events */ | ||
65 | #define MU_EVT_MSG_DESTROY 32 | ||
66 | extern int message_register __P ((message_t msg, size_t type, | ||
67 | int (*action) (size_t typ, void *arg), | ||
68 | void *arg)); | ||
69 | extern int message_deregister __P ((message_t msg, void *action)); | ||
64 | #ifdef _cpluscplus | 70 | #ifdef _cpluscplus |
65 | } | 71 | } |
66 | #endif | 72 | #endif | ... | ... |
... | @@ -22,6 +22,7 @@ | ... | @@ -22,6 +22,7 @@ |
22 | #include <header.h> | 22 | #include <header.h> |
23 | #include <message.h> | 23 | #include <message.h> |
24 | #include <mailbox.h> | 24 | #include <mailbox.h> |
25 | #include <event.h> | ||
25 | 26 | ||
26 | #include <sys/types.h> | 27 | #include <sys/types.h> |
27 | #include <stdio.h> | 28 | #include <stdio.h> |
... | @@ -30,6 +31,14 @@ | ... | @@ -30,6 +31,14 @@ |
30 | extern "C" { | 31 | extern "C" { |
31 | #endif | 32 | #endif |
32 | 33 | ||
34 | #ifndef __P | ||
35 | # ifdef __STDC__ | ||
36 | # define __P(args) args | ||
37 | # else | ||
38 | # define __P(args) () | ||
39 | # endif | ||
40 | #endif /*__P */ | ||
41 | |||
33 | struct _body | 42 | struct _body |
34 | { | 43 | { |
35 | FILE *file; | 44 | FILE *file; |
... | @@ -54,6 +63,9 @@ struct _message | ... | @@ -54,6 +63,9 @@ struct _message |
54 | void *owner; | 63 | void *owner; |
55 | int ref_count; | 64 | int ref_count; |
56 | 65 | ||
66 | event_t event; | ||
67 | size_t event_num; | ||
68 | |||
57 | int (*_get_header) __P ((message_t msg, header_t *hdr)); | 69 | int (*_get_header) __P ((message_t msg, header_t *hdr)); |
58 | int (*_set_header) __P ((message_t msg, header_t hdr, void *owner)); | 70 | int (*_set_header) __P ((message_t msg, header_t hdr, void *owner)); |
59 | 71 | ||
... | @@ -74,4 +86,5 @@ struct _message | ... | @@ -74,4 +86,5 @@ struct _message |
74 | } | 86 | } |
75 | #endif | 87 | #endif |
76 | 88 | ||
89 | extern void message_notification (message_t msg, size_t type); | ||
77 | #endif /* _MESSAGE_H */ | 90 | #endif /* _MESSAGE_H */ | ... | ... |
-
Please register or sign in to post a comment