Commit d3e3053a d3e3053a81c71f237a7598276f2d7221b0068754 by Alain Magloire

auth.c auth.h header.h mbx_unix.c message.c message.h

 	message0.h

add flaoting message support. Corrected a bug in mailbox_unix_expunge
1 parent 95b223e7
......@@ -25,15 +25,14 @@
struct _auth
{
char *login;
char *passwd;
uid_t owner;
gid_t group;
mode_t mode;
void *owner;
int (*_prologue) (auth_t);
int (*_authenticate) (auth_t);
int (*_epilogue) (auth_t);
};
int
auth_init (auth_t *pauth)
auth_init (auth_t *pauth, void *owner)
{
auth_t auth;
if (pauth == NULL)
......@@ -41,140 +40,77 @@ auth_init (auth_t *pauth)
auth = calloc (1, sizeof (*auth));
if (auth == NULL)
return ENOMEM;
auth->owner = auth->group = -1;
auth->mode = 0600;
auth->owner = owner;
*pauth = auth;
return 0;
}
void
auth_destroy (auth_t *pauth)
auth_destroy (auth_t *pauth, void *owner)
{
if (pauth && *pauth)
{
auth_t auth = *pauth;
free (auth->login);
free (auth->passwd);
free (auth);
if (auth->owner == owner)
free (auth);
*pauth = NULL;
}
}
/* login/passwd */
int
auth_get_login (auth_t auth, char *login, size_t len, size_t *n)
auth_set_authenticate (auth_t auth, int (*_authenticate)(auth_t),
void *owner)
{
size_t nwrite = 0;
if (auth == NULL)
return EINVAL;
nwrite = _cpystr (login, auth->login, len);
if (n)
*n = nwrite;
if (auth->owner != owner)
return EPERM;
auth->_authenticate = _authenticate;
return 0;
}
int
auth_set_login (auth_t auth, const char *login, size_t len)
auth_authenticate (auth_t auth)
{
char *log = NULL;
if (auth == NULL)
if (auth == NULL || auth->_authenticate == NULL)
return EINVAL;
if (login != NULL)
{
log = calloc (len + 1, sizeof (char));
if (log == NULL)
return ENOMEM;
memcpy (log, login, len);
}
free (auth->login);
auth->login = log;
return 0;
return auth->_authenticate (auth);
}
int
auth_get_passwd (auth_t auth, char *passwd, size_t len, size_t *n)
auth_set_epilogue (auth_t auth, int (*_epilogue)(auth_t), void *owner)
{
size_t nwrite = 0;
if (auth == NULL)
return EINVAL;
nwrite = _cpystr (passwd, auth->passwd, len);
if (n)
*n = nwrite;
if (auth->owner != owner)
return EPERM;
auth->_epilogue = _epilogue;
return 0;
}
int
auth_set_passwd (auth_t auth, const char *passwd, size_t len)
auth_epilogue (auth_t auth)
{
char *pass = NULL;
if (auth == NULL)
if (auth == NULL && auth->_epilogue == NULL)
return EINVAL;
if (passwd != NULL)
{
char *pass = calloc (len + 1, sizeof (char));
if (pass == NULL)
return ENOMEM;
memcpy (pass, passwd, len);
}
free (auth->passwd);
auth->passwd = pass;
return 0;
return auth->_epilogue (auth);
}
/* owner and group */
int
auth_get_owner (auth_t auth, uid_t *powner)
auth_set_prologue (auth_t auth, int (*_prologue)(auth_t), void *owner)
{
if (auth == NULL)
return EINVAL;
if (powner)
*powner = auth->owner;
return 0;
}
int
auth_set_owner (auth_t auth, uid_t owner)
{
if (auth == NULL)
return 0;
auth->owner = owner;
if (auth->owner != owner)
return EPERM;
auth->_prologue = _prologue;
return 0;
}
int
auth_get_group (auth_t auth, gid_t *pgroup)
auth_prologue (auth_t auth)
{
if (auth == NULL)
if (auth == NULL && auth->_prologue == NULL)
return EINVAL;
if (pgroup)
*pgroup = auth->group;
return 0;
}
int
auth_set_group (auth_t auth, gid_t group)
{
if (auth == NULL)
return EINVAL;
auth->group = group;
return 0;
}
int
auth_get_mode (auth_t auth, mode_t *pmode)
{
if (auth == NULL)
return EINVAL;
if (pmode)
*pmode = auth->mode;
return 0;
}
int
auth_set_mode (auth_t auth, mode_t mode)
{
if (auth == NULL)
return EINVAL;
auth->mode = mode;
return 0;
return auth->_prologue (auth);
}
......
......@@ -36,25 +36,23 @@ extern "C" {
struct _auth;
typedef struct _auth *auth_t;
extern int auth_init __P ((auth_t *));
extern void auth_destroy __P ((auth_t *));
/* login/passwd */
extern int auth_get_login __P ((auth_t, char *login,
size_t len, size_t *n));
extern int auth_set_login __P ((auth_t, const char *login, size_t len));
extern int auth_get_passwd __P ((auth_t, char *passwd,
size_t len, size_t *n));
extern int auth_set_passwd __P ((auth_t, const char *passwd, size_t len));
/* owner group mode*/
extern int auth_get_owner __P ((auth_t, uid_t *uid));
extern int auth_set_owner __P ((auth_t, uid_t uid));
extern int auth_get_group __P ((auth_t, gid_t *gid));
extern int auth_set_group __P ((auth_t, gid_t gid));
extern int auth_get_mode __P ((auth_t, mode_t *mode));
extern int auth_set_mode __P ((auth_t, mode_t mode));
extern int auth_init __P ((auth_t *, void *owner));
extern void auth_destroy __P ((auth_t *, void *owner));
extern int auth_prologue __P ((auth_t));
extern int auth_set_prologue __P ((auth_t auth,
int (*_prologue) __P ((auth_t)),
void *owner));
extern int auth_authenticate __P ((auth_t));
extern int auth_set_authenticate __P ((auth_t auth,
int (*_authenticate) __P ((auth_t)),
void *owner));
extern int auth_epilogue __P ((auth_t));
extern int auth_set_epilogue __P ((auth_t auth,
int (*_epilogue) __P ((auth_t)),
void *owner));
#ifdef _cpluscplus
}
......
......@@ -81,6 +81,7 @@ extern int header_entry_value __P ((header_t, size_t num, char *buf,
size_t buflen, size_t *total));
extern int header_get_istream __P ((header_t, istream_t *pis));
extern int header_get_ostream __P ((header_t, ostream_t *pos));
extern int header_get_size __P ((header_t, size_t *size));
#ifdef _cpluscplus
}
#endif
......
......@@ -91,6 +91,14 @@ typedef struct _mailbox_unix_message
} *mailbox_unix_message_t;
/*
* umessages is an array of pointers that contains umessages_count
* of mailbox_unix_message_t*; umessages[umessages_count].
* We do it this because realloc() can move everything to
* a new memory region and invalidating all the pointers someone
* has on the message. Thanks to <Dave Inglis> for pointing this out.
* messages_count is the count number of messages parsed so far.
*/
typedef struct _mailbox_unix_data
{
mailbox_unix_message_t *umessages;
......@@ -167,7 +175,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
#define UNIX_SCHEME_LEN 5
#define SEPARATOR '/'
/* sskip the url scheme */
/* skip the url scheme */
if (name_len > UNIX_SCHEME_LEN &&
(name[0] == 'u' || name[0] == 'U') &&
(name[1] == 'n' || name[1] == 'N') &&
......@@ -204,7 +212,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
/* save the basename and dirname */
/* FIXME: We may have to support imap "SELECT"
* So we split the name. But this should probably be
* supported via "maildir:"
* supported via "maildir:" or the mailbox mgr.
*/
/* equivalent to strrchr (name, '/'); */
for (i = name_len, sep = NULL; i >= 0; i--)
......@@ -352,12 +360,14 @@ mailbox_unix_open (mailbox_t mbox, int flags)
if (flags & MU_MAILBOX_APPEND)
flg |= O_APPEND;
/* FIXME: does not really work, but local folders
* should not block since it is local disk ???
*/
/* but local folders should not block since it is local disk ??? */
if (flags & MU_MAILBOX_NONBLOCK)
flg |= O_NONBLOCK;
/* Authentication prologues */
if (mbox->auth)
auth_prologue (mbox->auth);
/* handle CREAT with care, not to follow symlinks */
if (flags & MU_MAILBOX_CREAT)
{
......@@ -376,21 +386,6 @@ mailbox_unix_open (mailbox_t mbox, int flags)
if (fd < 0)
return errno;
}
/*
* Set the owner ship, but should we return the errno
*/
if (mbox->auth)
{
auth_t auth = mbox->auth;
gid_t g ; uid_t u; mode_t m;
g = u = -1; m = 0600;
/* FIXME: what to do when they failed */
auth_get_owner (auth, &u);
auth_get_group (auth, &g);
auth_get_mode (auth, &m);
(void)fchown (fd, u, g);
(void)fchmod (fd, m);
}
}
mailbox_unix_unlock (mbox);
}
......@@ -401,6 +396,29 @@ mailbox_unix_open (mailbox_t mbox, int flags)
return errno;
}
/* Authentication */
if (mbox->auth)
{
int status = auth_authenticate (mbox->auth);
if (status != 0)
return status;
}
else
{
/*
* Set the owner ship, but should we return the errno
*/
gid_t g ; uid_t u; mode_t m;
g = u = -1; m = 0600;
/* FIXME: what to do when they failed */
(void)fchown (fd, u, g);
(void)fchmod (fd, m);
}
/* Authentication epilogues */
if (mbox->auth)
auth_epilogue (mbox->auth);
/* we use FILE * object */
if (flags & MU_MAILBOX_APPEND)
mode = "a";
......@@ -673,7 +691,7 @@ mailbox_unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
{
int over = strlen (buf);
mum->body_end = ftell (mud->file);
mum->body_end -= (over + 1);
mum->body_end -= (over);
body = 0;
mud->messages_count++;
/* reset the progress_counter */
......@@ -993,7 +1011,7 @@ mailbox_unix_tmpfile ()
{
/*FIXME: racing conditions, to correct, .i.e don;t use tmpfile*/
//return tmpfile ();
return fopen ("/tmp/mymail", "w+");
return fopen ("/tmp/mumail", "w+");
}
static int
......
......@@ -26,6 +26,8 @@
#include <stdio.h>
#include <stdlib.h>
static int body_init (body_t *pbody, void *owner);
static void body_destroy (body_t *pbody, void *owner);
static int message_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread );
static int message_write (ostream_t os, const char *buf, size_t buflen,
......@@ -35,7 +37,6 @@ int
message_clone (message_t msg)
{
int status;
FILE *file;
istream_t is;
ostream_t os;
header_t header;
......@@ -70,13 +71,7 @@ message_clone (message_t msg)
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);
status = istream_read (is, buffer, sizeof (buffer), offset, &nread);
if (status != 0)
{
free (pbuf);
......@@ -108,13 +103,14 @@ message_clone (message_t msg)
/* retrieve the body */
{
is = msg->is;
file = tmpfile ();
if (file == NULL)
status = body_init (&body, msg);
if (status != 0)
{
header_destroy (&header, msg);
return errno;
return status;
}
is = msg->is;
offset = 0;
do {
do
......@@ -124,34 +120,28 @@ message_clone (message_t msg)
if (status != 0)
{
header_destroy (&header, msg);
body_destroy (&body, msg);
return status;
}
fwrite (buffer, sizeof (*buffer), nread, file);
fwrite (buffer, sizeof (*buffer), nread, body->file);
offset += nread;
} while (nread > 0);
rewind (file);
rewind (body->file);
}
/* set the body with the streams */
body = calloc (1, sizeof (*body));
if (body == NULL)
{
fclose (file);
header_destroy (&header, msg);
return ENOMEM;
}
status = istream_init (&is, message_read, msg);
if (status != 0)
{
fclose (file);
header_destroy (&header, msg);
body_destroy (&body, msg);
return status;
}
status = ostream_init (&os, message_write, msg);
if (status != 0)
{
fclose (file);
header_destroy (&header, msg);
body_destroy (&body, msg);
istream_destroy (&is, msg);
return status;
}
......@@ -160,8 +150,8 @@ message_clone (message_t msg)
status = attribute_init (&attribute, msg);
if (status != 0)
{
fclose (file);
header_destroy (&header, msg);
body_destroy (&body, msg);
istream_destroy (&is, msg);
ostream_destroy (&os, msg);
}
......@@ -174,7 +164,7 @@ message_clone (message_t msg)
msg->os = os;
msg->body = body;
msg->size = offset;
msg->ref_count = 1;
msg->ref_count++;
msg->owner = NULL; /* orphan */
return 0;
}
......@@ -200,10 +190,21 @@ message_destroy (message_t *pmsg, void *owner)
if (pmsg && *pmsg)
{
message_t msg = *pmsg;
int destroy = 0;
/* always decremente */
msg->ref_count--;
if ((msg->owner && msg->owner == owner) ||
(msg->owner == NULL && msg->ref_count <= 0))
if (msg->owner && msg->owner == owner)
destroy = 1;
if (msg->owner == NULL && msg->ref_count <= 0)
{
destroy = 1;
owner = msg;
}
if (destroy)
{
header_t header = msg->header;
attribute_t attribute = msg->attribute;
......@@ -227,11 +228,11 @@ message_destroy (message_t *pmsg, void *owner)
{
if (body->file)
fclose (body->file);
free (body->content);
free (body);
}
/* notifications are done */
free (msg->event);
/* check again for resurrection before free()ing
* the memory maybe it was clone, if yes we can not
* free the pointer.
......@@ -251,6 +252,15 @@ message_get_header (message_t msg, header_t *phdr)
if (phdr == NULL || msg == NULL)
return EINVAL;
/* is it a floating mesg */
if (msg->header == NULL && msg->owner == NULL)
{
header_t header;
int status = header_init (&header, NULL, 0, msg);
if (status != 0)
return status;
msg->header = header;
}
*phdr = msg->header;
return 0;
}
......@@ -262,6 +272,8 @@ message_set_header (message_t msg, header_t hdr, void *owner)
return EINVAL;
if (msg->owner != owner)
return EACCES;
/* make sure we destoy the old if it was own by the mesg */
header_destroy (&(msg->header), msg);
msg->header = hdr;
return 0;
}
......@@ -271,6 +283,39 @@ message_get_istream (message_t msg, istream_t *pis)
{
if (msg == NULL || pis == NULL)
return EINVAL;
/* lazy floating message body creation */
if (msg->is == NULL && msg->owner == NULL)
{
body_t body;
istream_t is;
ostream_t os;
int status;
status = body_init (&body, msg);
if (status != 0 )
return status;
status = istream_init (&is, message_read, msg);
if (status != 0)
{
body_destroy (&body, msg);
return status;
}
status = ostream_init (&os, message_write, msg);
if (status != 0)
{
istream_destroy (&is, msg);
body_destroy (&body, msg);
return status;
}
/* make sure we've clean */
istream_destroy (&(msg->is), msg);
ostream_destroy (&(msg->os), msg);
body_destroy (&(msg->body), msg);
msg->is = is;
msg->os = os;
msg->body = body;
}
*pis = msg->is;
return 0;
}
......@@ -282,6 +327,8 @@ message_set_istream (message_t msg, istream_t is, void *owner)
return EINVAL;
if (msg->owner != owner)
return EACCES;
/* make sure we destroy the old one if it is own by the message */
istream_destroy (&(msg->is), msg);
msg->is = is;
return 0;
}
......@@ -291,6 +338,39 @@ message_get_ostream (message_t msg, ostream_t *pos)
{
if (msg == NULL || pos == NULL)
return EINVAL;
/* lazy floating message body creation */
if (msg->os == NULL && msg->owner == NULL)
{
body_t body;
istream_t is;
ostream_t os;
int status;
status = body_init (&body, msg->owner);
if (status != 0 )
return status;
status = istream_init (&is, message_read, msg);
if (status != 0)
{
body_destroy (&body, msg->owner);
return status;
}
status = ostream_init (&os, message_write, msg);
if (status != 0)
{
istream_destroy (&is, msg);
body_destroy (&body, msg);
return status;
}
/* make sure we've clean */
istream_destroy (&(msg->is), msg);
ostream_destroy (&(msg->os), msg);
body_destroy (&(msg->body), msg);
msg->is = is;
msg->os = os;
msg->body = body;
}
*pos = msg->os;
return 0;
}
......@@ -302,6 +382,8 @@ message_set_ostream (message_t msg, ostream_t os, void *owner)
return EINVAL;
if (msg->owner != owner)
return EACCES;
/* make sure we destroy the old one if it is own by the message */
ostream_destroy (&(msg->os), msg);
msg->os = os;
return 0;
}
......@@ -332,6 +414,14 @@ message_get_attribute (message_t msg, attribute_t *pattribute)
{
if (msg == NULL || pattribute == NULL)
return EINVAL;
if (msg->attribute == NULL && msg->owner == NULL)
{
attribute_t attribute;
int status = attribute_init (&attribute, msg);
if (status != 0)
return status;
msg->attribute = attribute;
}
*pattribute = msg->attribute;
return 0;
}
......@@ -343,6 +433,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
return EINVAL;
if (msg->owner != owner)
return EACCES;
attribute_destroy (&(msg->attribute), msg);
msg->attribute = attribute;
return 0;
}
......@@ -414,6 +505,61 @@ message_notification (message_t msg, size_t type)
}
}
/* We use the notion of body_t here */
static int
body_init (body_t *pbody, void *owner)
{
body_t body;
FILE *file;
if (pbody == NULL)
return EINVAL;
#ifdef HAVE_MKSTEMP
{
char tmpbuf[L_tmpnam + 1];
int fd;
if (tmpnam (tmpbuf) == NULL ||
(fd = mkstemp (tmpbuf)) == -1 ||
(file = fdopen(fd, "w+")) == NULL)
return errno;
(void)remove(tmpbuf);
}
#else
file = tmpfile ();
if (file == NULL)
return errno;
#endif
/* set the body with the streams */
body = calloc (1, sizeof (*body));
if (body == NULL)
{
fclose (file);
return ENOMEM;
}
body->file = file;
body->owner = owner;
*pbody = body;
return 0;
}
static void
body_destroy (body_t *pbody, void *owner)
{
if (pbody && *pbody)
{
body_t body = *pbody;
if (body->owner == owner)
{
if (body->file)
fclose (body->file);
}
*pbody = NULL;
}
}
static int
message_read (istream_t is, char *buf, size_t buflen,
off_t off, ssize_t *pnread )
......@@ -445,22 +591,8 @@ message_read (istream_t is, char *buf, size_t buflen,
}
/* errno set by fread()/fseek() ? */
}
else if (body->content)
{
off_t ln = body->content_len - off;
if (ln > 0)
{
nread = ((size_t)ln < buflen) ? ln : buflen;
memcpy (buf, body->content + off, nread);
}
else
nread = 0;
errno = 0;
}
else
{
return EINVAL;
}
return EINVAL;
}
if (pnread)
......@@ -499,21 +631,8 @@ message_write (ostream_t os, const char *buf, size_t buflen,
}
/* errno set by fread()/fseek() ? */
}
else if (body->content)
{
off_t ln = body->content_len - off;
if (ln > 0)
{
nwrite = ((size_t)ln < buflen) ? ln : buflen;
memcpy (body->content + off, buf, nwrite);
}
else
nwrite = 0;
}
else
{
return EINVAL;
}
return EINVAL;
}
if (pnwrite)
......
......@@ -40,6 +40,14 @@ extern "C" {
struct _message;
typedef struct _message *message_t;
/* A message is considered to be a container for:
* header_t, body_t, and its attribute_t.
* The notion of body_t is not visible/exported, since
* they are alway tied to a floating message, there was no
* need to create yet another object, getting the {i,o}stream_t
* was enough.
*/
extern int message_init __P ((message_t *, void *owner));
extern void message_destroy __P ((message_t *, void *owner));
......
......@@ -39,11 +39,16 @@ extern "C" {
# endif
#endif /*__P */
/* The notion of body_t is not exported outside,
* there was no need for yet another object.
* since only floating messages need them. The functions
* that manipulate those objects are static to message.c
*
*/
struct _body
{
FILE *file;
char *content;
size_t content_len;
void *owner;
};
typedef struct _body * body_t;
......