summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--proc.c9
-rw-r--r--server-client.c15
-rw-r--r--server.c44
-rw-r--r--tmux.113
-rw-r--r--tmux.c9
-rw-r--r--tmux.h1
-rw-r--r--tty.c7
7 files changed, 73 insertions, 25 deletions
diff --git a/proc.c b/proc.c
index 3fc190a2..ce3bc8af 100644
--- a/proc.c
+++ b/proc.c
@@ -37,6 +37,7 @@ struct tmuxproc {
void (*signalcb)(int);
+ struct event ev_sigint;
struct event ev_sighup;
struct event ev_sigchld;
struct event ev_sigcont;
@@ -221,10 +222,13 @@ proc_set_signals(struct tmuxproc *tp, void (*signalcb)(int))
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_IGN;
- sigaction(SIGINT, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGTSTP, &sa, NULL);
+ sigaction(SIGTTIN, &sa, NULL);
+ sigaction(SIGTTOU, &sa, NULL);
+ signal_set(&tp->ev_sigint, SIGINT, proc_signal_cb, tp);
+ signal_add(&tp->ev_sigint, NULL);
signal_set(&tp->ev_sighup, SIGHUP, proc_signal_cb, tp);
signal_add(&tp->ev_sighup, NULL);
signal_set(&tp->ev_sigchld, SIGCHLD, proc_signal_cb, tp);
@@ -251,10 +255,10 @@ proc_clear_signals(struct tmuxproc *tp, int defaults)
sa.sa_flags = SA_RESTART;
sa.sa_handler = SIG_DFL;
- sigaction(SIGINT, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGTSTP, &sa, NULL);
+ signal_del(&tp->ev_sigint);
signal_del(&tp->ev_sighup);
signal_del(&tp->ev_sigchld);
signal_del(&tp->ev_sigcont);
@@ -264,6 +268,7 @@ proc_clear_signals(struct tmuxproc *tp, int defaults)
signal_del(&tp->ev_sigwinch);
if (defaults) {
+ sigaction(SIGINT, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
sigaction(SIGCONT, &sa, NULL);
diff --git a/server-client.c b/server-client.c
index 0bd00fc4..f42c9843 100644
--- a/server-client.c
+++ b/server-client.c
@@ -238,11 +238,22 @@ server_client_create(int fd)
int
server_client_open(struct client *c, char **cause)
{
+ const char *ttynam = _PATH_TTY;
+
if (c->flags & CLIENT_CONTROL)
return (0);
- if (strcmp(c->ttyname, "/dev/tty") == 0) {
- *cause = xstrdup("can't use /dev/tty");
+ if (strcmp(c->ttyname, ttynam) == 0||
+ ((isatty(STDIN_FILENO) &&
+ (ttynam = ttyname(STDIN_FILENO)) != NULL &&
+ strcmp(c->ttyname, ttynam) == 0) ||
+ (isatty(STDOUT_FILENO) &&
+ (ttynam = ttyname(STDOUT_FILENO)) != NULL &&
+ strcmp(c->ttyname, ttynam) == 0) ||
+ (isatty(STDERR_FILENO) &&
+ (ttynam = ttyname(STDERR_FILENO)) != NULL &&
+ strcmp(c->ttyname, ttynam) == 0))) {
+ xasprintf(cause, "can't use %s", c->ttyname);
return (-1);
}
diff --git a/server.c b/server.c
index a4216b87..f07479ae 100644
--- a/server.c
+++ b/server.c
@@ -161,29 +161,35 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
struct client *c;
char *cause = NULL;
- if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
- fatal("socketpair failed");
- server_client_flags = flags;
-
sigfillset(&set);
sigprocmask(SIG_BLOCK, &set, &oldset);
- switch (fork()) {
- case -1:
- fatal("fork failed");
- case 0:
- break;
- default:
- sigprocmask(SIG_SETMASK, &oldset, NULL);
- close(pair[1]);
- return (pair[0]);
+
+ if (~flags & CLIENT_NOFORK) {
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
+ fatal("socketpair failed");
+
+ switch (fork()) {
+ case -1:
+ fatal("fork failed");
+ case 0:
+ break;
+ default:
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
+ close(pair[1]);
+ return (pair[0]);
+ }
+ close(pair[0]);
+ if (daemon(1, 0) != 0)
+ fatal("daemon failed");
}
- close(pair[0]);
- if (daemon(1, 0) != 0)
- fatal("daemon failed");
+
+ server_client_flags = flags;
proc_clear_signals(client, 0);
+
if (event_reinit(base) != 0)
fatalx("event_reinit failed");
server_proc = proc_start("server");
+
proc_set_signals(server_proc, server_signal);
sigprocmask(SIG_SETMASK, &oldset, NULL);
@@ -205,7 +211,10 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
server_fd = server_create_socket(flags, &cause);
if (server_fd != -1)
server_update_socket();
- c = server_client_create(pair[1]);
+ if (~flags & CLIENT_NOFORK)
+ c = server_client_create(pair[1]);
+ else
+ options_set_number(global_options, "exit-empty", 0);
if (lockfd >= 0) {
unlink(lockfile);
@@ -396,6 +405,7 @@ server_signal(int sig)
log_debug("%s: %s", __func__, strsignal(sig));
switch (sig) {
+ case SIGINT:
case SIGTERM:
server_exit = 1;
server_send_exit();
diff --git a/tmux.1 b/tmux.1
index 45c004ff..6c19283e 100644
--- a/tmux.1
+++ b/tmux.1
@@ -23,7 +23,7 @@
.Sh SYNOPSIS
.Nm tmux
.Bk -words
-.Op Fl 2CluvV
+.Op Fl 2CDluvV
.Op Fl c Ar shell-command
.Op Fl f Ar file
.Op Fl L Ar socket-name
@@ -122,6 +122,17 @@ This option is for compatibility with
when
.Nm
is used as a login shell.
+.It Fl D
+Do not start the
+.Nm
+server as a daemon.
+This also turns the
+.Ic exit-empty
+option off.
+With
+.Fl D ,
+.Ar command
+may not be specified.
.It Fl f Ar file
Specify an alternative configuration file.
By default,
diff --git a/tmux.c b/tmux.c
index 137c7eeb..cfc84cd0 100644
--- a/tmux.c
+++ b/tmux.c
@@ -57,7 +57,7 @@ static __dead void
usage(void)
{
fprintf(stderr,
- "usage: %s [-2CluvV] [-c shell-command] [-f file] [-L socket-name]\n"
+ "usage: %s [-2CDluvV] [-c shell-command] [-f file] [-L socket-name]\n"
" [-S socket-path] [-T features] [command [flags]]\n",
getprogname());
exit(1);
@@ -336,7 +336,7 @@ main(int argc, char **argv)
if (**argv == '-')
flags = CLIENT_LOGIN;
- while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:T:uUvV")) != -1) {
+ while ((opt = getopt(argc, argv, "2c:CDdf:lL:qS:T:uUvV")) != -1) {
switch (opt) {
case '2':
tty_add_features(&feat, "256", ":,");
@@ -344,6 +344,9 @@ main(int argc, char **argv)
case 'c':
shell_command = optarg;
break;
+ case 'D':
+ flags |= CLIENT_NOFORK;
+ break;
case 'C':
if (flags & CLIENT_CONTROL)
flags |= CLIENT_CONTROLCONTROL;
@@ -387,6 +390,8 @@ main(int argc, char **argv)
if (shell_command != NULL && argc != 0)
usage();
+ if ((flags & CLIENT_NOFORK) && argc != 0)
+ usage();
if ((ptm_fd = getptmfd()) == -1)
err(1, "getptmfd");
diff --git a/tmux.h b/tmux.h
index 1abb6ca6..8ab78d7a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1584,6 +1584,7 @@ struct client {
#define CLIENT_DEFAULTSOCKET 0x8000000
#define CLIENT_STARTSERVER 0x10000000
#define CLIENT_REDRAWPANES 0x20000000
+#define CLIENT_NOFORK 0x40000000
#define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \
diff --git a/tty.c b/tty.c
index c8efeac7..a1e2f2c6 100644
--- a/tty.c
+++ b/tty.c
@@ -154,16 +154,21 @@ tty_read_callback(__unused int fd, __unused short events, void *data)
{
struct tty *tty = data;
struct client *c = tty->client;
+ const char *name = c->name;
size_t size = EVBUFFER_LENGTH(tty->in);
int nread;
nread = evbuffer_read(tty->in, tty->fd, -1);
if (nread == 0 || nread == -1) {
+ if (nread == 0)
+ log_debug("%s: read closed", name);
+ else
+ log_debug("%s: read error: %s", name, strerror(errno));
event_del(&tty->event_in);
server_client_lost(tty->client);
return;
}
- log_debug("%s: read %d bytes (already %zu)", c->name, nread, size);
+ log_debug("%s: read %d bytes (already %zu)", name, nread, size);
while (tty_keys_next(tty))
;