swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit d82a7211d14b8b1e3b03613ef26aa66a5d0426ed
parent ce2565fdca2f7bda7ecdb166726c138a88313d69
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 30 Apr 2016 02:55:56 -0700

launch: Use posix_spawn

Diffstat:
Mlaunch/launch.c | 107+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 45 insertions(+), 62 deletions(-)

diff --git a/launch/launch.c b/launch/launch.c @@ -1,6 +1,6 @@ /* swc: launch/launch.c * - * Copyright (c) 2013, 2014 Michael Forney + * Copyright (c) 2013, 2014, 2016 Michael Forney * * Based in part upon weston-launch.c from weston which is: * @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdbool.h> #include <string.h> +#include <spawn.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> @@ -405,14 +406,29 @@ error0: exit(EXIT_FAILURE); } +static void +run(int fd) { + struct pollfd pollfd = { .fd = fd, .events = POLLIN }; + + for (;;) { + if (poll(&pollfd, 1, -1) < 0) { + if (errno == EINTR) + continue; + die("poll:"); + } + handle_socket_data(pollfd.fd); + } +} + int main(int argc, char *argv[]) { int option; - int sockets[2]; - char *vt = NULL, vt_buf[64]; + int sock[2]; + char *vt = NULL, buf[64]; struct sigaction action = { 0 }; sigset_t set; + posix_spawnattr_t attr; while ((option = getopt(argc, argv, "ns:t:")) != -1) { switch (option) { @@ -433,12 +449,12 @@ main(int argc, char *argv[]) if (argc - optind < 1) usage(argv[0]); - if (socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, sockets) == -1) + if (socketpair(AF_LOCAL, SOCK_SEQPACKET, 0, sock) == -1) die("socketpair:"); - launcher.socket = sockets[0]; + launcher.socket = sock[0]; - if (fcntl(sockets[0], F_SETFD, FD_CLOEXEC) == -1) + if (fcntl(sock[0], F_SETFD, FD_CLOEXEC) == -1) die("failed set CLOEXEC on socket:"); action.sa_handler = &handle_chld; @@ -468,68 +484,35 @@ main(int argc, char *argv[]) sigprocmask(SIG_SETMASK, &set, NULL); if (!vt) { - find_vt(vt_buf, sizeof vt_buf); - vt = vt_buf; + find_vt(buf, sizeof(buf)); + vt = buf; } fprintf(stderr, "running on %s\n", vt); launcher.tty_fd = open_tty(vt); setup_tty(launcher.tty_fd); - child_pid = fork(); - - if (child_pid == 0) { - char string[64]; - - /* Reset signal handlers to defaults */ - action.sa_handler = SIG_DFL; - if (sigaction(SIGCHLD, &action, NULL) == -1) - die("failed to set default signal handler for SIGCHLD:"); - if (sigaction(SIGUSR1, &action, NULL) == -1) - die("failed to set default signal handler for SIGUSR1:"); - if (sigaction(SIGUSR2, &action, NULL) == -1) - die("failed to set default signal handler for SIGUSR2:"); - if (sigaction(SIGINT, &action, NULL) == -1) - die("failed to set default signal handler for SIGINT:"); - if (sigaction(SIGTERM, &action, NULL) == -1) - die("failed to set default signal handler for SIGTERM:"); - - /* Set empty signal mask */ - sigemptyset(&set); - sigprocmask(SIG_SETMASK, &set, NULL); - - sprintf(string, "%d", sockets[1]); - setenv(SWC_LAUNCH_SOCKET_ENV, string, 1); - - sprintf(string, "%d", launcher.tty_fd); - setenv(SWC_LAUNCH_TTY_FD_ENV, string, 1); - - if (setuid(getuid()) < 0) - die("setuid:"); - if (setgid(getgid()) < 0) - die("setgid:"); - - execvp(argv[optind], argv + optind); - die("exec %s:", argv[optind]); - } else { - struct pollfd pollfd; - int ret; - - pollfd.fd = sockets[0]; - pollfd.events = POLLIN; - - while (true) { - ret = poll(&pollfd, 1, -1); - - if (ret == -1) { - if (errno == EINTR) - continue; - die("poll:"); - } - - handle_socket_data(pollfd.fd); - } - } + sprintf(buf, "%d", sock[1]); + setenv(SWC_LAUNCH_SOCKET_ENV, buf, 1); + sprintf(buf, "%d", launcher.tty_fd); + setenv(SWC_LAUNCH_TTY_FD_ENV, buf, 1); + + if (posix_spawnattr_setflags(&attr, POSIX_SPAWN_RESETIDS | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK) < 0) + die("failed to set spawnattr flags:"); + sigemptyset(&set); + if (posix_spawnattr_setsigmask(&attr, &set) < 0) + die("failed to set spawnattr sigmask:"); + sigaddset(&set, SIGCHLD); + sigaddset(&set, SIGUSR1); + sigaddset(&set, SIGUSR2); + sigaddset(&set, SIGINT); + sigaddset(&set, SIGTERM); + if (posix_spawnattr_setsigdefault(&attr, &set) < 0) + die("failed to set spawnattr sigdefault:"); + if (posix_spawnp(&child_pid, argv[optind], NULL, &attr, argv + optind, environ) < 0) + die("failed to spawn server:"); + + run(sock[0]); return EXIT_SUCCESS; }