examples/mta.c: use streams instead of FILE; exit with codes from sysexits.h
Showing
1 changed file
with
137 additions
and
154 deletions
... | @@ -57,6 +57,7 @@ | ... | @@ -57,6 +57,7 @@ |
57 | #endif | 57 | #endif |
58 | #include <string.h> | 58 | #include <string.h> |
59 | #include <pwd.h> | 59 | #include <pwd.h> |
60 | #include <sysexits.h> | ||
60 | #include <sys/stat.h> | 61 | #include <sys/stat.h> |
61 | #include <sys/time.h> | 62 | #include <sys/time.h> |
62 | #include <sys/socket.h> | 63 | #include <sys/socket.h> |
... | @@ -141,7 +142,7 @@ main (int argc, char **argv) | ... | @@ -141,7 +142,7 @@ main (int argc, char **argv) |
141 | break; | 142 | break; |
142 | 143 | ||
143 | default: | 144 | default: |
144 | exit (1); | 145 | exit (EX_USAGE); |
145 | } | 146 | } |
146 | } | 147 | } |
147 | 148 | ||
... | @@ -190,73 +191,71 @@ from_address () | ... | @@ -190,73 +191,71 @@ from_address () |
190 | return strdup (from_person); | 191 | return strdup (from_person); |
191 | } | 192 | } |
192 | 193 | ||
193 | void | 194 | static mu_message_t |
194 | make_tmp (FILE *input, const char *from, char **tempfile) | 195 | make_tmp (mu_stream_t in) |
195 | { | 196 | { |
196 | time_t t; | 197 | int rc; |
197 | int fd = mu_tempfile (NULL, tempfile); | 198 | mu_stream_t out; |
198 | FILE *fp; | ||
199 | char *buf = NULL; | 199 | char *buf = NULL; |
200 | size_t n = 0; | 200 | size_t size = 0, n; |
201 | int line; | 201 | mu_message_t mesg; |
202 | 202 | ||
203 | if (fd == -1 || (fp = fdopen (fd, "w+")) == NULL) | 203 | rc = mu_temp_file_stream_create (&out, NULL); |
204 | if (rc) | ||
204 | { | 205 | { |
205 | mu_error ("%s: unable to open temporary file", progname); | 206 | mu_error (_("unable to open temporary file: %s"), mu_strerror (rc)); |
206 | exit (1); | 207 | exit (EX_UNAVAILABLE); |
207 | } | 208 | } |
208 | 209 | ||
209 | line = 0; | 210 | rc = mu_stream_getline (in, &buf, &size, &n); |
210 | while (getline (&buf, &n, input) > 0) | 211 | if (rc) |
211 | { | 212 | { |
212 | int len = strlen (buf); | 213 | mu_error (_("read error: %s"), mu_strerror (rc)); |
213 | if (len >= 2 && buf[len - 2] == '\r') | 214 | mu_stream_destroy (&out); |
214 | { | 215 | exit (EX_UNAVAILABLE); |
215 | buf[len - 2] = '\n'; | 216 | } |
216 | buf[len - 1] = 0; | 217 | if (n == 0) |
217 | } | 218 | { |
218 | 219 | mu_error (_("unexpected EOF on input")); | |
219 | line++; | 220 | mu_stream_destroy (&out); |
220 | if (line == 1) | 221 | exit (EX_DATAERR); |
221 | { | 222 | } |
222 | if (memcmp (buf, "From ", 5)) | ||
223 | { | ||
224 | char *from = from_address (); | ||
225 | if (from) | ||
226 | { | ||
227 | time (&t); | ||
228 | fprintf (fp, "From %s %s", from, ctime (&t)); | ||
229 | free (from); | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | mu_error ("%s: can't determine sender address", progname); | ||
234 | exit (1); | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | else if (!memcmp (buf, "From ", 5)) | ||
239 | fputc ('>', fp); | ||
240 | 223 | ||
241 | if (dot && buf[0] == '.' && | 224 | if (n >= 5 && memcmp (buf, "From ", 5)) |
242 | ((buf[1] == '\r' && buf[2] == '\n') || (buf[1] == '\n'))) | 225 | { |
243 | break; | 226 | time_t t; |
244 | 227 | const char *from = from_address (); | |
245 | if (fputs (buf, fp) == EOF) | 228 | if (!from) |
246 | { | 229 | { |
247 | mu_error ("%s: temporary file write error", progname); | 230 | mu_error ("%s: can't determine sender address", progname); |
248 | fclose (fp); | 231 | exit (EX_NOUSER); |
249 | exit (1); | ||
250 | } | 232 | } |
233 | |||
234 | time (&t); | ||
235 | mu_stream_printf (out, "From %s %s", from, ctime (&t)); | ||
251 | } | 236 | } |
252 | |||
253 | if (buf && strchr (buf, '\n') == NULL) | ||
254 | putc ('\n', fp); | ||
255 | 237 | ||
256 | putc ('\n', fp); | 238 | mu_stream_write (out, buf, n, NULL); |
257 | free (buf); | 239 | free (buf); |
240 | |||
241 | rc = mu_stream_copy (out, in, 0, NULL); | ||
242 | if (rc) | ||
243 | { | ||
244 | mu_error (_("copy error: %s"), mu_strerror (rc)); | ||
245 | mu_stream_destroy (&out); | ||
246 | exit (EX_UNAVAILABLE); | ||
247 | } | ||
248 | |||
249 | rc = mu_stream_to_message (out, &mesg); | ||
250 | mu_stream_destroy (&out); | ||
251 | if (rc) | ||
252 | { | ||
253 | mu_error (_("error creating temporary message: %s"), | ||
254 | mu_strerror (rc)); | ||
255 | exit (EX_UNAVAILABLE); | ||
256 | } | ||
258 | 257 | ||
259 | fclose (fp); | 258 | return mesg; |
260 | } | 259 | } |
261 | 260 | ||
262 | void | 261 | void |
... | @@ -462,9 +461,8 @@ message_finalize (mu_message_t msg, int warn) | ... | @@ -462,9 +461,8 @@ message_finalize (mu_message_t msg, int warn) |
462 | int | 461 | int |
463 | mta_stdin (int argc, char **argv) | 462 | mta_stdin (int argc, char **argv) |
464 | { | 463 | { |
465 | int c; | 464 | int c, rc; |
466 | char *tempfile; | 465 | mu_stream_t in; |
467 | mu_mailbox_t mbox; | ||
468 | mu_message_t msg = NULL; | 466 | mu_message_t msg = NULL; |
469 | 467 | ||
470 | for (c = 0; c < argc; c++) | 468 | for (c = 0; c < argc; c++) |
... | @@ -476,27 +474,19 @@ mta_stdin (int argc, char **argv) | ... | @@ -476,27 +474,19 @@ mta_stdin (int argc, char **argv) |
476 | } | 474 | } |
477 | } | 475 | } |
478 | 476 | ||
479 | make_tmp (stdin, from_person, &tempfile); | 477 | rc = mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_READ); |
480 | if ((c = mu_mailbox_create_default (&mbox, tempfile)) != 0) | 478 | if (rc) |
481 | { | 479 | { |
482 | mu_error ("%s: can't create mailbox %s: %s", | 480 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stdio_stream_create", |
483 | progname, tempfile, mu_strerror (c)); | 481 | "MU_STDIN_FD", rc); |
484 | unlink (tempfile); | 482 | exit (EX_UNAVAILABLE); |
485 | return 1; | 483 | } |
486 | } | ||
487 | 484 | ||
488 | if ((c = mu_mailbox_open (mbox, MU_STREAM_RDWR)) != 0) | 485 | msg = make_tmp (in); |
489 | { | 486 | mu_stream_destroy (&in); |
490 | mu_error ("%s: can't open mailbox %s: %s", | ||
491 | progname, tempfile, mu_strerror (c)); | ||
492 | unlink (tempfile); | ||
493 | return 1; | ||
494 | } | ||
495 | |||
496 | mu_mailbox_get_message (mbox, 1, &msg); | ||
497 | if (message_finalize (msg, 1)) | 487 | if (message_finalize (msg, 1)) |
498 | return 1; | 488 | return 1; |
499 | 489 | ||
500 | if (!recipients) | 490 | if (!recipients) |
501 | { | 491 | { |
502 | mu_error ("%s: Recipient names must be specified", progname); | 492 | mu_error ("%s: Recipient names must be specified", progname); |
... | @@ -504,24 +494,20 @@ mta_stdin (int argc, char **argv) | ... | @@ -504,24 +494,20 @@ mta_stdin (int argc, char **argv) |
504 | } | 494 | } |
505 | 495 | ||
506 | mta_send (msg); | 496 | mta_send (msg); |
507 | 497 | mu_message_destroy (&msg, mu_message_get_owner (msg)); | |
508 | unlink (tempfile); | ||
509 | free (tempfile); | ||
510 | return 0; | 498 | return 0; |
511 | } | 499 | } |
512 | 500 | ||
513 | FILE *in, *out; | ||
514 | |||
515 | void | 501 | void |
516 | smtp_reply (int code, char *fmt, ...) | 502 | smtp_reply (mu_stream_t str, int code, char *fmt, ...) |
517 | { | 503 | { |
518 | va_list ap; | 504 | va_list ap; |
519 | 505 | ||
506 | mu_stream_printf (str, "%d ", code); | ||
520 | va_start (ap, fmt); | 507 | va_start (ap, fmt); |
521 | fprintf (out, "%d ", code); | 508 | mu_stream_vprintf (str, fmt, ap); |
522 | vfprintf (out, fmt, ap); | ||
523 | va_end (ap); | 509 | va_end (ap); |
524 | fprintf (out, "\r\n"); | 510 | mu_stream_printf (str, "\r\n"); |
525 | } | 511 | } |
526 | 512 | ||
527 | #define STATE_INIT 0 | 513 | #define STATE_INIT 0 |
... | @@ -575,42 +561,34 @@ check_prefix (char *str, const char *prefix) | ... | @@ -575,42 +561,34 @@ check_prefix (char *str, const char *prefix) |
575 | } | 561 | } |
576 | 562 | ||
577 | void | 563 | void |
578 | smtp (int fd) | 564 | smtp (mu_stream_t str) |
579 | { | 565 | { |
580 | int state, c; | 566 | int state; |
581 | char *buf = NULL; | 567 | char *buf = NULL; |
582 | size_t size = 0; | 568 | size_t size = 0; |
583 | mu_mailbox_t mbox; | ||
584 | mu_message_t msg; | ||
585 | char *tempfile; | ||
586 | char *rcpt_addr; | 569 | char *rcpt_addr; |
587 | 570 | ||
588 | in = fdopen (fd, "r"); | 571 | smtp_reply (str, 220, "Ready"); |
589 | out = fdopen (fd, "w"); | ||
590 | SETVBUF (in, NULL, _IOLBF, 0); | ||
591 | SETVBUF (out, NULL, _IOLBF, 0); | ||
592 | |||
593 | smtp_reply (220, "Ready"); | ||
594 | for (state = STATE_INIT; state != STATE_QUIT; ) | 572 | for (state = STATE_INIT; state != STATE_QUIT; ) |
595 | { | 573 | { |
574 | char *s; | ||
596 | int argc; | 575 | int argc; |
597 | char **argv; | 576 | char **argv; |
598 | int kw, len; | 577 | int kw; |
578 | size_t len; | ||
599 | 579 | ||
600 | if (getline (&buf, &size, in) == -1) | 580 | if (mu_stream_getline (str, &buf, &size, &len) || len == 0) |
601 | exit (1); | 581 | exit (EX_PROTOCOL); |
602 | len = strlen (buf); | 582 | |
603 | while (len > 0 && (buf[len-1] == '\n' || buf[len-1] == '\r')) | 583 | s = mu_str_stripws (buf); |
604 | len --; | ||
605 | buf[len] = 0; | ||
606 | 584 | ||
607 | if (mu_argcv_get (buf, "", NULL, &argc, &argv)) | 585 | if (mu_argcv_get (s, "", NULL, &argc, &argv)) |
608 | exit (1); | 586 | exit (EX_UNAVAILABLE); |
609 | 587 | ||
610 | kw = smtp_kw (argv[0]); | 588 | kw = smtp_kw (argv[0]); |
611 | if (kw == KW_QUIT) | 589 | if (kw == KW_QUIT) |
612 | { | 590 | { |
613 | smtp_reply (221, "Done"); | 591 | smtp_reply (str, 221, "Done"); |
614 | state = STATE_QUIT; | 592 | state = STATE_QUIT; |
615 | mu_argcv_free (argc, argv); | 593 | mu_argcv_free (argc, argv); |
616 | continue; | 594 | continue; |
... | @@ -625,15 +603,15 @@ smtp (int fd) | ... | @@ -625,15 +603,15 @@ smtp (int fd) |
625 | case KW_HELO: | 603 | case KW_HELO: |
626 | if (argc == 2) | 604 | if (argc == 2) |
627 | { | 605 | { |
628 | smtp_reply (250, "pleased to meet you"); | 606 | smtp_reply (str, 250, "pleased to meet you"); |
629 | state = STATE_EHLO; | 607 | state = STATE_EHLO; |
630 | } | 608 | } |
631 | else | 609 | else |
632 | smtp_reply (501, "%s requires domain address", argv[0]); | 610 | smtp_reply (str, 501, "%s requires domain address", argv[0]); |
633 | break; | 611 | break; |
634 | 612 | ||
635 | default: | 613 | default: |
636 | smtp_reply (503, "Polite people say HELO first"); | 614 | smtp_reply (str, 503, "Polite people say HELO first"); |
637 | break; | 615 | break; |
638 | } | 616 | } |
639 | break; | 617 | break; |
... | @@ -652,15 +630,15 @@ smtp (int fd) | ... | @@ -652,15 +630,15 @@ smtp (int fd) |
652 | if (from_person) | 630 | if (from_person) |
653 | { | 631 | { |
654 | from_person = strdup (from_person); | 632 | from_person = strdup (from_person); |
655 | smtp_reply (250, "Sender OK"); | 633 | smtp_reply (str, 250, "Sender OK"); |
656 | state = STATE_MAIL; | 634 | state = STATE_MAIL; |
657 | } | 635 | } |
658 | else | 636 | else |
659 | smtp_reply (501, "Syntax error"); | 637 | smtp_reply (str, 501, "Syntax error"); |
660 | break; | 638 | break; |
661 | 639 | ||
662 | default: | 640 | default: |
663 | smtp_reply (503, "Need MAIL command"); | 641 | smtp_reply (str, 503, "Need MAIL command"); |
664 | } | 642 | } |
665 | break; | 643 | break; |
666 | 644 | ||
... | @@ -678,19 +656,19 @@ smtp (int fd) | ... | @@ -678,19 +656,19 @@ smtp (int fd) |
678 | if (rcpt_addr) | 656 | if (rcpt_addr) |
679 | { | 657 | { |
680 | if (add_recipient (rcpt_addr)) | 658 | if (add_recipient (rcpt_addr)) |
681 | smtp_reply (451, "Recipient not accepted"); | 659 | smtp_reply (str, 451, "Recipient not accepted"); |
682 | else | 660 | else |
683 | { | 661 | { |
684 | smtp_reply (250, "Recipient OK"); | 662 | smtp_reply (str, 250, "Recipient OK"); |
685 | state = STATE_RCPT; | 663 | state = STATE_RCPT; |
686 | } | 664 | } |
687 | } | 665 | } |
688 | else | 666 | else |
689 | smtp_reply (501, "Syntax error"); | 667 | smtp_reply (str, 501, "Syntax error"); |
690 | break; | 668 | break; |
691 | 669 | ||
692 | default: | 670 | default: |
693 | smtp_reply (503, "Need RCPT command"); | 671 | smtp_reply (str, 503, "Need RCPT command"); |
694 | } | 672 | } |
695 | break; | 673 | break; |
696 | 674 | ||
... | @@ -708,55 +686,51 @@ smtp (int fd) | ... | @@ -708,55 +686,51 @@ smtp (int fd) |
708 | if (rcpt_addr) | 686 | if (rcpt_addr) |
709 | { | 687 | { |
710 | if (add_recipient (rcpt_addr)) | 688 | if (add_recipient (rcpt_addr)) |
711 | smtp_reply (451, "Recipient not accepted"); | 689 | smtp_reply (str, 451, "Recipient not accepted"); |
712 | else | 690 | else |
713 | { | 691 | { |
714 | smtp_reply (250, "Recipient OK"); | 692 | smtp_reply (str, 250, "Recipient OK"); |
715 | state = STATE_RCPT; | 693 | state = STATE_RCPT; |
716 | } | 694 | } |
717 | } | 695 | } |
718 | else | 696 | else |
719 | smtp_reply (501, "Syntax error"); | 697 | smtp_reply (str, 501, "Syntax error"); |
720 | break; | 698 | break; |
721 | 699 | ||
722 | case KW_DATA: | 700 | case KW_DATA: |
723 | smtp_reply (354, | 701 | { |
724 | "Enter mail, end with \".\" on a line by itself"); | 702 | mu_stream_t flt; |
725 | make_tmp (in, from_person, &tempfile); | 703 | mu_message_t msg; |
726 | if ((c = mu_mailbox_create_default (&mbox, tempfile)) != 0) | 704 | int rc; |
727 | { | 705 | |
728 | mu_error ("%s: can't create mailbox %s: %s", | 706 | rc = mu_filter_create (&flt, str, "CRLFDOT", MU_FILTER_DECODE, |
729 | progname, | 707 | MU_STREAM_READ|MU_STREAM_WRTHRU); |
730 | tempfile, mu_strerror (c)); | 708 | if (rc) |
731 | unlink (tempfile); | 709 | { |
732 | exit (1); | 710 | mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_create", |
733 | } | 711 | "CRLFDOT", rc); |
734 | 712 | exit (EX_UNAVAILABLE); | |
735 | if ((c = mu_mailbox_open (mbox, MU_STREAM_RDWR)) != 0) | 713 | } |
736 | { | 714 | smtp_reply (str, 354, |
737 | mu_error ("%s: can't open mailbox %s: %s", | 715 | "Enter mail, end with \".\" on a line by itself"); |
738 | progname, | 716 | |
739 | tempfile, mu_strerror (c)); | 717 | msg = make_tmp (flt); |
740 | unlink (tempfile); | 718 | mu_stream_destroy (&flt); |
741 | exit (1); | 719 | if (message_finalize (msg, 0) == 0) |
742 | } | 720 | mta_send (msg); |
743 | 721 | else | |
744 | mu_mailbox_get_message (mbox, 1, &msg); | 722 | smtp_reply (str, 501, "can't send message"); /*FIXME: code?*/ |
745 | if (message_finalize (msg, 0) == 0) | 723 | mu_message_destroy (&msg, mu_message_get_owner (msg)); |
746 | mta_send (msg); | 724 | mu_address_destroy (&recipients); |
747 | else | 725 | from_person = NULL; |
748 | smtp_reply (501, "can't send message"); /*FIXME: code?*/ | ||
749 | unlink (tempfile); | ||
750 | |||
751 | mu_address_destroy (&recipients); | ||
752 | from_person = NULL; | ||
753 | 726 | ||
754 | smtp_reply (250, "Message accepted for delivery"); | 727 | smtp_reply (str, 250, "Message accepted for delivery"); |
755 | state = STATE_EHLO; | 728 | state = STATE_EHLO; |
729 | } | ||
756 | break; | 730 | break; |
757 | 731 | ||
758 | default: | 732 | default: |
759 | smtp_reply (503, "Invalid command"); | 733 | smtp_reply (str, 503, "Invalid command"); |
760 | break; | 734 | break; |
761 | } | 735 | } |
762 | break; | 736 | break; |
... | @@ -764,8 +738,6 @@ smtp (int fd) | ... | @@ -764,8 +738,6 @@ smtp (int fd) |
764 | } | 738 | } |
765 | mu_argcv_free (argc, argv); | 739 | mu_argcv_free (argc, argv); |
766 | } | 740 | } |
767 | |||
768 | close (fd); | ||
769 | } | 741 | } |
770 | 742 | ||
771 | int | 743 | int |
... | @@ -826,7 +798,9 @@ mta_smtp (int argc, char **argv) | ... | @@ -826,7 +798,9 @@ mta_smtp (int argc, char **argv) |
826 | struct sockaddr_in his_addr; | 798 | struct sockaddr_in his_addr; |
827 | int sfd, status; | 799 | int sfd, status; |
828 | socklen_t len; | 800 | socklen_t len; |
829 | 801 | int rc; | |
802 | mu_stream_t str; | ||
803 | |||
830 | FD_ZERO (&rfds); | 804 | FD_ZERO (&rfds); |
831 | FD_SET (fd, &rfds); | 805 | FD_SET (fd, &rfds); |
832 | 806 | ||
... | @@ -846,7 +820,16 @@ mta_smtp (int argc, char **argv) | ... | @@ -846,7 +820,16 @@ mta_smtp (int argc, char **argv) |
846 | return 1; | 820 | return 1; |
847 | } | 821 | } |
848 | 822 | ||
849 | smtp (sfd); | 823 | rc = mu_fd_stream_create (&str, NULL, sfd, |
824 | MU_STREAM_RDWR|MU_STREAM_AUTOCLOSE); | ||
825 | if (rc) | ||
826 | { | ||
827 | mu_diag_funcall (MU_DIAG_ERROR, "mu_fd_stream_create", NULL, rc); | ||
828 | break; | ||
829 | } | ||
830 | mu_stream_set_buffer (str, mu_buffer_line, 0); | ||
831 | smtp (str); | ||
832 | mu_stream_destroy (&str); | ||
850 | break; | 833 | break; |
851 | } | 834 | } |
852 | 835 | ... | ... |
-
Please register or sign in to post a comment