savannah-cvs
[Top][All Lists]
Advanced

[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;
 }




reply via email to

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