mirror of
https://github.com/tmate-io/tmate.git
synced 2024-12-27 17:18:50 +01:00
When using tmux as a login shell, there is currently no way to specify a shell
to be used as a login shell inside tmux, so add a default-shell session option. This sets the shell invoked as a login shell when the default-command option is empty. The default option value is whichever of $SHELL, getpwuid(getuid())'s pw_shell or /bin/sh is valid first. Based on a diff from martynas@, changed by me to be a session option rather than a window option.
This commit is contained in:
parent
f8aa5821be
commit
7d5e494716
@ -75,7 +75,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
window_destroy_panes(w);
|
||||
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
|
||||
window_pane_resize(wp, w->sx, w->sy);
|
||||
if (window_pane_spawn(wp, data->arg, NULL, &env, &s->tio, &cause) != 0) {
|
||||
if (window_pane_spawn(
|
||||
wp, data->arg, NULL, NULL, &env, &s->tio, &cause) != 0) {
|
||||
ctx->error(ctx, "respawn window failed: %s", cause);
|
||||
xfree(cause);
|
||||
environ_free(&env);
|
||||
|
@ -55,6 +55,7 @@ const struct set_option_entry set_option_table[] = {
|
||||
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
||||
{ "default-command", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "default-path", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "default-shell", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
|
||||
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
|
||||
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <paths.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -151,6 +152,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
struct window_pane *wp;
|
||||
struct environ env;
|
||||
char *cmd, *cwd, *cause;
|
||||
const char *shell;
|
||||
u_int hlimit;
|
||||
int size;
|
||||
enum layout_type type;
|
||||
@ -183,8 +185,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
|
||||
if (data->flag_horizontal)
|
||||
type = LAYOUT_LEFTRIGHT;
|
||||
|
||||
shell = options_get_string(&s->options, "default-shell");
|
||||
if (*shell == '\0' || areshell(shell))
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
wp = window_add_pane(w, hlimit);
|
||||
if (window_pane_spawn(wp, cmd, cwd, &env, &s->tio, &cause) != 0)
|
||||
if (window_pane_spawn(wp, cmd, shell, cwd, &env, &s->tio, &cause) != 0)
|
||||
goto error;
|
||||
if (layout_split_pane(w->active, type, size, wp) != 0) {
|
||||
cause = xstrdup("pane too small");
|
||||
|
2
names.c
2
names.c
@ -90,7 +90,7 @@ default_window_name(struct window *w)
|
||||
return (xstrdup("[tmux]"));
|
||||
if (w->active->cmd != NULL && *w->active->cmd != '\0')
|
||||
return (parse_window_name(w->active->cmd));
|
||||
return (parse_window_name(window_default_command()));
|
||||
return (parse_window_name(w->active->shell));
|
||||
}
|
||||
|
||||
char *
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <paths.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -207,6 +208,7 @@ session_new(struct session *s,
|
||||
{
|
||||
struct window *w;
|
||||
struct environ env;
|
||||
const char *shell;
|
||||
u_int hlimit;
|
||||
|
||||
environ_init(&env);
|
||||
@ -214,9 +216,13 @@ session_new(struct session *s,
|
||||
environ_copy(&s->environ, &env);
|
||||
server_fill_environ(s, &env);
|
||||
|
||||
shell = options_get_string(&s->options, "default-shell");
|
||||
if (*shell == '\0' || areshell(shell))
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
hlimit = options_get_number(&s->options, "history-limit");
|
||||
w = window_create(
|
||||
name, cmd, cwd, &env, &s->tio, s->sx, s->sy, hlimit, cause);
|
||||
name, cmd, shell, cwd, &env, &s->tio, s->sx, s->sy, hlimit, cause);
|
||||
if (w == NULL) {
|
||||
environ_free(&env);
|
||||
return (NULL);
|
||||
|
26
tmux.1
26
tmux.1
@ -1143,13 +1143,31 @@ maintain this maximum length.
|
||||
.It Ic default-command Ar command
|
||||
Set the command used for new windows (if not specified when the window is
|
||||
created) to
|
||||
.Ar command .
|
||||
.Ar command ,
|
||||
which may be any
|
||||
.Xr sh 1
|
||||
command.
|
||||
The default is an empty string, which instructs
|
||||
.Nm
|
||||
to create a login shell using the
|
||||
to create a login shell using the value of the
|
||||
.Ic default-shell
|
||||
option.
|
||||
.It Ic default-shell Ar path
|
||||
Specify the default shell.
|
||||
This is used as the login shell for new windows when the
|
||||
.Ic default-command
|
||||
option is set to empty, and must be the full path of the executable.
|
||||
When started
|
||||
.Nm
|
||||
tries to set a default value from the first suitable of the
|
||||
.Ev SHELL
|
||||
environment variable or, if it is unset, the user's shell returned by
|
||||
.Xr getpwuid 3 .
|
||||
environment variable, the shell returned by
|
||||
.Xr getpwuid 3 ,
|
||||
or
|
||||
.Pa /bin/sh .
|
||||
This option should be configured when
|
||||
.Nm
|
||||
is used as a login shell.
|
||||
.It Ic default-path Ar path
|
||||
Set the default working directory for processes created from keys, or
|
||||
interactively from the prompt.
|
||||
|
46
tmux.c
46
tmux.c
@ -175,6 +175,50 @@ sigreset(void)
|
||||
fatal("sigaction failed");
|
||||
}
|
||||
|
||||
const char *
|
||||
getshell(void)
|
||||
{
|
||||
struct passwd *pw;
|
||||
const char *shell;
|
||||
|
||||
shell = getenv("SHELL");
|
||||
if (checkshell(shell))
|
||||
return (shell);
|
||||
|
||||
pw = getpwuid(getuid());
|
||||
if (pw != NULL && checkshell(pw->pw_shell))
|
||||
return (pw->pw_shell);
|
||||
|
||||
return (_PATH_BSHELL);
|
||||
}
|
||||
|
||||
int
|
||||
checkshell(const char *shell)
|
||||
{
|
||||
if (shell == NULL || *shell == '\0' || areshell(shell))
|
||||
return (0);
|
||||
if (access(shell, X_OK) != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
areshell(const char *shell)
|
||||
{
|
||||
const char *progname, *ptr;
|
||||
|
||||
if ((ptr = strrchr(shell, '/')) != NULL)
|
||||
ptr++;
|
||||
else
|
||||
ptr = shell;
|
||||
progname = __progname;
|
||||
if (*progname == '-')
|
||||
progname++;
|
||||
if (strcmp(ptr, progname) == 0)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char *
|
||||
makesockpath(const char *label)
|
||||
{
|
||||
@ -346,6 +390,8 @@ main(int argc, char **argv)
|
||||
options_set_number(&global_s_options, "bell-action", BELL_ANY);
|
||||
options_set_number(&global_s_options, "buffer-limit", 9);
|
||||
options_set_string(&global_s_options, "default-command", "%s", "");
|
||||
options_set_string(
|
||||
&global_s_options, "default-shell", "%s", getshell());
|
||||
options_set_string(&global_s_options, "default-terminal", "screen");
|
||||
options_set_number(&global_s_options, "display-panes-colour", 4);
|
||||
options_set_number(&global_s_options, "display-panes-time", 1000);
|
||||
|
12
tmux.h
12
tmux.h
@ -675,6 +675,7 @@ struct window_pane {
|
||||
#define PANE_REDRAW 0x1
|
||||
|
||||
char *cmd;
|
||||
char *shell;
|
||||
char *cwd;
|
||||
|
||||
pid_t pid;
|
||||
@ -1117,6 +1118,9 @@ void logfile(const char *);
|
||||
void siginit(void);
|
||||
void sigreset(void);
|
||||
void sighandler(int);
|
||||
const char *getshell(void);
|
||||
int checkshell(const char *);
|
||||
int areshell(const char *);
|
||||
|
||||
/* cfg.c */
|
||||
int load_cfg(const char *, struct cmd_ctx *, char **);
|
||||
@ -1582,7 +1586,6 @@ int screen_check_selection(struct screen *, u_int, u_int);
|
||||
|
||||
/* window.c */
|
||||
extern struct windows windows;
|
||||
const char *window_default_command(void);
|
||||
int window_cmp(struct window *, struct window *);
|
||||
int winlink_cmp(struct winlink *, struct winlink *);
|
||||
RB_PROTOTYPE(windows, window, entry, window_cmp);
|
||||
@ -1600,8 +1603,8 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||
int window_index(struct window *, u_int *);
|
||||
struct window *window_create1(u_int, u_int);
|
||||
struct window *window_create(const char *, const char *, const char *,
|
||||
struct environ *, struct termios *, u_int, u_int, u_int,
|
||||
char **);
|
||||
const char *, struct environ *, struct termios *,
|
||||
u_int, u_int, u_int, char **);
|
||||
void window_destroy(struct window *);
|
||||
void window_set_active_pane(struct window *, struct window_pane *);
|
||||
struct window_pane *window_add_pane(struct window *, u_int);
|
||||
@ -1614,7 +1617,8 @@ void window_destroy_panes(struct window *);
|
||||
struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
||||
void window_pane_destroy(struct window_pane *);
|
||||
int window_pane_spawn(struct window_pane *, const char *,
|
||||
const char *, struct environ *, struct termios *, char **);
|
||||
const char *, const char *, struct environ *,
|
||||
struct termios *, char **);
|
||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||
int window_pane_set_mode(
|
||||
struct window_pane *, const struct window_mode *);
|
||||
|
58
window.c
58
window.c
@ -58,38 +58,6 @@ struct windows windows;
|
||||
|
||||
RB_GENERATE(winlinks, winlink, entry, winlink_cmp);
|
||||
|
||||
const char *
|
||||
window_default_command(void)
|
||||
{
|
||||
const char *shell, *ptr;
|
||||
char *progname;
|
||||
struct passwd *pw;
|
||||
|
||||
shell = getenv("SHELL");
|
||||
if (shell != NULL && *shell != '\0')
|
||||
goto found;
|
||||
|
||||
pw = getpwuid(getuid());
|
||||
if (pw != NULL && pw->pw_shell != NULL && *pw->pw_shell != '\0') {
|
||||
shell = pw->pw_shell;
|
||||
goto found;
|
||||
}
|
||||
|
||||
return (_PATH_BSHELL);
|
||||
|
||||
found:
|
||||
if ((ptr = strrchr(shell, '/')) != NULL)
|
||||
ptr++;
|
||||
else
|
||||
ptr = shell;
|
||||
progname = __progname;
|
||||
if (*progname == '-')
|
||||
progname++;
|
||||
if (strcmp(ptr, progname) == 0)
|
||||
return (_PATH_BSHELL);
|
||||
return (shell);
|
||||
}
|
||||
|
||||
int
|
||||
winlink_cmp(struct winlink *wl1, struct winlink *wl2)
|
||||
{
|
||||
@ -270,9 +238,9 @@ window_create1(u_int sx, u_int sy)
|
||||
}
|
||||
|
||||
struct window *
|
||||
window_create(const char *name, const char *cmd, const char *cwd,
|
||||
struct environ *env, struct termios *tio, u_int sx, u_int sy, u_int hlimit,
|
||||
char **cause)
|
||||
window_create(const char *name, const char *cmd, const char *shell,
|
||||
const char *cwd, struct environ *env, struct termios *tio,
|
||||
u_int sx, u_int sy, u_int hlimit,char **cause)
|
||||
{
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
@ -280,7 +248,7 @@ window_create(const char *name, const char *cmd, const char *cwd,
|
||||
w = window_create1(sx, sy);
|
||||
wp = window_add_pane(w, hlimit);
|
||||
layout_init(w);
|
||||
if (window_pane_spawn(wp, cmd, cwd, env, tio, cause) != 0) {
|
||||
if (window_pane_spawn(wp, cmd, shell, cwd, env, tio, cause) != 0) {
|
||||
window_destroy(w);
|
||||
return (NULL);
|
||||
}
|
||||
@ -423,6 +391,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
wp->window = w;
|
||||
|
||||
wp->cmd = NULL;
|
||||
wp->shell = NULL;
|
||||
wp->cwd = NULL;
|
||||
|
||||
wp->fd = -1;
|
||||
@ -467,13 +436,15 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
if (wp->cwd != NULL)
|
||||
xfree(wp->cwd);
|
||||
if (wp->shell != NULL)
|
||||
xfree(wp->shell);
|
||||
if (wp->cmd != NULL)
|
||||
xfree(wp->cmd);
|
||||
xfree(wp);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd,
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
const char *cwd, struct environ *env, struct termios *tio, char **cause)
|
||||
{
|
||||
struct winsize ws;
|
||||
@ -492,6 +463,11 @@ window_pane_spawn(struct window_pane *wp, const char *cmd,
|
||||
xfree(wp->cmd);
|
||||
wp->cmd = xstrdup(cmd);
|
||||
}
|
||||
if (shell != NULL) {
|
||||
if (wp->shell != NULL)
|
||||
xfree(wp->shell);
|
||||
wp->shell = xstrdup(shell);
|
||||
}
|
||||
if (cwd != NULL) {
|
||||
if (wp->cwd != NULL)
|
||||
xfree(wp->cwd);
|
||||
@ -541,12 +517,12 @@ window_pane_spawn(struct window_pane *wp, const char *cmd,
|
||||
}
|
||||
|
||||
/* No command; fork a login shell. */
|
||||
cmd = window_default_command();
|
||||
if ((ptr = strrchr(cmd, '/')) != NULL && *(ptr + 1) != '\0')
|
||||
ptr = strrchr(wp->shell, '/');
|
||||
if (ptr != NULL && *(ptr + 1) != '\0')
|
||||
xasprintf(&argv0, "-%s", ptr + 1);
|
||||
else
|
||||
xasprintf(&argv0, "-%s", cmd);
|
||||
execl(cmd, argv0, (char *) NULL);
|
||||
xasprintf(&argv0, "-%s", wp->shell);
|
||||
execl(wp->shell, argv0, (char *) NULL);
|
||||
fatal("execl failed");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user