mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
term: break out fork+exec functionality to a separate file
This commit is contained in:
parent
4d17423ed1
commit
9cdccdd2ac
4 changed files with 82 additions and 53 deletions
|
|
@ -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',
|
||||
|
|
|
|||
72
spawn.c
Normal file
72
spawn.c
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include "spawn.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
6
spawn.h
Normal file
6
spawn.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "reaper.h"
|
||||
|
||||
bool spawn(struct reaper *reaper, const char *cwd, char *const argv[]);
|
||||
56
terminal.c
56
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue