term: term_spawn_new(): new function, spawns a new foot/footclient process

Bind ctrl+shift+return to it
This commit is contained in:
Daniel Eklöf 2019-12-21 15:27:17 +01:00
parent 2a95f2949b
commit 57de9feaa5
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
6 changed files with 80 additions and 5 deletions

View file

@ -282,6 +282,11 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial,
search_begin(term);
goto maybe_repeat;
}
else if (sym == XKB_KEY_Return) {
term_spawn_new(term);
goto maybe_repeat;
}
}

5
main.c
View file

@ -223,8 +223,9 @@ main(int argc, char *const *argv)
if ((wayl = wayl_init(fdm)) == NULL)
goto out;
if (!as_server && (term = term_init(&conf, fdm, wayl, conf.term, argc, argv,
&term_shutdown_cb, &shutdown_ctx)) == NULL)
if (!as_server && (term = term_init(
&conf, fdm, wayl, conf.term, prog_name, argc, argv,
&term_shutdown_cb, &shutdown_ctx)) == NULL)
goto out;
if (as_server && (server = server_init(&conf, fdm, wayl)) == NULL)

View file

@ -213,7 +213,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data)
client->term = term_init(
server->conf, server->fdm, server->wayl,
strlen(term_env) > 0 ? term_env : server->conf->term,
argc, argv, &term_shutdown_handler, client);
"footclient" /* TODO */, argc, argv, &term_shutdown_handler, client);
if (client->term == NULL) {
LOG_ERR("failed to instantiate new terminal");

View file

@ -64,6 +64,7 @@ err:
close(pts);
if (ptmx != -1)
close(ptmx);
close(err_fd);
_exit(errno);
}

View file

@ -465,7 +465,7 @@ initialize_fonts(struct terminal *term, const struct config *conf)
struct terminal *
term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
const char *term_env, int argc, char *const *argv,
const char *term_env, const char *foot_exe, int argc, char *const *argv,
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data)
{
int ptmx = -1;
@ -600,6 +600,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
},
.shutdown_cb = shutdown_cb,
.shutdown_data = shutdown_data,
.foot_exe = strdup(foot_exe),
};
initialize_color_cube(term);
@ -830,6 +831,7 @@ term_destroy(struct terminal *term)
free(it->item.data);
tll_free(term->ptmx_buffer);
tll_free(term->tab_stops);
free(term->foot_exe);
int ret = EXIT_SUCCESS;
@ -1642,3 +1644,66 @@ term_flash(struct terminal *term, unsigned duration_ms)
term->flash.active = true;
}
}
bool
term_spawn_new(const struct terminal *term)
{
pid_t pid = fork();
if (pid < 0) {
LOG_ERRNO("failed to fork new terminal");
return false;
}
if (pid == 0) {
/* Child */
int pipe_fds[2] = {-1, -1};
if (pipe2(pipe_fds, O_CLOEXEC) < 0) {
LOG_ERRNO("failed to create pipe");
goto err;
}
/* Double fork */
pid_t pid2 = fork();
if (pid2 < 0) {
LOG_ERRNO("failed to double fork new terminal");
goto err;
}
if (pid2 == 0) {
/* Child */
close(pipe_fds[0]);
execl(term->foot_exe, term->foot_exe, NULL);
write(pipe_fds[1], &errno, sizeof(errno));
_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)
_exit(0);
else if (ret < 0)
LOG_ERRNO("failed to read from pipe");
else {
LOG_ERRNO_P("%s: failed to spawn new terminal", _errno, term->foot_exe);
errno = _errno;
waitpid(pid2, NULL, 0);
}
err:
if (pipe_fds[0] != -1)
close(pipe_fds[0]);
_exit(errno);
}
int result;
waitpid(pid, &result, 0);
return WIFEXITED(result) && WEXITSTATUS(result) == 0;
}

View file

@ -314,12 +314,14 @@ struct terminal {
bool is_shutting_down;
void (*shutdown_cb)(void *data, int exit_code);
void *shutdown_data;
char *foot_exe;
};
struct config;
struct terminal *term_init(
const struct config *conf, struct fdm *fdm, struct wayland *wayl,
const char *term_env, int argc, char *const *argv,
const char *term_env, const char *foot_exe, int argc, char *const *argv,
void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data);
bool term_shutdown(struct terminal *term);
@ -379,3 +381,4 @@ void term_xcursor_update(struct terminal *term);
void term_set_window_title(struct terminal *term, const char *title);
void term_flash(struct terminal *term, unsigned duration_ms);
bool term_spawn_new(const struct terminal *term);