Sync OpenBSD patchset 305:

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:
Tiago Cunha 2009-09-02 01:02:44 +00:00
parent ce5c441f0f
commit a3a150faf2
9 changed files with 121 additions and 63 deletions

View File

@ -1,4 +1,4 @@
/* $Id: cmd-respawn-window.c,v 1.20 2009-08-16 18:59:12 tcunha Exp $ */ /* $Id: cmd-respawn-window.c,v 1.21 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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

@ -1,4 +1,4 @@
/* $Id: cmd-set-option.c,v 1.77 2009-08-31 22:30:15 tcunha Exp $ */ /* $Id: cmd-set-option.c,v 1.78 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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

@ -1,4 +1,4 @@
/* $Id: cmd-split-window.c,v 1.24 2009-08-25 16:52:42 tcunha Exp $ */ /* $Id: cmd-split-window.c,v 1.25 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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

@ -1,4 +1,4 @@
/* $Id: names.c,v 1.14 2009-08-20 11:44:18 tcunha Exp $ */ /* $Id: names.c,v 1.15 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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

@ -1,4 +1,4 @@
/* $Id: session.c,v 1.62 2009-08-16 19:16:27 tcunha Exp $ */ /* $Id: session.c,v 1.63 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -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);

30
tmux.1
View File

@ -1,4 +1,4 @@
.\" $Id: tmux.1,v 1.160 2009-08-31 22:30:15 tcunha Exp $ .\" $Id: tmux.1,v 1.161 2009-09-02 01:02:44 tcunha Exp $
.\" .\"
.\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
.\" .\"
@ -14,7 +14,7 @@
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: August 31 2009 $ .Dd $Mdocdate: September 1 2009 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@ -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.

48
tmux.c
View File

@ -1,4 +1,4 @@
/* $Id: tmux.c,v 1.167 2009-09-02 00:55:49 tcunha Exp $ */ /* $Id: tmux.c,v 1.168 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -184,6 +184,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)
{ {
@ -355,6 +399,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);

14
tmux.h
View File

@ -1,4 +1,4 @@
/* $Id: tmux.h,v 1.430 2009-08-31 22:30:15 tcunha Exp $ */ /* $Id: tmux.h,v 1.431 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -673,6 +673,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;
@ -1115,6 +1116,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 **);
@ -1580,7 +1584,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);
@ -1598,8 +1601,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);
@ -1612,7 +1615,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

@ -1,4 +1,4 @@
/* $Id: window.c,v 1.104 2009-08-16 19:16:27 tcunha Exp $ */ /* $Id: window.c,v 1.105 2009-09-02 01:02:44 tcunha Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@ -56,38 +56,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)
{ {
@ -268,9 +236,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;
@ -278,7 +246,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);
} }
@ -421,6 +389,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;
@ -465,13 +434,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;
@ -490,6 +461,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);
@ -539,12 +515,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");
} }