Implement --hold

When specified, we don't exit when the slave/client process exits.
This commit is contained in:
Daniel Eklöf 2020-02-03 19:58:32 +01:00
parent 31baf334b3
commit 8f4ec9aa47
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 36 additions and 12 deletions

View file

@ -7,6 +7,7 @@ _arguments \
'(-t --term)'{-t,--term}'[value to set the environment variable TERM to (foot)]:term:->terms' \ '(-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:()' \ '(-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' \ '(-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]' \ '(-v --version)'{-v,--version}'[show the version number and quit]' \
'(-h --help)'{-h,--help}'[show help message and quit]' '(-h --help)'{-h,--help}'[show help message and quit]'

View file

@ -511,6 +511,8 @@ config_load(struct config *conf, const char *conf_path)
.render_worker_count = sysconf(_SC_NPROCESSORS_ONLN), .render_worker_count = sysconf(_SC_NPROCESSORS_ONLN),
.server_socket_path = get_server_socket_path(), .server_socket_path = get_server_socket_path(),
.presentation_timings = false,
.hold_at_exit = false,
}; };
char *default_path = NULL; char *default_path = NULL;

View file

@ -36,6 +36,7 @@ struct config {
size_t render_worker_count; size_t render_worker_count;
char *server_socket_path; char *server_socket_path;
bool presentation_timings; bool presentation_timings;
bool hold_at_exit;
}; };
bool config_load(struct config *conf, const char *path); bool config_load(struct config *conf, const char *path);

View file

@ -62,6 +62,9 @@ execute (instead of the shell).
*XDG\_RUNTIME\_DIR/foot.sock*. If you do so, you will need to use *XDG\_RUNTIME\_DIR/foot.sock*. If you do so, you will need to use
the *--server-socket* option in *footclient*(1). the *--server-socket* option in *footclient*(1).
*--hold*
Remain open after child process exits.
*-v*,*--version* *-v*,*--version*
Show the version number and quit. Show the version number and quit.

8
main.c
View file

@ -47,6 +47,7 @@ print_usage(const char *prog_name)
" -g,--geometry=WIDTHxHEIGHT set initial width and height\n" " -g,--geometry=WIDTHxHEIGHT set initial width and height\n"
" -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\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" " 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", " -v,--version show the version number and quit\n",
prog_name, prog_name); prog_name, prog_name);
} }
@ -96,6 +97,7 @@ main(int argc, char *const *argv)
{"font", required_argument, NULL, 'f'}, {"font", required_argument, NULL, 'f'},
{"geometry", required_argument, NULL, 'g'}, {"geometry", required_argument, NULL, 'g'},
{"server", optional_argument, NULL, 's'}, {"server", optional_argument, NULL, 's'},
{"hold", no_argument, NULL, 'H'},
{"presentation-timings", no_argument, NULL, 'p'}, /* Undocumented */ {"presentation-timings", no_argument, NULL, 'p'}, /* Undocumented */
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
@ -110,6 +112,7 @@ main(int argc, char *const *argv)
bool as_server = false; bool as_server = false;
const char *conf_server_socket_path = NULL; const char *conf_server_socket_path = NULL;
bool presentation_timings = false; bool presentation_timings = false;
bool hold = false;
while (true) { while (true) {
int c = getopt_long(argc, argv, "c:tf:g:s::pvh", longopts, NULL); 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; presentation_timings = true;
break; break;
case 'H':
hold = true;
break;
case 'v': case 'v':
printf("foot version %s\n", FOOT_VERSION); printf("foot version %s\n", FOOT_VERSION);
return EXIT_SUCCESS; return EXIT_SUCCESS;
@ -216,6 +223,7 @@ main(int argc, char *const *argv)
conf.server_socket_path = strdup(conf_server_socket_path); conf.server_socket_path = strdup(conf_server_socket_path);
} }
conf.presentation_timings = presentation_timings; conf.presentation_timings = presentation_timings;
conf.hold_at_exit = hold;
struct fdm *fdm = NULL; struct fdm *fdm = NULL;
struct wayland *wayl = NULL; struct wayland *wayl = NULL;

View file

@ -36,6 +36,11 @@ static const char *const XCURSOR_HAND2 = "hand2";
bool bool
term_to_slave(struct terminal *term, const void *_data, size_t len) 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; size_t async_idx = 0;
if (tll_length(term->ptmx_buffer) > 0) { if (tll_length(term->ptmx_buffer) > 0) {
/* With a non-empty queue, EPOLLOUT has already been enabled */ /* 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; struct terminal *term = data;
bool pollin = events & EPOLLIN; const bool pollin = events & EPOLLIN;
bool pollout = events & EPOLLOUT; const bool pollout = events & EPOLLOUT;
bool hup = events & EPOLLHUP; const bool hup = events & EPOLLHUP;
if (hup) {
/* TODO: should we *not* ignore pollin? */
return term_shutdown(term);
}
if (pollout) { if (pollout) {
if (!fdm_ptmx_out(fdm, fd, events, data)) if (!fdm_ptmx_out(fdm, fd, events, data))
return false; return false;
} }
#if 0
if (!pollin) if (!pollin)
return true; return true;
#endif
uint8_t buf[24 * 1024]; 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) { if (count < 0) {
LOG_ERRNO("failed to read from pseudo terminal"); LOG_ERRNO("failed to read from pseudo terminal");
@ -225,9 +227,14 @@ fdm_ptmx(struct fdm *fdm, int fd, int events, void *data)
} else } else
term->render.pending = true; term->render.pending = true;
if (events & EPOLLHUP) if (hup) {
return term_shutdown(term); if (term->hold_at_exit) {
fdm_del(fdm, fd);
term->ptmx = -1;
return true;
} else
return term_shutdown(term);
}
return true; return true;
} }
@ -672,6 +679,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.lower_fd = delay_lower_fd, .lower_fd = delay_lower_fd,
.upper_fd = delay_upper_fd, .upper_fd = delay_upper_fd,
}, },
.hold_at_exit = conf->hold_at_exit,
.shutdown_cb = shutdown_cb, .shutdown_cb = shutdown_cb,
.shutdown_data = shutdown_data, .shutdown_data = shutdown_data,
.foot_exe = strdup(foot_exe), .foot_exe = strdup(foot_exe),

View file

@ -340,6 +340,7 @@ struct terminal {
int upper_fd; int upper_fd;
} delayed_render_timer; } delayed_render_timer;
bool hold_at_exit;
bool is_shutting_down; bool is_shutting_down;
void (*shutdown_cb)(void *data, int exit_code); void (*shutdown_cb)(void *data, int exit_code);
void *shutdown_data; void *shutdown_data;