From 0c9d5c6f4958b90f9c314b682f19d001c58cb685 Mon Sep 17 00:00:00 2001 From: Daphne Pfister Date: Mon, 8 Apr 2013 16:48:33 -0500 Subject: Fix unix sockets --- src/xcb_util.c | 162 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 57 deletions(-) diff --git a/src/xcb_util.c b/src/xcb_util.c index 463d085..a687428 100644 --- a/src/xcb_util.c +++ b/src/xcb_util.c @@ -60,6 +60,12 @@ # include #endif +typedef struct +{ + const char* base; + char sep; +} _xcb_socket_base; + int xcb_popcount(uint32_t mask) { uint32_t y; @@ -78,6 +84,18 @@ int xcb_sumof(uint8_t *list, int len) return s; } +static int _xcb_add_base(_xcb_socket_base* bases, int max_cnt, int* cnt, + const char* base, char sep) +{ + if (*cnt >= max_cnt) + return -1; + + bases[*cnt].base = base; + bases[*cnt].sep = sep; + ++*cnt; + return 0; +} + static int _xcb_parse_display(const char *name, char **host, char **protocol, int *displayp, int *screenp) { @@ -164,89 +182,119 @@ static int _xcb_open_unix(char *protocol, const char *file); #ifdef HAVE_ABSTRACT_SOCKETS static int _xcb_open_abstract(char *protocol, const char *file, size_t filelen); #endif +#ifndef _WIN32 +static int _xcb_open_base(char *protocol, const int display, _xcb_socket_base* bases, int base_cnt); +#endif static int _xcb_open(const char *host, char *protocol, const int display) { int fd; + _xcb_socket_base bases[6]; + static const int max_base = sizeof(bases) / sizeof(bases[0]); + int base_cnt = 0; + +#ifndef _WIN32 static const char unix_base[] = "/tmp/.X11-unix/X"; - const char *base = unix_base; - size_t filelen; - char *file = NULL; - int actual_filelen; + static const char unix_var_spool_base[] = "/var/spool/sockets/X11"; + static const char unix_usr_spool_base[] = "/usr/spool/sockets/X11"; +#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED) + static const char tsol_base[] = "/var/tsol/doors/.X11-unix/X"; +#endif +#endif #ifdef HAVE_LAUNCHD if(strncmp(host, "/tmp/launch", 11) == 0) { - base = host; - host = ""; - protocol = "unix"; +#ifndef _WIN32 + _xcb_add_base(bases, max_base, &base_cnt, host, ':'); + + fd = _xcb_open_base("unix", display, bases, base_cnt); + if( fd >= 0 ) + return fd; +#endif + host = ""; } + else +#endif + if ((protocol && (strcmp("unix",protocol) == 0)) || + (*host == '\0') || (strcmp("unix",host) == 0)) { +#ifndef _WIN32 +#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED) + /* Check special path for Unix sockets under Solaris Trusted Extensions */ + if (is_system_labeled()) { + _xcb_add_base(bases, max_base, &base_cnt, tsol_base, '\0'); + } #endif - /* If protocol or host is "unix", fall through to Unix socket code below */ - if ((!protocol || (strcmp("unix",protocol) != 0)) && - (*host != '\0') && (strcmp("unix",host) != 0)) - { - /* display specifies TCP */ - unsigned short port = X_TCP_PORT + display; - return _xcb_open_tcp(host, protocol, port); + _xcb_add_base(bases, max_base, &base_cnt, unix_base, '\0'); + _xcb_add_base(bases, max_base, &base_cnt, unix_var_spool_base, '/'); + _xcb_add_base(bases, max_base, &base_cnt, unix_usr_spool_base, '/'); + + fd = _xcb_open_base("unix", display, bases, base_cnt); + if( fd >= 0 ) + return fd; +#endif + + if(strcmp("unix",host) == 0) + host = ""; } -#ifndef _WIN32 -#if defined(HAVE_TSOL_LABEL_H) && defined(HAVE_IS_SYSTEM_LABELED) - /* Check special path for Unix sockets under Solaris Trusted Extensions */ - if (is_system_labeled()) - { - struct stat sbuf; - const char *tsol_base = "/var/tsol/doors/.X11-unix/X"; - char tsol_socket[PATH_MAX]; + /* display specifies TCP */ + unsigned short port = X_TCP_PORT + display; + return _xcb_open_tcp(host, protocol, port); - snprintf(tsol_socket, sizeof(tsol_socket), "%s%d", tsol_base, display); + return -1; /* if control reaches here then something has gone wrong */ +} - if (stat(tsol_socket, &sbuf) == 0) - base = tsol_base; +#ifndef _WIN32 +static int _xcb_open_base(char *protocol, const int display, _xcb_socket_base* bases, int base_cnt) +{ + int fd; + size_t filelen; + char *file = NULL; + int actual_filelen; + int i; + size_t baselen = 0; + size_t len; + + for(i = 0; i < base_cnt; ++i) { + len = strlen(bases[i].base); + if (len > baselen) + baselen = len; } -#endif - filelen = strlen(base) + 1 + sizeof(display) * 3 + 1; + filelen = baselen + 1 + sizeof(display) * 3 + 1; file = malloc(filelen); if(file == NULL) return -1; - /* display specifies Unix socket */ -#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(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; - } + for(i = 0; i < base_cnt; ++i) { + if(bases[i].sep == '\0') + actual_filelen = snprintf(file, filelen, "%s%d", bases[i].base, display); + else + actual_filelen = snprintf(file, filelen, "%s%c%d", bases[i].base, bases[i].sep, display); + if(actual_filelen < 0) { + free(file); + return -1; + } +#ifdef HAVE_ABSTRACT_SOCKETS + fd = _xcb_open_abstract(protocol, file, actual_filelen); + if (fd >= 0 || (errno != ENOENT && errno != ECONNREFUSED)) { + free(file); + return fd; + } #endif - fd = _xcb_open_unix(protocol, file); - free(file); - - if (fd < 0 && !protocol && *host == '\0') { - unsigned short port = X_TCP_PORT + display; - fd = _xcb_open_tcp(host, protocol, port); + fd = _xcb_open_unix(protocol, file); + if (fd >= 0) { + free(file); + return fd; + } } + free(file); - return fd; -#endif /* !_WIN32 */ - return -1; /* if control reaches here then something has gone wrong */ + return -1; } +#endif static int _xcb_socket(int family, int type, int proto) { -- 1.8.3.1