aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.c4
-rw-r--r--server-msg.c27
-rw-r--r--tmux.112
-rw-r--r--tmux.c68
-rw-r--r--tmux.h12
-rw-r--r--tty.c18
6 files changed, 118 insertions, 23 deletions
diff --git a/client.c b/client.c
index 070fae10..87311445 100644
--- a/client.c
+++ b/client.c
@@ -1,4 +1,4 @@
-/* $Id: client.c,v 1.74 2009-09-23 15:00:08 tcunha Exp $ */
+/* $Id: client.c,v 1.75 2009-09-23 15:18:56 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -95,6 +95,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/server-msg.c b/server-msg.c
index 7cfdc2d9..8a18c4ab 100644
--- a/server-msg.c
+++ b/server-msg.c
@@ -1,4 +1,4 @@
-/* $Id: server-msg.c,v 1.87 2009-09-23 15:00:08 tcunha Exp $ */
+/* $Id: server-msg.c,v 1.88 2009-09-23 15:18:56 tcunha 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/tmux.1 b/tmux.1
index 3ebd091f..dbb8b88c 100644
--- a/tmux.1
+++ b/tmux.1
@@ -1,4 +1,4 @@
-.\" $Id: tmux.1,v 1.172 2009-09-23 15:00:09 tcunha Exp $
+.\" $Id: tmux.1,v 1.173 2009-09-23 15:18:56 tcunha 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/tmux.c b/tmux.c
index 979302fd..fd07845d 100644
--- a/tmux.c
+++ b/tmux.c
@@ -1,4 +1,4 @@
-/* $Id: tmux.c,v 1.174 2009-09-23 15:00:09 tcunha Exp $ */
+/* $Id: tmux.c,v 1.175 2009-09-23 15:18:56 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -62,7 +62,8 @@ 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 *);
#ifndef HAVE_PROGNAME
char *__progname = (char *) "tmux";
@@ -72,7 +73,7 @@ __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);
@@ -284,17 +285,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;
@@ -304,6 +305,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;
@@ -341,6 +347,9 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ if (shellcmd != NULL && argc != 0)
+ usage();
+
log_open_tty(debug_level);
siginit();
@@ -486,10 +495,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 {
/*
@@ -538,7 +553,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;
}
@@ -555,11 +570,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");
@@ -603,6 +619,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");
}
@@ -610,3 +633,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/tmux.h b/tmux.h
index 95f7dc2c..3c1f26b9 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1,4 +1,4 @@
-/* $Id: tmux.h,v 1.453 2009-09-23 15:00:09 tcunha Exp $ */
+/* $Id: tmux.h,v 1.454 2009-09-23 15:18:56 tcunha Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -21,7 +21,7 @@
#include "config.h"
-#define PROTOCOL_VERSION 4
+#define PROTOCOL_VERSION 5
#include <sys/param.h>
#include <sys/time.h>
@@ -128,6 +128,7 @@ enum key_code {
/* Function keys. */
KEYC_F1,
+
KEYC_F2,
KEYC_F3,
KEYC_F4,
@@ -306,7 +307,8 @@ enum msgtype {
MSG_WAKEUP,
MSG_ENVIRON,
MSG_UNLOCK,
- MSG_LOCK
+ MSG_LOCK,
+ MSG_SHELL
};
/*
@@ -346,6 +348,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/tty.c b/tty.c
index 1b0c3b7e..27a5fbe2 100644
--- a/tty.c
+++ b/tty.c
@@ -1,4 +1,4 @@
-/* $Id: tty.c,v 1.137 2009-09-23 15:08:21 tcunha Exp $ */
+/* $Id: tty.c,v 1.138 2009-09-23 15:18:56 tcunha 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,6 +124,7 @@ void
tty_start_tty(struct tty *tty)
{
struct termios tio;
+ int mode;
#ifdef TIOCFLUSH
int what;
#endif
@@ -136,6 +132,11 @@ tty_start_tty(struct tty *tty)
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
@@ -187,6 +188,7 @@ void
tty_stop_tty(struct tty *tty)
{
struct winsize ws;
+ int mode;
if (!(tty->flags & TTY_STARTED))
return;
@@ -197,6 +199,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)