Commit 0b61ff71 0b61ff712cce321fa32d7ad233f9cc5c058b38e7 by Alain Magloire

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.
1 parent 094d5087
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 {
73 /* FIXME: can not afford to be non blocking here
74 * so we busy spin. VERY VERY BAD
75 */
76 do {
58 status = istream_read (is, buffer, sizeof (buffer), offset, &nread); 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,24 +204,37 @@ message_destroy (message_t *pmsg, void *owner) ...@@ -160,24 +204,37 @@ 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 }
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)
181 free (msg); 238 free (msg);
182 } 239 }
183 /* loose the link */ 240 /* loose the link */
...@@ -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 */
......