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) ...@@ -308,7 +308,7 @@ _file_open (stream_t stream, const char *filename, int port, int flags)
308 } 308 }
309 #if BUFSIZ <= 1024 309 #if BUFSIZ <= 1024
310 /* Give us some room to breath, for OS with two small stdio buffers. */ 310 /* Give us some room to breath, for OS with two small stdio buffers. */
311 setvbuf (fs->file, iobuffer, _IOFBF, 8192); 311 setvbuf (fs->file, NULL, _IOFBF, 8192);
312 #endif 312 #endif
313 stream_set_flags (stream, flags |MU_STREAM_NO_CHECK); 313 stream_set_flags (stream, flags |MU_STREAM_NO_CHECK);
314 return 0; 314 return 0;
......
...@@ -51,9 +51,10 @@ extern "C" { ...@@ -51,9 +51,10 @@ extern "C" {
51 #define MIME_PARSER_ACTIVE 0x80000000 51 #define MIME_PARSER_ACTIVE 0x80000000
52 #define MIME_PARSER_HAVE_CR 0x40000000 52 #define MIME_PARSER_HAVE_CR 0x40000000
53 #define MIME_NEW_MESSAGE 0x20000000 53 #define MIME_NEW_MESSAGE 0x20000000
54 #define MIME_ADDED_CONTENT_TYPE 0x10000000 54 #define MIME_ADDED_CT 0x10000000
55 #define MIME_ADDED_MULTIPART 0x08000000 55 #define MIME_ADDED_MULTIPART_CT 0x08000000
56 #define MIME_INSERT_BOUNDARY 0x04000000 56 #define MIME_INSERT_BOUNDARY 0x04000000
57 #define MIME_ADDING_BOUNDARY 0x02000000
57 58
58 struct _mime 59 struct _mime
59 { 60 {
...@@ -70,7 +71,9 @@ struct _mime ...@@ -70,7 +71,9 @@ struct _mime
70 int cur_offset; 71 int cur_offset;
71 int cur_part; 72 int cur_part;
72 int part_offset; 73 int part_offset;
73 74 int boundary_len;
75 int preamble;
76 int postamble;
74 /* parser state */ 77 /* parser state */
75 char *cur_line; 78 char *cur_line;
76 int line_ndx; 79 int line_ndx;
......
...@@ -21,10 +21,13 @@ ...@@ -21,10 +21,13 @@
21 21
22 #include <string.h> 22 #include <string.h>
23 #include <stdlib.h> 23 #include <stdlib.h>
24 #include <paths.h>
25 #include <errno.h> 24 #include <errno.h>
26 #include <stdio.h> 25 #include <stdio.h>
27 26
27 #ifdef HAVE_PATHS_H
28 # include <paths.h>
29 #endif
30
28 #include <mailutils/mailbox.h> 31 #include <mailutils/mailbox.h>
29 32
30 #ifndef _PATH_MAILDIR 33 #ifndef _PATH_MAILDIR
......
...@@ -1551,25 +1551,35 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, ...@@ -1551,25 +1551,35 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset,
1551 return 0; 1551 return 0;
1552 } 1552 }
1553 1553
1554 /* C99 says that a conforming implementations of snprintf ()
1555 should return the number of char that would have been call
1556 but many GNU/Linux && BSD implementations return -1 on error.
1557 Worse QnX/Neutrino actually does not put the terminal
1558 null char. So let's try to cope. */
1554 static int 1559 static int
1555 pop_writeline (pop_data_t mpd, const char *format, ...) 1560 pop_writeline (pop_data_t mpd, const char *format, ...)
1556 { 1561 {
1557 int len; 1562 int len;
1558 va_list ap; 1563 va_list ap;
1564 int done = 1;
1559 1565
1560 va_start(ap, format); 1566 va_start(ap, format);
1561 do 1567 do
1562 { 1568 {
1563 len = vsnprintf (mpd->buffer, mpd->buflen - 1, format, ap); 1569 len = vsnprintf (mpd->buffer, mpd->buflen - 1, format, ap);
1564 if (len >= (int)mpd->buflen) 1570 if (len < 0 || len >= (int)mpd->buflen
1571 || !memchr (mpd->buffer, '\0', len + 1))
1565 { 1572 {
1566 mpd->buflen *= 2; 1573 mpd->buflen *= 2;
1567 mpd->buffer = realloc (mpd->buffer, mpd->buflen); 1574 mpd->buffer = realloc (mpd->buffer, mpd->buflen);
1568 if (mpd->buffer == NULL) 1575 if (mpd->buffer == NULL)
1569 return ENOMEM; 1576 return ENOMEM;
1577 done = 0;
1570 } 1578 }
1579 else
1580 done = 1;
1571 } 1581 }
1572 while (len > (int)mpd->buflen); 1582 while (!done);
1573 va_end(ap); 1583 va_end(ap);
1574 mpd->ptr = mpd->buffer + len; 1584 mpd->ptr = mpd->buffer + len;
1575 return 0; 1585 return 0;
......
...@@ -86,6 +86,7 @@ static int _mime_append_part(mime_t mime, message_t msg, int offset, int len, in ...@@ -86,6 +86,7 @@ static int _mime_append_part(mime_t mime, message_t msg, int offset, int len, in
86 mime_part->lines = lines; 86 mime_part->lines = lines;
87 mime_part->offset = offset; 87 mime_part->offset = offset;
88 } else { 88 } else {
89 message_ref(msg);
89 message_size(msg, &mime_part->len); 90 message_size(msg, &mime_part->len);
90 message_lines(msg, &mime_part->lines); 91 message_lines(msg, &mime_part->lines);
91 if ( mime->nmtp_parts > 1 ) 92 if ( mime->nmtp_parts > 1 )
...@@ -372,7 +373,7 @@ static int _mime_set_content_type(mime_t mime) ...@@ -372,7 +373,7 @@ static int _mime_set_content_type(mime_t mime)
372 size_t size; 373 size_t size;
373 374
374 if ( mime->nmtp_parts > 1 ) { 375 if ( mime->nmtp_parts > 1 ) {
375 if ( mime->flags & MIME_ADDED_MULTIPART ) 376 if ( mime->flags & MIME_ADDED_MULTIPART_CT )
376 return 0; 377 return 0;
377 if ( mime->flags & MIME_MULTIPART_MIXED ) 378 if ( mime->flags & MIME_MULTIPART_MIXED )
378 strcpy(content_type, "multipart/mixed; boundary="); 379 strcpy(content_type, "multipart/mixed; boundary=");
...@@ -386,11 +387,11 @@ static int _mime_set_content_type(mime_t mime) ...@@ -386,11 +387,11 @@ static int _mime_set_content_type(mime_t mime)
386 strcat(content_type, "\""); 387 strcat(content_type, "\"");
387 strcat(content_type, mime->boundary); 388 strcat(content_type, mime->boundary);
388 strcat(content_type, "\""); 389 strcat(content_type, "\"");
389 mime->flags |= MIME_ADDED_MULTIPART; 390 mime->flags |= MIME_ADDED_MULTIPART_CT;
390 } else { 391 } else {
391 if ( (mime->flags & (MIME_ADDED_CONTENT_TYPE|MIME_ADDED_MULTIPART)) == MIME_ADDED_CONTENT_TYPE ) 392 if ( (mime->flags & (MIME_ADDED_CT|MIME_ADDED_MULTIPART_CT)) == MIME_ADDED_CT )
392 return 0; 393 return 0;
393 mime->flags &= ~MIME_ADDED_MULTIPART; 394 mime->flags &= ~MIME_ADDED_MULTIPART_CT;
394 if ( mime->nmtp_parts ) 395 if ( mime->nmtp_parts )
395 message_get_header(mime->mtp_parts[0]->msg, &hdr); 396 message_get_header(mime->mtp_parts[0]->msg, &hdr);
396 if ( hdr == NULL || header_get_value(hdr, "Content-Type", NULL, 0, &size) != 0 || size == 0 ) 397 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) ...@@ -398,10 +399,12 @@ static int _mime_set_content_type(mime_t mime)
398 else 399 else
399 header_get_value(hdr, "Content-Type", content_type, sizeof(content_type), &size); 400 header_get_value(hdr, "Content-Type", content_type, sizeof(content_type), &size);
400 } 401 }
401 mime->flags |= MIME_ADDED_CONTENT_TYPE; 402 mime->flags |= MIME_ADDED_CT;
402 return header_set_value(mime->hdrs, "Content-Type", content_type, 1); 403 return header_set_value(mime->hdrs, "Content-Type", content_type, 1);
403 } 404 }
404 405
406 #define ADD_CHAR(buf, c, offset, buflen, nbytes) {*(buf)++ = c; (offset)++; (nbytes)++;if (--(buflen) == 0) return 0;}
407
405 static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes) 408 static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes)
406 { 409 {
407 body_t body = stream_get_owner(stream); 410 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, ...@@ -417,6 +420,8 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
417 if ( off == 0 ) { /* reset message */ 420 if ( off == 0 ) { /* reset message */
418 mime->cur_offset = 0; 421 mime->cur_offset = 0;
419 mime->cur_part = 0; 422 mime->cur_part = 0;
423 if ( mime->nmtp_parts > 1 )
424 mime->flags |= MIME_INSERT_BOUNDARY;
420 } 425 }
421 426
422 if ( off != mime->cur_offset ) 427 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, ...@@ -425,39 +430,37 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
425 if ( nbytes ) 430 if ( nbytes )
426 *nbytes = 0; 431 *nbytes = 0;
427 432
428 if ( mime->cur_part == mime->nmtp_parts )
429 return 0;
430
431 if ( ( ret = _mime_set_content_type(mime) ) == 0 ) { 433 if ( ( ret = _mime_set_content_type(mime) ) == 0 ) {
432 do { 434 do {
433 len = 0; 435 len = 0;
434 if ( mime->nmtp_parts > 1 ) { 436 if ( mime->nmtp_parts > 1 ) {
435 if ( ( mime->flags & MIME_INSERT_BOUNDARY || mime->cur_offset == 0 ) ) { 437 if ( mime->flags & MIME_INSERT_BOUNDARY ) {
436 mime->cur_part++; 438 if ( ( mime->flags & MIME_ADDING_BOUNDARY ) == 0 ) {
437 len = 2; 439 mime->boundary_len = strlen(mime->boundary);
438 buf[0] = buf[1] = '-'; 440 mime->preamble = 2;
439 buf+=2; 441 if ( mime->cur_part == mime->nmtp_parts )
440 len += strlen(mime->boundary); 442 mime->postamble = 2;
441 strcpy(buf, mime->boundary); 443 mime->flags |= MIME_ADDING_BOUNDARY;
442 buf+= strlen(mime->boundary);
443 if ( mime->cur_part == mime->nmtp_parts ) {
444 len+=2;
445 buf[0] = buf[1] = '-';
446 buf+=2;
447 } 444 }
448 len++; 445 while(mime->preamble) {
449 buf[0] = '\n'; 446 mime->preamble--;
450 buf++; 447 ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
451 mime->flags &= ~MIME_INSERT_BOUNDARY; 448 }
452 buflen =- len; 449 len = strlen(mime->boundary) - mime->boundary_len;
453 mime->part_offset = 0; 450 while(mime->boundary_len) {
454 if ( mime->cur_part == mime->nmtp_parts ) { 451 mime->boundary_len--;
455 if ( nbytes ) 452 ADD_CHAR(buf, mime->boundary[len++], mime->cur_offset, buflen, *nbytes);
456 *nbytes += len;
457 mime->cur_offset +=len;
458 break;
459 } 453 }
454 while(mime->postamble) {
455 mime->postamble--;
456 ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
457 }
458 mime->flags &= ~(MIME_INSERT_BOUNDARY|MIME_ADDING_BOUNDARY);
459 mime->part_offset = 0;
460 ADD_CHAR(buf, '\n',mime->cur_offset, buflen, *nbytes);
460 } 461 }
462 if ( mime->cur_part >= mime->nmtp_parts )
463 return 0;
461 message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream); 464 message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);
462 } else { 465 } else {
463 body_t body; 466 body_t body;
...@@ -470,8 +473,10 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off, ...@@ -470,8 +473,10 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
470 if ( nbytes ) 473 if ( nbytes )
471 *nbytes += len; 474 *nbytes += len;
472 mime->cur_offset += len; 475 mime->cur_offset += len;
473 if ( ret == 0 && part_nbytes == 0 && mime->nmtp_parts > 1 ) 476 if ( ret == 0 && part_nbytes == 0 && mime->nmtp_parts > 1 ) {
474 mime->flags |= MIME_INSERT_BOUNDARY; 477 mime->flags |= MIME_INSERT_BOUNDARY;
478 mime->cur_part++;
479 }
475 } while( ret == 0 && part_nbytes == 0 ); 480 } while( ret == 0 && part_nbytes == 0 );
476 } 481 }
477 return ret; 482 return ret;
...@@ -494,13 +499,14 @@ static int _mime_body_size (body_t body, size_t *psize) ...@@ -494,13 +499,14 @@ static int _mime_body_size (body_t body, size_t *psize)
494 { 499 {
495 message_t msg = body_get_owner(body); 500 message_t msg = body_get_owner(body);
496 mime_t mime = message_get_owner(msg); 501 mime_t mime = message_get_owner(msg);
497 int i; 502 int i, ret;
498 size_t size; 503 size_t size;
499 504
500 if ( mime->nmtp_parts == 0 ) 505 if ( mime->nmtp_parts == 0 )
501 return EINVAL; 506 return EINVAL;
502 507
503 _mime_set_content_type(mime); 508 if ( (ret = _mime_set_content_type(mime) ) != 0 )
509 return ret;
504 for ( i=0;i<mime->nmtp_parts;i++ ) { 510 for ( i=0;i<mime->nmtp_parts;i++ ) {
505 message_size(mime->mtp_parts[i]->msg, &size); 511 message_size(mime->mtp_parts[i]->msg, &size);
506 *psize+=size; 512 *psize+=size;
...@@ -517,13 +523,14 @@ static int _mime_body_lines (body_t body, size_t *plines) ...@@ -517,13 +523,14 @@ static int _mime_body_lines (body_t body, size_t *plines)
517 { 523 {
518 message_t msg = body_get_owner(body); 524 message_t msg = body_get_owner(body);
519 mime_t mime = message_get_owner(msg); 525 mime_t mime = message_get_owner(msg);
520 int i; 526 int i, ret;
521 size_t lines; 527 size_t lines;
522 528
523 if ( mime->nmtp_parts == 0 ) 529 if ( mime->nmtp_parts == 0 )
524 return EINVAL; 530 return EINVAL;
525 531
526 _mime_set_content_type(mime); 532 if ( (ret = _mime_set_content_type(mime) ) != 0 )
533 return ret;
527 for ( i = 0; i < mime->nmtp_parts; i++ ) { 534 for ( i = 0; i < mime->nmtp_parts; i++ ) {
528 message_lines(mime->mtp_parts[i]->msg, &lines); 535 message_lines(mime->mtp_parts[i]->msg, &lines);
529 plines+=lines; 536 plines+=lines;
...@@ -566,7 +573,7 @@ int mime_create(mime_t *pmime, message_t msg, int flags) ...@@ -566,7 +573,7 @@ int mime_create(mime_t *pmime, message_t msg, int flags)
566 } 573 }
567 } 574 }
568 else { 575 else {
569 mime->flags |= MIME_NEW_MESSAGE; 576 mime->flags |= MIME_NEW_MESSAGE | MIME_MULTIPART_MIXED;
570 } 577 }
571 if ( ret != 0 ) { 578 if ( ret != 0 ) {
572 if ( mime->content_type ) 579 if ( mime->content_type )
...@@ -591,13 +598,16 @@ void mime_destroy(mime_t *pmime) ...@@ -591,13 +598,16 @@ void mime_destroy(mime_t *pmime)
591 if ( mime->mtp_parts != NULL ) { 598 if ( mime->mtp_parts != NULL ) {
592 for ( i = 0; i < mime->nmtp_parts; i++ ) { 599 for ( i = 0; i < mime->nmtp_parts; i++ ) {
593 mime_part = mime->mtp_parts[i]; 600 mime_part = mime->mtp_parts[i];
594 if ( mime_part->msg ) { 601 if ( mime_part->msg && mime->flags & MIME_NEW_MESSAGE )
602 message_unref(mime_part->msg);
603 else
595 message_destroy(&mime_part->msg, mime_part); 604 message_destroy(&mime_part->msg, mime_part);
596 free (mime_part); 605 free (mime_part);
597 }
598 } 606 }
599 free (mime->mtp_parts); 607 free (mime->mtp_parts);
600 } 608 }
609 if ( mime->msg && mime->flags & MIME_NEW_MESSAGE )
610 message_destroy(&mime->msg, mime);
601 if ( mime->content_type ) 611 if ( mime->content_type )
602 free(mime->content_type); 612 free(mime->content_type);
603 if ( mime->cur_buf ) 613 if ( mime->cur_buf )
...@@ -662,9 +672,13 @@ int mime_get_num_parts(mime_t mime, int *nmtp_parts) ...@@ -662,9 +672,13 @@ int mime_get_num_parts(mime_t mime, int *nmtp_parts)
662 672
663 int mime_add_part(mime_t mime, message_t msg) 673 int mime_add_part(mime_t mime, message_t msg)
664 { 674 {
675 int ret;
676
665 if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 ) 677 if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 )
666 return EINVAL; 678 return EINVAL;
667 return _mime_append_part(mime, msg, 0, 0, 0); 679 if ( ( ret = _mime_append_part(mime, msg, 0, 0, 0) ) == 0 )
680 ret = _mime_set_content_type(mime);
681 return ret;
668 } 682 }
669 683
670 int mime_get_message(mime_t mime, message_t *msg) 684 int mime_get_message(mime_t mime, message_t *msg)
......
...@@ -285,7 +285,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -285,7 +285,7 @@ smtp_open (mailer_t mailer, int flags)
285 /* allocate a working io buffer. */ 285 /* allocate a working io buffer. */
286 if (smtp->buffer == NULL) 286 if (smtp->buffer == NULL)
287 { 287 {
288 smtp->buflen = 255; /* Initial guess. */ 288 smtp->buflen = 512; /* Initial guess. */
289 smtp->buffer = malloc (smtp->buflen + 1); 289 smtp->buffer = malloc (smtp->buflen + 1);
290 if (smtp->buffer == NULL) 290 if (smtp->buffer == NULL)
291 { 291 {
...@@ -305,7 +305,7 @@ smtp_open (mailer_t mailer, int flags) ...@@ -305,7 +305,7 @@ smtp_open (mailer_t mailer, int flags)
305 smtp->state = SMTP_OPEN; 305 smtp->state = SMTP_OPEN;
306 306
307 case SMTP_OPEN: 307 case SMTP_OPEN:
308 MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (%s:%d)\n", smtp->localhost, port); 308 MAILER_DEBUG2 (mailer, MU_DEBUG_PROT, "smtp_open (%s:%d)\n", smtp->mailhost, port);
309 status = stream_open (mailer->stream, smtp->mailhost, port, 309 status = stream_open (mailer->stream, smtp->mailhost, port,
310 mailer->flags); 310 mailer->flags);
311 CHECK_EAGAIN (smtp, status); 311 CHECK_EAGAIN (smtp, status);
...@@ -565,7 +565,8 @@ smtp_send_message(mailer_t mailer, message_t msg) ...@@ -565,7 +565,8 @@ smtp_send_message(mailer_t mailer, message_t msg)
565 CHECK_ERROR (smtp, status); 565 CHECK_ERROR (smtp, status);
566 } 566 }
567 smtp->offset += n; 567 smtp->offset += n;
568 status = smtp_write (smtp); 568 MAILER_DEBUG0 (mailer, MU_DEBUG_PROT, smtp->buffer);
569 status = smtp_write (smtp);
569 CHECK_EAGAIN (smtp, status); 570 CHECK_EAGAIN (smtp, status);
570 } 571 }
571 smtp->offset = 0; 572 smtp->offset = 0;
...@@ -716,25 +717,36 @@ get_rcpt (message_t msg, address_t *prcpt_to) ...@@ -716,25 +717,36 @@ get_rcpt (message_t msg, address_t *prcpt_to)
716 } 717 }
717 return EINVAL; 718 return EINVAL;
718 } 719 }
719 static int 720
721 /* C99 says that a conforming implementations of snprintf ()
722 should return the number of char that would have been call
723 but many GNU/Linux && BSD implementations return -1 on error.
724 Worse QNX/Neutrino actually does not put the terminal
725 null char. So let's try to cope. */
726 static int
720 smtp_writeline (smtp_t smtp, const char *format, ...) 727 smtp_writeline (smtp_t smtp, const char *format, ...)
721 { 728 {
722 int len; 729 int len;
723 va_list ap; 730 va_list ap;
731 int done = 1;
724 732
725 va_start(ap, format); 733 va_start(ap, format);
726 do 734 do
727 { 735 {
728 len = vsnprintf (smtp->buffer, smtp->buflen - 1, format, ap); 736 len = vsnprintf (smtp->buffer, smtp->buflen - 1, format, ap);
729 if (len >= (int)smtp->buflen) 737 if (len < 0 || (len >= (int)smtp->buflen)
738 || !memchr (smtp->buffer, '\0', len + 1))
730 { 739 {
731 smtp->buflen *= 2; 740 smtp->buflen *= 2;
732 smtp->buffer = realloc (smtp->buffer, smtp->buflen); 741 smtp->buffer = realloc (smtp->buffer, smtp->buflen);
733 if (smtp->buffer == NULL) 742 if (smtp->buffer == NULL)
734 return ENOMEM; 743 return ENOMEM;
744 done = 0;
735 } 745 }
746 else
747 done = 1;
736 } 748 }
737 while (len > (int)smtp->buflen); 749 while (!done);
738 va_end(ap); 750 va_end(ap);
739 smtp->ptr = smtp->buffer + len; 751 smtp->ptr = smtp->buffer + len;
740 return 0; 752 return 0;
......
...@@ -231,7 +231,7 @@ stream_readline (stream_t is, char *buf, size_t count, ...@@ -231,7 +231,7 @@ stream_readline (stream_t is, char *buf, size_t count,
231 231
232 *buf = '\0'; 232 *buf = '\0';
233 if (pnread) 233 if (pnread)
234 *pnread = n; 234 *pnread = (n == count) ? n - 1: n;
235 235
236 return 0; 236 return 0;
237 } 237 }
......