]> Pileus Git - ~andy/fetchmail/blobdiff - socket.c
Minor corrections.
[~andy/fetchmail] / socket.c
index 9dfa5587347e43666fc4aeb5a514c10d5f9f90e5..8c367d0c1182c90e399866e8d35cd8c4b88a84f7 100644 (file)
--- a/socket.c
+++ b/socket.c
 #include <memory.h>
 #endif /* HAVE_MEMORY_H */
 #include <sys/types.h>
+#ifndef HAVE_NET_SOCKET_H
 #include <sys/socket.h>
+#else
+#include <net/socket.h>
+#endif
 #include <netinet/in.h>
+#ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>
+#endif
 #include <netdb.h>
 #if defined(STDC_HEADERS)
 #include <stdlib.h>
 #include "fetchmail.h"
 #include "i18n.h"
 
+/* Defines to allow BeOS to play nice... */
+#ifdef __BEOS__
+static char peeked;
+#define fm_close(a)  closesocket(a)
+#define fm_write(a,b,c)  send(a,b,c,0)
+#define fm_peek(a,b,c)   recv(a,b,c,0)
+#define fm_read(a,b,c)   recv(a,b,c,0)
+#else
+#define fm_close(a)  close(a)
+#define fm_write(a,b,c)  write(a,b,c)
+#define fm_peek(a,b,c)   recv(a,b,c, MSG_PEEK)
+#define fm_read(a,b,c)   read(a,b,c)
+#endif
+
 /* We need to define h_errno only if it is not already */
 #ifndef h_errno
 
@@ -121,13 +141,12 @@ int SockCheckOpen(int fd)
 int SockOpen(const char *host, const char *service, const char *options,
             const char *plugin)
 {
-    struct addrinfo *ai, req;
+    struct addrinfo *ai, *ai0, req;
     int i;
 #if NET_SECURITY
     void *request = NULL;
     int requestlen;
 #endif /* NET_SECURITY */
-    int i;
 
 #ifdef HAVE_SOCKETPAIR
     if (plugin)
@@ -136,10 +155,10 @@ int SockOpen(const char *host, const char *service, const char *options,
     memset(&req, 0, sizeof(struct addrinfo));
     req.ai_socktype = SOCK_STREAM;
 
-    if (getaddrinfo(host, service, &req, &ai)) {
+    if (getaddrinfo(host, service, &req, &ai0)) {
        report(stderr, _("fetchmail: getaddrinfo(%s.%s)\n"), host,service);
        return -1;
-    };
+    }
 
 #if NET_SECURITY
     if (!options)
@@ -148,19 +167,36 @@ int SockOpen(const char *host, const char *service, const char *options,
        if (net_security_strtorequest((char *)options, &request, &requestlen))
            goto ret;
 
-    i = inner_connect(ai, request, requestlen, NULL, NULL, "fetchmail", NULL);
+    i = inner_connect(ai0, request, requestlen, NULL, NULL, "fetchmail", NULL);
     if (request)
        free(request);
 
  ret:
 #else /* NET_SECURITY */
-    i = inner_connect(ai, NULL, 0, NULL, NULL, "fetchmail", NULL);
+#ifdef HAVE_INNER_CONNECT
+    i = inner_connect(ai0, NULL, 0, NULL, NULL, "fetchmail", NULL);
+    if (i >= 0)
+       break;
+#else
+    i = -1;
+    for (ai = ai0; ai; ai = ai->ai_next) {
+       i = socket(ai->ai_family, ai->ai_socktype, 0);
+       if (i < 0)
+           continue;
+       if (connect(i, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0) {
+           fm_close(i);
+           i = -1;
+           continue;
+       }
+       break;
+    }
+#endif
 #endif /* NET_SECURITY */
 
-    freeaddrinfo(ai);
+    freeaddrinfo(ai0);
 
     return i;
-};
+}
 #else /* INET6_ENABLE */
 #ifndef HAVE_INET_ATON
 #ifndef  INADDR_NONE
@@ -214,7 +250,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);
+            fm_close(sock);    /* don't use SockClose, no traffic yet */
             h_errno = 0;
             errno = olderr;
             return -1;
@@ -260,19 +296,20 @@ 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);
+           fm_close(sock);     /* don't use SockClose, no traffic yet */
            memset(&ad, 0, sizeof(ad));
            ad.sin_family = AF_INET;
        }
        if(*pptr == NULL)
        {
            int olderr = errno;
-           close(sock);
+           fm_close(sock);     /* don't use SockClose, no traffic yet */
            h_errno = 0;
            errno = olderr;
            return -1;
        }
     }
+
     return(sock);
 }
 #endif /* INET6_ENABLE */
@@ -331,9 +368,9 @@ int SockWrite(int sock, char *buf, int len)
        if( NULL != ( ssl = SSLGetContext( sock ) ) )
                n = SSL_write(ssl, buf, len);
        else
-               n = write(sock, buf, len);
+               n = fm_write(sock, buf, len);
 #else
-        n = write(sock, buf, len);
+        n = fm_write(sock, buf, len);
 #endif
         if (n <= 0)
             return -1;
@@ -354,6 +391,14 @@ int SockRead(int sock, char *buf, int len)
 
     if (--len < 1)
        return(-1);
+#ifdef __BEOS__
+    if (peeked != 0){
+        (*bp) = peeked;
+        bp++;
+        len--;
+        peeked = 0;
+    }
+#endif        
     do {
        /* 
         * The reason for these gymnastics is that we want two things:
@@ -406,20 +451,27 @@ int SockRead(int sock, char *buf, int len)
                        newline = bp;
                }
        } else {
-               if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
+               if ((n = fm_peek(sock, bp, len)) <= 0)
                        return(-1);
                if ((newline = memchr(bp, '\n', n)) != NULL)
                        n = newline - bp + 1;
-               if ((n = read(sock, bp, n)) == -1)
+               if ((n = fm_read(sock, bp, n)) == -1)
                        return(-1);
        }
 #else
-       if ((n = recv(sock, bp, len, MSG_PEEK)) <= 0)
-           return(-1);
+
+#ifdef __BEOS__
+    if ((n = fm_read(sock, bp, 1)) <= 0)
+#else
+    if ((n = fm_peek(sock, bp, len)) <= 0)
+#endif
+        return (-1);
        if ((newline = memchr(bp, '\n', n)) != NULL)
            n = newline - bp + 1;
-       if ((n = read(sock, bp, n)) == -1)
+#ifndef __BEOS__
+       if ((n = fm_read(sock, bp, n)) == -1)
            return(-1);
+#endif /* __BEOS__ */
 #endif
        bp += n;
        len -= n;
@@ -463,15 +515,20 @@ int SockPeek(int sock)
                        return 0;       /* Give him a '\0' character */
                }
        } else {
-               n = recv(sock, &ch, 1, MSG_PEEK);
+               n = fm_peek(sock, &ch, 1);
        }
 #else
-       n = recv(sock, &ch, 1, MSG_PEEK);
-#endif
+
+        n = fm_peek(sock, &ch, 1);
+
+#endif /* SSL_ENABLE */
        if (n == -1)
                return -1;
-       else
-               return(ch);
+
+#ifdef __BEOS__
+    peeked = ch;
+#endif
+    return(ch);
 }
 
 #ifdef SSL_ENABLE
@@ -518,10 +575,10 @@ int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx )
                                *str_ptr = '\0';
                        }
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Issuer Organization: %s", cbuf );
+                               report(stdout, "Issuer Organization: %s\n", cbuf );
                } else {
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Unknown Organization", cbuf );
+                               report(stdout, "Unknown Organization\n", cbuf );
                }
                if( ( str_ptr = strstr( ibuf, "/CN=" ) ) ) {
                        str_ptr += 4;
@@ -530,10 +587,10 @@ int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx )
                                *str_ptr = '\0';
                        }
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Issuer CommonName: %s", cbuf );
+                               report(stdout, "Issuer CommonName: %s\n", cbuf );
                } else {
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Unknown Issuer CommonName", cbuf );
+                               report(stdout, "Unknown Issuer CommonName\n", cbuf );
                }
                if( ( str_ptr = strstr( buf, "/CN=" ) ) ) {
                        str_ptr += 4;
@@ -542,14 +599,17 @@ int SSL_verify_callback( int ok_return, X509_STORE_CTX *ctx )
                                *str_ptr = '\0';
                        }
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Server CommonName: %s", cbuf );
+                               report(stdout, "Server CommonName: %s\n", cbuf );
                        /* Should we have some wildcarding here? */
-                       if ( NULL != _ssl_server_cname && 0 != strcmp( cbuf, _ssl_server_cname ) ) {
-                               report(stdout, "Server CommonName mismatch: %s != %s", cbuf, _ssl_server_cname );
+                       if ( NULL != _ssl_server_cname
+                            && 0 != strcasemp( cbuf, _ssl_server_cname ) ) {
+                               report(stdout,
+                                      "Server CommonName mismatch: %s != %s\n",
+                                      cbuf, _ssl_server_cname );
                        }
                } else {
                        if (outlevel == O_VERBOSE)
-                               report(stdout, "Unknown Server CommonName", cbuf );
+                               report(stdout, "Unknown Server CommonName\n", cbuf );
                }
        }
 
@@ -636,8 +696,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;
 
@@ -647,15 +708,39 @@ int SockClose(int sock)
         _ssl_context[sock] = NULL;
     }
 #endif
-    return(close(sock));
+
+#ifdef __UNUSED__
+    /* 
+     * This hangs in RedHat 6.2 after fetchmail runs for a while a
+     * FIN_WAIT2 comes up in netstat and fetchmail never returns from
+     * the recv system call. (Reported from jtnews
+     * <jtnews@bellatlantic.net>, Wed, 24 May 2000 21:26:02.)
+     *
+     * Half-close the connection first so the other end gets notified.
+     *
+     * This stops sends but allows receives (effectively, it sends a
+     * TCP <FIN>).  */
+    if (shutdown(sock, 1) == 0) {
+       /* 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 (fm_peek(sock, &ch, 1) > 0)
+           while (fm_read(sock, &ch, 1) > 0)
+               continue;
+    }
+#endif /* __UNUSED__ */
+
+    /* if there's an error closing at this point, not much we can do */
+    return(fm_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);