1
0
mirror of https://github.com/tmate-io/tmate-ssh-server.git synced 2020-11-18 19:53:51 -08: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:
Nicholas Marriott 2009-09-01 13:09:49 +00:00
parent f8aa5821be
commit 7d5e494716
9 changed files with 111 additions and 53 deletions

View File

@ -75,7 +75,8 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_ctx *ctx)
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 (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); ctx->error(ctx, "respawn window failed: %s", cause);
xfree(cause); xfree(cause);
environ_free(&env); environ_free(&env);

View File

@ -55,6 +55,7 @@ const struct set_option_entry set_option_table[] = {
{ "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "buffer-limit", SET_OPTION_NUMBER, 1, INT_MAX, NULL },
{ "default-command", SET_OPTION_STRING, 0, 0, NULL }, { "default-command", SET_OPTION_STRING, 0, 0, NULL },
{ "default-path", 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 }, { "default-terminal", SET_OPTION_STRING, 0, 0, NULL },
{ "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL }, { "display-panes-colour", SET_OPTION_COLOUR, 0, 0, NULL },
{ "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL }, { "display-panes-time", SET_OPTION_NUMBER, 1, INT_MAX, NULL },

View File

@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <paths.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -151,6 +152,7 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
struct window_pane *wp; struct window_pane *wp;
struct environ env; struct environ env;
char *cmd, *cwd, *cause; char *cmd, *cwd, *cause;
const char *shell;
u_int hlimit; u_int hlimit;
int size; int size;
enum layout_type type; enum layout_type type;
@ -183,8 +185,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx)
if (data->flag_horizontal) if (data->flag_horizontal)
type = LAYOUT_LEFTRIGHT; 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); 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; goto error;
if (layout_split_pane(w->active, type, size, wp) != 0) { if (layout_split_pane(w->active, type, size, wp) != 0) {
cause = xstrdup("pane too small"); cause = xstrdup("pane too small");

View File

@ -90,7 +90,7 @@ default_window_name(struct window *w)
return (xstrdup("[tmux]")); return (xstrdup("[tmux]"));
if (w->active->cmd != NULL && *w->active->cmd != '\0') if (w->active->cmd != NULL && *w->active->cmd != '\0')
return (parse_window_name(w->active->cmd)); return (parse_window_name(w->active->cmd));
return (parse_window_name(window_default_command())); return (parse_window_name(w->active->shell));
} }
char * char *

View File

@ -19,6 +19,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <paths.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
@ -207,6 +208,7 @@ session_new(struct session *s,
{ {
struct window *w; struct window *w;
struct environ env; struct environ env;
const char *shell;
u_int hlimit; u_int hlimit;
environ_init(&env); environ_init(&env);
@ -214,9 +216,13 @@ session_new(struct session *s,
environ_copy(&s->environ, &env); environ_copy(&s->environ, &env);
server_fill_environ(s, &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"); hlimit = options_get_number(&s->options, "history-limit");
w = window_create( 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) { if (w == NULL) {
environ_free(&env); environ_free(&env);
return (NULL); return (NULL);

26
tmux.1
View File

@ -1143,13 +1143,31 @@ maintain this maximum length.
.It Ic default-command Ar command .It Ic default-command Ar command
Set the command used for new windows (if not specified when the window is Set the command used for new windows (if not specified when the window is
created) to created) to
.Ar command . .Ar command ,
which may be any
.Xr sh 1
command.
The default is an empty string, which instructs The default is an empty string, which instructs
.Nm .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 .Ev SHELL
environment variable or, if it is unset, the user's shell returned by environment variable, the shell returned by
.Xr getpwuid 3 . .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 .It Ic default-path Ar path
Set the default working directory for processes created from keys, or Set the default working directory for processes created from keys, or
interactively from the prompt. interactively from the prompt.

46
tmux.c
View File

@ -175,6 +175,50 @@ sigreset(void)
fatal("sigaction failed"); 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 * char *
makesockpath(const char *label) 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, "bell-action", BELL_ANY);
options_set_number(&global_s_options, "buffer-limit", 9); 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-command", "%s", "");
options_set_string(
&global_s_options, "default-shell", "%s", getshell());
options_set_string(&global_s_options, "default-terminal", "screen"); 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-colour", 4);
options_set_number(&global_s_options, "display-panes-time", 1000); options_set_number(&global_s_options, "display-panes-time", 1000);

12
tmux.h
View File

@ -675,6 +675,7 @@ struct window_pane {
#define PANE_REDRAW 0x1 #define PANE_REDRAW 0x1
char *cmd; char *cmd;
char *shell;
char *cwd; char *cwd;
pid_t pid; pid_t pid;
@ -1117,6 +1118,9 @@ void logfile(const char *);
void siginit(void); void siginit(void);
void sigreset(void); void sigreset(void);
void sighandler(int); void sighandler(int);
const char *getshell(void);
int checkshell(const char *);
int areshell(const char *);
/* cfg.c */ /* cfg.c */
int load_cfg(const char *, struct cmd_ctx *, char **); 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 */ /* window.c */
extern struct windows windows; extern struct windows windows;
const char *window_default_command(void);
int window_cmp(struct window *, struct window *); int window_cmp(struct window *, struct window *);
int winlink_cmp(struct winlink *, struct winlink *); int winlink_cmp(struct winlink *, struct winlink *);
RB_PROTOTYPE(windows, window, entry, window_cmp); 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 *); int window_index(struct window *, 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 *, const char *, const char *,
struct environ *, struct termios *, u_int, u_int, u_int, const char *, struct environ *, struct termios *,
char **); u_int, u_int, u_int, char **);
void window_destroy(struct window *); void window_destroy(struct window *);
void window_set_active_pane(struct window *, struct window_pane *); void window_set_active_pane(struct window *, struct window_pane *);
struct window_pane *window_add_pane(struct window *, u_int); 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); 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 *);
int window_pane_spawn(struct window_pane *, const char *, 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); void window_pane_resize(struct window_pane *, u_int, u_int);
int window_pane_set_mode( int window_pane_set_mode(
struct window_pane *, const struct window_mode *); struct window_pane *, const struct window_mode *);

View File

@ -58,38 +58,6 @@ struct windows windows;
RB_GENERATE(winlinks, winlink, entry, winlink_cmp); 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 int
winlink_cmp(struct winlink *wl1, struct winlink *wl2) winlink_cmp(struct winlink *wl1, struct winlink *wl2)
{ {
@ -270,9 +238,9 @@ window_create1(u_int sx, u_int sy)
} }
struct window * struct window *
window_create(const char *name, const char *cmd, const char *cwd, window_create(const char *name, const char *cmd, const char *shell,
struct environ *env, struct termios *tio, u_int sx, u_int sy, u_int hlimit, const char *cwd, struct environ *env, struct termios *tio,
char **cause) u_int sx, u_int sy, u_int hlimit,char **cause)
{ {
struct window *w; struct window *w;
struct window_pane *wp; struct window_pane *wp;
@ -280,7 +248,7 @@ window_create(const char *name, const char *cmd, const char *cwd,
w = window_create1(sx, sy); w = window_create1(sx, sy);
wp = window_add_pane(w, hlimit); wp = window_add_pane(w, hlimit);
layout_init(w); 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); window_destroy(w);
return (NULL); 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->window = w;
wp->cmd = NULL; wp->cmd = NULL;
wp->shell = NULL;
wp->cwd = NULL; wp->cwd = NULL;
wp->fd = -1; wp->fd = -1;
@ -467,13 +436,15 @@ window_pane_destroy(struct window_pane *wp)
if (wp->cwd != NULL) if (wp->cwd != NULL)
xfree(wp->cwd); xfree(wp->cwd);
if (wp->shell != NULL)
xfree(wp->shell);
if (wp->cmd != NULL) if (wp->cmd != NULL)
xfree(wp->cmd); xfree(wp->cmd);
xfree(wp); xfree(wp);
} }
int 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) const char *cwd, struct environ *env, struct termios *tio, char **cause)
{ {
struct winsize ws; struct winsize ws;
@ -492,6 +463,11 @@ window_pane_spawn(struct window_pane *wp, const char *cmd,
xfree(wp->cmd); xfree(wp->cmd);
wp->cmd = xstrdup(cmd); wp->cmd = xstrdup(cmd);
} }
if (shell != NULL) {
if (wp->shell != NULL)
xfree(wp->shell);
wp->shell = xstrdup(shell);
}
if (cwd != NULL) { if (cwd != NULL) {
if (wp->cwd != NULL) if (wp->cwd != NULL)
xfree(wp->cwd); xfree(wp->cwd);
@ -541,12 +517,12 @@ window_pane_spawn(struct window_pane *wp, const char *cmd,
} }
/* No command; fork a login shell. */ /* No command; fork a login shell. */
cmd = window_default_command(); ptr = strrchr(wp->shell, '/');
if ((ptr = strrchr(cmd, '/')) != 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", cmd); xasprintf(&argv0, "-%s", wp->shell);
execl(cmd, argv0, (char *) NULL); execl(wp->shell, argv0, (char *) NULL);
fatal("execl failed"); fatal("execl failed");
} }