mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-03 16:46:18 +00:00 
			
		
		
		
	Pass the stdout file descriptor from the client as well as stdin and use
them for control clients directly instead of passing everything via the client.
This commit is contained in:
		
							
								
								
									
										5
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								client.c
									
									
									
									
									
								
							@@ -402,6 +402,8 @@ client_main(struct event_base *base, int argc, char **argv, int flags, int feat)
 | 
				
			|||||||
	} else if (client_exitreason != CLIENT_EXIT_NONE)
 | 
						} else if (client_exitreason != CLIENT_EXIT_NONE)
 | 
				
			||||||
		fprintf(stderr, "%s\n", client_exit_message());
 | 
							fprintf(stderr, "%s\n", client_exit_message());
 | 
				
			||||||
	setblocking(STDIN_FILENO, 1);
 | 
						setblocking(STDIN_FILENO, 1);
 | 
				
			||||||
 | 
						setblocking(STDOUT_FILENO, 1);
 | 
				
			||||||
 | 
						setblocking(STDERR_FILENO, 1);
 | 
				
			||||||
	return (client_exitval);
 | 
						return (client_exitval);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -429,6 +431,9 @@ client_send_identify(const char *ttynam, const char *cwd, int feat)
 | 
				
			|||||||
	if ((fd = dup(STDIN_FILENO)) == -1)
 | 
						if ((fd = dup(STDIN_FILENO)) == -1)
 | 
				
			||||||
		fatal("dup failed");
 | 
							fatal("dup failed");
 | 
				
			||||||
	proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
 | 
						proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
 | 
				
			||||||
 | 
						if ((fd = dup(STDOUT_FILENO)) == -1)
 | 
				
			||||||
 | 
							fatal("dup failed");
 | 
				
			||||||
 | 
						proc_send(client_peer, MSG_IDENTIFY_STDOUT, fd, NULL, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pid = getpid();
 | 
						pid = getpid();
 | 
				
			||||||
	proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
 | 
						proc_send(client_peer, MSG_IDENTIFY_CLIENTPID, -1, &pid, sizeof pid);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										75
									
								
								control.c
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								control.c
									
									
									
									
									
								
							@@ -23,10 +23,11 @@
 | 
				
			|||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <time.h>
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "tmux.h"
 | 
					#include "tmux.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Control offsets. */
 | 
					/* Control client offset. */
 | 
				
			||||||
struct control_offset {
 | 
					struct control_offset {
 | 
				
			||||||
	u_int				pane;
 | 
						u_int				pane;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,9 +39,12 @@ struct control_offset {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
RB_HEAD(control_offsets, control_offset);
 | 
					RB_HEAD(control_offsets, control_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Control state. */
 | 
					/* Control client state. */
 | 
				
			||||||
struct control_state {
 | 
					struct control_state {
 | 
				
			||||||
	struct control_offsets	 offsets;
 | 
						struct control_offsets	 offsets;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct bufferevent	*read_event;
 | 
				
			||||||
 | 
						struct bufferevent	*write_event;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Compare client offsets. */
 | 
					/* Compare client offsets. */
 | 
				
			||||||
@@ -146,18 +150,24 @@ control_set_pane_off(struct client *c, struct window_pane *wp)
 | 
				
			|||||||
void
 | 
					void
 | 
				
			||||||
control_write(struct client *c, const char *fmt, ...)
 | 
					control_write(struct client *c, const char *fmt, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct control_state	*cs = c->control_state;
 | 
				
			||||||
	va_list			 ap;
 | 
						va_list			 ap;
 | 
				
			||||||
 | 
						char			*s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	va_start(ap, fmt);
 | 
						va_start(ap, fmt);
 | 
				
			||||||
	file_vprint(c, fmt, ap);
 | 
						xvasprintf(&s, fmt, ap);
 | 
				
			||||||
	file_print(c, "\n");
 | 
					 | 
				
			||||||
	va_end(ap);
 | 
						va_end(ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bufferevent_write(cs->write_event, s, strlen(s));
 | 
				
			||||||
 | 
						bufferevent_write(cs->write_event, "\n", 1);
 | 
				
			||||||
 | 
						free(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Write output from a pane. */
 | 
					/* Write output from a pane. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
control_write_output(struct client *c, struct window_pane *wp)
 | 
					control_write_output(struct client *c, struct window_pane *wp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct control_state	*cs = c->control_state;
 | 
				
			||||||
	struct control_offset	*co;
 | 
						struct control_offset	*co;
 | 
				
			||||||
	struct evbuffer		*message;
 | 
						struct evbuffer		*message;
 | 
				
			||||||
	u_char			*new_data;
 | 
						u_char			*new_data;
 | 
				
			||||||
@@ -165,11 +175,6 @@ control_write_output(struct client *c, struct window_pane *wp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	if (c->flags & CLIENT_CONTROL_NOOUTPUT)
 | 
						if (c->flags & CLIENT_CONTROL_NOOUTPUT)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * Only write input if the window pane is linked to a window belonging
 | 
					 | 
				
			||||||
	 * to the client's session.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
 | 
						if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -193,15 +198,15 @@ control_write_output(struct client *c, struct window_pane *wp)
 | 
				
			|||||||
		else
 | 
							else
 | 
				
			||||||
			evbuffer_add_printf(message, "%c", new_data[i]);
 | 
								evbuffer_add_printf(message, "%c", new_data[i]);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	evbuffer_add(message, "", 1);
 | 
						evbuffer_add(message, "\n", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	control_write(c, "%s", EVBUFFER_DATA(message));
 | 
						bufferevent_write_buffer(cs->write_event, message);
 | 
				
			||||||
	evbuffer_free(message);
 | 
						evbuffer_free(message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window_pane_update_used_data(wp, &co->offset, new_size, 1);
 | 
						window_pane_update_used_data(wp, &co->offset, new_size, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Control error callback. */
 | 
					/* Control client error callback. */
 | 
				
			||||||
static enum cmd_retval
 | 
					static enum cmd_retval
 | 
				
			||||||
control_error(struct cmdq_item *item, void *data)
 | 
					control_error(struct cmdq_item *item, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -216,18 +221,27 @@ control_error(struct cmdq_item *item, void *data)
 | 
				
			|||||||
	return (CMD_RETURN_NORMAL);
 | 
						return (CMD_RETURN_NORMAL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Control input callback. Read lines and fire commands. */
 | 
					/* Control client error callback. */
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
control_callback(__unused struct client *c, __unused const char *path,
 | 
					control_error_callback(__unused struct bufferevent *bufev,
 | 
				
			||||||
    int read_error, int closed, struct evbuffer *buffer, __unused void *data)
 | 
					    __unused short what, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct client	*c = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c->flags |= CLIENT_EXIT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Control client input callback. Read lines and fire commands. */
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					control_read_callback(__unused struct bufferevent *bufev, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct client		*c = data;
 | 
				
			||||||
 | 
						struct control_state	*cs = c->control_state;
 | 
				
			||||||
 | 
						struct evbuffer		*buffer = cs->read_event->input;
 | 
				
			||||||
	char			*line, *error;
 | 
						char			*line, *error;
 | 
				
			||||||
	struct cmdq_state	*state;
 | 
						struct cmdq_state	*state;
 | 
				
			||||||
	enum cmd_parse_status	 status;
 | 
						enum cmd_parse_status	 status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (closed || read_error != 0)
 | 
					 | 
				
			||||||
		c->flags |= CLIENT_EXIT;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (;;) {
 | 
						for (;;) {
 | 
				
			||||||
		line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF);
 | 
							line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF);
 | 
				
			||||||
		if (line == NULL)
 | 
							if (line == NULL)
 | 
				
			||||||
@@ -255,13 +269,30 @@ control_start(struct client *c)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct control_state	*cs;
 | 
						struct control_state	*cs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->flags & CLIENT_CONTROLCONTROL) {
 | 
				
			||||||
 | 
							close(c->out_fd);
 | 
				
			||||||
 | 
							c->out_fd = -1;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							setblocking(c->out_fd, 0);
 | 
				
			||||||
 | 
						setblocking(c->fd, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cs = c->control_state = xcalloc(1, sizeof *cs);
 | 
						cs = c->control_state = xcalloc(1, sizeof *cs);
 | 
				
			||||||
	RB_INIT(&cs->offsets);
 | 
						RB_INIT(&cs->offsets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file_read(c, "-", control_callback, c);
 | 
						cs->read_event = bufferevent_new(c->fd, control_read_callback, NULL,
 | 
				
			||||||
 | 
						    control_error_callback, c);
 | 
				
			||||||
 | 
						bufferevent_enable(cs->read_event, EV_READ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->flags & CLIENT_CONTROLCONTROL)
 | 
						if (c->flags & CLIENT_CONTROLCONTROL)
 | 
				
			||||||
		file_print(c, "\033P1000p");
 | 
							cs->write_event = cs->read_event;
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							cs->write_event = bufferevent_new(c->out_fd, NULL, NULL,
 | 
				
			||||||
 | 
							    control_error_callback, c);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bufferevent_enable(cs->write_event, EV_WRITE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->flags & CLIENT_CONTROLCONTROL)
 | 
				
			||||||
 | 
							control_write(c, "\033P1000p");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Stop control mode. */
 | 
					/* Stop control mode. */
 | 
				
			||||||
@@ -270,6 +301,10 @@ control_stop(struct client *c)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct control_state	*cs = c->control_state;
 | 
						struct control_state	*cs = c->control_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (~c->flags & CLIENT_CONTROLCONTROL)
 | 
				
			||||||
 | 
							bufferevent_free(cs->write_event);
 | 
				
			||||||
 | 
						bufferevent_free(cs->read_event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	control_free_offsets(c);
 | 
						control_free_offsets(c);
 | 
				
			||||||
	free(cs);
 | 
						free(cs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								file.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								file.c
									
									
									
									
									
								
							@@ -242,7 +242,9 @@ file_write(struct client *c, const char *path, int flags, const void *bdata,
 | 
				
			|||||||
		cf->path = xstrdup("-");
 | 
							cf->path = xstrdup("-");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fd = STDOUT_FILENO;
 | 
							fd = STDOUT_FILENO;
 | 
				
			||||||
		if (c == NULL || c->flags & CLIENT_ATTACHED) {
 | 
							if (c == NULL ||
 | 
				
			||||||
 | 
							    (c->flags & CLIENT_ATTACHED) ||
 | 
				
			||||||
 | 
							    (c->flags & CLIENT_CONTROL)) {
 | 
				
			||||||
			cf->error = EBADF;
 | 
								cf->error = EBADF;
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -311,7 +313,9 @@ file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
 | 
				
			|||||||
		cf->path = xstrdup("-");
 | 
							cf->path = xstrdup("-");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fd = STDIN_FILENO;
 | 
							fd = STDIN_FILENO;
 | 
				
			||||||
		if (c == NULL || c->flags & CLIENT_ATTACHED) {
 | 
							if (c == NULL ||
 | 
				
			||||||
 | 
							    (c->flags & CLIENT_ATTACHED) ||
 | 
				
			||||||
 | 
							    (c->flags & CLIENT_CONTROL)) {
 | 
				
			||||||
			cf->error = EBADF;
 | 
								cf->error = EBADF;
 | 
				
			||||||
			goto done;
 | 
								goto done;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -223,7 +223,7 @@ server_client_create(int fd)
 | 
				
			|||||||
	c->environ = environ_create();
 | 
						c->environ = environ_create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->fd = -1;
 | 
						c->fd = -1;
 | 
				
			||||||
	c->cwd = NULL;
 | 
						c->out_fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c->queue = cmdq_new();
 | 
						c->queue = cmdq_new();
 | 
				
			||||||
	RB_INIT(&c->windows);
 | 
						RB_INIT(&c->windows);
 | 
				
			||||||
@@ -338,6 +338,8 @@ server_client_lost(struct client *c)
 | 
				
			|||||||
	proc_remove_peer(c->peer);
 | 
						proc_remove_peer(c->peer);
 | 
				
			||||||
	c->peer = NULL;
 | 
						c->peer = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (c->out_fd != -1)
 | 
				
			||||||
 | 
							close(c->out_fd);
 | 
				
			||||||
	if (c->fd != -1) {
 | 
						if (c->fd != -1) {
 | 
				
			||||||
		close(c->fd);
 | 
							close(c->fd);
 | 
				
			||||||
		c->fd = -1;
 | 
							c->fd = -1;
 | 
				
			||||||
@@ -1573,10 +1575,9 @@ server_client_check_pane_buffer(struct window_pane *wp)
 | 
				
			|||||||
out:
 | 
					out:
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If there is data remaining, and there are no clients able to consume
 | 
						 * If there is data remaining, and there are no clients able to consume
 | 
				
			||||||
	 * it, do not read any more. This is true when 1) there are attached
 | 
						 * it, do not read any more. This is true when there are attached
 | 
				
			||||||
	 * clients 2) all the clients are control clients 3) all of them have
 | 
						 * clients, all of which are control clients which are not able to
 | 
				
			||||||
	 * either the OFF flag set, or are otherwise not able to accept any
 | 
						 * accept any more data.
 | 
				
			||||||
	 * more data for this pane.
 | 
					 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (off)
 | 
						if (off)
 | 
				
			||||||
		bufferevent_disable(wp->event, EV_READ);
 | 
							bufferevent_disable(wp->event, EV_READ);
 | 
				
			||||||
@@ -1969,6 +1970,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
 | 
				
			|||||||
	case MSG_IDENTIFY_TTYNAME:
 | 
						case MSG_IDENTIFY_TTYNAME:
 | 
				
			||||||
	case MSG_IDENTIFY_CWD:
 | 
						case MSG_IDENTIFY_CWD:
 | 
				
			||||||
	case MSG_IDENTIFY_STDIN:
 | 
						case MSG_IDENTIFY_STDIN:
 | 
				
			||||||
 | 
						case MSG_IDENTIFY_STDOUT:
 | 
				
			||||||
	case MSG_IDENTIFY_ENVIRON:
 | 
						case MSG_IDENTIFY_ENVIRON:
 | 
				
			||||||
	case MSG_IDENTIFY_CLIENTPID:
 | 
						case MSG_IDENTIFY_CLIENTPID:
 | 
				
			||||||
	case MSG_IDENTIFY_DONE:
 | 
						case MSG_IDENTIFY_DONE:
 | 
				
			||||||
@@ -2179,6 +2181,12 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
				
			|||||||
		c->fd = imsg->fd;
 | 
							c->fd = imsg->fd;
 | 
				
			||||||
		log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd);
 | 
							log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case MSG_IDENTIFY_STDOUT:
 | 
				
			||||||
 | 
							if (datalen != 0)
 | 
				
			||||||
 | 
								fatalx("bad MSG_IDENTIFY_STDOUT size");
 | 
				
			||||||
 | 
							c->out_fd = imsg->fd;
 | 
				
			||||||
 | 
							log_debug("client %p IDENTIFY_STDOUT %d", c, imsg->fd);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case MSG_IDENTIFY_ENVIRON:
 | 
						case MSG_IDENTIFY_ENVIRON:
 | 
				
			||||||
		if (datalen == 0 || data[datalen - 1] != '\0')
 | 
							if (datalen == 0 || data[datalen - 1] != '\0')
 | 
				
			||||||
			fatalx("bad MSG_IDENTIFY_ENVIRON string");
 | 
								fatalx("bad MSG_IDENTIFY_ENVIRON string");
 | 
				
			||||||
@@ -2207,11 +2215,9 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
				
			|||||||
	c->name = name;
 | 
						c->name = name;
 | 
				
			||||||
	log_debug("client %p name is %s", c, c->name);
 | 
						log_debug("client %p name is %s", c, c->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (c->flags & CLIENT_CONTROL) {
 | 
						 if (c->flags & CLIENT_CONTROL)
 | 
				
			||||||
		close(c->fd);
 | 
					 | 
				
			||||||
		c->fd = -1;
 | 
					 | 
				
			||||||
		control_start(c);
 | 
							control_start(c);
 | 
				
			||||||
	} else if (c->fd != -1) {
 | 
						else if (c->fd != -1) {
 | 
				
			||||||
		if (tty_init(&c->tty, c) != 0) {
 | 
							if (tty_init(&c->tty, c) != 0) {
 | 
				
			||||||
			close(c->fd);
 | 
								close(c->fd);
 | 
				
			||||||
			c->fd = -1;
 | 
								c->fd = -1;
 | 
				
			||||||
@@ -2219,6 +2225,8 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
				
			|||||||
			tty_resize(&c->tty);
 | 
								tty_resize(&c->tty);
 | 
				
			||||||
			c->flags |= CLIENT_TERMINAL;
 | 
								c->flags |= CLIENT_TERMINAL;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							close(c->out_fd);
 | 
				
			||||||
 | 
							c->out_fd = -1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
@@ -2335,7 +2343,8 @@ void
 | 
				
			|||||||
server_client_set_flags(struct client *c, const char *flags)
 | 
					server_client_set_flags(struct client *c, const char *flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char	*s, *copy, *next;
 | 
						char	*s, *copy, *next;
 | 
				
			||||||
	int	 flag, not;
 | 
						uint64_t flag;
 | 
				
			||||||
 | 
						int	 not;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s = copy = xstrdup (flags);
 | 
						s = copy = xstrdup (flags);
 | 
				
			||||||
	while ((next = strsep(&s, ",")) != NULL) {
 | 
						while ((next = strsep(&s, ",")) != NULL) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								tmux.h
									
									
									
									
									
								
							@@ -498,6 +498,7 @@ enum msgtype {
 | 
				
			|||||||
	MSG_IDENTIFY_CLIENTPID,
 | 
						MSG_IDENTIFY_CLIENTPID,
 | 
				
			||||||
	MSG_IDENTIFY_CWD,
 | 
						MSG_IDENTIFY_CWD,
 | 
				
			||||||
	MSG_IDENTIFY_FEATURES,
 | 
						MSG_IDENTIFY_FEATURES,
 | 
				
			||||||
 | 
						MSG_IDENTIFY_STDOUT,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MSG_COMMAND = 200,
 | 
						MSG_COMMAND = 200,
 | 
				
			||||||
	MSG_DETACH,
 | 
						MSG_DETACH,
 | 
				
			||||||
@@ -967,6 +968,7 @@ struct window_pane {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	int		 fd;
 | 
						int		 fd;
 | 
				
			||||||
	struct bufferevent *event;
 | 
						struct bufferevent *event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct window_pane_offset offset;
 | 
						struct window_pane_offset offset;
 | 
				
			||||||
	size_t		 base_offset;
 | 
						size_t		 base_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1581,6 +1583,7 @@ struct client {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	pid_t		 pid;
 | 
						pid_t		 pid;
 | 
				
			||||||
	int		 fd;
 | 
						int		 fd;
 | 
				
			||||||
 | 
						int		 out_fd;
 | 
				
			||||||
	struct event	 event;
 | 
						struct event	 event;
 | 
				
			||||||
	int		 retval;
 | 
						int		 retval;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user