Commit 977661a0 977661a0f430d96613265328371c1c4653efda07 by Sergey Poznyakoff

(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*.
1 parent 6f7e5734
...@@ -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)
......