mirror of
https://github.com/tmux/tmux.git
synced 2025-01-07 16:28:48 +00:00
If multiple arguments are given to new-session, new-window,
split-window, respawn-window or respawn-pane, pass them directly to execvp() to help avoid quoting problems. One argument still goes to "sh -c" like before. Requested by many over the years. Patch from J Raynor.
This commit is contained in:
parent
b1a06ef22e
commit
b3e8d440ed
@ -35,10 +35,10 @@ enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_new_session_entry = {
|
const struct cmd_entry cmd_new_session_entry = {
|
||||||
"new-session", "new",
|
"new-session", "new",
|
||||||
"Ac:dDF:n:Ps:t:x:y:", 0, 1,
|
"Ac:dDF:n:Ps:t:x:y:", 0, -1,
|
||||||
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
|
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
|
||||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
|
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
||||||
"[command]",
|
"[-y height] [command]",
|
||||||
CMD_STARTSERVER|CMD_CANTNEST,
|
CMD_STARTSERVER|CMD_CANTNEST,
|
||||||
NULL,
|
NULL,
|
||||||
cmd_new_session_exec
|
cmd_new_session_exec
|
||||||
@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct termios tio, *tiop;
|
struct termios tio, *tiop;
|
||||||
const char *newname, *target, *update, *errstr, *template;
|
const char *newname, *target, *update, *errstr, *template;
|
||||||
const char *path;
|
const char *path;
|
||||||
char *cmd, *cause, *cp;
|
char **argv, *cmd, *cause, *cp;
|
||||||
int detached, already_attached, idx, cwd, fd = -1;
|
int detached, already_attached, idx, cwd, fd = -1;
|
||||||
|
int argc;
|
||||||
u_int sx, sy;
|
u_int sx, sy;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
sy = 1;
|
sy = 1;
|
||||||
|
|
||||||
/* Figure out the command for the new window. */
|
/* Figure out the command for the new window. */
|
||||||
if (target != NULL)
|
argc = -1;
|
||||||
cmd = NULL;
|
argv = NULL;
|
||||||
else if (args->argc != 0)
|
if (target == NULL && args->argc != 0) {
|
||||||
cmd = args->argv[0];
|
argc = args->argc;
|
||||||
else
|
argv = args->argv;
|
||||||
|
} else if (target == NULL) {
|
||||||
cmd = options_get_string(&global_s_options, "default-command");
|
cmd = options_get_string(&global_s_options, "default-command");
|
||||||
|
if (cmd != NULL && *cmd != '\0') {
|
||||||
|
argc = 1;
|
||||||
|
argv = &cmd;
|
||||||
|
} else {
|
||||||
|
argc = 0;
|
||||||
|
argv = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
if (c != NULL && c->session == NULL)
|
if (c != NULL && c->session == NULL)
|
||||||
@ -206,8 +216,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
/* Create the new session. */
|
/* Create the new session. */
|
||||||
idx = -1 - options_get_number(&global_s_options, "base-index");
|
idx = -1 - options_get_number(&global_s_options, "base-index");
|
||||||
s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy,
|
s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
|
||||||
&cause);
|
sy, &cause);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
cmdq_error(cmdq, "create session failed: %s", cause);
|
cmdq_error(cmdq, "create session failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
|
|
||||||
/* Set the initial window name if one given. */
|
/* Set the initial window name if one given. */
|
||||||
if (cmd != NULL && args_has(args, 'n')) {
|
if (argc >= 0 && args_has(args, 'n')) {
|
||||||
w = s->curw->window;
|
w = s->curw->window;
|
||||||
window_set_name(w, args_get(args, 'n'));
|
window_set_name(w, args_get(args, 'n'));
|
||||||
options_set_number(&w->options, "automatic-rename", 0);
|
options_set_number(&w->options, "automatic-rename", 0);
|
||||||
|
@ -34,7 +34,7 @@ enum cmd_retval cmd_new_window_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_new_window_entry = {
|
const struct cmd_entry cmd_new_window_entry = {
|
||||||
"new-window", "neww",
|
"new-window", "neww",
|
||||||
"ac:dF:kn:Pt:", 0, 1,
|
"ac:dF:kn:Pt:", 0, -1,
|
||||||
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
||||||
CMD_TARGET_WINDOW_USAGE " [command]",
|
CMD_TARGET_WINDOW_USAGE " [command]",
|
||||||
0,
|
0,
|
||||||
@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct winlink *wl;
|
struct winlink *wl;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
const char *cmd, *path, *template;
|
const char *cmd, *path, *template;
|
||||||
char *cause, *cp;
|
char **argv, *cause, *cp;
|
||||||
int idx, last, detached, cwd, fd = -1;
|
int argc, idx, last, detached, cwd, fd = -1;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
|
|
||||||
@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
}
|
}
|
||||||
detached = args_has(args, 'd');
|
detached = args_has(args, 'd');
|
||||||
|
|
||||||
if (args->argc == 0)
|
if (args->argc == 0) {
|
||||||
cmd = options_get_string(&s->options, "default-command");
|
cmd = options_get_string(&s->options, "default-command");
|
||||||
else
|
if (cmd != NULL && *cmd != '\0') {
|
||||||
cmd = args->argv[0];
|
argc = 1;
|
||||||
|
argv = (char**)&cmd;
|
||||||
|
} else {
|
||||||
|
argc = 0;
|
||||||
|
argv = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
argc = args->argc;
|
||||||
|
argv = args->argv;
|
||||||
|
}
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||||
@ -145,7 +154,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
|
|
||||||
if (idx == -1)
|
if (idx == -1)
|
||||||
idx = -1 - options_get_number(&s->options, "base-index");
|
idx = -1 - options_get_number(&s->options, "base-index");
|
||||||
wl = session_new(s, args_get(args, 'n'), cmd, path, cwd, idx, &cause);
|
wl = session_new(s, args_get(args, 'n'), argc, argv, path, cwd, idx,
|
||||||
|
&cause);
|
||||||
if (wl == NULL) {
|
if (wl == NULL) {
|
||||||
cmdq_error(cmdq, "create window failed: %s", cause);
|
cmdq_error(cmdq, "create window failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
|
@ -32,7 +32,7 @@ enum cmd_retval cmd_respawn_pane_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_respawn_pane_entry = {
|
const struct cmd_entry cmd_respawn_pane_entry = {
|
||||||
"respawn-pane", "respawnp",
|
"respawn-pane", "respawnp",
|
||||||
"kt:", 0, 1,
|
"kt:", 0, -1,
|
||||||
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct environ env;
|
struct environ env;
|
||||||
const char *cmd, *path;
|
const char *path;
|
||||||
char *cause;
|
char *cause;
|
||||||
u_int idx;
|
u_int idx;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
screen_reinit(&wp->base);
|
screen_reinit(&wp->base);
|
||||||
input_init(wp);
|
input_init(wp);
|
||||||
|
|
||||||
if (args->argc != 0)
|
|
||||||
cmd = args->argv[0];
|
|
||||||
else
|
|
||||||
cmd = NULL;
|
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||||
envent = environ_find(&cmdq->client->environ, "PATH");
|
envent = environ_find(&cmdq->client->environ, "PATH");
|
||||||
@ -87,8 +82,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||||
&cause) != 0) {
|
s->tio, &cause) != 0) {
|
||||||
cmdq_error(cmdq, "respawn pane failed: %s", cause);
|
cmdq_error(cmdq, "respawn pane failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
|
@ -31,7 +31,7 @@ enum cmd_retval cmd_respawn_window_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_respawn_window_entry = {
|
const struct cmd_entry cmd_respawn_window_entry = {
|
||||||
"respawn-window", "respawnw",
|
"respawn-window", "respawnw",
|
||||||
"kt:", 0, 1,
|
"kt:", 0, -1,
|
||||||
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct window_pane *wp;
|
struct window_pane *wp;
|
||||||
struct session *s;
|
struct session *s;
|
||||||
struct environ env;
|
struct environ env;
|
||||||
const char *cmd, *path;
|
const char *path;
|
||||||
char *cause;
|
char *cause;
|
||||||
struct environ_entry *envent;
|
struct environ_entry *envent;
|
||||||
|
|
||||||
@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
window_destroy_panes(w);
|
window_destroy_panes(w);
|
||||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||||
window_pane_resize(wp, w->sx, w->sy);
|
window_pane_resize(wp, w->sx, w->sy);
|
||||||
if (args->argc != 0)
|
|
||||||
cmd = args->argv[0];
|
|
||||||
else
|
|
||||||
cmd = NULL;
|
|
||||||
|
|
||||||
path = NULL;
|
path = NULL;
|
||||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||||
@ -89,8 +85,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||||
&cause) != 0) {
|
s->tio, &cause) != 0) {
|
||||||
cmdq_error(cmdq, "respawn window failed: %s", cause);
|
cmdq_error(cmdq, "respawn window failed: %s", cause);
|
||||||
free(cause);
|
free(cause);
|
||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
|
@ -36,7 +36,7 @@ enum cmd_retval cmd_split_window_exec(struct cmd *, struct cmd_q *);
|
|||||||
|
|
||||||
const struct cmd_entry cmd_split_window_entry = {
|
const struct cmd_entry cmd_split_window_entry = {
|
||||||
"split-window", "splitw",
|
"split-window", "splitw",
|
||||||
"c:dF:l:hp:Pt:v", 0, 1,
|
"c:dF:l:hp:Pt:v", 0, -1,
|
||||||
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
|
"[-dhvP] [-c start-directory] [-F format] [-p percentage|-l size] "
|
||||||
CMD_TARGET_PANE_USAGE " [command]",
|
CMD_TARGET_PANE_USAGE " [command]",
|
||||||
0,
|
0,
|
||||||
@ -62,9 +62,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
struct window_pane *wp, *new_wp = NULL;
|
struct window_pane *wp, *new_wp = NULL;
|
||||||
struct environ env;
|
struct environ env;
|
||||||
const char *cmd, *path, *shell, *template;
|
const char *cmd, *path, *shell, *template;
|
||||||
char *cause, *new_cause, *cp;
|
char **argv, *cause, *new_cause, *cp;
|
||||||
u_int hlimit;
|
u_int hlimit;
|
||||||
int size, percentage, cwd, fd = -1;
|
int argc, size, percentage, cwd, fd = -1;
|
||||||
enum layout_type type;
|
enum layout_type type;
|
||||||
struct layout_cell *lc;
|
struct layout_cell *lc;
|
||||||
struct client *c;
|
struct client *c;
|
||||||
@ -81,10 +81,19 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
environ_copy(&s->environ, &env);
|
environ_copy(&s->environ, &env);
|
||||||
server_fill_environ(s, &env);
|
server_fill_environ(s, &env);
|
||||||
|
|
||||||
if (args->argc == 0)
|
if (args->argc == 0) {
|
||||||
cmd = options_get_string(&s->options, "default-command");
|
cmd = options_get_string(&s->options, "default-command");
|
||||||
else
|
if (cmd != NULL && *cmd != '\0') {
|
||||||
cmd = args->argv[0];
|
argc = 1;
|
||||||
|
argv = (char**)&cmd;
|
||||||
|
} else {
|
||||||
|
argc = 0;
|
||||||
|
argv = NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
argc = args->argc;
|
||||||
|
argv = args->argv;
|
||||||
|
}
|
||||||
|
|
||||||
if (args_has(args, 'c')) {
|
if (args_has(args, 'c')) {
|
||||||
ft = format_create();
|
ft = format_create();
|
||||||
@ -158,8 +167,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
|||||||
if (envent != NULL)
|
if (envent != NULL)
|
||||||
path = envent->value;
|
path = envent->value;
|
||||||
|
|
||||||
if (window_pane_spawn(
|
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
|
||||||
new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0)
|
s->tio, &cause) != 0)
|
||||||
goto error;
|
goto error;
|
||||||
layout_assign_pane(lc, new_wp);
|
layout_assign_pane(lc, new_wp);
|
||||||
|
|
||||||
|
28
cmd.c
28
cmd.c
@ -187,7 +187,7 @@ cmd_copy_argv(int argc, char **argv)
|
|||||||
|
|
||||||
if (argc == 0)
|
if (argc == 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
new_argv = xcalloc(argc, sizeof *new_argv);
|
new_argv = xcalloc(argc + 1, sizeof *new_argv);
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++) {
|
||||||
if (argv[i] != NULL)
|
if (argv[i] != NULL)
|
||||||
new_argv[i] = xstrdup(argv[i]);
|
new_argv[i] = xstrdup(argv[i]);
|
||||||
@ -207,6 +207,32 @@ cmd_free_argv(int argc, char **argv)
|
|||||||
free(argv);
|
free(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
cmd_stringify_argv(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int i;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (argc == 0)
|
||||||
|
return (xstrdup(""));
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
buf = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
len += strlen(argv[i]) + 1;
|
||||||
|
buf = xrealloc(buf, 1, len);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
*buf = '\0';
|
||||||
|
else
|
||||||
|
strlcat(buf, " ", len);
|
||||||
|
strlcat(buf, argv[i], len);
|
||||||
|
}
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
struct cmd *
|
struct cmd *
|
||||||
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||||
{
|
{
|
||||||
|
8
format.c
8
format.c
@ -368,7 +368,7 @@ format_get_command(struct window_pane *wp)
|
|||||||
cmd = get_proc_name(wp->fd, wp->tty);
|
cmd = get_proc_name(wp->fd, wp->tty);
|
||||||
if (cmd == NULL || *cmd == '\0') {
|
if (cmd == NULL || *cmd == '\0') {
|
||||||
free(cmd);
|
free(cmd);
|
||||||
cmd = xstrdup(wp->cmd);
|
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||||
if (cmd == NULL || *cmd == '\0') {
|
if (cmd == NULL || *cmd == '\0') {
|
||||||
free(cmd);
|
free(cmd);
|
||||||
cmd = xstrdup(wp->shell);
|
cmd = xstrdup(wp->shell);
|
||||||
@ -559,8 +559,10 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
|||||||
if (wp->tty != NULL)
|
if (wp->tty != NULL)
|
||||||
format_add(ft, "pane_tty", "%s", wp->tty);
|
format_add(ft, "pane_tty", "%s", wp->tty);
|
||||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||||
if (wp->cmd != NULL)
|
if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
|
||||||
format_add(ft, "pane_start_command", "%s", wp->cmd);
|
format_add(ft, "pane_start_command", "%s", cmd);
|
||||||
|
free(cmd);
|
||||||
|
}
|
||||||
if ((cmd = format_get_command(wp)) != NULL) {
|
if ((cmd = format_get_command(wp)) != NULL) {
|
||||||
format_add(ft, "pane_current_command", "%s", cmd);
|
format_add(ft, "pane_current_command", "%s", cmd);
|
||||||
free(cmd);
|
free(cmd);
|
||||||
|
12
names.c
12
names.c
@ -68,9 +68,15 @@ window_name_callback(unused int fd, unused short events, void *data)
|
|||||||
char *
|
char *
|
||||||
default_window_name(struct window *w)
|
default_window_name(struct window *w)
|
||||||
{
|
{
|
||||||
if (w->active->cmd != NULL && *w->active->cmd != '\0')
|
char *cmd, *s;
|
||||||
return (parse_window_name(w->active->cmd));
|
|
||||||
return (parse_window_name(w->active->shell));
|
cmd = cmd_stringify_argv(w->active->argc, w->active->argv);
|
||||||
|
if (cmd != NULL && *cmd != '\0')
|
||||||
|
s = parse_window_name(cmd);
|
||||||
|
else
|
||||||
|
s = parse_window_name(w->active->shell);
|
||||||
|
free(cmd);
|
||||||
|
return (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
|
18
session.c
18
session.c
@ -85,11 +85,12 @@ session_find_by_id(u_int id)
|
|||||||
|
|
||||||
/* Create a new session. */
|
/* Create a new session. */
|
||||||
struct session *
|
struct session *
|
||||||
session_create(const char *name, const char *cmd, const char *path, int cwd,
|
session_create(const char *name, int argc, char **argv, const char *path,
|
||||||
struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
|
int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
|
||||||
char **cause)
|
u_int sy, char **cause)
|
||||||
{
|
{
|
||||||
struct session *s;
|
struct session *s;
|
||||||
|
struct winlink *wl;
|
||||||
|
|
||||||
s = xmalloc(sizeof *s);
|
s = xmalloc(sizeof *s);
|
||||||
s->references = 0;
|
s->references = 0;
|
||||||
@ -132,8 +133,9 @@ session_create(const char *name, const char *cmd, const char *path, int cwd,
|
|||||||
}
|
}
|
||||||
RB_INSERT(sessions, &sessions, s);
|
RB_INSERT(sessions, &sessions, s);
|
||||||
|
|
||||||
if (cmd != NULL) {
|
if (argc >= 0) {
|
||||||
if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) {
|
wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
|
||||||
|
if (wl == NULL) {
|
||||||
session_destroy(s);
|
session_destroy(s);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -227,7 +229,7 @@ session_previous_session(struct session *s)
|
|||||||
|
|
||||||
/* Create a new window on a session. */
|
/* Create a new window on a session. */
|
||||||
struct winlink *
|
struct winlink *
|
||||||
session_new(struct session *s, const char *name, const char *cmd,
|
session_new(struct session *s, const char *name, int argc, char **argv,
|
||||||
const char *path, int cwd, int idx, char **cause)
|
const char *path, int cwd, int idx, char **cause)
|
||||||
{
|
{
|
||||||
struct window *w;
|
struct window *w;
|
||||||
@ -251,8 +253,8 @@ session_new(struct session *s, const char *name, const char *cmd,
|
|||||||
shell = _PATH_BSHELL;
|
shell = _PATH_BSHELL;
|
||||||
|
|
||||||
hlimit = options_get_number(&s->options, "history-limit");
|
hlimit = options_get_number(&s->options, "history-limit");
|
||||||
w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx,
|
w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
|
||||||
s->sy, hlimit, cause);
|
s->sx, s->sy, hlimit, cause);
|
||||||
if (w == NULL) {
|
if (w == NULL) {
|
||||||
winlink_remove(&s->windows, wl);
|
winlink_remove(&s->windows, wl);
|
||||||
environ_free(&env);
|
environ_free(&env);
|
||||||
|
29
tmux.1
29
tmux.1
@ -478,12 +478,37 @@ It may be used alone to target a pane or the window containing it.
|
|||||||
arguments are
|
arguments are
|
||||||
.Xr sh 1
|
.Xr sh 1
|
||||||
commands.
|
commands.
|
||||||
These must be passed as a single item, which typically means quoting them, for
|
This may be a single argument passed to the shell, for example:
|
||||||
example:
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
new-window 'vi /etc/passwd'
|
new-window 'vi /etc/passwd'
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
|
Will run:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
/bin/sh -c 'vi /etc/passwd'
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Additionally, the
|
||||||
|
.Ic new-window ,
|
||||||
|
.Ic new-session ,
|
||||||
|
.Ic split-window ,
|
||||||
|
.Ic respawn-window
|
||||||
|
and
|
||||||
|
.Ic respawn-pane
|
||||||
|
commands allow
|
||||||
|
.Ar shell-command
|
||||||
|
to be given as multiple arguments and executed directly (without
|
||||||
|
.Ql sh -c ) .
|
||||||
|
This can avoid issues with shell quoting.
|
||||||
|
For example:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
$ tmux new-window vi /etc/passwd
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Will run
|
||||||
|
.Xr vi 1
|
||||||
|
directly without invoking the shell.
|
||||||
|
.Pp
|
||||||
.Ar command
|
.Ar command
|
||||||
.Op Ar arguments
|
.Op Ar arguments
|
||||||
refers to a
|
refers to a
|
||||||
|
20
tmux.h
20
tmux.h
@ -914,7 +914,8 @@ struct window_pane {
|
|||||||
#define PANE_RESIZE 0x8
|
#define PANE_RESIZE 0x8
|
||||||
#define PANE_FOCUSPUSH 0x10
|
#define PANE_FOCUSPUSH 0x10
|
||||||
|
|
||||||
char *cmd;
|
int argc;
|
||||||
|
char **argv;
|
||||||
char *shell;
|
char *shell;
|
||||||
int cwd;
|
int cwd;
|
||||||
|
|
||||||
@ -1750,6 +1751,7 @@ int cmd_pack_argv(int, char **, char *, size_t);
|
|||||||
int cmd_unpack_argv(char *, size_t, int, char ***);
|
int cmd_unpack_argv(char *, size_t, int, char ***);
|
||||||
char **cmd_copy_argv(int, char **);
|
char **cmd_copy_argv(int, char **);
|
||||||
void cmd_free_argv(int, char **);
|
void cmd_free_argv(int, char **);
|
||||||
|
char *cmd_stringify_argv(int, char **);
|
||||||
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
struct cmd *cmd_parse(int, char **, const char *, u_int, char **);
|
||||||
size_t cmd_print(struct cmd *, char *, size_t);
|
size_t cmd_print(struct cmd *, char *, size_t);
|
||||||
struct session *cmd_current_session(struct cmd_q *, int);
|
struct session *cmd_current_session(struct cmd_q *, int);
|
||||||
@ -2140,7 +2142,7 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
|||||||
int window_index(struct window *, u_int *);
|
int window_index(struct window *, u_int *);
|
||||||
struct window *window_find_by_id(u_int);
|
struct window *window_find_by_id(u_int);
|
||||||
struct window *window_create1(u_int, u_int);
|
struct window *window_create1(u_int, u_int);
|
||||||
struct window *window_create(const char *, const char *, const char *,
|
struct window *window_create(const char *, int, char **, const char *,
|
||||||
const char *, int, struct environ *, struct termios *,
|
const char *, int, struct environ *, struct termios *,
|
||||||
u_int, u_int, u_int, char **);
|
u_int, u_int, u_int, char **);
|
||||||
void window_destroy(struct window *);
|
void window_destroy(struct window *);
|
||||||
@ -2166,7 +2168,7 @@ struct window_pane *window_pane_find_by_id(u_int);
|
|||||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
||||||
void window_pane_destroy(struct window_pane *);
|
void window_pane_destroy(struct window_pane *);
|
||||||
void window_pane_timer_start(struct window_pane *);
|
void window_pane_timer_start(struct window_pane *);
|
||||||
int window_pane_spawn(struct window_pane *, const char *,
|
int window_pane_spawn(struct window_pane *, int, char **,
|
||||||
const char *, const char *, int, struct environ *,
|
const char *, const char *, int, struct environ *,
|
||||||
struct termios *, char **);
|
struct termios *, char **);
|
||||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||||
@ -2304,18 +2306,18 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
|||||||
int session_alive(struct session *);
|
int session_alive(struct session *);
|
||||||
struct session *session_find(const char *);
|
struct session *session_find(const char *);
|
||||||
struct session *session_find_by_id(u_int);
|
struct session *session_find_by_id(u_int);
|
||||||
struct session *session_create(const char *, const char *, const char *, int,
|
struct session *session_create(const char *, int, char **, const char *,
|
||||||
struct environ *, struct termios *, int, u_int, u_int,
|
int, struct environ *, struct termios *, int, u_int,
|
||||||
char **);
|
u_int, char **);
|
||||||
void session_destroy(struct session *);
|
void session_destroy(struct session *);
|
||||||
int session_check_name(const char *);
|
int session_check_name(const char *);
|
||||||
void session_update_activity(struct session *);
|
void session_update_activity(struct session *);
|
||||||
struct session *session_next_session(struct session *);
|
struct session *session_next_session(struct session *);
|
||||||
struct session *session_previous_session(struct session *);
|
struct session *session_previous_session(struct session *);
|
||||||
struct winlink *session_new(struct session *, const char *, const char *,
|
struct winlink *session_new(struct session *, const char *, int, char **,
|
||||||
const char *, int, int, char **);
|
const char *, int, int, char **);
|
||||||
struct winlink *session_attach(
|
struct winlink *session_attach(struct session *, struct window *, int,
|
||||||
struct session *, struct window *, int, char **);
|
char **);
|
||||||
int session_detach(struct session *, struct winlink *);
|
int session_detach(struct session *, struct winlink *);
|
||||||
struct winlink *session_has(struct session *, struct window *);
|
struct winlink *session_has(struct session *, struct window *);
|
||||||
int session_next(struct session *, int);
|
int session_next(struct session *, int);
|
||||||
|
60
window.c
60
window.c
@ -307,7 +307,7 @@ window_create1(u_int sx, u_int sy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct window *
|
struct window *
|
||||||
window_create(const char *name, const char *cmd, const char *path,
|
window_create(const char *name, int argc, char **argv, const char *path,
|
||||||
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
||||||
u_int sx, u_int sy, u_int hlimit, char **cause)
|
u_int sx, u_int sy, u_int hlimit, char **cause)
|
||||||
{
|
{
|
||||||
@ -318,7 +318,7 @@ window_create(const char *name, const char *cmd, const char *path,
|
|||||||
wp = window_add_pane(w, hlimit);
|
wp = window_add_pane(w, hlimit);
|
||||||
layout_init(w, wp);
|
layout_init(w, wp);
|
||||||
|
|
||||||
if (window_pane_spawn(wp, cmd, path, shell, cwd, env, tio,
|
if (window_pane_spawn(wp, argc, argv, path, shell, cwd, env, tio,
|
||||||
cause) != 0) {
|
cause) != 0) {
|
||||||
window_destroy(w);
|
window_destroy(w);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@ -678,7 +678,8 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
|||||||
wp->id = next_window_pane_id++;
|
wp->id = next_window_pane_id++;
|
||||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||||
|
|
||||||
wp->cmd = NULL;
|
wp->argc = 0;
|
||||||
|
wp->argv = NULL;
|
||||||
wp->shell = NULL;
|
wp->shell = NULL;
|
||||||
wp->cwd = -1;
|
wp->cwd = -1;
|
||||||
|
|
||||||
@ -737,27 +738,29 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
close(wp->cwd);
|
close(wp->cwd);
|
||||||
free(wp->shell);
|
free(wp->shell);
|
||||||
free(wp->cmd);
|
cmd_free_argv(wp->argc, wp->argv);
|
||||||
free(wp);
|
free(wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||||
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
const char *path, const char *shell, int cwd, struct environ *env,
|
||||||
char **cause)
|
struct termios *tio, char **cause)
|
||||||
{
|
{
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
char *argv0, paneid[16];
|
char *argv0, *cmd, **argvp, paneid[16];
|
||||||
const char *ptr;
|
const char *ptr, *first;
|
||||||
struct termios tio2;
|
struct termios tio2;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (wp->fd != -1) {
|
if (wp->fd != -1) {
|
||||||
bufferevent_free(wp->event);
|
bufferevent_free(wp->event);
|
||||||
close(wp->fd);
|
close(wp->fd);
|
||||||
}
|
}
|
||||||
if (cmd != NULL) {
|
if (argc > 0) {
|
||||||
free(wp->cmd);
|
cmd_free_argv(wp->argc, wp->argv);
|
||||||
wp->cmd = xstrdup(cmd);
|
wp->argc = argc;
|
||||||
|
wp->argv = cmd_copy_argv(argc, argv);
|
||||||
}
|
}
|
||||||
if (shell != NULL) {
|
if (shell != NULL) {
|
||||||
free(wp->shell);
|
free(wp->shell);
|
||||||
@ -768,7 +771,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
|||||||
wp->cwd = dup(cwd);
|
wp->cwd = dup(cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
|
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||||
|
log_debug("spawn: %s -- %s", wp->shell, cmd);
|
||||||
|
for (i = 0; i < wp->argc; i++)
|
||||||
|
log_debug("spawn: argv[%d] = %s", i, wp->argv[i]);
|
||||||
|
|
||||||
memset(&ws, 0, sizeof ws);
|
memset(&ws, 0, sizeof ws);
|
||||||
ws.ws_col = screen_size_x(&wp->base);
|
ws.ws_col = screen_size_x(&wp->base);
|
||||||
@ -778,6 +784,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
|||||||
case -1:
|
case -1:
|
||||||
wp->fd = -1;
|
wp->fd = -1;
|
||||||
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
||||||
|
free(cmd);
|
||||||
return (-1);
|
return (-1);
|
||||||
case 0:
|
case 0:
|
||||||
if (fchdir(wp->cwd) != 0)
|
if (fchdir(wp->cwd) != 0)
|
||||||
@ -805,31 +812,42 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
|||||||
setenv("SHELL", wp->shell, 1);
|
setenv("SHELL", wp->shell, 1);
|
||||||
ptr = strrchr(wp->shell, '/');
|
ptr = strrchr(wp->shell, '/');
|
||||||
|
|
||||||
if (*wp->cmd != '\0') {
|
/*
|
||||||
/* Use the command. */
|
* If given one argument, assume it should be passed to sh -c;
|
||||||
|
* with more than one argument, use execvp(). If there is no
|
||||||
|
* arguments, create a login shell.
|
||||||
|
*/
|
||||||
|
if (wp->argc > 0) {
|
||||||
|
if (wp->argc != 1) {
|
||||||
|
/* Copy to ensure argv ends in NULL. */
|
||||||
|
argvp = cmd_copy_argv(wp->argc, wp->argv);
|
||||||
|
execvp(argvp[0], argvp);
|
||||||
|
fatal("execvp failed");
|
||||||
|
}
|
||||||
|
first = wp->argv[0];
|
||||||
|
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||||
xasprintf(&argv0, "%s", ptr + 1);
|
xasprintf(&argv0, "%s", ptr + 1);
|
||||||
else
|
else
|
||||||
xasprintf(&argv0, "%s", wp->shell);
|
xasprintf(&argv0, "%s", wp->shell);
|
||||||
execl(wp->shell, argv0, "-c", wp->cmd, (char *) NULL);
|
execl(wp->shell, argv0, "-c", first, (char *)NULL);
|
||||||
fatal("execl failed");
|
fatal("execl failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No command; fork a login shell. */
|
|
||||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||||
xasprintf(&argv0, "-%s", ptr + 1);
|
xasprintf(&argv0, "-%s", ptr + 1);
|
||||||
else
|
else
|
||||||
xasprintf(&argv0, "-%s", wp->shell);
|
xasprintf(&argv0, "-%s", wp->shell);
|
||||||
execl(wp->shell, argv0, (char *) NULL);
|
execl(wp->shell, argv0, (char *)NULL);
|
||||||
fatal("execl failed");
|
fatal("execl failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
setblocking(wp->fd, 0);
|
setblocking(wp->fd, 0);
|
||||||
|
|
||||||
wp->event = bufferevent_new(wp->fd,
|
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
|
||||||
window_pane_read_callback, NULL, window_pane_error_callback, wp);
|
window_pane_error_callback, wp);
|
||||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||||
|
|
||||||
|
free(cmd);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user