mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master'
This commit is contained in:
		@@ -165,13 +165,13 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
 | 
			
		||||
	 * the terminal as that calls tcsetattr() to prepare for tmux taking
 | 
			
		||||
	 * over.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!detached && !already_attached && c->tty.fd != -1) {
 | 
			
		||||
	if (!detached && !already_attached && c->fd != -1) {
 | 
			
		||||
		if (server_client_check_nested(cmdq_get_client(item))) {
 | 
			
		||||
			cmdq_error(item, "sessions should be nested with care, "
 | 
			
		||||
			    "unset $TMUX to force");
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
		if (tcgetattr(c->tty.fd, &tio) != 0)
 | 
			
		||||
		if (tcgetattr(c->fd, &tio) != 0)
 | 
			
		||||
			fatal("tcgetattr failed");
 | 
			
		||||
		tiop = &tio;
 | 
			
		||||
	} else
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										43
									
								
								control.c
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								control.c
									
									
									
									
									
								
							@@ -38,6 +38,11 @@ struct control_offset {
 | 
			
		||||
};
 | 
			
		||||
RB_HEAD(control_offsets, control_offset);
 | 
			
		||||
 | 
			
		||||
/* Control state. */
 | 
			
		||||
struct control_state {
 | 
			
		||||
	struct control_offsets	offsets;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Compare client offsets. */
 | 
			
		||||
static int
 | 
			
		||||
control_offset_cmp(struct control_offset *co1, struct control_offset *co2)
 | 
			
		||||
@@ -54,31 +59,26 @@ RB_GENERATE_STATIC(control_offsets, control_offset, entry, control_offset_cmp);
 | 
			
		||||
static struct control_offset *
 | 
			
		||||
control_get_offset(struct client *c, struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct control_offset	co = { .pane = wp->id };
 | 
			
		||||
	struct control_state	*cs = c->control_state;
 | 
			
		||||
	struct control_offset	 co = { .pane = wp->id };
 | 
			
		||||
 | 
			
		||||
	if (c->offsets == NULL)
 | 
			
		||||
		return (NULL);
 | 
			
		||||
	return (RB_FIND(control_offsets, c->offsets, &co));
 | 
			
		||||
	return (RB_FIND(control_offsets, &cs->offsets, &co));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Add pane offsets for this client. */
 | 
			
		||||
static struct control_offset *
 | 
			
		||||
control_add_offset(struct client *c, struct window_pane *wp)
 | 
			
		||||
{
 | 
			
		||||
	struct control_state	*cs = c->control_state;
 | 
			
		||||
	struct control_offset	*co;
 | 
			
		||||
 | 
			
		||||
	co = control_get_offset(c, wp);
 | 
			
		||||
	if (co != NULL)
 | 
			
		||||
		return (co);
 | 
			
		||||
 | 
			
		||||
	if (c->offsets == NULL) {
 | 
			
		||||
		c->offsets = xmalloc(sizeof *c->offsets);
 | 
			
		||||
		RB_INIT(c->offsets);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	co = xcalloc(1, sizeof *co);
 | 
			
		||||
	co->pane = wp->id;
 | 
			
		||||
	RB_INSERT(control_offsets, c->offsets, co);
 | 
			
		||||
	RB_INSERT(control_offsets, &cs->offsets, co);
 | 
			
		||||
	memcpy(&co->offset, &wp->offset, sizeof co->offset);
 | 
			
		||||
	return (co);
 | 
			
		||||
}
 | 
			
		||||
@@ -87,15 +87,13 @@ control_add_offset(struct client *c, struct window_pane *wp)
 | 
			
		||||
void
 | 
			
		||||
control_free_offsets(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct control_state	*cs = c->control_state;
 | 
			
		||||
	struct control_offset	*co, *co1;
 | 
			
		||||
 | 
			
		||||
	if (c->offsets == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	RB_FOREACH_SAFE(co, control_offsets, c->offsets, co1) {
 | 
			
		||||
		RB_REMOVE(control_offsets, c->offsets, co);
 | 
			
		||||
	RB_FOREACH_SAFE(co, control_offsets, &cs->offsets, co1) {
 | 
			
		||||
		RB_REMOVE(control_offsets, &cs->offsets, co);
 | 
			
		||||
		free(co);
 | 
			
		||||
	}
 | 
			
		||||
	free(c->offsets);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Get offsets for client. */
 | 
			
		||||
@@ -255,8 +253,23 @@ control_callback(__unused struct client *c, __unused const char *path,
 | 
			
		||||
void
 | 
			
		||||
control_start(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct control_state	*cs;
 | 
			
		||||
 | 
			
		||||
	cs = c->control_state = xcalloc(1, sizeof *cs);
 | 
			
		||||
	RB_INIT(&cs->offsets);
 | 
			
		||||
 | 
			
		||||
	file_read(c, "-", control_callback, c);
 | 
			
		||||
 | 
			
		||||
	if (c->flags & CLIENT_CONTROLCONTROL)
 | 
			
		||||
		file_print(c, "\033P1000p");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Stop control mode. */
 | 
			
		||||
void
 | 
			
		||||
control_stop(struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	struct control_state	*cs = c->control_state;
 | 
			
		||||
 | 
			
		||||
	control_free_offsets(c);
 | 
			
		||||
	free(cs);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -227,7 +227,6 @@ server_client_create(int fd)
 | 
			
		||||
	RB_INIT(&c->windows);
 | 
			
		||||
	RB_INIT(&c->files);
 | 
			
		||||
 | 
			
		||||
	c->tty.fd = -1;
 | 
			
		||||
	c->tty.sx = 80;
 | 
			
		||||
	c->tty.sy = 24;
 | 
			
		||||
 | 
			
		||||
@@ -305,10 +304,8 @@ server_client_lost(struct client *c)
 | 
			
		||||
	TAILQ_REMOVE(&clients, c, entry);
 | 
			
		||||
	log_debug("lost client %p", c);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
 | 
			
		||||
	 * and tty_free might close an unrelated fd.
 | 
			
		||||
	 */
 | 
			
		||||
	if (c->flags & CLIENT_CONTROL)
 | 
			
		||||
		control_stop(c);
 | 
			
		||||
	if (c->flags & CLIENT_TERMINAL)
 | 
			
		||||
		tty_free(&c->tty);
 | 
			
		||||
	free(c->ttyname);
 | 
			
		||||
@@ -340,6 +337,10 @@ server_client_lost(struct client *c)
 | 
			
		||||
	proc_remove_peer(c->peer);
 | 
			
		||||
	c->peer = NULL;
 | 
			
		||||
 | 
			
		||||
	if (c->fd != -1) {
 | 
			
		||||
		close(c->fd);
 | 
			
		||||
		c->fd = -1;
 | 
			
		||||
	}
 | 
			
		||||
	server_client_unref(c);
 | 
			
		||||
 | 
			
		||||
	server_add_accept(0); /* may be more file descriptors now */
 | 
			
		||||
@@ -2006,7 +2007,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
 | 
			
		||||
			break;
 | 
			
		||||
		c->flags &= ~CLIENT_SUSPENDED;
 | 
			
		||||
 | 
			
		||||
		if (c->tty.fd == -1) /* exited in the meantime */
 | 
			
		||||
		if (c->fd == -1) /* exited in the meantime */
 | 
			
		||||
			break;
 | 
			
		||||
		s = c->session;
 | 
			
		||||
 | 
			
		||||
@@ -2212,11 +2213,9 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 | 
			
		||||
	if (c->flags & CLIENT_CONTROL) {
 | 
			
		||||
		close(c->fd);
 | 
			
		||||
		c->fd = -1;
 | 
			
		||||
 | 
			
		||||
		control_start(c);
 | 
			
		||||
		c->tty.fd = -1;
 | 
			
		||||
	} else if (c->fd != -1) {
 | 
			
		||||
		if (tty_init(&c->tty, c, c->fd) != 0) {
 | 
			
		||||
		if (tty_init(&c->tty, c) != 0) {
 | 
			
		||||
			close(c->fd);
 | 
			
		||||
			c->fd = -1;
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tmux.h
									
									
									
									
									
								
							@@ -47,7 +47,7 @@ struct cmdq_item;
 | 
			
		||||
struct cmdq_list;
 | 
			
		||||
struct cmdq_state;
 | 
			
		||||
struct cmds;
 | 
			
		||||
struct control_offsets;
 | 
			
		||||
struct control_state;
 | 
			
		||||
struct environ;
 | 
			
		||||
struct format_job_tree;
 | 
			
		||||
struct format_tree;
 | 
			
		||||
@@ -1285,7 +1285,6 @@ struct tty {
 | 
			
		||||
	u_int		 rleft;
 | 
			
		||||
	u_int		 rright;
 | 
			
		||||
 | 
			
		||||
	int		 fd;
 | 
			
		||||
	struct event	 event_in;
 | 
			
		||||
	struct evbuffer	*in;
 | 
			
		||||
	struct event	 event_out;
 | 
			
		||||
@@ -1566,7 +1565,7 @@ struct client {
 | 
			
		||||
	struct cmdq_list *queue;
 | 
			
		||||
 | 
			
		||||
	struct client_windows windows;
 | 
			
		||||
	struct control_offsets *offsets;
 | 
			
		||||
	struct control_state *control_state;
 | 
			
		||||
 | 
			
		||||
	pid_t		 pid;
 | 
			
		||||
	int		 fd;
 | 
			
		||||
@@ -2066,7 +2065,7 @@ void	tty_putc(struct tty *, u_char);
 | 
			
		||||
void	tty_putn(struct tty *, const void *, size_t, u_int);
 | 
			
		||||
void	tty_cell(struct tty *, const struct grid_cell *,
 | 
			
		||||
	    const struct grid_cell *, int *);
 | 
			
		||||
int	tty_init(struct tty *, struct client *, int);
 | 
			
		||||
int	tty_init(struct tty *, struct client *);
 | 
			
		||||
void	tty_resize(struct tty *);
 | 
			
		||||
void	tty_set_size(struct tty *, u_int, u_int, u_int, u_int);
 | 
			
		||||
void	tty_start_tty(struct tty *);
 | 
			
		||||
@@ -2816,6 +2815,7 @@ char	*parse_window_name(const char *);
 | 
			
		||||
 | 
			
		||||
/* control.c */
 | 
			
		||||
void	control_start(struct client *);
 | 
			
		||||
void	control_stop(struct client *);
 | 
			
		||||
void	control_set_pane_on(struct client *, struct window_pane *);
 | 
			
		||||
void	control_set_pane_off(struct client *, struct window_pane *);
 | 
			
		||||
struct window_pane_offset *control_pane_offset(struct client *,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										67
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								tty.c
									
									
									
									
									
								
							@@ -90,19 +90,19 @@ tty_create_log(void)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
tty_init(struct tty *tty, struct client *c, int fd)
 | 
			
		||||
tty_init(struct tty *tty, struct client *c)
 | 
			
		||||
{
 | 
			
		||||
	if (!isatty(fd))
 | 
			
		||||
	if (!isatty(c->fd))
 | 
			
		||||
		return (-1);
 | 
			
		||||
 | 
			
		||||
	memset(tty, 0, sizeof *tty);
 | 
			
		||||
 | 
			
		||||
	tty->fd = fd;
 | 
			
		||||
	tty->client = c;
 | 
			
		||||
 | 
			
		||||
	tty->cstyle = 0;
 | 
			
		||||
	tty->ccolour = xstrdup("");
 | 
			
		||||
 | 
			
		||||
	if (tcgetattr(c->fd, &tty->tio) != 0)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	return (0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -113,7 +113,7 @@ tty_resize(struct tty *tty)
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
	u_int		 sx, sy, xpixel, ypixel;
 | 
			
		||||
 | 
			
		||||
	if (ioctl(tty->fd, TIOCGWINSZ, &ws) != -1) {
 | 
			
		||||
	if (ioctl(c->fd, TIOCGWINSZ, &ws) != -1) {
 | 
			
		||||
		sx = ws.ws_col;
 | 
			
		||||
		if (sx == 0) {
 | 
			
		||||
			sx = 80;
 | 
			
		||||
@@ -156,7 +156,7 @@ tty_read_callback(__unused int fd, __unused short events, void *data)
 | 
			
		||||
	size_t		 size = EVBUFFER_LENGTH(tty->in);
 | 
			
		||||
	int		 nread;
 | 
			
		||||
 | 
			
		||||
	nread = evbuffer_read(tty->in, tty->fd, -1);
 | 
			
		||||
	nread = evbuffer_read(tty->in, c->fd, -1);
 | 
			
		||||
	if (nread == 0 || nread == -1) {
 | 
			
		||||
		if (nread == 0)
 | 
			
		||||
			log_debug("%s: read closed", name);
 | 
			
		||||
@@ -225,7 +225,7 @@ tty_write_callback(__unused int fd, __unused short events, void *data)
 | 
			
		||||
	size_t		 size = EVBUFFER_LENGTH(tty->out);
 | 
			
		||||
	int		 nwrite;
 | 
			
		||||
 | 
			
		||||
	nwrite = evbuffer_write(tty->out, tty->fd);
 | 
			
		||||
	nwrite = evbuffer_write(tty->out, c->fd);
 | 
			
		||||
	if (nwrite == -1)
 | 
			
		||||
		return;
 | 
			
		||||
	log_debug("%s: wrote %d bytes (of %zu)", c->name, nwrite, size);
 | 
			
		||||
@@ -250,7 +250,7 @@ tty_open(struct tty *tty, char **cause)
 | 
			
		||||
	struct client	*c = tty->client;
 | 
			
		||||
 | 
			
		||||
	tty->term = tty_term_create(tty, c->term_name, &c->term_features,
 | 
			
		||||
	    tty->fd, cause);
 | 
			
		||||
	    c->fd, cause);
 | 
			
		||||
	if (tty->term == NULL) {
 | 
			
		||||
		tty_close(tty);
 | 
			
		||||
		return (-1);
 | 
			
		||||
@@ -259,13 +259,13 @@ tty_open(struct tty *tty, char **cause)
 | 
			
		||||
 | 
			
		||||
	tty->flags &= ~(TTY_NOCURSOR|TTY_FREEZE|TTY_BLOCK|TTY_TIMER);
 | 
			
		||||
 | 
			
		||||
	event_set(&tty->event_in, tty->fd, EV_PERSIST|EV_READ,
 | 
			
		||||
	event_set(&tty->event_in, c->fd, EV_PERSIST|EV_READ,
 | 
			
		||||
	    tty_read_callback, tty);
 | 
			
		||||
	tty->in = evbuffer_new();
 | 
			
		||||
	if (tty->in == NULL)
 | 
			
		||||
		fatal("out of memory");
 | 
			
		||||
 | 
			
		||||
	event_set(&tty->event_out, tty->fd, EV_WRITE, tty_write_callback, tty);
 | 
			
		||||
	event_set(&tty->event_out, c->fd, EV_WRITE, tty_write_callback, tty);
 | 
			
		||||
	tty->out = evbuffer_new();
 | 
			
		||||
	if (tty->out == NULL)
 | 
			
		||||
		fatal("out of memory");
 | 
			
		||||
@@ -298,21 +298,19 @@ tty_start_tty(struct tty *tty)
 | 
			
		||||
	struct termios	 tio;
 | 
			
		||||
	struct timeval	 tv = { .tv_sec = 1 };
 | 
			
		||||
 | 
			
		||||
	if (tty->fd != -1 && tcgetattr(tty->fd, &tty->tio) == 0) {
 | 
			
		||||
		setblocking(tty->fd, 0);
 | 
			
		||||
		event_add(&tty->event_in, NULL);
 | 
			
		||||
	setblocking(c->fd, 0);
 | 
			
		||||
	event_add(&tty->event_in, NULL);
 | 
			
		||||
 | 
			
		||||
		memcpy(&tio, &tty->tio, sizeof tio);
 | 
			
		||||
		tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
 | 
			
		||||
		tio.c_iflag |= IGNBRK;
 | 
			
		||||
		tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
 | 
			
		||||
		tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|
 | 
			
		||||
		    ECHOPRT|ECHOKE|ISIG);
 | 
			
		||||
		tio.c_cc[VMIN] = 1;
 | 
			
		||||
		tio.c_cc[VTIME] = 0;
 | 
			
		||||
		if (tcsetattr(tty->fd, TCSANOW, &tio) == 0)
 | 
			
		||||
			tcflush(tty->fd, TCIOFLUSH);
 | 
			
		||||
	}
 | 
			
		||||
	memcpy(&tio, &tty->tio, sizeof tio);
 | 
			
		||||
	tio.c_iflag &= ~(IXON|IXOFF|ICRNL|INLCR|IGNCR|IMAXBEL|ISTRIP);
 | 
			
		||||
	tio.c_iflag |= IGNBRK;
 | 
			
		||||
	tio.c_oflag &= ~(OPOST|ONLCR|OCRNL|ONLRET);
 | 
			
		||||
	tio.c_lflag &= ~(IEXTEN|ICANON|ECHO|ECHOE|ECHONL|ECHOCTL|ECHOPRT|
 | 
			
		||||
	    ECHOKE|ISIG);
 | 
			
		||||
	tio.c_cc[VMIN] = 1;
 | 
			
		||||
	tio.c_cc[VTIME] = 0;
 | 
			
		||||
	if (tcsetattr(c->fd, TCSANOW, &tio) == 0)
 | 
			
		||||
		tcflush(c->fd, TCIOFLUSH);
 | 
			
		||||
 | 
			
		||||
	tty_putcode(tty, TTYC_SMCUP);
 | 
			
		||||
 | 
			
		||||
@@ -363,7 +361,8 @@ tty_send_requests(struct tty *tty)
 | 
			
		||||
void
 | 
			
		||||
tty_stop_tty(struct tty *tty)
 | 
			
		||||
{
 | 
			
		||||
	struct winsize	ws;
 | 
			
		||||
	struct client	*c = tty->client;
 | 
			
		||||
	struct winsize	 ws;
 | 
			
		||||
 | 
			
		||||
	if (!(tty->flags & TTY_STARTED))
 | 
			
		||||
		return;
 | 
			
		||||
@@ -382,9 +381,9 @@ tty_stop_tty(struct tty *tty)
 | 
			
		||||
	 * because the fd is invalid. Things like ssh -t can easily leave us
 | 
			
		||||
	 * with a dead tty.
 | 
			
		||||
	 */
 | 
			
		||||
	if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1)
 | 
			
		||||
	if (ioctl(c->fd, TIOCGWINSZ, &ws) == -1)
 | 
			
		||||
		return;
 | 
			
		||||
	if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1)
 | 
			
		||||
	if (tcsetattr(c->fd, TCSANOW, &tty->tio) == -1)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	tty_raw(tty, tty_term_string2(tty->term, TTYC_CSR, 0, ws.ws_row - 1));
 | 
			
		||||
@@ -419,7 +418,7 @@ tty_stop_tty(struct tty *tty)
 | 
			
		||||
		tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG));
 | 
			
		||||
	tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP));
 | 
			
		||||
 | 
			
		||||
	setblocking(tty->fd, 1);
 | 
			
		||||
	setblocking(c->fd, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -440,11 +439,6 @@ tty_close(struct tty *tty)
 | 
			
		||||
 | 
			
		||||
		tty->flags &= ~TTY_OPENED;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tty->fd != -1) {
 | 
			
		||||
		close(tty->fd);
 | 
			
		||||
		tty->fd = -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
@@ -475,12 +469,13 @@ tty_update_features(struct tty *tty)
 | 
			
		||||
void
 | 
			
		||||
tty_raw(struct tty *tty, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t	n, slen;
 | 
			
		||||
	u_int	i;
 | 
			
		||||
	struct client	*c = tty->client;
 | 
			
		||||
	ssize_t		 n, slen;
 | 
			
		||||
	u_int		 i;
 | 
			
		||||
 | 
			
		||||
	slen = strlen(s);
 | 
			
		||||
	for (i = 0; i < 5; i++) {
 | 
			
		||||
		n = write(tty->fd, s, slen);
 | 
			
		||||
		n = write(c->fd, s, slen);
 | 
			
		||||
		if (n >= 0) {
 | 
			
		||||
			s += n;
 | 
			
		||||
			slen -= n;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user