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>
42
+ #include <stdio.h>
39
43
#include <syslog.h>
40
44
#include <unistd.h>
41
45
@@ -341,18 +345,54 @@ parse_addrs(struct parse_state *ps, char *s, struct queue *queue)
341
345
goto again ;
342
346
}
343
347
348
+ static int
349
+ writeline (struct queue * queue , const char * line , ssize_t linelen )
350
+ {
351
+ const char * walk ;
352
+
353
+ while (linelen > 0 ) {
354
+ /* if the line is too long, split on the last space of the line */
355
+ if (linelen > 1000 ) {
356
+ walk = line + 1000 ;
357
+ while (!isspace (* walk )) {
358
+ /*
359
+ * if there is no spaces in the line we can
360
+ * consider it as junk
361
+ */
362
+ if (walk == line )
363
+ errlogx (EX_DATAERR , "bad mail input format:"
364
+ " from %s (uid %d) (envelope-from %s)" ,
365
+ username , useruid , queue -> sender );
366
+ walk -- ;
367
+ }
368
+ } else {
369
+ walk = line + linelen ;
370
+ }
371
+ if (fwrite (line , walk - line , 1 , queue -> mailf ) != 1 )
372
+ return (-1 );
373
+ if (linelen <= 1000 )
374
+ break ;
375
+ if (fwrite ("\n" , 1 , 1 , queue -> mailf ) != 1 )
376
+ return (-1 );
377
+ line = walk + 1 ;
378
+ linelen = strlen (line );
379
+ }
380
+ return (0 );
381
+ }
382
+
344
383
int
345
384
readmail (struct queue * queue , int nodot , int recp_from_header )
346
385
{
347
386
struct parse_state parse_state ;
348
- char line [1000 ]; /* by RFC2822 */
349
- size_t linelen ;
387
+ char * line = NULL ;
388
+ ssize_t linelen ;
389
+ size_t linecap = 0 ;
390
+ char newline [1000 ];
350
391
size_t error ;
351
392
int had_headers = 0 ;
352
393
int had_from = 0 ;
353
394
int had_messagid = 0 ;
354
395
int had_date = 0 ;
355
- int had_last_line = 0 ;
356
396
int nocopy = 0 ;
357
397
358
398
parse_state .state = NONE ;
@@ -372,24 +412,15 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
372
412
return (-1 );
373
413
374
414
while (!feof (stdin )) {
375
- if (fgets (line , sizeof (line ) - 1 , stdin ) == NULL )
415
+ newline [0 ] = '\0' ;
416
+ if ((linelen = getline (& line , & linecap , stdin )) <= 0 )
376
417
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
418
if (!had_headers ) {
419
+ if (linelen > 1000 )
420
+ errlogx (EX_DATAERR , "bad mail input format:"
421
+ " from %s (uid %d) (envelope-from %s)" ,
422
+ username , useruid , queue -> sender );
423
+
393
424
/*
394
425
* Unless this is a continuation, switch of
395
426
* the Bcc: nocopy flag.
@@ -425,36 +456,44 @@ readmail(struct queue *queue, int nodot, int recp_from_header)
425
456
}
426
457
}
427
458
428
- if (strcmp ( line , "\n" ) == 0 && !had_headers ) {
459
+ if (line [ 0 ] == '\n' && !had_headers ) {
429
460
had_headers = 1 ;
430
461
while (!had_date || !had_messagid || !had_from ) {
431
462
if (!had_date ) {
432
463
had_date = 1 ;
433
- snprintf (line , sizeof (line ), "Date: %s\n" , rfc822date ());
464
+ snprintf (newline , sizeof (newline ), "Date: %s\n" , rfc822date ());
434
465
} else if (!had_messagid ) {
435
466
/* XXX msgid, assign earlier and log? */
436
467
had_messagid = 1 ;
437
- snprintf (line , sizeof (line ), "Message-Id: <%" PRIxMAX ".%s.%" PRIxMAX "@%s>\n" ,
468
+ snprintf (newline , sizeof (newline ), "Message-Id: <%" PRIxMAX ".%s.%" PRIxMAX "@%s>\n" ,
438
469
(uintmax_t )time (NULL ),
439
470
queue -> id ,
440
471
(uintmax_t )random (),
441
472
hostname ());
442
473
} else if (!had_from ) {
443
474
had_from = 1 ;
444
- snprintf (line , sizeof (line ), "From: <%s>\n" , queue -> sender );
475
+ snprintf (newline , sizeof (newline ), "From: <%s>\n" , queue -> sender );
445
476
}
446
- if (fwrite (line , strlen (line ), 1 , queue -> mailf ) != 1 )
447
- return ( -1 ) ;
477
+ if (fwrite (newline , strlen (newline ), 1 , queue -> mailf ) != 1 )
478
+ goto fail ;
448
479
}
449
- strcpy ( line , "\n" );
480
+ strlcpy ( newline , "\n" , sizeof ( newline ) );
450
481
}
451
482
if (!nodot && linelen == 2 && line [0 ] == '.' )
452
483
break ;
453
484
if (!nocopy ) {
454
- if (fwrite (line , strlen (line ), 1 , queue -> mailf ) != 1 )
455
- return (-1 );
485
+ if (newline [0 ] != '\0' ) {
486
+ if (fwrite (newline , strlen (newline ), 1 , queue -> mailf ) != 1 )
487
+ goto fail ;
488
+ } else {
489
+ if (writeline (queue , line , linelen ) != 0 )
490
+ goto fail ;
491
+ }
456
492
}
457
493
}
458
494
459
495
return (0 );
496
+ fail :
497
+ free (line );
498
+ return (-1 );
460
499
}
0 commit comments