[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Savannah-cvs] administration/infra/commit_prep-log_accum sock...
From: |
Sylvain Beucler |
Subject: |
[Savannah-cvs] administration/infra/commit_prep-log_accum sock... |
Date: |
Sat, 11 Dec 2004 05:20:06 -0500 |
CVSROOT: /cvsroot/administration
Module name: administration
Branch:
Changes by: Sylvain Beucler <address@hidden> 04/12/11 09:56:45
Modified files:
infra/commit_prep-log_accum: socket-mail.c
Log message:
Changes by rao and ward
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/administration/administration/infra/commit_prep-log_accum/socket-mail.c.diff?tr1=1.1&tr2=1.2&r1=text&r2=text
Patches:
Index: administration/infra/commit_prep-log_accum/socket-mail.c
diff -u administration/infra/commit_prep-log_accum/socket-mail.c:1.1
administration/infra/commit_prep-log_accum/socket-mail.c:1.2
--- administration/infra/commit_prep-log_accum/socket-mail.c:1.1 Sat Dec
11 09:56:01 2004
+++ administration/infra/commit_prep-log_accum/socket-mail.c Sat Dec 11
09:56:45 2004
@@ -1,3 +1,27 @@
+/*
+ * socket_mail.c
+ *
+ * v1.03
+ *
+ * Simple e-mail script. Reads sender & recipient(s) as command line
+ * arguments, and takes the message headers & body on STDIN.
+ *
+ * 2004-05-26, Paul Fisher <address@hidden>
+ * 2004-05-25, Paul Fisher <address@hidden>
+ * 2004-05-12, Paul Fisher <address@hidden>
+ * 2004-04-28, Ward Vandewege <address@hidden>
+ * Based on some work by Paul Fisher <address@hidden>.
+ * Released under the GPL (for a copy, see http://www.fsf.org/licenses/gpl.txt)
+ *
+ * Arguments: sender e-mail, 1 or more recipient(s) as additional
+ * arguments
+ *
+ * Compile with:
+ * gcc -Wall socket_mail.c -o socket_mail
+ * Or for a statically compiled binary:
+ * gcc -Wall -static socket_mail.c -o socket_mail
+ */
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -11,137 +35,170 @@
#define HOST "127.0.0.1"
#define PORT 25
+#define SMTP_DATA "data\r\n"
+#define SMTP_QUIT "quit\r\n"
+
ssize_t write_all (int fd, const void *buf, size_t count)
{
- int res, remaining;
+ int res, remaining, offset;
+
+ for (remaining = count, offset = 0;
+ remaining > 0;
+ remaining -= res, offset += res)
+ {
+ res = write (fd, buf + offset, remaining);
+
+ if (res == -1)
+ return -1;
+ }
+
+ return count;
+}
- for (remaining = count; remaining > 0; remaining -= res)
+/* reads a full SMTP reply
+ returns 1 on replycode match, 0 on no match, and -1 on error */
+int read_smtp_reply (int fd, char *replycode)
+{
+ int res, remaining, offset;
+ char ch;
+ char buf[3];
+
+ /* error code must be three characters */
+ if ((!replycode) || strlen (replycode) != 3)
+ return -1;
+
+ for (remaining = 3, offset = 0;
+ remaining > 0;
+ remaining -= res)
{
- res = write (fd, buf, remaining);
+ res = read (fd, buf + offset, remaining);
+ offset += res;
+
+ if (res == -1 || res == 0)
+ return -1;
+ }
- if (res == -1)
+ /* make sure we've been able to read at least 3 characters */
+ if (offset < 3)
+ return -1;
+
+ /* continue reading from the input stream until we hit a \r\n */
+ while (1)
+ {
+ res = read (fd, &ch, 1);
+ if (res == -1 || res == 0)
return -1;
+
+ if (ch != '\r')
+ continue;
+
+ res = read (fd, &ch, 1);
+ if (res == -1 || res == 0)
+ return -1;
+
+ if (ch == '\n')
+ break;
}
-
- return count;
+
+ return (strncmp (buf, replycode, 3) == 0) ? 1 : 0;
}
-ssize_t read_all (int fd, void *buf, size_t count, char *errorcode)
+void write_rcpt (int sockfd, const char *rcpt)
{
- int res;
- int debug = 0;
- /* TODO:
- * 1. put \0 in buf at position 'res'
- * 2. make read_all behave when the server DOESN'T give the proper
return code
- */
-
- while (res != 0) {
- res = read (fd, buf, count);
-// buf[res] = '\0';
- if (debug) printf("%s\n",buf);
- if (!strncmp(buf,strstr(buf,errorcode),3)) {
- return res;
-// } else if (buf != NULL) {
-// } else {
-// printf("Bad return code: %s\n",buf);
- return 0;
- }
- }
- if (res == 0) {
- return 0;
- }
- return res;
+ char buf[400];
+
+ snprintf (buf, 400, "rcpt to: %s\r\n", rcpt);
+
+ if (write_all (sockfd, buf, strlen (buf)) < 0
+ || read_smtp_reply (sockfd, "250") != 1)
+ {
+ close (sockfd);
+ exit (1);
+ }
}
int main (int argc, char **argv)
{
- int sockfd;
+ int sockfd, i;
struct sockaddr_in addr;
- char line[500];
- int len = 0;
- int res;
- char byte_len[7];
-
- if (argc != 3 || argv[1] == NULL || argv[2] == NULL) {
- printf("%s","Need more arguments!\n");
- return 1;
- }
+ char buf[1024];
+
+ if (argc < 3) /* must have at least 3 arguments */
+ {
+ fprintf (stderr, "Usage: %s smtp-from smpt-to...\n", argv[0]);
+ return 1;
+ }
/* setup the sockaddr_in */
memset(&addr, '\0', sizeof (addr));
addr.sin_family = AF_INET;
- addr.sin_port = htons(PORT);
+ addr.sin_port = htons (PORT);
addr.sin_addr.s_addr = inet_addr (HOST);
-
+
/* create a socket */
if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- return 1;
-
+ {
+ fprintf (stderr, "Can't create a socket\n");
+ return 1;
+ }
+
/* open up a connection */
if (connect (sockfd, (struct sockaddr *) &addr,
sizeof (struct sockaddr)) < 0)
- return 1;
+ {
+ fprintf (stderr, "Can't connect to %s:%i\n", HOST, PORT);
+ return 1;
+ }
- char *buf;
- buf = (char *) malloc(1024);
+ /* Accept server welcome message */
+ if (read_smtp_reply (sockfd, "220") != 1)
+ {
+ fprintf (stderr, "Didn't receive a server welcome message\n");
+ close (sockfd);
+ return 1;
+ }
- char *errorcode;
- errorcode = (char *) malloc(strlen("220")+1);
- strcpy(errorcode,"220");
- if (!read_all (sockfd, buf,100,errorcode)) {
- printf("%s","NOK\n");
- }
+ /* send off the "mail from" and get a response back */
+ snprintf (buf, 1024, "mail from: %s\r\n", argv[1]);
+ if (write_all (sockfd, buf, strlen (buf)) < 0
+ || read_smtp_reply (sockfd, "250") != 1)
+ {
+ close (sockfd);
+ return 1;
+ }
- /* write mail from */
- char *wrbuf;
- int maxlen = strlen(argv[1]);
- if (maxlen < strlen(argv[2])) maxlen = strlen(argv[2]);
- wrbuf = (char *) malloc (maxlen+1); // Make sure to account for the \0
char at the end of the string
- strcpy(wrbuf,"mail from: ");
- strcat(wrbuf,argv[1]);
- strcat(wrbuf,"\r\n");
- if (write_all (sockfd, wrbuf, strlen (wrbuf)) < 0)
- return 1;
-
- strcpy(errorcode,"250");
- if (!read_all (sockfd, buf,100,errorcode)) {
- printf("%s","NOK\n");
- }
+ /* write out all the rcpts of the message */
+ for (i = 2; i < argc; i++)
+ write_rcpt (sockfd, argv[i]); /* write_rcpt will exit() out, if needed */
- strcpy(wrbuf,"rcpt to: ");
- strcat(wrbuf,argv[2]); // TODO: add code to allow multiple recipients
(comma-separated)
- strcat(wrbuf,"\r\n");
- if (write_all (sockfd, wrbuf, strlen (wrbuf)) < 0)
- return 1;
-
- strcpy(errorcode,"250");
- if (!read_all (sockfd, buf,100,errorcode)) {
- printf("%s","NOK\n");
+ if (write_all (sockfd, SMTP_DATA, strlen (SMTP_DATA)) < 0
+ || read_smtp_reply (sockfd, "354") != 1)
+ {
+ close (sockfd);
+ return 1;
+ }
+
+ /* read message from STDIN.
+ no dot-stuffing or other modifications are made to the input stream */
+ while (fgets (buf, 1024, stdin))
+ if (write_all (sockfd, buf, strlen (buf)) < 0)
+ {
+ close (sockfd);
+ return 1;
}
- strcpy(wrbuf,"data\r\n");
- if (write_all (sockfd, wrbuf, strlen (wrbuf)) < 0)
- return 1;
-
- strcpy(errorcode,"354");
- if (!read_all (sockfd, buf,100,errorcode)) {
- printf("%s%s\n","Problem - ",buf);
- }
+ /* hopefully we'll get a 250 back after the DATA portion */
+ if (read_smtp_reply (sockfd, "250") != 1)
+ {
+ close (sockfd);
+ return 1;
+ }
- // Read message from STDIN!
- char input[1024];
- while (feof(stdin) == 0) {
- fgets(input, 1024, stdin);
- strcpy(wrbuf,input);
- if (write_all (sockfd, wrbuf, strlen (wrbuf)) < 0) return 1;
- if (!strcmp(input,".\n")) break; // We end with a line with a
single dot...
- }
-
- strcpy(errorcode,"250");
- if (!read_all (sockfd, buf,100,errorcode)) {
- printf("%s","NOK\n");
- }
+ /* everything went fine. tell the server that we're ending */
+ write_all (sockfd, SMTP_QUIT, strlen (SMTP_QUIT));
+
/* close up the socket and exit */
close (sockfd);
+
return 0;
}