diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2000-01-31 22:16:23 +0000 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2000-01-31 22:16:23 +0000 |
commit | 6ae74f9b7a1ec9170efa53cab74e889eb1697a50 (patch) | |
tree | 8bad50e9cdd67c73ebf90abb902b5c86adfa8ecb | |
parent | 8fa6b11990283115b0751212222ff6aaaaf81e60 (diff) | |
download | fetchmail-6ae74f9b7a1ec9170efa53cab74e889eb1697a50.tar.gz fetchmail-6ae74f9b7a1ec9170efa53cab74e889eb1697a50.tar.bz2 fetchmail-6ae74f9b7a1ec9170efa53cab74e889eb1697a50.zip |
Graceful socket closing.
svn path=/trunk/; revision=2726
-rw-r--r-- | NEWS | 14 | ||||
-rw-r--r-- | driver.c | 2 | ||||
-rw-r--r-- | fetchmail-FAQ.html | 7 | ||||
-rw-r--r-- | fetchmail.c | 2 | ||||
-rw-r--r-- | interface.c | 2 | ||||
-rw-r--r-- | sink.c | 2 | ||||
-rw-r--r-- | socket.c | 37 |
7 files changed, 51 insertions, 15 deletions
@@ -1,5 +1,11 @@ Things to do: +Scrollbars on fetchmailconf help windows (Debian bug #51770). + +Log bounced messages via syslog (Debian bug #50184). + +Notify user by mail when pop server nonexistent (Debian bug #47143). + In the SSL support, we need to add server certificate validation (In other words, does the certificate match the system we are trying to contact?). Also, add authentication of Certifying Authority (Is this @@ -15,12 +21,18 @@ package will have two security verifications instead of one... (The `lines' figures total .c, .h, .l, and .y files under version control.) +* Close down sockets using shutdown(2) and discarding read data until we + get a TCP FIN. With any luck this will squash our socket leak. +* Added Martijn Lievaart's sendmail hacks for multidrop to the contrib + directory. +* Debian buglist cleanup. + fetchmail-5.2.5 (Mon Jan 31 02:02:48 EST 2000), 18445 lines: * Fixed bugs in BSMTP generation reported by Jaap Lutz. * Make fetchmailconf better at handling backslashes in usernames and passwords. -* Jochen Hayeek's patch to handle spaces in UID usernames. +* Jochen Hayek's patch to handle spaces in UID usernames. There are 279 people on fetchmail-friends and 497 on fetchmail-announce. @@ -1537,7 +1537,7 @@ const int maxfetch; /* maximum number of messages to fetch */ /* try to clean up all streams */ release_sink(ctl); if (ctl->smtp_socket != -1) - close(ctl->smtp_socket); + SockClose(ctl->smtp_socket); if (mailserver_socket != -1) SockClose(mailserver_socket); } diff --git a/fetchmail-FAQ.html b/fetchmail-FAQ.html index 6107b829..256406c3 100644 --- a/fetchmail-FAQ.html +++ b/fetchmail-FAQ.html @@ -10,7 +10,7 @@ <table width="100%" cellpadding=0><tr> <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a> <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a> -<td width="30%" align=right>$Date: 2000/01/31 04:07:30 $ +<td width="30%" align=right>$Date: 2000/01/31 22:16:21 $ </table> <HR> <H1>Frequently Asked Questions About Fetchmail</H1> @@ -1042,6 +1042,9 @@ reliably even when the Received header omits the envelope address (which will typically be the case when the message has multiple recipients). <P> +Martijn Lievart has a more detailed recipe in the contrib subdirectory +of the fetchmail source distribution. + <hr> <h2><a name="T2">T2. How can I use fetchmail with qmail?</a></h2> @@ -2578,7 +2581,7 @@ terminate it.<p> <table width="100%" cellpadding=0><tr> <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a> <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a> -<td width="30%" align=right>$Date: 2000/01/31 04:07:30 $ +<td width="30%" align=right>$Date: 2000/01/31 22:16:21 $ </table> <P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com"><esr@snark.thyrsus.com></A></ADDRESS> diff --git a/fetchmail.c b/fetchmail.c index bbd6bfab..c6b2e72f 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -1322,7 +1322,7 @@ static void terminate_poll(int sig) if (ctl->smtp_socket != -1) { SMTP_quit(ctl->smtp_socket); - close(ctl->smtp_socket); + SockClose(ctl->smtp_socket); ctl->smtp_socket = -1; } } diff --git a/interface.c b/interface.c index 6ddbbbbf..7a485e78 100644 --- a/interface.c +++ b/interface.c @@ -174,7 +174,7 @@ static int get_ifinfo(const char *ifname, ifinfo_t *ifinfo) *sp = '/'; } if (socket_fd >= 0) - close(socket_fd); /* not checking should be safe, mode was "r" */ + SockClose(close(socket_fd)); if (stats_file) fclose(stats_file); /* not checking should be safe, mode was "r" */ return(result); @@ -51,7 +51,7 @@ static int smtp_open(struct query *ctl) /* maybe it's time to close the socket in order to force delivery */ if (NUM_NONZERO(ctl->batchlimit) && (ctl->smtp_socket != -1) && ++batchcount == ctl->batchlimit) { - close(ctl->smtp_socket); + SockClose(ctl->smtp_socket); ctl->smtp_socket = -1; batchcount = 0; } @@ -163,7 +163,7 @@ int SockOpen(const char *host, const char *service, const char *options, } if (connect(i, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) { freeaddrinfo(ai); - close(i); + SockClose(i); return -1; } #endif @@ -226,7 +226,7 @@ int SockOpen(const char *host, int clientPort, const char *options, if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) < 0) { int olderr = errno; - close(sock); + SockClose(sock); h_errno = 0; errno = olderr; return -1; @@ -272,14 +272,14 @@ int SockOpen(const char *host, int clientPort, const char *options, memcpy(&ad.sin_addr, *pptr, sizeof(struct in_addr)); if (connect(sock, (struct sockaddr *) &ad, sizeof(ad)) == 0) break; /* success */ - close(sock); + SockClose(sock); memset(&ad, 0, sizeof(ad)); ad.sin_family = AF_INET; } if(*pptr == NULL) { int olderr = errno; - close(sock); + SockClose(sock); h_errno = 0; errno = olderr; return -1; @@ -651,8 +651,9 @@ int SSLOpen(int sock, char *mycert, char *mykey, char *servercname ) #endif int SockClose(int sock) -/* close a socket (someday we may do other cleanup here) */ +/* close a socket gracefully */ { + char ch; #ifdef SSL_ENABLE SSL *ssl; @@ -662,15 +663,35 @@ int SockClose(int sock) _ssl_context[sock] = NULL; } #endif - return(close(sock)); + + /* Half-close the connection first so the other end gets notified. + * + * This stops sends but allows receives (effectively, it sends a + * TCP <FIN>). We ignore the return from this function because + * some older BSD-based implementations fail shutdown() if a TCP + * reset has been recieved. In any case, if it fails it means the + * connection is already closed anyway, so it doesn't matter. + */ + shutdown(sock, 1); + + /* If there is any data still waiting in the queue, discard it. + * Call recv() until either it returns 0 (meaning we received a FIN) + * or any error occurs. This makes sure all data sent by the other + * side is acknowledged at the TCP level. + */ + if (recv(sock, &ch, 1, MSG_PEEK) > 0) + while (recv(sock, &ch, 1, MSG_NOSIGNAL) > 0) + continue; + + /* if there's an error closing at this point, not much we can do */ + return(close(sock)); /* this is guarded */ } #ifdef MAIN /* * Use the chargen service to test input buffering directly. * You may have to uncomment the `chargen' service description in your - * inetd.conf (and then SIGHUP inetd) for this to work. - */ + * inetd.conf (and then SIGHUP inetd) for this to work. */ main() { int sock = SockOpen("localhost", 19, NULL); |