File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / tmux / server-client.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:22:44 2017 UTC (7 years ago) by misho
CVS tags: MAIN, HEAD
Initial revision

    1: /* $OpenBSD$ */
    2: 
    3: /*
    4:  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
    5:  *
    6:  * Permission to use, copy, modify, and distribute this software for any
    7:  * purpose with or without fee is hereby granted, provided that the above
    8:  * copyright notice and this permission notice appear in all copies.
    9:  *
   10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
   15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
   16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17:  */
   18: 
   19: #include <sys/types.h>
   20: #include <sys/ioctl.h>
   21: #include <sys/uio.h>
   22: 
   23: #include <errno.h>
   24: #include <event.h>
   25: #include <fcntl.h>
   26: #include <stdlib.h>
   27: #include <string.h>
   28: #include <time.h>
   29: #include <unistd.h>
   30: 
   31: #include "tmux.h"
   32: 
   33: static void	server_client_free(int, short, void *);
   34: static void	server_client_check_focus(struct window_pane *);
   35: static void	server_client_check_resize(struct window_pane *);
   36: static key_code	server_client_check_mouse(struct client *);
   37: static void	server_client_repeat_timer(int, short, void *);
   38: static void	server_client_click_timer(int, short, void *);
   39: static void	server_client_check_exit(struct client *);
   40: static void	server_client_check_redraw(struct client *);
   41: static void	server_client_set_title(struct client *);
   42: static void	server_client_reset_state(struct client *);
   43: static int	server_client_assume_paste(struct session *);
   44: 
   45: static void	server_client_dispatch(struct imsg *, void *);
   46: static void	server_client_dispatch_command(struct client *, struct imsg *);
   47: static void	server_client_dispatch_identify(struct client *, struct imsg *);
   48: static void	server_client_dispatch_shell(struct client *);
   49: 
   50: /* Idenfity mode callback. */
   51: static void
   52: server_client_callback_identify(__unused int fd, __unused short events, void *data)
   53: {
   54: 	server_client_clear_identify(data, NULL);
   55: }
   56: 
   57: /* Set identify mode on client. */
   58: void
   59: server_client_set_identify(struct client *c)
   60: {
   61: 	struct timeval	tv;
   62: 	int		delay;
   63: 
   64: 	delay = options_get_number(c->session->options, "display-panes-time");
   65: 	tv.tv_sec = delay / 1000;
   66: 	tv.tv_usec = (delay % 1000) * 1000L;
   67: 
   68: 	if (event_initialized(&c->identify_timer))
   69: 		evtimer_del(&c->identify_timer);
   70: 	evtimer_set(&c->identify_timer, server_client_callback_identify, c);
   71: 	evtimer_add(&c->identify_timer, &tv);
   72: 
   73: 	c->flags |= CLIENT_IDENTIFY;
   74: 	c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
   75: 	server_redraw_client(c);
   76: }
   77: 
   78: /* Clear identify mode on client. */
   79: void
   80: server_client_clear_identify(struct client *c, struct window_pane *wp)
   81: {
   82: 	if (~c->flags & CLIENT_IDENTIFY)
   83: 		return;
   84: 	c->flags &= ~CLIENT_IDENTIFY;
   85: 
   86: 	if (c->identify_callback != NULL)
   87: 		c->identify_callback(c, wp);
   88: 
   89: 	c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
   90: 	server_redraw_client(c);
   91: }
   92: 
   93: /* Check if this client is inside this server. */
   94: int
   95: server_client_check_nested(struct client *c)
   96: {
   97: 	struct environ_entry	*envent;
   98: 	struct window_pane	*wp;
   99: 
  100: 	envent = environ_find(c->environ, "TMUX");
  101: 	if (envent == NULL || *envent->value == '\0')
  102: 		return (0);
  103: 
  104: 	RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
  105: 		if (strcmp(wp->tty, c->ttyname) == 0)
  106: 			return (1);
  107: 	}
  108: 	return (0);
  109: }
  110: 
  111: /* Set client key table. */
  112: void
  113: server_client_set_key_table(struct client *c, const char *name)
  114: {
  115: 	if (name == NULL)
  116: 		name = server_client_get_key_table(c);
  117: 
  118: 	key_bindings_unref_table(c->keytable);
  119: 	c->keytable = key_bindings_get_table(name, 1);
  120: 	c->keytable->references++;
  121: }
  122: 
  123: /* Get default key table. */
  124: const char *
  125: server_client_get_key_table(struct client *c)
  126: {
  127: 	struct session	*s = c->session;
  128: 	const char	*name;
  129: 
  130: 	if (s == NULL)
  131: 		return ("root");
  132: 
  133: 	name = options_get_string(s->options, "key-table");
  134: 	if (*name == '\0')
  135: 		return ("root");
  136: 	return (name);
  137: }
  138: 
  139: /* Is this client using the default key table? */
  140: int
  141: server_client_is_default_key_table(struct client *c)
  142: {
  143: 	return (strcmp(c->keytable->name, server_client_get_key_table(c)) == 0);
  144: }
  145: 
  146: /* Create a new client. */
  147: void
  148: server_client_create(int fd)
  149: {
  150: 	struct client	*c;
  151: 
  152: 	setblocking(fd, 0);
  153: 
  154: 	c = xcalloc(1, sizeof *c);
  155: 	c->references = 1;
  156: 	c->peer = proc_add_peer(server_proc, fd, server_client_dispatch, c);
  157: 
  158: 	if (gettimeofday(&c->creation_time, NULL) != 0)
  159: 		fatal("gettimeofday failed");
  160: 	memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
  161: 
  162: 	c->environ = environ_create();
  163: 
  164: 	c->fd = -1;
  165: 	c->cwd = NULL;
  166: 
  167: 	TAILQ_INIT(&c->queue);
  168: 
  169: 	c->stdin_data = evbuffer_new();
  170: 	c->stdout_data = evbuffer_new();
  171: 	c->stderr_data = evbuffer_new();
  172: 
  173: 	c->tty.fd = -1;
  174: 	c->title = NULL;
  175: 
  176: 	c->session = NULL;
  177: 	c->last_session = NULL;
  178: 	c->tty.sx = 80;
  179: 	c->tty.sy = 24;
  180: 
  181: 	screen_init(&c->status, c->tty.sx, 1, 0);
  182: 
  183: 	c->message_string = NULL;
  184: 	TAILQ_INIT(&c->message_log);
  185: 
  186: 	c->prompt_string = NULL;
  187: 	c->prompt_buffer = NULL;
  188: 	c->prompt_index = 0;
  189: 
  190: 	c->flags |= CLIENT_FOCUSED;
  191: 
  192: 	c->keytable = key_bindings_get_table("root", 1);
  193: 	c->keytable->references++;
  194: 
  195: 	evtimer_set(&c->repeat_timer, server_client_repeat_timer, c);
  196: 	evtimer_set(&c->click_timer, server_client_click_timer, c);
  197: 
  198: 	TAILQ_INSERT_TAIL(&clients, c, entry);
  199: 	log_debug("new client %p", c);
  200: }
  201: 
  202: /* Open client terminal if needed. */
  203: int
  204: server_client_open(struct client *c, char **cause)
  205: {
  206: 	if (c->flags & CLIENT_CONTROL)
  207: 		return (0);
  208: 
  209: 	if (strcmp(c->ttyname, "/dev/tty") == 0) {
  210: 		*cause = xstrdup("can't use /dev/tty");
  211: 		return (-1);
  212: 	}
  213: 
  214: 	if (!(c->flags & CLIENT_TERMINAL)) {
  215: 		*cause = xstrdup("not a terminal");
  216: 		return (-1);
  217: 	}
  218: 
  219: 	if (tty_open(&c->tty, cause) != 0)
  220: 		return (-1);
  221: 
  222: 	return (0);
  223: }
  224: 
  225: /* Lost a client. */
  226: void
  227: server_client_lost(struct client *c)
  228: {
  229: 	struct message_entry	*msg, *msg1;
  230: 
  231: 	c->flags |= CLIENT_DEAD;
  232: 
  233: 	server_client_clear_identify(c, NULL);
  234: 	status_prompt_clear(c);
  235: 	status_message_clear(c);
  236: 
  237: 	if (c->stdin_callback != NULL)
  238: 		c->stdin_callback(c, 1, c->stdin_callback_data);
  239: 
  240: 	TAILQ_REMOVE(&clients, c, entry);
  241: 	log_debug("lost client %p", c);
  242: 
  243: 	/*
  244: 	 * If CLIENT_TERMINAL hasn't been set, then tty_init hasn't been called
  245: 	 * and tty_free might close an unrelated fd.
  246: 	 */
  247: 	if (c->flags & CLIENT_TERMINAL)
  248: 		tty_free(&c->tty);
  249: 	free(c->ttyname);
  250: 	free(c->term);
  251: 
  252: 	evbuffer_free(c->stdin_data);
  253: 	evbuffer_free(c->stdout_data);
  254: 	if (c->stderr_data != c->stdout_data)
  255: 		evbuffer_free(c->stderr_data);
  256: 
  257: 	if (event_initialized(&c->status_timer))
  258: 		evtimer_del(&c->status_timer);
  259: 	screen_free(&c->status);
  260: 
  261: 	free(c->title);
  262: 	free((void *)c->cwd);
  263: 
  264: 	evtimer_del(&c->repeat_timer);
  265: 	evtimer_del(&c->click_timer);
  266: 
  267: 	key_bindings_unref_table(c->keytable);
  268: 
  269: 	if (event_initialized(&c->identify_timer))
  270: 		evtimer_del(&c->identify_timer);
  271: 
  272: 	free(c->message_string);
  273: 	if (event_initialized(&c->message_timer))
  274: 		evtimer_del(&c->message_timer);
  275: 	TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) {
  276: 		free(msg->msg);
  277: 		TAILQ_REMOVE(&c->message_log, msg, entry);
  278: 		free(msg);
  279: 	}
  280: 
  281: 	free(c->prompt_string);
  282: 	free(c->prompt_buffer);
  283: 
  284: 	environ_free(c->environ);
  285: 
  286: 	proc_remove_peer(c->peer);
  287: 	c->peer = NULL;
  288: 
  289: 	server_client_unref(c);
  290: 
  291: 	server_add_accept(0); /* may be more file descriptors now */
  292: 
  293: 	recalculate_sizes();
  294: 	server_check_unattached();
  295: 	server_update_socket();
  296: }
  297: 
  298: /* Remove reference from a client. */
  299: void
  300: server_client_unref(struct client *c)
  301: {
  302: 	log_debug("unref client %p (%d references)", c, c->references);
  303: 
  304: 	c->references--;
  305: 	if (c->references == 0)
  306: 		event_once(-1, EV_TIMEOUT, server_client_free, c, NULL);
  307: }
  308: 
  309: /* Free dead client. */
  310: static void
  311: server_client_free(__unused int fd, __unused short events, void *arg)
  312: {
  313: 	struct client	*c = arg;
  314: 
  315: 	log_debug("free client %p (%d references)", c, c->references);
  316: 
  317: 	if (!TAILQ_EMPTY(&c->queue))
  318: 		fatalx("queue not empty");
  319: 
  320: 	if (c->references == 0) {
  321: 		free((void *)c->name);
  322: 		free(c);
  323: 	}
  324: }
  325: 
  326: /* Detach a client. */
  327: void
  328: server_client_detach(struct client *c, enum msgtype msgtype)
  329: {
  330: 	struct session	*s = c->session;
  331: 
  332: 	if (s == NULL)
  333: 		return;
  334: 
  335: 	notify_client("client-detached", c);
  336: 	proc_send_s(c->peer, msgtype, s->name);
  337: }
  338: 
  339: /* Execute command to replace a client. */
  340: void
  341: server_client_exec(struct client *c, const char *cmd)
  342: {
  343: 	struct session	*s = c->session;
  344: 	char		*msg;
  345: 	const char	*shell;
  346: 	size_t		 cmdsize, shellsize;
  347: 
  348: 	if (*cmd == '\0')
  349: 		return;
  350: 	cmdsize = strlen(cmd) + 1;
  351: 
  352: 	if (s != NULL)
  353: 		shell = options_get_string(s->options, "default-shell");
  354: 	else
  355: 		shell = options_get_string(global_s_options, "default-shell");
  356: 	shellsize = strlen(shell) + 1;
  357: 
  358: 	msg = xmalloc(cmdsize + shellsize);
  359: 	memcpy(msg, cmd, cmdsize);
  360: 	memcpy(msg + cmdsize, shell, shellsize);
  361: 
  362: 	proc_send(c->peer, MSG_EXEC, -1, msg, cmdsize + shellsize);
  363: 	free(msg);
  364: }
  365: 
  366: /* Check for mouse keys. */
  367: static key_code
  368: server_client_check_mouse(struct client *c)
  369: {
  370: 	struct session		*s = c->session;
  371: 	struct mouse_event	*m = &c->tty.mouse;
  372: 	struct window		*w;
  373: 	struct window_pane	*wp;
  374: 	u_int			 x, y, b;
  375: 	int			 flag;
  376: 	key_code		 key;
  377: 	struct timeval		 tv;
  378: 	enum { NOTYPE, MOVE, DOWN, UP, DRAG, WHEEL, DOUBLE, TRIPLE } type;
  379: 	enum { NOWHERE, PANE, STATUS, BORDER } where;
  380: 
  381: 	type = NOTYPE;
  382: 	where = NOWHERE;
  383: 
  384: 	log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
  385: 	    m->lx, m->ly, c->tty.mouse_drag_flag);
  386: 
  387: 	/* What type of event is this? */
  388: 	if ((m->sgr_type != ' ' &&
  389: 	    MOUSE_DRAG(m->sgr_b) &&
  390: 	    MOUSE_BUTTONS(m->sgr_b) == 3) ||
  391: 	    (m->sgr_type == ' ' &&
  392: 	    MOUSE_DRAG(m->b) &&
  393: 	    MOUSE_BUTTONS(m->b) == 3 &&
  394: 	    MOUSE_BUTTONS(m->lb) == 3)) {
  395: 		type = MOVE;
  396: 		x = m->x, y = m->y, b = 0;
  397: 		log_debug("move at %u,%u", x, y);
  398: 	} else if (MOUSE_DRAG(m->b)) {
  399: 		type = DRAG;
  400: 		if (c->tty.mouse_drag_flag) {
  401: 			x = m->x, y = m->y, b = m->b;
  402: 			log_debug("drag update at %u,%u", x, y);
  403: 		} else {
  404: 			x = m->lx, y = m->ly, b = m->lb;
  405: 			log_debug("drag start at %u,%u", x, y);
  406: 		}
  407: 	} else if (MOUSE_WHEEL(m->b)) {
  408: 		type = WHEEL;
  409: 		x = m->x, y = m->y, b = m->b;
  410: 		log_debug("wheel at %u,%u", x, y);
  411: 	} else if (MOUSE_RELEASE(m->b)) {
  412: 		type = UP;
  413: 		x = m->x, y = m->y, b = m->lb;
  414: 		log_debug("up at %u,%u", x, y);
  415: 	} else {
  416: 		if (c->flags & CLIENT_DOUBLECLICK) {
  417: 			evtimer_del(&c->click_timer);
  418: 			c->flags &= ~CLIENT_DOUBLECLICK;
  419: 			if (m->b == c->click_button) {
  420: 				type = DOUBLE;
  421: 				x = m->x, y = m->y, b = m->b;
  422: 				log_debug("double-click at %u,%u", x, y);
  423: 				flag = CLIENT_TRIPLECLICK;
  424: 				goto add_timer;
  425: 			}
  426: 		} else if (c->flags & CLIENT_TRIPLECLICK) {
  427: 			evtimer_del(&c->click_timer);
  428: 			c->flags &= ~CLIENT_TRIPLECLICK;
  429: 			if (m->b == c->click_button) {
  430: 				type = TRIPLE;
  431: 				x = m->x, y = m->y, b = m->b;
  432: 				log_debug("triple-click at %u,%u", x, y);
  433: 				goto have_event;
  434: 			}
  435: 		}
  436: 
  437: 		type = DOWN;
  438: 		x = m->x, y = m->y, b = m->b;
  439: 		log_debug("down at %u,%u", x, y);
  440: 		flag = CLIENT_DOUBLECLICK;
  441: 
  442: 	add_timer:
  443: 		if (KEYC_CLICK_TIMEOUT != 0) {
  444: 			c->flags |= flag;
  445: 			c->click_button = m->b;
  446: 
  447: 			tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
  448: 			tv.tv_usec = (KEYC_CLICK_TIMEOUT % 1000) * 1000L;
  449: 			evtimer_del(&c->click_timer);
  450: 			evtimer_add(&c->click_timer, &tv);
  451: 		}
  452: 	}
  453: 
  454: have_event:
  455: 	if (type == NOTYPE)
  456: 		return (KEYC_UNKNOWN);
  457: 
  458: 	/* Always save the session. */
  459: 	m->s = s->id;
  460: 
  461: 	/* Is this on the status line? */
  462: 	m->statusat = status_at_line(c);
  463: 	if (m->statusat != -1 && y == (u_int)m->statusat) {
  464: 		w = status_get_window_at(c, x);
  465: 		if (w == NULL)
  466: 			return (KEYC_UNKNOWN);
  467: 		m->w = w->id;
  468: 		where = STATUS;
  469: 	} else
  470: 		m->w = -1;
  471: 
  472: 	/* Not on status line. Adjust position and check for border or pane. */
  473: 	if (where == NOWHERE) {
  474: 		if (m->statusat == 0 && y > 0)
  475: 			y--;
  476: 		else if (m->statusat > 0 && y >= (u_int)m->statusat)
  477: 			y = m->statusat - 1;
  478: 
  479: 		TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
  480: 			if ((wp->xoff + wp->sx == x &&
  481: 			    wp->yoff <= 1 + y &&
  482: 			    wp->yoff + wp->sy >= y) ||
  483: 			    (wp->yoff + wp->sy == y &&
  484: 			    wp->xoff <= 1 + x &&
  485: 			    wp->xoff + wp->sx >= x))
  486: 				break;
  487: 		}
  488: 		if (wp != NULL)
  489: 			where = BORDER;
  490: 		else {
  491: 			wp = window_get_active_at(s->curw->window, x, y);
  492: 			if (wp != NULL) {
  493: 				where = PANE;
  494: 				log_debug("mouse at %u,%u is on pane %%%u",
  495: 				    x, y, wp->id);
  496: 			}
  497: 		}
  498: 		if (where == NOWHERE)
  499: 			return (KEYC_UNKNOWN);
  500: 		m->wp = wp->id;
  501: 		m->w = wp->window->id;
  502: 	} else
  503: 		m->wp = -1;
  504: 
  505: 	/* Stop dragging if needed. */
  506: 	if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag) {
  507: 		if (c->tty.mouse_drag_release != NULL)
  508: 			c->tty.mouse_drag_release(c, m);
  509: 
  510: 		c->tty.mouse_drag_update = NULL;
  511: 		c->tty.mouse_drag_release = NULL;
  512: 
  513: 		/*
  514: 		 * End a mouse drag by passing a MouseDragEnd key corresponding
  515: 		 * to the button that started the drag.
  516: 		 */
  517: 		switch (c->tty.mouse_drag_flag) {
  518: 		case 1:
  519: 			if (where == PANE)
  520: 				key = KEYC_MOUSEDRAGEND1_PANE;
  521: 			if (where == STATUS)
  522: 				key = KEYC_MOUSEDRAGEND1_STATUS;
  523: 			if (where == BORDER)
  524: 				key = KEYC_MOUSEDRAGEND1_BORDER;
  525: 			break;
  526: 		case 2:
  527: 			if (where == PANE)
  528: 				key = KEYC_MOUSEDRAGEND2_PANE;
  529: 			if (where == STATUS)
  530: 				key = KEYC_MOUSEDRAGEND2_STATUS;
  531: 			if (where == BORDER)
  532: 				key = KEYC_MOUSEDRAGEND2_BORDER;
  533: 			break;
  534: 		case 3:
  535: 			if (where == PANE)
  536: 				key = KEYC_MOUSEDRAGEND3_PANE;
  537: 			if (where == STATUS)
  538: 				key = KEYC_MOUSEDRAGEND3_STATUS;
  539: 			if (where == BORDER)
  540: 				key = KEYC_MOUSEDRAGEND3_BORDER;
  541: 			break;
  542: 		default:
  543: 			key = KEYC_MOUSE;
  544: 			break;
  545: 		}
  546: 		c->tty.mouse_drag_flag = 0;
  547: 
  548: 		return (key);
  549: 	}
  550: 
  551: 	/* Convert to a key binding. */
  552: 	key = KEYC_UNKNOWN;
  553: 	switch (type) {
  554: 	case NOTYPE:
  555: 		break;
  556: 	case MOVE:
  557: 		if (where == PANE)
  558: 			key = KEYC_MOUSEMOVE_PANE;
  559: 		if (where == STATUS)
  560: 			key = KEYC_MOUSEMOVE_STATUS;
  561: 		if (where == BORDER)
  562: 			key = KEYC_MOUSEMOVE_BORDER;
  563: 		break;
  564: 	case DRAG:
  565: 		if (c->tty.mouse_drag_update != NULL)
  566: 			key = KEYC_DRAGGING;
  567: 		else {
  568: 			switch (MOUSE_BUTTONS(b)) {
  569: 			case 0:
  570: 				if (where == PANE)
  571: 					key = KEYC_MOUSEDRAG1_PANE;
  572: 				if (where == STATUS)
  573: 					key = KEYC_MOUSEDRAG1_STATUS;
  574: 				if (where == BORDER)
  575: 					key = KEYC_MOUSEDRAG1_BORDER;
  576: 				break;
  577: 			case 1:
  578: 				if (where == PANE)
  579: 					key = KEYC_MOUSEDRAG2_PANE;
  580: 				if (where == STATUS)
  581: 					key = KEYC_MOUSEDRAG2_STATUS;
  582: 				if (where == BORDER)
  583: 					key = KEYC_MOUSEDRAG2_BORDER;
  584: 				break;
  585: 			case 2:
  586: 				if (where == PANE)
  587: 					key = KEYC_MOUSEDRAG3_PANE;
  588: 				if (where == STATUS)
  589: 					key = KEYC_MOUSEDRAG3_STATUS;
  590: 				if (where == BORDER)
  591: 					key = KEYC_MOUSEDRAG3_BORDER;
  592: 				break;
  593: 			}
  594: 		}
  595: 
  596: 		/*
  597: 		 * Begin a drag by setting the flag to a non-zero value that
  598: 		 * corresponds to the mouse button in use.
  599: 		 */
  600: 		c->tty.mouse_drag_flag = MOUSE_BUTTONS(b) + 1;
  601: 		break;
  602: 	case WHEEL:
  603: 		if (MOUSE_BUTTONS(b) == MOUSE_WHEEL_UP) {
  604: 			if (where == PANE)
  605: 				key = KEYC_WHEELUP_PANE;
  606: 			if (where == STATUS)
  607: 				key = KEYC_WHEELUP_STATUS;
  608: 			if (where == BORDER)
  609: 				key = KEYC_WHEELUP_BORDER;
  610: 		} else {
  611: 			if (where == PANE)
  612: 				key = KEYC_WHEELDOWN_PANE;
  613: 			if (where == STATUS)
  614: 				key = KEYC_WHEELDOWN_STATUS;
  615: 			if (where == BORDER)
  616: 				key = KEYC_WHEELDOWN_BORDER;
  617: 		}
  618: 		break;
  619: 	case UP:
  620: 		switch (MOUSE_BUTTONS(b)) {
  621: 		case 0:
  622: 			if (where == PANE)
  623: 				key = KEYC_MOUSEUP1_PANE;
  624: 			if (where == STATUS)
  625: 				key = KEYC_MOUSEUP1_STATUS;
  626: 			if (where == BORDER)
  627: 				key = KEYC_MOUSEUP1_BORDER;
  628: 			break;
  629: 		case 1:
  630: 			if (where == PANE)
  631: 				key = KEYC_MOUSEUP2_PANE;
  632: 			if (where == STATUS)
  633: 				key = KEYC_MOUSEUP2_STATUS;
  634: 			if (where == BORDER)
  635: 				key = KEYC_MOUSEUP2_BORDER;
  636: 			break;
  637: 		case 2:
  638: 			if (where == PANE)
  639: 				key = KEYC_MOUSEUP3_PANE;
  640: 			if (where == STATUS)
  641: 				key = KEYC_MOUSEUP3_STATUS;
  642: 			if (where == BORDER)
  643: 				key = KEYC_MOUSEUP3_BORDER;
  644: 			break;
  645: 		}
  646: 		break;
  647: 	case DOWN:
  648: 		switch (MOUSE_BUTTONS(b)) {
  649: 		case 0:
  650: 			if (where == PANE)
  651: 				key = KEYC_MOUSEDOWN1_PANE;
  652: 			if (where == STATUS)
  653: 				key = KEYC_MOUSEDOWN1_STATUS;
  654: 			if (where == BORDER)
  655: 				key = KEYC_MOUSEDOWN1_BORDER;
  656: 			break;
  657: 		case 1:
  658: 			if (where == PANE)
  659: 				key = KEYC_MOUSEDOWN2_PANE;
  660: 			if (where == STATUS)
  661: 				key = KEYC_MOUSEDOWN2_STATUS;
  662: 			if (where == BORDER)
  663: 				key = KEYC_MOUSEDOWN2_BORDER;
  664: 			break;
  665: 		case 2:
  666: 			if (where == PANE)
  667: 				key = KEYC_MOUSEDOWN3_PANE;
  668: 			if (where == STATUS)
  669: 				key = KEYC_MOUSEDOWN3_STATUS;
  670: 			if (where == BORDER)
  671: 				key = KEYC_MOUSEDOWN3_BORDER;
  672: 			break;
  673: 		}
  674: 		break;
  675: 	case DOUBLE:
  676: 		switch (MOUSE_BUTTONS(b)) {
  677: 		case 0:
  678: 			if (where == PANE)
  679: 				key = KEYC_DOUBLECLICK1_PANE;
  680: 			if (where == STATUS)
  681: 				key = KEYC_DOUBLECLICK1_STATUS;
  682: 			if (where == BORDER)
  683: 				key = KEYC_DOUBLECLICK1_BORDER;
  684: 			break;
  685: 		case 1:
  686: 			if (where == PANE)
  687: 				key = KEYC_DOUBLECLICK2_PANE;
  688: 			if (where == STATUS)
  689: 				key = KEYC_DOUBLECLICK2_STATUS;
  690: 			if (where == BORDER)
  691: 				key = KEYC_DOUBLECLICK2_BORDER;
  692: 			break;
  693: 		case 2:
  694: 			if (where == PANE)
  695: 				key = KEYC_DOUBLECLICK3_PANE;
  696: 			if (where == STATUS)
  697: 				key = KEYC_DOUBLECLICK3_STATUS;
  698: 			if (where == BORDER)
  699: 				key = KEYC_DOUBLECLICK3_BORDER;
  700: 			break;
  701: 		}
  702: 		break;
  703: 	case TRIPLE:
  704: 		switch (MOUSE_BUTTONS(b)) {
  705: 		case 0:
  706: 			if (where == PANE)
  707: 				key = KEYC_TRIPLECLICK1_PANE;
  708: 			if (where == STATUS)
  709: 				key = KEYC_TRIPLECLICK1_STATUS;
  710: 			if (where == BORDER)
  711: 				key = KEYC_TRIPLECLICK1_BORDER;
  712: 			break;
  713: 		case 1:
  714: 			if (where == PANE)
  715: 				key = KEYC_TRIPLECLICK2_PANE;
  716: 			if (where == STATUS)
  717: 				key = KEYC_TRIPLECLICK2_STATUS;
  718: 			if (where == BORDER)
  719: 				key = KEYC_TRIPLECLICK2_BORDER;
  720: 			break;
  721: 		case 2:
  722: 			if (where == PANE)
  723: 				key = KEYC_TRIPLECLICK3_PANE;
  724: 			if (where == STATUS)
  725: 				key = KEYC_TRIPLECLICK3_STATUS;
  726: 			if (where == BORDER)
  727: 				key = KEYC_TRIPLECLICK3_BORDER;
  728: 			break;
  729: 		}
  730: 		break;
  731: 	}
  732: 	if (key == KEYC_UNKNOWN)
  733: 		return (KEYC_UNKNOWN);
  734: 
  735: 	/* Apply modifiers if any. */
  736: 	if (b & MOUSE_MASK_META)
  737: 		key |= KEYC_ESCAPE;
  738: 	if (b & MOUSE_MASK_CTRL)
  739: 		key |= KEYC_CTRL;
  740: 	if (b & MOUSE_MASK_SHIFT)
  741: 		key |= KEYC_SHIFT;
  742: 
  743: 	return (key);
  744: }
  745: 
  746: /* Is this fast enough to probably be a paste? */
  747: static int
  748: server_client_assume_paste(struct session *s)
  749: {
  750: 	struct timeval	tv;
  751: 	int		t;
  752: 
  753: 	if ((t = options_get_number(s->options, "assume-paste-time")) == 0)
  754: 		return (0);
  755: 
  756: 	timersub(&s->activity_time, &s->last_activity_time, &tv);
  757: 	if (tv.tv_sec == 0 && tv.tv_usec < t * 1000) {
  758: 		log_debug("session %s pasting (flag %d)", s->name,
  759: 		    !!(s->flags & SESSION_PASTING));
  760: 		if (s->flags & SESSION_PASTING)
  761: 			return (1);
  762: 		s->flags |= SESSION_PASTING;
  763: 		return (0);
  764: 	}
  765: 	log_debug("session %s not pasting", s->name);
  766: 	s->flags &= ~SESSION_PASTING;
  767: 	return (0);
  768: }
  769: 
  770: /* Handle data key input from client. */
  771: void
  772: server_client_handle_key(struct client *c, key_code key)
  773: {
  774: 	struct mouse_event	*m = &c->tty.mouse;
  775: 	struct session		*s = c->session;
  776: 	struct window		*w;
  777: 	struct window_pane	*wp;
  778: 	struct timeval		 tv;
  779: 	const char		*name;
  780: 	struct key_table	*table;
  781: 	struct key_binding	 bd_find, *bd;
  782: 	int			 xtimeout;
  783: 	struct cmd_find_state	 fs;
  784: 
  785: 	/* Check the client is good to accept input. */
  786: 	if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
  787: 		return;
  788: 	w = s->curw->window;
  789: 
  790: 	/* Update the activity timer. */
  791: 	if (gettimeofday(&c->activity_time, NULL) != 0)
  792: 		fatal("gettimeofday failed");
  793: 	session_update_activity(s, &c->activity_time);
  794: 
  795: 	/* Number keys jump to pane in identify mode. */
  796: 	if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
  797: 		if (c->flags & CLIENT_READONLY)
  798: 			return;
  799: 		window_unzoom(w);
  800: 		wp = window_pane_at_index(w, key - '0');
  801: 		if (wp != NULL && !window_pane_visible(wp))
  802: 			wp = NULL;
  803: 		server_client_clear_identify(c, wp);
  804: 		return;
  805: 	}
  806: 
  807: 	/* Handle status line. */
  808: 	if (!(c->flags & CLIENT_READONLY)) {
  809: 		status_message_clear(c);
  810: 		server_client_clear_identify(c, NULL);
  811: 	}
  812: 	if (c->prompt_string != NULL) {
  813: 		if (c->flags & CLIENT_READONLY)
  814: 			return;
  815: 		if (status_prompt_key(c, key) == 0)
  816: 			return;
  817: 	}
  818: 
  819: 	/* Check for mouse keys. */
  820: 	m->valid = 0;
  821: 	if (key == KEYC_MOUSE) {
  822: 		if (c->flags & CLIENT_READONLY)
  823: 			return;
  824: 		key = server_client_check_mouse(c);
  825: 		if (key == KEYC_UNKNOWN)
  826: 			return;
  827: 
  828: 		m->valid = 1;
  829: 		m->key = key;
  830: 
  831: 		/*
  832: 		 * Mouse drag is in progress, so fire the callback (now that
  833: 		 * the mouse event is valid).
  834: 		 */
  835: 		if (key == KEYC_DRAGGING) {
  836: 			c->tty.mouse_drag_update(c, m);
  837: 			return;
  838: 		}
  839: 	} else
  840: 		m->valid = 0;
  841: 
  842: 	/* Find affected pane. */
  843: 	if (KEYC_IS_MOUSE(key) && m->valid)
  844: 		wp = cmd_mouse_pane(m, NULL, NULL);
  845: 	else
  846: 		wp = w->active;
  847: 
  848: 	/* Forward mouse keys if disabled. */
  849: 	if (KEYC_IS_MOUSE(key) && !options_get_number(s->options, "mouse"))
  850: 		goto forward;
  851: 
  852: 	/* Treat everything as a regular key when pasting is detected. */
  853: 	if (!KEYC_IS_MOUSE(key) && server_client_assume_paste(s))
  854: 		goto forward;
  855: 
  856: retry:
  857: 	/*
  858: 	 * Work out the current key table. If the pane is in a mode, use
  859: 	 * the mode table instead of the default key table.
  860: 	 */
  861: 	name = NULL;
  862: 	if (wp != NULL && wp->mode != NULL && wp->mode->key_table != NULL)
  863: 		name = wp->mode->key_table(wp);
  864: 	if (name == NULL || !server_client_is_default_key_table(c))
  865: 		table = c->keytable;
  866: 	else
  867: 		table = key_bindings_get_table(name, 1);
  868: 	if (wp == NULL)
  869: 		log_debug("key table %s (no pane)", table->name);
  870: 	else
  871: 		log_debug("key table %s (pane %%%u)", table->name, wp->id);
  872: 
  873: 	/*
  874: 	 * The prefix always takes precedence and forces a switch to the prefix
  875: 	 * table, unless we are already there.
  876: 	 */
  877: 	if ((key == (key_code)options_get_number(s->options, "prefix") ||
  878: 	    key == (key_code)options_get_number(s->options, "prefix2")) &&
  879: 	    strcmp(table->name, "prefix") != 0) {
  880: 		server_client_set_key_table(c, "prefix");
  881: 		server_status_client(c);
  882: 		return;
  883: 	}
  884: 
  885: 	/* Try to see if there is a key binding in the current table. */
  886: 	bd_find.key = key;
  887: 	bd = RB_FIND(key_bindings, &table->key_bindings, &bd_find);
  888: 	if (bd != NULL) {
  889: 		/*
  890: 		 * Key was matched in this table. If currently repeating but a
  891: 		 * non-repeating binding was found, stop repeating and try
  892: 		 * again in the root table.
  893: 		 */
  894: 		if ((c->flags & CLIENT_REPEAT) && !bd->can_repeat) {
  895: 			server_client_set_key_table(c, NULL);
  896: 			c->flags &= ~CLIENT_REPEAT;
  897: 			server_status_client(c);
  898: 			goto retry;
  899: 		}
  900: 
  901: 		/*
  902: 		 * Take a reference to this table to make sure the key binding
  903: 		 * doesn't disappear.
  904: 		 */
  905: 		table->references++;
  906: 
  907: 		/*
  908: 		 * If this is a repeating key, start the timer. Otherwise reset
  909: 		 * the client back to the root table.
  910: 		 */
  911: 		xtimeout = options_get_number(s->options, "repeat-time");
  912: 		if (xtimeout != 0 && bd->can_repeat) {
  913: 			c->flags |= CLIENT_REPEAT;
  914: 
  915: 			tv.tv_sec = xtimeout / 1000;
  916: 			tv.tv_usec = (xtimeout % 1000) * 1000L;
  917: 			evtimer_del(&c->repeat_timer);
  918: 			evtimer_add(&c->repeat_timer, &tv);
  919: 		} else {
  920: 			c->flags &= ~CLIENT_REPEAT;
  921: 			server_client_set_key_table(c, NULL);
  922: 		}
  923: 		server_status_client(c);
  924: 
  925: 		/* Find default state if the pane is known. */
  926: 		cmd_find_clear_state(&fs, NULL, 0);
  927: 		if (wp != NULL) {
  928: 			fs.s = s;
  929: 			fs.wl = fs.s->curw;
  930: 			fs.w = fs.wl->window;
  931: 			fs.wp = wp;
  932: 			cmd_find_log_state(__func__, &fs);
  933: 
  934: 			if (!cmd_find_valid_state(&fs))
  935: 				fatalx("invalid key state");
  936: 		}
  937: 
  938: 		/* Dispatch the key binding. */
  939: 		key_bindings_dispatch(bd, c, m, &fs);
  940: 		key_bindings_unref_table(table);
  941: 		return;
  942: 	}
  943: 
  944: 	/*
  945: 	 * No match in this table. If repeating, switch the client back to the
  946: 	 * root table and try again.
  947: 	 */
  948: 	if (c->flags & CLIENT_REPEAT) {
  949: 		server_client_set_key_table(c, NULL);
  950: 		c->flags &= ~CLIENT_REPEAT;
  951: 		server_status_client(c);
  952: 		goto retry;
  953: 	}
  954: 
  955: 	/* If no match and we're not in the root table, that's it. */
  956: 	if (name == NULL && !server_client_is_default_key_table(c)) {
  957: 		log_debug("no key in key table %s", table->name);
  958: 		server_client_set_key_table(c, NULL);
  959: 		server_status_client(c);
  960: 		return;
  961: 	}
  962: 
  963: forward:
  964: 	if (c->flags & CLIENT_READONLY)
  965: 		return;
  966: 	if (wp != NULL)
  967: 		window_pane_key(wp, c, s, key, m);
  968: }
  969: 
  970: /* Client functions that need to happen every loop. */
  971: void
  972: server_client_loop(void)
  973: {
  974: 	struct client		*c;
  975: 	struct window		*w;
  976: 	struct window_pane	*wp;
  977: 	int			 focus;
  978: 
  979: 	TAILQ_FOREACH(c, &clients, entry) {
  980: 		server_client_check_exit(c);
  981: 		if (c->session != NULL) {
  982: 			server_client_check_redraw(c);
  983: 			server_client_reset_state(c);
  984: 		}
  985: 	}
  986: 
  987: 	/*
  988: 	 * Any windows will have been redrawn as part of clients, so clear
  989: 	 * their flags now. Also check pane focus and resize.
  990: 	 */
  991: 	focus = options_get_number(global_options, "focus-events");
  992: 	RB_FOREACH(w, windows, &windows) {
  993: 		TAILQ_FOREACH(wp, &w->panes, entry) {
  994: 			if (wp->fd != -1) {
  995: 				if (focus)
  996: 					server_client_check_focus(wp);
  997: 				server_client_check_resize(wp);
  998: 			}
  999: 			wp->flags &= ~PANE_REDRAW;
 1000: 		}
 1001: 		check_window_name(w);
 1002: 	}
 1003: }
 1004: 
 1005: /* Resize timer event. */
 1006: static void
 1007: server_client_resize_event(__unused int fd, __unused short events, void *data)
 1008: {
 1009: 	struct window_pane	*wp = data;
 1010: 	struct winsize		 ws;
 1011: 
 1012: 	evtimer_del(&wp->resize_timer);
 1013: 
 1014: 	if (!(wp->flags & PANE_RESIZE))
 1015: 		return;
 1016: 
 1017: 	memset(&ws, 0, sizeof ws);
 1018: 	ws.ws_col = wp->sx;
 1019: 	ws.ws_row = wp->sy;
 1020: 
 1021: 	if (ioctl(wp->fd, TIOCSWINSZ, &ws) == -1) {
 1022: #ifdef __sun
 1023: 		/*
 1024: 		 * Some versions of Solaris apparently can return an error when
 1025: 		 * resizing; don't know why this happens, can't reproduce on
 1026: 		 * other platforms and ignoring it doesn't seem to cause any
 1027: 		 * issues.
 1028: 		 */
 1029: 		if (errno != EINVAL && errno != ENXIO)
 1030: #endif
 1031: 		fatal("ioctl failed");
 1032: 	}
 1033: 
 1034: 	wp->flags &= ~PANE_RESIZE;
 1035: }
 1036: 
 1037: /* Check if pane should be resized. */
 1038: static void
 1039: server_client_check_resize(struct window_pane *wp)
 1040: {
 1041: 	struct timeval	 tv = { .tv_usec = 250000 };
 1042: 
 1043: 	if (!(wp->flags & PANE_RESIZE))
 1044: 		return;
 1045: 
 1046: 	if (!event_initialized(&wp->resize_timer))
 1047: 		evtimer_set(&wp->resize_timer, server_client_resize_event, wp);
 1048: 
 1049: 	/*
 1050: 	 * The first resize should happen immediately, so if the timer is not
 1051: 	 * running, do it now.
 1052: 	 */
 1053: 	if (!evtimer_pending(&wp->resize_timer, NULL))
 1054: 		server_client_resize_event(-1, 0, wp);
 1055: 
 1056: 	/*
 1057: 	 * If the pane is in the alternate screen, let the timer expire and
 1058: 	 * resize to give the application a chance to redraw. If not, keep
 1059: 	 * pushing the timer back.
 1060: 	 */
 1061: 	if (wp->saved_grid != NULL && evtimer_pending(&wp->resize_timer, NULL))
 1062: 		return;
 1063: 	evtimer_del(&wp->resize_timer);
 1064: 	evtimer_add(&wp->resize_timer, &tv);
 1065: }
 1066: 
 1067: /* Check whether pane should be focused. */
 1068: static void
 1069: server_client_check_focus(struct window_pane *wp)
 1070: {
 1071: 	struct client	*c;
 1072: 	int		 push;
 1073: 
 1074: 	/* Do we need to push the focus state? */
 1075: 	push = wp->flags & PANE_FOCUSPUSH;
 1076: 	wp->flags &= ~PANE_FOCUSPUSH;
 1077: 
 1078: 	/* If we don't care about focus, forget it. */
 1079: 	if (!(wp->base.mode & MODE_FOCUSON))
 1080: 		return;
 1081: 
 1082: 	/* If we're not the active pane in our window, we're not focused. */
 1083: 	if (wp->window->active != wp)
 1084: 		goto not_focused;
 1085: 
 1086: 	/* If we're in a mode, we're not focused. */
 1087: 	if (wp->screen != &wp->base)
 1088: 		goto not_focused;
 1089: 
 1090: 	/*
 1091: 	 * If our window is the current window in any focused clients with an
 1092: 	 * attached session, we're focused.
 1093: 	 */
 1094: 	TAILQ_FOREACH(c, &clients, entry) {
 1095: 		if (c->session == NULL || !(c->flags & CLIENT_FOCUSED))
 1096: 			continue;
 1097: 		if (c->session->flags & SESSION_UNATTACHED)
 1098: 			continue;
 1099: 
 1100: 		if (c->session->curw->window == wp->window)
 1101: 			goto focused;
 1102: 	}
 1103: 
 1104: not_focused:
 1105: 	if (push || (wp->flags & PANE_FOCUSED))
 1106: 		bufferevent_write(wp->event, "\033[O", 3);
 1107: 	wp->flags &= ~PANE_FOCUSED;
 1108: 	return;
 1109: 
 1110: focused:
 1111: 	if (push || !(wp->flags & PANE_FOCUSED))
 1112: 		bufferevent_write(wp->event, "\033[I", 3);
 1113: 	wp->flags |= PANE_FOCUSED;
 1114: }
 1115: 
 1116: /*
 1117:  * Update cursor position and mode settings. The scroll region and attributes
 1118:  * are cleared when idle (waiting for an event) as this is the most likely time
 1119:  * a user may interrupt tmux, for example with ~^Z in ssh(1). This is a
 1120:  * compromise between excessive resets and likelihood of an interrupt.
 1121:  *
 1122:  * tty_region/tty_reset/tty_update_mode already take care of not resetting
 1123:  * things that are already in their default state.
 1124:  */
 1125: static void
 1126: server_client_reset_state(struct client *c)
 1127: {
 1128: 	struct window		*w = c->session->curw->window;
 1129: 	struct window_pane	*wp = w->active, *loop;
 1130: 	struct screen		*s = wp->screen;
 1131: 	struct options		*oo = c->session->options;
 1132: 	int			 status, mode, o;
 1133: 
 1134: 	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
 1135: 		return;
 1136: 
 1137: 	tty_region_off(&c->tty);
 1138: 	tty_margin_off(&c->tty);
 1139: 
 1140: 	status = options_get_number(oo, "status");
 1141: 	if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - status)
 1142: 		tty_cursor(&c->tty, 0, 0);
 1143: 	else {
 1144: 		o = status && options_get_number(oo, "status-position") == 0;
 1145: 		tty_cursor(&c->tty, wp->xoff + s->cx, o + wp->yoff + s->cy);
 1146: 	}
 1147: 
 1148: 	/*
 1149: 	 * Set mouse mode if requested. To support dragging, always use button
 1150: 	 * mode.
 1151: 	 */
 1152: 	mode = s->mode;
 1153: 	if (options_get_number(oo, "mouse")) {
 1154: 		mode &= ~ALL_MOUSE_MODES;
 1155: 		TAILQ_FOREACH(loop, &w->panes, entry) {
 1156: 			if (loop->screen->mode & MODE_MOUSE_ALL)
 1157: 				mode |= MODE_MOUSE_ALL;
 1158: 		}
 1159: 		if (~mode & MODE_MOUSE_ALL)
 1160: 			mode |= MODE_MOUSE_BUTTON;
 1161: 	}
 1162: 
 1163: 	/* Clear bracketed paste mode if at the prompt. */
 1164: 	if (c->prompt_string != NULL)
 1165: 		mode &= ~MODE_BRACKETPASTE;
 1166: 
 1167: 	/* Set the terminal mode and reset attributes. */
 1168: 	tty_update_mode(&c->tty, mode, s);
 1169: 	tty_reset(&c->tty);
 1170: }
 1171: 
 1172: /* Repeat time callback. */
 1173: static void
 1174: server_client_repeat_timer(__unused int fd, __unused short events, void *data)
 1175: {
 1176: 	struct client	*c = data;
 1177: 
 1178: 	if (c->flags & CLIENT_REPEAT) {
 1179: 		server_client_set_key_table(c, NULL);
 1180: 		c->flags &= ~CLIENT_REPEAT;
 1181: 		server_status_client(c);
 1182: 	}
 1183: }
 1184: 
 1185: /* Double-click callback. */
 1186: static void
 1187: server_client_click_timer(__unused int fd, __unused short events, void *data)
 1188: {
 1189: 	struct client	*c = data;
 1190: 
 1191: 	c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK);
 1192: }
 1193: 
 1194: /* Check if client should be exited. */
 1195: static void
 1196: server_client_check_exit(struct client *c)
 1197: {
 1198: 	if (!(c->flags & CLIENT_EXIT))
 1199: 		return;
 1200: 
 1201: 	if (EVBUFFER_LENGTH(c->stdin_data) != 0)
 1202: 		return;
 1203: 	if (EVBUFFER_LENGTH(c->stdout_data) != 0)
 1204: 		return;
 1205: 	if (EVBUFFER_LENGTH(c->stderr_data) != 0)
 1206: 		return;
 1207: 
 1208: 	proc_send(c->peer, MSG_EXIT, -1, &c->retval, sizeof c->retval);
 1209: 	c->flags &= ~CLIENT_EXIT;
 1210: }
 1211: 
 1212: /* Check for client redraws. */
 1213: static void
 1214: server_client_check_redraw(struct client *c)
 1215: {
 1216: 	struct session		*s = c->session;
 1217: 	struct tty		*tty = &c->tty;
 1218: 	struct window_pane	*wp;
 1219: 	int		 	 flags, masked;
 1220: 
 1221: 	if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
 1222: 		return;
 1223: 
 1224: 	if (c->flags & (CLIENT_REDRAW|CLIENT_STATUS)) {
 1225: 		if (options_get_number(s->options, "set-titles"))
 1226: 			server_client_set_title(c);
 1227: 		screen_redraw_update(c); /* will adjust flags */
 1228: 	}
 1229: 
 1230: 	flags = tty->flags & (TTY_FREEZE|TTY_NOCURSOR);
 1231: 	tty->flags = (tty->flags & ~TTY_FREEZE) | TTY_NOCURSOR;
 1232: 
 1233: 	if (c->flags & CLIENT_REDRAW) {
 1234: 		tty_update_mode(tty, tty->mode, NULL);
 1235: 		screen_redraw_screen(c, 1, 1, 1);
 1236: 		c->flags &= ~(CLIENT_STATUS|CLIENT_BORDERS);
 1237: 	} else {
 1238: 		TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) {
 1239: 			if (wp->flags & PANE_REDRAW) {
 1240: 				tty_update_mode(tty, tty->mode, NULL);
 1241: 				screen_redraw_pane(c, wp);
 1242: 			}
 1243: 		}
 1244: 	}
 1245: 
 1246: 	masked = c->flags & (CLIENT_BORDERS|CLIENT_STATUS);
 1247: 	if (masked != 0)
 1248: 		tty_update_mode(tty, tty->mode, NULL);
 1249: 	if (masked == CLIENT_BORDERS)
 1250: 		screen_redraw_screen(c, 0, 0, 1);
 1251: 	else if (masked == CLIENT_STATUS)
 1252: 		screen_redraw_screen(c, 0, 1, 0);
 1253: 	else if (masked != 0)
 1254: 		screen_redraw_screen(c, 0, 1, 1);
 1255: 
 1256: 	tty->flags = (tty->flags & ~(TTY_FREEZE|TTY_NOCURSOR)) | flags;
 1257: 	tty_update_mode(tty, tty->mode, NULL);
 1258: 
 1259: 	c->flags &= ~(CLIENT_REDRAW|CLIENT_BORDERS|CLIENT_STATUS|
 1260: 	    CLIENT_STATUSFORCE);
 1261: }
 1262: 
 1263: /* Set client title. */
 1264: static void
 1265: server_client_set_title(struct client *c)
 1266: {
 1267: 	struct session		*s = c->session;
 1268: 	const char		*template;
 1269: 	char			*title;
 1270: 	struct format_tree	*ft;
 1271: 
 1272: 	template = options_get_string(s->options, "set-titles-string");
 1273: 
 1274: 	ft = format_create(NULL, FORMAT_NONE, 0);
 1275: 	format_defaults(ft, c, NULL, NULL, NULL);
 1276: 
 1277: 	title = format_expand_time(ft, template, time(NULL));
 1278: 	if (c->title == NULL || strcmp(title, c->title) != 0) {
 1279: 		free(c->title);
 1280: 		c->title = xstrdup(title);
 1281: 		tty_set_title(&c->tty, c->title);
 1282: 	}
 1283: 	free(title);
 1284: 
 1285: 	format_free(ft);
 1286: }
 1287: 
 1288: /* Dispatch message from client. */
 1289: static void
 1290: server_client_dispatch(struct imsg *imsg, void *arg)
 1291: {
 1292: 	struct client		*c = arg;
 1293: 	struct msg_stdin_data	 stdindata;
 1294: 	const char		*data;
 1295: 	ssize_t			 datalen;
 1296: 	struct session		*s;
 1297: 
 1298: 	if (c->flags & CLIENT_DEAD)
 1299: 		return;
 1300: 
 1301: 	if (imsg == NULL) {
 1302: 		server_client_lost(c);
 1303: 		return;
 1304: 	}
 1305: 
 1306: 	data = imsg->data;
 1307: 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 1308: 
 1309: 	switch (imsg->hdr.type) {
 1310: 	case MSG_IDENTIFY_FLAGS:
 1311: 	case MSG_IDENTIFY_TERM:
 1312: 	case MSG_IDENTIFY_TTYNAME:
 1313: 	case MSG_IDENTIFY_CWD:
 1314: 	case MSG_IDENTIFY_STDIN:
 1315: 	case MSG_IDENTIFY_ENVIRON:
 1316: 	case MSG_IDENTIFY_CLIENTPID:
 1317: 	case MSG_IDENTIFY_DONE:
 1318: 		server_client_dispatch_identify(c, imsg);
 1319: 		break;
 1320: 	case MSG_COMMAND:
 1321: 		server_client_dispatch_command(c, imsg);
 1322: 		break;
 1323: 	case MSG_STDIN:
 1324: 		if (datalen != sizeof stdindata)
 1325: 			fatalx("bad MSG_STDIN size");
 1326: 		memcpy(&stdindata, data, sizeof stdindata);
 1327: 
 1328: 		if (c->stdin_callback == NULL)
 1329: 			break;
 1330: 		if (stdindata.size <= 0)
 1331: 			c->stdin_closed = 1;
 1332: 		else {
 1333: 			evbuffer_add(c->stdin_data, stdindata.data,
 1334: 			    stdindata.size);
 1335: 		}
 1336: 		c->stdin_callback(c, c->stdin_closed,
 1337: 		    c->stdin_callback_data);
 1338: 		break;
 1339: 	case MSG_RESIZE:
 1340: 		if (datalen != 0)
 1341: 			fatalx("bad MSG_RESIZE size");
 1342: 
 1343: 		if (c->flags & CLIENT_CONTROL)
 1344: 			break;
 1345: 		if (tty_resize(&c->tty)) {
 1346: 			recalculate_sizes();
 1347: 			server_redraw_client(c);
 1348: 		}
 1349: 		if (c->session != NULL)
 1350: 			notify_client("client-resized", c);
 1351: 		break;
 1352: 	case MSG_EXITING:
 1353: 		if (datalen != 0)
 1354: 			fatalx("bad MSG_EXITING size");
 1355: 
 1356: 		c->session = NULL;
 1357: 		tty_close(&c->tty);
 1358: 		proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
 1359: 		break;
 1360: 	case MSG_WAKEUP:
 1361: 	case MSG_UNLOCK:
 1362: 		if (datalen != 0)
 1363: 			fatalx("bad MSG_WAKEUP size");
 1364: 
 1365: 		if (!(c->flags & CLIENT_SUSPENDED))
 1366: 			break;
 1367: 		c->flags &= ~CLIENT_SUSPENDED;
 1368: 
 1369: 		if (c->tty.fd == -1) /* exited in the meantime */
 1370: 			break;
 1371: 		s = c->session;
 1372: 
 1373: 		if (gettimeofday(&c->activity_time, NULL) != 0)
 1374: 			fatal("gettimeofday failed");
 1375: 
 1376: 		tty_start_tty(&c->tty);
 1377: 		server_redraw_client(c);
 1378: 		recalculate_sizes();
 1379: 
 1380: 		if (s != NULL)
 1381: 			session_update_activity(s, &c->activity_time);
 1382: 		break;
 1383: 	case MSG_SHELL:
 1384: 		if (datalen != 0)
 1385: 			fatalx("bad MSG_SHELL size");
 1386: 
 1387: 		server_client_dispatch_shell(c);
 1388: 		break;
 1389: 	}
 1390: }
 1391: 
 1392: /* Callback when command is done. */
 1393: static enum cmd_retval
 1394: server_client_command_done(struct cmdq_item *item, __unused void *data)
 1395: {
 1396: 	struct client	*c = item->client;
 1397: 
 1398: 	if (~c->flags & CLIENT_ATTACHED)
 1399: 		c->flags |= CLIENT_EXIT;
 1400: 	return (CMD_RETURN_NORMAL);
 1401: }
 1402: 
 1403: /* Show an error message. */
 1404: static enum cmd_retval
 1405: server_client_command_error(struct cmdq_item *item, void *data)
 1406: {
 1407: 	char	*error = data;
 1408: 
 1409: 	cmdq_error(item, "%s", error);
 1410: 	free(error);
 1411: 
 1412: 	return (CMD_RETURN_NORMAL);
 1413: }
 1414: 
 1415: /* Handle command message. */
 1416: static void
 1417: server_client_dispatch_command(struct client *c, struct imsg *imsg)
 1418: {
 1419: 	struct msg_command_data	  data;
 1420: 	char			 *buf;
 1421: 	size_t			  len;
 1422: 	struct cmd_list		 *cmdlist = NULL;
 1423: 	int			  argc;
 1424: 	char			**argv, *cause;
 1425: 
 1426: 	if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data)
 1427: 		fatalx("bad MSG_COMMAND size");
 1428: 	memcpy(&data, imsg->data, sizeof data);
 1429: 
 1430: 	buf = (char *)imsg->data + sizeof data;
 1431: 	len = imsg->hdr.len  - IMSG_HEADER_SIZE - sizeof data;
 1432: 	if (len > 0 && buf[len - 1] != '\0')
 1433: 		fatalx("bad MSG_COMMAND string");
 1434: 
 1435: 	argc = data.argc;
 1436: 	if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
 1437: 		cause = xstrdup("command too long");
 1438: 		goto error;
 1439: 	}
 1440: 
 1441: 	if (argc == 0) {
 1442: 		argc = 1;
 1443: 		argv = xcalloc(1, sizeof *argv);
 1444: 		*argv = xstrdup("new-session");
 1445: 	}
 1446: 
 1447: 	if ((cmdlist = cmd_list_parse(argc, argv, NULL, 0, &cause)) == NULL) {
 1448: 		cmd_free_argv(argc, argv);
 1449: 		goto error;
 1450: 	}
 1451: 	cmd_free_argv(argc, argv);
 1452: 
 1453: 	cmdq_append(c, cmdq_get_command(cmdlist, NULL, NULL, 0));
 1454: 	cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
 1455: 	cmd_list_free(cmdlist);
 1456: 	return;
 1457: 
 1458: error:
 1459: 	cmdq_append(c, cmdq_get_callback(server_client_command_error, cause));
 1460: 
 1461: 	if (cmdlist != NULL)
 1462: 		cmd_list_free(cmdlist);
 1463: 
 1464: 	c->flags |= CLIENT_EXIT;
 1465: }
 1466: 
 1467: /* Handle identify message. */
 1468: static void
 1469: server_client_dispatch_identify(struct client *c, struct imsg *imsg)
 1470: {
 1471: 	const char	*data, *home;
 1472: 	size_t	 	 datalen;
 1473: 	int		 flags;
 1474: 	char		*name;
 1475: 
 1476: 	if (c->flags & CLIENT_IDENTIFIED)
 1477: 		fatalx("out-of-order identify message");
 1478: 
 1479: 	data = imsg->data;
 1480: 	datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
 1481: 
 1482: 	switch (imsg->hdr.type)	{
 1483: 	case MSG_IDENTIFY_FLAGS:
 1484: 		if (datalen != sizeof flags)
 1485: 			fatalx("bad MSG_IDENTIFY_FLAGS size");
 1486: 		memcpy(&flags, data, sizeof flags);
 1487: 		c->flags |= flags;
 1488: 		log_debug("client %p IDENTIFY_FLAGS %#x", c, flags);
 1489: 		break;
 1490: 	case MSG_IDENTIFY_TERM:
 1491: 		if (datalen == 0 || data[datalen - 1] != '\0')
 1492: 			fatalx("bad MSG_IDENTIFY_TERM string");
 1493: 		c->term = xstrdup(data);
 1494: 		log_debug("client %p IDENTIFY_TERM %s", c, data);
 1495: 		break;
 1496: 	case MSG_IDENTIFY_TTYNAME:
 1497: 		if (datalen == 0 || data[datalen - 1] != '\0')
 1498: 			fatalx("bad MSG_IDENTIFY_TTYNAME string");
 1499: 		c->ttyname = xstrdup(data);
 1500: 		log_debug("client %p IDENTIFY_TTYNAME %s", c, data);
 1501: 		break;
 1502: 	case MSG_IDENTIFY_CWD:
 1503: 		if (datalen == 0 || data[datalen - 1] != '\0')
 1504: 			fatalx("bad MSG_IDENTIFY_CWD string");
 1505: 		if (access(data, X_OK) == 0)
 1506: 			c->cwd = xstrdup(data);
 1507: 		else if ((home = find_home()) != NULL)
 1508: 			c->cwd = xstrdup(home);
 1509: 		else
 1510: 			c->cwd = xstrdup("/");
 1511: 		log_debug("client %p IDENTIFY_CWD %s", c, data);
 1512: 		break;
 1513: 	case MSG_IDENTIFY_STDIN:
 1514: 		if (datalen != 0)
 1515: 			fatalx("bad MSG_IDENTIFY_STDIN size");
 1516: 		c->fd = imsg->fd;
 1517: 		log_debug("client %p IDENTIFY_STDIN %d", c, imsg->fd);
 1518: 		break;
 1519: 	case MSG_IDENTIFY_ENVIRON:
 1520: 		if (datalen == 0 || data[datalen - 1] != '\0')
 1521: 			fatalx("bad MSG_IDENTIFY_ENVIRON string");
 1522: 		if (strchr(data, '=') != NULL)
 1523: 			environ_put(c->environ, data);
 1524: 		log_debug("client %p IDENTIFY_ENVIRON %s", c, data);
 1525: 		break;
 1526: 	case MSG_IDENTIFY_CLIENTPID:
 1527: 		if (datalen != sizeof c->pid)
 1528: 			fatalx("bad MSG_IDENTIFY_CLIENTPID size");
 1529: 		memcpy(&c->pid, data, sizeof c->pid);
 1530: 		log_debug("client %p IDENTIFY_CLIENTPID %ld", c, (long)c->pid);
 1531: 		break;
 1532: 	default:
 1533: 		break;
 1534: 	}
 1535: 
 1536: 	if (imsg->hdr.type != MSG_IDENTIFY_DONE)
 1537: 		return;
 1538: 	c->flags |= CLIENT_IDENTIFIED;
 1539: 
 1540: 	if (*c->ttyname != '\0')
 1541: 		name = xstrdup(c->ttyname);
 1542: 	else
 1543: 		xasprintf(&name, "client-%ld", (long)c->pid);
 1544: 	c->name = name;
 1545: 	log_debug("client %p name is %s", c, c->name);
 1546: 
 1547: #ifdef __CYGWIN__
 1548: 	c->fd = open(c->ttyname, O_RDWR|O_NOCTTY);
 1549: #endif
 1550: 
 1551: 	if (c->flags & CLIENT_CONTROL) {
 1552: 		c->stdin_callback = control_callback;
 1553: 
 1554: 		evbuffer_free(c->stderr_data);
 1555: 		c->stderr_data = c->stdout_data;
 1556: 
 1557: 		if (c->flags & CLIENT_CONTROLCONTROL)
 1558: 			evbuffer_add_printf(c->stdout_data, "\033P1000p");
 1559: 		proc_send(c->peer, MSG_STDIN, -1, NULL, 0);
 1560: 
 1561: 		c->tty.fd = -1;
 1562: 
 1563: 		close(c->fd);
 1564: 		c->fd = -1;
 1565: 
 1566: 		return;
 1567: 	}
 1568: 
 1569: 	if (c->fd == -1)
 1570: 		return;
 1571: 	if (tty_init(&c->tty, c, c->fd, c->term) != 0) {
 1572: 		close(c->fd);
 1573: 		c->fd = -1;
 1574: 		return;
 1575: 	}
 1576: 	if (c->flags & CLIENT_UTF8)
 1577: 		c->tty.flags |= TTY_UTF8;
 1578: 	if (c->flags & CLIENT_256COLOURS)
 1579: 		c->tty.term_flags |= TERM_256COLOURS;
 1580: 
 1581: 	tty_resize(&c->tty);
 1582: 
 1583: 	if (!(c->flags & CLIENT_CONTROL))
 1584: 		c->flags |= CLIENT_TERMINAL;
 1585: }
 1586: 
 1587: /* Handle shell message. */
 1588: static void
 1589: server_client_dispatch_shell(struct client *c)
 1590: {
 1591: 	const char	*shell;
 1592: 
 1593: 	shell = options_get_string(global_s_options, "default-shell");
 1594: 	if (*shell == '\0' || areshell(shell))
 1595: 		shell = _PATH_BSHELL;
 1596: 	proc_send_s(c->peer, MSG_SHELL, shell);
 1597: 
 1598: 	proc_kill_peer(c->peer);
 1599: }
 1600: 
 1601: /* Event callback to push more stdout data if any left. */
 1602: static void
 1603: server_client_stdout_cb(__unused int fd, __unused short events, void *arg)
 1604: {
 1605: 	struct client	*c = arg;
 1606: 
 1607: 	if (~c->flags & CLIENT_DEAD)
 1608: 		server_client_push_stdout(c);
 1609: 	server_client_unref(c);
 1610: }
 1611: 
 1612: /* Push stdout to client if possible. */
 1613: void
 1614: server_client_push_stdout(struct client *c)
 1615: {
 1616: 	struct msg_stdout_data data;
 1617: 	size_t                 sent, left;
 1618: 
 1619: 	left = EVBUFFER_LENGTH(c->stdout_data);
 1620: 	while (left != 0) {
 1621: 		sent = left;
 1622: 		if (sent > sizeof data.data)
 1623: 			sent = sizeof data.data;
 1624: 		memcpy(data.data, EVBUFFER_DATA(c->stdout_data), sent);
 1625: 		data.size = sent;
 1626: 
 1627: 		if (proc_send(c->peer, MSG_STDOUT, -1, &data, sizeof data) != 0)
 1628: 			break;
 1629: 		evbuffer_drain(c->stdout_data, sent);
 1630: 
 1631: 		left = EVBUFFER_LENGTH(c->stdout_data);
 1632: 		log_debug("%s: client %p, sent %zu, left %zu", __func__, c,
 1633: 		    sent, left);
 1634: 	}
 1635: 	if (left != 0) {
 1636: 		c->references++;
 1637: 		event_once(-1, EV_TIMEOUT, server_client_stdout_cb, c, NULL);
 1638: 		log_debug("%s: client %p, queued", __func__, c);
 1639: 	}
 1640: }
 1641: 
 1642: /* Event callback to push more stderr data if any left. */
 1643: static void
 1644: server_client_stderr_cb(__unused int fd, __unused short events, void *arg)
 1645: {
 1646: 	struct client	*c = arg;
 1647: 
 1648: 	if (~c->flags & CLIENT_DEAD)
 1649: 		server_client_push_stderr(c);
 1650: 	server_client_unref(c);
 1651: }
 1652: 
 1653: /* Push stderr to client if possible. */
 1654: void
 1655: server_client_push_stderr(struct client *c)
 1656: {
 1657: 	struct msg_stderr_data data;
 1658: 	size_t                 sent, left;
 1659: 
 1660: 	if (c->stderr_data == c->stdout_data) {
 1661: 		server_client_push_stdout(c);
 1662: 		return;
 1663: 	}
 1664: 
 1665: 	left = EVBUFFER_LENGTH(c->stderr_data);
 1666: 	while (left != 0) {
 1667: 		sent = left;
 1668: 		if (sent > sizeof data.data)
 1669: 			sent = sizeof data.data;
 1670: 		memcpy(data.data, EVBUFFER_DATA(c->stderr_data), sent);
 1671: 		data.size = sent;
 1672: 
 1673: 		if (proc_send(c->peer, MSG_STDERR, -1, &data, sizeof data) != 0)
 1674: 			break;
 1675: 		evbuffer_drain(c->stderr_data, sent);
 1676: 
 1677: 		left = EVBUFFER_LENGTH(c->stderr_data);
 1678: 		log_debug("%s: client %p, sent %zu, left %zu", __func__, c,
 1679: 		    sent, left);
 1680: 	}
 1681: 	if (left != 0) {
 1682: 		c->references++;
 1683: 		event_once(-1, EV_TIMEOUT, server_client_stderr_cb, c, NULL);
 1684: 		log_debug("%s: client %p, queued", __func__, c);
 1685: 	}
 1686: }
 1687: 
 1688: /* Add to client message log. */
 1689: void
 1690: server_client_add_message(struct client *c, const char *fmt, ...)
 1691: {
 1692: 	struct message_entry	*msg, *msg1;
 1693: 	char			*s;
 1694: 	va_list			 ap;
 1695: 	u_int			 limit;
 1696: 
 1697: 	va_start(ap, fmt);
 1698: 	xvasprintf(&s, fmt, ap);
 1699: 	va_end(ap);
 1700: 
 1701: 	log_debug("message %s (client %p)", s, c);
 1702: 
 1703: 	msg = xcalloc(1, sizeof *msg);
 1704: 	msg->msg_time = time(NULL);
 1705: 	msg->msg_num = c->message_next++;
 1706: 	msg->msg = s;
 1707: 	TAILQ_INSERT_TAIL(&c->message_log, msg, entry);
 1708: 
 1709: 	limit = options_get_number(global_options, "message-limit");
 1710: 	TAILQ_FOREACH_SAFE(msg, &c->message_log, entry, msg1) {
 1711: 		if (msg->msg_num + limit >= c->message_next)
 1712: 			break;
 1713: 		free(msg->msg);
 1714: 		TAILQ_REMOVE(&c->message_log, msg, entry);
 1715: 		free(msg);
 1716: 	}
 1717: }
 1718: 
 1719: /* Get client working directory. */
 1720: const char *
 1721: server_client_get_cwd(struct client *c)
 1722: {
 1723: 	struct session	*s;
 1724: 
 1725: 	if (c != NULL && c->session == NULL && c->cwd != NULL)
 1726: 		return (c->cwd);
 1727: 	if (c != NULL && (s = c->session) != NULL && s->cwd != NULL)
 1728: 		return (s->cwd);
 1729: 	return (".");
 1730: }
 1731: 
 1732: /* Resolve an absolute path or relative to client working directory. */
 1733: char *
 1734: server_client_get_path(struct client *c, const char *file)
 1735: {
 1736: 	char	*path, resolved[PATH_MAX];
 1737: 
 1738: 	if (*file == '/')
 1739: 		path = xstrdup(file);
 1740: 	else
 1741: 		xasprintf(&path, "%s/%s", server_client_get_cwd(c), file);
 1742: 	if (realpath(path, resolved) == NULL)
 1743: 		return (path);
 1744: 	free(path);
 1745: 	return (xstrdup(resolved));
 1746: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>