diff --git a/compositor/compositor.c b/compositor/compositor.c index 2c04c3b4..79440fdf 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -83,6 +85,75 @@ wlsc_watch_process(struct wlsc_process *process) wl_list_insert(&child_process_list, &process->link); } +static void +child_client_exec(int sockfd, const char *path) +{ + int flags; + char s[32]; + + /* 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 (execl(path, path, NULL) < 0) + fprintf(stderr, "compositor: executing '%s' failed: %m\n", + path); +} + +WL_EXPORT struct wl_client * +wlsc_client_launch(struct wlsc_compositor *compositor, + struct wlsc_process *proc, + const char *path, + wlsc_process_cleanup_func_t cleanup) +{ + int sv[2]; + pid_t pid; + struct wl_client *client; + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) { + fprintf(stderr, "wlsc_client_launch: " + "socketpair failed while launching '%s': %m\n", + path); + return NULL; + } + + pid = fork(); + if (pid == -1) { + close(sv[0]); + close(sv[1]); + fprintf(stderr, "wlsc_client_launch: " + "fork failed while launching '%s': %m\n", path); + return NULL; + } + + if (pid == 0) { + child_client_exec(sv[1], path); + exit(-1); + } + + close(sv[1]); + + client = wl_client_create(compositor->wl_display, sv[0]); + if (!client) { + close(sv[0]); + fprintf(stderr, "wlsc_client_launch: " + "wl_client_create failed while launching '%s'.\n", + path); + return NULL; + } + + proc->pid = pid; + proc->cleanup = cleanup; + wlsc_watch_process(proc); + + return client; +} + static void surface_handle_buffer_destroy(struct wl_listener *listener, struct wl_resource *resource, uint32_t time) diff --git a/compositor/compositor.h b/compositor/compositor.h index 1d551584..7f1dd74c 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -418,12 +418,22 @@ uint32_t * wlsc_load_image(const char *filename, int32_t *width_arg, int32_t *height_arg, uint32_t *stride_arg); +struct wlsc_process; +typedef void (*wlsc_process_cleanup_func_t)(struct wlsc_process *process, + int status); + struct wlsc_process { pid_t pid; - void (*cleanup)(struct wlsc_process *process, int status); + wlsc_process_cleanup_func_t cleanup; struct wl_list link; }; +struct wl_client * +wlsc_client_launch(struct wlsc_compositor *compositor, + struct wlsc_process *proc, + const char *path, + wlsc_process_cleanup_func_t cleanup); + int wlsc_data_device_manager_init(struct wlsc_compositor *compositor); void diff --git a/compositor/shell.c b/compositor/shell.c index b7cfdd33..e1049417 100644 --- a/compositor/shell.c +++ b/compositor/shell.c @@ -27,9 +27,6 @@ #include #include #include -#include -#include -#include #include #include @@ -880,44 +877,14 @@ static int launch_desktop_shell_process(struct wl_shell *shell) { const char *shell_exe = LIBEXECDIR "/wayland-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); + shell->child.client = wlsc_client_launch(shell->compositor, + &shell->child.process, + shell_exe, + desktop_shell_sigchld); - 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__); + if (!shell->child.client) return -1; - } return 0; } diff --git a/compositor/tablet-shell.c b/compositor/tablet-shell.c index 416a971f..6901acdf 100644 --- a/compositor/tablet-shell.c +++ b/compositor/tablet-shell.c @@ -25,9 +25,6 @@ #include #include #include -#include -#include -#include #include #include "compositor.h" @@ -369,43 +366,10 @@ static void launch_ux_daemon(struct tablet_shell *shell) { const char *shell_exe = LIBEXECDIR "/wayland-tablet-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; - } - - shell->process.pid = fork(); - shell->process.cleanup = tablet_shell_sigchld; - - switch (shell->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, "exec failed: %m\n"); - exit(-1); - - default: - close(sv[1]); - shell->client = - wl_client_create(compositor->wl_display, sv[0]); - wlsc_watch_process(&shell->process); - break; - - case -1: - fprintf(stderr, "failed to fork\n"); - break; - } + shell->client = wlsc_client_launch(shell->compositor, + &shell->process, + shell_exe, tablet_shell_sigchld); } static void