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.

Reply via email to