From 9cdccdd2ac5140a5a265926501a919a3b86f8d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 15 Jul 2020 12:39:10 +0200 Subject: [PATCH] term: break out fork+exec functionality to a separate file --- meson.build | 1 + spawn.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ spawn.h | 6 +++++ terminal.c | 56 +++-------------------------------------- 4 files changed, 82 insertions(+), 53 deletions(-) create mode 100644 spawn.c create mode 100644 spawn.h diff --git a/meson.build b/meson.build index a64f239f..a7db2105 100644 --- a/meson.build +++ b/meson.build @@ -123,6 +123,7 @@ executable( 'sixel.c', 'sixel.h', 'sixel-hls.c', 'sixel-hls.h', 'slave.c', 'slave.h', + 'spawn.c', 'spawn.h', 'terminal.c', 'terminal.h', 'tokenize.c', 'tokenize.h', 'vt.c', 'vt.h', diff --git a/spawn.c b/spawn.c new file mode 100644 index 00000000..94bbb928 --- /dev/null +++ b/spawn.c @@ -0,0 +1,72 @@ +#include "spawn.h" + +#include +#include +#include + +#include +#include +#include + +#define LOG_MODULE "spawn" +#define LOG_ENABLE_DBG 0 +#include "log.h" + +bool +spawn(struct reaper *reaper, const char *cwd, char *const argv[]) +{ + int pipe_fds[2] = {-1, -1}; + if (pipe2(pipe_fds, O_CLOEXEC) < 0) { + LOG_ERRNO("failed to create pipe"); + goto err; + } + + pid_t pid = fork(); + if (pid < 0) { + LOG_ERRNO("failed to fork"); + goto err; + } + + if (pid == 0) { + /* Child */ + close(pipe_fds[0]); + if ((cwd != NULL && chdir(cwd) < 0) || + //execlp(term->foot_exe, term->foot_exe, NULL) < 0) + execvp(argv[0], argv) < 0) + { + (void)!write(pipe_fds[1], &errno, sizeof(errno)); + _exit(errno); + } + assert(false); + _exit(errno); + } + + /* Parent */ + close(pipe_fds[1]); + + int _errno; + static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch"); + + ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno)); + close(pipe_fds[0]); + + if (ret == 0) { + reaper_add(reaper, pid); + return true; + } else if (ret < 0) { + LOG_ERRNO("failed to read from pipe"); + return false; + } else { + LOG_ERRNO_P("%s: failed to spawn", _errno, argv[0]); + errno = _errno; + waitpid(pid, NULL, 0); + return false; + } + +err: + if (pipe_fds[0] != -1) + close(pipe_fds[0]); + if (pipe_fds[1] != -1) + close(pipe_fds[1]); + return false; +} diff --git a/spawn.h b/spawn.h new file mode 100644 index 00000000..129cadc2 --- /dev/null +++ b/spawn.h @@ -0,0 +1,6 @@ +#pragma once + +#include +#include "reaper.h" + +bool spawn(struct reaper *reaper, const char *cwd, char *const argv[]); diff --git a/terminal.c b/terminal.c index d237de97..53640baa 100644 --- a/terminal.c +++ b/terminal.c @@ -30,6 +30,7 @@ #include "selection.h" #include "sixel.h" #include "slave.h" +#include "spawn.h" #include "util.h" #include "vt.h" @@ -2246,59 +2247,8 @@ term_flash(struct terminal *term, unsigned duration_ms) bool term_spawn_new(const struct terminal *term) { - int pipe_fds[2] = {-1, -1}; - if (pipe2(pipe_fds, O_CLOEXEC) < 0) { - LOG_ERRNO("failed to create pipe"); - goto err; - } - - pid_t pid = fork(); - if (pid < 0) { - LOG_ERRNO("failed to fork new terminal"); - goto err; - } - - if (pid == 0) { - /* Child */ - close(pipe_fds[0]); - if (chdir(term->cwd) < 0 || - execlp(term->foot_exe, term->foot_exe, NULL) < 0) - { - (void)!write(pipe_fds[1], &errno, sizeof(errno)); - _exit(errno); - } - assert(false); - _exit(errno); - } - - /* Parent */ - close(pipe_fds[1]); - - int _errno; - static_assert(sizeof(_errno) == sizeof(errno), "errno size mismatch"); - - ssize_t ret = read(pipe_fds[0], &_errno, sizeof(_errno)); - close(pipe_fds[0]); - - if (ret == 0) { - reaper_add(term->reaper, pid); - return true; - } else if (ret < 0) { - LOG_ERRNO("failed to read from pipe"); - return false; - } else { - LOG_ERRNO_P("%s: failed to spawn new terminal", _errno, term->foot_exe); - errno = _errno; - waitpid(pid, NULL, 0); - return false; - } - -err: - if (pipe_fds[0] != -1) - close(pipe_fds[0]); - if (pipe_fds[1] != -1) - close(pipe_fds[1]); - return false; + return spawn( + term->reaper, term->cwd, (char *const []){term->foot_exe, NULL}); } void