[PATCH 1/4] desktop-shell: launch from the compositor

Pekka Paalanen ppaalanen at gmail.com
Thu Nov 3 05:11:32 PDT 2011


Fork and exec desktop-shell in the compositor. This is a way to create
an authenticated client. Later, the desktop-shell interface will be
reserved for this client only.

For exec to work, the compositor should be started from the
wayland-demos' root directory.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 clients/desktop-shell.c |    3 ++
 compositor/shell.c      |   66 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 0 deletions(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index 016d720..b915723 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -323,6 +323,9 @@ int main(int argc, char *argv[])
 		return -1;
 	}
 
+	/* The fd is our private, do not confuse our children with it. */
+	unsetenv("WAYLAND_SOCKET");
+
 	wl_display_add_global_listener(display_get_display(desktop.display),
 				       global_handler, &desktop);
 
diff --git a/compositor/shell.c b/compositor/shell.c
index 50c80e9..1407272 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -25,6 +25,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <linux/input.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <fcntl.h>
 
 #include "wayland-server.h"
 #include "compositor.h"
@@ -37,6 +40,11 @@ struct wl_shell {
 	struct wl_listener panel_listener;
 	struct wlsc_surface *background;
 	struct wl_listener background_listener;
+
+	struct {
+		struct wlsc_process process;
+		struct wl_client *client;
+	} child;
 };
 
 struct wlsc_move_grab {
@@ -926,6 +934,61 @@ attach(struct wlsc_shell *base, struct wlsc_surface *es)
 }
 
 static void
+desktop_shell_sigchld(struct wlsc_process *process, int status)
+{
+	struct wl_shell *shell =
+		container_of(process, struct wl_shell, child.process);
+
+	shell->child.process.pid = 0;
+	shell->child.client = NULL; /* already destroyed by wayland */
+}
+
+static int
+launch_desktop_shell_process(struct wl_shell *shell)
+{
+	const char *shell_exe = "./clients/desktop-shell";
+	struct wlsc_compositor *compositor = shell->compositor;
+	char s[32];
+	int sv[2], flags;
+
+	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
+		fprintf(stderr, "socketpair failed\n");
+		return -1;
+	}
+
+	shell->child.process.pid = fork();
+	shell->child.process.cleanup = desktop_shell_sigchld;
+
+	switch (shell->child.process.pid) {
+	case 0:
+		/* SOCK_CLOEXEC closes both ends, so we need to unset
+		 * the flag on the client fd. */
+		flags = fcntl(sv[1], F_GETFD);
+		if (flags != -1)
+			fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
+
+		snprintf(s, sizeof s, "%d", sv[1]);
+		setenv("WAYLAND_SOCKET", s, 1);
+		if (execl(shell_exe, shell_exe, NULL) < 0)
+			fprintf(stderr, "%s: running '%s' failed: %m\n",
+				__func__, shell_exe);
+		exit(-1);
+
+	default:
+		close(sv[1]);
+		shell->child.client =
+			wl_client_create(compositor->wl_display, sv[0]);
+		wlsc_watch_process(&shell->child.process);
+		break;
+
+	case -1:
+		fprintf(stderr, "%s: fork failed: %m\n", __func__);
+		return -1;
+	}
+	return 0;
+}
+
+static void
 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
 	struct wl_shell *shell = data;
@@ -972,6 +1035,9 @@ shell_init(struct wlsc_compositor *ec)
 				  shell, bind_desktop_shell) == NULL)
 		return -1;
 
+	if (launch_desktop_shell_process(shell) != 0)
+		return -1;
+
 	wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
 				    move_binding, shell);
 	wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
-- 
1.7.3.4



More information about the wayland-devel mailing list