aboutsummaryrefslogtreecommitdiff
path: root/server-client.c
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2015-06-07 23:42:25 +0100
committerThomas Adam <thomas@xteddy.org>2015-06-07 23:42:25 +0100
commit7acc4addb51c711afed3761302c2d3457125445c (patch)
tree03cca6f3242974dba6adc2c1d1b721a595d24a37 /server-client.c
parenta5c55e439383202547e442f6afc0c8c664687728 (diff)
parentc4e811e51936edab66803a7b9e099ac135e6e19b (diff)
downloadrtmux-7acc4addb51c711afed3761302c2d3457125445c.tar.gz
rtmux-7acc4addb51c711afed3761302c2d3457125445c.tar.bz2
rtmux-7acc4addb51c711afed3761302c2d3457125445c.zip
Merge branch 'obsd-master'
Conflicts: client.c tmux.1 tmux.c
Diffstat (limited to 'server-client.c')
-rw-r--r--server-client.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/server-client.c b/server-client.c
index 532d643e..27efc57d 100644
--- a/server-client.c
+++ b/server-client.c
@@ -30,6 +30,7 @@
#include "tmux.h"
void server_client_key_table(struct client *, const char *);
+void server_client_free(int, short, void *);
void server_client_check_focus(struct window_pane *);
void server_client_check_resize(struct window_pane *);
int server_client_check_mouse(struct client *);
@@ -45,6 +46,27 @@ void server_client_msg_command(struct client *, struct imsg *);
void server_client_msg_identify(struct client *, struct imsg *);
void server_client_msg_shell(struct client *);
+/* Check if this client is inside this server. */
+int
+server_client_check_nested(struct client *c)
+{
+ struct environ_entry *envent;
+ struct window_pane *wp;
+
+ if (c->tty.path == NULL)
+ return (0);
+
+ envent = environ_find(&c->environ, "TMUX");
+ if (envent == NULL || *envent->value == '\0')
+ return (0);
+
+ RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
+ if (strcmp(wp->tty, c->tty.path) == 0)
+ return (1);
+ }
+ return (0);
+}
+
/* Set client key table. */
void
server_client_key_table(struct client *c, const char *name)
@@ -63,7 +85,7 @@ server_client_create(int fd)
setblocking(fd, 0);
c = xcalloc(1, sizeof *c);
- c->references = 0;
+ c->references = 1;
imsg_init(&c->ibuf, fd);
server_update_event(c);
@@ -139,6 +161,14 @@ server_client_lost(struct client *c)
{
struct message_entry *msg, *msg1;
+ c->flags |= CLIENT_DEAD;
+
+ status_prompt_clear(c);
+ status_message_clear(c);
+
+ if (c->stdin_callback != NULL)
+ c->stdin_callback(c, 1, c->stdin_callback_data);
+
TAILQ_REMOVE(&clients, c, entry);
log_debug("lost client %d", c->ibuf.fd);
@@ -191,8 +221,7 @@ server_client_lost(struct client *c)
if (event_initialized(&c->event))
event_del(&c->event);
- TAILQ_INSERT_TAIL(&dead_clients, c, entry);
- c->flags |= CLIENT_DEAD;
+ server_client_unref(c);
server_add_accept(0); /* may be more file descriptors now */
@@ -201,6 +230,29 @@ server_client_lost(struct client *c)
server_update_socket();
}
+/* Remove reference from a client. */
+void
+server_client_unref(struct client *c)
+{
+ log_debug("unref client %d (%d references)", c->ibuf.fd, c->references);
+
+ c->references--;
+ if (c->references == 0)
+ event_once(-1, EV_TIMEOUT, server_client_free, c, NULL);
+}
+
+/* Free dead client. */
+void
+server_client_free(unused int fd, unused short events, void *arg)
+{
+ struct client *c = arg;
+
+ log_debug("free client %d (%d references)", c->ibuf.fd, c->references);
+
+ if (c->references == 0)
+ free(c);
+}
+
/* Process a single client event. */
void
server_client_callback(int fd, short events, void *data)