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
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _EVENT_H
#define _EVENT_H
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /* __P */
#ifdef _cpluscplus
extern "C" {
#endif
struct _event
{
size_t type;
void *arg;
int (*_action) __P ((size_t type, void *arg));
};
typedef struct _event *event_t;
#ifdef _cpluscplus
}
#endif
#endif /* _EVENT_H */
......@@ -26,9 +26,11 @@
#include <stdlib.h>
#include <errno.h>
static int header_parse (header_t *h, const char *blurb, size_t len);
static int header_parse (header_t h, const char *blurb, size_t len);
static int header_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread);
static int header_write (ostream_t os, const char *buf, size_t buflen,
off_t off, ssize_t *pnwrite);
struct _hdr
{
......@@ -67,9 +69,18 @@ header_init (header_t *ph, const char *blurb, size_t len, void *owner)
return ENOMEM;
h->owner = owner;
status = header_parse (&h, blurb, len);
status = header_parse (h, blurb, len);
if (status != 0)
free (h);
status = istream_init (&(h->is), header_read, h);
if (status != 0)
return status;
status = ostream_init (&(h->os), header_write, h);
if (status != 0)
return status;
*ph = h;
return status;
}
......@@ -109,21 +120,16 @@ header_destroy (header_t *ph, void *owner)
* on how to handle the case.
*/
static int
header_parse (header_t *h, const char *blurb, size_t len)
header_parse (header_t header, const char *blurb, size_t len)
{
header_t header;
char *header_end;
char *header_start;
char *header_start2;
struct _hdr *hdr;
if (h == NULL || blurb == NULL || len == 0)
if (header == NULL || blurb == NULL || len == 0)
return EINVAL;
header = calloc (1, sizeof (*header));
if (header == NULL)
return ENOMEM;
header->blurb = calloc (1, len);
if (header->blurb == NULL)
{
......@@ -200,7 +206,6 @@ header_parse (header_t *h, const char *blurb, size_t len)
header->hdr[header->hdr_count - 1].fv_end = header_end;
}
}
*h = header;
return 0;
}
......@@ -336,6 +341,24 @@ header_entry_value (header_t header, size_t num, char *buf,
}
static int
header_write (ostream_t os, const char *buf, size_t buflen,
off_t off, ssize_t *pnwrite)
{
header_t header;
if (os == NULL || (header = (header_t)os->owner) == NULL)
return EINVAL;
(void)buf; (void)off;
if (buflen == 0)
return 0;
if (pnwrite)
*pnwrite = 0;
return ENOSYS;
}
static int
header_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread)
{
......@@ -365,16 +388,8 @@ header_read (istream_t is, char *buf, size_t buflen,
int
header_get_istream (header_t header, istream_t *pis)
{
int err;
if (header == NULL || pis == NULL)
return EINVAL;
/* already done */
if (header->is)
*pis = header->is;
err = istream_init (&(header->is), header_read, header->owner);
if (err != 0)
return err;
*pis = header->is;
return 0;
}
......@@ -384,5 +399,6 @@ rfc822_get_ostream (header_t header, ostream_t *pos)
{
if (header == NULL || pos == NULL)
return EINVAL;
*pos = header->os;
return ENOSYS;
}
......
......@@ -64,7 +64,7 @@ istream_destroy (istream_t *pis, void *owner)
is->ref_count--;
if ((is->owner && is->owner == owner) ||
(is->owner == NULL && is->ref_count <= 0))
free (pis);
free (is);
*pis = NULL;
}
}
......@@ -78,7 +78,7 @@ ostream_destroy (ostream_t *pos, void *owner)
os->ref_count--;
if ((os->owner && os->owner == owner) ||
(os->owner == NULL && os->ref_count <= 0))
free (*pos);
free (os);
*pos = NULL;
}
}
......
......@@ -157,19 +157,6 @@ mailbox_num_deleted (mailbox_t mbox, size_t *num)
return mbox->_num_deleted (mbox, num);
}
/* hook to allow some sort of "progress bar" .. I don't like it
* but can not find any other way yet
*/
int
mailbox_progress (mailbox_t mbox, int (*progress) (int, void *arg), void *arg)
{
if (mbox == NULL)
return EINVAL;
mbox->_progress = progress;
mbox->progress_arg = arg;
return 0;
}
int
mailbox_is_updated (mailbox_t mbox)
{
......@@ -217,3 +204,73 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth)
return 0;
}
int
mailbox_register (mailbox_t mbox, size_t type,
int (*action) (size_t type, void *arg),
void *arg)
{
size_t i;
event_t event;
/* FIXME: I should check for invalid types */
if (mbox == NULL || action == NULL)
return EINVAL;
/* find a free spot */
for (i = 0; i < mbox->event_num; i++)
{
event = &(mbox->event[i]);
if (event->_action == NULL)
{
event->_action = action;
event->type = type;
event->arg = arg;
return 0;
}
}
/* a new one */
event = realloc (mbox->event, (mbox->event_num + 1) * sizeof (*event));
if (event == NULL)
return ENOMEM;
mbox->event = event;
event[mbox->event_num]._action = action;
event[mbox->event_num].type = type;
event[mbox->event_num].arg = arg;
mbox->event_num++;
return 0;
}
int
mailbox_deregister (mailbox_t mbox, void *action)
{
size_t i;
event_t event;
for (i = 0; i < mbox->event_num; i++)
{
event = &(mbox->event[i]);
if (event->_action == action)
{
event->type = 0;
event->_action = NULL;
event->arg = NULL;
return 0;
}
}
return ENOENT;
}
void
mailbox_notification (mailbox_t mbox, size_t type)
{
size_t i;
event_t event;
for (i = 0; i < mbox->event_num; i++)
{
event = &(mbox->event[i]);
if ((event->_action) && (event->type & type))
event->_action (type, event->arg);
}
}
......
......@@ -81,6 +81,17 @@ extern int mailbox_size __P ((mailbox_t, off_t size));
extern int mailbox_get_url __P ((mailbox_t, url_t *));
/* events */
#define MU_EVT_MBX_DESTROY 1
#define MU_EVT_MBX_CORRUPTED 2
#define MU_EVT_MBX_MSG_ADD 4
#define MU_EVT_MBX_PROGRESS 8
extern int mailbox_register __P ((mailbox_t mbox, size_t type,
int (*action) (size_t type, void *arg),
void *arg));
extern int mailbox_deregister __P ((mailbox_t mbox, void *action));
#ifdef __cplusplus
}
#endif
......
......@@ -19,6 +19,7 @@
#define _MAILBOX0_H
#include <mailbox.h>
#include <event.h>
#include <sys/types.h>
#include <stdio.h>
......@@ -42,8 +43,10 @@ struct _mailbox
auth_t auth;
locker_t locker;
url_t url;
int (*_progress) __P ((int, void *arg));
void *progress_arg;
/* register events */
event_t event;
size_t event_num;
/* Back pointer to the specific mailbox */
void *data;
......@@ -87,9 +90,7 @@ extern int mailbox_get_attribute __P ((mailbox_t mbox, size_t msgno,
attribute_t *attr));
extern int mailbox_set_attribute __P ((mailbox_t mbox, size_t msgno,
attribute_t attr));
extern int mailbox_progress __P ((mailbox_t mbox,
int (*progress) (int, void *arg),
void *arg));
extern void mailbox_notification __P ((mailbox_t mbox, size_t type));
#ifdef __cplusplus
......
......@@ -21,8 +21,8 @@
#include <registrar0.h>
#include <message0.h>
#include <url0.h>
#include <attribute.h>
#include <io0.h>
#include <attribute.h>
#include <header.h>
#include <auth.h>
#include <locker.h>
......@@ -105,6 +105,8 @@ typedef struct _mailbox_unix_data
#endif
time_t mtime;
off_t size;
int busy;
} *mailbox_unix_data_t;
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,
/* private stuff */
static int mailbox_unix_validity (mailbox_t mbox, size_t msgno);
static int mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
off_t off, ssize_t *pnread);
static int mailbox_unix_is_from (const char *);
......@@ -312,6 +315,8 @@ mailbox_unix_destroy (mailbox_t *pmbox)
free (mbox->data);
}
free (mbox->name);
/* free the event array */
free (mbox->event);
/* destroy the url */
if (mbox->url)
url_destroy (&(mbox->url));
......@@ -623,6 +628,10 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
if (mud->busy == 1)
return 0;
mud->busy = 1;
/* FIXME: I should also block signals and check cancelstate(Pthread)
since We can not afford to be intr */
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
......@@ -635,6 +644,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mud->busy = 0;
return status;
}
mud->mtime = st.st_mtime;
......@@ -653,6 +663,18 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
mum[count - 1].body_end = ftell (mud->file);
mum[count - 1].body_end -= (over + 1);
body = 0;
/* notifications */
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD);
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
}
header = 1;
}
......@@ -665,21 +687,6 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
int over = strlen (buf);
count++;
/* FIXME: This is a bad idea, we should not be allowed to
* jump out from the parsing this way. We sit at the mercy
* of this function(_progress) waiting for disaster.
*/
if (mbox->_progress)
{
/* FIXME: and its getting better, they can even bailout */
if (mbox->_progress (count, mbox->progress_arg) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return EINTR;
}
}
/* allocate space for the new message */
if (count > mud->messages_count)
{
......@@ -689,6 +696,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mud->busy = 0;
return ENOMEM;
}
mud->messages_count++;
......@@ -712,6 +720,7 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mud->busy = 0;
return status;
}
mum[count - 1].header_end = ftell (mud->file) - strlen(buf);
......@@ -733,8 +742,32 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
fseek (mud->file, content_length, SEEK_CUR);
content_length = -1;
body = 0;
/* notification release all locks*/
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD);
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
}
}
/* notifications release all locks */
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
mailbox_notification (mbox, MU_EVT_MBX_PROGRESS);
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
mailbox_unix_touchlock (mbox);
} /* while */
status = errno;
......@@ -750,6 +783,8 @@ mailbox_unix_parse (mailbox_t mbox, size_t *msgs)
mailbox_unix_unlock (mbox);
if (msgs)
*msgs = count;
mud->busy = 0;
mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD);
return status;
}
......@@ -771,25 +806,26 @@ mailbox_unix_is_updated (mailbox_t mbox)
}
static int
mailbox_unix_is_valid (mailbox_t mbox, size_t msgno)
mailbox_unix_validity (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return 0;
return EINVAL;
/* valid ? */
return (mud->messages_count > 0 && msgno <= mud->messages_count);
return !(mud->messages_count > 0 && msgno > 0 &&
msgno <= mud->messages_count);
}
static int
mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
! mailbox_unix_is_valid (mbox, msgno))
return 0;
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
msgno--;
mud = (mailbox_unix_data_t) mbox->data;
return attribute_is_deleted (mud->umessages[msgno].new_attr);
}
......@@ -797,18 +833,17 @@ static int
mailbox_unix_delete (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
/* oops out of range ? */
/* if already deleted, noop */
if (! mailbox_unix_is_valid (mbox, msgno) ||
mailbox_unix_is_deleted (mbox, msgno))
if (mailbox_unix_is_deleted (mbox, msgno))
return 0;
/* Mark for deletion */
msgno--;
mud = (mailbox_unix_data_t) mbox->data;
attribute_set_deleted (mud->umessages[msgno].new_attr);
return 0;
}
......@@ -838,17 +873,17 @@ static int
mailbox_unix_undelete (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
/* oops out of range ? */
/* if already undeleted, noop */
if (! mailbox_unix_is_valid (mbox, msgno) ||
! mailbox_unix_is_deleted (mbox, msgno))
if (! mailbox_unix_is_deleted (mbox, msgno))
return 0;
/* Mark undeletion */
msgno--;
mud = (mailbox_unix_data_t) mbox->data;
attribute_unset_deleted (mud->umessages[msgno].new_attr);
return 0;
}
......@@ -894,10 +929,15 @@ mailbox_unix_expunge (mailbox_t mbox)
if (tmpfile == NULL)
return errno;
if (mud->busy == 1)
return EINPROGRESS;
mud->busy = 1;
/* Get the lock */
if (mailbox_unix_lock (mbox, MU_LOCKER_WRLOCK) < 0)
{
fclose (tmpfile);
mud->busy = 0;
return ENOLCK;
}
......@@ -1147,6 +1187,7 @@ bailout:
mailbox_unix_iunlock (mbox);
fclose (tmpfile);
sigprocmask (SIG_UNBLOCK, &sigset, 0);
mud->busy = 0;
return status;
}
......@@ -1155,7 +1196,6 @@ mailbox_unix_readstream (istream_t is, char *buffer, size_t buflen,
off_t off, ssize_t *pnread)
{
mailbox_unix_message_t mum;
size_t len;
size_t nread = 0;
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,
off_t ln = mum->body_end - (mum->body + off);
if (ln > 0)
{
nread = ((size_t)ln < len) ? ln : len;
nread = ((size_t)ln < buflen) ? ln : buflen;
/* position the file pointer and the buffer */
if (fseek (mum->file, mum->body + off, SEEK_SET) < 0)
{
......@@ -1202,14 +1242,13 @@ mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
{
mailbox_unix_data_t mud;
size_t nread = 0;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
/* check if valid */
if (! mailbox_unix_is_valid (mbox, msgno))
return EINVAL;
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
mud = (mailbox_unix_data_t) mbox->data;
msgno--;
if (buffer == NULL || len == 0)
{
......@@ -1271,7 +1310,7 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
mailbox_unix_is_deleted (mbox, msgno))
return EINVAL;
mum = &(mud->umessages[msgno]);
mum = &(mud->umessages[msgno - 1]);
/* check if we already have it */
if (mum->message)
......@@ -1326,14 +1365,12 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
message_set_header (msg, header, mum);
/* prepare the istream */
status = istream_init (&is, mailbox_unix_readstream, mum);
if ((status = istream_init (&is, mailbox_unix_readstream, mum)) != 0 ||
(status = message_set_istream (msg, is, mum)) != 0)
{
message_destroy (&msg, mum);
return status;
}
message_set_istream (msg, is, mum);
/* set the attribute */
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)
return status;
}
/* attach the message to the mailbox unix data */
mum->message = msg;
if (pmsg)
*pmsg = msg;
return 0;
......
......@@ -31,36 +31,59 @@ static int message_read (istream_t is, char *buf, size_t buflen,
static int message_write (ostream_t os, const char *buf, size_t buflen,
off_t off, ssize_t *pnwrite);
int message_clone (message_t omsg, message_t *pmsg)
int
message_clone (message_t msg)
{
int status;
FILE *file;
message_t msg;
istream_t is;
ostream_t os;
header_t header;
attribute_t attribute;
body_t body;
char buffer[BUFSIZ];
char *pbuf = NULL;
char *tbuf = NULL;
off_t offset = 0;
size_t nread = 0;
if (msg == NULL)
return EINVAL;
/* If is not own, then it's a floating message
* just bump the reference count.
*/
if (msg->owner == NULL)
{
if (msg->ref_count <= 0)
msg->ref_count = 1;
else
msg->ref_count++;
return 0;
}
/* retreive the header */
{
status = message_get_header (omsg, &header);
if (status != 0)
return status;
header = msg->header;
status = header_get_istream (header, &is);
if (status != 0)
return status;
do {
/* FIXME: can not afford to be non blocking here
* so we busy spin. VERY VERY BAD
*/
do {
status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
} while (status == EAGAIN);
if (status != 0)
{
free (pbuf);
return status;
}
if (nread == 0)
break;
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
......@@ -73,7 +96,6 @@ int message_clone (message_t omsg, message_t *pmsg)
offset += nread;
} while (nread > 0);
status = header_init (&header, pbuf, offset, NULL);
if (status != 0)
{
......@@ -81,11 +103,11 @@ int message_clone (message_t omsg, message_t *pmsg)
return status;
}
free (pbuf);
}
/* retrieve the body */
{
is = msg->is;
file = tmpfile ();
if (file == NULL)
{
......@@ -93,44 +115,66 @@ int message_clone (message_t omsg, message_t *pmsg)
return errno;
}
offset = 0;
message_get_istream (omsg, &is);
do {
istream_read (is, buffer, sizeof (buffer), offset, &nread);
do
{
status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
} while (status == EAGAIN);
if (status != 0)
{
header_destroy (&header, NULL);
return status;
}
fwrite (buffer, sizeof (*buffer), nread, file);
offset += nread;
} while (nread > 0);
rewind (file);
}
/* create the message */
status = message_init (&msg, NULL);
if (status != 0)
return status;
/* set the header */
message_set_header (msg, header, NULL);
/* set the body with the streams */
msg->body = calloc (1, sizeof (*(msg->body)));
if (msg->body == NULL)
body = calloc (1, sizeof (*body));
if (body == NULL)
{
fclose (file);
message_destroy (&msg, NULL);
header_destroy (&header, NULL);
return ENOMEM;
}
status = istream_init (&is, message_read, NULL);
if (status != 0)
{
message_destroy (&msg, NULL);
fclose (file);
header_destroy (&header, NULL);
return status;
}
status = ostream_init (&os, message_write, NULL);
if (status != 0)
{
message_destroy (&msg, NULL);
fclose (file);
header_destroy (&header, NULL);
istream_destroy (&is, NULL);
return status;
}
*pmsg = msg;
/* attribute */
status = attribute_init (&attribute, NULL);
if (status != 0)
{
fclose (file);
header_destroy (&header, NULL);
istream_destroy (&is, NULL);
ostream_destroy (&os, NULL);
}
attribute_copy (attribute, msg->attribute);
/* every thing went ok */
msg->header = header;
msg->attribute = attribute;
msg->is = is;
msg->os = os;
msg->body = body;
msg->size = offset;
msg->ref_count = 1;
msg->owner = NULL; /* orphan */
return 0;
}
......@@ -160,24 +204,37 @@ message_destroy (message_t *pmsg, void *owner)
if ((msg->owner && msg->owner == owner) ||
(msg->owner == NULL && msg->ref_count <= 0))
{
header_t header = msg->header;
attribute_t attribute = msg->attribute;
istream_t is = msg->is;
ostream_t os = msg->os;
body_t body = msg->body;
/* notify the listeners */
message_notification (msg, MU_EVT_MSG_DESTROY);
/* header */
header_destroy (&(msg->header), owner);
header_destroy (&header, owner);
/* attribute */
attribute_destroy (&(msg->attribute), owner);
attribute_destroy (&attribute, owner);
/* istream */
istream_destroy (&(msg->is), owner);
istream_destroy (&is, owner);
/* ostream */
ostream_destroy (&(msg->os), owner);
ostream_destroy (&os, owner);
/* if sometype of floating/temporary message */
if (msg->body)
if (body)
{
body_t body = msg->body;
if (body->file)
fclose (body->file);
free (body->content);
free (msg->body);
free (body);
}
/* check again for resurrection before free()ing
* the memory maybe it was clone, if yes we can not
* free the pointer.
*
*/
if (msg->ref_count <= 0)
free (msg);
}
/* loose the link */
......@@ -287,6 +344,73 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
return 0;
}
int
message_register (message_t msg, size_t type,
int (*action) (size_t typ, void *arg), void *arg)
{
event_t event;
size_t i;
if (msg == NULL || action == NULL || type == 0)
return EINVAL;
/* find a free spot */
for (i = 0; i < msg->event_num; i++)
{
event = &(msg->event[i]);
if (event->_action == NULL)
{
event->type = type;
event->_action = action;
event->arg = arg;
return 0;
}
}
event = realloc (msg->event, (msg->event_num + 1)*sizeof (*event));
if (event == NULL)
return ENOMEM;
msg->event = event;
event[msg->event_num]._action = action;
event[msg->event_num].type = type;
event[msg->event_num].arg = arg;
msg->event_num++;
return 0;
}
int
message_deregister (message_t msg, void *action)
{
size_t i;
event_t event;
if (msg == NULL || action == NULL)
return EINVAL;
for (i = 0; i < msg->event_num; i++)
{
event = &(msg->event[i]);
if (event->_action == action)
{
event->type = 0;
event->_action = NULL;
event->arg = NULL;
return 0;
}
}
return ENOENT;
}
void
message_notification (message_t msg, size_t type)
{
size_t i;
event_t event;
for (i = 0; i < msg->event_num; i++)
{
event = &(msg->event[i]);
if ((event->_action) && (event->type & type))
event->_action (type, event->arg);
}
}
static int
message_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread )
......
......@@ -59,8 +59,14 @@ extern int message_set_size __P ((message_t, size_t, void *owner));
extern int message_get_attribute __P ((message_t, attribute_t *));
extern int message_set_attribute __P ((message_t, attribute_t, void *owner));
extern int message_clone __P ((message_t, message_t *));
extern int message_clone __P ((message_t));
/* events */
#define MU_EVT_MSG_DESTROY 32
extern int message_register __P ((message_t msg, size_t type,
int (*action) (size_t typ, void *arg),
void *arg));
extern int message_deregister __P ((message_t msg, void *action));
#ifdef _cpluscplus
}
#endif
......
......@@ -22,6 +22,7 @@
#include <header.h>
#include <message.h>
#include <mailbox.h>
#include <event.h>
#include <sys/types.h>
#include <stdio.h>
......@@ -30,6 +31,14 @@
extern "C" {
#endif
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /*__P */
struct _body
{
FILE *file;
......@@ -54,6 +63,9 @@ struct _message
void *owner;
int ref_count;
event_t event;
size_t event_num;
int (*_get_header) __P ((message_t msg, header_t *hdr));
int (*_set_header) __P ((message_t msg, header_t hdr, void *owner));
......@@ -74,4 +86,5 @@ struct _message
}
#endif
extern void message_notification (message_t msg, size_t type);
#endif /* _MESSAGE_H */
......