From 8f4ec9aa479c5414661a7507543e6a59e4e1f6da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 3 Feb 2020 19:58:32 +0100 Subject: [PATCH] Implement --hold When specified, we don't exit when the slave/client process exits. --- completions/zsh/_foot | 1 + config.c | 2 ++ config.h | 1 + doc/foot.1.scd | 3 +++ main.c | 8 ++++++++ terminal.c | 32 ++++++++++++++++++++------------ terminal.h | 1 + 7 files changed, 36 insertions(+), 12 deletions(-) diff --git a/completions/zsh/_foot b/completions/zsh/_foot index bd74e118..a6d19f9a 100644 --- a/completions/zsh/_foot +++ b/completions/zsh/_foot @@ -7,6 +7,7 @@ _arguments \ '(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \ '(-g --geometry)'{-g,--geometry}'[window WIDTHxHEIGHT, in pixels (80x24 cells)]:geometry:()' \ '(-s --server)'{-s,--server}'[run as server; open terminals by running footclient]:server:_files' \ + '--hold[remain open after child process exits]:hold:()' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \ '(-h --help)'{-h,--help}'[show help message and quit]' diff --git a/config.c b/config.c index 133cecee..80e0e868 100644 --- a/config.c +++ b/config.c @@ -511,6 +511,8 @@ config_load(struct config *conf, const char *conf_path) .render_worker_count = sysconf(_SC_NPROCESSORS_ONLN), .server_socket_path = get_server_socket_path(), + .presentation_timings = false, + .hold_at_exit = false, }; char *default_path = NULL; diff --git a/config.h b/config.h index 30e18f25..2fb82151 100644 --- a/config.h +++ b/config.h @@ -36,6 +36,7 @@ struct config { size_t render_worker_count; char *server_socket_path; bool presentation_timings; + bool hold_at_exit; }; bool config_load(struct config *conf, const char *path); diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 08c65e46..0cb1235c 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -62,6 +62,9 @@ execute (instead of the shell). *XDG\_RUNTIME\_DIR/foot.sock*. If you do so, you will need to use the *--server-socket* option in *footclient*(1). +*--hold* + Remain open after child process exits. + *-v*,*--version* Show the version number and quit. diff --git a/main.c b/main.c index e418b584..ba13ea93 100644 --- a/main.c +++ b/main.c @@ -47,6 +47,7 @@ print_usage(const char *prog_name) " -g,--geometry=WIDTHxHEIGHT set initial width and height\n" " -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n" " Without PATH, XDG_RUNTIME_DIR/foot.sock will be used.\n" + " --hold remain open after child process exits\n" " -v,--version show the version number and quit\n", prog_name, prog_name); } @@ -96,6 +97,7 @@ main(int argc, char *const *argv) {"font", required_argument, NULL, 'f'}, {"geometry", required_argument, NULL, 'g'}, {"server", optional_argument, NULL, 's'}, + {"hold", no_argument, NULL, 'H'}, {"presentation-timings", no_argument, NULL, 'p'}, /* Undocumented */ {"version", no_argument, NULL, 'v'}, {"help", no_argument, NULL, 'h'}, @@ -110,6 +112,7 @@ main(int argc, char *const *argv) bool as_server = false; const char *conf_server_socket_path = NULL; bool presentation_timings = false; + bool hold = false; while (true) { int c = getopt_long(argc, argv, "c:tf:g:s::pvh", longopts, NULL); @@ -169,6 +172,10 @@ main(int argc, char *const *argv) presentation_timings = true; break; + case 'H': + hold = true; + break; + case 'v': printf("foot version %s\n", FOOT_VERSION); return EXIT_SUCCESS; @@ -216,6 +223,7 @@ main(int argc, char *const *argv) conf.server_socket_path = strdup(conf_server_socket_path); } conf.presentation_timings = presentation_timings; + conf.hold_at_exit = hold; struct fdm *fdm = NULL; struct wayland *wayl = NULL; diff --git a/terminal.c b/terminal.c index 26c2163f..69f3c5d2 100644 --- a/terminal.c +++ b/terminal.c @@ -36,6 +36,11 @@ static const char *const XCURSOR_HAND2 = "hand2"; bool term_to_slave(struct terminal *term, const void *_data, size_t len) { + if (term->ptmx < 0) { + /* We're probably in "hold" */ + return false; + } + size_t async_idx = 0; if (tll_length(term->ptmx_buffer) > 0) { /* With a non-empty queue, EPOLLOUT has already been enabled */ @@ -128,25 +133,22 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) { struct terminal *term = data; - bool pollin = events & EPOLLIN; - bool pollout = events & EPOLLOUT; - bool hup = events & EPOLLHUP; - - if (hup) { - /* TODO: should we *not* ignore pollin? */ - return term_shutdown(term); - } + const bool pollin = events & EPOLLIN; + const bool pollout = events & EPOLLOUT; + const bool hup = events & EPOLLHUP; if (pollout) { if (!fdm_ptmx_out(fdm, fd, events, data)) return false; } +#if 0 if (!pollin) return true; +#endif uint8_t buf[24 * 1024]; - ssize_t count = read(term->ptmx, buf, sizeof(buf)); + ssize_t count = pollin ? read(term->ptmx, buf, sizeof(buf)) : 0; if (count < 0) { LOG_ERRNO("failed to read from pseudo terminal"); @@ -225,9 +227,14 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data) } else term->render.pending = true; - if (events & EPOLLHUP) - return term_shutdown(term); - + if (hup) { + if (term->hold_at_exit) { + fdm_del(fdm, fd); + term->ptmx = -1; + return true; + } else + return term_shutdown(term); + } return true; } @@ -672,6 +679,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl, .lower_fd = delay_lower_fd, .upper_fd = delay_upper_fd, }, + .hold_at_exit = conf->hold_at_exit, .shutdown_cb = shutdown_cb, .shutdown_data = shutdown_data, .foot_exe = strdup(foot_exe), diff --git a/terminal.h b/terminal.h index b9db2bfe..cf691f5e 100644 --- a/terminal.h +++ b/terminal.h @@ -340,6 +340,7 @@ struct terminal { int upper_fd; } delayed_render_timer; + bool hold_at_exit; bool is_shutting_down; void (*shutdown_cb)(void *data, int exit_code); void *shutdown_data;