Merge branch 'master' of git://github.com/topcat/xcb-win32
authorPeter Harris <pharris@opentext.com>
Tue, 31 Aug 2010 22:33:36 +0000 (18:33 -0400)
committerPeter Harris <pharris@opentext.com>
Tue, 31 Aug 2010 22:35:20 +0000 (18:35 -0400)
Conflicts:
src/xcb_conn.c
src/xcb_util.c

Signed-off-by: Peter Harris <pharris@opentext.com>
1  2 
src/xcb_auth.c
src/xcb_conn.c
src/xcb_in.c
src/xcb_util.c

diff --combined src/xcb_auth.c
  
  #include <assert.h>
  #include <X11/Xauth.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <sys/un.h>
  #include <sys/param.h>
  #include <unistd.h>
  #include <stdlib.h>
  
+ #ifdef _WIN32
+ #include "xcb_windefs.h"
+ #else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <sys/un.h>
+ #endif /* _WIN32 */
  #include "xcb.h"
  #include "xcbint.h"
  
@@@ -89,7 -94,8 +94,7 @@@ static int authname_match(enum auth_pro
  
  #define SIN6_ADDR(s) (&((struct sockaddr_in6 *)s)->sin6_addr)
  
 -static Xauth *get_authptr(struct sockaddr *sockname, unsigned int socknamelen,
 -                          int display)
 +static Xauth *get_authptr(struct sockaddr *sockname, int display)
  {
      char *addr = 0;
      int addrlen = 0;
@@@ -242,55 -248,13 +247,55 @@@ static int compute_auth(xcb_auth_info_
      return 0;   /* Unknown authorization type */
  }
  
 +/* `sockaddr_un.sun_path' typical size usually ranges between 92 and 108 */
 +#define INITIAL_SOCKNAME_SLACK 108
 +
 +/* Return a dynamically allocated socket address structure according
 +   to the value returned by either getpeername() or getsockname()
 +   (according to POSIX, applications should not assume a particular
 +   length for `sockaddr_un.sun_path') */
 +static struct sockaddr *get_peer_sock_name(int (*socket_func)(int,
 +                                                            struct sockaddr *,
 +                                                            socklen_t *),
 +                                         int fd)
 +{
 +    socklen_t socknamelen = sizeof(struct sockaddr) + INITIAL_SOCKNAME_SLACK;
 +    socklen_t actual_socknamelen = socknamelen;
 +    struct sockaddr *sockname = malloc(socknamelen), *new_sockname = NULL;
 +
 +    if (sockname == NULL)
 +        return NULL;
 +
 +    /* Both getpeername() and getsockname() truncates sockname if
 +       there is not enough space and set the required length in
 +       actual_socknamelen */
 +    if (socket_func(fd, sockname, &actual_socknamelen) == -1)
 +        goto sock_or_realloc_error;
 +
 +    if (actual_socknamelen > socknamelen)
 +    {
 +        socknamelen = actual_socknamelen;
 +
 +        if ((new_sockname = realloc(sockname, actual_socknamelen)) == NULL ||
 +            socket_func(fd, new_sockname, &actual_socknamelen) == -1 ||
 +            actual_socknamelen > socknamelen) 
 +            goto sock_or_realloc_error;
 +
 +        sockname = new_sockname;
 +    }
 +
 +    return sockname;
 +
 + sock_or_realloc_error:
 +    free(sockname);
 +    return NULL;
 +}
 +
  int _xcb_get_auth_info(int fd, xcb_auth_info_t *info, int display)
  {
      /* code adapted from Xlib/ConnDis.c, xtrans/Xtranssocket.c,
         xtrans/Xtransutils.c */
 -    char sockbuf[sizeof(struct sockaddr) + MAXPATHLEN];
 -    unsigned int socknamelen = sizeof(sockbuf);   /* need extra space */
 -    struct sockaddr *sockname = (struct sockaddr *) &sockbuf;
 +    struct sockaddr *sockname = NULL;
      int gotsockname = 0;
      Xauth *authptr = 0;
      int ret = 1;
       * for UNIX Domain Sockets, but this is irrelevant,
       * since compute_auth() ignores the peer name in this
       * case anyway.*/
 -    if (getpeername(fd, sockname, &socknamelen) == -1)
 +    if ((sockname = get_peer_sock_name(getpeername, fd)) == NULL)
      {
 +        if ((sockname = get_peer_sock_name(getsockname, fd)) == NULL)
 +            return 0;   /* can only authenticate sockets */
          if (sockname->sa_family != AF_UNIX)
 +        {
 +            free(sockname);
              return 0;   /* except for AF_UNIX, sockets should have peernames */
 -        if (getsockname(fd, sockname, &socknamelen) == -1)
 -            return 0;   /* can only authenticate sockets */
 +        }
          gotsockname = 1;
      }
  
 -    authptr = get_authptr(sockname, socknamelen, display);
 +    authptr = get_authptr(sockname, display);
      if (authptr == 0)
 +    {
 +        free(sockname);
          return 0;   /* cannot find good auth data */
 +    }
  
      info->namelen = memdup(&info->name, authptr->name, authptr->name_length);
      if (!info->namelen)
          goto no_auth;   /* out of memory */
  
 -    if (!gotsockname && getsockname(fd, sockname, &socknamelen) == -1)
 +    if (!gotsockname && (sockname = get_peer_sock_name(getsockname, fd)) == NULL)
      {
          free(info->name);
          goto no_auth;   /* can only authenticate sockets */
          goto no_auth;   /* cannot build auth record */
      }
  
 +    free(sockname);
 +    sockname = NULL;
 +
      XauDisposeAuth(authptr);
      return ret;
  
   no_auth:
 +    free(sockname);
 +
      info->name = 0;
      info->namelen = 0;
      XauDisposeAuth(authptr);
diff --combined src/xcb_conn.c
@@@ -30,7 -30,6 +30,6 @@@
  #include <stdio.h>
  #include <unistd.h>
  #include <stdlib.h>
- #include <netinet/in.h>
  #include <fcntl.h>
  #include <errno.h>
  
  #include "xcbint.h"
  #if USE_POLL
  #include <poll.h>
- #else
+ #elif !defined _WIN32
  #include <sys/select.h>
  #endif
  
+ #ifdef _WIN32
+ #include "xcb_windefs.h"
+ #else
+ #include <netinet/in.h>
+ #endif /* _WIN32 */
 +/* SHUT_RDWR is fairly recent and is not available on all platforms */
 +#if !defined(SHUT_RDWR)
 +#define SHUT_RDWR 2
 +#endif
 +
  typedef struct {
      uint8_t  status;
      uint8_t  pad0[5];
@@@ -57,6 -57,17 +62,17 @@@ static const int error_connection = 1
  
  static int set_fd_flags(const int fd)
  {
+ /* Win32 doesn't have file descriptors and the fcntl function. This block sets the socket in non-blocking mode */
+ #ifdef _WIN32
+    u_long iMode = 1; /* non-zero puts it in non-blocking mode, 0 in blocking mode */   
+    int ret = 0;
+    ret = ioctlsocket(fd, FIONBIO, &iMode);
+    if(ret != 0) 
+        return 0;
+    return 1;
+ #else
      int flags = fcntl(fd, F_GETFL, 0);
      if(flags == -1)
          return 0;
@@@ -66,6 -77,7 +82,7 @@@
      if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
          return 0;
      return 1;
+ #endif /* _WIN32 */
  }
  
  static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info)
      assert(count <= (int) (sizeof(parts) / sizeof(*parts)));
  
      pthread_mutex_lock(&c->iolock);
 -    {
 -        struct iovec *parts_ptr = parts;
 -        ret = _xcb_out_send(c, &parts_ptr, &count);
 -    }
 +    ret = _xcb_out_send(c, parts, count);
      pthread_mutex_unlock(&c->iolock);
      return ret;
  }
@@@ -158,9 -173,37 +175,37 @@@ static int write_vec(xcb_connection_t *
  {
      int n;
      assert(!c->out.queue_len);
+ #ifdef _WIN32
+     int i = 0;
+     int ret = 0,err = 0;
+     struct iovec *vec;
+     n = 0;
+     /* Could use the WSASend win32 function for scatter/gather i/o but setting up the WSABUF struct from
+        an iovec would require more work and I'm not sure of the benefit....works for now */
+     vec = *vector;
+     while(i < *count)
+     {                  
+          ret = send(c->fd,vec->iov_base,vec->iov_len,0);       
+          if(ret == SOCKET_ERROR)
+          {
+              err  = WSAGetLastError();
+              if(err == WSAEWOULDBLOCK)
+              {
+                  return 1;
+              }
+          }
+          n += ret;
+          *vec++;
+          i++;
+     }
+ #else
      n = writev(c->fd, *vector, *count);
      if(n < 0 && errno == EAGAIN)
          return 1;
+ #endif /* _WIN32 */    
      if(n <= 0)
      {
          _xcb_conn_shutdown(c);
@@@ -212,14 -255,6 +257,14 @@@ xcb_connection_t *xcb_connect_to_fd(in
  {
      xcb_connection_t* c;
  
 +#ifndef USE_POLL
 +    if(fd >= FD_SETSIZE) /* would overflow in FD_SET */
 +    {
 +        close(fd);
 +        return (xcb_connection_t *) &error_connection;
 +    }
 +#endif
 +
      c = calloc(1, sizeof(xcb_connection_t));
      if(!c) {
          close(fd);
@@@ -252,9 -287,6 +297,9 @@@ void xcb_disconnect(xcb_connection_t *c
          return;
  
      free(c->setup);
 +
 +    /* disallow further sends and receives */
 +    shutdown(c->fd, SHUT_RDWR);
      close(c->fd);
  
      pthread_mutex_destroy(&c->iolock);
@@@ -318,15 -350,15 +363,15 @@@ int _xcb_conn_wait(xcb_connection_t *c
      pthread_mutex_unlock(&c->iolock);
      do {
  #if USE_POLL
 -    ret = poll(&fd, 1, -1);
 +        ret = poll(&fd, 1, -1);
  #else
 -      ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
 +        ret = select(c->fd + 1, &rfds, &wfds, 0, 0);
  #endif
      } while (ret == -1 && errno == EINTR);
 -    if (ret < 0)
 +    if(ret < 0)
      {
          _xcb_conn_shutdown(c);
 -      ret = 0;
 +        ret = 0;
      }
      pthread_mutex_lock(&c->iolock);
  
diff --combined src/xcb_in.c
  #include "xcbint.h"
  #if USE_POLL
  #include <poll.h>
- #else
 -#elif !defined _WIN32
++#endif
++#ifndef _WIN32
  #include <sys/select.h>
+ #include <sys/socket.h>
  #endif
  
+ #ifdef _WIN32
+ #include "xcb_windefs.h"
+ #endif /* _WIN32 */
  #define XCB_ERROR 0
  #define XCB_REPLY 1
  #define XCB_XGE_EVENT 35
  
+ /* required for compiling for Win32 using MinGW */
+ #ifndef MSG_WAITALL
+ #define MSG_WAITALL 0
+ #endif
  struct event_list {
      xcb_generic_event_t *event;
      struct event_list *next;
@@@ -69,6 -79,16 +80,6 @@@ typedef struct reader_list 
      struct reader_list *next;
  } reader_list;
  
 -static void wake_up_next_reader(xcb_connection_t *c)
 -{
 -    int pthreadret;
 -    if(c->in.readers)
 -        pthreadret = pthread_cond_signal(c->in.readers->data);
 -    else
 -        pthreadret = pthread_cond_signal(&c->in.event_cond);
 -    assert(pthreadret == 0);
 -}
 -
  static int read_packet(xcb_connection_t *c)
  {
      xcb_generic_reply_t genrep;
  
      /* XGE events may have sizes > 32 */
      if (genrep.response_type == XCB_XGE_EVENT)
 -    {
 -        eventlength = ((xcb_ge_event_t*)&genrep)->length * 4;
 -    }
 +        eventlength = genrep.length * 4;
  
      buf = malloc(length + eventlength +
              (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)));
@@@ -255,10 -277,14 +266,14 @@@ static int read_block(const int fd, voi
      int done = 0;
      while(done < len)
      {
-         int ret = read(fd, ((char *) buf) + done, len - done);
+         int ret = recv(fd, ((char *) buf) + done, len - done,MSG_WAITALL);
          if(ret > 0)
              done += ret;
+ #ifndef _WIN32
          if(ret < 0 && errno == EAGAIN)
+ #else
+         if(ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK)
+ #endif /* !_Win32 */
          {
  #if USE_POLL
              struct pollfd pfd;
              fd_set fds;
              FD_ZERO(&fds);
              FD_SET(fd, &fds);
+           /* Initializing errno here makes sure that for Win32 this loop will execute only once */
+           errno = 0;  
            do {
                ret = select(fd + 1, &fds, 0, 0, 0);
            } while (ret == -1 && errno == EINTR);
- #endif
+ #endif /* USE_POLL */
          }
          if(ret <= 0)
              return ret;
@@@ -392,7 -421,7 +410,7 @@@ void *xcb_wait_for_reply(xcb_connection
          pthread_cond_destroy(&cond);
      }
  
 -    wake_up_next_reader(c);
 +    _xcb_in_wake_up_next_reader(c);
      pthread_mutex_unlock(&c->iolock);
      return ret;
  }
@@@ -535,7 -564,7 +553,7 @@@ xcb_generic_event_t *xcb_wait_for_event
          if(!_xcb_conn_wait(c, &c->in.event_cond, 0, 0))
              break;
  
 -    wake_up_next_reader(c);
 +    _xcb_in_wake_up_next_reader(c);
      pthread_mutex_unlock(&c->iolock);
      return ret;
  }
@@@ -564,7 -593,7 +582,7 @@@ xcb_generic_error_t *xcb_request_check(
      void *reply;
      if(c->has_error)
          return 0;
 -    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_expected)
 +    if(XCB_SEQUENCE_COMPARE_32(cookie.sequence,>=,c->in.request_expected)
         && XCB_SEQUENCE_COMPARE_32(cookie.sequence,>,c->in.request_completed))
      {
          free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), &ret));
@@@ -619,16 -648,6 +637,16 @@@ void _xcb_in_destroy(_xcb_in *in
      }
  }
  
 +void _xcb_in_wake_up_next_reader(xcb_connection_t *c)
 +{
 +    int pthreadret;
 +    if(c->in.readers)
 +        pthreadret = pthread_cond_signal(c->in.readers->data);
 +    else
 +        pthreadret = pthread_cond_signal(&c->in.event_cond);
 +    assert(pthreadret == 0);
 +}
 +
  int _xcb_in_expect_reply(xcb_connection_t *c, uint64_t request, enum workarounds workaround, int flags)
  {
      pending_reply *pend = malloc(sizeof(pending_reply));
@@@ -663,12 -682,16 +681,16 @@@ void _xcb_in_replies_done(xcb_connectio
  
  int _xcb_in_read(xcb_connection_t *c)
  {
-     int n = read(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len);
+     int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len,MSG_WAITALL);
      if(n > 0)
          c->in.queue_len += n;
      while(read_packet(c))
          /* empty */;
+ #ifndef _WIN32
      if((n > 0) || (n < 0 && errno == EAGAIN))
+ #else
+     if((n > 0) || (n < 0 && WSAGetLastError() == WSAEWOULDBLOCK))
+ #endif /* !_WIN32 */
          return 1;
      _xcb_conn_shutdown(c);
      return 0;
diff --combined src/xcb_util.c
  
  #include <assert.h>
  #include <sys/types.h>
- #include <sys/socket.h>
 +#include <limits.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
  #ifdef DNETCONN
  #include <netdnet/dnetdb.h>
  #include <netdnet/dn.h>
  #endif
- #include <netdb.h>
  #include <errno.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stddef.h>
  #include <unistd.h>
- #include <fcntl.h>
  #include <string.h>
  
+ #ifdef _WIN32
+ #include "xcb_windefs.h"
+ #else
+ #include <sys/socket.h>
+ #include <sys/un.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+ #include <fcntl.h>
+ #include <netdb.h>
+ #endif /* _WIN32 */
  #include "xcb.h"
  #include "xcbext.h"
  #include "xcbint.h"
@@@ -64,19 -68,11 +69,19 @@@ static int _xcb_parse_display(const cha
  {
      int len, display, screen;
      char *slash, *colon, *dot, *end;
 +
      if(!name || !*name)
          name = getenv("DISPLAY");
      if(!name)
          return 0;
 +
 +#ifdef HAVE_LAUNCHD
 +    if(strncmp(name, "/tmp/launch", 11) == 0)
 +        slash = NULL;
 +    else
 +#endif
      slash = strrchr(name, '/');
 +
      if (slash) {
          len = slash - name;
          if (protocol) {
  
      colon = strrchr(name, ':');
      if(!colon)
 -        return 0;
 +        goto error_out;
      len = colon - name;
      ++colon;
      display = strtoul(colon, &dot, 10);
      if(dot == colon)
 -        return 0;
 +        goto error_out;
      if(*dot == '\0')
          screen = 0;
      else
      {
          if(*dot != '.')
 -            return 0;
 +            goto error_out;
          ++dot;
          screen = strtoul(dot, &end, 10);
          if(end == dot || *end != '\0')
 -            return 0;
 +            goto error_out;
      }
      /* At this point, the display string is fully parsed and valid, but
       * the caller's memory is untouched. */
  
      *host = malloc(len + 1);
      if(!*host)
 -        return 0;
 +        goto error_out;
      memcpy(*host, name, len);
      (*host)[len] = '\0';
      *displayp = display;
      if(screenp)
          *screenp = screen;
      return 1;
 +
 +error_out:
 +    if (protocol) {
 +        free(*protocol);
 +        *protocol = NULL;
 +    }
 +
 +    return 0;
  }
  
  int xcb_parse_display(const char *name, char **host, int *displayp,
      return _xcb_parse_display(name, host, NULL, displayp, screenp);
  }
  
 -static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port);
 +static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port);
+ #ifndef _WIN32
  static int _xcb_open_unix(char *protocol, const char *file);
+ #endif /* !WIN32 */
  #ifdef DNETCONN
  static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
  #endif
  static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen);
  #endif
  
 -static int _xcb_open(char *host, char *protocol, const int display)
 +static int _xcb_open(const char *host, char *protocol, const int display)
  {
 -#ifdef HAVE_ABSTRACT_SOCKETS
      int fd;
 +    static const char unix_base[] = "/tmp/.X11-unix/X";
 +    const char *base = unix_base;
 +    size_t filelen;
 +    char *file = NULL;
 +    int actual_filelen;
 +
 +#ifdef HAVE_LAUNCHD
 +        if(strncmp(host, "/tmp/launch", 11) == 0) {
 +              base = host;
 +              host = "";
 +              protocol = NULL;
 +        }
  #endif
 -    static const char base[] = "/tmp/.X11-unix/X";
 -    char file[sizeof(base) + 20];
 -    int filelen;
  
 -    if(*host)
 +    if(*host || protocol)
      {
  #ifdef DNETCONN
          /* DECnet displays have two colons, so _xcb_parse_display will have
                  return _xcb_open_tcp(host, protocol, port);
              }
      }
 +
+ #ifndef _WIN32
 +    filelen = strlen(base) + 1 + sizeof(display) * 3 + 1;
 +    file = malloc(filelen);
 +    if(file == NULL)
 +        return -1;
 +
      /* display specifies Unix socket */
 -    filelen = snprintf(file, sizeof(file), "%s%d", base, display);
 -    if(filelen < 0)
 +#ifdef HAVE_LAUNCHD
 +    if(strncmp(base, "/tmp/launch", 11) == 0)
 +        actual_filelen = snprintf(file, filelen, "%s:%d", base, display);
 +    else
 +#endif
 +        actual_filelen = snprintf(file, filelen, "%s%d", base, display);
 +    if(actual_filelen < 0)
 +    {
 +        free(file);
          return -1;
 +    }
      /* snprintf may truncate the file */
 -    filelen = MIN(filelen, sizeof(file) - 1);
 +    filelen = MIN(actual_filelen, filelen - 1);
  #ifdef HAVE_ABSTRACT_SOCKETS
      fd = _xcb_open_abstract(protocol, file, filelen);
      if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED))
 +    {
 +        free(file);
          return fd;
 +    }
 +
  #endif
 -    return  _xcb_open_unix(protocol, file);
 +    fd = _xcb_open_unix(protocol, file);
 +    free(file);
 +
 +    return fd;
+ #endif /* !_WIN32 */
+     return -1; /* if control reaches here then something has gone wrong */
  }
  
  static int _xcb_socket(int family, int type, int proto)
  #endif
      {
        fd = socket(family, type, proto);
+ #ifndef _WIN32
        if (fd >= 0)
            fcntl(fd, F_SETFD, FD_CLOEXEC);
+ #endif
      }
      return fd;
  }
@@@ -278,7 -244,7 +290,7 @@@ static int _xcb_open_decnet(const char 
  }
  #endif
  
 -static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
 +static int _xcb_open_tcp(const char *host, char *protocol, const unsigned short port)
  {
      int fd = -1;
      struct addrinfo hints;
      struct addrinfo *results, *addr;
      char *bracket;
  
 -    if (protocol && strcmp("tcp",protocol))
 +    if (protocol && strcmp("tcp",protocol) && strcmp("inet",protocol)
 +#ifdef AF_INET6
 +               && strcmp("inet6",protocol)
 +#endif
 +      )
          return -1;
 +      
 +    if (*host == '\0')
 +      host = "localhost";
  
      memset(&hints, 0, sizeof(hints));
  #ifdef AI_ADDRCONFIG
      return fd;
  }
  
+ #ifndef _WIN32
  static int _xcb_open_unix(char *protocol, const char *file)
  {
      int fd;
      }
      return fd;
  }
+ #endif /* !_WIN32 */
  
  #ifdef HAVE_ABSTRACT_SOCKETS
  static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen)
@@@ -398,28 -359,31 +412,28 @@@ xcb_connection_t *xcb_connect(const cha
  xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname, xcb_auth_info_t *auth, int *screenp)
  {
      int fd, display = 0;
 -    char *host;
 -    char *protocol;
 +    char *host = NULL;
 +    char *protocol = NULL;
      xcb_auth_info_t ourauth;
      xcb_connection_t *c;
  
      int parsed = _xcb_parse_display(displayname, &host, &protocol, &display, screenp);
      
 -#ifdef HAVE_LAUNCHD
 -    if(!displayname)
 -        displayname = getenv("DISPLAY");
 -    if(displayname && strlen(displayname)>11 && !strncmp(displayname, "/tmp/launch", 11))
 -        fd = _xcb_open_unix(NULL, displayname);
 -    else
 -#endif
 -    if(!parsed)
 -        return (xcb_connection_t *) &error_connection;
 -    else
 +    if(!parsed) {
 +        c = (xcb_connection_t *) &error_connection;
 +        goto out;
 +    } else
          fd = _xcb_open(host, protocol, display);
 -    free(host);
  
 -    if(fd == -1)
 -        return (xcb_connection_t *) &error_connection;
 +    if(fd == -1) {
 +        c = (xcb_connection_t *) &error_connection;
 +        goto out;
 +    }
  
 -    if(auth)
 -        return xcb_connect_to_fd(fd, auth);
 +    if(auth) {
 +        c = xcb_connect_to_fd(fd, auth);
 +        goto out;
 +    }
  
      if(_xcb_get_auth_info(fd, &ourauth, display))
      {
      else
          c = xcb_connect_to_fd(fd, 0);
  
 +out:
 +    free(host);
 +    free(protocol);
      return c;
  }