X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fxcb_util.c;h=0e3728a53f08f6acd6a7a57c2e6c712083c45a94;hb=20da10490f8dac75ec9fe1df28cb9e862e171be5;hp=e08a3205f37efbe647ba37d3d6918cd4599a6762;hpb=2dcf8b025be88a25d4333abdc28d425b88238d96;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/xcb_util.c b/src/xcb_util.c index e08a320..0e3728a 100644 --- a/src/xcb_util.c +++ b/src/xcb_util.c @@ -27,6 +27,7 @@ #include #include +#include #ifdef DNETCONN #include #include @@ -68,11 +69,19 @@ static int _xcb_parse_display(const char *name, char **host, char **protocol, { 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) { @@ -89,35 +98,43 @@ static int _xcb_parse_display(const char *name, char **host, char **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, @@ -126,7 +143,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); #ifndef _WIN32 static int _xcb_open_unix(char *protocol, const char *file); #endif /* !WIN32 */ @@ -137,16 +154,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 @@ -169,19 +194,40 @@ static int _xcb_open(char *host, char *protocol, const int display) 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 */ } @@ -244,7 +290,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; @@ -252,8 +298,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 @@ -359,31 +412,28 @@ xcb_connection_t *xcb_connect(const char *displayname, int *screenp) 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)) { @@ -394,5 +444,8 @@ xcb_connection_t *xcb_connect_to_display_with_auth_info(const char *displayname, else c = xcb_connect_to_fd(fd, 0); +out: + free(host); + free(protocol); return c; }