[PATCH] compositor: pass options to the shell process, v2

Pekka Paalanen ppaalanen at gmail.com
Mon Nov 7 01:06:30 PST 2011


When desktop-shell was changed to be launched by the compositor alone,
we also lost the opportunity to give it arguments, specifically the
background picture.

Add the compositor option -b (--shell-options) for passing arguments to
the shell process. The parameter to -b is a comma-separated list of
arguments to the shell.

Option -b cannot be used multiple times, and it cannot be used to pass
arguments containing commas to the shell.

Signed-off-by: Pekka Paalanen <ppaalanen at gmail.com>
---
 compositor/compositor.c         |    9 +++++-
 compositor/meego-tablet-shell.c |    4 +-
 compositor/shell.c              |   50 +++++++++++++++++++++++++-------------
 3 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/compositor/compositor.c b/compositor/compositor.c
index 53b282a..642022e 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -2159,12 +2159,13 @@ int main(int argc, char *argv[])
 	struct wl_event_loop *loop;
 	int o, xserver = 0;
 	void *shell_module, *backend_module;
-	int (*shell_init)(struct wlsc_compositor *ec);
+	int (*shell_init)(struct wlsc_compositor *ec, char *options);
 	struct wlsc_compositor
 		*(*backend_init)(struct wl_display *display, char *options);
 	char *backend = NULL;
 	char *backend_options = "";
 	char *shell = NULL;
+	char *shell_options = NULL;
 	char *p;
 
 	static const char opts[] = "B:b:o:S:i:s:x";
@@ -2174,12 +2175,16 @@ int main(int argc, char *argv[])
 		{ "socket", 1, NULL, 'S' },
 		{ "idle-time", 1, NULL, 'i' },
 		{ "shell", 1, NULL, 's' },
+		{ "shell-options", 1, NULL, 'b' },
 		{ "xserver", 0, NULL, 'x' },
 		{ NULL, }
 	};
 
 	while (o = getopt_long(argc, argv, opts, longopts, &o), o > 0) {
 		switch (o) {
+		case 'b':
+			shell_options = optarg;
+			break;
 		case 'B':
 			backend = optarg;
 			break;
@@ -2245,7 +2250,7 @@ int main(int argc, char *argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (shell_init(ec) < 0)
+	if (shell_init(ec, shell_options) < 0)
 		exit(EXIT_FAILURE);
 
 	if (xserver)
diff --git a/compositor/meego-tablet-shell.c b/compositor/meego-tablet-shell.c
index 35b9775..9c64405 100644
--- a/compositor/meego-tablet-shell.c
+++ b/compositor/meego-tablet-shell.c
@@ -638,10 +638,10 @@ bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 }
 
 void
-shell_init(struct wlsc_compositor *compositor);
+shell_init(struct wlsc_compositor *compositor, char *options);
 
 WL_EXPORT void
-shell_init(struct wlsc_compositor *compositor)
+shell_init(struct wlsc_compositor *compositor, char *options)
 {
 	struct meego_tablet_shell *shell;
 	struct wl_event_loop *loop;
diff --git a/compositor/shell.c b/compositor/shell.c
index ed2637d..7af2d86 100644
--- a/compositor/shell.c
+++ b/compositor/shell.c
@@ -943,13 +943,39 @@ desktop_shell_sigchld(struct wlsc_process *process, int status)
 	shell->child.client = NULL; /* already destroyed by wayland */
 }
 
+static void
+child_exec(int sockfd, const char *path, char *options)
+{
+	const int argc_max = 16;
+	char *argv[argc_max + 1];
+	int i = 0;
+	char s[32];
+	int flags;
+
+	argv[i] = (char *)path;
+	while (argv[i] && i < argc_max)
+		argv[++i] = strsep(&options, ",");
+	argv[i] = NULL;
+
+	/* SOCK_CLOEXEC closes both ends, so we need to unset
+	 * the flag on the client fd. */
+	flags = fcntl(sockfd, F_GETFD);
+	if (flags != -1)
+		fcntl(sockfd, F_SETFD, flags & ~FD_CLOEXEC);
+
+	snprintf(s, sizeof s, "%d", sockfd);
+	setenv("WAYLAND_SOCKET", s, 1);
+
+	if (execv(path, argv) < 0)
+		fprintf(stderr, "running '%s' failed: %m\n", path);
+}
+
 static int
-launch_desktop_shell_process(struct wl_shell *shell)
+launch_desktop_shell_process(struct wl_shell *shell, char *options)
 {
 	const char *shell_exe = "./clients/desktop-shell";
 	struct wlsc_compositor *compositor = shell->compositor;
-	char s[32];
-	int sv[2], flags;
+	int sv[2];
 
 	if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
 		fprintf(stderr, "socketpair failed\n");
@@ -961,17 +987,7 @@ launch_desktop_shell_process(struct wl_shell *shell)
 
 	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);
+		child_exec(sv[1], shell_exe, options);
 		exit(-1);
 
 	default:
@@ -1017,10 +1033,10 @@ bind_desktop_shell(struct wl_client *client,
 }
 
 int
-shell_init(struct wlsc_compositor *ec);
+shell_init(struct wlsc_compositor *ec, char *options);
 
 WL_EXPORT int
-shell_init(struct wlsc_compositor *ec)
+shell_init(struct wlsc_compositor *ec, char *options)
 {
 	struct wl_shell *shell;
 
@@ -1044,7 +1060,7 @@ shell_init(struct wlsc_compositor *ec)
 				  shell, bind_desktop_shell) == NULL)
 		return -1;
 
-	if (launch_desktop_shell_process(shell) != 0)
+	if (launch_desktop_shell_process(shell, options) != 0)
 		return -1;
 
 	wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
-- 
1.7.3.4



More information about the wayland-devel mailing list