(make_tmp): Create a message instead
of returning file pointer. (argp_capa): Added "mailer" capability. (sieve_test): Second argument. (mda,deliver): Take message_t as first argument, instead of FILE*.
Showing
1 changed file
with
124 additions
and
75 deletions
... | @@ -35,8 +35,8 @@ mu_debug_t mudebug; | ... | @@ -35,8 +35,8 @@ mu_debug_t mudebug; |
35 | #define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE) | 35 | #define EX_QUOTA() (ex_quota_tempfail ? EX_TEMPFAIL : EX_UNAVAILABLE) |
36 | 36 | ||
37 | void close_fds (); | 37 | void close_fds (); |
38 | FILE *make_tmp (const char *from, char **tempfile); | 38 | int make_tmp __P((const char *from, message_t *msg, char **tempfile)); |
39 | void deliver (FILE *fp, char *name); | 39 | void deliver (message_t msg, char *name); |
40 | void guess_retval (int ec); | 40 | void guess_retval (int ec); |
41 | void mailer_err (char *fmt, ...); | 41 | void mailer_err (char *fmt, ...); |
42 | void notify_biff (mailbox_t mbox, char *name, size_t size); | 42 | void notify_biff (mailbox_t mbox, char *name, size_t size); |
... | @@ -99,15 +99,15 @@ static const char *argp_capa[] = { | ... | @@ -99,15 +99,15 @@ static const char *argp_capa[] = { |
99 | "auth", | 99 | "auth", |
100 | "common", | 100 | "common", |
101 | "license", | 101 | "license", |
102 | "mailbox", | ||
103 | "logging", | 102 | "logging", |
103 | "mailbox", | ||
104 | "mailer", | ||
104 | NULL | 105 | NULL |
105 | }; | 106 | }; |
106 | 107 | ||
107 | char *from = NULL; | 108 | char *from = NULL; |
108 | char *progfile_pattern = NULL; | 109 | char *progfile_pattern = NULL; |
109 | char *sieve_pattern = NULL; | 110 | char *sieve_pattern = NULL; |
110 | message_t sieve_msg = NULL; | ||
111 | 111 | ||
112 | #define D_DEFAULT "9s" | 112 | #define D_DEFAULT "9s" |
113 | 113 | ||
... | @@ -264,8 +264,8 @@ _sieve_parse_error (void *user_name, const char *filename, int lineno, | ... | @@ -264,8 +264,8 @@ _sieve_parse_error (void *user_name, const char *filename, int lineno, |
264 | int | 264 | int |
265 | main (int argc, char *argv[]) | 265 | main (int argc, char *argv[]) |
266 | { | 266 | { |
267 | FILE *fp; | ||
268 | char *tempfile = NULL; | 267 | char *tempfile = NULL; |
268 | message_t message = NULL; | ||
269 | int arg_index; | 269 | int arg_index; |
270 | 270 | ||
271 | /* Preparative work: close inherited fds, force a reasonable umask | 271 | /* Preparative work: close inherited fds, force a reasonable umask |
... | @@ -324,35 +324,8 @@ main (int argc, char *argv[]) | ... | @@ -324,35 +324,8 @@ main (int argc, char *argv[]) |
324 | list_append (bookie, smtp_record); | 324 | list_append (bookie, smtp_record); |
325 | } | 325 | } |
326 | 326 | ||
327 | fp = make_tmp (from, &tempfile); | 327 | if (make_tmp (from, &message, &tempfile)) |
328 | if (sieve_pattern) | 328 | exit (exit_code); |
329 | { | ||
330 | stream_t stream; | ||
331 | int status; | ||
332 | |||
333 | fflush (fp); | ||
334 | file_stream_create (&stream, tempfile, MU_STREAM_RDWR); | ||
335 | if ((status = stream_open (stream))) | ||
336 | { | ||
337 | mu_error ("Opening temporary file failed: %s\n", | ||
338 | mu_errstring (status)); | ||
339 | return EX_TEMPFAIL; | ||
340 | } | ||
341 | |||
342 | if ((status = message_create (&sieve_msg, NULL))) | ||
343 | { | ||
344 | mu_error ("Can't create temporary message: %s\n", | ||
345 | mu_errstring (status)); | ||
346 | return EX_TEMPFAIL; | ||
347 | } | ||
348 | |||
349 | if ((status = message_set_stream (sieve_msg, stream, NULL))) | ||
350 | { | ||
351 | mu_error ("Can't assign stream to temporary message: %s\n", | ||
352 | mu_errstring (status)); | ||
353 | return EX_TEMPFAIL; | ||
354 | } | ||
355 | } | ||
356 | 329 | ||
357 | if (multiple_delivery) | 330 | if (multiple_delivery) |
358 | multiple_delivery = argc > 1; | 331 | multiple_delivery = argc > 1; |
... | @@ -363,7 +336,7 @@ main (int argc, char *argv[]) | ... | @@ -363,7 +336,7 @@ main (int argc, char *argv[]) |
363 | struct mda_data mda_data; | 336 | struct mda_data mda_data; |
364 | 337 | ||
365 | memset (&mda_data, 0, sizeof mda_data); | 338 | memset (&mda_data, 0, sizeof mda_data); |
366 | mda_data.fp = fp; | 339 | mda_data.msg = message; |
367 | mda_data.argv = argv; | 340 | mda_data.argv = argv; |
368 | mda_data.progfile_pattern = progfile_pattern; | 341 | mda_data.progfile_pattern = progfile_pattern; |
369 | mda_data.tempfile = tempfile; | 342 | mda_data.tempfile = tempfile; |
... | @@ -373,12 +346,12 @@ main (int argc, char *argv[]) | ... | @@ -373,12 +346,12 @@ main (int argc, char *argv[]) |
373 | 346 | ||
374 | unlink (tempfile); | 347 | unlink (tempfile); |
375 | for (; *argv; argv++) | 348 | for (; *argv; argv++) |
376 | mda (fp, *argv); | 349 | mda (message, *argv); |
377 | return exit_code; | 350 | return exit_code; |
378 | } | 351 | } |
379 | 352 | ||
380 | int | 353 | int |
381 | sieve_test (struct mu_auth_data *auth) | 354 | sieve_test (struct mu_auth_data *auth, message_t msg) |
382 | { | 355 | { |
383 | int rc = 1; | 356 | int rc = 1; |
384 | char *progfile; | 357 | char *progfile; |
... | @@ -414,13 +387,13 @@ sieve_test (struct mu_auth_data *auth) | ... | @@ -414,13 +387,13 @@ sieve_test (struct mu_auth_data *auth) |
414 | { | 387 | { |
415 | attribute_t attr; | 388 | attribute_t attr; |
416 | 389 | ||
417 | message_get_attribute (sieve_msg, &attr); | 390 | message_get_attribute (msg, &attr); |
418 | attribute_unset_deleted (attr); | 391 | attribute_unset_deleted (attr); |
419 | if (switch_user_id (auth, 1) == 0) | 392 | if (switch_user_id (auth, 1) == 0) |
420 | { | 393 | { |
421 | chdir (auth->dir); | 394 | chdir (auth->dir); |
422 | 395 | ||
423 | rc = sieve_message (mach, sieve_msg); | 396 | rc = sieve_message (mach, msg); |
424 | if (rc == 0) | 397 | if (rc == 0) |
425 | rc = attribute_is_deleted (attr) == 0; | 398 | rc = attribute_is_deleted (attr) == 0; |
426 | 399 | ||
... | @@ -436,9 +409,9 @@ sieve_test (struct mu_auth_data *auth) | ... | @@ -436,9 +409,9 @@ sieve_test (struct mu_auth_data *auth) |
436 | } | 409 | } |
437 | 410 | ||
438 | int | 411 | int |
439 | mda (FILE *fp, char *username) | 412 | mda (message_t msg, char *username) |
440 | { | 413 | { |
441 | deliver (fp, username); | 414 | deliver (msg, username); |
442 | 415 | ||
443 | if (multiple_delivery) | 416 | if (multiple_delivery) |
444 | exit_code = EX_OK; | 417 | exit_code = EX_OK; |
... | @@ -491,21 +464,38 @@ switch_user_id (struct mu_auth_data *auth, int user) | ... | @@ -491,21 +464,38 @@ switch_user_id (struct mu_auth_data *auth, int user) |
491 | return rc; | 464 | return rc; |
492 | } | 465 | } |
493 | 466 | ||
494 | FILE * | 467 | static int |
495 | make_tmp (const char *from, char **tempfile) | 468 | tmp_write (stream_t stream, off_t *poffset, char *buf, size_t len) |
496 | { | 469 | { |
497 | time_t t; | 470 | size_t n = 0; |
498 | FILE *fp; | 471 | int status = stream_write (stream, buf, len, *poffset, &n); |
472 | if (status == 0 && n != len) | ||
473 | status = EIO; | ||
474 | *poffset += n; | ||
475 | return status; | ||
476 | } | ||
477 | |||
478 | int | ||
479 | make_tmp (const char *from, message_t *msg, char **tempfile) | ||
480 | { | ||
481 | stream_t stream; | ||
499 | char *buf = NULL; | 482 | char *buf = NULL; |
500 | size_t n = 0; | 483 | size_t n = 0; |
501 | int line; | 484 | off_t offset = 0; |
485 | size_t line; | ||
486 | int status; | ||
487 | static char *newline = "\n"; | ||
502 | 488 | ||
503 | *tempfile = mu_tempname (NULL); | 489 | *tempfile = mu_tempname (NULL); |
504 | fp = fopen (*tempfile, "w+"); | 490 | if ((status = file_stream_create (&stream, *tempfile, MU_STREAM_RDWR))) |
491 | { | ||
492 | mailer_err ("unable to open temporary file: %s", mu_errstring (status)); | ||
493 | exit (exit_code); | ||
494 | } | ||
505 | 495 | ||
506 | if (fp == NULL) | 496 | if ((status = stream_open (stream))) |
507 | { | 497 | { |
508 | mailer_err ("unable to open temporary file"); | 498 | mailer_err ("unable to open temporary file: %s", mu_errstring (status)); |
509 | exit (exit_code); | 499 | exit (exit_code); |
510 | } | 500 | } |
511 | 501 | ||
... | @@ -526,8 +516,13 @@ make_tmp (const char *from, char **tempfile) | ... | @@ -526,8 +516,13 @@ make_tmp (const char *from, char **tempfile) |
526 | } | 516 | } |
527 | if (from) | 517 | if (from) |
528 | { | 518 | { |
519 | time_t t; | ||
520 | char *ptr; | ||
521 | |||
529 | time (&t); | 522 | time (&t); |
530 | fprintf (fp, "From %s %s", from, ctime (&t)); | 523 | asprintf (&ptr, "From %s %s", from, ctime (&t)); |
524 | status = tmp_write (stream, &offset, ptr, strlen (ptr)); | ||
525 | free (ptr); | ||
531 | } | 526 | } |
532 | else | 527 | else |
533 | { | 528 | { |
... | @@ -539,35 +534,61 @@ make_tmp (const char *from, char **tempfile) | ... | @@ -539,35 +534,61 @@ make_tmp (const char *from, char **tempfile) |
539 | } | 534 | } |
540 | } | 535 | } |
541 | else if (!memcmp (buf, "From ", 5)) | 536 | else if (!memcmp (buf, "From ", 5)) |
542 | fputc ('>', fp); | ||
543 | if (fputs (buf, fp) == EOF) | ||
544 | { | 537 | { |
545 | mailer_err ("temporary file write error"); | 538 | static char *escape = ">"; |
546 | fclose (fp); | 539 | status = tmp_write (stream, &offset, escape, 1); |
547 | return NULL; | 540 | } |
541 | |||
542 | if (!status) | ||
543 | status = tmp_write (stream, &offset, buf, strlen (buf)); | ||
544 | |||
545 | if (status) | ||
546 | { | ||
547 | mailer_err ("temporary file write error: %s", mu_errstring (status)); | ||
548 | stream_destroy (&stream, stream_get_owner (stream)); | ||
549 | return status; | ||
548 | } | 550 | } |
549 | } | 551 | } |
550 | 552 | ||
551 | if (buf && strchr (buf, '\n') == NULL) | 553 | if (buf && strchr (buf, '\n') == NULL) |
552 | putc ('\n', fp); | 554 | status = tmp_write (stream, &offset, newline, 1); |
553 | 555 | ||
554 | putc ('\n', fp); | 556 | status = tmp_write (stream, &offset, newline, 1); |
555 | free (buf); | 557 | free (buf); |
556 | 558 | ||
557 | return fp; | 559 | if (status) |
560 | { | ||
561 | errno = status; | ||
562 | mailer_err ("temporary file write error: %s", mu_errstring (status)); | ||
563 | stream_destroy (&stream, stream_get_owner (stream)); | ||
564 | return status; | ||
565 | } | ||
566 | |||
567 | if ((status = message_create (msg, NULL)) == 0) | ||
568 | status = message_set_stream (*msg, stream, NULL); | ||
569 | |||
570 | if (status) | ||
571 | { | ||
572 | errno = status; | ||
573 | mailer_err ("temporary message creation error: %s", | ||
574 | mu_errstring (status)); | ||
575 | stream_destroy (&stream, stream_get_owner (stream)); | ||
576 | return status; | ||
577 | } | ||
578 | |||
579 | return status; | ||
558 | } | 580 | } |
559 | 581 | ||
560 | void | 582 | void |
561 | deliver (FILE *fp, char *name) | 583 | deliver (message_t msg, char *name) |
562 | { | 584 | { |
563 | mailbox_t mbox; | 585 | mailbox_t mbox; |
564 | char *path; | 586 | char *path; |
565 | url_t url = NULL; | 587 | url_t url = NULL; |
566 | size_t n = 0; | ||
567 | locker_t lock; | 588 | locker_t lock; |
568 | struct mu_auth_data *auth; | 589 | struct mu_auth_data *auth; |
569 | int status; | 590 | int status; |
570 | stream_t stream; | 591 | stream_t istream, ostream; |
571 | size_t size; | 592 | size_t size; |
572 | int failed = 0; | 593 | int failed = 0; |
573 | #if defined(USE_DBM) | 594 | #if defined(USE_DBM) |
... | @@ -582,13 +603,20 @@ deliver (FILE *fp, char *name) | ... | @@ -582,13 +603,20 @@ deliver (FILE *fp, char *name) |
582 | return; | 603 | return; |
583 | } | 604 | } |
584 | 605 | ||
585 | if (!sieve_test (auth)) | 606 | if (!sieve_test (auth, msg)) |
586 | { | 607 | { |
587 | exit_code = EX_OK; | 608 | exit_code = EX_OK; |
588 | mu_auth_data_free (auth); | 609 | mu_auth_data_free (auth); |
589 | return; | 610 | return; |
590 | } | 611 | } |
591 | 612 | ||
613 | if ((status = message_get_stream (msg, &istream)) != 0) | ||
614 | { | ||
615 | mailer_err ("can't get input message stream: %s", mu_errstring (status)); | ||
616 | mu_auth_data_free (auth); | ||
617 | return; | ||
618 | } | ||
619 | |||
592 | if ((status = mailbox_create (&mbox, auth->mailbox)) != 0) | 620 | if ((status = mailbox_create (&mbox, auth->mailbox)) != 0) |
593 | { | 621 | { |
594 | mailer_err ("can't open mailbox %s: %s", | 622 | mailer_err ("can't open mailbox %s: %s", |
... | @@ -629,7 +657,7 @@ deliver (FILE *fp, char *name) | ... | @@ -629,7 +657,7 @@ deliver (FILE *fp, char *name) |
629 | return; | 657 | return; |
630 | } | 658 | } |
631 | 659 | ||
632 | if ((status = mailbox_get_stream (mbox, &stream))) | 660 | if ((status = mailbox_get_stream (mbox, &ostream))) |
633 | { | 661 | { |
634 | mailer_err ("can't get stream for mailbox %s: %s", | 662 | mailer_err ("can't get stream for mailbox %s: %s", |
635 | path, mu_errstring (status)); | 663 | path, mu_errstring (status)); |
... | @@ -637,7 +665,7 @@ deliver (FILE *fp, char *name) | ... | @@ -637,7 +665,7 @@ deliver (FILE *fp, char *name) |
637 | return; | 665 | return; |
638 | } | 666 | } |
639 | 667 | ||
640 | if ((status = stream_size (stream, (off_t *) &size))) | 668 | if ((status = stream_size (ostream, (off_t *) &size))) |
641 | { | 669 | { |
642 | mailer_err ("can't get stream size (mailbox %s): %s", | 670 | mailer_err ("can't get stream size (mailbox %s): %s", |
643 | path, mu_errstring (status)); | 671 | path, mu_errstring (status)); |
... | @@ -656,9 +684,10 @@ deliver (FILE *fp, char *name) | ... | @@ -656,9 +684,10 @@ deliver (FILE *fp, char *name) |
656 | case MQUOTA_UNLIMITED: | 684 | case MQUOTA_UNLIMITED: |
657 | break; | 685 | break; |
658 | default: | 686 | default: |
659 | if (fstat (fileno (fp), &sb)) | 687 | if ((status = stream_size (istream, (off_t *) &isize))) |
660 | { | 688 | { |
661 | mailer_err ("cannot stat tempfile: %s", strerror (errno)); | 689 | mailer_err ("can't get stream size (input message): %s", |
690 | path, mu_errstring (status)); | ||
662 | exit_code = EX_UNAVAILABLE; | 691 | exit_code = EX_UNAVAILABLE; |
663 | failed++; | 692 | failed++; |
664 | } | 693 | } |
... | @@ -675,26 +704,46 @@ deliver (FILE *fp, char *name) | ... | @@ -675,26 +704,46 @@ deliver (FILE *fp, char *name) |
675 | 704 | ||
676 | if (!failed && switch_user_id (auth, 1) == 0) | 705 | if (!failed && switch_user_id (auth, 1) == 0) |
677 | { | 706 | { |
707 | off_t ioff = 0; | ||
678 | off_t off = size; | 708 | off_t off = size; |
679 | size_t nwr; | 709 | size_t nwr, nrd; |
680 | char *buf = NULL; | 710 | char *buf = NULL; |
711 | size_t bufsize = 1024; | ||
712 | |||
713 | stream_size (istream, (off_t *) &bufsize); | ||
714 | for (; (buf = malloc (bufsize)) == NULL && bufsize > 1; bufsize /= 2) | ||
715 | ; | ||
681 | 716 | ||
682 | n = 0; | 717 | if (!buf) |
718 | { | ||
719 | status = errno = ENOMEM; | ||
720 | failed++; | ||
721 | } | ||
722 | else | ||
723 | { | ||
683 | status = 0; | 724 | status = 0; |
684 | fseek (fp, 0, SEEK_SET); | 725 | |
685 | while (getline(&buf, &n, fp) > 0) | 726 | while ((status = stream_read (istream, buf, bufsize, ioff, &nrd)) |
727 | == 0 | ||
728 | && nrd > 0) | ||
686 | { | 729 | { |
687 | status = stream_write (stream, buf, strlen (buf), off, &nwr); | 730 | status = stream_write (ostream, buf, nrd, off, &nwr); |
688 | if (status) | 731 | if (status) |
689 | { | ||
690 | mailer_err ("error writing to mailbox: %s", | ||
691 | mu_errstring (status)); | ||
692 | break; | 732 | break; |
693 | } | 733 | ioff += nrd; |
694 | off += nwr; | 734 | off += nwr; |
695 | } | 735 | } |
736 | |||
696 | free (buf); | 737 | free (buf); |
738 | } | ||
739 | |||
697 | switch_user_id (auth, 0); | 740 | switch_user_id (auth, 0); |
741 | |||
742 | if (status) | ||
743 | { | ||
744 | mailer_err ("error writing to mailbox: %s", | ||
745 | mu_errstring (status)); | ||
746 | } | ||
698 | } | 747 | } |
699 | 748 | ||
700 | if (!failed) | 749 | if (!failed) | ... | ... |
-
Please register or sign in to post a comment