]> Pileus Git - ~andy/fetchmail/commitdiff
Drop back to using SockGets/SockWrite.
authorEric S. Raymond <esr@thyrsus.com>
Tue, 24 Dec 1996 19:18:02 +0000 (19:18 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Tue, 24 Dec 1996 19:18:02 +0000 (19:18 -0000)
svn path=/trunk/; revision=683

driver.c
imap.c
pop2.c
pop3.c
smtp.c
socket.c
socket.h

index 633f29afc8be750ca4de1d0a1dad7e2c1e82aab8..49d97c980ec1c537ed099bc88057d59e01adb861 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -42,6 +42,7 @@
 #endif /* KERBEROS_V4 */
 #include  "socket.h"
 #include  "fetchmail.h"
+#include  "socket.h"
 #include  "smtp.h"
 
 /* BSD portability hack...I know, this is an ugly place to put it */
@@ -279,7 +280,7 @@ static FILE *smtp_open(struct query *ctl)
     /* if no socket to this host is already set up, try to open one */
     if (ctl->smtp_sockfp == (FILE *)NULL)
     {
-       if ((ctl->smtp_sockfp = sockopen(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
+       if ((ctl->smtp_sockfp = SockOpen(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
            return((FILE *)NULL);
        else if (SMTP_ok(ctl->smtp_sockfp) != SM_OK
                 || SMTP_helo(ctl->smtp_sockfp, ctl->servernames->id) != SM_OK)
@@ -292,26 +293,6 @@ static FILE *smtp_open(struct query *ctl)
     return(ctl->smtp_sockfp);
 }
 
-static int SockGets(char *buf, int len, FILE *sockfp)
-/* get a LF-terminated line, removing \r characters */
-{
-    int rdlen = 0;
-
-    while (--len)
-    {
-        if ((*buf = fgetc(sockfp)) == EOF)
-            return -1;
-        else
-           rdlen++;
-        if (*buf == '\n')
-            break;
-        if (*buf != '\r') /* remove all CRs */
-            buf++;
-    }
-    *buf = 0;
-    return rdlen;
-}
-
 static int gen_readmsg (sockfp, len, delimited, ctl)
 /* read message content and ship to SMTP or MDA */
 FILE *sockfp;          /* to which the server is connected */
@@ -337,10 +318,17 @@ struct query *ctl;        /* query control record */
     oldlen = 0;
     while (delimited || len > 0)
     {
-       if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
+       if (!SockGets(buf,sizeof(buf),sockfp))
            return(PS_SOCKET);
+       n = strlen(buf);
        vtalarm(ctl->timeout);
 
+       /* squeeze out all carriage returns */
+       for (fromhdr = tohdr = buf; *fromhdr; fromhdr++)
+           if (*fromhdr != '\r' && *fromhdr != '\n')
+               *tohdr++ = *fromhdr;
+       *tohdr = '\0';
+
        /* write the message size dots */
        if (n > 0)
        {
@@ -664,8 +652,10 @@ struct query *ctl; /* query control record */
 
            /* write all the headers */
            n = 0;
-           if (sinkfp)
+           if (ctl->mda[0])
                n = fwrite(headers, 1, oldlen, sinkfp);
+           else if (sinkfp)
+               n = SockWrite(headers, 1, oldlen, sinkfp);
 
            if (n < 0)
            {
@@ -749,8 +739,10 @@ struct query *ctl; /* query control record */
 
        /* ship out the text line */
        n = 0;
-       if (sinkfp)
+       if (ctl->mda[0])
            n = fwrite(bufp, 1, strlen(bufp), sinkfp);
+       else if (sinkfp)
+           n = SockWrite(bufp, 1, strlen(bufp), sinkfp);
 
        if (!ctl->mda[0])
            free(bufp);
@@ -902,7 +894,7 @@ const struct method *proto; /* protocol method table */
        FILE *sockfp;
 
        /* open a socket to the mail server */
-       if ((sockfp = sockopen(ctl->servernames->id,
+       if ((sockfp = SockOpen(ctl->servernames->id,
                             ctl->port ? ctl->port : protocol->port)) == NULL)
        {
            error(0, errno, "connecting to host");
@@ -1191,8 +1183,7 @@ va_dcl
     va_end(ap);
 
     strcat(buf, "\r\n");
-    fputs(buf, sockfp);
-    fflush(sockfp);    /* sockfp should be linebuffered, but let's be sure */
+    SockWrite(buf, 1, strlen(buf), sockfp);
 
     if (outlevel == O_VERBOSE)
     {
@@ -1234,8 +1225,7 @@ va_dcl
     va_end(ap);
 
     strcat(buf, "\r\n");
-    fputs(buf, sockfp);
-    fflush(sockfp);    /* sockfp should be linebuffered, but let's be sure */
+    SockWrite(buf, 1, strlen(buf), sockfp);
 
     if (outlevel == O_VERBOSE)
     {
diff --git a/imap.c b/imap.c
index 944c246bc846806f6e8fb5e970884094447b5457..f9fdbbaa9f5f2463663efa9416367ae4be748cf3 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -14,6 +14,7 @@
 #include  <stdlib.h>
 #endif
 #include  "fetchmail.h"
+#include  "socket.h"
 
 static int count, seen, recent, unseen, imap4;
 
@@ -24,7 +25,7 @@ int imap_ok (FILE *sockfp,  char *argbuf)
 
     seen = 0;
     do {
-       if (!fgets(buf, sizeof(buf), sockfp))
+       if (!SockGets(buf, sizeof(buf), sockfp))
            return(PS_SOCKET);
        if (buf[strlen(buf)-1] == '\n')
            buf[strlen(buf)-1] = '\0';
@@ -121,7 +122,7 @@ static int imap_getsizes(FILE *sockfp, int count, int *sizes)
     char buf [POPBUFSIZE+1];
 
     gen_send(sockfp, "FETCH 1:%d RFC822.SIZE", count);
-    while (fgets(buf, sizeof(buf), sockfp))
+    while (SockGets(buf, sizeof(buf), sockfp))
     {
        int num, size;
 
@@ -172,7 +173,7 @@ static int imap_fetch(FILE *sockfp, int number, int *lenp)
 
     /* looking for FETCH response */
     do {
-       if (!fgets(buf, sizeof(buf), sockfp))
+       if (!SockGets(buf, sizeof(buf), sockfp))
            return(PS_SOCKET);
     } while
            (sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
@@ -188,7 +189,7 @@ static int imap_trail(FILE *sockfp, struct query *ctl, int number)
 {
     char buf [POPBUFSIZE+1];
 
-    if (!fgets(buf, sizeof(buf), sockfp))
+    if (!SockGets(buf, sizeof(buf), sockfp))
        return(PS_SOCKET);
     else
        return(0);
diff --git a/pop2.c b/pop2.c
index 4b389f20cd64adb0395524ac30e61e6e529e9374..955e634ee51841769bf4edeae8424df63bc6a6dd 100644 (file)
--- a/pop2.c
+++ b/pop2.c
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #endif
 #include  "fetchmail.h"
+#include  "socket.h"
 
 static int pound_arg, equal_arg;
 
@@ -22,7 +23,7 @@ int pop2_ok (FILE *sockfp, char *argbuf)
     char buf [POPBUFSIZE+1];
 
     pound_arg = equal_arg = -1;
-    if (fgets(buf, sizeof(buf), sockfp)) {
+    if (SockGets(buf, sizeof(buf), sockfp)) {
        if (buf[strlen(buf)-1] == '\n')
            buf[strlen(buf)-1] = '\0';
        if (buf[strlen(buf)-1] == '\r')
diff --git a/pop3.c b/pop3.c
index 3ee5489befd1273c961cc1a1b4b58589ef84e42c..0238fc3573bf19e5c380af2b092871d36778af02 100644 (file)
--- a/pop3.c
+++ b/pop3.c
@@ -17,6 +17,7 @@
 #endif
  
 #include  "fetchmail.h"
+#include  "socket.h"
 
 #define PROTOCOL_ERROR {error(0, 0, "protocol error"); return(PS_ERROR);}
 
@@ -29,7 +30,7 @@ int pop3_ok (FILE *sockfp, char *argbuf)
     char buf [POPBUFSIZE+1];
     char *bufp;
 
-    if (fgets(buf, sizeof(buf), sockfp)) {
+    if (SockGets(buf, sizeof(buf), sockfp)) {
        if (buf[strlen(buf)-1] == '\n')
            buf[strlen(buf)-1] = '\0';
        if (buf[strlen(buf)-1] == '\r')
@@ -168,7 +169,7 @@ static int pop3_getrange(FILE *sockfp, struct query *ctl, int*countp, int*newp)
                int     num;
 
                *newp = 0;
-               while (fgets(buf, sizeof(buf), sockfp))
+               while (SockGets(buf, sizeof(buf), sockfp))
                {
                    if (buf[strlen(buf)-1] == '\n')
                        buf[strlen(buf)-1] = '\0';
@@ -205,7 +206,7 @@ static int pop3_getsizes(FILE *sockfp, int count, int *sizes)
     {
        char buf [POPBUFSIZE+1];
 
-       while (fgets(buf, sizeof(buf), sockfp))
+       while (SockGets(buf, sizeof(buf), sockfp))
        {
            int num, size;
 
diff --git a/smtp.c b/smtp.c
index cee1841bbc365505ffa2f308e3289b38701b9fc7..a5be092779cde4c5d15985ae2c037dfd2b8f2f8c 100644 (file)
--- a/smtp.c
+++ b/smtp.c
@@ -14,6 +14,7 @@
 #include <unistd.h>
 #include <string.h>
 #include "fetchmail.h"
+#include "socket.h"
 #include "smtp.h"
 
 int smtp_response;     /* numeric value of SMTP response code */
@@ -23,7 +24,7 @@ int SMTP_helo(FILE *sockfp,char *host)
 {
   int ok;
 
-  fprintf(sockfp,"HELO %s\r\n", host);
+  SockPrintf(sockfp,"HELO %s\r\n", host);
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP> HELO %s", host);
   ok = SMTP_ok(sockfp);
@@ -35,7 +36,7 @@ int SMTP_from(FILE *sockfp, char *from)
 {
   int ok;
 
-  fprintf(sockfp,"MAIL FROM:<%s>\r\n", from);
+  SockPrintf(sockfp,"MAIL FROM:<%s>\r\n", from);
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP> MAIL FROM:<%s>", from);
   ok = SMTP_ok(sockfp);
@@ -47,7 +48,7 @@ int SMTP_rcpt(FILE *sockfp, char *to)
 {
   int ok;
 
-  fprintf(sockfp,"RCPT TO:<%s>\r\n", to);
+  SockPrintf(sockfp,"RCPT TO:<%s>\r\n", to);
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP> RCPT TO:<%s>", to);
   ok = SMTP_ok(sockfp);
@@ -59,7 +60,7 @@ int SMTP_data(FILE *sockfp)
 {
   int ok;
 
-  fprintf(sockfp,"DATA\r\n");
+  SockPrintf(sockfp,"DATA\r\n");
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP> DATA");
   ok = SMTP_ok(sockfp);
@@ -71,7 +72,7 @@ int SMTP_quit(FILE *sockfp)
 {
   int ok;
 
-  fprintf(sockfp,"QUIT\r\n");
+  SockPrintf(sockfp,"QUIT\r\n");
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP> QUIT");
   ok = SMTP_ok(sockfp);
@@ -83,7 +84,7 @@ int SMTP_eom(FILE *sockfp)
 {
   int ok;
 
-  fprintf(sockfp,".\r\n");
+  SockPrintf(sockfp,".\r\n");
   if (outlevel == O_VERBOSE)
       error(0, 0, "SMTP>. (EOM)");
   ok = SMTP_ok(sockfp);
@@ -95,7 +96,7 @@ int SMTP_ok(FILE *sockfp)
 {
     char buf[SMTPBUFSIZE], *ip;
   
-    while ((ip = fgets(buf, sizeof(buf)-1, sockfp)))
+    while ((ip = SockGets(buf, sizeof(buf)-1, sockfp)))
     {
        int  n = strlen(ip);
 
index 39b9f8468a39d527bc665ae8a88262b43c930b3c..16974b6918544ec34e083774407420398c1bf24b 100644 (file)
--- a/socket.c
+++ b/socket.c
 #endif
 #endif
 
-/*
- * Size of buffer for internal buffering read function 
- * don't increase beyond the maximum atomic read/write size for
- * your sockets, or you'll take a potentially huge performance hit
- */
-#define  INTERNAL_BUFSIZE      2048
-
-FILE *sockopen(char *host, int clientPort)
+FILE *SockOpen(char *host, int clientPort)
 {
     int sock;
     unsigned long inaddr;
     struct sockaddr_in ad;
     struct hostent *hp;
-    FILE *fp;
-
+    
     memset(&ad, 0, sizeof(ad));
     ad.sin_family = AF_INET;
 
@@ -72,26 +64,89 @@ FILE *sockopen(char *host, int clientPort)
        close(sock);
         return (FILE *)NULL;
     }
-    fp = fdopen(sock, "r+");
+    return fdopen(sock, "r+");
+}
 
-    /* the point of all this mishigoss ... dynamic per-stream buffering */
-    setvbuf(fp, NULL, _IOLBF, INTERNAL_BUFSIZE);
 
-    return(fp);
+#if defined(HAVE_STDARG_H)
+int SockPrintf(FILE *sockfp, char* format, ...)
+{
+#else
+int SockPrintf(sockfp,format,va_alist)
+FILE *sockfp;
+char *format;
+va_dcl {
+#endif
+
+    va_list ap;
+    char buf[8192];
+
+#if defined(HAVE_STDARG_H)
+    va_start(ap, format) ;
+#else
+    va_start(ap);
+#endif
+    vsprintf(buf, format, ap);
+    va_end(ap);
+    return SockWrite(buf, 1, strlen(buf), sockfp);
+
 }
 
-#ifdef MAIN
 /*
- * Use the chargen service to test buffering directly.
+ * FIXME: This needs to be recoded to use stdio, if that's possible.
+ *
+ * If you think these functions are too slow and inefficient, you're
+ * absolutely right.  I wish I could figure out what to do about it.
+ * The ancestral popclient used static buffering here to cut down on the
+ * number of read(2) calls, but we can't do that because we can have
+ * two or more sockets open at a time.
+ *
+ * The right thing to do would be to use stdio for internal per-socket
+ * buffering here (which is why Socket() returns a file pointer) but 
+ * this causes mysterious lossage.  In case someone ever finds a way
+ * around this, a note on Carl Harris's original implementation said:
+ *
+ * Size of buffer for internal buffering read function 
+ * don't increase beyond the maximum atomic read/write size for
+ * your sockets, or you'll take a potentially huge performance hit
+ *
+ * #define  INTERNAL_BUFSIZE   2048
+ *
  */
-main()
+
+int SockWrite(char *buf, int size, int len, FILE *sockfp)
 {
-    FILE       *fp = sockopen("localhost", 19);
-    char       buf[80];
+    int n, wrlen = 0;
+
+    len *= size;
+    while (len)
+    {
+        n = write(fileno(sockfp), buf, len);
+        if (n <= 0)
+            return -1;
+        len -= n;
+       wrlen += n;
+       buf += n;
+    }
+    return wrlen;
+}
 
-    while (fgets(buf, sizeof(buf)-1, fp))
-       fputs(buf, stdout);
+char *SockGets(char *buf, int len, FILE *sockfp)
+{
+    int rdlen = 0;
+    char *cp = buf;
+
+    while (--len)
+    {
+        if (read(fileno(sockfp), cp, 1) != 1)
+            return((char *)NULL);
+        else
+           rdlen++;
+        if (*cp++ == '\n')
+            break;
+    }
+    *cp = 0;
+    return buf;
 }
-#endif /* MAIN */
 
 /* socket.c ends here */
index 11d9e29676e2c59b239a8b5726acb6598ac2bc78..6c93c6348e68d8cdfa2187f47bac1f9ce13ce188 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -8,6 +8,30 @@
 #define SOCKET__
 
 /* Create a new client socket; returns (FILE *)NULL on error */
-FILE *sockopen(char *host, int clientPort);
+FILE *SockOpen(char *host, int clientPort);
 
+/* 
+Get a string terminated by an '\n' (matches interface of fgets).
+Pass it a valid socket, a buffer for the string, and
+the length of the buffer (including the trailing \0)
+returns buffer on success, NULL on failure. 
+*/
+char *SockGets(char *buf, int len, FILE *sockfp);
+
+/*
+Write a chunk of bytes to the socket (matches interface of fwrite).
+Returns number of bytes successfully written.
+*/
+int SockWrite(char *buf, int size, int nels, FILE *sockfp);
+
+/* 
+Send formatted output to the socket (matches interface of fprintf).
+Returns number of bytes successfully written.
+*/
+#if defined(HAVE_STDARG_H)
+int SockPrintf(FILE *sockfp, char *format, ...) ;
+#else
+int SockPrintf();
+#endif
 #endif /* SOCKET__ */