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);
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);

View File

@ -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 },

View File

@ -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");

View File

@ -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 *

View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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 *);

View File

@ -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");
}