X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=transact.c;h=2b8d04f8ec15e8b5256d90f2aa5545954340d722;hb=87bcf29364c4640edb87cc2186b965d1a564d70c;hp=0f0cd35378a4c4f5f053b8db9093562e899a1d52;hpb=dbb179567dd2e850e0e8327a823d21ee311db823;p=~andy%2Ffetchmail diff --git a/transact.c b/transact.c index 0f0cd353..2b8d04f8 100644 --- a/transact.c +++ b/transact.c @@ -472,13 +472,13 @@ int readheaders(int sock, do { char *sp, *tp; - SockTimeout(sock, mytimeout); - n = SockRead(sock, buf, sizeof(buf) - 1); - - if (n == -1) { + set_timeout(mytimeout); + if ((n = SockRead(sock, buf, sizeof(buf)-1)) == -1) { + set_timeout(0); free(line); return(PS_SOCKET); } + set_timeout(0); /* * Smash out any NULs, they could wreak havoc later on. @@ -603,8 +603,9 @@ eoh: } /* check for RFC822 continuations */ - SockTimeout(sock, mytimeout); + set_timeout(mytimeout); ch = SockPeek(sock); + set_timeout(0); } while (ch == ' ' || ch == '\t'); /* continuation to next line? */ @@ -1341,6 +1342,28 @@ process_headers: return PS_SOCKET; } +/** Convenience function factored out from readbody(): + * send buffer \a buf via stuffline() and handle errors and progress. + * Store return value in \a *n, and return PS_IOERR for failure or + * PS_SUCCESS otherwise. */ +static int rb_send(struct query *ctl, char *buf, int *n) +{ + *n = stuffline(ctl, buf); + + if (*n < 0) + { + report(stdout, GT_("error writing message text\n")); + release_sink(ctl); + return(PS_IOERR); + } + else if (want_progress()) + { + fputc('*', stdout); + fflush(stdout); + } + return PS_SUCCESS; +} + int readbody(int sock, struct query *ctl, flag forward, int len) /** read and dispose of a message body presented on \a sock */ /** \param ctl query control record */ @@ -1365,16 +1388,17 @@ int readbody(int sock, struct query *ctl, flag forward, int len) */ while (protocol->delimited || len > 0) { - SockTimeout(sock, mytimeout); + set_timeout(mytimeout); /* XXX FIXME: for undelimited protocols that ship the size, such * as IMAP, we might want to use the count of remaining characters * instead of the buffer size -- not for fetchmail 6.3.X though */ - linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf)); - if (linelen == -1) + if ((linelen = SockRead(sock, inbufp, sizeof(buf)-4-(inbufp-buf)))==-1) { + set_timeout(0); release_sink(ctl); return(PS_SOCKET); } + set_timeout(0); /* write the message size dots */ if (linelen > 0) @@ -1392,7 +1416,15 @@ int readbody(int sock, struct query *ctl, flag forward, int len) * so we might end truncating messages prematurely. */ if (!protocol->delimited && linelen > len) { + /* FIXME: HACK ALERT! This \r\n is only here to make sure the + * \n\0 hunt works later on. The \n generated here was not + * part of the original message! + * The real fix will be to use buffer + length strings, + * rather than 0-terminated C strings. */ + inbufp[len++] = '\r'; + inbufp[len++] = '\n'; inbufp[len] = '\0'; + linelen = len; } len -= linelen; @@ -1427,7 +1459,7 @@ int readbody(int sock, struct query *ctl, flag forward, int len) /* ship out the text line */ if (forward && (!issoftline)) { - int n; + int n, err; inbufp = buf; /* guard against very long lines */ @@ -1435,22 +1467,31 @@ int readbody(int sock, struct query *ctl, flag forward, int len) buf[MSGBUFSIZE+2] = '\n'; buf[MSGBUFSIZE+3] = '\0'; - n = stuffline(ctl, buf); - - if (n < 0) - { - report(stdout, GT_("error writing message text\n")); - release_sink(ctl); - return(PS_IOERR); - } - else if (want_progress()) - { - fputc('*', stdout); - fflush(stdout); - } + err = rb_send(ctl, buf, &n); + if (err != PS_SUCCESS) + return err; } } + /* Flush buffer -- bug introduced by ESR on 1998-03-20 before + * release 4.4.1 when ESR did not sufficiently audit Henrik + * Storner's patch. + * Trouble reported in June 2011 by Lars Hecking, with + * text/html quoted-printable messages generated by + * Outlook/Exchange that got mutilated by fetchmail. + */ + if (forward && issoftline) + { + int n; + + /* force proper line termination */ + inbufp[0] = '\r'; + inbufp[1] = '\n'; + inbufp[2] = '\0'; + + return rb_send(ctl, buf, &n); + } + return(PS_SUCCESS); } @@ -1516,15 +1557,13 @@ int gen_recv(int sock /** socket to which server is connected */, { size_t n; int oldphase = phase; /* we don't have to be re-entrant */ - int retval; phase = SERVER_WAIT; - SockTimeout(sock, mytimeout); - retval = SockRead(sock, buf, size); - phase = oldphase; - - if (retval == -1) + set_timeout(mytimeout); + if (SockRead(sock, buf, size) == -1) { + set_timeout(0); + phase = oldphase; if(is_idletimeout()) { resetidletimeout(); @@ -1543,6 +1582,7 @@ int gen_recv(int sock /** socket to which server is connected */, buf[--n] = '\0'; if (outlevel >= O_MONITOR) report(stdout, "%s< %s\n", protocol->name, buf); + phase = oldphase; return(PS_SUCCESS); } }