diff options
| -rw-r--r-- | driver.c | 48 | ||||
| -rw-r--r-- | imap.c | 9 | ||||
| -rw-r--r-- | pop2.c | 3 | ||||
| -rw-r--r-- | pop3.c | 7 | ||||
| -rw-r--r-- | smtp.c | 15 | ||||
| -rw-r--r-- | socket.c | 99 | ||||
| -rw-r--r-- | socket.h | 26 | 
7 files changed, 140 insertions, 67 deletions
@@ -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)      { @@ -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); @@ -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') @@ -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; @@ -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); @@ -34,21 +34,13 @@  #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 */ @@ -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__ */  | 
