This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch feat/e-wl-proxy-planb
in repository enlightenment.
View the commit online.
commit 78c8c18e2f182dbbfbb9fb29f132c69954b94e8d
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 7 22:48:46 2026 -0600
feat(e_wl_proxy): pipe flush with SCM_RIGHTS fd passing
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
src/bin/e_wl_proxy/e_wl_proxy_pipe.c | 63 +++++++++++++++++++++++++++++-
src/bin/e_wl_proxy/tests/e_wl_proxy_test.c | 48 +++++++++++++++++++++++
2 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/bin/e_wl_proxy/e_wl_proxy_pipe.c b/src/bin/e_wl_proxy/e_wl_proxy_pipe.c
index 36bfe5ce9..3e143b8d6 100644
--- a/src/bin/e_wl_proxy/e_wl_proxy_pipe.c
+++ b/src/bin/e_wl_proxy/e_wl_proxy_pipe.c
@@ -1,5 +1,66 @@
#include "config.h"
#include "e_wl_proxy.h"
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Write pipe->buf[off..len) plus any pending fds to `to`. fds ride on the
+ * first sendmsg that places any byte; once off > 0 they are gone. */
+int
+e_wl_proxy_pipe_flush(int to, E_Wl_Proxy_Pipe *pipe)
+{
+ while (pipe->len - pipe->off > 0)
+ {
+ struct iovec iov;
+ struct msghdr msg;
+ union {
+ struct cmsghdr align;
+ char buf[CMSG_SPACE(E_WL_PROXY_MAX_FDS * sizeof(int))];
+ } cmsgbuf;
+ ssize_t sent;
+
+ iov.iov_base = pipe->buf + pipe->off;
+ iov.iov_len = pipe->len - pipe->off;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+
+ if (pipe->off == 0 && pipe->nfds > 0)
+ {
+ struct cmsghdr *c;
+ size_t fdbytes = pipe->nfds * sizeof(int);
+
+ memset(&cmsgbuf, 0, sizeof(cmsgbuf));
+ msg.msg_control = cmsgbuf.buf;
+ msg.msg_controllen = CMSG_SPACE(fdbytes);
+ c = CMSG_FIRSTHDR(&msg);
+ c->cmsg_level = SOL_SOCKET;
+ c->cmsg_type = SCM_RIGHTS;
+ c->cmsg_len = CMSG_LEN(fdbytes);
+ memcpy(CMSG_DATA(c), pipe->fds, fdbytes);
+ }
+
+ do {
+ sent = sendmsg(to, &msg, MSG_NOSIGNAL);
+ } while (sent < 0 && errno == EINTR);
+
+ if (sent < 0)
+ {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) return 1;
+ return -1;
+ }
+
+ /* fds (if any) were delivered with this sendmsg */
+ pipe->nfds = 0;
+ pipe->off += sent;
+ }
+
+ pipe->len = 0;
+ pipe->off = 0;
+ return 0;
+}
-int e_wl_proxy_pipe_flush(int to, E_Wl_Proxy_Pipe *pipe) { (void)to; (void)pipe; return -1; }
ssize_t e_wl_proxy_forward(int from, int to, E_Wl_Proxy_Pipe *pipe) { (void)from; (void)to; (void)pipe; return -1; }
diff --git a/src/bin/e_wl_proxy/tests/e_wl_proxy_test.c b/src/bin/e_wl_proxy/tests/e_wl_proxy_test.c
index 491298dcd..fef8d5e19 100644
--- a/src/bin/e_wl_proxy/tests/e_wl_proxy_test.c
+++ b/src/bin/e_wl_proxy/tests/e_wl_proxy_test.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <sys/uio.h>
#include <unistd.h>
static int failures = 0;
@@ -58,12 +59,59 @@ test_listen_and_connect(void)
if (lfd >= 0) close(lfd);
}
+/* send bytes + one fd through a socketpair using a pipe, read them back */
+static void
+test_pipe_flush_bytes_and_fd(void)
+{
+ int sp[2];
+ CHECK(socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sp) == 0);
+
+ /* an fd to pass: a second socketpair's end carrying a known marker */
+ int marker[2];
+ CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, marker) == 0);
+ CHECK(write(marker[0], "Z", 1) == 1);
+
+ E_Wl_Proxy_Pipe pipe;
+ memset(&pipe, 0, sizeof(pipe));
+ memcpy(pipe.buf, "hello", 5);
+ pipe.len = 5;
+ pipe.fds[0] = marker[1];
+ pipe.nfds = 1;
+
+ CHECK(e_wl_proxy_pipe_flush(sp[0], &pipe) == 0); /* fully drained */
+ CHECK(pipe.len == 0 && pipe.nfds == 0);
+
+ /* read bytes back */
+ char rb[8] = {0};
+ struct iovec iov = { rb, sizeof(rb) };
+ union { struct cmsghdr h; char b[CMSG_SPACE(sizeof(int))]; } cm;
+ struct msghdr msg = {0};
+ msg.msg_iov = &iov; msg.msg_iovlen = 1;
+ msg.msg_control = cm.b; msg.msg_controllen = sizeof(cm.b);
+ ssize_t n = recvmsg(sp[1], &msg, 0);
+ CHECK(n == 5);
+ CHECK(memcmp(rb, "hello", 5) == 0);
+
+ /* the passed fd must point at the same object: read its marker byte */
+ struct cmsghdr *c = CMSG_FIRSTHDR(&msg);
+ CHECK(c != NULL && c->cmsg_type == SCM_RIGHTS);
+ int got = -1;
+ memcpy(&got, CMSG_DATA(c), sizeof(int));
+ CHECK(got >= 0);
+ char z = 0;
+ CHECK(read(got, &z, 1) == 1 && z == 'Z');
+
+ close(got); close(marker[0]); close(marker[1]);
+ close(sp[0]); close(sp[1]);
+}
+
int
main(void)
{
test_harness_runs();
test_socket_path();
test_listen_and_connect();
+ test_pipe_flush_bytes_and_fd();
if (failures) { fprintf(stderr, "%d check(s) failed\n", failures); return 1; }
printf("all checks passed\n");
return 0;
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.