summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@openbsd.org>2009-09-01 13:09:49 +0000
committerNicholas Marriott <nicm@openbsd.org>2009-09-01 13:09:49 +0000
commit7d5e4947160d9355353c29a983e373b66c05abef (patch)
treeefc2a0bce29bc661d657895828bb486c632a8cb1
parentf8aa5821be6bb802785c5ca7c23c91465cfba4a3 (diff)
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.
-rw-r--r--cmd-respawn-window.c3
-rw-r--r--cmd-set-option.c1
-rw-r--r--cmd-split-window.c8
-rw-r--r--names.c2
-rw-r--r--session.c8
-rw-r--r--tmux.126
-rw-r--r--tmux.c46
-rw-r--r--tmux.h12
-rw-r--r--window.c58
9 files changed, 111 insertions, 53 deletions
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index 8ed678b1..cd96f50b 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -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);
diff --git a/cmd-set-option.c b/cmd-set-option.c
index b69ffe0d..90cb6e0b 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -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 },
diff --git a/cmd-split-window.c b/cmd-split-window.c
index d5f0ba6c..d6fc3f78 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -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");
diff --git a/names.c b/names.c
index 915d06bf..75f6c7b8 100644
--- a/names.c
+++ b/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 *
diff --git a/session.c b/session.c
index 2e1aae3d..55d38c80 100644
--- a/session.c
+++ b/session.c
@@ -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);
diff --git a/tmux.1 b/tmux.1
index 8b92fa69..a524c025 100644
--- a/tmux.1
+++ b/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.
diff --git a/tmux.c b/tmux.c
index 7053201c..f77b1d6c 100644
--- a/tmux.c
+++ b/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);
diff --git a/tmux.h b/tmux.h
index 36e660df..20f316dd 100644
--- a/tmux.h
+++ b/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 *);
diff --git a/window.c b/window.c
index 630533ee..97381785 100644
--- a/window.c
+++ b/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");
}