$(srcdir)/rcfile_y.c: $(srcdir)/rcfile_y.y
parser = $(srcdir)/rcfile_l.l $(srcdir)/rcfile_y.y
-headers = $(srcdir)/fetchmail.h $(srcdir)/smtp.h \
+headers = $(srcdir)/fetchmail.h $(srcdir)/socket.h $(srcdir)/smtp.h \
$(srcdir)/mx.h $(srcdir)/md5.h $(srcdir)/md5global.h
extra = $(srcdir)/alloca.c $(srcdir)/getopt.[ch] $(srcdir)/getopt1.c \
$(srcdir)/strcasecmp.c
pl 1.9.8 (Mon Nov 4 12:28:25 EST 1996):
* Don't append spurious NUL to the headers, qmail actually notices it.
-* Full dynamic buffering on all socket streams.
* Fail cleanly, instead of core-dumping, on mail lacking an RFC822 From line.
pl 1.9.7 (Fri Nov 1 10:02:34 EST 1996):
#include <netinet/in.h> /* must be included before "socket.h".*/
#include <netdb.h>
#endif /* KERBEROS_V4 */
+#include "socket.h"
#include "fetchmail.h"
#include "smtp.h"
/* 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 = Socket(ctl->smtphost, SMTP_PORT)) == (FILE *)NULL)
return((FILE *)NULL);
else if (SMTP_ok(ctl->smtp_sockfp, NULL) != SM_OK
|| SMTP_helo(ctl->smtp_sockfp, ctl->servername) != SM_OK)
return(ctl->smtp_sockfp);
}
-static int strip_gets(buf, len, sockfp)
-/* get a line of input, stripping out \r and \n */
-char *buf;
-int len;
-FILE *sockfp;
-{
- if (fgets(buf, len, sockfp) == (char *)NULL)
- return(-1);
- else
- {
- char *sp, *tp;
-
- for (tp = sp = buf; *sp; sp++)
- if (*sp != '\r' && *sp != '\n')
- *tp++ = *sp;
- *tp++ = '\0';
-
- return(strlen(buf));
- }
-}
-
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 */
oldlen = 0;
while (delimited || len > 0)
{
- char *sp, *tp;
-
- if (fgets(buf,sizeof(buf),sockfp) == (char *)NULL)
+ if ((n = SockGets(buf,sizeof(buf),sockfp)) < 0)
return(PS_SOCKET);
vtalarm(ctl->timeout);
- for (tp = sp = buf; *sp; sp++)
- if (*sp != '\r' && *sp != '\n')
- *tp++ = *sp;
- *tp++ = '\0';
-
/* write the message size dots */
- if ((n = strlen(buf)) > 0)
+ if (n > 0)
{
sizeticker += n;
while (sizeticker >= SIZETICKER)
if (!lines)
{
oldlen = strlen(bufp);
- headers = malloc(oldlen + 1);
- if (headers == NULL)
- return(PS_SYNTAX);
+ headers = xmalloc(oldlen + 1);
(void) strcpy(headers, bufp);
bufp = headers;
}
* We deal with RFC822 continuation lines here.
* Replace previous '\n' with '\r' so nxtaddr
* and reply_hack will be able to see past it.
- * (We know this is safe because we stripped
+ * (We know this is safe because SocketGets stripped
* out all carriage returns in the read loop above
* and we haven't reintroduced any since then.)
* We'll undo this before writing the header.
newlen = oldlen + strlen(bufp);
headers = realloc(headers, newlen + 1);
if (headers == NULL)
- return(PS_SYNTAX);
+ return(PS_IOERR);
strcpy(headers + oldlen, bufp);
bufp = headers + oldlen;
oldlen = newlen;
/*
* We go through this in order to be able to handle very
- * long lists of users and (re)implement %s.
+ * long lists of users and (re
+)implement %s.
*/
for (idp = xmit_names; idp; idp = idp->next)
nlocals++;
if (ctl->mda[0])
n = write(mboxfd,headers,oldlen);
else
- n = fwrite(headers, sizeof(char), oldlen, sinkfp);
+ n = SockWrite(headers, oldlen, sinkfp);
if (n < 0)
{
/* SMTP byte-stuffing */
if (*bufp == '.' && ctl->mda[0] == 0)
- fwrite(".", sizeof(char), 1, sinkfp);
+ SockWrite(".", 1, sinkfp);
/* replace all LFs with CR-LF in the line */
if (!ctl->mda[0])
if (ctl->mda[0])
n = write(mboxfd,bufp,strlen(bufp));
else
- n = fwrite(bufp, sizeof(char), strlen(bufp), sinkfp);
+ n = SockWrite(bufp, strlen(bufp), sinkfp);
if (!ctl->mda[0])
free(bufp);
lines++;
}
- /*
- * Required by Standard C and the Linux stdio library,
- * which wants a seek between read and write operations on a
- * read/write stream. Without this we got weird lossage
- * trying to issue delete commands after reading a long message.
- */
- fseek(sockfp, 0L, SEEK_CUR);
-
if (ctl->mda[0])
{
/* close the delivery pipe, we'll reopen before next message */
FILE *sockfp;
/* open a socket to the mail server */
- if ((sockfp = sockopen(ctl->servername,
- ctl->port ? ctl->port : protocol->port)) == (FILE *)NULL)
+ if ((sockfp = Socket(ctl->servername,
+ ctl->port ? ctl->port : protocol->port))<0)
{
perror("fetchmail, connecting to host");
ok = PS_SOCKET;
vtalarm(ctl->timeout);
if (ok != 0)
goto cleanUp;
- delete_uid(&ctl->newsaved, num);
}
else if (outlevel > O_SILENT)
+ {
+ /* nuke it from the unseen-messages list */
+ delete_uid(&ctl->newsaved, num);
fprintf(stderr, " not flushed\n");
+ }
}
/* remove all messages flagged for deletion */
}
if (ok==PS_SOCKET || ok==PS_AUTHFAIL || ok==PS_SYNTAX || ok==PS_IOERR
|| ok==PS_ERROR || ok==PS_PROTOCOL || ok==PS_SMTP)
- fprintf(stderr, "error while talking to %s\n", ctl->servername);
+ fprintf(stderr, " error while talking to %s\n", ctl->servername);
closeUp:
signal(SIGVTALRM, sigsave);
va_end(ap);
strcat(buf, "\r\n");
- fputs(buf, sockfp); fseek(sockfp, 0L, SEEK_CUR);
+ SockWrite(buf, strlen(buf), sockfp);
if (outlevel == O_VERBOSE)
{
va_end(ap);
strcat(buf, "\r\n");
- fputs(buf, sockfp); fseek(sockfp, 0L, SEEK_CUR);
+ SockWrite(buf, strlen(buf), sockfp);
if (outlevel == O_VERBOSE)
{
char *cp;
int closemailpipe(int);
int daemonize(const char *, void (*)(int));
-FILE *sockopen(char *, int);
-
int prc_parse_file(const char *);
int prc_filecheck(const char *);
#if defined(STDC_HEADERS)
#include <stdlib.h>
#endif
+#include "socket.h"
#include "fetchmail.h"
static int count, seen, recent, unseen;
seen = 0;
do {
- if (fgets(buf, sizeof(buf), sockfp) == (char *)NULL)
+ if (SockGets(buf, sizeof(buf), sockfp) < 0)
return(PS_SOCKET);
if (outlevel == O_VERBOSE)
- fprintf(stderr,"%s",buf);
+ fprintf(stderr,"%s\n",buf);
/* interpret untagged status responses */
if (strstr(buf, "EXISTS"))
char buf [POPBUFSIZE+1];
gen_send(sockfp, "FETCH 1:%d RFC822.SIZE", count);
- while (fgets(buf, sizeof(buf), sockfp) != (char *)NULL)
+ while (SockGets(buf, sizeof(buf), sockfp) >= 0)
{
int num, size;
else
sizes[num - 1] = -1;
}
- fseek(sockfp, 0L, SEEK_CUR);
return(0);
}
/* looking for FETCH response */
do {
- if (fgets(buf, sizeof(buf), sockfp) == (char *)NULL)
+ if (SockGets(buf, sizeof(buf), sockfp) < 0)
return(PS_SOCKET);
} while
(sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
- fseek(sockfp, 0L, SEEK_CUR);
if (num != number)
return(PS_ERROR);
{
char buf [POPBUFSIZE+1];
- if (fgets(buf, sizeof(buf), sockfp) == (char *)NULL)
+ if (SockGets(buf, sizeof(buf), sockfp) < 0)
return(PS_SOCKET);
else
- {
- fseek(sockfp, 0L, SEEK_CUR);
return(0);
- }
}
static int imap_delete(sockfp, ctl, number)
#if defined(STDC_HEADERS)
#include <stdlib.h>
#endif
+#include "socket.h"
#include "fetchmail.h"
static int pound_arg, equal_arg;
char buf [POPBUFSIZE+1];
pound_arg = equal_arg = -1;
- if (fgets(buf, sizeof(buf), sockfp) != (char *)NULL) {
+ if (SockGets(buf, sizeof(buf), sockfp) >= 0) {
if (outlevel == O_VERBOSE)
- fprintf(stderr,"%s",buf);
+ fprintf(stderr,"%s\n",buf);
if (buf[0] == '+')
ok = 0;
#include <stdlib.h>
#endif
+#include "socket.h"
#include "fetchmail.h"
#define PROTOCOL_ERROR {fputs("fetchmail: protocol error\n", stderr); return(PS_ERROR);}
char buf [POPBUFSIZE+1];
char *bufp;
- if (fgets(buf, sizeof(buf), sockfp) != (char *)NULL) {
+ if (SockGets(buf, sizeof(buf), sockfp) >= 0) {
if (outlevel == O_VERBOSE)
- fprintf(stderr,"%s",buf);
+ fprintf(stderr,"%s\n",buf);
bufp = buf;
if (*bufp == '+' || *bufp == '-')
int num;
*newp = 0;
- while (fgets(buf, sizeof(buf), sockfp) != (char *)NULL)
+ while (SockGets(buf, sizeof(buf), sockfp) >= 0)
{
if (outlevel == O_VERBOSE)
fprintf(stderr,"%s\n",buf);
if (!uid_in_list(&ctl->oldsaved, id))
(*newp)++;
}
- fseek(sockfp, 0L, SEEK_CUR);
}
}
}
{
char buf [POPBUFSIZE+1];
- while (fgets(buf, sizeof(buf), sockfp) != (char *)NULL)
+ while (SockGets(buf, sizeof(buf), sockfp) >= 0)
{
int num, size;
else
sizes[num - 1] = -1;
}
- fseek(sockfp, 0L, SEEK_CUR);
return(0);
}
* For license terms, see the file COPYING in this directory.
*/
-#include <config.h>
#include <stdio.h>
+#include <config.h>
+#include <sys/types.h>
#include <unistd.h>
#include <string.h>
+#include "socket.h"
#include "fetchmail.h"
#include "smtp.h"
{
int ok;
- fprintf(sockfp,"HELO %s\r\n", host);
+ SockPrintf(sockfp,"HELO %s\r\n", host);
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> HELO %s\n", host);
ok = SMTP_ok(sockfp,NULL);
{
int ok;
- fprintf(sockfp,"MAIL FROM:<%s>\r\n", from);
+ SockPrintf(sockfp,"MAIL FROM:<%s>\r\n", from);
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> MAIL FROM:<%s>\n", from);
ok = SMTP_ok(sockfp,NULL);
{
int ok;
- fprintf(sockfp,"RCPT TO:<%s>\r\n", to);
+ SockPrintf(sockfp,"RCPT TO:<%s>\r\n", to);
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> RCPT TO:<%s>\n", to);
ok = SMTP_ok(sockfp,NULL);
{
int ok;
- fprintf(sockfp,"DATA\r\n");
+ SockPrintf(sockfp,"DATA\r\n");
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> DATA\n");
ok = SMTP_ok(sockfp,NULL);
{
int ok;
- fprintf(sockfp,"QUIT\r\n");
+ SockPrintf(sockfp,"QUIT\r\n");
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> QUIT\n");
ok = SMTP_ok(sockfp,NULL);
{
int ok;
- fprintf(sockfp,".\r\n");
+ SockPrintf(sockfp,".\r\n");
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP>. (EOM)\n");
ok = SMTP_ok(sockfp,NULL);
void SMTP_rset(FILE *sockfp)
/* send a "RSET" message to the SMTP listener */
{
- fprintf(sockfp,"RSET\r\n");
+ SockPrintf(sockfp,"RSET\r\n");
if (outlevel == O_VERBOSE)
fprintf(stderr, "SMTP> RSET\n");
}
int ok;
char buf[SMTPBUFSIZE];
- if (fgets(buf, sizeof(buf)-1, sockfp) != (char *)NULL) {
+ if ((ok = SockGets(buf, sizeof(buf)-1, sockfp)) > 0) {
+ buf[ok] = '\0';
if (outlevel == O_VERBOSE)
- {
- char *sp, *tp;
-
- for (tp = sp = buf; *sp; sp++)
- if (*sp != '\r')
- *tp++ = *sp;
- *tp++ = '\0';
fprintf(stderr, "SMTP< %s", buf);
- }
if (argbuf)
strcpy(argbuf,buf);
if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3')
#include <config.h>
#include <stdio.h>
+#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#if defined(STDC_HEADERS)
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
+#if defined(HAVE_STDARG_H)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include "socket.h"
#ifndef INADDR_NONE
#ifdef INADDR_BROADCAST
#endif
#endif
-#define INTERNAL_BUFSIZE 2048
-
-FILE *sockopen(host, clientPort)
+FILE *Socket(host, clientPort)
char *host;
int clientPort;
{
unsigned long inaddr;
struct sockaddr_in ad;
struct hostent *hp;
- FILE *sockfp;
-
+
memset(&ad, 0, sizeof(ad));
ad.sin_family = AF_INET;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
return (FILE *)NULL;
-
if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0)
{
close(sock);
return (FILE *)NULL;
}
+ return fdopen(sock, "r+");
+}
+
+
+#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, strlen(buf), sockfp);
+
+}
+
+/*
+ * 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
+ *
+ */
+
+int SockWrite(buf,len,sockfp)
+char *buf;
+int len;
+FILE *sockfp;
+{
+ int n, wrlen = 0;
+
+ while (len)
+ {
+ n = write(fileno(sockfp), buf, len);
+ if (n <= 0)
+ return -1;
+ len -= n;
+ wrlen += n;
+ buf += n;
+ }
+ return wrlen;
+}
- sockfp = fdopen(sock, "r+");
- setvbuf(sockfp, NULL, _IOLBF, INTERNAL_BUFSIZE);
- return sockfp;
+int SockGets(buf, len, sockfp)
+char *buf;
+int len;
+FILE *sockfp;
+{
+ int rdlen = 0;
+
+ while (--len)
+ {
+ if (read(fileno(sockfp), buf, 1) != 1)
+ return -1;
+ else
+ rdlen++;
+ if (*buf == '\n')
+ break;
+ if (*buf != '\r') /* remove all CRs */
+ buf++;
+ }
+ *buf = 0;
+ return rdlen;
}
/* socket.c ends here */
#ifndef SOCKET__
#define SOCKET__
-#ifndef INADDR_NONE
-#ifdef INADDR_BROADCAST
-#define INADDR_NONE INADDR_BROADCAST
-#else
-#define INADDR_NONE -1
-#endif
-#endif
-
#if defined(HAVE_PROTOTYPES)
/*
Create a new client socket
-returns < 0 on error
+returns (FILE *)NULL on error
*/
-int Socket(char *host, int clientPort);
+FILE *Socket(char *host, int clientPort);
/*
Get a string terminated by an '\n', delete any '\r' and the '\n'.
the length of the buffer (including the trailing \0)
returns 0 for success.
*/
-int SockGets(int socket, char *buf, int len);
-
-/*
-Send a nul terminated string to the socket, followed by
-a CR-LF. Returns 0 for success.
-*/
-int SockPuts(int socket, char *buf);
+int SockGets(char *buf, int len, FILE *sockfp);
/*
Write a chunk of bytes to the socket.
Returns 0 for success.
*/
-int SockWrite(int socket, char *buf, int len);
-
-/*
-Read a chunk of bytes from the socket.
-Returns 0 for success.
-*/
-int SockRead(int socket, char *buf, int len);
+int SockWrite(char *buf, int len, FILE *sockfp);
/*
Send formatted output to the socket, followed
Returns 0 for success.
*/
#if defined(HAVE_STDARG_H)
-int SockPrintf(int socket, char *format, ...) ;
+int SockPrintf(FILE *sockfp, char *format, ...) ;
#else
int SockPrintf();
#endif
-/*
-Check socket for readability. return 0 for not readable,
->0 for readable.
-*/
-int SockStatus(int socket, int seconds);
#endif /* defined(HAVE_PROTOTYPES) */
#include <config.h>
#include <stdio.h>
-#include <string.h>
#if defined(STDC_HEADERS)
#include <stdlib.h>
+#include <string.h>
#endif
#if defined(HAVE_UNISTD_H)