Support pre-IPv6 systems (without getaddrinfo)
authorMarkus Duft <mduft@gentoo.org>
Wed, 24 Aug 2011 14:49:06 +0000 (10:49 -0400)
committerPeter Harris <pharris@opentext.com>
Wed, 24 Aug 2011 14:49:06 +0000 (10:49 -0400)
Some of these systems (eg. Interix on XP) are still in use.

Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Peter Harris <pharris@opentext.com>
configure.ac
src/xcb_auth.c
src/xcb_util.c

index 1a8cd2e..cba9dbd 100644 (file)
@@ -135,6 +135,8 @@ AC_PREREQ([2.59c], [], [AC_SUBST([htmldir], [m4_ifset([AC_PACKAGE_TARNAME],
 
 XCB_CHECK_DOXYGEN()
 
+AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAVE_GETADDRINFO, 1, [getaddrinfo() function is available])], )
+
 case $host_os in
        # darwin through Snow Leopard has poll() but can't be used to poll character devices.
        darwin@<:@789@:>@*|darwin10*) ;;
index a3a7e45..859ab8a 100644 (file)
 #include <sys/param.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <arpa/inet.h>
+
+#ifdef __INTERIX
+/* _don't_ ask. interix has INADDR_LOOPBACK in here. */
+#include <rpc/types.h>
+#endif
 
 #ifdef _WIN32
 #include "xcb_windefs.h"
index 1bde7b7..fcb11f0 100644 (file)
@@ -34,6 +34,7 @@
 #include <stddef.h>
 #include <unistd.h>
 #include <string.h>
+#include <arpa/inet.h>
 
 #ifdef _WIN32
 #include "xcb_windefs.h"
@@ -258,13 +259,27 @@ static int _xcb_socket(int family, int type, int proto)
 }
 
 
+static int _xcb_do_connect(int fd, const struct sockaddr* addr, int addrlen) {
+       int on = 1;
+
+       if(fd < 0)
+               return -1;
+
+       setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+       setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+
+       return connect(fd, addr, addrlen);
+}
+
 static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
 {
     int fd = -1;
+#if HAVE_GETADDRINFO
     struct addrinfo hints;
     char service[6]; /* "65535" with the trailing '\0' */
     struct addrinfo *results, *addr;
     char *bracket;
+#endif
 
     if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
 #ifdef AF_INET6
@@ -276,6 +291,7 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
     if (*host == '\0')
        host = "localhost";
 
+#if HAVE_GETADDRINFO
     memset(&hints, 0, sizeof(hints));
 #ifdef AI_NUMERICSERV
     hints.ai_flags |= AI_NUMERICSERV;
@@ -302,19 +318,42 @@ static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short
     for(addr = results; addr; addr = addr->ai_next)
     {
         fd = _xcb_socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
-        if(fd >= 0) {
-            int on = 1;
-            setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
-           setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
+        if (_xcb_do_connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+            break;
+        close(fd);
+        fd = -1;
+    }
+    freeaddrinfo(results);
+    return fd;
+#else
+    {
+        struct hostent* _h;
+        struct sockaddr_in _s;
+        struct in_addr ** _c;
+
+        if((_h = gethostbyname(host)) == NULL)
+            return -1;
+
+        _c = (struct in_addr**)_h->h_addr_list;
+        fd = -1;
 
-            if (connect(fd, addr->ai_addr, addr->ai_addrlen) >= 0)
+        while(*_c) {
+            _s.sin_family = AF_INET;
+            _s.sin_port = htons(port);
+            _s.sin_addr = *(*_c);
+
+            fd = _xcb_socket(_s.sin_family, SOCK_STREAM, 0);
+            if(_xcb_do_connect(fd, (struct sockaddr*)&_s, sizeof(_s)) >= 0)
                 break;
+
             close(fd);
             fd = -1;
+            ++_c;
         }
+
+        return fd;
     }
-    freeaddrinfo(results);
-    return fd;
+#endif
 }
 
 #ifndef _WIN32