partial rewrite of serialize helper functions completed;
[free-sw/xcb/libxcb] / src / xcb_util.c
index 996ff25..58bd12d 100644 (file)
@@ -28,6 +28,7 @@
 #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>
@@ -58,6 +59,16 @@ int xcb_popcount(uint32_t mask)
     return ((y + (y >> 3)) & 030707070707) % 077;
 }
 
+int xcb_sumof(uint8_t *list, int len)
+{
+  int i, s = 0;
+  for(i=0; i<len; i++) {
+    s += *list;
+    list++;
+  }
+  return s;
+}
+
 static int _xcb_parse_display(const char *name, char **host, char **protocol,
                       int *displayp, int *screenp)
 {
@@ -67,7 +78,14 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol,
         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) {
@@ -121,7 +139,7 @@ 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);
 static int _xcb_open_unix(char *protocol, const char *file);
 #ifdef DNETCONN
 static int _xcb_open_decnet(const char *host, char *protocol, const unsigned short port);
@@ -130,16 +148,24 @@ static int _xcb_open_decnet(const char *host, char *protocol, const unsigned sho
 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
@@ -163,19 +189,38 @@ static int _xcb_open(char *host, char *protocol, const int display)
             }
     }
 
+    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;
 }
 
 static int _xcb_socket(int family, int type, int proto)
@@ -234,7 +279,7 @@ static int _xcb_open_decnet(const char *host, const char *protocol, const unsign
 }
 #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;
@@ -242,8 +287,15 @@ static int _xcb_open_tcp(char *host, char *protocol, const unsigned short port)
     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
@@ -354,13 +406,6 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname,
 
     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