Commit 96bbd015 96bbd0154c3f35e3fc9b7797249ce1337279fb75 by Sergey Poznyakoff

Message body primitives.

1 parent 4a8b51f3
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "mu_scm.h"
long body_tag;
struct mu_body
{
body_t body; /* Message body */
stream_t stream; /* Associated stream */
int offset; /* Current offset in the stream */
char *buffer; /* I/O buffer */
int bufsize; /* Size of allocated buffer */
SCM msg; /* Message the body belongs to */
};
/* Initial buffer size */
#define BUF_SIZE 64
/* SMOB functions: */
static SCM
mu_scm_body_mark (SCM body_smob)
{
struct mu_body *mbp = (struct mu_body *) SCM_CDR (body_smob);
return mbp->msg;
}
static scm_sizet
mu_scm_body_free (SCM body_smob)
{
struct mu_body *mbp = (struct mu_body *) SCM_CDR (body_smob);
if (mbp->buffer)
free (mbp->buffer);
free (mbp);
return sizeof (struct mu_body);
}
static int
mu_scm_body_print (SCM body_smob, SCM port, scm_print_state * pstate)
{
struct mu_body *mbp = (struct mu_body *) SCM_CDR (body_smob);
size_t b_size = 0, b_lines = 0, len = 0;
char buffer[512];
body_size (mbp->body, &b_size);
body_lines (mbp->body, &b_lines);
buffer[0] = 0;
body_get_filename (mbp->body, buffer, sizeof (buffer), &len);
scm_puts ("#<body \"", port);
scm_puts (buffer, port);
scm_puts ("\" ", port);
snprintf (buffer, sizeof (buffer), "%3ld %-5ld", b_lines, b_size);
scm_puts (buffer, port);
scm_puts (">", port);
return 1;
}
/* Internal functions: */
int
mu_scm_is_body (SCM scm)
{
return SCM_NIMP (scm) && SCM_CAR (scm) == body_tag;
}
SCM
mu_scm_body_create (SCM msg, body_t body)
{
struct mu_body *mbp;
mbp = scm_must_malloc (sizeof (struct mu_body), "body");
mbp->msg = msg;
mbp->body = body;
mbp->stream = NULL;
mbp->offset = 0;
mbp->buffer = NULL;
mbp->bufsize = 0;
SCM_RETURN_NEWSMOB (body_tag, mbp);
}
/* ************************************************************************* */
/* Guile primitives */
SCM_DEFINE (mu_body_read_line, "mu-body-read-line", 1, 0, 0,
(SCM BODY),
"Read next line from the BODY.")
#define FUNC_NAME s_mu_body_read_line
{
struct mu_body *mbp;
int n, nread;
SCM_ASSERT (mu_scm_is_body (BODY), BODY, SCM_ARG1, FUNC_NAME);
mbp = (struct mu_body *) SCM_CDR (BODY);
if (!mbp->stream)
{
if (body_get_stream (mbp->body, &mbp->stream))
return SCM_BOOL_F;
}
if (!mbp->buffer)
{
mbp->bufsize = BUF_SIZE;
mbp->buffer = malloc (mbp->bufsize);
if (!mbp->buffer)
return SCM_BOOL_F;
}
nread = 0;
while (1)
{
if (stream_readline (mbp->stream, mbp->buffer + nread,
mbp->bufsize - nread,
mbp->offset, &n))
return SCM_BOOL_F;
if (n == 0)
break;
nread += n;
mbp->offset += n;
if (mbp->buffer[n - 1] != '\n' && n == mbp->bufsize)
{
char *p = realloc (mbp->buffer, mbp->bufsize + BUF_SIZE);
if (!p)
break;
mbp->buffer = p;
mbp->bufsize += BUF_SIZE;
}
else
break;
}
if (nread == 0)
return SCM_EOF_VAL;
return scm_makfrom0str (mbp->buffer);
}
#undef FUNC_NAME
SCM_DEFINE (mu_body_write, "mu-body-write", 2, 0, 0,
(SCM BODY, SCM TEXT),
"Append TEXT to message BODY.")
#define FUNC_NAME s_mu_body_write
{
char *ptr;
size_t len, n;
struct mu_body *mbp;
SCM_ASSERT (mu_scm_is_body (BODY), BODY, SCM_ARG1, FUNC_NAME);
mbp = (struct mu_body *) SCM_CDR (BODY);
SCM_ASSERT (SCM_NIMP (TEXT) && SCM_STRINGP (TEXT),
TEXT, SCM_ARG2, FUNC_NAME);
if (!mbp->stream)
{
if (body_get_stream (mbp->body, &mbp->stream))
return SCM_BOOL_F;
}
ptr = SCM_CHARS (TEXT);
len = strlen (ptr);
if (stream_write (mbp->stream, ptr, len, mbp->offset, &n))
{
return SCM_BOOL_F;
}
mbp->offset += n;
return SCM_BOOL_T;
}
#undef FUNC_NAME
/* Initialize the module */
void
mu_scm_body_init ()
{
body_tag = scm_make_smob_type ("body", sizeof (struct mu_body));
scm_set_smob_mark (body_tag, mu_scm_body_mark);
scm_set_smob_free (body_tag, mu_scm_body_free);
scm_set_smob_print (body_tag, mu_scm_body_print);
#include "mu_body.x"
}