This uses sendmsg to transmit file descriptors from the application to the X server
Signed-off-by: Keith Packard <[email protected]> --- configure.ac | 1 + src/c_client.py | 4 ++++ src/xcb_auth.c | 11 ++++++----- src/xcb_conn.c | 39 +++++++++++++++++++++++++++++++++------ src/xcb_ext.c | 3 +++ src/xcb_in.c | 9 +++++---- src/xcb_list.c | 3 +++ src/xcb_out.c | 19 +++++++++++++++++++ src/xcb_xid.c | 4 ++++ src/xcbext.h | 2 ++ src/xcbint.h | 13 +++++++++++++ 11 files changed, 93 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 835f7d5..2fb1968 100644 --- a/configure.ac +++ b/configure.ac @@ -80,6 +80,7 @@ AC_SUBST(XCBPROTO_XCBPYTHONDIR) AC_HEADER_STDC AC_SEARCH_LIBS(getaddrinfo, socket) AC_SEARCH_LIBS(connect, socket) +AC_SEARCH_LIBS(sendmsg, socket, AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg])) have_win32="no" lt_enable_auto_import="" diff --git a/src/c_client.py b/src/c_client.py index 942e78a..ed92185 100644 --- a/src/c_client.py +++ b/src/c_client.py @@ -2149,6 +2149,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False): # no padding necessary - _serialize() keeps track of padding automatically _c(' ') + for field in param_fields: + if field.isfd: + _c(' xcb_send_fd(c, %s);', field.c_field_name) + _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags) # free dyn. all. data, if any diff --git a/src/xcb_auth.c b/src/xcb_auth.c index a5b730c..2f7c93e 100644 --- a/src/xcb_auth.c +++ b/src/xcb_auth.c @@ -34,6 +34,12 @@ #include <sys/param.h> #include <unistd.h> #include <stdlib.h> +#ifndef _WIN32 +#include <arpa/inet.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/un.h> +#endif #ifdef __INTERIX /* _don't_ ask. interix has INADDR_LOOPBACK in here. */ @@ -47,11 +53,6 @@ #include <X11/Xwindows.h> #endif #include "xcb_windefs.h" -#else -#include <arpa/inet.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <sys/un.h> #endif /* _WIN32 */ #include "xcb.h" diff --git a/src/xcb_conn.c b/src/xcb_conn.c index 6a7a806..329b9e8 100644 --- a/src/xcb_conn.c +++ b/src/xcb_conn.c @@ -38,6 +38,11 @@ #include <errno.h> #include <limits.h> +#ifndef _WIN32 +#include <sys/socket.h> +#include <netinet/in.h> +#endif /* !_WIN32 */ + #include "xcb.h" #include "xcbint.h" #if USE_POLL @@ -48,9 +53,6 @@ #ifdef _WIN32 #include "xcb_windefs.h" -#else -#include <sys/socket.h> -#include <netinet/in.h> #endif /* _WIN32 */ /* SHUT_RDWR is fairly recent and is not available on all platforms */ @@ -214,9 +216,34 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count) if (n > IOV_MAX) n = IOV_MAX; - n = writev(c->fd, *vector, n); - if(n < 0 && errno == EAGAIN) - return 1; +#if HAVE_SENDMSG + if (c->out.out_fd.nfd) { + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = *vector, + .msg_iovlen = n, + .msg_control = &c->out.out_fd, + .msg_controllen = sizeof (struct cmsghdr) + c->out.out_fd.nfd * sizeof (int), + }; + int i; + c->out.out_fd.cmsghdr.cmsg_len = msg.msg_controllen; + c->out.out_fd.cmsghdr.cmsg_level = SOL_SOCKET; + c->out.out_fd.cmsghdr.cmsg_type = SCM_RIGHTS; + n = sendmsg(c->fd, &msg, 0); + if(n < 0 && errno == EAGAIN) + return 1; + for (i = 0; i < c->out.out_fd.nfd; i++) + close(c->out.out_fd.fd[i]); + c->out.out_fd.nfd = 0; + } else +#endif + { + n = writev(c->fd, *vector, n); + if(n < 0 && errno == EAGAIN) + return 1; + } + #endif /* _WIN32 */ if(n <= 0) diff --git a/src/xcb_ext.c b/src/xcb_ext.c index 831f283..1ff2b05 100644 --- a/src/xcb_ext.c +++ b/src/xcb_ext.c @@ -31,6 +31,9 @@ #include <stdlib.h> #include <string.h> +#ifndef _WIN32 +#include <sys/socket.h> +#endif #include "xcb.h" #include "xcbext.h" diff --git a/src/xcb_in.c b/src/xcb_in.c index 8a7af92..ac4d284 100644 --- a/src/xcb_in.c +++ b/src/xcb_in.c @@ -36,16 +36,17 @@ #include <stdio.h> #include <errno.h> +#ifndef _WIN32 +#include <sys/select.h> +#include <sys/socket.h> +#endif + #include "xcb.h" #include "xcbext.h" #include "xcbint.h" #if USE_POLL #include <poll.h> #endif -#ifndef _WIN32 -#include <sys/select.h> -#include <sys/socket.h> -#endif #ifdef _WIN32 #include "xcb_windefs.h" diff --git a/src/xcb_list.c b/src/xcb_list.c index 6f5c611..a219cdb 100644 --- a/src/xcb_list.c +++ b/src/xcb_list.c @@ -30,6 +30,9 @@ #endif #include <stdlib.h> +#ifndef _WIN32 +#include <sys/socket.h> +#endif #include "xcb.h" #include "xcbint.h" diff --git a/src/xcb_out.c b/src/xcb_out.c index 429fa99..ed8458c 100644 --- a/src/xcb_out.c +++ b/src/xcb_out.c @@ -33,6 +33,9 @@ #include <stdlib.h> #include <unistd.h> #include <string.h> +#ifndef _WIN32 +#include <sys/socket.h> +#endif #include "xcb.h" #include "xcbext.h" @@ -263,6 +266,22 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect return request; } +void +xcb_send_fd(xcb_connection_t *c, int fd) +{ +#if HAVE_SENDMSG + pthread_mutex_lock(&c->iolock); + while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) { + _xcb_out_flush_to(c, c->out.request); + if (c->has_error) + break; + } + if (!c->has_error) + c->out.out_fd.fd[c->out.out_fd.nfd++] = fd; + pthread_mutex_unlock(&c->iolock); +#endif +} + int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent) { int ret; diff --git a/src/xcb_xid.c b/src/xcb_xid.c index 79a9a27..3c5682c 100644 --- a/src/xcb_xid.c +++ b/src/xcb_xid.c @@ -31,6 +31,10 @@ #include <assert.h> #include <stdlib.h> +#ifndef _WIN32 +#include <sys/socket.h> +#endif + #include "xcb.h" #include "xcbext.h" #include "xcbint.h" diff --git a/src/xcbext.h b/src/xcbext.h index 4e1f2f7..44030c3 100644 --- a/src/xcbext.h +++ b/src/xcbext.h @@ -59,6 +59,8 @@ enum xcb_send_request_flags_t { unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request); +void xcb_send_fd(xcb_connection_t *c, int fd); + /* xcb_take_socket allows external code to ask XCB for permission to * take over the write side of the socket and send raw data with * xcb_writev. xcb_take_socket provides the sequence number of the last diff --git a/src/xcbint.h b/src/xcbint.h index 7f9ab28..356350b 100644 --- a/src/xcbint.h +++ b/src/xcbint.h @@ -81,6 +81,16 @@ void *_xcb_map_remove(_xcb_map *q, unsigned int key); typedef void (*xcb_return_socket_func_t)(void *closure); +#if HAVE_SENDMSG +#define XCB_MAX_PASS_FD 16 + +typedef struct _xcb_out_fd { + struct cmsghdr cmsghdr; + int fd[XCB_MAX_PASS_FD]; + int nfd; +} _xcb_out_fd; +#endif + typedef struct _xcb_out { pthread_cond_t cond; int writing; @@ -101,6 +111,9 @@ typedef struct _xcb_out { xcb_big_requests_enable_cookie_t cookie; uint32_t value; } maximum_request_length; +#if HAVE_SENDMSG + _xcb_out_fd out_fd; +#endif } _xcb_out; int _xcb_out_init(_xcb_out *out); -- 1.8.4.2 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
