Commit 9388abdf 9388abdf122789ac02258c6ff09534a120f87965 by Alain Magloire

After exchange with Sam Roberts, it should possible to

	set a stream on the message and have the message_t do
	the rfc822 parsing.
	{
	  message_t mesg = NULL;
	  header_t header = NULL;
	  stream_t stream = NULL;
	  char buffer[512];
	  off_t off = 0;
	  size_t n = 0;

	  message_create (mesg, NULL);
	  file_stream_crete (&stream, "/home/user/mh/mesg_1");
	  message_set_stream (mesg, stream, NULL);

	  stream = NULL;
	  message_get_header (mesg, &header);
	  header_get_stream (header, &stream);
	  while (stream_readline (stream, buffer, sizeof buffer, off, &n) == 0
	          && n > 0) {
	    printf ("%s", buffer);
	    off += n;
	  }
	  message_destroy (&mesg, NULL);
	}

	* mailbox/message.c (message_header_fill): New
	function implements a header if there was a stream set on the message.
	(message_body_read): Implements the stream_read of body_t of
	a message if there were a stream set.
	(message_is_modified): Check if an object was set to message_t
	and flag it as modified.
	(message_get_body): If a stream was set on the message create a
	temporary stream for the body.
	(message_set_body): Set the message modified.
	(message_set_header): Set the message modified.
	(message_set_envelope): Set the message modified.
	(message_set_attribute): Set the message modified.

	* mailbox/wicket.c (wicket_destroy): return void.
	* include/mailutils/auth.h: wicket_destroy ()
	should return void.
	* mailbox/body.c (body_is_modified): Implemented.
	(body_clear_modified): Implemented.
	* mailbox/body.c (body_is_modified): Implemented.
	(body_clear_modified): Implemented.
	(_body_get_size0): New function.
	(_body_get_lines0): New function.
	(body_get_lines): Call _body_get_lines0().
	(body_get_size): Call _body_get_size0().
	(body_lines): Fall back on the stream and iterate
	the entire stream to find the  line numbers.
	(body_size):  Fall back on the stream for the size.

	* mailbox/folder_imap.c: Check if memory_stream_create()
	succeed and bailout if not.

	* mailbox/header.c (header_destroy): Free header->mstream.
	(fill_blurb): Remove redundant code, header_free_cache was
	doing the same.  Implement the code in term of a memory
	stream to hold the temporary header blurb.
	(header_write): Implemented.

	* mailbox/memory_stream.c (_memory_read): Cast the offset to size_t
	(_memory_readline): Cast the offset to size_t.
	(_memory_write): Cast the offset to size_t.
1 parent 1c1e3040
......@@ -61,14 +61,14 @@ extern int authority_set_authenticate __P ((authority_t, int (*_authenticate) __
struct _wicket;
typedef struct _wicket *wicket_t;
extern int wicket_create __P ((wicket_t *, const char *));
extern int wicket_destroy __P ((wicket_t *));
extern int wicket_set_filename __P ((wicket_t, const char *));
extern int wicket_get_filename __P ((wicket_t, char *, size_t, size_t *));
extern int wicket_set_ticket __P ((wicket_t, int (*)
__P ((wicket_t, const char *,
extern int wicket_create __P ((wicket_t *, const char *));
extern void wicket_destroy __P ((wicket_t *));
extern int wicket_set_filename __P ((wicket_t, const char *));
extern int wicket_get_filename __P ((wicket_t, char *, size_t, size_t *));
extern int wicket_set_ticket __P ((wicket_t, int (*)
__P ((wicket_t, const char *,
const char *, ticket_t *))));
extern int wicket_get_ticket __P ((wicket_t, ticket_t *, const char *, const char *));
extern int wicket_get_ticket __P ((wicket_t, ticket_t *, const char *, const char *));
#ifdef __cplusplus
}
......
......@@ -31,6 +31,8 @@
#include <mailutils/stream.h>
#include <body0.h>
#define BODY_MODIFIED 0x10000
static int lazy_create __P ((body_t));
static int _body_flush __P ((stream_t));
static int _body_get_fd __P ((stream_t, int *));
......@@ -39,8 +41,12 @@ static int _body_readline __P ((stream_t, char *, size_t, off_t, size_t *));
static int _body_truncate __P ((stream_t, off_t));
static int _body_size __P ((stream_t, off_t *));
static int _body_write __P ((stream_t, const char *, size_t, off_t, size_t *));
static int _body_get_size __P ((body_t, size_t *));
static int _body_get_lines __P ((body_t, size_t *));
/* Our own defaults for the body. */
static int _body_get_size __P ((body_t, size_t *));
static int _body_get_lines __P ((body_t, size_t *));
static int _body_get_size0 __P ((stream_t, size_t *));
static int _body_get_lines0 __P ((stream_t, size_t *));
int
body_create (body_t *pbody, void *owner)
......@@ -100,14 +106,15 @@ int
body_is_modified (body_t body)
{
(void)body;
return 0;
return (body) ? (body->flags & BODY_MODIFIED) : 0;
}
/* FIXME: not implemented. */
int
body_clear_modified (body_t body)
{
(void)body;
if (body)
body->flags &= ~BODY_MODIFIED;
return 0;
}
......@@ -178,11 +185,12 @@ body_set_stream (body_t body, stream_t stream, void *owner)
/* make sure we destroy the old one if it is own by the body */
stream_destroy (&(body->stream), body);
body->stream = stream;
body->flags |= BODY_MODIFIED;
return 0;
}
int
body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner)
body_set_lines (body_t body, int (*_lines)__P ((body_t, size_t *)), void *owner)
{
if (body == NULL)
return EINVAL;
......@@ -199,6 +207,9 @@ body_lines (body_t body, size_t *plines)
return EINVAL;
if (body->_lines)
return body->_lines (body, plines);
/* Fall on the stream. */
if (body->stream)
return _body_get_lines0 (body->stream, plines);
if (plines)
*plines = 0;
return 0;
......@@ -211,6 +222,9 @@ body_size (body_t body, size_t *psize)
return EINVAL;
if (body->_size)
return body->_size (body, psize);
/* Fall on the stream. */
if (body->stream)
return _body_get_size0 (body->stream, psize);
if (psize)
*psize = 0;
return 0;
......@@ -227,6 +241,8 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner)
return 0;
}
/* Stub function for the body stream. */
static int
_body_get_fd (stream_t stream, int *fd)
{
......@@ -276,27 +292,40 @@ _body_flush (stream_t stream)
return stream_flush (body->fstream);
}
/* Default function for the body. */
static int
_body_get_size (body_t body, size_t *plines)
_body_get_lines (body_t body, size_t *plines)
{
return _body_get_lines0 (body->fstream, plines);
}
static int
_body_get_size (body_t body, size_t *psize)
{
return _body_get_size0 (body->fstream, psize);
}
static int
_body_get_size0 (stream_t stream, size_t *psize)
{
off_t off = 0;
int status = _body_size (body->stream, &off);
if (plines)
*plines = off;
int status = stream_size (stream, &off);
if (psize)
*psize = off;
return status;
}
static int
_body_get_lines (body_t body, size_t *plines)
_body_get_lines0 (stream_t stream, size_t *plines)
{
int status = stream_flush (body->fstream);
int status = stream_flush (stream);
size_t lines = 0;
if (status == 0)
{
char buf[128];
size_t n = 0;
off_t off = 0;
while ((status = stream_readline (body->fstream, buf, sizeof buf,
while ((status = stream_readline (stream, buf, sizeof buf,
off, &n)) == 0 && n > 0)
{
if (buf[n - 1] == '\n')
......
......@@ -434,7 +434,9 @@ folder_imap_open (folder_t folder, int flags)
{
CHECK_ERROR (f_imap, ENOMEM);
}
memory_stream_create (&f_imap->string.stream);
status = memory_stream_create (&f_imap->string.stream);
CHECK_ERROR (f_imap, status);
stream_open (f_imap->string.stream, NULL, 0, MU_STREAM_RDWR);
}
else
{
......
......@@ -100,6 +100,9 @@ header_destroy (header_t *ph, void *owner)
header_free_cache (header);
if (header->mstream)
stream_destroy (&(header->mstream), NULL);
free (header);
}
*ph = NULL;
......@@ -144,7 +147,7 @@ header_parse (header_t header, const char *blurb, int len)
return 0;
header->blurb_len = len;
header->blurb = calloc (header->blurb_len + 1, sizeof(char));
header->blurb = calloc (1, header->blurb_len + 1);
if (header->blurb == NULL)
return ENOMEM;
memcpy (header->blurb, blurb, header->blurb_len);
......@@ -845,27 +848,11 @@ fill_blurb (header_t header)
{
int status;
char buf[1024];
char *tbuf;
size_t nread = 0;
size_t i;
size_t nread;
if (header->_fill == NULL)
return 0;
/* Free any fast header, since we will load the entire headers. */
for (i = 0; i < header->fhdr_count; i++)
{
if (header->fhdr[i].fn)
free (header->fhdr[i].fn);
if (header->fhdr[i].fv)
free (header->fhdr[i].fv);
}
if (header->fhdr)
{
free (header->fhdr);
header->fhdr = NULL;
}
/* The entire header is now ours(part of header_t), clear all the
overloading. */
header_free_cache (header);
......@@ -875,45 +862,58 @@ fill_blurb (header_t header)
header->_size = NULL;
header->_lines = NULL;
if (header->mstream == NULL)
{
status = memory_stream_create (&(header->mstream));
if (status != 0)
return status;
stream_open (header->mstream, NULL, 0, MU_STREAM_RDWR);
header->stream_len = 0;
}
/* Bring in the entire header. */
do
{
status = header->_fill (header, buf, sizeof (buf),
header->temp_blurb_len, &nread) ;
nread = 0;
status = header->_fill (header, buf, sizeof buf,
header->stream_len, &nread) ;
if (status != 0)
{
if (status != EAGAIN && status != EINTR)
{
free (header->temp_blurb);
header->temp_blurb = NULL;
header->temp_blurb_len = 0;
stream_destroy (&(header->mstream), NULL);
header->stream_len = 0;
}
return status;
}
if (nread > 0)
{
tbuf = realloc (header->temp_blurb, header->temp_blurb_len + nread);
if (tbuf == NULL)
status = stream_write (header->mstream, buf, nread, header->stream_len, NULL);
if (status != 0)
{
free (header->temp_blurb);
header->temp_blurb = NULL;
header->temp_blurb_len = 0;
return ENOMEM;
stream_destroy (&(header->mstream), NULL);
header->stream_len = 0;
return status;
}
header->temp_blurb = tbuf;
memcpy (header->temp_blurb + header->temp_blurb_len, buf, nread);
header->temp_blurb_len += nread;
header->stream_len += nread;
}
}
while (nread > 0);
/* parse it. */
status = header_parse (header, header->temp_blurb, header->temp_blurb_len);
if (header->temp_blurb)
{
free (header->temp_blurb);
header->temp_blurb = NULL;
}
header->temp_blurb_len = 0;
{
char *blurb;
size_t len = header->stream_len;
blurb = calloc (1, len + 1);
if (blurb)
{
stream_read (header->mstream, blurb, len, 0, &len);
status = header_parse (header, blurb, len);
}
free (blurb);
}
stream_destroy (&header->mstream, NULL);
header->stream_len = 0;
return status;
}
......@@ -922,17 +922,80 @@ header_write (stream_t os, const char *buf, size_t buflen,
off_t off, size_t *pnwrite)
{
header_t header = stream_get_owner (os);
if (os == NULL || header == NULL)
int status;
if (header == NULL)
return EINVAL;
(void)buf; (void)off;
if (buflen == 0)
return 0;
if ((size_t)off != header->stream_len)
return ESPIPE;
/* Skip the obvious. */
if (buf == NULL || *buf == '\0' || buflen == 0)
{
if (pnwrite)
*pnwrite = 0;
return 0;
}
if (header->mstream == NULL)
{
status = memory_stream_create (&(header->mstream));
if (status != 0)
return status;
stream_open (header->mstream, NULL, 0, MU_STREAM_RDWR);
header->stream_len = 0;
}
status = stream_write (header->mstream, buf, buflen, header->stream_len, &buflen);
if (status != 0)
{
stream_destroy (&header->mstream, NULL);
header->stream_len = 0;
return status;
}
header->stream_len += buflen;
/* We detect an empty line .i.e "^\n$" this signal the end of the
header. */
if (header->stream_len)
{
int finish = 0;
char nlnl[2];
nlnl[1] = nlnl[0] = '\0';
stream_read (header->mstream, nlnl, 1, 0, NULL);
if (nlnl[0] == '\n')
{
finish = 1;
}
else
{
stream_read (header->mstream, nlnl, 2, header->stream_len - 2, NULL);
if (nlnl[0] == '\n' && nlnl[1] == '\n')
{
finish = 1;
}
}
if (finish)
{
char *blurb;
size_t len = header->stream_len;
blurb = calloc (1, len + 1);
if (blurb)
{
stream_read (header->mstream, blurb, len, 0, &len);
status = header_parse (header, blurb, len);
}
free (blurb);
stream_destroy (&header->mstream, NULL);
header->stream_len = 0;
}
}
if (pnwrite)
*pnwrite = 0;
*pnwrite = buflen;
return 0;
return ENOSYS;
}
static int
......
......@@ -55,8 +55,8 @@ struct _header
void *owner;
/* Data. */
char *temp_blurb;
size_t temp_blurb_len;
stream_t mstream;
size_t stream_len;
char *blurb;
size_t blurb_len;
size_t hdr_count;
......@@ -65,7 +65,7 @@ struct _header
struct _hdr *fhdr;
int flags;
/* Streams. */
/* Stream. */
stream_t stream;
int (*_get_value) __P ((header_t, const char *, char *, size_t , size_t *));
int (*_get_fvalue) __P ((header_t, const char *, char *, size_t , size_t *));
......
......@@ -57,7 +57,7 @@ _memory_read (stream_t stream, char *optr, size_t osize,
{
struct _memory_stream *mfs = stream_get_owner (stream);
size_t n = 0;
if (mfs->ptr != NULL && (offset <= (off_t)mfs->size))
if (mfs->ptr != NULL && ((size_t)offset <= mfs->size))
{
n = ((offset + osize) > mfs->size) ? mfs->size - offset : osize;
memcpy (optr, mfs->ptr + offset, n);
......@@ -74,7 +74,7 @@ _memory_readline (stream_t stream, char *optr, size_t osize,
struct _memory_stream *mfs = stream_get_owner (stream);
char *nl;
size_t n = 0;
if (mfs->ptr && (offset < (off_t)mfs->size))
if (mfs->ptr && ((size_t)offset < mfs->size))
{
/* Save space for the null byte. */
osize--;
......@@ -96,7 +96,7 @@ _memory_write (stream_t stream, const char *iptr, size_t isize,
struct _memory_stream *mfs = stream_get_owner (stream);
/* Bigger we have to realloc. */
if (mfs->capacity < (offset + isize))
if (mfs->capacity < ((size_t)offset + isize))
{
/* Realloc by fixed blocks of 128. */
int newsize = MU_STREAM_MEMORY_BLOCKSIZE *
......
......@@ -35,6 +35,8 @@
#include <message0.h>
#include <mailutils/address.h>
#define MESSAGE_MODIFIED 0x10000;
static int message_read __P ((stream_t is, char *buf, size_t buflen,
off_t off, size_t *pnread ));
static int message_write __P ((stream_t os, const char *buf, size_t buflen,
......@@ -45,6 +47,11 @@ static int message_sender __P ((envelope_t envelope, char *buf, size_t len,
static int message_date __P ((envelope_t envelope, char *buf, size_t len,
size_t *pnwrite));
static int message_stream_size __P((stream_t stream, off_t *psize));
static int message_header_fill __P ((header_t header, char *buffer,
size_t buflen, off_t off,
size_t * pnread));
static int message_body_read __P ((stream_t stream, char *buffer,
size_t n, off_t off, size_t *pn));
/* Allocate ressources for the message_t. */
int
......@@ -168,6 +175,7 @@ message_is_modified (message_t msg)
mod |= header_is_modified (msg->header);
mod |= attribute_is_modified (msg->attribute);
mod |= body_is_modified (msg->body);
mod |= msg->flags;
}
return mod;
}
......@@ -183,6 +191,7 @@ message_clear_modified (message_t msg)
attribute_clear_modified (msg->attribute);
if (msg->body)
body_clear_modified (msg->body);
msg->flags &= ~MESSAGE_MODIFIED;
}
return 0;
}
......@@ -220,6 +229,13 @@ message_get_header (message_t msg, header_t *phdr)
int status = header_create (&header, NULL, 0, msg);
if (status != 0)
return status;
if (msg->stream)
{
/* Was it created by us? */
message_t mesg = stream_get_owner (msg->stream);
if (mesg != msg)
header_set_fill (header, message_header_fill, msg);
}
msg->header = header;
}
*phdr = msg->header;
......@@ -238,6 +254,7 @@ message_set_header (message_t msg, header_t hdr, void *owner)
if (msg->header)
header_destroy (&(msg->header), msg);
msg->header = hdr;
msg->flags |= MESSAGE_MODIFIED;
return 0;
}
......@@ -254,6 +271,26 @@ message_get_body (message_t msg, body_t *pbody)
int status = body_create (&body, msg);
if (status != 0)
return status;
/* If a stream is already set use it to create the body stream. */
if (msg->stream)
{
/* Was it created by us? */
message_t mesg = stream_get_owner (msg->stream);
if (mesg != msg)
{
stream_t stream;
int flags = 0;
stream_get_flags (msg->stream, &flags);
if ((status = stream_create (&stream, flags, body)) != 0)
{
body_destroy (&body, msg);
return status;
}
stream_set_read (stream, message_body_read, body);
stream_setbufsiz (stream, 128);
body_set_stream (body, stream, msg);
}
}
msg->body = body;
}
*pbody = msg->body;
......@@ -272,6 +309,7 @@ message_set_body (message_t msg, body_t body, void *owner)
if (msg->body)
body_destroy (&(msg->body), msg);
msg->body = body;
msg->flags |= MESSAGE_MODIFIED;
return 0;
}
......@@ -287,6 +325,7 @@ message_set_stream (message_t msg, stream_t stream, void *owner)
if (msg->stream)
stream_destroy (&(msg->stream), msg);
msg->stream = stream;
msg->flags |= MESSAGE_MODIFIED;
return 0;
}
......@@ -411,6 +450,7 @@ message_set_envelope (message_t msg, envelope_t envelope, void *owner)
if (msg->envelope)
envelope_destroy (&(msg->envelope), msg);
msg->envelope = envelope;
msg->flags |= MESSAGE_MODIFIED;
return 0;
}
......@@ -442,6 +482,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
if (msg->attribute)
attribute_destroy (&(msg->attribute), owner);
msg->attribute = attribute;
msg->flags |= MESSAGE_MODIFIED;
return 0;
}
......@@ -666,6 +707,7 @@ message_get_observable (message_t msg, observable_t *pobservable)
return 0;
}
/* Implements the stream_read () on the message stream. */
static int
message_read (stream_t is, char *buf, size_t buflen,
off_t off, size_t *pnread )
......@@ -703,6 +745,7 @@ message_read (stream_t is, char *buf, size_t buflen,
return 0;
}
/* Implements the stream_write () on the message stream. */
static int
message_write (stream_t os, const char *buf, size_t buflen,
off_t off, size_t *pnwrite)
......@@ -715,7 +758,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
return EINVAL;
/* Skip the obvious. */
if (buf == NULL || *buf == '\0' || buflen == 0)
if (buf == NULL || buflen == 0)
{
if (pnwrite)
*pnwrite = 0;
......@@ -726,39 +769,21 @@ message_write (stream_t os, const char *buf, size_t buflen,
{
size_t len;
char *nl;
char *thdr;
header_t header = NULL;
stream_t hstream = NULL;
message_get_header (msg, &header);
header_get_stream (header, &hstream);
while (!msg->hdr_done && (nl = memchr (buf, '\n', buflen)) != NULL)
{
len = nl - buf + 1;
/* Allocate more buffer to hold the header. */
thdr = realloc (msg->hdr_buf, msg->hdr_buflen + len);
if (thdr == NULL)
{
free (msg->hdr_buf);
msg->hdr_buf = NULL;
msg->hdr_buflen = 0;
return ENOMEM;
}
else
msg->hdr_buf = thdr;
memcpy (msg->hdr_buf + msg->hdr_buflen, buf, len);
status = stream_write (hstream, buf, len, msg->hdr_buflen, NULL);
if (status != 0)
return status;
msg->hdr_buflen += len;
/* We detect an empty line .i.e "^\n$" this signal the end of the
header. */
if (buf == nl)
{
header_destroy (&(msg->header), msg);
status = header_create (&(msg->header), msg->hdr_buf,
msg->hdr_buflen, msg);
free (msg->hdr_buf);
msg->hdr_buf = NULL;
if (status != 0)
{
msg->hdr_buflen = 0;
return status;
}
msg->hdr_done = 1;
}
msg->hdr_done = 1;
buf = nl + 1;
buflen -= len;
}
......@@ -767,17 +792,13 @@ message_write (stream_t os, const char *buf, size_t buflen,
/* Message header is not complete but was not a full line. */
if (!msg->hdr_done && buflen > 0)
{
char *thdr = realloc (msg->hdr_buf, msg->hdr_buflen + buflen);
if (thdr == NULL)
{
free (msg->hdr_buf);
msg->hdr_buf = NULL;
msg->hdr_buflen = 0;
return ENOMEM;
}
else
msg->hdr_buf = thdr;
memcpy (msg->hdr_buf + msg->hdr_buflen, buf, buflen);
header_t header = NULL;
stream_t hstream = NULL;
message_get_header (msg, &header);
header_get_stream (header, &hstream);
status = stream_write (hstream, buf, buflen, msg->hdr_buflen, NULL);
if (status != 0)
return status;
msg->hdr_buflen += buflen;
buflen = 0;
}
......@@ -806,6 +827,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
return status;
}
/* Implements the stream_get_fd () on the message stream. */
static int
message_get_fd (stream_t stream, int *pfd)
{
......@@ -831,7 +853,8 @@ message_get_fd (stream_t stream, int *pfd)
return stream_get_fd (is, pfd);
}
int
/* Implements the stream_stream_size () on the message stream. */
static int
message_stream_size (stream_t stream, off_t *psize)
{
message_t msg = stream_get_owner (stream);
......@@ -920,3 +943,66 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
*pnwrite = n;
return 0;
}
static int
message_header_fill (header_t header, char *buffer, size_t buflen,
off_t off, size_t * pnread)
{
int status = 0;
message_t msg = header_get_owner (header);
stream_t stream = NULL;
size_t nread = 0;
/* Noop. */
if (buffer == NULL || buflen == 0)
{
if (pnread)
*pnread = nread;
return 0;
}
if (!msg->hdr_done)
{
status = message_get_stream (msg, &stream);
if (status == 0)
{
/* Position the file pointer and the buffer. */
status = stream_readline (stream, buffer, buflen, off, &nread);
/* Detect the end of the headers. */
if (nread && buffer[0] == '\n' && buffer[1] == '\0')
{
msg->hdr_done = 1;
}
msg->hdr_buflen += nread;
}
}
if (pnread)
*pnread = nread;
return status;
}
static int
message_body_read (stream_t stream, char *buffer, size_t n, off_t off,
size_t *pn)
{
body_t body = stream_get_owner (stream);
message_t msg = body_get_owner (body);
size_t nread = 0;
header_t header = NULL;
stream_t bstream = NULL;
size_t size = 0;
int status;
message_get_header (msg, &header);
status = header_size (msg->header, &size);
if (status == 0)
{
message_get_stream (msg, &bstream);
status = stream_read (bstream, buffer, n, size + off, &nread);
}
if (pn)
*pn = nread;
return status;
}
......
......@@ -27,6 +27,7 @@
#include <unistd.h>
#include <ctype.h>
#include <mailutils/mutil.h>
#include <auth0.h>
struct myticket_data
......@@ -56,7 +57,7 @@ wicket_create (wicket_t *pwicket, const char *filename)
return 0;
}
int
void
wicket_destroy (wicket_t *pwicket)
{
if (pwicket && *pwicket)
......@@ -96,13 +97,13 @@ wicket_set_filename (wicket_t wicket, const char *filename)
}
int
wicket_set_ticket (wicket_t wicket, int _get_ticket
wicket_set_ticket (wicket_t wicket, int get_ticket
__P ((wicket_t, const char *, const char *, ticket_t *)))
{
if (wicket == NULL)
return EINVAL;
wicket->_get_ticket = _get_ticket;
wicket->_get_ticket = get_ticket;
return 0;
}
......