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 cf3fc9afa9febc45695c05a3d7840dd114db1e2a
Author: [email protected] <[email protected]>
AuthorDate: Sun Jun 7 22:46:56 2026 -0600

    feat(e_wl_proxy): listening socket with lock + connect helper
    
    Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
---
 src/bin/e_wl_proxy/e_wl_proxy_socket.c     | 78 +++++++++++++++++++++++++++++-
 src/bin/e_wl_proxy/tests/e_wl_proxy_test.c | 31 ++++++++++++
 2 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/src/bin/e_wl_proxy/e_wl_proxy_socket.c b/src/bin/e_wl_proxy/e_wl_proxy_socket.c
index 5d4ba9580..a52b7f66e 100644
--- a/src/bin/e_wl_proxy/e_wl_proxy_socket.c
+++ b/src/bin/e_wl_proxy/e_wl_proxy_socket.c
@@ -3,6 +3,12 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
 
 int
 e_wl_proxy_socket_path(const char *name, char *buf, size_t buflen)
@@ -21,5 +27,73 @@ e_wl_proxy_socket_path(const char *name, char *buf, size_t buflen)
    return 0;
 }
 
-int e_wl_proxy_listen(const char *name) { (void)name; return -1; }
-int e_wl_proxy_connect(const char *name) { (void)name; return -1; }
+static int
+_fill_addr(const char *name, struct sockaddr_un *addr)
+{
+   char path[256];
+
+   if (e_wl_proxy_socket_path(name, path, sizeof(path)) < 0) return -1;
+   if (strlen(path) >= sizeof(addr->sun_path)) return -1;
+
+   memset(addr, 0, sizeof(*addr));
+   addr->sun_family = AF_UNIX;
+   strcpy(addr->sun_path, path);
+   return 0;
+}
+
+int
+e_wl_proxy_listen(const char *name)
+{
+   struct sockaddr_un addr;
+   char lockpath[256 + 8];
+   char path[256];
+   int fd, lock;
+
+   if (e_wl_proxy_socket_path(name, path, sizeof(path)) < 0) return -1;
+   if (_fill_addr(name, &addr) < 0) return -1;
+
+   /* take "<path>.lock" so two servers can't share the name */
+   snprintf(lockpath, sizeof(lockpath), "%s.lock", path);
+   lock = open(lockpath, O_CREAT | O_CLOEXEC, 0660);
+   if (lock < 0) return -1;
+   if (flock(lock, LOCK_EX | LOCK_NB) < 0) { close(lock); return -1; }
+
+   /* a leftover socket from a crash is safe to remove now we hold the lock */
+   unlink(path);
+
+   fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+   if (fd < 0) { close(lock); return -1; }
+
+   if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) goto err;
+   if (listen(fd, 128) < 0) goto err;
+
+   /* intentionally leak `lock`: it must stay open for the socket's lifetime.
+    * The process exit releases it. */
+   return fd;
+
+err:
+   close(fd);
+   close(lock);
+   return -1;
+}
+
+int
+e_wl_proxy_connect(const char *name)
+{
+   struct sockaddr_un addr;
+   int fd;
+
+   if (_fill_addr(name, &addr) < 0) return -1;
+
+   fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+   if (fd < 0) return -1;
+
+   if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+     {
+        if (errno != EINPROGRESS) { close(fd); return -1; }
+        /* nonblocking connect in progress: fine for a unix socket, it
+         * completes effectively immediately; caller treats it as connected. */
+     }
+
+   return fd;
+}
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 9616a8748..491298dcd 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
@@ -2,6 +2,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
 
 static int failures = 0;
 
@@ -28,11 +31,39 @@ test_socket_path(void)
    CHECK(e_wl_proxy_socket_path("wayland-0", buf, 8) == -1);
 }
 
+static void
+test_listen_and_connect(void)
+{
+   char tmpl[] = "/tmp/ewlpXXXXXX";
+   char *dir = mkdtemp(tmpl);
+   CHECK(dir != NULL);
+   setenv("XDG_RUNTIME_DIR", dir, 1);
+
+   int lfd = e_wl_proxy_listen("wayland-test");
+   CHECK(lfd >= 0);
+
+   /* a second listen on the same name must fail (lock held) */
+   int lfd2 = e_wl_proxy_listen("wayland-test");
+   CHECK(lfd2 == -1);
+
+   /* a plain client can connect */
+   int cfd = e_wl_proxy_connect("wayland-test");
+   CHECK(cfd >= 0);
+
+   int afd = accept(lfd, NULL, NULL);
+   CHECK(afd >= 0);
+
+   if (afd >= 0) close(afd);
+   if (cfd >= 0) close(cfd);
+   if (lfd >= 0) close(lfd);
+}
+
 int
 main(void)
 {
    test_harness_runs();
    test_socket_path();
+   test_listen_and_connect();
    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