Commit 41d545f2 41d545f2adbebedd5e19b2338df4f1cad3005bc7 by Alain Magloire

snprintf() on some platforms return -1 for error on others

the count that would have been written, the latter is C99 conformant
but the former is also in wide use since snprintf () was not part
of ANSI C, or posix.
1 parent c3fb8658
......@@ -308,7 +308,7 @@ _file_open (stream_t stream, const char *filename, int port, int flags)
}
#if BUFSIZ <= 1024
/* Give us some room to breath, for OS with two small stdio buffers. */
setvbuf (fs->file, iobuffer, _IOFBF, 8192);
setvbuf (fs->file, NULL, _IOFBF, 8192);
#endif
stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
return 0;
......
......@@ -51,9 +51,10 @@ extern "C" {
#define MIME_PARSER_ACTIVE 0x80000000
#define MIME_PARSER_HAVE_CR 0x40000000
#define MIME_NEW_MESSAGE 0x20000000
#define MIME_ADDED_CONTENT_TYPE 0x10000000
#define MIME_ADDED_MULTIPART 0x08000000
#define MIME_ADDED_CT 0x10000000
#define MIME_ADDED_MULTIPART_CT 0x08000000
#define MIME_INSERT_BOUNDARY 0x04000000
#define MIME_ADDING_BOUNDARY 0x02000000
struct _mime
{
......@@ -70,7 +71,9 @@ struct _mime
int cur_offset;
int cur_part;
int part_offset;
int boundary_len;
int preamble;
int postamble;
/* parser state */
char *cur_line;
int line_ndx;
......
......@@ -21,10 +21,13 @@
#include <string.h>
#include <stdlib.h>
#include <paths.h>
#include <errno.h>
#include <stdio.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
#include <mailutils/mailbox.h>
#ifndef _PATH_MAILDIR
......
......@@ -1551,25 +1551,35 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset,
return 0;
}
/* C99 says that a conforming implementations of snprintf ()
should return the number of char that would have been call
but many GNU/Linux && BSD implementations return -1 on error.
Worse QnX/Neutrino actually does not put the terminal
null char. So let's try to cope. */
static int
pop_writeline (pop_data_t mpd, const char *format, ...)
{
int len;
va_list ap;
int done = 1;
va_start(ap, format);
do
{
len = vsnprintf (mpd->buffer, mpd->buflen - 1, format, ap);
if (len >= (int)mpd->buflen)
if (len < 0 || len >= (int)mpd->buflen
|| !memchr (mpd->buffer, '\0', len + 1))
{
mpd->buflen *= 2;
mpd->buffer = realloc (mpd->buffer, mpd->buflen);
if (mpd->buffer == NULL)
return ENOMEM;
done = 0;
}
else
done = 1;
}
while (len > (int)mpd->buflen);
while (!done);
va_end(ap);
mpd->ptr = mpd->buffer + len;
return 0;
......
......@@ -86,6 +86,7 @@ static int _mime_append_part(mime_t mime, message_t msg, int offset, int len, in
mime_part->lines = lines;
mime_part->offset = offset;
} else {
message_ref(msg);
message_size(msg, &mime_part->len);
message_lines(msg, &mime_part->lines);
if ( mime->nmtp_parts > 1 )
......@@ -372,7 +373,7 @@ static int _mime_set_content_type(mime_t mime)
size_t size;
if ( mime->nmtp_parts > 1 ) {
if ( mime->flags & MIME_ADDED_MULTIPART )
if ( mime->flags & MIME_ADDED_MULTIPART_CT )
return 0;
if ( mime->flags & MIME_MULTIPART_MIXED )
strcpy(content_type, "multipart/mixed; boundary=");
......@@ -386,11 +387,11 @@ static int _mime_set_content_type(mime_t mime)
strcat(content_type, "\"");
strcat(content_type, mime->boundary);
strcat(content_type, "\"");
mime->flags |= MIME_ADDED_MULTIPART;
mime->flags |= MIME_ADDED_MULTIPART_CT;
} else {
if ( (mime->flags & (MIME_ADDED_CONTENT_TYPE|MIME_ADDED_MULTIPART)) == MIME_ADDED_CONTENT_TYPE )
if ( (mime->flags & (MIME_ADDED_CT|MIME_ADDED_MULTIPART_CT)) == MIME_ADDED_CT )
return 0;
mime->flags &= ~MIME_ADDED_MULTIPART;
mime->flags &= ~MIME_ADDED_MULTIPART_CT;
if ( mime->nmtp_parts )
message_get_header(mime->mtp_parts[0]->msg, &hdr);
if ( hdr == NULL || header_get_value(hdr, "Content-Type", NULL, 0, &size) != 0 || size == 0 )
......@@ -398,10 +399,12 @@ static int _mime_set_content_type(mime_t mime)
else
header_get_value(hdr, "Content-Type", content_type, sizeof(content_type), &size);
}
mime->flags |= MIME_ADDED_CONTENT_TYPE;
mime->flags |= MIME_ADDED_CT;
return header_set_value(mime->hdrs, "Content-Type", content_type, 1);
}
#define ADD_CHAR(buf, c, offset, buflen, nbytes) {*(buf)++ = c; (offset)++; (nbytes)++;if (--(buflen) == 0) return 0;}
static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes)
{
body_t body = stream_get_owner(stream);
......@@ -417,6 +420,8 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
if ( off == 0 ) { /* reset message */
mime->cur_offset = 0;
mime->cur_part = 0;
if ( mime->nmtp_parts > 1 )
mime->flags |= MIME_INSERT_BOUNDARY;
}
if ( off != mime->cur_offset )
......@@ -425,39 +430,37 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
if ( nbytes )
*nbytes = 0;
if ( mime->cur_part == mime->nmtp_parts )
return 0;
if ( ( ret = _mime_set_content_type(mime) ) == 0 ) {
do {
len = 0;
if ( mime->nmtp_parts > 1 ) {
if ( ( mime->flags & MIME_INSERT_BOUNDARY || mime->cur_offset == 0 ) ) {
mime->cur_part++;
len = 2;
buf[0] = buf[1] = '-';
buf+=2;
len += strlen(mime->boundary);
strcpy(buf, mime->boundary);
buf+= strlen(mime->boundary);
if ( mime->cur_part == mime->nmtp_parts ) {
len+=2;
buf[0] = buf[1] = '-';
buf+=2;
}
len++;
buf[0] = '\n';
buf++;
mime->flags &= ~MIME_INSERT_BOUNDARY;
buflen =- len;
mime->part_offset = 0;
if ( mime->cur_part == mime->nmtp_parts ) {
if ( nbytes )
*nbytes += len;
mime->cur_offset +=len;
break;
if ( mime->flags & MIME_INSERT_BOUNDARY ) {
if ( ( mime->flags & MIME_ADDING_BOUNDARY ) == 0 ) {
mime->boundary_len = strlen(mime->boundary);
mime->preamble = 2;
if ( mime->cur_part == mime->nmtp_parts )
mime->postamble = 2;
mime->flags |= MIME_ADDING_BOUNDARY;
}
while(mime->preamble) {
mime->preamble--;
ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
}
len = strlen(mime->boundary) - mime->boundary_len;
while(mime->boundary_len) {
mime->boundary_len--;
ADD_CHAR(buf, mime->boundary[len++], mime->cur_offset, buflen, *nbytes);
}
while(mime->postamble) {
mime->postamble--;
ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
}
mime->flags &= ~(MIME_INSERT_BOUNDARY|MIME_ADDING_BOUNDARY);
mime->part_offset = 0;
ADD_CHAR(buf, '\n',mime->cur_offset, buflen, *nbytes);
}
if ( mime->cur_part >= mime->nmtp_parts )
return 0;
message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);
} else {
body_t body;
......@@ -470,8 +473,10 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
if ( nbytes )
*nbytes += len;
mime->cur_offset += len;
if ( ret == 0 && part_nbytes == 0 && mime->nmtp_parts > 1 )
if ( ret == 0 && part_nbytes == 0 && mime->nmtp_parts > 1 ) {
mime->flags |= MIME_INSERT_BOUNDARY;
mime->cur_part++;
}
} while( ret == 0 && part_nbytes == 0 );
}
return ret;
......@@ -494,13 +499,14 @@ static int _mime_body_size (body_t body, size_t *psize)
{
message_t msg = body_get_owner(body);
mime_t mime = message_get_owner(msg);
int i;
int i, ret;
size_t size;
if ( mime->nmtp_parts == 0 )
return EINVAL;
_mime_set_content_type(mime);
if ( (ret = _mime_set_content_type(mime) ) != 0 )
return ret;
for ( i=0;i<mime->nmtp_parts;i++ ) {
message_size(mime->mtp_parts[i]->msg, &size);
*psize+=size;
......@@ -517,13 +523,14 @@ static int _mime_body_lines (body_t body, size_t *plines)
{
message_t msg = body_get_owner(body);
mime_t mime = message_get_owner(msg);
int i;
int i, ret;
size_t lines;
if ( mime->nmtp_parts == 0 )
return EINVAL;
_mime_set_content_type(mime);
if ( (ret = _mime_set_content_type(mime) ) != 0 )
return ret;
for ( i = 0; i < mime->nmtp_parts; i++ ) {
message_lines(mime->mtp_parts[i]->msg, &lines);
plines+=lines;
......@@ -566,7 +573,7 @@ int mime_create(mime_t *pmime, message_t msg, int flags)
}
}
else {
mime->flags |= MIME_NEW_MESSAGE;
mime->flags |= MIME_NEW_MESSAGE | MIME_MULTIPART_MIXED;
}
if ( ret != 0 ) {
if ( mime->content_type )
......@@ -591,13 +598,16 @@ void mime_destroy(mime_t *pmime)
if ( mime->mtp_parts != NULL ) {
for ( i = 0; i < mime->nmtp_parts; i++ ) {
mime_part = mime->mtp_parts[i];
if ( mime_part->msg ) {
if ( mime_part->msg && mime->flags & MIME_NEW_MESSAGE )
message_unref(mime_part->msg);
else
message_destroy(&mime_part->msg, mime_part);
free (mime_part);
}
}
free (mime->mtp_parts);
}
if ( mime->msg && mime->flags & MIME_NEW_MESSAGE )
message_destroy(&mime->msg, mime);
if ( mime->content_type )
free(mime->content_type);
if ( mime->cur_buf )
......@@ -662,9 +672,13 @@ int mime_get_num_parts(mime_t mime, int *nmtp_parts)
int mime_add_part(mime_t mime, message_t msg)
{
int ret;
if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 )
return EINVAL;
return _mime_append_part(mime, msg, 0, 0, 0);
if ( ( ret = _mime_append_part(mime, msg, 0, 0, 0) ) == 0 )
ret = _mime_set_content_type(mime);
return ret;
}
int mime_get_message(mime_t mime, message_t *msg)
......
......@@ -285,7 +285,7 @@ smtp_open (mailer_t mailer, int flags)
/* allocate a working io buffer. */
if (smtp->buffer == NULL)
{
smtp->buflen = 255; /* Initial guess. */
smtp->buflen = 512; /* Initial guess. */
smtp->buffer = malloc (smtp->buflen + 1);
if (smtp->buffer == NULL)
{
......@@ -305,7 +305,7 @@ smtp_open (mailer_t mailer, int flags)
smtp->state = SMTP_OPEN;
case SMTP_OPEN:
MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (%s:%d)\n", smtp->localhost, port);
MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (%s:%d)\n", smtp->mailhost, port);
status = stream_open (mailer->stream, smtp->mailhost, port,
mailer->flags);
CHECK_EAGAIN (smtp, status);
......@@ -565,6 +565,7 @@ smtp_send_message(mailer_t mailer, message_t msg)
CHECK_ERROR (smtp, status);
}
smtp->offset += n;
MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
status = smtp_write (smtp);
CHECK_EAGAIN (smtp, status);
}
......@@ -716,25 +717,36 @@ get_rcpt (message_t msg, address_t *prcpt_to)
}
return EINVAL;
}
static int
/* C99 says that a conforming implementations of snprintf ()
should return the number of char that would have been call
but many GNU/Linux && BSD implementations return -1 on error.
Worse QNX/Neutrino actually does not put the terminal
null char. So let's try to cope. */
static int
smtp_writeline (smtp_t smtp, const char *format, ...)
{
int len;
va_list ap;
int done = 1;
va_start(ap, format);
do
{
len = vsnprintf (smtp->buffer, smtp->buflen - 1, format, ap);
if (len >= (int)smtp->buflen)
if (len < 0 || (len >= (int)smtp->buflen)
|| !memchr (smtp->buffer, '\0', len + 1))
{
smtp->buflen *= 2;
smtp->buffer = realloc (smtp->buffer, smtp->buflen);
if (smtp->buffer == NULL)
return ENOMEM;
done = 0;
}
else
done = 1;
}
while (len > (int)smtp->buflen);
while (!done);
va_end(ap);
smtp->ptr = smtp->buffer + len;
return 0;
......
......@@ -231,7 +231,7 @@ stream_readline (stream_t is, char *buf, size_t count,
*buf = '\0';
if (pnread)
*pnread = n;
*pnread = (n == count) ? n - 1: n;
return 0;
}
......