Merge branch 'obsd-master' into master

pull/2525/head
Thomas Adam 2021-01-01 10:01:21 +00:00
commit f04cc39976
2 changed files with 80 additions and 28 deletions

View File

@ -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);

23
tmux.1
View File

@ -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