// https://www.x.org/releases/current/doc/xproto/x11protocol.html#Encoding::Connection_Setup static void read_client_setup_request_cb(EV_P_ ev_io *w, int revents) { ev_io_stop(EV_A_ w); struct connstate *connstate = (struct connstate *)w->data; /* Read X11 setup request in its entirety. */ xcb_setup_request_t setup_request; must_read(readall_into(&setup_request, sizeof(setup_request), w->fd)); /* Establish a connection to X11. */ int fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { err(EXIT_FAILURE, "socket()"); } char *host; int displayp; if (xcb_parse_display(getenv("DISPLAY"), &host, &displayp, NULL) == 0) { errx(EXIT_FAILURE, "Could not parse DISPLAY=%s", getenv("DISPLAY")); } free(host); struct sockaddr_un addr; memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_LOCAL; snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/.X11-unix/X%d", displayp); if (connect(fd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) { err(EXIT_FAILURE, "connect(%s)", addr.sun_path); } /* Relay setup request. */ must_write(writeall(fd, &setup_request, sizeof(setup_request))); if (setup_request.authorization_protocol_name_len > 0 || setup_request.authorization_protocol_data_len > 0) { const size_t authlen = setup_request.authorization_protocol_name_len + XCB_PAD(setup_request.authorization_protocol_name_len) + setup_request.authorization_protocol_data_len + XCB_PAD(setup_request.authorization_protocol_data_len); void *buf = smalloc(authlen); must_read(readall_into(buf, authlen, w->fd)); must_write(writeall(fd, buf, authlen)); free(buf); } /* Wait for a response from the X11 server. */ ev_io *serverw = scalloc(1, sizeof(ev_io)); connstate->serverw = serverw; serverw->data = connstate; ev_io_init(serverw, read_server_setup_reply_cb, fd, EV_READ); ev_io_start(EV_A_ serverw); }
static int write_setup(xcb_connection_t *c, xcb_auth_info_t *auth_info) { static const char pad[3]; xcb_setup_request_t out; struct iovec parts[6]; int count = 0; static const uint32_t endian = 0x01020304; int ret; memset(&out, 0, sizeof(out)); /* B = 0x42 = MSB first, l = 0x6c = LSB first */ if(htonl(endian) == endian) out.byte_order = 0x42; else out.byte_order = 0x6c; out.protocol_major_version = X_PROTOCOL; out.protocol_minor_version = X_PROTOCOL_REVISION; out.authorization_protocol_name_len = 0; out.authorization_protocol_data_len = 0; parts[count].iov_len = sizeof(xcb_setup_request_t); parts[count++].iov_base = &out; parts[count].iov_len = XCB_PAD(sizeof(xcb_setup_request_t)); parts[count++].iov_base = (char *) pad; if(auth_info) { parts[count].iov_len = out.authorization_protocol_name_len = auth_info->namelen; parts[count++].iov_base = auth_info->name; parts[count].iov_len = XCB_PAD(out.authorization_protocol_name_len); parts[count++].iov_base = (char *) pad; parts[count].iov_len = out.authorization_protocol_data_len = auth_info->datalen; parts[count++].iov_base = auth_info->data; parts[count].iov_len = XCB_PAD(out.authorization_protocol_data_len); parts[count++].iov_base = (char *) pad; } assert(count <= (int) (sizeof(parts) / sizeof(*parts))); pthread_mutex_lock(&c->iolock); ret = _xcb_out_send(c, parts, count); pthread_mutex_unlock(&c->iolock); return ret; }