diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-09-01 13:09:51 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2009-09-01 13:09:51 +0000 |
commit | 8d04a68ef40c12c6955fb36c9e75c15dc0198c72 (patch) | |
tree | eb58360c304172f41e64e2ca20b9fd34255070f0 | |
parent | 3c72b221f38793115feebc4d9b966955647044c4 (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-- | usr.bin/tmux/cmd-respawn-window.c | 5 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-set-option.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/cmd-split-window.c | 10 | ||||
-rw-r--r-- | usr.bin/tmux/names.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/session.c | 10 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 30 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.c | 48 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 14 | ||||
-rw-r--r-- | usr.bin/tmux/window.c | 60 |
9 files changed, 121 insertions, 63 deletions
diff --git a/usr.bin/tmux/cmd-respawn-window.c b/usr.bin/tmux/cmd-respawn-window.c index 2ef024faf34..a201eb7a350 100644 --- a/usr.bin/tmux/cmd-respawn-window.c +++ b/usr.bin/tmux/cmd-respawn-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-respawn-window.c,v 1.7 2009/08/13 19:04:00 nicm Exp $ */ +/* $OpenBSD: cmd-respawn-window.c,v 1.8 2009/09/01 13:09:49 nicm Exp $ */ /* * 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); 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/usr.bin/tmux/cmd-set-option.c b/usr.bin/tmux/cmd-set-option.c index 49e5d50d13a..f7185a40ee0 100644 --- a/usr.bin/tmux/cmd-set-option.c +++ b/usr.bin/tmux/cmd-set-option.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-set-option.c,v 1.16 2009/08/31 20:46:19 nicm Exp $ */ +/* $OpenBSD: cmd-set-option.c,v 1.17 2009/09/01 13:09:49 nicm Exp $ */ /* * 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 }, { "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/usr.bin/tmux/cmd-split-window.c b/usr.bin/tmux/cmd-split-window.c index 7442ec8a015..19fe3af2ebb 100644 --- a/usr.bin/tmux/cmd-split-window.c +++ b/usr.bin/tmux/cmd-split-window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-split-window.c,v 1.10 2009/08/25 14:53:22 nicm Exp $ */ +/* $OpenBSD: cmd-split-window.c,v 1.11 2009/09/01 13:09:49 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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/usr.bin/tmux/names.c b/usr.bin/tmux/names.c index 95fb8cb4dfa..33892d336ca 100644 --- a/usr.bin/tmux/names.c +++ b/usr.bin/tmux/names.c @@ -1,4 +1,4 @@ -/* $OpenBSD: names.c,v 1.5 2009/08/18 21:18:20 nicm Exp $ */ +/* $OpenBSD: names.c,v 1.6 2009/09/01 13:09:49 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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/usr.bin/tmux/session.c b/usr.bin/tmux/session.c index 21f9dcfdb89..6058acf9128 100644 --- a/usr.bin/tmux/session.c +++ b/usr.bin/tmux/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.5 2009/08/13 20:11:58 nicm Exp $ */ +/* $OpenBSD: session.c,v 1.6 2009/09/01 13:09:49 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 87a8790b643..20ac9f25f15 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.78 2009/08/31 20:46:19 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.79 2009/09/01 13:09:50 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" 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 .Os .Sh NAME @@ -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/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c index bc80f830e50..83f24d01be5 100644 --- a/usr.bin/tmux/tmux.c +++ b/usr.bin/tmux/tmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.c,v 1.38 2009/09/01 09:11:05 nicm Exp $ */ +/* $OpenBSD: tmux.c,v 1.39 2009/09/01 13:09:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 356c8b9dbc1..db603ac8fd6 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.92 2009/08/31 20:46:19 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.93 2009/09/01 13:09:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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/usr.bin/tmux/window.c b/usr.bin/tmux/window.c index e6809ebea7f..8b05d63eba1 100644 --- a/usr.bin/tmux/window.c +++ b/usr.bin/tmux/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.22 2009/08/13 20:11:58 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.23 2009/09/01 13:09:50 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -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"); } |