mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-07 16:54:01 +01: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 = {
|
||||
"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] "
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
|
||||
"[command]",
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] "
|
||||
"[-y height] [command]",
|
||||
CMD_STARTSERVER|CMD_CANTNEST,
|
||||
NULL,
|
||||
cmd_new_session_exec
|
||||
@ -55,8 +55,9 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct termios tio, *tiop;
|
||||
const char *newname, *target, *update, *errstr, *template;
|
||||
const char *path;
|
||||
char *cmd, *cause, *cp;
|
||||
char **argv, *cmd, *cause, *cp;
|
||||
int detached, already_attached, idx, cwd, fd = -1;
|
||||
int argc;
|
||||
u_int sx, sy;
|
||||
struct format_tree *ft;
|
||||
struct environ_entry *envent;
|
||||
@ -183,12 +184,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
sy = 1;
|
||||
|
||||
/* Figure out the command for the new window. */
|
||||
if (target != NULL)
|
||||
cmd = NULL;
|
||||
else if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
argc = -1;
|
||||
argv = NULL;
|
||||
if (target == NULL && args->argc != 0) {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
} else if (target == NULL) {
|
||||
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;
|
||||
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. */
|
||||
idx = -1 - options_get_number(&global_s_options, "base-index");
|
||||
s = session_create(newname, cmd, path, cwd, &env, tiop, idx, sx, sy,
|
||||
&cause);
|
||||
s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx,
|
||||
sy, &cause);
|
||||
if (s == NULL) {
|
||||
cmdq_error(cmdq, "create session failed: %s", cause);
|
||||
free(cause);
|
||||
@ -216,7 +226,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
environ_free(&env);
|
||||
|
||||
/* 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;
|
||||
window_set_name(w, args_get(args, 'n'));
|
||||
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 = {
|
||||
"new-window", "neww",
|
||||
"ac:dF:kn:Pt:", 0, 1,
|
||||
"ac:dF:kn:Pt:", 0, -1,
|
||||
"[-adkP] [-c start-directory] [-F format] [-n window-name] "
|
||||
CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
@ -50,8 +50,8 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct winlink *wl;
|
||||
struct client *c;
|
||||
const char *cmd, *path, *template;
|
||||
char *cause, *cp;
|
||||
int idx, last, detached, cwd, fd = -1;
|
||||
char **argv, *cause, *cp;
|
||||
int argc, idx, last, detached, cwd, fd = -1;
|
||||
struct format_tree *ft;
|
||||
struct environ_entry *envent;
|
||||
|
||||
@ -84,10 +84,19 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
}
|
||||
detached = args_has(args, 'd');
|
||||
|
||||
if (args->argc == 0)
|
||||
if (args->argc == 0) {
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
if (cmd != NULL && *cmd != '\0') {
|
||||
argc = 1;
|
||||
argv = (char**)&cmd;
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
} else {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
}
|
||||
|
||||
path = 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)
|
||||
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) {
|
||||
cmdq_error(cmdq, "create window failed: %s", 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 = {
|
||||
"respawn-pane", "respawnp",
|
||||
"kt:", 0, 1,
|
||||
"kt:", 0, -1,
|
||||
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
@ -48,7 +48,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct environ env;
|
||||
const char *cmd, *path;
|
||||
const char *path;
|
||||
char *cause;
|
||||
u_int idx;
|
||||
struct environ_entry *envent;
|
||||
@ -74,11 +74,6 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
screen_reinit(&wp->base);
|
||||
input_init(wp);
|
||||
|
||||
if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
path = NULL;
|
||||
if (cmdq->client != NULL && cmdq->client->session == NULL)
|
||||
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)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
||||
&cause) != 0) {
|
||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||
s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn pane failed: %s", cause);
|
||||
free(cause);
|
||||
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 = {
|
||||
"respawn-window", "respawnw",
|
||||
"kt:", 0, 1,
|
||||
"kt:", 0, -1,
|
||||
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
@ -47,7 +47,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp;
|
||||
struct session *s;
|
||||
struct environ env;
|
||||
const char *cmd, *path;
|
||||
const char *path;
|
||||
char *cause;
|
||||
struct environ_entry *envent;
|
||||
|
||||
@ -76,10 +76,6 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
window_destroy_panes(w);
|
||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||
window_pane_resize(wp, w->sx, w->sy);
|
||||
if (args->argc != 0)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
path = 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)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(wp, cmd, path, NULL, -1, &env, s->tio,
|
||||
&cause) != 0) {
|
||||
if (window_pane_spawn(wp, args->argc, args->argv, path, NULL, -1, &env,
|
||||
s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn window failed: %s", cause);
|
||||
free(cause);
|
||||
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 = {
|
||||
"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] "
|
||||
CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
@ -62,9 +62,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window_pane *wp, *new_wp = NULL;
|
||||
struct environ env;
|
||||
const char *cmd, *path, *shell, *template;
|
||||
char *cause, *new_cause, *cp;
|
||||
char **argv, *cause, *new_cause, *cp;
|
||||
u_int hlimit;
|
||||
int size, percentage, cwd, fd = -1;
|
||||
int argc, size, percentage, cwd, fd = -1;
|
||||
enum layout_type type;
|
||||
struct layout_cell *lc;
|
||||
struct client *c;
|
||||
@ -81,10 +81,19 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
environ_copy(&s->environ, &env);
|
||||
server_fill_environ(s, &env);
|
||||
|
||||
if (args->argc == 0)
|
||||
if (args->argc == 0) {
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
if (cmd != NULL && *cmd != '\0') {
|
||||
argc = 1;
|
||||
argv = (char**)&cmd;
|
||||
} else {
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
}
|
||||
} else {
|
||||
argc = args->argc;
|
||||
argv = args->argv;
|
||||
}
|
||||
|
||||
if (args_has(args, 'c')) {
|
||||
ft = format_create();
|
||||
@ -158,8 +167,8 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (envent != NULL)
|
||||
path = envent->value;
|
||||
|
||||
if (window_pane_spawn(
|
||||
new_wp, cmd, path, shell, cwd, &env, s->tio, &cause) != 0)
|
||||
if (window_pane_spawn(new_wp, argc, argv, path, shell, cwd, &env,
|
||||
s->tio, &cause) != 0)
|
||||
goto error;
|
||||
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)
|
||||
return (NULL);
|
||||
new_argv = xcalloc(argc, sizeof *new_argv);
|
||||
new_argv = xcalloc(argc + 1, sizeof *new_argv);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i] != NULL)
|
||||
new_argv[i] = xstrdup(argv[i]);
|
||||
@ -207,6 +207,32 @@ cmd_free_argv(int argc, char **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 *
|
||||
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);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->cmd);
|
||||
cmd = cmd_stringify_argv(wp->argc, wp->argv);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->shell);
|
||||
@ -559,8 +559,10 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
if (wp->tty != NULL)
|
||||
format_add(ft, "pane_tty", "%s", wp->tty);
|
||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||
if (wp->cmd != NULL)
|
||||
format_add(ft, "pane_start_command", "%s", wp->cmd);
|
||||
if ((cmd = cmd_stringify_argv(wp->argc, wp->argv)) != NULL) {
|
||||
format_add(ft, "pane_start_command", "%s", cmd);
|
||||
free(cmd);
|
||||
}
|
||||
if ((cmd = format_get_command(wp)) != NULL) {
|
||||
format_add(ft, "pane_current_command", "%s", 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 *
|
||||
default_window_name(struct window *w)
|
||||
{
|
||||
if (w->active->cmd != NULL && *w->active->cmd != '\0')
|
||||
return (parse_window_name(w->active->cmd));
|
||||
return (parse_window_name(w->active->shell));
|
||||
char *cmd, *s;
|
||||
|
||||
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 *
|
||||
|
18
session.c
18
session.c
@ -85,11 +85,12 @@ session_find_by_id(u_int id)
|
||||
|
||||
/* Create a new session. */
|
||||
struct session *
|
||||
session_create(const char *name, const char *cmd, const char *path, int cwd,
|
||||
struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
|
||||
char **cause)
|
||||
session_create(const char *name, int argc, char **argv, const char *path,
|
||||
int cwd, struct environ *env, struct termios *tio, int idx, u_int sx,
|
||||
u_int sy, char **cause)
|
||||
{
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
|
||||
s = xmalloc(sizeof *s);
|
||||
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);
|
||||
|
||||
if (cmd != NULL) {
|
||||
if (session_new(s, NULL, cmd, path, cwd, idx, cause) == NULL) {
|
||||
if (argc >= 0) {
|
||||
wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause);
|
||||
if (wl == NULL) {
|
||||
session_destroy(s);
|
||||
return (NULL);
|
||||
}
|
||||
@ -227,7 +229,7 @@ session_previous_session(struct session *s)
|
||||
|
||||
/* Create a new window on a session. */
|
||||
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)
|
||||
{
|
||||
struct window *w;
|
||||
@ -251,8 +253,8 @@ session_new(struct session *s, const char *name, const char *cmd,
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
hlimit = options_get_number(&s->options, "history-limit");
|
||||
w = window_create(name, cmd, path, shell, cwd, &env, s->tio, s->sx,
|
||||
s->sy, hlimit, cause);
|
||||
w = window_create(name, argc, argv, path, shell, cwd, &env, s->tio,
|
||||
s->sx, s->sy, hlimit, cause);
|
||||
if (w == NULL) {
|
||||
winlink_remove(&s->windows, wl);
|
||||
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
|
||||
.Xr sh 1
|
||||
commands.
|
||||
These must be passed as a single item, which typically means quoting them, for
|
||||
example:
|
||||
This may be a single argument passed to the shell, for example:
|
||||
.Bd -literal -offset indent
|
||||
new-window 'vi /etc/passwd'
|
||||
.Ed
|
||||
.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
|
||||
.Op Ar arguments
|
||||
refers to a
|
||||
|
20
tmux.h
20
tmux.h
@ -914,7 +914,8 @@ struct window_pane {
|
||||
#define PANE_RESIZE 0x8
|
||||
#define PANE_FOCUSPUSH 0x10
|
||||
|
||||
char *cmd;
|
||||
int argc;
|
||||
char **argv;
|
||||
char *shell;
|
||||
int cwd;
|
||||
|
||||
@ -1750,6 +1751,7 @@ int cmd_pack_argv(int, char **, char *, size_t);
|
||||
int cmd_unpack_argv(char *, size_t, int, char ***);
|
||||
char **cmd_copy_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 **);
|
||||
size_t cmd_print(struct cmd *, char *, size_t);
|
||||
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 *);
|
||||
struct window *window_find_by_id(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 *,
|
||||
u_int, u_int, u_int, char **);
|
||||
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);
|
||||
void window_pane_destroy(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 *,
|
||||
struct termios *, char **);
|
||||
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 *);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_find_by_id(u_int);
|
||||
struct session *session_create(const char *, const char *, const char *, int,
|
||||
struct environ *, struct termios *, int, u_int, u_int,
|
||||
char **);
|
||||
struct session *session_create(const char *, int, char **, const char *,
|
||||
int, struct environ *, struct termios *, int, u_int,
|
||||
u_int, char **);
|
||||
void session_destroy(struct session *);
|
||||
int session_check_name(const char *);
|
||||
void session_update_activity(struct session *);
|
||||
struct session *session_next_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 **);
|
||||
struct winlink *session_attach(
|
||||
struct session *, struct window *, int, char **);
|
||||
struct winlink *session_attach(struct session *, struct window *, int,
|
||||
char **);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
struct winlink *session_has(struct session *, struct window *);
|
||||
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 *
|
||||
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,
|
||||
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);
|
||||
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) {
|
||||
window_destroy(w);
|
||||
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++;
|
||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
wp->cmd = NULL;
|
||||
wp->argc = 0;
|
||||
wp->argv = NULL;
|
||||
wp->shell = NULL;
|
||||
wp->cwd = -1;
|
||||
|
||||
@ -737,27 +738,29 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
close(wp->cwd);
|
||||
free(wp->shell);
|
||||
free(wp->cmd);
|
||||
cmd_free_argv(wp->argc, wp->argv);
|
||||
free(wp);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
const char *shell, int cwd, struct environ *env, struct termios *tio,
|
||||
char **cause)
|
||||
window_pane_spawn(struct window_pane *wp, int argc, char **argv,
|
||||
const char *path, const char *shell, int cwd, struct environ *env,
|
||||
struct termios *tio, char **cause)
|
||||
{
|
||||
struct winsize ws;
|
||||
char *argv0, paneid[16];
|
||||
const char *ptr;
|
||||
char *argv0, *cmd, **argvp, paneid[16];
|
||||
const char *ptr, *first;
|
||||
struct termios tio2;
|
||||
int i;
|
||||
|
||||
if (wp->fd != -1) {
|
||||
bufferevent_free(wp->event);
|
||||
close(wp->fd);
|
||||
}
|
||||
if (cmd != NULL) {
|
||||
free(wp->cmd);
|
||||
wp->cmd = xstrdup(cmd);
|
||||
if (argc > 0) {
|
||||
cmd_free_argv(wp->argc, wp->argv);
|
||||
wp->argc = argc;
|
||||
wp->argv = cmd_copy_argv(argc, argv);
|
||||
}
|
||||
if (shell != NULL) {
|
||||
free(wp->shell);
|
||||
@ -768,7 +771,10 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *path,
|
||||
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);
|
||||
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:
|
||||
wp->fd = -1;
|
||||
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
||||
free(cmd);
|
||||
return (-1);
|
||||
case 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);
|
||||
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')
|
||||
xasprintf(&argv0, "%s", ptr + 1);
|
||||
else
|
||||
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");
|
||||
}
|
||||
|
||||
/* No command; fork a login shell. */
|
||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||
xasprintf(&argv0, "-%s", ptr + 1);
|
||||
else
|
||||
xasprintf(&argv0, "-%s", wp->shell);
|
||||
execl(wp->shell, argv0, (char *) NULL);
|
||||
execl(wp->shell, argv0, (char *)NULL);
|
||||
fatal("execl failed");
|
||||
}
|
||||
|
||||
setblocking(wp->fd, 0);
|
||||
|
||||
wp->event = bufferevent_new(wp->fd,
|
||||
window_pane_read_callback, NULL, window_pane_error_callback, wp);
|
||||
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
|
||||
window_pane_error_callback, wp);
|
||||
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
|
||||
|
||||
free(cmd);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user