Add exec bind action

This commit is contained in:
Mildred Ki'Lya 2023-01-18 00:41:46 +01:00
parent b81b98d47c
commit 0c252d1b05
7 changed files with 43 additions and 10 deletions

View file

@ -108,6 +108,7 @@ static const char *const binding_action_map[] = {
[BIND_ACTION_MINIMIZE] = "minimize", [BIND_ACTION_MINIMIZE] = "minimize",
[BIND_ACTION_MAXIMIZE] = "maximize", [BIND_ACTION_MAXIMIZE] = "maximize",
[BIND_ACTION_FULLSCREEN] = "fullscreen", [BIND_ACTION_FULLSCREEN] = "fullscreen",
[BIND_ACTION_EXEC] = "exec",
[BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback", [BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback",
[BIND_ACTION_PIPE_VIEW] = "pipe-visible", [BIND_ACTION_PIPE_VIEW] = "pipe-visible",
[BIND_ACTION_PIPE_SELECTED] = "pipe-selected", [BIND_ACTION_PIPE_SELECTED] = "pipe-selected",

View file

@ -812,6 +812,20 @@ e.g. *search-start=none*.
Default: _not bound_ Default: _not bound_
*exec*
Executes a slave process bound to the same tty as the main
session process. The syntax is similar to *pipe-visible* and
similar bindings.
Note that the process is controlling the tty at the same time
as the currently running process and it can mess up completely
the terminal state. Be careful of what you configure.
Example:
*exec=[clear] Control+Shift+l*
Default: _not bound_
*show-urls-launch* *show-urls-launch*
Enter URL mode, where all currently visible URLs are tagged with a Enter URL mode, where all currently visible URLs are tagged with a
jump label with a key sequence that will open the URL (and exit jump label with a key sequence that will open the URL (and exit

17
input.c
View file

@ -42,6 +42,7 @@
#include "vt.h" #include "vt.h"
#include "xmalloc.h" #include "xmalloc.h"
#include "xsnprintf.h" #include "xsnprintf.h"
#include "slave.h"
struct pipe_context { struct pipe_context {
char *text; char *text;
@ -204,6 +205,22 @@ execute_binding(struct seat *seat, struct terminal *term,
xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL); xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL);
return true; return true;
case BIND_ACTION_EXEC:
if (binding->aux->type != BINDING_AUX_PIPE)
return true;
int argc = 0;
while(binding->aux->pipe.args[argc]) argc++;
if (slave_spawn(
term->ptmx, argc, term->cwd, binding->aux->pipe.args, NULL,
&term->conf->env_vars, term->conf->term, NULL, false, false, NULL) == -1) {
LOG_ERRNO("failed to spawn slave for exec action");
return true;
}
return true;
case BIND_ACTION_PIPE_SCROLLBACK: case BIND_ACTION_PIPE_SCROLLBACK:
if (term->grid == &term->alt) if (term->grid == &term->alt)
break; break;

View file

@ -29,6 +29,7 @@ enum bind_action_normal {
BIND_ACTION_MINIMIZE, BIND_ACTION_MINIMIZE,
BIND_ACTION_MAXIMIZE, BIND_ACTION_MAXIMIZE,
BIND_ACTION_FULLSCREEN, BIND_ACTION_FULLSCREEN,
BIND_ACTION_EXEC,
BIND_ACTION_PIPE_SCROLLBACK, BIND_ACTION_PIPE_SCROLLBACK,
BIND_ACTION_PIPE_VIEW, BIND_ACTION_PIPE_VIEW,
BIND_ACTION_PIPE_SELECTED, BIND_ACTION_PIPE_SELECTED,

16
slave.c
View file

@ -205,16 +205,16 @@ emit_notifications(int fd, const user_notifications_t *notifications)
static noreturn void static noreturn void
slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd, slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
bool login_shell, const user_notifications_t *notifications) bool login_shell, bool init, const user_notifications_t *notifications)
{ {
int pts = -1; int pts = -1;
const char *pts_name = ptsname(ptmx); const char *pts_name = ptsname(ptmx);
if (grantpt(ptmx) == -1) { if (init && grantpt(ptmx) == -1) {
LOG_ERRNO("failed to grantpt()"); LOG_ERRNO("failed to grantpt()");
goto err; goto err;
} }
if (unlockpt(ptmx) == -1) { if (init && unlockpt(ptmx) == -1) {
LOG_ERRNO("failed to unlockpt()"); LOG_ERRNO("failed to unlockpt()");
goto err; goto err;
} }
@ -222,7 +222,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
close(ptmx); close(ptmx);
ptmx = -1; ptmx = -1;
if (setsid() == -1) { if (init && setsid() == -1) {
LOG_ERRNO("failed to setsid()"); LOG_ERRNO("failed to setsid()");
goto err; goto err;
} }
@ -233,7 +233,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
goto err; goto err;
} }
if (ioctl(pts, TIOCSCTTY, 0) < 0) { if (init && ioctl(pts, TIOCSCTTY, 0) < 0) {
LOG_ERRNO("failed to configure controlling terminal"); LOG_ERRNO("failed to configure controlling terminal");
goto err; goto err;
} }
@ -254,7 +254,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
} }
#endif #endif
if (tll_length(*notifications) > 0) { if (notifications && tll_length(*notifications) > 0) {
int flags = fcntl(pts, F_GETFL); int flags = fcntl(pts, F_GETFL);
if (flags < 0) if (flags < 0)
goto err; goto err;
@ -307,7 +307,7 @@ pid_t
slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv, slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
char *const *envp, const env_var_list_t *extra_env_vars, char *const *envp, const env_var_list_t *extra_env_vars,
const char *term_env, const char *conf_shell, bool login_shell, const char *term_env, const char *conf_shell, bool login_shell,
const user_notifications_t *notifications) bool init, const user_notifications_t *notifications)
{ {
int fork_pipe[2]; int fork_pipe[2];
if (pipe2(fork_pipe, O_CLOEXEC) < 0) { if (pipe2(fork_pipe, O_CLOEXEC) < 0) {
@ -393,7 +393,7 @@ slave_spawn(int ptmx, int argc, const char *cwd, char *const *argv,
setenv("SHELL", shell_argv[0], 1); setenv("SHELL", shell_argv[0], 1);
slave_exec(ptmx, shell_argv, envp != NULL ? envp : environ, slave_exec(ptmx, shell_argv, envp != NULL ? envp : environ,
fork_pipe[1], login_shell, notifications); fork_pipe[1], login_shell, init, notifications);
BUG("Unexpected return from slave_exec()"); BUG("Unexpected return from slave_exec()");
break; break;

View file

@ -9,5 +9,5 @@
pid_t slave_spawn( pid_t slave_spawn(
int ptmx, int argc, const char *cwd, char *const *argv, char *const *envp, int ptmx, int argc, const char *cwd, char *const *argv, char *const *envp,
const env_var_list_t *extra_env_vars, const char *term_env, const env_var_list_t *extra_env_vars, const char *term_env,
const char *conf_shell, bool login_shell, const char *conf_shell, bool login_shell, bool init,
const user_notifications_t *notifications); const user_notifications_t *notifications);

View file

@ -1336,7 +1336,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
/* Start the slave/client */ /* Start the slave/client */
if ((term->slave = slave_spawn( if ((term->slave = slave_spawn(
term->ptmx, argc, term->cwd, argv, envp, &conf->env_vars, term->ptmx, argc, term->cwd, argv, envp, &conf->env_vars,
conf->term, conf->shell, conf->login_shell, conf->term, conf->shell, conf->login_shell, true,
&conf->notifications)) == -1) &conf->notifications)) == -1)
{ {
goto err; goto err;