From 6cb6fe265eb8c066fce8ce12473d6b8135f3b3cb Mon Sep 17 00:00:00 2001 From: Alyssa Ross Date: Fri, 10 Dec 2021 17:40:59 +0000 Subject: [PATCH] Add support for opening an existing PTY --- main.c | 12 +++++++++- server.c | 2 +- terminal.c | 65 +++++++++++++++++++++++++++++++----------------------- terminal.h | 2 +- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/main.c b/main.c index 4f2dc7b6..d1307a84 100644 --- a/main.c +++ b/main.c @@ -152,6 +152,10 @@ print_pid(const char *pid_file, bool *unlink_at_exit) return false; } +enum { + PTY_OPTION = CHAR_MAX + 1, +}; + int main(int argc, char *const *argv) { @@ -187,6 +191,7 @@ main(int argc, char *const *argv) {"maximized", no_argument, NULL, 'm'}, {"fullscreen", no_argument, NULL, 'F'}, {"presentation-timings", no_argument, NULL, 'P'}, /* Undocumented */ + {"pty", required_argument, NULL, PTY_OPTION}, {"print-pid", required_argument, NULL, 'p'}, {"log-level", required_argument, NULL, 'd'}, {"log-colorize", optional_argument, NULL, 'l'}, @@ -202,6 +207,7 @@ main(int argc, char *const *argv) const char *conf_title = NULL; const char *conf_app_id = NULL; const char *custom_cwd = NULL; + const char *pty_path = NULL; bool login_shell = false; tll(char *) conf_fonts = tll_init(); enum conf_size_type conf_size_type = CONF_SIZE_PX; @@ -320,6 +326,10 @@ main(int argc, char *const *argv) conf_server_socket_path = optarg; break; + case PTY_OPTION: + pty_path = optarg; + break; + case 'P': presentation_timings = true; break; @@ -538,7 +548,7 @@ main(int argc, char *const *argv) goto out; if (!as_server && (term = term_init( - &conf, fdm, reaper, wayl, "foot", cwd, token, + &conf, fdm, reaper, wayl, "foot", cwd, token, pty_path, argc, argv, &term_shutdown_cb, &shutdown_ctx)) == NULL) { goto out; diff --git a/server.c b/server.c index 1d31abc6..190d224d 100644 --- a/server.c +++ b/server.c @@ -315,7 +315,7 @@ fdm_client(struct fdm *fdm, int fd, int events, void *data) instance->terminal = term_init( conf != NULL ? conf : server->conf, server->fdm, server->reaper, server->wayl, "footclient", cwd, token, - cdata.argc, argv, &term_shutdown_handler, instance); + NULL, cdata.argc, argv, &term_shutdown_handler, instance); if (instance->terminal == NULL) { LOG_ERR("failed to instantiate new terminal"); diff --git a/terminal.c b/terminal.c index ac887412..e11ef0d6 100644 --- a/terminal.c +++ b/terminal.c @@ -327,6 +327,7 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) if (hup) { fdm_del(fdm, fd); term->ptmx = -1; + term_shutdown(term); } return true; @@ -1035,10 +1036,12 @@ load_fonts_from_conf(struct terminal *term) static void fdm_client_terminated( struct reaper *reaper, pid_t pid, int status, void *data); +static const int PTY_OPEN_FLAGS = O_RDWR | O_NOCTTY; + struct terminal * term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, struct wayland *wayl, const char *foot_exe, const char *cwd, - const char *token, int argc, char *const *argv, + const char *token, const char *pty_path, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data) { int ptmx = -1; @@ -1054,7 +1057,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, return NULL; } - if ((ptmx = posix_openpt(O_RDWR | O_NOCTTY)) < 0) { + ptmx = pty_path ? open(pty_path, PTY_OPEN_FLAGS) : posix_openpt(PTY_OPEN_FLAGS); + if (ptmx < 0) { LOG_ERRNO("failed to open PTY"); goto close_fds; } @@ -1116,6 +1120,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .fdm = fdm, .reaper = reaper, .conf = conf, + .slave = -1, .ptmx = ptmx, .ptmx_buffers = tll_init(), .ptmx_paste_buffers = tll_init(), @@ -1237,16 +1242,18 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, } term->font_line_height = conf->line_height; - /* Start the slave/client */ - if ((term->slave = slave_spawn( - term->ptmx, argc, term->cwd, argv, - conf->term, conf->shell, conf->login_shell, - &conf->notifications)) == -1) - { - goto err; - } + if (!pty_path) { + /* Start the slave/client */ + if ((term->slave = slave_spawn( + term->ptmx, argc, term->cwd, argv, + conf->term, conf->shell, conf->login_shell, + &conf->notifications)) == -1) + { + goto err; + } - reaper_add(term->reaper, term->slave, &fdm_client_terminated, term); + reaper_add(term->reaper, term->slave, &fdm_client_terminated, term); + } /* Guess scale; we're not mapped yet, so we don't know on which * output we'll be. Pick highest scale we find for now */ @@ -1506,26 +1513,30 @@ term_shutdown(struct terminal *term) close(term->ptmx); if (!term->shutdown.client_has_terminated) { - LOG_DBG("initiating asynchronous terminate of slave; " - "sending SIGTERM to PID=%u", term->slave); + if (term->slave <= 0) { + term->shutdown.client_has_terminated = true; + } else { + LOG_DBG("initiating asynchronous terminate of slave; " + "sending SIGTERM to PID=%u", term->slave); - kill(-term->slave, SIGTERM); + kill(-term->slave, SIGTERM); - const struct itimerspec timeout = {.it_value = {.tv_sec = 60}}; + const struct itimerspec timeout = {.it_value = {.tv_sec = 60}}; - int timeout_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (timeout_fd < 0 || - timerfd_settime(timeout_fd, 0, &timeout, NULL) < 0 || - !fdm_add(term->fdm, timeout_fd, EPOLLIN, &fdm_terminate_timeout, term)) - { - if (timeout_fd >= 0) - close(timeout_fd); - LOG_ERRNO("failed to create slave terminate timeout FD"); - return false; + int timeout_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (timeout_fd < 0 || + timerfd_settime(timeout_fd, 0, &timeout, NULL) < 0 || + !fdm_add(term->fdm, timeout_fd, EPOLLIN, &fdm_terminate_timeout, term)) + { + if (timeout_fd >= 0) + close(timeout_fd); + LOG_ERRNO("failed to create slave terminate timeout FD"); + return false; + } + + xassert(term->shutdown.terminate_timeout_fd < 0); + term->shutdown.terminate_timeout_fd = timeout_fd; } - - xassert(term->shutdown.terminate_timeout_fd < 0); - term->shutdown.terminate_timeout_fd = timeout_fd; } term->selection.auto_scroll.fd = -1; diff --git a/terminal.h b/terminal.h index 09b04614..3beb3e80 100644 --- a/terminal.h +++ b/terminal.h @@ -671,7 +671,7 @@ struct config; struct terminal *term_init( const struct config *conf, struct fdm *fdm, struct reaper *reaper, struct wayland *wayl, const char *foot_exe, const char *cwd, - const char *token, int argc, char *const *argv, + const char *token, const char *pty_path, int argc, char *const *argv, void (*shutdown_cb)(void *data, int exit_code), void *shutdown_data); bool term_shutdown(struct terminal *term); -- 2.33.0