nmh-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Nmh-commits] [SCM] The nmh Mail Handling System branch, master, updated


From: Ken Hornstein
Subject: [Nmh-commits] [SCM] The nmh Mail Handling System branch, master, updated. d6b1aed6b65b10cd5db73a5b2080c4bdefefff39
Date: Wed, 14 Mar 2012 19:51:35 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The nmh Mail Handling System".

The branch, master has been updated
       via  d6b1aed6b65b10cd5db73a5b2080c4bdefefff39 (commit)
       via  f319ad1eba15fbb0f387a0b5246bd0b8f4b36dcf (commit)
      from  86c5a525f242b0a0464d1fa9a5a53029401d093a (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit/nmh.git/commit/?id=d6b1aed6b65b10cd5db73a5b2080c4bdefefff39


commit d6b1aed6b65b10cd5db73a5b2080c4bdefefff39
Author: Ken Hornstein <address@hidden>
Date:   Wed Mar 14 15:51:22 2012 -0400

    A new test program, fakesmtp, to help us test post.

diff --git a/.gitignore b/.gitignore
index d1dd750..9031616 100644
--- a/.gitignore
+++ b/.gitignore
@@ -96,6 +96,7 @@ a.out.DSYM/
 /uip/whatnow
 /uip/whom
 /uip/*.exe
+/test/fakesmtp
 /test/getfullname
 /test/getfqdn
 
diff --git a/Makefile.am b/Makefile.am
index 9ca7740..e402ca1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,7 +65,7 @@ TESTS = test/bad-input/test-header \
        test/cleanup ## The "cleanup" test should always be last.
 
 check_SCRIPTS = test/common.sh
-check_PROGRAMS = test/getfullname test/getfqdn
+check_PROGRAMS = test/getfullname test/getfqdn test/fakesmtp
 
 ##
 ## Stuff that should be cleaned via "make clean"
@@ -366,6 +366,9 @@ test_getfullname_LDADD =
 test_getfqdn_SOURCES = test/getfqdn.c
 test_getfqdn_LDADD =
 
+test_fakesmtp_SOURCES = test/fakesmtp.c
+test_fakesmtp_LDADD =
+
 ##
 ## Our rebuild rules for files that aren't built via the normal mechanisms
 ##
diff --git a/test/fakesmtp.c b/test/fakesmtp.c
new file mode 100644
index 0000000..19df2e9
--- /dev/null
+++ b/test/fakesmtp.c
@@ -0,0 +1,310 @@
+/*
+ * fakesmtp - A fake SMTP server used by the nmh test suite
+ *
+ * This code is Copyright (c) 2012, by the authors of nmh.  See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <signal.h>
+
+#define PIDFILE "/tmp/fakesmtp.pid"
+
+#define LINESIZE 1024
+
+static void killpidfile(void);
+static void handleterm(int);
+static void putsmtp(int, char *);
+static int getsmtp(int, char *);
+
+int
+main(int argc, char *argv[])
+{
+       struct addrinfo hints, *res;
+       int rc, l, conn, on, datamode;
+       FILE *f, *pid;
+       fd_set readfd;
+       struct stat st;
+       struct timeval tv;
+
+       if (argc != 3) {
+               fprintf(stderr, "Usage: %s output-filename port\n", argv[0]);
+               exit(1);
+       }
+
+       if (!(f = fopen(argv[1], "w"))) {
+               fprintf(stderr, "Unable to open output file \"%s\": %s\n",
+                       argv[1], strerror(errno));
+               exit(1);
+       }
+
+       memset(&hints, 0, sizeof(hints));
+
+       hints.ai_family = PF_INET;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_protocol = IPPROTO_TCP;
+       hints.ai_flags = AI_PASSIVE;
+
+       rc = getaddrinfo("127.0.0.1", argv[2], &hints, &res);
+
+       if (rc) {
+               fprintf(stderr, "Unable to resolve localhost/%s: %s\n",
+                       argv[2], gai_strerror(rc));
+               exit(1);
+       }
+
+       l = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+
+       if (l == -1) {
+               fprintf(stderr, "Unable to create listening socket: %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       on = 1;
+
+       if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
+               fprintf(stderr, "Unable to set SO_REUSEADDR: %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       if (bind(l, res->ai_addr, res->ai_addrlen) == -1) {
+               fprintf(stderr, "Unable to bind socket: %s\n", strerror(errno));
+               exit(1);
+       }
+
+       if (listen(l, 1) == -1) {
+               fprintf(stderr, "Unable to listen on socket: %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       /*
+        * Now that our socket & files are set up, do the following things:
+        *
+        * - Check for a PID file.  If there is one, kill the old version.
+        * - Wait 30 seconds for a connection.  If there isn't one, then
+        *   exit.
+        */
+
+       if (stat(PIDFILE, &st) == 0) {
+               long oldpid;
+
+               if (!(pid = fopen(PIDFILE, "r"))) {
+                       fprintf(stderr, "Cannot open " PIDFILE
+                               " (%s), continuing ...\n", strerror(errno));
+               } else {
+                       rc = fscanf(pid, "%ld", &oldpid);
+                       fclose(pid);
+
+                       if (rc != 1) {
+                               fprintf(stderr, "Unable to parse pid in "
+                                       PIDFILE ", continuing ...\n");
+                       } else {
+                               kill((pid_t) oldpid, SIGTERM);
+                       }
+               }
+
+               unlink(PIDFILE);
+       }
+
+       if (!(pid = fopen(PIDFILE, "w"))) {
+               fprintf(stderr, "Cannot open " PIDFILE ": %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       fprintf(pid, "%ld\n", (long) getpid());
+       fclose(pid);
+
+       signal(SIGTERM, handleterm);
+       atexit(killpidfile);
+
+       FD_ZERO(&readfd);
+       FD_SET(l, &readfd);
+       tv.tv_sec = 30;
+       tv.tv_usec = 0;
+
+       rc = select(l + 1, &readfd, NULL, NULL, &tv);
+
+       if (rc < 0) {
+               fprintf(stderr, "select() failed: %s\n", strerror(errno));
+               exit(1);
+       }
+
+       /*
+        * I think if we get a timeout, we should just exit quietly.
+        */
+
+       if (rc == 0) {
+               exit(1);
+       }
+
+       /*
+        * Alright, got a connection!  Accept it.
+        */
+
+       if ((conn = accept(l, NULL, NULL)) == -1) {
+               fprintf(stderr, "Unable to accept connection: %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       close(l);
+       
+       /*
+        * Pretend to be an SMTP server.
+        */
+
+       putsmtp(conn, "220 Not really an ESMTP server");
+       datamode = 0;
+
+       for (;;) {
+               char line[LINESIZE];
+
+               rc = getsmtp(conn, line);
+
+               if (rc == -1)
+                       break;  /* EOF */
+
+               fprintf(f, "%s\n", line);
+
+               /*
+                * If we're in DATA mode, then check to see if we've got
+                * a "."; otherwise, continue
+                */
+
+               if (datamode) {
+                       if (strcmp(line, ".") == 0) {
+                               datamode = 0;
+                               putsmtp(conn, "250 Thanks for the info!");
+                       }
+                       continue;
+               }
+
+               /*
+                * Most commands we ignore and send the same response to.
+                */
+
+               if (strcmp(line, "QUIT") == 0) {
+                       putsmtp(conn, "221 Later alligator!");
+                       close(conn);
+                       break;
+               } else if (strcmp(line, "DATA") == 0) {
+                       putsmtp(conn, "354 Go ahead");
+                       datamode = 1;
+               } else {
+                       putsmtp(conn, "250 I'll buy that for a dollar!");
+               }
+       }
+
+       fclose(f);
+
+       exit(0);
+}
+
+/*
+ * Write a line to the SMTP client on the other end
+ */
+
+static void
+putsmtp(int socket, char *data)
+{
+       struct iovec iov[2];
+
+       iov[0].iov_base = data;
+       iov[0].iov_len = strlen(data);
+       iov[1].iov_base = "\r\n";
+       iov[1].iov_len = 2;
+
+       writev(socket, iov, 2);
+}
+
+/*
+ * Read a line (up to the \r\n)
+ */
+
+static int
+getsmtp(int socket, char *data)
+{
+       int cc;
+       static int bytesinbuf = 0;
+       static char buffer[LINESIZE * 2], *p;
+
+       for (;;) {
+               /*
+                * Find our \r\n
+                */
+
+               if (bytesinbuf > 0 && (p = strchr(buffer, '\r')) &&
+                                                       *(p + 1) == '\n') {
+                       *p = '\0';
+                       strncpy(data, buffer, LINESIZE);
+                       data[LINESIZE - 1] = '\0';
+                       cc = strlen(buffer);
+
+                       /*
+                        * Shuffle leftover bytes back to the beginning
+                        */
+
+                       bytesinbuf -= cc + 2;   /* Don't forget \r\n */
+                       if (bytesinbuf > 0) {
+                               memmove(buffer, buffer + cc + 2, bytesinbuf);
+                       }
+                       return cc;
+               }
+
+               if (bytesinbuf >= sizeof(buffer)) {
+                       fprintf(stderr, "Buffer overflow in getsmtp()!\n");
+                       exit(1);
+               }
+
+               memset(buffer + bytesinbuf, 0, sizeof(buffer) - bytesinbuf);
+               cc = read(socket, buffer + bytesinbuf,
+                         sizeof(buffer) - bytesinbuf);
+
+               if (cc < 0) {
+                       fprintf(stderr, "Read failed: %s\n", strerror(errno));
+                       exit(1);
+               }
+
+               if (cc == 0)
+                       return -1;
+
+               bytesinbuf += cc;
+       }
+}
+
+/*
+ * Handle a SIGTERM
+ */
+
+static void
+handleterm(int signal)
+{
+       killpidfile();
+       fflush(NULL);
+       _exit(1);
+}
+
+/*
+ * Get rid of our pid file
+ */
+
+static void
+killpidfile(void)
+{
+       unlink(PIDFILE);
+}

http://git.savannah.gnu.org/cgit/nmh.git/commit/?id=f319ad1eba15fbb0f387a0b5246bd0b8f4b36dcf


commit f319ad1eba15fbb0f387a0b5246bd0b8f4b36dcf
Author: Ken Hornstein <address@hidden>
Date:   Wed Mar 14 15:47:01 2012 -0400

    Fix the SMTP code so it doesn't end up in a hard loop during a DATA
    command.

diff --git a/mts/smtp/smtp.c b/mts/smtp/smtp.c
index b7135f5..5e4b7bd 100644
--- a/mts/smtp/smtp.c
+++ b/mts/smtp/smtp.c
@@ -1496,7 +1496,7 @@ sm_rrecord (char *buffer, int *len)
     buffer[*len = 0] = 0;
 
     if ((retval = sm_fgets (buffer, BUFSIZ, sm_rfp)) != RP_OK)
-       return retval;
+       return sm_rerror (retval);
     *len = strlen (buffer);
     /* *len should be >0 except on EOF, but check for safety's sake */
     if (*len == 0)

-----------------------------------------------------------------------

Summary of changes:
 .gitignore      |    1 +
 Makefile.am     |    5 +-
 mts/smtp/smtp.c |    2 +-
 test/fakesmtp.c |  310 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 316 insertions(+), 2 deletions(-)
 create mode 100644 test/fakesmtp.c


hooks/post-receive
-- 
The nmh Mail Handling System



reply via email to

[Prev in Thread] Current Thread [Next in Thread]