AC_SEARCH_LIBS(getaddrinfo, socket)
AC_SEARCH_LIBS(connect, socket)
+have_sendmsg="no"
+case $host_os in
+linux*)
+ AC_SEARCH_LIBS(sendmsg, socket, [have_sendmsg="yes"], [have_sendmsg="no"])
+ ;;
+esac
+
+case x$have_sendmsg in
+xyes)
+ AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg])
+ ;;
+esac
+
have_win32="no"
lt_enable_auto_import=""
case $host_os in
echo ""
echo " Configuration"
echo " XDM support.........: ${have_xdmcp}"
+echo " sendmsg fd passing..: ${have_sendmsg}"
echo " Build unit tests....: ${HAVE_CHECK}"
echo " with html results.: ${HTML_CHECK_RESULT}"
echo " XCB buffer size.....: ${xcb_queue_buffer_size}"
# 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
/** Connection closed because the server does not have a screen matching the display. */
#define XCB_CONN_CLOSED_INVALID_SCREEN 6
+/** Connection closed because some FD passing operation failed */
+#define XCB_CONN_CLOSED_FDPASSING_FAILED 7
+
#define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1))
/* Opaque structures */
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)
return request;
}
+void
+xcb_send_fd(xcb_connection_t *c, int fd)
+{
+#if HAVE_SENDMSG
+ if (c->has_error)
+ return;
+ 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;
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
#include "config.h"
#endif
+#if HAVE_SENDMSG
+#include <sys/socket.h>
+#endif
+
#ifdef GCC_HAS_VISIBILITY
#pragma GCC visibility push(hidden)
#endif
typedef void (*xcb_return_socket_func_t)(void *closure);
+#if HAVE_SENDMSG
+#define XCB_MAX_PASS_FD 16
+
+typedef struct _xcb_fd {
+ struct cmsghdr cmsghdr;
+ int fd[XCB_MAX_PASS_FD];
+ int nfd;
+} _xcb_fd;
+#endif
+
typedef struct _xcb_out {
pthread_cond_t cond;
int writing;
xcb_big_requests_enable_cookie_t cookie;
uint32_t value;
} maximum_request_length;
+#if HAVE_SENDMSG
+ _xcb_fd out_fd;
+#endif
} _xcb_out;
int _xcb_out_init(_xcb_out *out);