mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 01:34:18 +00:00 
			
		
		
		
	Add a -C flag to run-shell to use a tmux command rather than a shell command.
This commit is contained in:
		@@ -40,8 +40,8 @@ const struct cmd_entry cmd_run_shell_entry = {
 | 
				
			|||||||
	.name = "run-shell",
 | 
						.name = "run-shell",
 | 
				
			||||||
	.alias = "run",
 | 
						.alias = "run",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.args = { "bd:t:", 0, 1 },
 | 
						.args = { "bd:Ct:", 0, 1 },
 | 
				
			||||||
	.usage = "[-b] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
 | 
						.usage = "[-bC] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
 | 
						.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 cmd_run_shell_data {
 | 
				
			||||||
 | 
						struct client		*client;
 | 
				
			||||||
	char			*cmd;
 | 
						char			*cmd;
 | 
				
			||||||
 | 
						int			 shell;
 | 
				
			||||||
	char			*cwd;
 | 
						char			*cwd;
 | 
				
			||||||
	struct cmdq_item	*item;
 | 
						struct cmdq_item	*item;
 | 
				
			||||||
	struct session		*s;
 | 
						struct session		*s;
 | 
				
			||||||
	int			 wp_id;
 | 
						int			 wp_id;
 | 
				
			||||||
	struct event		 timer;
 | 
						struct event		 timer;
 | 
				
			||||||
	int			 flags;
 | 
						int			 flags;
 | 
				
			||||||
 | 
						struct cmd_parse_input	 pi;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					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 args			*args = cmd_get_args(self);
 | 
				
			||||||
	struct cmd_find_state		*target = cmdq_get_target(item);
 | 
						struct cmd_find_state		*target = cmdq_get_target(item);
 | 
				
			||||||
	struct cmd_run_shell_data	*cdata;
 | 
						struct cmd_run_shell_data	*cdata;
 | 
				
			||||||
 | 
						struct client			*tc = cmdq_get_target_client(item);
 | 
				
			||||||
	struct session			*s = target->s;
 | 
						struct session			*s = target->s;
 | 
				
			||||||
	struct window_pane		*wp = target->wp;
 | 
						struct window_pane		*wp = target->wp;
 | 
				
			||||||
	const char			*delay;
 | 
						const char			*delay;
 | 
				
			||||||
	double				 d;
 | 
						double				 d;
 | 
				
			||||||
	struct timeval			 tv;
 | 
						struct timeval			 tv;
 | 
				
			||||||
	char				*end;
 | 
						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);
 | 
						cdata = xcalloc(1, sizeof *cdata);
 | 
				
			||||||
	if (args->argc != 0)
 | 
						if (args->argc != 0)
 | 
				
			||||||
		cdata->cmd = format_single_from_target(item, args->argv[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)
 | 
						if (args_has(args, 't') && wp != NULL)
 | 
				
			||||||
		cdata->wp_id = wp->id;
 | 
							cdata->wp_id = wp->id;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		cdata->wp_id = -1;
 | 
							cdata->wp_id = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!args_has(args, 'b'))
 | 
						if (wait) {
 | 
				
			||||||
 | 
							cdata->client = cmdq_get_client(item);
 | 
				
			||||||
		cdata->item = item;
 | 
							cdata->item = item;
 | 
				
			||||||
	else
 | 
						} else {
 | 
				
			||||||
 | 
							cdata->client = tc;
 | 
				
			||||||
		cdata->flags |= JOB_NOWAIT;
 | 
							cdata->flags |= JOB_NOWAIT;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (cdata->client != NULL)
 | 
				
			||||||
 | 
							cdata->client->references++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->cwd = xstrdup(server_client_get_cwd(cmdq_get_client(item), s));
 | 
						cdata->cwd = xstrdup(server_client_get_cwd(cmdq_get_client(item), s));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cdata->s = s;
 | 
						cdata->s = s;
 | 
				
			||||||
	if (s != NULL)
 | 
						if (s != NULL)
 | 
				
			||||||
		session_add_ref(s, __func__);
 | 
							session_add_ref(s, __func__);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evtimer_set(&cdata->timer, cmd_run_shell_timer, cdata);
 | 
						evtimer_set(&cdata->timer, cmd_run_shell_timer, cdata);
 | 
				
			||||||
 | 
						if (delay != NULL) {
 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		timerclear(&tv);
 | 
							timerclear(&tv);
 | 
				
			||||||
		tv.tv_sec = (time_t)d;
 | 
							tv.tv_sec = (time_t)d;
 | 
				
			||||||
		tv.tv_usec = (d - (double)tv.tv_sec) * 1000000U;
 | 
							tv.tv_usec = (d - (double)tv.tv_sec) * 1000000U;
 | 
				
			||||||
		evtimer_add(&cdata->timer, &tv);
 | 
							evtimer_add(&cdata->timer, &tv);
 | 
				
			||||||
	} else
 | 
						} 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_NORMAL);
 | 
				
			||||||
	return (CMD_RETURN_WAIT);
 | 
						return (CMD_RETURN_WAIT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -144,18 +167,38 @@ static void
 | 
				
			|||||||
cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
 | 
					cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct cmd_run_shell_data	*cdata = 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 (cmd != NULL && cdata->shell) {
 | 
				
			||||||
		if (job_run(cdata->cmd, cdata->s, cdata->cwd, NULL,
 | 
							if (job_run(cmd, cdata->s, cdata->cwd, NULL,
 | 
				
			||||||
		    cmd_run_shell_callback, cmd_run_shell_free, cdata,
 | 
							    cmd_run_shell_callback, cmd_run_shell_free, cdata,
 | 
				
			||||||
		    cdata->flags, -1, -1) == NULL)
 | 
							    cdata->flags, -1, -1) == NULL)
 | 
				
			||||||
			cmd_run_shell_free(cdata);
 | 
								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 {
 | 
							} 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)
 | 
						if (cdata->item != NULL)
 | 
				
			||||||
		cmdq_continue(cdata->item);
 | 
							cmdq_continue(cdata->item);
 | 
				
			||||||
	cmd_run_shell_free(cdata);
 | 
						cmd_run_shell_free(cdata);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
cmd_run_shell_callback(struct job *job)
 | 
					cmd_run_shell_callback(struct job *job)
 | 
				
			||||||
@@ -215,6 +258,8 @@ cmd_run_shell_free(void *data)
 | 
				
			|||||||
	evtimer_del(&cdata->timer);
 | 
						evtimer_del(&cdata->timer);
 | 
				
			||||||
	if (cdata->s != NULL)
 | 
						if (cdata->s != NULL)
 | 
				
			||||||
		session_remove_ref(cdata->s, __func__);
 | 
							session_remove_ref(cdata->s, __func__);
 | 
				
			||||||
 | 
						if (cdata->client != NULL)
 | 
				
			||||||
 | 
							server_client_unref(cdata->client);
 | 
				
			||||||
	free(cdata->cwd);
 | 
						free(cdata->cwd);
 | 
				
			||||||
	free(cdata->cmd);
 | 
						free(cdata->cmd);
 | 
				
			||||||
	free(cdata);
 | 
						free(cdata);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								tmux.1
									
									
									
									
									
								
							@@ -5827,7 +5827,7 @@ Lock each client individually by running the command specified by the
 | 
				
			|||||||
.Ic lock-command
 | 
					.Ic lock-command
 | 
				
			||||||
option.
 | 
					option.
 | 
				
			||||||
.It Xo Ic run-shell
 | 
					.It Xo Ic run-shell
 | 
				
			||||||
.Op Fl b
 | 
					.Op Fl bC
 | 
				
			||||||
.Op Fl d Ar delay
 | 
					.Op Fl d Ar delay
 | 
				
			||||||
.Op Fl t Ar target-pane
 | 
					.Op Fl t Ar target-pane
 | 
				
			||||||
.Op Ar shell-command
 | 
					.Op Ar shell-command
 | 
				
			||||||
@@ -5835,9 +5835,14 @@ option.
 | 
				
			|||||||
.D1 (alias: Ic run )
 | 
					.D1 (alias: Ic run )
 | 
				
			||||||
Execute
 | 
					Execute
 | 
				
			||||||
.Ar shell-command
 | 
					.Ar shell-command
 | 
				
			||||||
in the background without creating a window.
 | 
					or (with
 | 
				
			||||||
Before being executed, shell-command is expanded using the rules specified in
 | 
					.Fl C )
 | 
				
			||||||
the
 | 
					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
 | 
					.Sx FORMATS
 | 
				
			||||||
section.
 | 
					section.
 | 
				
			||||||
With
 | 
					With
 | 
				
			||||||
@@ -5847,11 +5852,13 @@ the command is run in the background.
 | 
				
			|||||||
waits for
 | 
					waits for
 | 
				
			||||||
.Ar delay
 | 
					.Ar delay
 | 
				
			||||||
seconds before starting the command.
 | 
					seconds before starting the command.
 | 
				
			||||||
After the command finishes, any output to stdout is displayed in view mode (in
 | 
					If
 | 
				
			||||||
the pane specified by
 | 
					.Fl C
 | 
				
			||||||
 | 
					is not given, any output to stdout is displayed in view mode (in the pane
 | 
				
			||||||
 | 
					specified by
 | 
				
			||||||
.Fl t
 | 
					.Fl t
 | 
				
			||||||
or the current pane if omitted).
 | 
					or the current pane if omitted) after the command finishes.
 | 
				
			||||||
If the command doesn't return success, the exit status is also displayed.
 | 
					If the command fails, the exit status is also displayed.
 | 
				
			||||||
.It Xo Ic wait-for
 | 
					.It Xo Ic wait-for
 | 
				
			||||||
.Op Fl L | S | U
 | 
					.Op Fl L | S | U
 | 
				
			||||||
.Ar channel
 | 
					.Ar channel
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user