summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2021-01-01 08:36:52 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2021-01-01 08:36:52 +0000
commitfa75537befca06a0d1f1a609874051564636cce6 (patch)
tree247fa199d478ff8fa5978372975c67b5d01ca308 /usr.bin/tmux
parentce97ff30b65ca4aebd54404963024cce7b4feb9b (diff)
Add a -C flag to run-shell to use a tmux command rather than a shell command.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/cmd-run-shell.c87
-rw-r--r--usr.bin/tmux/tmux.127
2 files changed, 83 insertions, 31 deletions
diff --git a/usr.bin/tmux/cmd-run-shell.c b/usr.bin/tmux/cmd-run-shell.c
index d8b4e539a82..053cd6bf49b 100644
--- a/usr.bin/tmux/cmd-run-shell.c
+++ b/usr.bin/tmux/cmd-run-shell.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-run-shell.c,v 1.69 2020/06/12 10:31:12 nicm Exp $ */
+/* $OpenBSD: cmd-run-shell.c,v 1.70 2021/01/01 08:36:51 nicm Exp $ */
/*
* Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org>
@@ -40,8 +40,8 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell",
.alias = "run",
- .args = { "bd:t:", 0, 1 },
- .usage = "[-b] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
+ .args = { "bd:Ct:", 0, 1 },
+ .usage = "[-bC] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@@ -50,13 +50,16 @@ const struct cmd_entry cmd_run_shell_entry = {
};
struct cmd_run_shell_data {
+ struct client *client;
char *cmd;
+ int shell;
char *cwd;
struct cmdq_item *item;
struct session *s;
int wp_id;
struct event timer;
int flags;
+ struct cmd_parse_input pi;
};
static void
@@ -93,49 +96,69 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
struct args *args = cmd_get_args(self);
struct cmd_find_state *target = cmdq_get_target(item);
struct cmd_run_shell_data *cdata;
+ struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct window_pane *wp = target->wp;
const char *delay;
double d;
struct timeval tv;
char *end;
+ int wait = !args_has(args, 'b');
+
+ if ((delay = args_get(args, 'd')) != NULL) {
+ d = strtod(delay, &end);
+ if (*end != '\0') {
+ cmdq_error(item, "invalid delay time: %s", delay);
+ return (CMD_RETURN_ERROR);
+ }
+ } else if (args->argc == 0)
+ return (CMD_RETURN_NORMAL);
cdata = xcalloc(1, sizeof *cdata);
if (args->argc != 0)
cdata->cmd = format_single_from_target(item, args->argv[0]);
+ cdata->shell = !args_has(args, 'C');
+ if (!cdata->shell) {
+ memset(&cdata->pi, 0, sizeof cdata->pi);
+ cmd_get_source(self, &cdata->pi.file, &cdata->pi.line);
+ if (wait)
+ cdata->pi.item = item;
+ cdata->pi.c = tc;
+ cmd_find_copy_state(&cdata->pi.fs, target);
+ }
+
if (args_has(args, 't') && wp != NULL)
cdata->wp_id = wp->id;
else
cdata->wp_id = -1;
- if (!args_has(args, 'b'))
+ if (wait) {
+ cdata->client = cmdq_get_client(item);
cdata->item = item;
- else
+ } else {
+ cdata->client = tc;
cdata->flags |= JOB_NOWAIT;
+ }
+ if (cdata->client != NULL)
+ cdata->client->references++;
cdata->cwd = xstrdup(server_client_get_cwd(cmdq_get_client(item), s));
+
cdata->s = s;
if (s != NULL)
session_add_ref(s, __func__);
evtimer_set(&cdata->timer, cmd_run_shell_timer, cdata);
-
- if ((delay = args_get(args, 'd')) != NULL) {
- d = strtod(delay, &end);
- if (*end != '\0') {
- cmdq_error(item, "invalid delay time: %s", delay);
- cmd_run_shell_free(cdata);
- return (CMD_RETURN_ERROR);
- }
+ if (delay != NULL) {
timerclear(&tv);
tv.tv_sec = (time_t)d;
tv.tv_usec = (d - (double)tv.tv_sec) * 1000000U;
evtimer_add(&cdata->timer, &tv);
} else
- cmd_run_shell_timer(-1, 0, cdata);
+ event_active(&cdata->timer, EV_TIMEOUT, 1);
- if (args_has(args, 'b'))
+ if (!wait)
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
}
@@ -144,17 +167,37 @@ static void
cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
{
struct cmd_run_shell_data *cdata = arg;
+ struct client *c = cdata->client;
+ const char *cmd = cdata->cmd;
+ char *error;
+ struct cmdq_item *item = cdata->item;
+ enum cmd_parse_status status;
- if (cdata->cmd != NULL) {
- if (job_run(cdata->cmd, cdata->s, cdata->cwd, NULL,
+ if (cmd != NULL && cdata->shell) {
+ if (job_run(cmd, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
cdata->flags, -1, -1) == NULL)
cmd_run_shell_free(cdata);
- } else {
- if (cdata->item != NULL)
- cmdq_continue(cdata->item);
- cmd_run_shell_free(cdata);
+ return;
}
+
+ if (cmd != NULL) {
+ if (item != NULL) {
+ status = cmd_parse_and_insert(cmd, &cdata->pi, item,
+ cmdq_get_state(item), &error);
+ } else {
+ status = cmd_parse_and_append(cmd, &cdata->pi, c, NULL,
+ &error);
+ }
+ if (status == CMD_PARSE_ERROR) {
+ cmdq_error(cdata->item, "%s", error);
+ free(error);
+ }
+ }
+
+ if (cdata->item != NULL)
+ cmdq_continue(cdata->item);
+ cmd_run_shell_free(cdata);
}
static void
@@ -215,6 +258,8 @@ cmd_run_shell_free(void *data)
evtimer_del(&cdata->timer);
if (cdata->s != NULL)
session_remove_ref(cdata->s, __func__);
+ if (cdata->client != NULL)
+ server_client_unref(cdata->client);
free(cdata->cwd);
free(cdata->cmd);
free(cdata);
diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1
index e1e735d4c91..2678c04d1eb 100644
--- a/usr.bin/tmux/tmux.1
+++ b/usr.bin/tmux/tmux.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: tmux.1,v 1.808 2020/12/15 08:31:50 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.809 2021/01/01 08:36:51 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
@@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: December 15 2020 $
+.Dd $Mdocdate: January 1 2021 $
.Dt TMUX 1
.Os
.Sh NAME
@@ -5827,7 +5827,7 @@ Lock each client individually by running the command specified by the
.Ic lock-command
option.
.It Xo Ic run-shell
-.Op Fl b
+.Op Fl bC
.Op Fl d Ar delay
.Op Fl t Ar target-pane
.Op Ar shell-command
@@ -5835,9 +5835,14 @@ option.
.D1 (alias: Ic run )
Execute
.Ar shell-command
-in the background without creating a window.
-Before being executed, shell-command is expanded using the rules specified in
-the
+or (with
+.Fl C )
+a
+.Nm
+command in the background without creating a window.
+Before being executed,
+.Ar shell-command
+is expanded using the rules specified in the
.Sx FORMATS
section.
With
@@ -5847,11 +5852,13 @@ the command is run in the background.
waits for
.Ar delay
seconds before starting the command.
-After the command finishes, any output to stdout is displayed in view mode (in
-the pane specified by
+If
+.Fl C
+is not given, any output to stdout is displayed in view mode (in the pane
+specified by
.Fl t
-or the current pane if omitted).
-If the command doesn't return success, the exit status is also displayed.
+or the current pane if omitted) after the command finishes.
+If the command fails, the exit status is also displayed.
.It Xo Ic wait-for
.Op Fl L | S | U
.Ar channel