Annotation of src/usr.bin/tmux/control.c, Revision 1.31
1.31 ! nicm 1: /* $OpenBSD: control.c,v 1.30 2020/04/13 18:59:41 nicm Exp $ */
1.1 nicm 2:
3: /*
1.17 nicm 4: * Copyright (c) 2012 Nicholas Marriott <nicholas.marriott@gmail.com>
1.1 nicm 5: * Copyright (c) 2012 George Nachman <tmux@georgester.com>
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
16: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
17: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/types.h>
21:
22: #include <event.h>
1.2 nicm 23: #include <stdlib.h>
1.1 nicm 24: #include <string.h>
1.10 nicm 25: #include <time.h>
1.1 nicm 26:
27: #include "tmux.h"
28:
29: /* Write a line. */
1.13 nicm 30: void
1.1 nicm 31: control_write(struct client *c, const char *fmt, ...)
32: {
1.25 nicm 33: va_list ap;
1.1 nicm 34:
35: va_start(ap, fmt);
1.25 nicm 36: file_vprint(c, fmt, ap);
37: file_print(c, "\n");
1.1 nicm 38: va_end(ap);
1.31 ! nicm 39: }
! 40:
! 41: /* Write output from a pane. */
! 42: void
! 43: control_write_output(struct client *c, struct window_pane *wp)
! 44: {
! 45: struct client_offset *co;
! 46: struct evbuffer *message;
! 47: u_char *new_data;
! 48: size_t new_size, i;
! 49:
! 50: if (c->flags & CLIENT_CONTROL_NOOUTPUT)
! 51: return;
! 52:
! 53: /*
! 54: * Only write input if the window pane is linked to a window belonging
! 55: * to the client's session.
! 56: */
! 57: if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
! 58: return;
! 59:
! 60: co = server_client_add_pane_offset(c, wp);
! 61: if (co->flags & CLIENT_OFFSET_OFF) {
! 62: window_pane_update_used_data(wp, &co->offset, SIZE_MAX, 1);
! 63: return;
! 64: }
! 65: new_data = window_pane_get_new_data(wp, &co->offset, &new_size);
! 66: if (new_size == 0)
! 67: return;
! 68:
! 69: message = evbuffer_new();
! 70: if (message == NULL)
! 71: fatalx("out of memory");
! 72: evbuffer_add_printf(message, "%%output %%%u ", wp->id);
! 73:
! 74: for (i = 0; i < new_size; i++) {
! 75: if (new_data[i] < ' ' || new_data[i] == '\\')
! 76: evbuffer_add_printf(message, "\\%03o", new_data[i]);
! 77: else
! 78: evbuffer_add_printf(message, "%c", new_data[i]);
! 79: }
! 80: evbuffer_add(message, "", 1);
! 81:
! 82: control_write(c, "%s", EVBUFFER_DATA(message));
! 83: evbuffer_free(message);
! 84:
! 85: window_pane_update_used_data(wp, &co->offset, new_size, 1);
1.1 nicm 86: }
87:
1.18 nicm 88: /* Control error callback. */
89: static enum cmd_retval
1.19 nicm 90: control_error(struct cmdq_item *item, void *data)
1.18 nicm 91: {
1.26 nicm 92: struct client *c = cmdq_get_client(item);
1.18 nicm 93: char *error = data;
94:
1.19 nicm 95: cmdq_guard(item, "begin", 1);
1.18 nicm 96: control_write(c, "parse error: %s", error);
1.19 nicm 97: cmdq_guard(item, "error", 1);
1.18 nicm 98:
99: free(error);
100: return (CMD_RETURN_NORMAL);
101: }
102:
1.1 nicm 103: /* Control input callback. Read lines and fire commands. */
1.25 nicm 104: static void
105: control_callback(__unused struct client *c, __unused const char *path,
1.30 nicm 106: int read_error, int closed, struct evbuffer *buffer, __unused void *data)
1.1 nicm 107: {
1.30 nicm 108: char *line, *error;
1.29 nicm 109: struct cmdq_state *state;
1.30 nicm 110: enum cmd_parse_status status;
1.1 nicm 111:
1.30 nicm 112: if (closed || read_error != 0)
1.1 nicm 113: c->flags |= CLIENT_EXIT;
114:
115: for (;;) {
1.25 nicm 116: line = evbuffer_readln(buffer, NULL, EVBUFFER_EOL_LF);
1.1 nicm 117: if (line == NULL)
118: break;
1.25 nicm 119: log_debug("%s: %s", __func__, line);
1.1 nicm 120: if (*line == '\0') { /* empty line exit */
1.24 nicm 121: free(line);
1.1 nicm 122: c->flags |= CLIENT_EXIT;
123: break;
124: }
125:
1.30 nicm 126: state = cmdq_new_state(NULL, NULL, CMDQ_STATE_CONTROL);
127: status = cmd_parse_and_append(line, NULL, c, state, &error);
128: if (status == CMD_PARSE_ERROR)
129: cmdq_append(c, cmdq_get_callback(control_error, error));
130: cmdq_free_state(state);
1.1 nicm 131:
1.2 nicm 132: free(line);
1.1 nicm 133: }
1.25 nicm 134: }
135:
136: void
137: control_start(struct client *c)
138: {
139: file_read(c, "-", control_callback, c);
140:
141: if (c->flags & CLIENT_CONTROLCONTROL)
142: file_print(c, "\033P1000p");
1.1 nicm 143: }