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_MAXIMIZE] = "maximize",
[BIND_ACTION_FULLSCREEN] = "fullscreen",
[BIND_ACTION_EXEC] = "exec",
[BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback",
[BIND_ACTION_PIPE_VIEW] = "pipe-visible",
[BIND_ACTION_PIPE_SELECTED] = "pipe-selected",

View file

@ -812,6 +812,20 @@ e.g. *search-start=none*.
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*
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

17
input.c
View file

@ -42,6 +42,7 @@
#include "vt.h"
#include "xmalloc.h"
#include "xsnprintf.h"
#include "slave.h"
struct pipe_context {
char *text;
@ -204,6 +205,22 @@ execute_binding(struct seat *seat, struct terminal *term,
xdg_toplevel_set_fullscreen(term->window->xdg_toplevel, NULL);
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:
if (term->grid == &term->alt)
break;

View file

@ -29,6 +29,7 @@ enum bind_action_normal {
BIND_ACTION_MINIMIZE,
BIND_ACTION_MAXIMIZE,
BIND_ACTION_FULLSCREEN,
BIND_ACTION_EXEC,
BIND_ACTION_PIPE_SCROLLBACK,
BIND_ACTION_PIPE_VIEW,
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
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;
const char *pts_name = ptsname(ptmx);
if (grantpt(ptmx) == -1) {
if (init && grantpt(ptmx) == -1) {
LOG_ERRNO("failed to grantpt()");
goto err;
}
if (unlockpt(ptmx) == -1) {
if (init && unlockpt(ptmx) == -1) {
LOG_ERRNO("failed to unlockpt()");
goto err;
}
@ -222,7 +222,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
close(ptmx);
ptmx = -1;
if (setsid() == -1) {
if (init && setsid() == -1) {
LOG_ERRNO("failed to setsid()");
goto err;
}
@ -233,7 +233,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
goto err;
}
if (ioctl(pts, TIOCSCTTY, 0) < 0) {
if (init && ioctl(pts, TIOCSCTTY, 0) < 0) {
LOG_ERRNO("failed to configure controlling terminal");
goto err;
}
@ -254,7 +254,7 @@ slave_exec(int ptmx, char *argv[], char *const envp[], int err_fd,
}
#endif
if (tll_length(*notifications) > 0) {
if (notifications && tll_length(*notifications) > 0) {
int flags = fcntl(pts, F_GETFL);
if (flags < 0)
goto err;
@ -307,7 +307,7 @@ pid_t
slave_spawn(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 char *conf_shell, bool login_shell,
const user_notifications_t *notifications)
bool init, const user_notifications_t *notifications)
{
int fork_pipe[2];
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);
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()");
break;

View file

@ -9,5 +9,5 @@
pid_t slave_spawn(
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 char *conf_shell, bool login_shell,
const char *conf_shell, bool login_shell, bool init,
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 */
if ((term->slave = slave_spawn(
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)
{
goto err;