33
33
* SUCH DAMAGE.
34
34
*/
35
35
36
+ #include "dfcompat.h"
37
+
38
+ #include <ctype.h>
36
39
#include <errno.h>
37
40
#include <inttypes.h>
38
41
#include <signal.h>
@@ -341,19 +344,43 @@ parse_addrs(struct parse_state *ps, char *s, struct queue *queue)
341
344
goto again ;
342
345
}
343
346
347
+ static int
348
+ writeline (struct queue * queue , const char * line , ssize_t linelen )
349
+ {
350
+ ssize_t len ;
351
+
352
+ while (linelen > 0 ) {
353
+ len = linelen ;
354
+ if (linelen > 1000 ) {
355
+ len = 990 ;
356
+ }
357
+ if (fwrite (line , len , 1 , queue -> mailf ) != 1 )
358
+ return (-1 );
359
+ if (linelen <= 1000 )
360
+ break ;
361
+ if (fwrite ("\n" , 1 , 1 , queue -> mailf ) != 1 )
362
+ return (-1 );
363
+ line += 990 ;
364
+ linelen = strlen (line );
365
+ }
366
+ return (0 );
367
+ }
368
+
344
369
int
345
370
readmail (struct queue * queue , int nodot , int recp_from_header )
346
371
{
347
372
struct parse_state parse_state ;
348
- char line [1000 ]; /* by RFC2822 */
349
- size_t linelen ;
373
+ char * line = NULL ;
374
+ ssize_t linelen ;
375
+ size_t linecap = 0 ;
376
+ char newline [1000 ];
350
377
size_t error ;
351
378
int had_headers = 0 ;
352
379
int had_from = 0 ;
353
380
int had_messagid = 0 ;
354
381
int had_date = 0 ;
355
- int had_last_line = 0 ;
356
382
int nocopy = 0 ;
383
+ int ret = -1 ;
357
384
358
385
parse_state .state = NONE ;
359
386
@@ -372,24 +399,15 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
372
399
return (-1 );
373
400
374
401
while (!feof (stdin )) {
375
- if (fgets (line , sizeof (line ) - 1 , stdin ) == NULL )
402
+ newline [0 ] = '\0' ;
403
+ if ((linelen = getline (& line , & linecap , stdin )) <= 0 )
376
404
break ;
377
- if (had_last_line )
378
- errlogx (EX_DATAERR , "bad mail input format:"
379
- " from %s (uid %d) (envelope-from %s)" ,
380
- username , useruid , queue -> sender );
381
- linelen = strlen (line );
382
- if (linelen == 0 || line [linelen - 1 ] != '\n' ) {
383
- /*
384
- * This line did not end with a newline character.
385
- * If we fix it, it better be the last line of
386
- * the file.
387
- */
388
- line [linelen ] = '\n' ;
389
- line [linelen + 1 ] = 0 ;
390
- had_last_line = 1 ;
391
- }
392
405
if (!had_headers ) {
406
+ if (linelen > 1000 )
407
+ errlogx (EX_DATAERR , "bad mail input format:"
408
+ " from %s (uid %d) (envelope-from %s)" ,
409
+ username , useruid , queue -> sender );
410
+
393
411
/*
394
412
* Unless this is a continuation, switch of
395
413
* the Bcc: nocopy flag.
@@ -430,31 +448,39 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
430
448
while (!had_date || !had_messagid || !had_from ) {
431
449
if (!had_date ) {
432
450
had_date = 1 ;
433
- snprintf (line , sizeof (line ), "Date: %s\n" , rfc822date ());
451
+ snprintf (newline , sizeof (newline ), "Date: %s\n" , rfc822date ());
434
452
} else if (!had_messagid ) {
435
453
/* XXX msgid, assign earlier and log? */
436
454
had_messagid = 1 ;
437
- snprintf (line , sizeof (line ), "Message-Id: <%" PRIxMAX ".%s.%" PRIxMAX "@%s>\n" ,
455
+ snprintf (newline , sizeof (newline ), "Message-Id: <%" PRIxMAX ".%s.%" PRIxMAX "@%s>\n" ,
438
456
(uintmax_t )time (NULL ),
439
457
queue -> id ,
440
458
(uintmax_t )random (),
441
459
hostname ());
442
460
} else if (!had_from ) {
443
461
had_from = 1 ;
444
- snprintf (line , sizeof (line ), "From: <%s>\n" , queue -> sender );
462
+ snprintf (newline , sizeof (newline ), "From: <%s>\n" , queue -> sender );
445
463
}
446
- if (fwrite (line , strlen (line ), 1 , queue -> mailf ) != 1 )
447
- return ( -1 ) ;
464
+ if (fwrite (newline , strlen (newline ), 1 , queue -> mailf ) != 1 )
465
+ goto fail ;
448
466
}
449
- strcpy ( line , "\n" );
467
+ strlcpy ( newline , "\n" , sizeof ( newline ) );
450
468
}
451
469
if (!nodot && linelen == 2 && line [0 ] == '.' )
452
470
break ;
453
471
if (!nocopy ) {
454
- if (fwrite (line , strlen (line ), 1 , queue -> mailf ) != 1 )
455
- return (-1 );
472
+ if (newline [0 ]) {
473
+ if (fwrite (newline , strlen (newline ), 1 , queue -> mailf ) != 1 )
474
+ goto fail ;
475
+ } else {
476
+ if (writeline (queue , line , linelen ) != 0 )
477
+ goto fail ;
478
+ }
456
479
}
457
480
}
458
481
459
- return (0 );
482
+ ret = 0
483
+ fail :
484
+ free (line );
485
+ return (ret );
460
486
}
0 commit comments