static void
receive_data_to_file (FILE *peer, FILE *output)
{
- char *line = NULL;
- size_t line_size;
- ssize_t line_len;
+ char *line = NULL;
+ size_t line_size;
+ ssize_t line_len;
- while ((line_len = getline (&line, &line_size, peer)) != -1) {
- if (STRNCMP_LITERAL (line, ".\r\n") == 0)
- break;
- if (line_len < 2)
- continue;
- if (line[line_len-1] == '\n' && line[line_len-2] == '\r') {
- line[line_len-2] = '\n';
- line[line_len-1] = '\0';
- }
- fprintf (output, "%s",
- line[0] == '.' ? line + 1 : line);
+ while ((line_len = getline (&line, &line_size, peer)) != -1) {
+ if (STRNCMP_LITERAL (line, ".\r\n") == 0)
+ break;
+ if (line_len < 2)
+ continue;
+ if (line[line_len - 1] == '\n' && line[line_len - 2] == '\r') {
+ line[line_len - 2] = '\n';
+ line[line_len - 1] = '\0';
}
+ fprintf (output, "%s",
+ line[0] == '.' ? line + 1 : line);
+ }
- free (line);
+ free (line);
}
static int
process_command (FILE *peer, FILE *output, const char *command)
{
- if (STRNCMP_LITERAL (command, "EHLO ") == 0) {
- fprintf (peer, "502 not implemented\r\n");
- fflush (peer);
- } else if (STRNCMP_LITERAL (command, "HELO ") == 0) {
- fprintf (peer, "250 localhost\r\n");
- fflush (peer);
- } else if (STRNCMP_LITERAL (command, "MAIL FROM:") == 0 ||
- STRNCMP_LITERAL (command, "RCPT TO:") == 0) {
- fprintf (peer, "250 OK\r\n");
- fflush (peer);
- } else if (STRNCMP_LITERAL (command, "DATA") == 0) {
- fprintf (peer, "354 End data with <CR><LF>.<CR><LF>\r\n");
- fflush (peer);
- receive_data_to_file (peer, output);
- fprintf (peer, "250 OK\r\n");
- fflush (peer);
- } else if (STRNCMP_LITERAL (command, "QUIT") == 0) {
- fprintf (peer, "221 BYE\r\n");
- fflush (peer);
- return 1;
- } else {
- fprintf (stderr, "Unknown command: %s\n", command);
- }
- return 0;
+ if (STRNCMP_LITERAL (command, "EHLO ") == 0) {
+ fprintf (peer, "502 not implemented\r\n");
+ fflush (peer);
+ } else if (STRNCMP_LITERAL (command, "HELO ") == 0) {
+ fprintf (peer, "250 localhost\r\n");
+ fflush (peer);
+ } else if (STRNCMP_LITERAL (command, "MAIL FROM:") == 0 ||
+ STRNCMP_LITERAL (command, "RCPT TO:") == 0) {
+ fprintf (peer, "250 OK\r\n");
+ fflush (peer);
+ } else if (STRNCMP_LITERAL (command, "DATA") == 0) {
+ fprintf (peer, "354 End data with <CR><LF>.<CR><LF>\r\n");
+ fflush (peer);
+ receive_data_to_file (peer, output);
+ fprintf (peer, "250 OK\r\n");
+ fflush (peer);
+ } else if (STRNCMP_LITERAL (command, "QUIT") == 0) {
+ fprintf (peer, "221 BYE\r\n");
+ fflush (peer);
+ return 1;
+ } else {
+ fprintf (stderr, "Unknown command: %s\n", command);
+ }
+ return 0;
}
static void
do_smtp_to_file (FILE *peer, FILE *output)
{
- char *line = NULL;
- size_t line_size;
- ssize_t line_len;
+ char *line = NULL;
+ size_t line_size;
+ ssize_t line_len;
- fprintf (peer, "220 localhost smtp-dummy\r\n");
- fflush (peer);
+ fprintf (peer, "220 localhost smtp-dummy\r\n");
+ fflush (peer);
- while ((line_len = getline (&line, &line_size, peer)) != -1) {
- if (process_command (peer, output, line))
- break;
- }
+ while ((line_len = getline (&line, &line_size, peer)) != -1) {
+ if (process_command (peer, output, line))
+ break;
+ }
- free (line);
+ free (line);
}
int
main (int argc, char *argv[])
{
- const char * progname;
- char *output_filename;
- FILE *peer_file, *output;
- int sock, peer, err;
- struct sockaddr_in addr, peer_addr;
- struct hostent *hostinfo;
- socklen_t peer_addr_len;
- int reuse;
- int background;
+ const char *progname;
+ char *output_filename;
+ FILE *peer_file, *output;
+ int sock, peer, err;
+ struct sockaddr_in addr, peer_addr;
+ struct hostent *hostinfo;
+ socklen_t peer_addr_len;
+ int reuse;
+ int background;
- progname = argv[0];
+ progname = argv[0];
- background = 0;
- for (; argc >= 2; argc--, argv++) {
- if (argv[1][0] != '-')
- break;
- if (strcmp (argv[1], "--") == 0) {
- argc--;
- argv++;
- break;
- }
- if (strcmp (argv[1], "--background") == 0) {
- background = 1;
- continue;
- }
- fprintf(stderr, "%s: unregognized option '%s'\n",
- progname, argv[1]);
- return 1;
+ background = 0;
+ for (; argc >= 2; argc--, argv++) {
+ if (argv[1][0] != '-')
+ break;
+ if (strcmp (argv[1], "--") == 0) {
+ argc--;
+ argv++;
+ break;
}
-
- if (argc != 2) {
- fprintf (stderr,
- "Usage: %s [--background] <output-file>\n", progname);
- return 1;
+ if (strcmp (argv[1], "--background") == 0) {
+ background = 1;
+ continue;
}
+ fprintf (stderr, "%s: unregognized option '%s'\n",
+ progname, argv[1]);
+ return 1;
+ }
- output_filename = argv[1];
- output = fopen (output_filename, "w");
- if (output == NULL) {
- fprintf (stderr, "Failed to open %s for writing: %s\n",
- output_filename, strerror (errno));
- return 1;
- }
+ if (argc != 2) {
+ fprintf (stderr,
+ "Usage: %s [--background] <output-file>\n", progname);
+ return 1;
+ }
- sock = socket (AF_INET, SOCK_STREAM, 0);
- if (sock == -1) {
- fprintf (stderr, "Error: socket() failed: %s\n",
- strerror (errno));
- return 1;
- }
+ output_filename = argv[1];
+ output = fopen (output_filename, "w");
+ if (output == NULL) {
+ fprintf (stderr, "Failed to open %s for writing: %s\n",
+ output_filename, strerror (errno));
+ return 1;
+ }
- reuse = 1;
- err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse));
- if (err) {
- fprintf (stderr, "Error: setsockopt() failed: %s\n",
- strerror (errno));
- return 1;
- }
+ sock = socket (AF_INET, SOCK_STREAM, 0);
+ if (sock == -1) {
+ fprintf (stderr, "Error: socket() failed: %s\n",
+ strerror (errno));
+ return 1;
+ }
- hostinfo = gethostbyname ("localhost");
- if (hostinfo == NULL) {
- fprintf (stderr, "Unknown host: localhost\n");
- return 1;
- }
+ reuse = 1;
+ err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof (reuse));
+ if (err) {
+ fprintf (stderr, "Error: setsockopt() failed: %s\n",
+ strerror (errno));
+ return 1;
+ }
- memset (&addr, 0, sizeof (addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons (25025);
- addr.sin_addr = *(struct in_addr *) hostinfo->h_addr;
- err = bind (sock, (struct sockaddr *) &addr, sizeof(addr));
- if (err) {
- fprintf (stderr, "Error: bind() failed: %s\n",
- strerror (errno));
- close (sock);
- return 1;
- }
+ hostinfo = gethostbyname ("localhost");
+ if (hostinfo == NULL) {
+ fprintf (stderr, "Unknown host: localhost\n");
+ return 1;
+ }
- err = listen (sock, 1);
- if (err) {
- fprintf (stderr, "Error: listen() failed: %s\n",
- strerror (errno));
- close (sock);
- return 1;
- }
+ memset (&addr, 0, sizeof (addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons (25025);
+ addr.sin_addr = *(struct in_addr *) hostinfo->h_addr;
+ err = bind (sock, (struct sockaddr *) &addr, sizeof (addr));
+ if (err) {
+ fprintf (stderr, "Error: bind() failed: %s\n",
+ strerror (errno));
+ close (sock);
+ return 1;
+ }
- if (background) {
- int pid = fork ();
- if (pid > 0) {
- printf ("smtp_dummy_pid='%d'\n", pid);
- fflush (stdout);
- close (sock);
- return 0;
- }
- if (pid < 0) {
- fprintf (stderr, "Error: fork() failed: %s\n",
- strerror (errno));
- close (sock);
- return 1;
- }
- /* Reached if pid == 0 (the child process). */
- /* Close stdout so that the one interested in pid value will
- also get EOF. */
- close (STDOUT_FILENO);
- /* dup2() will re-reserve fd of stdout (1) (opportunistically),
- in case fd of stderr (2) is open. If that was not open we
- don't care fd of stdout (1) either. */
- dup2 (STDERR_FILENO, STDOUT_FILENO);
+ err = listen (sock, 1);
+ if (err) {
+ fprintf (stderr, "Error: listen() failed: %s\n",
+ strerror (errno));
+ close (sock);
+ return 1;
+ }
- /* This process is now out of reach of shell's job control.
- To resolve the rare but possible condition where this
- "daemon" is started but never connected this process will
- (only) have 30 seconds to exist. */
- alarm (30);
+ if (background) {
+ int pid = fork ();
+ if (pid > 0) {
+ printf ("smtp_dummy_pid='%d'\n", pid);
+ fflush (stdout);
+ close (sock);
+ return 0;
}
-
- peer_addr_len = sizeof (peer_addr);
- peer = accept (sock, (struct sockaddr *) &peer_addr, &peer_addr_len);
- if (peer == -1) {
- fprintf (stderr, "Error: accept() failed: %s\n",
- strerror (errno));
- return 1;
+ if (pid < 0) {
+ fprintf (stderr, "Error: fork() failed: %s\n",
+ strerror (errno));
+ close (sock);
+ return 1;
}
+ /* Reached if pid == 0 (the child process). */
+ /* Close stdout so that the one interested in pid value will
+ * also get EOF. */
+ close (STDOUT_FILENO);
+ /* dup2() will re-reserve fd of stdout (1) (opportunistically),
+ * in case fd of stderr (2) is open. If that was not open we
+ * don't care fd of stdout (1) either. */
+ dup2 (STDERR_FILENO, STDOUT_FILENO);
- peer_file = fdopen (peer, "w+");
- if (peer_file == NULL) {
- fprintf (stderr, "Error: fdopen() failed: %s\n",
- strerror (errno));
- return 1;
- }
+ /* This process is now out of reach of shell's job control.
+ * To resolve the rare but possible condition where this
+ * "daemon" is started but never connected this process will
+ * (only) have 30 seconds to exist. */
+ alarm (30);
+ }
- do_smtp_to_file (peer_file, output);
+ peer_addr_len = sizeof (peer_addr);
+ peer = accept (sock, (struct sockaddr *) &peer_addr, &peer_addr_len);
+ if (peer == -1) {
+ fprintf (stderr, "Error: accept() failed: %s\n",
+ strerror (errno));
+ return 1;
+ }
- fclose (output);
- fclose (peer_file);
- close (sock);
+ peer_file = fdopen (peer, "w+");
+ if (peer_file == NULL) {
+ fprintf (stderr, "Error: fdopen() failed: %s\n",
+ strerror (errno));
+ return 1;
+ }
+
+ do_smtp_to_file (peer_file, output);
+
+ fclose (output);
+ fclose (peer_file);
+ close (sock);
- return 0;
+ return 0;
}