Fossil SCM
Add features to make it easier to test and debug the "fossil smtp" command from the command-line using stdin and stdout.
Commit
8643602dae8556738c9fb5ec2b47fcb568f084c04d9719dd43d6f21c3cde93a0
Parent
be55fc60c074384…
1 file changed
+26
-6
+26
-6
| --- src/smtp.c | ||
| +++ src/smtp.c | ||
| @@ -613,10 +613,11 @@ | ||
| 613 | 613 | }; |
| 614 | 614 | |
| 615 | 615 | #define SMTPSRV_CLEAR_MSG 1 /* smtp_server_clear() last message only */ |
| 616 | 616 | #define SMTPSRV_CLEAR_ALL 2 /* smtp_server_clear() everything */ |
| 617 | 617 | #define SMTPSRV_LOG 0x001 /* Record a transcript of the interaction */ |
| 618 | +#define SMTPSRV_STDERR 0x002 /* Transcription written to stderr */ | |
| 618 | 619 | |
| 619 | 620 | #endif /* LOCAL_INTERFACE */ |
| 620 | 621 | |
| 621 | 622 | /* |
| 622 | 623 | ** Clear the SmtpServer object. Deallocate resources. |
| @@ -668,10 +669,13 @@ | ||
| 668 | 669 | assert( z[n-1]=='\n' ); |
| 669 | 670 | assert( z[n-2]=='\r' ); |
| 670 | 671 | if( p->srvrFlags & SMTPSRV_LOG ){ |
| 671 | 672 | blob_appendf(&p->transcript, "S: %.*s\n", n-2, z); |
| 672 | 673 | } |
| 674 | + if( p->srvrFlags & SMTPSRV_STDERR ){ | |
| 675 | + fprintf(stderr, "S: %.*s\n", n-2, z); | |
| 676 | + } | |
| 673 | 677 | fwrite(z, n, 1, stdout); |
| 674 | 678 | fflush(stdout); |
| 675 | 679 | blob_zero(&b); |
| 676 | 680 | } |
| 677 | 681 | |
| @@ -678,28 +682,43 @@ | ||
| 678 | 682 | /* |
| 679 | 683 | ** Read a single line from the client. |
| 680 | 684 | */ |
| 681 | 685 | static int smtp_server_gets(SmtpServer *p, char *aBuf, int nBuf){ |
| 682 | 686 | int rc = fgets(aBuf, nBuf, stdin)!=0; |
| 683 | - if( rc && (p->srvrFlags & SMTPSRV_LOG)!=0 ){ | |
| 684 | - blob_appendf(&p->transcript, "C: %s\n", aBuf); | |
| 687 | + if( rc ){ | |
| 688 | + if( (p->srvrFlags & SMTPSRV_LOG)!=0 ){ | |
| 689 | + blob_appendf(&p->transcript, "C: %s", aBuf); | |
| 690 | + } | |
| 691 | + if( (p->srvrFlags & SMTPSRV_STDERR)!=0 ){ | |
| 692 | + fprintf(stderr, "C: %s", aBuf); | |
| 693 | + } | |
| 685 | 694 | } |
| 686 | 695 | return rc; |
| 687 | 696 | } |
| 688 | 697 | |
| 689 | 698 | /* |
| 690 | 699 | ** Capture the incoming email data into the p->msg blob. Dequote |
| 691 | 700 | ** lines of "..\r\n" into just ".\r\n". |
| 692 | 701 | */ |
| 693 | 702 | static void smtp_server_capture_data(SmtpServer *p, char *z, int n){ |
| 703 | + int nLine = 0; | |
| 694 | 704 | while( fgets(z, n, stdin) ){ |
| 695 | - if( strncmp(z, ".\r\n", 3)==0 ) return; | |
| 696 | - if( strncmp(z, "..\r\n", 4)==0 ){ | |
| 705 | + if( strncmp(z, ".\r\n", 3)==0 || strncmp(z, ".\n",2)==0 ) break; | |
| 706 | + nLine++; | |
| 707 | + if( strncmp(z, "..\r\n", 4)==0 || strncmp(z, "..\n",3)==0 ){ | |
| 697 | 708 | memmove(z, z+1, 4); |
| 698 | 709 | } |
| 699 | 710 | blob_append(&p->msg, z, -1); |
| 700 | 711 | } |
| 712 | + if( p->srvrFlags & SMTPSRV_LOG ){ | |
| 713 | + blob_appendf(&p->transcript, "C: # %d lines, %d bytes of content\n", | |
| 714 | + nLine, blob_size(&p->msg)); | |
| 715 | + } | |
| 716 | + if( p->srvrFlags & SMTPSRV_STDERR ){ | |
| 717 | + fprintf(stderr, "C: # %d lines, %d bytes of content\n", | |
| 718 | + nLine, blob_size(&p->msg)); | |
| 719 | + } | |
| 701 | 720 | } |
| 702 | 721 | |
| 703 | 722 | /* |
| 704 | 723 | ** COMMAND: smtp |
| 705 | 724 | ** |
| @@ -717,16 +736,17 @@ | ||
| 717 | 736 | char z[5000]; |
| 718 | 737 | |
| 719 | 738 | smtp_server_init(&x); |
| 720 | 739 | zDomain = find_option("domain",0,1); |
| 721 | 740 | if( zDomain==0 ) zDomain = "unspecified.domain"; |
| 741 | + if( find_option("trace",0,0)!=0 ) x.srvrFlags |= SMTPSRV_STDERR; | |
| 722 | 742 | verify_all_options(); |
| 723 | 743 | if( g.argc!=3 ) usage("DBNAME"); |
| 724 | 744 | zDbName = g.argv[2]; |
| 725 | 745 | zDbName = enter_chroot_jail(zDbName, 0); |
| 726 | - smtp_server_send(&x, "220 %s ESMTP Fossil ([%.*s] %s)\r\n", | |
| 727 | - zDomain, 16, MANIFEST_VERSION, MANIFEST_DATE); | |
| 746 | + smtp_server_send(&x, "220 %s ESMTP https://fossil-scm.org/ %s\r\n", | |
| 747 | + zDomain, MANIFEST_VERSION); | |
| 728 | 748 | while( smtp_server_gets(&x, z, sizeof(z)) ){ |
| 729 | 749 | if( strncmp(z, "EHLO ", 5)==0 ){ |
| 730 | 750 | smtp_server_send(&x, "250 ok\r\n"); |
| 731 | 751 | }else |
| 732 | 752 | if( strncmp(z, "HELO ", 5)==0 ){ |
| 733 | 753 |
| --- src/smtp.c | |
| +++ src/smtp.c | |
| @@ -613,10 +613,11 @@ | |
| 613 | }; |
| 614 | |
| 615 | #define SMTPSRV_CLEAR_MSG 1 /* smtp_server_clear() last message only */ |
| 616 | #define SMTPSRV_CLEAR_ALL 2 /* smtp_server_clear() everything */ |
| 617 | #define SMTPSRV_LOG 0x001 /* Record a transcript of the interaction */ |
| 618 | |
| 619 | #endif /* LOCAL_INTERFACE */ |
| 620 | |
| 621 | /* |
| 622 | ** Clear the SmtpServer object. Deallocate resources. |
| @@ -668,10 +669,13 @@ | |
| 668 | assert( z[n-1]=='\n' ); |
| 669 | assert( z[n-2]=='\r' ); |
| 670 | if( p->srvrFlags & SMTPSRV_LOG ){ |
| 671 | blob_appendf(&p->transcript, "S: %.*s\n", n-2, z); |
| 672 | } |
| 673 | fwrite(z, n, 1, stdout); |
| 674 | fflush(stdout); |
| 675 | blob_zero(&b); |
| 676 | } |
| 677 | |
| @@ -678,28 +682,43 @@ | |
| 678 | /* |
| 679 | ** Read a single line from the client. |
| 680 | */ |
| 681 | static int smtp_server_gets(SmtpServer *p, char *aBuf, int nBuf){ |
| 682 | int rc = fgets(aBuf, nBuf, stdin)!=0; |
| 683 | if( rc && (p->srvrFlags & SMTPSRV_LOG)!=0 ){ |
| 684 | blob_appendf(&p->transcript, "C: %s\n", aBuf); |
| 685 | } |
| 686 | return rc; |
| 687 | } |
| 688 | |
| 689 | /* |
| 690 | ** Capture the incoming email data into the p->msg blob. Dequote |
| 691 | ** lines of "..\r\n" into just ".\r\n". |
| 692 | */ |
| 693 | static void smtp_server_capture_data(SmtpServer *p, char *z, int n){ |
| 694 | while( fgets(z, n, stdin) ){ |
| 695 | if( strncmp(z, ".\r\n", 3)==0 ) return; |
| 696 | if( strncmp(z, "..\r\n", 4)==0 ){ |
| 697 | memmove(z, z+1, 4); |
| 698 | } |
| 699 | blob_append(&p->msg, z, -1); |
| 700 | } |
| 701 | } |
| 702 | |
| 703 | /* |
| 704 | ** COMMAND: smtp |
| 705 | ** |
| @@ -717,16 +736,17 @@ | |
| 717 | char z[5000]; |
| 718 | |
| 719 | smtp_server_init(&x); |
| 720 | zDomain = find_option("domain",0,1); |
| 721 | if( zDomain==0 ) zDomain = "unspecified.domain"; |
| 722 | verify_all_options(); |
| 723 | if( g.argc!=3 ) usage("DBNAME"); |
| 724 | zDbName = g.argv[2]; |
| 725 | zDbName = enter_chroot_jail(zDbName, 0); |
| 726 | smtp_server_send(&x, "220 %s ESMTP Fossil ([%.*s] %s)\r\n", |
| 727 | zDomain, 16, MANIFEST_VERSION, MANIFEST_DATE); |
| 728 | while( smtp_server_gets(&x, z, sizeof(z)) ){ |
| 729 | if( strncmp(z, "EHLO ", 5)==0 ){ |
| 730 | smtp_server_send(&x, "250 ok\r\n"); |
| 731 | }else |
| 732 | if( strncmp(z, "HELO ", 5)==0 ){ |
| 733 |
| --- src/smtp.c | |
| +++ src/smtp.c | |
| @@ -613,10 +613,11 @@ | |
| 613 | }; |
| 614 | |
| 615 | #define SMTPSRV_CLEAR_MSG 1 /* smtp_server_clear() last message only */ |
| 616 | #define SMTPSRV_CLEAR_ALL 2 /* smtp_server_clear() everything */ |
| 617 | #define SMTPSRV_LOG 0x001 /* Record a transcript of the interaction */ |
| 618 | #define SMTPSRV_STDERR 0x002 /* Transcription written to stderr */ |
| 619 | |
| 620 | #endif /* LOCAL_INTERFACE */ |
| 621 | |
| 622 | /* |
| 623 | ** Clear the SmtpServer object. Deallocate resources. |
| @@ -668,10 +669,13 @@ | |
| 669 | assert( z[n-1]=='\n' ); |
| 670 | assert( z[n-2]=='\r' ); |
| 671 | if( p->srvrFlags & SMTPSRV_LOG ){ |
| 672 | blob_appendf(&p->transcript, "S: %.*s\n", n-2, z); |
| 673 | } |
| 674 | if( p->srvrFlags & SMTPSRV_STDERR ){ |
| 675 | fprintf(stderr, "S: %.*s\n", n-2, z); |
| 676 | } |
| 677 | fwrite(z, n, 1, stdout); |
| 678 | fflush(stdout); |
| 679 | blob_zero(&b); |
| 680 | } |
| 681 | |
| @@ -678,28 +682,43 @@ | |
| 682 | /* |
| 683 | ** Read a single line from the client. |
| 684 | */ |
| 685 | static int smtp_server_gets(SmtpServer *p, char *aBuf, int nBuf){ |
| 686 | int rc = fgets(aBuf, nBuf, stdin)!=0; |
| 687 | if( rc ){ |
| 688 | if( (p->srvrFlags & SMTPSRV_LOG)!=0 ){ |
| 689 | blob_appendf(&p->transcript, "C: %s", aBuf); |
| 690 | } |
| 691 | if( (p->srvrFlags & SMTPSRV_STDERR)!=0 ){ |
| 692 | fprintf(stderr, "C: %s", aBuf); |
| 693 | } |
| 694 | } |
| 695 | return rc; |
| 696 | } |
| 697 | |
| 698 | /* |
| 699 | ** Capture the incoming email data into the p->msg blob. Dequote |
| 700 | ** lines of "..\r\n" into just ".\r\n". |
| 701 | */ |
| 702 | static void smtp_server_capture_data(SmtpServer *p, char *z, int n){ |
| 703 | int nLine = 0; |
| 704 | while( fgets(z, n, stdin) ){ |
| 705 | if( strncmp(z, ".\r\n", 3)==0 || strncmp(z, ".\n",2)==0 ) break; |
| 706 | nLine++; |
| 707 | if( strncmp(z, "..\r\n", 4)==0 || strncmp(z, "..\n",3)==0 ){ |
| 708 | memmove(z, z+1, 4); |
| 709 | } |
| 710 | blob_append(&p->msg, z, -1); |
| 711 | } |
| 712 | if( p->srvrFlags & SMTPSRV_LOG ){ |
| 713 | blob_appendf(&p->transcript, "C: # %d lines, %d bytes of content\n", |
| 714 | nLine, blob_size(&p->msg)); |
| 715 | } |
| 716 | if( p->srvrFlags & SMTPSRV_STDERR ){ |
| 717 | fprintf(stderr, "C: # %d lines, %d bytes of content\n", |
| 718 | nLine, blob_size(&p->msg)); |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | /* |
| 723 | ** COMMAND: smtp |
| 724 | ** |
| @@ -717,16 +736,17 @@ | |
| 736 | char z[5000]; |
| 737 | |
| 738 | smtp_server_init(&x); |
| 739 | zDomain = find_option("domain",0,1); |
| 740 | if( zDomain==0 ) zDomain = "unspecified.domain"; |
| 741 | if( find_option("trace",0,0)!=0 ) x.srvrFlags |= SMTPSRV_STDERR; |
| 742 | verify_all_options(); |
| 743 | if( g.argc!=3 ) usage("DBNAME"); |
| 744 | zDbName = g.argv[2]; |
| 745 | zDbName = enter_chroot_jail(zDbName, 0); |
| 746 | smtp_server_send(&x, "220 %s ESMTP https://fossil-scm.org/ %s\r\n", |
| 747 | zDomain, MANIFEST_VERSION); |
| 748 | while( smtp_server_gets(&x, z, sizeof(z)) ){ |
| 749 | if( strncmp(z, "EHLO ", 5)==0 ){ |
| 750 | smtp_server_send(&x, "250 ok\r\n"); |
| 751 | }else |
| 752 | if( strncmp(z, "HELO ", 5)==0 ){ |
| 753 |