diff options
-rw-r--r-- | usr.bin/tmux/client.c | 4 | ||||
-rw-r--r-- | usr.bin/tmux/server-msg.c | 27 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 12 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.c | 68 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 12 | ||||
-rw-r--r-- | usr.bin/tmux/tty.c | 19 |
6 files changed, 118 insertions, 24 deletions
diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c index 70429fa5e4d..b74fe210e5a 100644 --- a/usr.bin/tmux/client.c +++ b/usr.bin/tmux/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.21 2009/09/23 06:18:47 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.22 2009/09/23 12:03:30 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -91,6 +91,8 @@ server_started: fatal("fcntl failed"); if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) fatal("fcntl failed"); + if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) + fatal("fcntl failed"); imsg_init(&cctx->ibuf, fd); if (cmdflags & CMD_SENDENVIRON) diff --git a/usr.bin/tmux/server-msg.c b/usr.bin/tmux/server-msg.c index 81387f4c0db..96b38592df9 100644 --- a/usr.bin/tmux/server-msg.c +++ b/usr.bin/tmux/server-msg.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-msg.c,v 1.20 2009/09/23 06:18:47 nicm Exp $ */ +/* $OpenBSD: server-msg.c,v 1.21 2009/09/23 12:03:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -20,6 +20,7 @@ #include <sys/ioctl.h> #include <errno.h> +#include <paths.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -29,6 +30,7 @@ void server_msg_command(struct client *, struct msg_command_data *); void server_msg_identify(struct client *, struct msg_identify_data *, int); +void server_msg_shell(struct client *); void printflike2 server_msg_command_error(struct cmd_ctx *, const char *, ...); void printflike2 server_msg_command_print(struct cmd_ctx *, const char *, ...); @@ -113,6 +115,12 @@ server_msg_dispatch(struct client *c) if (strchr(environdata.var, '=') != NULL) environ_put(&c->environ, environdata.var); break; + case MSG_SHELL: + if (datalen != 0) + fatalx("bad MSG_SHELL size"); + + server_msg_shell(c); + break; default: fatalx("unexpected message"); } @@ -248,3 +256,20 @@ server_msg_identify(struct client *c, struct msg_identify_data *data, int fd) c->flags |= CLIENT_TERMINAL; } + +void +server_msg_shell(struct client *c) +{ + struct msg_shell_data data; + const char *shell; + + shell = options_get_string(&global_s_options, "default-shell"); + + if (*shell == '\0' || areshell(shell)) + shell = _PATH_BSHELL; + if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell) + strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell); + + server_write_client(c, MSG_SHELL, &data, sizeof data); + c->flags |= CLIENT_BAD; /* it will die after exec */ +} diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index f293a134e11..bf31ed49b7a 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.90 2009/09/23 06:18:48 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.91 2009/09/23 12:03:31 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -24,6 +24,7 @@ .Nm tmux .Bk -words .Op Fl 28dlquv +.Op Fl c Ar shell-command .Op Fl f Ar file .Op Fl L Ar socket-name .Op Fl S Ar socket-path @@ -101,6 +102,15 @@ to assume the terminal supports 256 colours. Like .Fl 2 , but indicates that the terminal supports 88 colours. +.It Fl c Ar shell-command +Execute +.Ar shell-command +using the default shell. +If necessary, the +.Nm +server will be started to retrieve the +.Ic default-shell +option. .It Fl d Force .Nm diff --git a/usr.bin/tmux/tmux.c b/usr.bin/tmux/tmux.c index 3163445aacc..afbff6277ed 100644 --- a/usr.bin/tmux/tmux.c +++ b/usr.bin/tmux/tmux.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.c,v 1.45 2009/09/23 06:18:48 nicm Exp $ */ +/* $OpenBSD: tmux.c,v 1.46 2009/09/23 12:03:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -57,13 +57,14 @@ int login_shell; __dead void usage(void); char *makesockpath(const char *); int prepare_cmd(enum msgtype *, void **, size_t *, int, char **); -int dispatch_imsg(struct client_ctx *, int *); +int dispatch_imsg(struct client_ctx *, const char *, int *); +__dead void shell_exec(const char *, const char *); __dead void usage(void) { fprintf(stderr, - "usage: %s [-28dlquv] [-f file] [-L socket-name]\n" + "usage: %s [-28dlquv] [-c shell-command] [-f file] [-L socket-name]\n" " [-S socket-path] [command [flags]]\n", __progname); exit(1); @@ -275,17 +276,17 @@ main(int argc, char **argv) struct passwd *pw; struct options *so, *wo; struct keylist *keylist; - char *s, *path, *label, *home, *cause, **var; - char cwd[MAXPATHLEN]; + char *s, *shellcmd, *path, *label, *home, *cause; + char cwd[MAXPATHLEN], **var; void *buf; size_t len; int retcode, opt, flags, cmdflags = 0; int nfds; flags = 0; - label = path = NULL; + shellcmd = label = path = NULL; login_shell = (**argv == '-'); - while ((opt = getopt(argc, argv, "28df:lL:qS:uUv")) != -1) { + while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) { switch (opt) { case '2': flags |= IDENTIFY_256COLOURS; @@ -295,6 +296,11 @@ main(int argc, char **argv) flags |= IDENTIFY_88COLOURS; flags &= ~IDENTIFY_256COLOURS; break; + case 'c': + if (shellcmd != NULL) + xfree(shellcmd); + shellcmd = xstrdup(optarg); + break; case 'd': flags |= IDENTIFY_HASDEFAULTS; break; @@ -332,6 +338,9 @@ main(int argc, char **argv) argc -= optind; argv += optind; + if (shellcmd != NULL && argc != 0) + usage(); + log_open_tty(debug_level); siginit(); @@ -477,10 +486,16 @@ main(int argc, char **argv) } xfree(label); - if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0) + if (shellcmd != NULL) { + msg = MSG_SHELL; + buf = NULL; + len = 0; + } else if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0) exit(1); - if (argc == 0) /* new-session is the default */ + if (shellcmd != NULL) + cmdflags |= CMD_STARTSERVER; + else if (argc == 0) /* new-session is the default */ cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON; else { /* @@ -529,7 +544,7 @@ main(int argc, char **argv) fatalx("socket error"); if (pfd.revents & POLLIN) { - if (dispatch_imsg(&cctx, &retcode) != 0) + if (dispatch_imsg(&cctx, shellcmd, &retcode) != 0) break; } @@ -546,11 +561,12 @@ main(int argc, char **argv) } int -dispatch_imsg(struct client_ctx *cctx, int *retcode) +dispatch_imsg(struct client_ctx *cctx, const char *shellcmd, int *retcode) { struct imsg imsg; ssize_t n, datalen; struct msg_print_data printdata; + struct msg_shell_data shelldata; if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) fatalx("imsg_read failed"); @@ -594,6 +610,13 @@ dispatch_imsg(struct client_ctx *cctx, int *retcode) "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid); *retcode = 1; return (-1); + case MSG_SHELL: + if (datalen != sizeof shelldata) + fatalx("bad MSG_SHELL size"); + memcpy(&shelldata, imsg.data, sizeof shelldata); + shelldata.shell[(sizeof shelldata.shell) - 1] = '\0'; + + shell_exec(shelldata.shell, shellcmd); default: fatalx("unexpected message"); } @@ -601,3 +624,26 @@ dispatch_imsg(struct client_ctx *cctx, int *retcode) imsg_free(&imsg); } } + +__dead void +shell_exec(const char *shell, const char *shellcmd) +{ + const char *shellname, *ptr; + char *argv0; + + sigreset(); + + ptr = strrchr(shell, '/'); + if (ptr != NULL && *(ptr + 1) != '\0') + shellname = ptr + 1; + else + shellname = shell; + if (login_shell) + xasprintf(&argv0, "-%s", shellname); + else + xasprintf(&argv0, "%s", shellname); + setenv("SHELL", shell, 1); + + execl(shell, argv0, "-c", shellcmd, (char *) NULL); + fatal("execl failed"); +} diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 0fef42c52b9..804335a83c7 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.115 2009/09/23 06:18:48 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.116 2009/09/23 12:03:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -19,7 +19,7 @@ #ifndef TMUX_H #define TMUX_H -#define PROTOCOL_VERSION 4 +#define PROTOCOL_VERSION 5 #include <sys/param.h> #include <sys/time.h> @@ -130,6 +130,7 @@ enum key_code { /* Function keys. */ KEYC_F1, + KEYC_F2, KEYC_F3, KEYC_F4, @@ -308,7 +309,8 @@ enum msgtype { MSG_WAKEUP, MSG_ENVIRON, MSG_UNLOCK, - MSG_LOCK + MSG_LOCK, + MSG_SHELL }; /* @@ -348,6 +350,10 @@ struct msg_environ_data { char var[ENVIRON_LENGTH]; }; +struct msg_shell_data { + char shell[MAXPATHLEN]; +}; + /* Mode key commands. */ enum mode_key_cmd { MODEKEY_NONE, diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index d6c49bb0e6a..12ed1acd82b 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.33 2009/09/23 07:25:31 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.34 2009/09/23 12:03:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -44,7 +44,6 @@ void tty_cell(struct tty *, void tty_init(struct tty *tty, int fd, char *term) { - int mode; char *path; memset(tty, 0, sizeof *tty); @@ -55,10 +54,6 @@ tty_init(struct tty *tty, int fd, char *term) else tty->termname = xstrdup(term); - if ((mode = fcntl(fd, F_GETFL)) == -1) - fatal("fcntl failed"); - if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) - fatal("fcntl failed"); if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) fatal("fcntl failed"); tty->fd = fd; @@ -129,11 +124,16 @@ void tty_start_tty(struct tty *tty) { struct termios tio; - int what; + int what, mode; if (tty->fd == -1) return; + if ((mode = fcntl(tty->fd, F_GETFL)) == -1) + fatal("fcntl failed"); + if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1) + fatal("fcntl failed"); + #if 0 tty_detect_utf8(tty); #endif @@ -183,6 +183,7 @@ void tty_stop_tty(struct tty *tty) { struct winsize ws; + int mode; if (!(tty->flags & TTY_STARTED)) return; @@ -193,6 +194,10 @@ tty_stop_tty(struct tty *tty) * because the fd is invalid. Things like ssh -t can easily leave us * with a dead tty. */ + if ((mode = fcntl(tty->fd, F_GETFL)) == -1) + return; + if (fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK) == -1) + return; if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) return; if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) |