=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/control.c,v retrieving revision 1.33 retrieving revision 1.34 diff -c -r1.33 -r1.34 *** src/usr.bin/tmux/control.c 2020/05/24 09:40:17 1.33 --- src/usr.bin/tmux/control.c 2020/05/26 08:41:47 1.34 *************** *** 1,4 **** ! /* $OpenBSD: control.c,v 1.33 2020/05/24 09:40:17 nicm Exp $ */ /* * Copyright (c) 2012 Nicholas Marriott --- 1,4 ---- ! /* $OpenBSD: control.c,v 1.34 2020/05/26 08:41:47 nicm Exp $ */ /* * Copyright (c) 2012 Nicholas Marriott *************** *** 23,32 **** #include #include #include #include "tmux.h" ! /* Control offsets. */ struct control_offset { u_int pane; --- 23,33 ---- #include #include #include + #include #include "tmux.h" ! /* Control client offset. */ struct control_offset { u_int pane; *************** *** 34,46 **** int flags; #define CONTROL_OFFSET_OFF 0x1 ! RB_ENTRY(control_offset) entry; }; RB_HEAD(control_offsets, control_offset); ! /* Control state. */ struct control_state { ! struct control_offsets offsets; }; /* Compare client offsets. */ --- 35,50 ---- int flags; #define CONTROL_OFFSET_OFF 0x1 ! RB_ENTRY(control_offset) entry; }; RB_HEAD(control_offsets, control_offset); ! /* Control client state. */ struct control_state { ! struct control_offsets offsets; ! ! struct bufferevent *read_event; ! struct bufferevent *write_event; }; /* Compare client offsets. */ *************** *** 146,163 **** void control_write(struct client *c, const char *fmt, ...) { ! va_list ap; va_start(ap, fmt); ! file_vprint(c, fmt, ap); ! file_print(c, "\n"); va_end(ap); } /* Write output from a pane. */ void control_write_output(struct client *c, struct window_pane *wp) { struct control_offset *co; struct evbuffer *message; u_char *new_data; --- 150,173 ---- void control_write(struct client *c, const char *fmt, ...) { ! struct control_state *cs = c->control_state; ! va_list ap; ! char *s; va_start(ap, fmt); ! xvasprintf(&s, fmt, 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. */ void control_write_output(struct client *c, struct window_pane *wp) { + struct control_state *cs = c->control_state; struct control_offset *co; struct evbuffer *message; u_char *new_data; *************** *** 165,175 **** if (c->flags & CLIENT_CONTROL_NOOUTPUT) 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) return; --- 175,180 ---- *************** *** 193,207 **** else evbuffer_add_printf(message, "%c", new_data[i]); } ! evbuffer_add(message, "", 1); ! control_write(c, "%s", EVBUFFER_DATA(message)); evbuffer_free(message); window_pane_update_used_data(wp, &co->offset, new_size, 1); } ! /* Control error callback. */ static enum cmd_retval control_error(struct cmdq_item *item, void *data) { --- 198,212 ---- else evbuffer_add_printf(message, "%c", new_data[i]); } ! evbuffer_add(message, "\n", 1); ! bufferevent_write_buffer(cs->write_event, message); evbuffer_free(message); window_pane_update_used_data(wp, &co->offset, new_size, 1); } ! /* Control client error callback. */ static enum cmd_retval control_error(struct cmdq_item *item, void *data) { *************** *** 216,233 **** return (CMD_RETURN_NORMAL); } ! /* Control input callback. Read lines and fire commands. */ static void ! control_callback(__unused struct client *c, __unused const char *path, ! int read_error, int closed, struct evbuffer *buffer, __unused void *data) { char *line, *error; struct cmdq_state *state; enum cmd_parse_status status; - if (closed || read_error != 0) - c->flags |= CLIENT_EXIT; - for (;;) { line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF); if (line == NULL) --- 221,247 ---- return (CMD_RETURN_NORMAL); } ! /* Control client error callback. */ static void ! control_error_callback(__unused struct bufferevent *bufev, ! __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; struct cmdq_state *state; enum cmd_parse_status status; for (;;) { line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF); if (line == NULL) *************** *** 255,267 **** { 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. */ --- 269,298 ---- { 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); RB_INIT(&cs->offsets); ! 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) ! 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. */ *************** *** 269,274 **** --- 300,309 ---- control_stop(struct client *c) { 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); free(cs);